借り初めのひみつきち

仮ブログです。

3種のビットマップ

昨日の日記で何故ビットマップクラスが3種類必要になるのか少し補則します。

生ポインタと Box

旧 MYOS のビットマップは生ポインタでデータを管理していました。 これは所有権もライフタイムも Rust によって管理されておらず借用の制限もなかったので C 言語とあまり変わらない危険な状態でした。

TOE のビットマップクラスで旧 MYOS に一番近いのは、 Box でヒープに所有しているビットマップ (BoxedBitmap) です。 所有権とライフタイムを Rust が管理しているのが大きな違いです。

pub struct BoxedBitmap8<'a> {
    inner: Bitmap8<'a>,
    slice: UnsafeCell<Box<[IndexedColor]>>,
}

BoxedBitmap を直接可変借用すれば通常の描画は大抵事足りそうですが、いくつか問題があります。

可変借用

フレームバッファや他のビットマップの一部を切り取った View オブジェクトはデータをヒープに所有していないので BoxedBitmap で扱うことができません。 ウィンドウの描画などは描画する範囲だけ切り取った View を多用します。

Rust ではヒープに確保するクラスとそうではないクラスは通常明確に分かれています。 そこで、普段の描画はビットマップデータを可変借用スライスで扱うクラスを使います。基本の描画クラスになるので名前もシンプルに Bitmap にしました。

pub struct Bitmap8<'a> {
    width: usize,
    height: usize,
    stride: usize,
    slice: UnsafeCell<&'a mut [IndexedColor]>,
}

BoxedBitmap は内部に Bitmap を保持しているのでゼロコピーで借用できます。

不変借用

Rust は可変借用に対して制限が厳しい言語です。 blt のソースに使う画像などは可変借用する必要性がないので不変借用したいです。

また、ソースファイルにパターンデータを記述してそのまま blt するようなプログラムも簡単に記述したいので定数でデータを保持したいですが、 BoxedBitmap や Bitmap は内部で可変のビットマップデータを管理しているので、不変のデータを扱うことができません。

このような状況では、内部で不変スライスを借用した定数ビットマップ (ConstBitmap) を使用します。

pub struct ConstBitmap8<'a> {
    width: usize,
    height: usize,
    stride: usize,
    slice: &'a [IndexedColor],
}

BoxedBitmap や Bitmap は ConstBitmap に変換して借用できます。

いかがでしたか?

このように、状況に応じて3種類のビットマップオブジェクトを定義して使い分けることで、さまざまなケースで効率的にデータを扱うことができるようになります。