☆Zaurus SZAB C言語《オフスクリーン解析》

オフスクリーンに直接データを描き込んで、高速に表示しよう。

○オフスクリーンの構造

実は最近ザウルス宝箱のFAQに答えが記載されました(汗)
1157のQAに『オフスクリーンのイメージはPixMap形式です。形式につきましてはプログラミングガイド第10章に記載されています。』と書かれて、「何じゃ? そのプログラミングガイドとは?(汗)」状態に陥りました。
クラスライブラリリファレンスとAPI リファレンスは、SZABのヘルプにありますが、プログラミングガイドは別途ダウンロードが必要です。

……が、確かに PixMap形式の説明が図入りで行われているのですが、すぐに理解できた人はどのくらいいるでしょうか?
RGBが5:6:5bitなのは分かりますが、このクロス矢印は一体?
プログラムで書くと、こういう意味でしょうか?

unsigned char R8bit, G8bit, B8bit;
unsigned short RGB16bit;
//カラーが真っ白とする
R8bit = 255;
G8bit = 255;
B8bit = 255;
//RGBを5:6:5bitにする
R8bit = R8bit >> 3;
G8bit = G8bit >> 2;
B8bit = B8bit >> 3;
//RGB16bitに RGBの順で格納する
RGB16bit = (unsigned short)R8bit << 11 + (unsigned short)G8bit << 5 + B8bit;

で、生成した RGB16bitをオフスクリーンに格納する際には、下、上の順で行う。
下:(RGB16bit << 8) >> 8
上:RGB16bit >> 8
……と言うことは、単純に memcpyとか使えないと言うことになりますね。

もしくは、反転しなくて良いように、最初から逆転させてセットするかですね。
//RGB16bitに RGBの順で、更に上下8ビット反転で格納する
RGB16bit = (unsigned short)G8bit << 13 + (unsigned short)B8bit << 8 + R8bit << 3 + G8bit >> 3;
うざいですねぇ……。

○オフスクリーンの作り方

NewOffscreen関数にて生成します。
ドット指定ですので、素直にターゲットの画面サイズを指定して下さい。
なぜか左上の指定もあるのが謎ですが、反対に書いても座標系が反転するわけでは無いです。

//宣言は関数の先頭で
WINDOWHD off_scrn_hd;  //オフスクリーン ハンドル
RECTANGLE rect;        //オフスクリーン サイズ(ドット単位指定)

rect.left=0;
rect.top=0;
rect.width=320;
rect.height=240;
if((off_scrn_hd=NewOffscreen(&rect, 16, 2)) == 0){
  //オフスクリーンの確保に失敗
}

○オフスクリーンのクリアーの仕方

オフスクリーン生成時は、中身はゴミで埋まっています(汗)
そこで、まずはクリアーしなければなりません。

直接データを入れようとすると、最初に説明した複雑な手順が必要です。
ですが、オフスクリーンに対しても、実画面と同じ描画関数が使えるものがあります。
クリアーをするだけであれば、BoxPaint関数で十分です。

//宣言は関数の先頭で
POINT st_point;  //左上の座標(ポイント単位指定)
POINT end_point; //右下の座標(ポイント単位指定)
COLOR fg_color;  //表示色
COLOR bg_color;  //背景色

st_point.x=0;
st_point.y=0;
end_point.x=320 * 4 - 1;
end_point.y=240 * 4 - 1;
fg_color.CValue=WHITE;
bg_color.CValue=BLACK;
BoxPaint(off_scrn_hd, &st_point, &end_point, &fg_color, &bg_color, FSET, P_BLACK, NULL);

○オフスクリーンに直接描画

GetPixMapAdrOffscreen関数にて、ドットデータの先頭アドレスを取得して行います。
ここでは、青色で正方形を描画してみます。

//ヘッダはソースの一番先頭に記述
#include <offscrn.h>  //オフスクリーンアドレス獲得に必要

//宣言は関数の先頭で
UCHAR *off_scrn_pix;
int x, y;

//ドットデータの先頭アドレスを取得
off_scrn_pix=GetPixMapAdrOffscreen(off_scrn_hd);

//100 * 100の範囲を青で塗りつぶす
for(y=0; y < 100; y++){
for(x=0; x < 100 * 2; x += 2){
  *(off_scrn_pix + y * 320 * 2 + x)=0x1F;
  *(off_scrn_pix + y * 320 * 2 + x + 1)=0x00;
}
}

○オフスクリーンを実画面に転送

DrawOffscreen関数を使います。
注意点として、オフスクリーン生成時はドット単位ですが、実画面転送時にはポイント単位になります。

//宣言は関数の先頭で
RECTANGLE rect;  //実画面 サイズ(ポイント単位指定)
COLOR fg_color;  //表示色
COLOR bg_color;  //背景色

rect.left=0;
rect.top=0;
rect.width=320 * 4 - 1;
rect.height=240 * 4 - 1;
fg_color.CValue=WHITE;
bg_color.CValue=BLACK;
DrawOffscreen(AplForm->FormWnHandle, &rect, off_scrn_hd, &rect, 0, 0, &fg_color, &bg_color);

トップメニュープログラマ専用Zaurus開発