ドロー系処理と日本語描画を実装する

ここでは、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の全角・半角混在文字列の表示について

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;
        }
    }
}

Graphics Tool Kit(GTK)のソースコード一式

GTK ソースコード




Author: projectc3@gmail.com
Last modified: Mon Aug 01 22:00:57 JST 2005