2024/02/13(火) [n年前の日記]
#1 [basic] FreeBASICでCustom fontを使ってみたい
FreeBASICは、Draw String() を使うと、グラフィックス画面にテキストを描画することができる。ただ、使われるフォントが豆粒みたいに小さくて読みづらい…。もう少し大きいフォントを使いたい。
一応、Draw String はカスタムフォントを利用できるらしいので、そのあたりを試してみた。
ファイル一式は以下。
_fbcustomfont_20240213.zip
一応、Draw String はカスタムフォントを利用できるらしいので、そのあたりを試してみた。
ファイル一式は以下。
_fbcustomfont_20240213.zip
◎ カスタムフォントの仕様 :
bitmap font が敷き詰められたフォント画像(.bmp)を与えればすぐさま利用できるのかなと思ったけれど、どうやらそんな単純な仕様では無さそうで…。
_DrawString
_FBgfx Image and Font Buffers - FreeBASIC Wiki Manual | FBWiki
bitmap font画像を渡すまでは予想通りだったけど、そのbmp画像の中にフォント情報(対象文字コードや各文字の横幅)も含ませておかないといかんらしい。
まず、bmp画像の最初の1ラスター目が、font header になっていて、そこにフォント情報を byte 単位で書き込まないといけないらしい。実際の bitmap font部分は、2ラスター目から置かれている。
font header の内容は以下。
個人的に、この仕様はどうなんだと思えた。例えば画像編集ソフトでフォント画像を開いて、色調補正をしただけで、フォント情報が一発で破壊されてしまう。よろしくない気がする。いやまあ、フォント画像一つでカスタムフォントを扱いたい、フォント画像の中にフォント情報まで含めてしまいたい、と考えたらこうなったのだろうとは想像できるけど…。
_DrawString
_FBgfx Image and Font Buffers - FreeBASIC Wiki Manual | FBWiki
bitmap font画像を渡すまでは予想通りだったけど、そのbmp画像の中にフォント情報(対象文字コードや各文字の横幅)も含ませておかないといかんらしい。
まず、bmp画像の最初の1ラスター目が、font header になっていて、そこにフォント情報を byte 単位で書き込まないといけないらしい。実際の bitmap font部分は、2ラスター目から置かれている。
font header の内容は以下。
1 byte目 : Version情報。これは現在 0 しか用意されてないらしい。 2 byte目 : 開始文字コード。例えば ASCIIコードの「空白」から始まるなら、0x20になる。 3 byte目 : 終了文字コード。例えば ASCIIコードの「DEL」で終わるなら、0x7f になる。 4 byte目 : 開始文字 + 0 の横幅ドット数 5 byte目 : 開始文字 + 1 の横幅ドット数 6 byte目 : 開始文字 + 2 の横幅ドット数 ... ... N byte目 : 終了文字の横幅ドット数
個人的に、この仕様はどうなんだと思えた。例えば画像編集ソフトでフォント画像を開いて、色調補正をしただけで、フォント情報が一発で破壊されてしまう。よろしくない気がする。いやまあ、フォント画像一つでカスタムフォントを扱いたい、フォント画像の中にフォント情報まで含めてしまいたい、と考えたらこうなったのだろうとは想像できるけど…。
◎ 変換ツールを書いてみた :
とりあえず、使ってみよう…。
等幅フォント、色深度32bitに限定して、読み込んだ bitmapフォント画像(.bmp)に Font header情報を追加/書き込んでから、bmp画像として保存するツールを書いてみた。
例えば、以下のように、ASCIIコード 0x20 - 0x7f の文字が、横一列に並んでいるbitmapフォント画像を用意して…。
_fbfont_bs_pet2015_16x16.bmp
このbmp画像を読み込んで、Font header 情報を追加して、以下のようなカスタムフォント用画像として出力する。
_fbfont_pet2015_16x16.bmp
見た目で違いは分からないだろうけど、一番上に1ラスター分追加されていて、そこに Font header情報が書き込まれている。
変換ツールのソースは以下。
_make_mono_font.bas
fbc make_mono_font.bas でコンパイル。
使い方は以下。
等幅フォント、色深度32bitに限定して、読み込んだ bitmapフォント画像(.bmp)に Font header情報を追加/書き込んでから、bmp画像として保存するツールを書いてみた。
例えば、以下のように、ASCIIコード 0x20 - 0x7f の文字が、横一列に並んでいるbitmapフォント画像を用意して…。
_fbfont_bs_pet2015_16x16.bmp
このbmp画像を読み込んで、Font header 情報を追加して、以下のようなカスタムフォント用画像として出力する。
_fbfont_pet2015_16x16.bmp
見た目で違いは分からないだろうけど、一番上に1ラスター分追加されていて、そこに Font header情報が書き込まれている。
変換ツールのソースは以下。
_make_mono_font.bas
Const START_CHR = &H20 Const END_CHR = &H7f Const SCRW = 800 Const SCRH = 600 Dim As Integer sdepth = 32 If Command(1) = "" And Command(2) = "" Then Print "Usage: " & Command(0) & " INPUT.bmp OUTPUT.bmp" : End End If Dim As String infilename = Command(1) Dim As String outfilename = Command(2) Dim As Integer f Dim As Long w, h ' open bitmap file f = FreeFile() Open infilename For Binary Access Read As #f If Err > 0 Then Print "Error: Can not open file" : End ' get bitmap width and height Get #f, 19, w ' get width Get #f, , h ' get height Close #f ScreenRes SCRW, SCRH, sdepth ' load base font image Dim As Any Ptr base_font = ImageCreate(w, h, RGB(0, 0, 0)) bload infilename, base_font Print "Load : " & infilename ' create new font image Dim As Any Ptr out_font = ImageCreate(w, h + 1, RGB(255, 0, 255)) Put out_font, (0, 1), base_font, PSet ' get custom font header address Dim As ubyte Ptr headerp ImageInfo out_font, , , , , headerp ' set header headerp[0] = 0 headerp[1] = START_CHR ' first character code headerp[2] = END_CHR ' end character code ' get 1 character Width Dim As Integer cw = Int(w / (END_CHR - START_CHR + 1)) For i As Integer = 0 To (END_CHR - START_CHR) headerp[3 + i] = cw Next i bsave outfilename, out_font color RGB(255, 255, 255), RGB(0, 0, 0) Print "Save : " & outfilename Print "Push Any Key" sleep ImageDestroy out_font ImageDestroy base_font
fbc make_mono_font.bas でコンパイル。
使い方は以下。
Usage: make_mono_font.exe INPUT_FONT.bmp OUTPUT_FONT.bmp
◎ テスト表示してみる :
変換して生成されたフォント画像(.bmp)を読み込んで、カスタムフォントとして利用してみる。
_test_fbfont.bas
fbc test_fbfont.bas でコンパイル。
使い方は以下。表示してみたいフォント画像をコマンドラインオプションで指定する。
たしかに、カスタムフォントが利用できた。
再度メモ。ファイル一式は以下。
_fbcustomfont_20240213.zip
_test_fbfont.bas
Const SCRW = 512 Const SCRH = 288 Dim As Integer sdepth = 32 If Command(1) = "" Then Print "Usage : " & Command(0) & " INPUT_FONT.bmp" : end End If ScreenRes SCRW, SCRH, sdepth Dim As String infilename = Command(1) Dim As Integer f Dim As Long w, h ' open bitmap file f = FreeFile() Open infilename For Binary Access Read As #f If Err > 0 Then Print "Error: Can not open file" : End ' get bitmap width and height Get #f, 19, w ' get width Get #f, , h ' get height Close #f Dim As Any Ptr img = ImageCreate(w, h) bload infilename, img Color RGB(255, 255, 255), RGB(0, 0, 0) cls h = 34 Draw String (0, h * 0), "Hello World !", , img Draw String (0, h * 1), infilename, , img Draw String (0, h * 2), "0123456789", , img Draw String (0, h * 3), "@ABCDEFGHIJKLMNO", , img Draw String (0, h * 4), "PQRSTUVWXYZ[\]^_", , img Draw String (0, h * 5), "`abcdefghijklmno", , img Draw String (0, h * 6), "pqrstuvwxyz{|}~ ", , img sleep ImageDestroy img
fbc test_fbfont.bas でコンパイル。
使い方は以下。表示してみたいフォント画像をコマンドラインオプションで指定する。
Usage: test_fbfont.exe INPUT_FONT.bmp
たしかに、カスタムフォントが利用できた。
再度メモ。ファイル一式は以下。
_fbcustomfont_20240213.zip
◎ 他のフォントを利用した際のスクリーンショット :
以前、
_OpenGLでビットマップフォントを描画した際
のフォントデータを利用して試してみた。
courR18 (16x26)
profont (12x22)
東雲フォント shnm8x16r (8x16)
東雲フォント2倍拡大 shnm8x16r x 2 (16x32)
Terminus font (12x24)
各フォントの入手先やライセンスは以下を参照のこと。
_readme.md
courR18 (16x26)
profont (12x22)
東雲フォント shnm8x16r (8x16)
東雲フォント2倍拡大 shnm8x16r x 2 (16x32)
Terminus font (12x24)
各フォントの入手先やライセンスは以下を参照のこと。
_readme.md
[ ツッコむ ]
以上です。