Doc.12 日本語の表示方法(ビットマップモード2)

前回に続き、今度は日本語を表現していきます。
ただ漢字の個数が不明で、どれぐらいデータ量が増加するか検討もつきません。
そこでプログラマー的視点に立って、ある程度の概算を出してみます。

1ドット1バイト、1文字16x16ドットの場合、16 * 16 = 256バイトです。
文字数を大雑把に6000字とすると、

6000 * 256 = 1,536,000バイト = 1.5MB

となります。本職のプログラマーが見たら卒倒しそうな数字ですが、せめて
1ドット1ビット単位にしたらどうかと言ってきそうです。ここでは無視します(ぉ。

日本語を表示しよう

文字と16進数の対応テーブルは代表的なものとして
SJIS、EUC、UTF-8などがあります。ここではSJISのみ扱います。

表示したい文字列をSJISで見ると、以下のようになります。

猫 - 0x944c
ま - 0x82dc
ん - 0x82f1
ま - 0x82dc
clip_2.png

1文字2バイト表現となっていて、つまり

Mode3DrawSJISStr(0, 0, "猫まんま");

っぽい関数を作って内部で文字コードと文字データを付き合わせれば完成するわけです。
前のサンプルコードと同じ・・・と行きたいですが、そうは問屋が下ろしません。

文字データの順番が、文字コードと対応していないのです。
SJISコード表をよーくみると微妙な空白が存在しており、
文字データはその空白を無視して詰めて書いてあります。

ではどうするかというと、空白部分を除去したフォントシートと呼ばれる
テキストデータを用意して、フォントデータのインデックスを求めます。

  • Mode3DrawSJISStr関数のラフスケッチ
u8* pDat = pフォントデータ;
s32 i;

for(i=0; i<フォントシート内の文字数; i++)
{
	if(フォントシート[i] == 表示したい文字)
	{
		pDat += i * 横のドット分;
		break;
	}
}

// 描画処理

本職のプログラマーな方がみたら卒倒しそうなループ処理ですね(本日2回目。

サンプルコード

今回もmain関数から見てみましょう。

int main(void)
{
	SetMode(MODE_3 | BG2_ENABLE);

	ST_FONT f;

	f.pDat   = (u8*)&mplus_j10rBitmap;
	f.imgCx  = 69630 + 2;		// +2は、gritのサイズ調整分
	f.cx     = 10;
	f.cy     = 11;

	f.pSheet = (u16*)&mplus_jfnt_txt;
	f.cnt    = 6963;

	Mode3DrawSJISStr(&f, 16, 16, "猫まんま", RGB5(31,31,31));

	for(;;)
	{
	    WaitForVsync();
	}
}

サンプルでは10x11ドットのmplusフォントを使用しました。6963文字入っています。

void Mode3DrawSJISStr(ST_FONT* p, s32 sx, s32 sy, char* str, u16 col)
{
	u16 chr;
	s32 i=0, x=0, y=0;

	for(;;)
	{
		chr = str[i] | (str[i+1] << 8);
		i += 2;

		if(chr == '\0')
		{
			return;
		}

		// 改行処理
		if(sx + x >= 240)
		{
			x  = 0;
			y += p->cy;

			if(sy + y + p->cy >= 160)
			{
				return;
			}
		}

		Mode3DrawSJISChr(p, sx + x, sy + y, chr, col);
		x += p->cx;
	}
}

2バイト文字を扱うため、chr変数に2バイト入れるようにしています。

void Mode3DrawSJISChr(ST_FONT* p, s32 sx, s32 sy, u16 chr, u16 col)
{
	u8* pDat = p->pDat;
	s32 i;

	for(i=0; i<p->cnt; i++)
	{
		if(chr == p->pSheet[i])
		{
			pDat += i * p->cx;
			break;
		}
	}

	u16* pScreen = (u16*)VRAM + (sy * 240) + sx;
	s32  x, y;

	for(y=0; y<p->cy; y++)
	{
		for(x=0; x<p->cx; x++)
		{
			if(pDat[y*p->imgCx + x] == 0x00)
			{
				continue;
			}

			pScreen[y*240 + x] = col;
		}
	}
}

フォントシートのインデックスを求めるだけで前回のコードと変わりありません。

なお、main関数の「猫まんま」はソースコードのテキスト保存形式に依存しています。
EUCで保存していたら表示されないので注意してください。

動作画面

clip_1.png

履歴

  • 2014/11/16

添付ファイル: fileclip_2.png 245件 [詳細] fileclip_1.png 218件 [詳細]

Last-modified: 2014-11-16 (日) 14:52:05 (2827d)