ここでは、GTK(Graphics Tool Kit)と名づけた処理を実装する事にします。
直接VFDパネルドライバを制御はせず、あくまで内部で確保した仮想VRAMに対しての描画を行います。
VFDドライバで仮想VRAMから実際のVFDパネルへのコピーを行います。
ここでは、任意のピクセルのドット単位でのPSET、PRESETを実装します。
以下のようになりました。
/********************************************************************************** Group : GTK Function name : gtk_putpixel_vvram Note : 仮想VRAMの任意の座標(x,y)にドットを打つ Input : None Output : None Condition to call : Last updated : **********************************************************************************/ void gtk_putpixel_vvram(int x,int y,int color){ unsigned short address; unsigned char bitdata; if((x>GTK_SCREEN_AREA_X2)|| (x<GTK_SCREEN_AREA_X1)|| (y>GTK_SCREEN_AREA_Y2)|| (y<GTK_SCREEN_AREA_Y1)){ return; } // VRAMアドレス算出 address = (x << 3) + (y >> 3) + 0x04; bitdata = 0x80 >> (y - (y & 0xfff8)); if(color){ gtk_vvram.vbuf[address] = gtk_vvram.vbuf[address] | bitdata; } else { gtk_vvram.vbuf[address] = gtk_vvram.vbuf[address] & (~bitdata); } }
ライン描画は、整数演算だけで座標を算出できるブレゼンハムのアルゴリズムを使用しています。参考文献もあったはずなのですが、あまりに昔に作った関数を流用したため、失念してしまいました。
/********************************************************************************** Group : GTK Function name : gtk_line_vvram Note : 仮想VRAMに対して直線描画する Input : x1,y1,x2,y2,color Output : None Condition to call : Last updated : **********************************************************************************/ void gtk_line_vvram(int x1,int y1,int x2,int y2,int color){ int dx,dy; int x,y; int error; if (x2 < x1){ error = x1; x1 = x2; x2 = error; } if (y2 < y1){ error = y1; y1 = y2; y2 = error; } error = 0; dx = x2 - x1; dy = y2 - y1; if (dx >= dy){ for (y=y1,x=x1;x<=x2;x++){ error += dy; if (error > dx){ y++; error -= dx; } gtk_putpixel_vvram (x,y,color); } } else { for (x=x1,y=y1;y<=y2;y++){ error += dx; if (error > dy){ x++; error -= dy; } gtk_putpixel_vvram (x,y,color); } } }
円の描画については、ミッチェナーのアルゴリズムが有効であるということで、Webの内容を参考にしてGTKに移植させていただきました。
参考文献(サイト)
/********************************************************************************** Group : GTK Function name : gtk_putpixel_vvram Note : 仮想VRAMに対してミッチェナーのアルゴリズムで円描画する Input : None Output : None Condition to call : Last updated : (ミッチェナーのアルゴリズム。 出典:http://www.alpha-net.ne.jp/users2/gmaru/programs_07/pg_graphic_09a1.html) **********************************************************************************/ void gtk_circle_vvram(int x,int y,int radius,int color){ int cx, cy, d; d = 3 - 2 * radius; cy = radius; // 開始点の描画 gtk_putpixel_vvram ( x, radius + y, color); // point (0, R); gtk_putpixel_vvram ( x, -radius + y, color); // point (0, -R); gtk_putpixel_vvram ( radius + x, y, color); // point (R, 0); gtk_putpixel_vvram ( -radius + x, y, color); // point (-R, 0); for (cx = 0; cx <= cy; cx++) { if (d < 0){ d += 6 + 4 * cx; } else { d += 10 + 4 * cx - 4 * cy--; } // 描画 gtk_putpixel_vvram ( cy + x, cx + y, color); // 0-45 度の間 gtk_putpixel_vvram ( cx + x, cy + y, color); // 45-90 度の間 gtk_putpixel_vvram ( -cx + x, cy + y, color); // 90-135 度の間 gtk_putpixel_vvram ( -cy + x, cx + y, color); // 135-180 度の間 gtk_putpixel_vvram ( -cy + x, -cx + y, color); // 180-225 度の間 gtk_putpixel_vvram ( -cx + x, -cy + y, color); // 225-270 度の間 gtk_putpixel_vvram ( cx + x, -cy + y, color); // 270-315 度の間 gtk_putpixel_vvram ( cy + x, -cx + y, color); // 315-360 度の間 } }
フォントデータへのアクセスは、前述のFONTX2ドライバを使用します。
ここではちょっと手抜きですが、16ドット×16ドットのフォントのみ対応しています。
/********************************************************************************** Group : GTK Function name : gtk_put_kanji_vvram Note : 仮想VRAM上の指定座標に2バイト系文字を1つ描画する Input : ptr : 文字フォントのアドレス x,y : 文字の左上座標 Output : None Condition to call : Last updated : **********************************************************************************/ static void gtk_put_kanji_vvram(unsigned char* ptr,int x,int y){ int lx,ly; unsigned short buff; for (ly = 0;ly < 16;ly++){ buff = *((unsigned short*)ptr + ly); for (lx = 0;lx < 16;lx++){ if ((buff >> 15-lx) & 0x01){ gtk_putpixel_vvram(lx + x,ly + y,1); } } } }
/********************************************************************************** Group : GTK Function name : gtk_put_ascii_vvram Note : 仮想VRAM上の指定座標に全角 Input : Output : Condition to call : Last updated : **********************************************************************************/ static void gtk_put_ascii_vvram(unsigned char* ptr,int x,int y){ int lx,ly; unsigned short buff; for (ly = 0;ly < 16;ly++){ buff = *(ptr + ly); for (lx = 0;lx < 8;lx++){ if ((buff >> 7-lx) & 0x01){ gtk_putpixel_vvram(lx + x,ly + y,1); } } } }
Shift-JISでは、文字コードは上位バイトが必ず0x80以上であると決められています。
従って、Shift-JIS文字列の場合、1バイト目の値で全角データか半角データかを判断する事ができます。
/********************************************************************************** Group : Function name : Note : Input : Output : Condition to call : Last updated : **********************************************************************************/ void gtk_put_string_to_vvram(char* str,int x,int y){ unsigned char* ptr; y *= 16; while (*str){ if(*(str) < 0x80){ // 1バイト系半角文字 ptr = GetFontPtr_Ascii(*str); gtk_put_ascii_vvram(ptr,x,y); x+=8; str++; } else { // 2バイト系全角文字 ptr = GetFontPtr_Kanji(*(str) << 8 | *(str+1)); gtk_put_kanji_vvram(ptr,x,y); x+=16; str+=2; } } }