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
[ ツッコむ ]
以上です。






