mieki256's diary



2024/02/13(火) [n年前の日記]

#1 [basic] FreeBASICでCustom fontを使ってみたい

FreeBASICは、Draw String() を使うと、グラフィックス画面にテキストを描画することができる。ただ、使われるフォントが豆粒みたいに小さくて読みづらい…。もう少し大きいフォントを使いたい。

一応、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ラスター目から置かれている。

about_fbfont.png


font header の内容は以下。

about_fbfont_header.png

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

ss_fbfont_pet2015_16x16.png

たしかに、カスタムフォントが利用できた。

再度メモ。ファイル一式は以下。

_fbcustomfont_20240213.zip

他のフォントを利用した際のスクリーンショット :

以前、 _OpenGLでビットマップフォントを描画した際 のフォントデータを利用して試してみた。

courR18 (16x26)

ss_fbfont_courR18_16x26.png


profont (12x22)

ss_fbfont_profont_12x22.png


東雲フォント shnm8x16r (8x16)

ss_fbfont_shnm8x16r_8x16.png


東雲フォント2倍拡大 shnm8x16r x 2 (16x32)
ss_fbfont_shnm8x16rx2_16x32.png


Terminus font (12x24)

ss_fbfont_ter-u24b_12x24.png


各フォントの入手先やライセンスは以下を参照のこと。

_readme.md

#2 [basic] FreeBASICで等幅ビットマップフォントのみを使って描画

FreeBASIC の Draw string でカスタムフォントを使ってみたけれど、フォント画像を用意するのが面倒臭いだろうなと思えてきた。これがもし、等幅フォントのみを扱うことを前提にするなら、もっと簡単にフォント画像を用意できそうだし、描画処理も簡単にできそうな気がする。試してみた。

環境は、Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit。

フォント画像の用意 :

まずは、以下のような文字が並んでいる画像を、等幅フォントで作成。

 !"#$%&'()*+,-./
0123456789:;<=>?
@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~ 


透明色=RGB(255, 0, 255) として扱う。以下のような画像になる。

font_pet2015_16x16.bmp


これなら、1文字当たりの横幅、縦幅は、(画像横幅 / 16), (画像縦幅 / 6) で求められる。

後は、与えらえた文字列の、各文字に対応する領域を Put() で描画していけばいい。

描画処理 :

そんな感じで、描画処理は以下のようになった。


画像の読み込み、テキスト描画をする部分。

_bitmapasciifont.bi


簡単な使用サンプル。

_simple_sample.bas
#include "bitmapasciifont.bi"
ScreenRes 320, 240, 32

Dim fnt As BitmapAsciiFont
fnt.load_image("font_profont_12x22.bmp")

fnt.draw_string(10, 10, "Hello World !")

sleep
fnt.destroy()


フォント画像を渡して描画するサンプル。

_test_bitmapasciifont.bas
#include "bitmapasciifont.bi"

If Command(1) = "" Then
    Print "Usage: " & Command(0) & " INPUT_FONT.bmp" : end
End If

Dim As String fontfile = Command(1)

Const SCRW = 640
Const SCRH = 480
Dim As Integer sdepth = 32

ScreenRes SCRW, SCRH, sdepth

Dim fnt As BitmapAsciiFont
fnt.load_image(fontfile)

Dim As Integer h = fnt.cheight + 1
fnt.draw_string(0, h * 0, "Load: " & fontfile)
fnt.draw_string(0, h * 1, "Hello World ! 0123456789")
fnt.draw_string(0, h * 2, "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_")
fnt.draw_string(0, h * 3, "`abcdefghijklmnopqrstuvwxyz{|}~ ")
fnt.draw_string(0, h * 4, "Push any key to exit.")

sleep
fnt.destroy()


スクリーンショットは以下。

ss_font_courr18_16x26.png

ss_font_pet2015_16x16.png

ss_font_profont_12x22.png

ss_font_shnm8x16r_8x16.png

ss_font_shnm8x16rx2_16x32.png

ss_font_ter-u24b_12x24.png


ファイル一式を置いておきます。御自由にどうぞ。

_bitmapasciifont_20240213.zip


これなら、フォント画像を作るのも簡単なのではないかな…。

フォントの入手先は以下を参照のこと。

_readme.md

#3 [basic] FreeBASICでテキストファイル読み込みをしたい

FreeBASIC で、テキストファイルを行単位で読み込みたい。環境は Windows10 x64 22H2 + FreeBASIC 1.10.1 32bit。

以下が参考になった。

_ファイル入出力関連
_Freefile
_Open
_Eof
_LineinputPp

  1. FreeFile() で空いているファイル番号を取得して、
  2. Open でファイルを開いて、
  3. EOF() でファイルの終端かどうかをチェックしつつ、
  4. Line Input で1行読み込んで、
  5. 処理が終わったら Close
そんな感じらしい。

動作確認するために、サンプルソースを書いてみた。

_lineinput.bas
Const infile = "test.txt"

' Open file
Dim As Long f = FreeFile()
If (Open(infile For Input As #f)) Then
    Print "Error: Cano not open " & infile : End -1
End If

' Read lines
Dim As Integer count = 0
Do until EOF(f)
    count += 1
    Dim As String s
    Line Input #f, s  ' Read 1 line
    Print Str(count) & ": " & s
Loop

' Close file
Close #f

fbc lineinput.bas でコンパイル。

_test.txt を用意して読み込ませてみた。

_test.txt
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,

sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.

> lineinput.exe
1: Lorem ipsum dolor sit amet,
2: consectetur adipiscing elit,
3:
4: sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
5:
6: Ut enim ad minim veniam, quis nostrud exercitation ullamco
7: laboris nisi ut aliquip ex ea commodo consequat.

たしかに、1行ずつ読み込みができた。

行末については、LF か CRLF があれば行末/改行コードとして扱う、と書いてある。本当にそうなっているのか、読み込むテキストファイルの改行コードを LF もしくは CRLF にして試してみたけど、どちらも行単位で読み込んでくれた。

以上、1 日分です。

過去ログ表示

Prev - 2024/02 - Next
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project