# damage-rects
[](https://crates.io/crates/damage-rects)
[](https://docs.rs/damage-rects)
[](LICENSE)
[](Cargo.toml)
[](https://crates.io/crates/damage-rects)
ダーティ矩形を集めて、GPU キャンバスの部分更新のためのマージ済み再描画領域を生成します。依存ゼロ、GPU との結合なし、ビューポートの仮定もなし——任意の 2D レンダラ(Skia、wgpu、softbuffer、生 Metal)と組み合わせ可能。
> **同義語 / 検索ワード**: damage tracking、ダーティ矩形トラッキング、部分再描画(partial redraw)、無効化領域(invalidation region)、再描画領域、領域合流、エディタ/ターミナルのインクリメンタル再描画。
## なぜ
インタラクティブな GPU レンダリングアプリはどれも選択を迫られます: 毎ティック全体を再描画するか、どの領域が変わったかを追跡してそこだけ再描画するか。前者は単純だが電力を浪費し、後者はエディタ、デザインツール、ターミナル、ダッシュボードが実際に行っていることです。
GUI フレームワーク(`gpui`、`iced`、`slint`)は damage トラッキングを内部に抱え込み、再利用可能な crate として公開しません。この crate がその再利用可能な実装です。
## API
```rust
use damage_rects::{DamageRect, DamageTracker};
let mut tracker = DamageTracker::new();
// 状態更新時
tracker.add(DamageRect::new(10.0, 20.0, 100.0, 30.0)); // ある行が変化
tracker.add(DamageRect::new(50.0, 30.0, 80.0, 40.0)); // カーソル移動
// フレーム描画時
if tracker.is_full() {
// 何かがビューポート全体を無効化 —— 全体を再描画
} else if let Some(region) = tracker.merged() {
// render(region)
}
tracker.clear();
```
2 つの直交する状態:
- **full-damage フラグ**(`mark_full`)——ウィンドウリサイズやテーマ切替などでビューポート全体が無効化された時にセット。この間 `merged()` は `None` を返し、`is_full()` は `true`。個別の矩形は無視されます。
- **pending 矩形**(`add`)——`merged()` で 1 つのバウンディング矩形にマージ、もしくは `rects()` で生リストを取得し独自の合流戦略(保守的 / 積極的 / 閾値)を実装可能。
## 閾値戦略
ダーティ領域の合計が大きい場合、小さな矩形を多数描くより全体再描画のほうが安上がりです。`area_upper_bound()` は軽量な矩形面積合計(重複は二重計上)を返します:
```rust
if tracker.area_upper_bound() > viewport_area * 0.5 {
// 部分描画を諦めて全体再描画
tracker.mark_full();
}
```
## デモ
```bash
cargo run --example visualize -p damage-rects
```
インタラクティブなウィンドウ:
- クリックでダーティ矩形を追加
- `Space` でマージ領域を描画(緑の枠、その後クリア)
- `F` で full-damage フラグをトグル(黄色のティント)
- `C` でクリア
## インストール
```toml
[dependencies]
damage-rects = "0.1"
```
## 座標系
`DamageRect { x, y, width, height }`、`f32`。右/下は開区間(`contains_point` は右/下境界で `false` を返す)。座標の向きは呼び出し側に委ねられます——ライブラリは算術しか使いません。
## ライセンス
MIT —— [LICENSE](LICENSE) を参照。