Init 🏴‍☠️

This commit is contained in:
Alexander Popov 2023-05-02 21:01:20 +03:00
commit a2e6ddbac9
Signed by: iiiypuk
GPG Key ID: E47FE0AB36CD5ED6
18 changed files with 5511 additions and 0 deletions

20
.editorconfig Normal file
View File

@ -0,0 +1,20 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{*.c,*.h}]
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
indent_size = 4

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

20
README.md Normal file
View File

@ -0,0 +1,20 @@
## 🧰 Build
1. Clone Flipper Zero firmware.
```sh
git clone --depth 1 --branch 0.82.3 https://github.com/flipperdevices/flipperzero-firmware.git
```
2. Copy this repo to firmware sources directory.
```sh
cd /path/to/flipperzero-firmware
ln -s /path/to/cyr_fap .
```
3. Build application
```sh
./fbt fap_cyr_example
```

View File

@ -0,0 +1,5 @@
root = true
[{*.c,*.h}]
indent_style = unset
indent_size = unset

520
font/bdfconv/Makefile Normal file
View File

@ -0,0 +1,520 @@
# works within ubuntu and min-gw (win7) environment
# win7 exe uploaded on google drive
CC = gcc
CFLAGS = -g -Wall
#CFLAGS = -O4 -Wall
SRC = main.c bdf_font.c bdf_glyph.c bdf_parser.c bdf_map.c bdf_rle.c bdf_tga.c fd.c bdf_8x8.c bdf_kern.c
OBJ = $(SRC:.c=.o)
ASM = $(SRC:.c=.s)
.c.s:
$(CC) $(CFLAGS) -S -o $@ $<
bdfconv: $(OBJ) $(ASM)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ) -o bdfconv
clean:
-rm $(OBJ) $(ASM) bdfconv
test: bdfconv
./bdfconv
issue_1811: bdfconv
./bdfconv -f 1 -v -m '32-127,$$980-$$9FF,$$A00-$$A7F,$$A80-$$AFF,$$B00-$$B7f,$$B80-$$BFF,$$C00-$$C7f,$$C80-$$CFF' ../bdf/unifont.bdf -n unifont_1811 -o unifont_1811.c -d ../bdf/7x13.bdf
convert -trim bdf.tga issue_1811.png
greek: bdfconv
./bdfconv -f 1 -v -m '32-127,$$370-$$3ff' ../bdf/unifont.bdf -n unifont_greek -o unifont_greek.c -d ../bdf/7x13.bdf
cyrillic: bdfconv
./bdfconv -f 1 -v -m '$$20-$$7E, $$410-$$44F' ../bdf/unifont.bdf -n unifont_cyrillic_44f -o unifont_cyrillic_44f.c -d ../bdf/7x13.bdf
convert bdf.tga unifont_cyrillic_44f.png
./bdfconv -f 1 -v -m '$$20-$$7E, $$400-$$4ff' ../bdf/unifont.bdf -n unifont_cyrillic_4ff -o unifont_cyrillic_4ff.c -d ../bdf/7x13.bdf
convert bdf.tga unifont_cyrillic_4ff.png
battery19: bdfconv
./bdfconv -f 1 -v -m '32-127' ../bdf/battery19.bdf -n battery19 -o battery19.c -d ../bdf/7x13.bdf
battery24: bdfconv
./bdfconv -f 1 -v -m '32-127s' ../bdf/battery24.bdf -n battery24 -o battery24.c -d ../bdf/7x13.bdf
convert -trim bdf.tga battery24.png
hornet: bdfconv
./bdfconv -a -f 1 -v -m '32-127s' ./tmp/hornet.bdf -n hornet -o hornet.c -d ../bdf/7x13.bdf
convert -trim bdf.tga hornet.png
10x20greek: bdfconv
./bdfconv -f 1 -v -m '32-127,$$370-$$3ff' ../bdf/10x20.bdf -n 10x20_greek -o 10x20_greek.c -d ../bdf/7x13.bdf
5x7: bdfconv
./bdfconv -b 4 -f 1 -a -v -m '32-255' ../bdf/5x7.bdf -n 5x7lcd -o 5x7lcd.c -d ../bdf/7x13.bdf
ti83: bdfconv
-../otf2bdf/otf2bdf -n -p 5 -o ../bdf/ti83.bdf ../ttf/ti83.ttf
./bdfconv -b 4 -f 1 -a -v -m '32-65000' ../bdf/ti83.bdf -n u8g2_ti83_5x7 -o ti83.c -d ../bdf/7x13.bdf
kalpurush: bdfconv
-../otf2bdf/otf2bdf -g -v -p 16 -o ../bdf/kalpurush.bdf kalpurush.ttf
./bdfconv -f 1 -m '0-65000>32' ../bdf/kalpurush.bdf -n u8g2_kalpurush -o kalpurush.c -d ../bdf/7x13.bdf
convert bdf.tga -trim kalpurush.png
polish: bdfconv
./bdfconv -f 1 -v -m '32-127,$$104-$$107,$$118-$$119,$$141-$$144,$$15a-$$15b,$$179-$$17c,$$d3,$$f3' ../bdf/unifont.bdf -n unifont_polish -o unifont_polish.c -d ../bdf/7x13.bdf
helvb18: bdfconv
./bdfconv -f 1 -m '32-127,x32-64,x91-96,x123-191,x247,x697-879' -p 10 ../bdf/helvB18.bdf -o helvb18_tr.c -n u8g2_font_helvB18_tr -k helvb18_tr_k.c
helvb18n: bdfconv
./bdfconv -v -f 1 -m '32,48-57' ../bdf/helvB18.bdf -o helvb18_tn.c -n u8g2_font_helvB18_tn -d ../bdf/helvB18.bdf
dseg7: bdfconv
./bdfconv -v -f 1 -m '32-65000' dseg7_classic_regular.bdf -o u8g2_font_dseg7_classic_regular_all.c -n u8g2_font_dseg7_classic_regular_all -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_dseg7_classic_regular_all.png
nmv1: bdfconv
./bdfconv -v -f 1 -m '32-65000' NMV1.bdf -o u8g2_font_nmv1.c -n u8g2_font_nmv1 -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_nmv1.png
dseg7cr: bdfconv
./bdfconv -v -f 1 -b 2 -m '48-57,65-90,97-122' dseg7_classic_regular.bdf -o u8g2_font_dseg7_cr.c -n u8g2_font_dseg7_cr -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_dseg7_cr.png
dseg14cr: bdfconv
./bdfconv -v -f 1 -b 2 -m '32-255' dseg14_classic_regular.bdf -o u8g2_font_dseg14_cr.c -n u8g2_font_dseg14_cr -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_dseg14_cr.png
issue1769: bdfconv
./bdfconv -v -f 1 -b 2 -m '32-128' 3x7_Multi_V7.bdf -o u8g2_font_3x7_multi.c -n u8g2_font_3x7_multi -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_3x7_multi.png
emoticons21: bdfconv
./bdfconv -v -f 1 -m '32-64' ../emoticons/emoticons21.bdf -o emoticons21.c -n u8g2_font_emoticons21_tn -d ../bdf/helvB18.bdf
mmmicons: bdfconv
./bdfconv -v -f 1 -m '32-700' mmmicons.bdf -o mmmicons.c -n u8g2_font_mmmicons -d ../bdf/helvB18.bdf
convert bdf.tga -trim mmmicons.png
ded: bdfconv
./bdfconv -v -b 0 -f 1 ./F16_DED.bdf -o ded.c -n ded -d ../bdf/helvB12.bdf
old16x16: bdfconv
-../otf2bdf/otf2bdf -r 72 -p 16 -o tmp.bdf ../ttf/Px437_Wyse700a.ttf
./bdfconv -x 0 -y 8 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700a_ul_n.c -n u8x8_font_px437wyse700a_ul_n
./bdfconv -x 8 -y 8 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700a_ur_n.c -n u8x8_font_px437wyse700a_ur_n
./bdfconv -x 0 -y 0 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700a_ll_n.c -n u8x8_font_px437wyse700a_ll_n
./bdfconv -x 8 -y 0 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700a_lr_n.c -n u8x8_font_px437wyse700a_lr_n
./bdfconv -x 0 -y 8 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700a_ul_r.c -n u8x8_font_px437wyse700a_ul_r
./bdfconv -x 8 -y 8 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700a_ur_r.c -n u8x8_font_px437wyse700a_ur_r
./bdfconv -x 0 -y 0 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700a_ll_r.c -n u8x8_font_px437wyse700a_ll_r
./bdfconv -x 8 -y 0 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700a_lr_r.c -n u8x8_font_px437wyse700a_lr_r
./bdfconv -x 0 -y 8 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700a_ul_f.c -n u8x8_font_px437wyse700a_ul_f
./bdfconv -x 8 -y 8 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700a_ur_f.c -n u8x8_font_px437wyse700a_ur_f
./bdfconv -x 0 -y 0 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700a_ll_f.c -n u8x8_font_px437wyse700a_ll_f
./bdfconv -x 8 -y 0 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700a_lr_f.c -n u8x8_font_px437wyse700a_lr_f
-../otf2bdf/otf2bdf -r 72 -p 16 -o tmp.bdf ../ttf/Px437_Wyse700b.ttf
./bdfconv -x 0 -y 8 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700b_ul_n.c -n u8x8_font_px437wyse700b_ul_n
./bdfconv -x 8 -y 8 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700b_ur_n.c -n u8x8_font_px437wyse700b_ur_n
./bdfconv -x 0 -y 0 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700b_ll_n.c -n u8x8_font_px437wyse700b_ll_n
./bdfconv -x 8 -y 0 -v -f 2 -m '32-59' tmp.bdf -o u8x8_font_px437wyse700b_lr_n.c -n u8x8_font_px437wyse700b_lr_n
./bdfconv -x 0 -y 8 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700b_ul_r.c -n u8x8_font_px437wyse700b_ul_r
./bdfconv -x 8 -y 8 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700b_ur_r.c -n u8x8_font_px437wyse700b_ur_r
./bdfconv -x 0 -y 0 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700b_ll_r.c -n u8x8_font_px437wyse700b_ll_r
./bdfconv -x 8 -y 0 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700b_lr_r.c -n u8x8_font_px437wyse700b_lr_r
./bdfconv -x 0 -y 8 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700b_ul_f.c -n u8x8_font_px437wyse700b_ul_f
./bdfconv -x 8 -y 8 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700b_ur_f.c -n u8x8_font_px437wyse700b_ur_f
./bdfconv -x 0 -y 0 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700b_ll_f.c -n u8x8_font_px437wyse700b_ll_f
./bdfconv -x 8 -y 0 -v -f 2 -m '32-255' tmp.bdf -o u8x8_font_px437wyse700b_lr_f.c -n u8x8_font_px437wyse700b_lr_f
cat u8x8_font_px437*.c >16x16.c
16x16: bdfconv
-../otf2bdf/otf2bdf -r 72 -p 16 -o tmp.bdf ../ttf/Px437_Wyse700b.ttf
./bdfconv -y -1 -th 2 -tv 2 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700b_2x2_r.c -n u8x8_font_px437wyse700b_2x2_r
-../otf2bdf/otf2bdf -r 72 -p 16 -o tmp.bdf ../ttf/Px437_Wyse700a.ttf
./bdfconv -y -1 -th 2 -tv 2 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_px437wyse700a_2x2_r.c -n u8x8_font_px437wyse700a_2x2_r
-../otf2bdf/otf2bdf -r 72 -p 32 -o tmp.bdf ../ttf/BALTT_0.ttf
./bdfconv -y 0 -th 1 -tv 2 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_balthasar_titling_nbp_1x2_r.c -n u8x8_font_balthasar_titling_nbp_1x2_r
-../otf2bdf/otf2bdf -r 72 -p 32 -o tmp.bdf ../ttf/lucasarts-scumm-subtitle-roman-outline.ttf
./bdfconv -y 1 -th 2 -tv 2 -v -f 2 -m '32-127' tmp.bdf -o lucasarts_scumm_subtitle_o_2x2_r.c -n lucasarts_scumm_subtitle_o_2x2_r
-../otf2bdf/otf2bdf -r 72 -p 16 -o tmp.bdf ../ttf/lucasarts-scumm-subtitle-roman.ttf
./bdfconv -y 0 -th 2 -tv 2 -v -f 2 -m '32-127' tmp.bdf -o lucasarts_scumm_subtitle_r_2x2_r.c -n lucasarts_scumm_subtitle_r_2x2_r
./bdfconv -y -1 -th 2 -tv 3 -v -f 2 -m '32-127' ../bdf/courB18.bdf -o u8x8_font_courb18_2x3_r.c -n u8x8_font_courB18_2x3_r
./bdfconv -y -1 -th 2 -tv 3 -v -f 2 -m '32-127' ../bdf/courR18.bdf -o u8x8_font_courr18_2x3_r.c -n u8x8_font_courR18_2x3_r
./bdfconv -y -2 -th 3 -tv 4 -v -f 2 -m '32-127' ../bdf/courB24.bdf -o u8x8_font_courb24_3x4_r.c -n u8x8_font_courB24_3x4_r
./bdfconv -y -2 -th 3 -tv 4 -v -f 2 -m '32-127' ../bdf/courR24.bdf -o u8x8_font_courr24_3x4_r.c -n u8x8_font_courR24_3x4_r
./bdfconv -y 0 -th 2 -tv 3 -v -f 2 -m '32-127' ../bdf/profont29.bdf -o u8x8_font_profont29_2x3_r.c -n u8x8_font_profont29_2x3_r
./bdfconv -y -2 -th 1 -tv 2 -v -f 2 -m '32-127' ../bdf/8x13.bdf -o u8x8_font_8x13_r.c -n u8x8_font_8x13_1x2_r
./bdfconv -y -2 -th 1 -tv 2 -v -f 2 -m '32-127' ../bdf/8x13B.bdf -o u8x8_font_8x13b_r.c -n u8x8_font_8x13B_1x2_r
./bdfconv -y -1 -x -1 -th 1 -tv 2 -v -f 2 -m '32-127' ../bdf/7x14.bdf -o u8x8_font_7x14_r.c -n u8x8_font_7x14_1x2_r
./bdfconv -y -1 -x -1 -th 1 -tv 2 -v -f 2 -m '32-127' ../bdf/7x14B.bdf -o u8x8_font_7x14b_r.c -n u8x8_font_7x14B_1x2_r
-../otf2bdf/otf2bdf -r 72 -p 16 -o tmp.bdf ../ttf/shylock_nbp.ttf
./bdfconv -y -1 -th 1 -tv 2 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_shylock_nbp_1x2_r.c -n u8x8_font_shylock_nbp_1x2_r
-../otf2bdf/otf2bdf -a -r 72 -p 30 -o tmp.bdf ../ttf/inr.otf
./bdfconv -y -1 -x 1 -th 2 -tv 4 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_inr21_2x4_r.c -n u8x8_font_inr21_2x4_r
-../otf2bdf/otf2bdf -a -r 72 -p 44 -o tmp.bdf ../ttf/inr.otf
./bdfconv -y -1 -x 2 -th 3 -tv 6 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_inr33_3x6_r.c -n u8x8_font_inr33_3x6_r
-../otf2bdf/otf2bdf -a -r 72 -p 62 -o tmp.bdf ../ttf/inr.otf
./bdfconv -y 0 -x 3 -th 4 -tv 8 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_inr46_4x8_r.c -n u8x8_font_inr46_4x8_r
-../otf2bdf/otf2bdf -a -r 72 -p 30 -o tmp.bdf ../ttf/inb.otf
./bdfconv -y -1 -x 1 -th 2 -tv 4 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_inb21_2x4_r.c -n u8x8_font_inb21_2x4_r
-../otf2bdf/otf2bdf -a -r 72 -p 44 -o tmp.bdf ../ttf/inb.otf
./bdfconv -y -1 -x 2 -th 3 -tv 6 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_inb33_3x6_r.c -n u8x8_font_inb33_3x6_r
-../otf2bdf/otf2bdf -a -r 72 -p 62 -o tmp.bdf ../ttf/inb.otf
./bdfconv -y 0 -x 3 -th 4 -tv 8 -v -f 2 -m '32-127' tmp.bdf -o u8x8_font_inb46_4x8_r.c -n u8x8_font_inb46_4x8_r
./bdfconv -y 0 -th 2 -tv 2 -v -f 2 -m '32-127' ../bdf/open_iconic_weather_2x.bdf -o u8x8_font_open_iconic_weather_2x2.c -n u8x8_font_open_iconic_weather_2x2
./bdfconv -y 0 -th 4 -tv 4 -v -f 2 -m '32-127' ../bdf/open_iconic_weather_4x.bdf -o u8x8_font_open_iconic_weather_4x4.c -n u8x8_font_open_iconic_weather_4x4
./bdfconv -y 0 -th 8 -tv 8 -v -f 2 -m '32-127' ../bdf/open_iconic_weather_8x.bdf -o u8x8_font_open_iconic_weather_8x8.c -n u8x8_font_open_iconic_weather_8x8
falconded: bdfconv
-../otf2bdf/otf2bdf -n -p 12 -o falconded.bdf FalconDED2.ttf
./bdfconv -v -f 1 -b 2 -a -m '32-96' falconded.bdf -o u8g2_font_falconded_mr.c -n u8g2_font_falconded_mr -d ../bdf/helvR12.bdf
-../otf2bdf/otf2bdf -n -p 12 -o falconded.bdf FalconDED2.ttf
./bdfconv -v -f 1 -b 1 -a -m '32-96' falconded.bdf -o u8g2_font_falconded_hr.c -n u8g2_font_falconded_hr -d ../bdf/helvR12.bdf
falconded9: bdfconv
./bdfconv -v -f 1 -b 2 -a -m '32-99' falconded.bdf -o u8g2_font_falconded_mr.c -n u8g2_font_falconded_mr -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_falconded_mr.png
./bdfconv -v -f 1 -b 1 -a -m '32-99' falconded.bdf -o u8g2_font_falconded_hr.c -n u8g2_font_falconded_hr -d ../bdf/helvR12.bdf
convert bdf.tga -trim u8g2_font_falconded_hr.png
analecta: bdfconv
-../otf2bdf/otf2bdf -a -p 20 -o analecta.bdf Analecta.otf
./bdfconv -v -f 1 -m '32-65535' analecta.bdf -o u8g2_font_analecta.c -n u8g2_font_analecta -d ../bdf/helvB18.bdf
logisoso: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 131 -o tmp.bdf ../ttf/Logisoso.ttf
./bdfconv -v -f 1 -m '32,42-57' tmp.bdf -o u8g2_font_logisoso_tn.c -n u8g2_font_logisoso_tn -d ../bdf/helvB18.bdf
tpss: bdfconv
-../otf2bdf/otf2bdf -r 72 -p 8 -o tmp.bdf ../ttf/TEACPSS_.TTF
./bdfconv -v -f 1 -m '32-255' tmp.bdf -o u8g2_font_tpss_tf.c -n u8g2_font_tpss_tn -d ../bdf/helvR10.bdf
q_pixia: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 13 -o tmp.bdf q_pixia.ttf
./bdfconv -v -f 1 -m '32-65534' tmp.bdf -o u8g2_font_q_pixia.c -n u8g2_font_q_pixia -d ../bdf/helvB18.bdf
inr: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 86 -o tmp.bdf ../ttf/inr.otf
./bdfconv -v -b 2 -f 1 -m '42-57' tmp.bdf -o u8g2_font_inr64_m.c -n u8g2_font_inr64_m -d ../bdf/helvB18.bdf
-../otf2bdf/otf2bdf -a -r 72 -p 43 -o tmp.bdf ../ttf/inr.otf
./bdfconv -v -b 2 -f 1 -m '42-57' tmp.bdf -o u8g2_font_inr32_m.c -n u8g2_font_inr32_m -d ../bdf/helvB18.bdf
# ./bdfconv -v -b 2 -f 1 -m '32-128,$$400-$$52f' tmp.bdf -o u8g2_font_inr_m.c -n u8g2_font_inr_m -d ../bdf/helvB18.bdf
logisoso92x: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 131 -o tmp.bdf ../ttf/Logisoso.ttf
./bdfconv -v -f 1 -m '32,42-57,65-70' tmp.bdf -o u8g2_font_logisoso92_tx.c -n u8g2_font_logisoso92_tx -d ../bdf/helvB18.bdf
fub: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 40 -o tmp.bdf ../ttf/FreeUniversal-Bold.ttf
./bdfconv -v -f 2 -m '32-255' tmp.bdf -o fub30_tf.c -n fub30_tf -d ../bdf/helvB18.bdf
fub20x: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 27 -o tmp.bdf ../ttf/FreeUniversal-Bold.ttf
./bdfconv -v -f 1 -m '32-127,8364' tmp.bdf -o u8g2_font_fub20_tx.c -n u8g2_font_fub20_tx -d ../bdf/helvB18.bdf
unifont_emoticon: bdfconv
./bdfconv -v -f 1 -m '$$01f600-$$01f64f>$$20, $$01f910-$$01f92f>$$70, $$01f970-$$01f971>$$90, $$01f973-$$01f976>$$92,$$01f97a>$$96, $$01f9b8-$$01f9b9>$$97, $$01f9d0-$$01f9d6>$$99' ../bdf/unifont_upper.bdf -o u8g2_font_unifont_emoticon.c -n u8g2_font_unifont_emoticon_tx -d ../bdf/helvB18.bdf
unifont_misc_sym_and_pic: bdfconv
./bdfconv -v -f 1 -m '$$01f300-$$01f5ff>$$f300' ../bdf/unifont_upper.bdf -o u8g2_font_unifont_misc_sym_and_pic.c -n u8g2_font_unifont_misc_sym_and_pic_tx -d ../bdf/helvB18.bdf
unifont_animals: bdfconv
./bdfconv -v -f 1 -m '$$01f400-$$01f43f>$$20,$$01f980-$$01f9af>$$60' ../bdf/unifont_upper.bdf -o u8g2_font_unifont_animal.c -n u8g2_font_unifont_animal_tx -d ../bdf/helvB18.bdf
unifont_domino: bdfconv
./bdfconv -v -f 1 -m '$$01f030-$$01f093>$$20' ../bdf/unifont_upper.bdf -o u8g2_font_unifont_domino.c -n u8g2_font_unifont_domino_tx -d ../bdf/helvB18.bdf
unifont_cards: bdfconv
./bdfconv -v -f 1 -m '$$01f0a0-$$01f0f5>$$20' ../bdf/unifont_upper.bdf -o u8g2_font_unifont_cards.c -n u8g2_font_unifont_cards_tx -d ../bdf/helvB18.bdf
unifont_weather: bdfconv
./bdfconv -v -f 1 -m '$$01f310-$$01f32c>$$20' ../bdf/unifont_upper.bdf -o u8g2_font_unifont_weather.c -n u8g2_font_unifont_weather_tx -d ../bdf/helvB18.bdf
climacons: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 32 -o tmp.bdf Climacons.ttf
./bdfconv -v -f 1 -m '32-256' tmp.bdf -o u8g2_font_climacons.c -n u8g2_font_climacons -d ../bdf/helvB18.bdf
logisoso20x: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 30 -o tmp.bdf ../ttf/Logisoso.ttf
./bdfconv -v -f 1 -m '32-127,8364' tmp.bdf -o u8g2_font_logisoso20_tx.c -n u8g2_font_logisoso20_tx -d ../bdf/helvB18.bdf
xlogisoso: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 131 -o tmp.bdf ../ttf/Logisoso.ttf
./bdfconv -v -f 1 -m '32,42-57,$$370-$$3ff,$$2100-$$21ff' tmp.bdf -o u8g2_font_logisoso_tn.c -n u8g2_font_logisoso_tn -d ../bdf/helvB18.bdf
omega: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 32 -o tmp.bdf ../ttf/FreeUniversal-Regular.ttf
./bdfconv -v -f 1 -m '32,35-57,$$300-$$3ff,$$2030-$$3000' tmp.bdf -o u8g2_font_omega_tn.c -n u8g2_font_omega_tn -d ../bdf/helvB18.bdf
tga: bdfconv
./bdfconv -v -f 1 -m '32-255' ../bdf/helvB18.bdf -o helvb18_tn.c -n u8g2_font_helvB18_tn -d ../bdf/7x13.bdf
etl: bdfconv
./bdfconv -v -f 1 -m '32-127,128-255>3552' ../bdf/etl16-thai.bdf -o etl16_t.c -n u8g2_font_etl16_t -d ../bdf/7x13.bdf
etl2: bdfconv
./bdfconv -v -f 1 -m '32-127,128-255>14*256-32' ../bdf/etl16-thai.bdf -o etl16_t.c -n u8g2_font_etl16_t -d ../bdf/7x13.bdf
artos: bdfconv
./bdfconv -b 3 -d ../bdf/7x13.bdf ../bdf/ArtosSerif-8.bdf -a -v
hebrew: bdfconv
./bdfconv -v -f 1 -m '32-128,$$590-$$5ff,$$fb1d-$$fb4f' ../bdf/unifont.bdf -o u8g2_hebrew.c -n u8g2_hebrew -d ../bdf/helvB18.bdf
korean: bdfconv
./bdfconv -v -f 1 -m '32-128,$$AC00-$$D7AF' ../bdf/unifont.bdf -o u8g2_korean.c -n u8g2_korean -d ../bdf/helvB18.bdf
bengali: bdfconv
./bdfconv -v -f 1 -m '32-128,$$980-$$9ff' ../bdf/unifont.bdf -o u8g2_bengali.c -n u8g2_bengali -d ../bdf/helvB12.bdf
urdu: bdfconv
./bdfconv -v -f 1 -m '32-128,$$600-$$6ff,$$750-$$77f,$$fb50-$$fdff,$$fe70-$$feff' ../bdf/unifont.bdf -o u8g2_urdu.c -n u8g2_urdu -d ../bdf/helvB12.bdf
malayalam: bdfconv
./bdfconv -v -f 1 -m '32-128,$$d00-$$d7f' ../bdf/unifont.bdf -o u8g2_malayalam.c -n u8g2_font_malayalam -d ../bdf/helvB12.bdf
lubr24: bdfconv
./bdfconv -f 1 -m '32-65500' -p 10 lubR24.bdf -o lubR24.c -n u8g2_font_lubR24 -d ../bdf/helvB12.bdf
lurs24: bdfconv
./bdfconv -f 1 -m '32-255' -p 10 luRS24.bdf -o luRS24.c -n u8g2_font_luRS24 -d ../bdf/helvB12.bdf
luBS18: bdfconv
./bdfconv -v -f 1 -m '32-34,36-125,176>35,8364>126' -p 10 ../bdf/luBS18.bdf -o luBS18.c -n u8g2_font_luBS18 -d ../bdf/helvB12.bdf
siji: bdfconv
# ./bdfconv -v -f 1 -m '32-$$ffff' ./siji.bdf -o test1.c -n test -d ../bdf/helvB12.bdf
./bdfconv -v -f 1 -m '32-$$ffff' ../bdf/siji_with_6x10.bdf -o test2.c -n test -d ../bdf/helvB12.bdf
wqy: bdfconv
./bdfconv -v -f 1 -M ../build/gb2312.map ../bdf/wenquanyi_9pt.bdf -o test.c -n test -d ../bdf/helvB12.bdf
# ./bdfconv -v -f 1 -M ../build/gb2312.map ../bdf/wenquanyi_10pt.bdf -o test.c -n test -d ../bdf/helvB12.bdf
# ./bdfconv -v -f 1 -M ../build/gb2312.map ../bdf/wenquanyi_13px.bdf -o test.c -n test -d ../bdf/helvB12.bdf
# ./bdfconv -v -f 1 -M ../build/gb2312.map ../bdf/wenquanyi_11pt.bdf -o test.c -n test -d ../bdf/helvB12.bdf
# ./bdfconv -v -f 1 -M ../build/gb2312.map ../bdf/wenquanyi_12pt.bdf -o test.c -n test -d ../bdf/helvB12.bdf
ncenR24: bdfconv
./bdfconv -v -f 1 -b 0 -m '32-701>32,7838' ../bdf/ncenR24.bdf -n u8g2_font_ncenR24_te -o test.c
ncenR10: bdfconv
./bdfconv -v -f 1 -m '48-57,88,89' ../bdf/ncenR10.bdf -n u8g2_font_ncenR10 -o test.c -d ../bdf/helvB12.bdf
convert bdf.tga -trim ncenR10.png
profont12v2: bdfconv
#./bdfconv -v -f 1 -b 0 -m '32-701>32,7838' ../bdf/profont12v2.bdf -n u8g2_font_profont12v2_te -o test.c
./bdfconv -v -f 1 -b 0 -m '32-127' ../bdf/profont12v2.bdf -n u8g2_font_profont12v2_tr -o test.c
# http://stackoverflow.com/questions/713397/what-is-a-minimal-set-of-unicode-characters-for-reasonable-japanese-support
chinese: bdfconv
./bdfconv ../bdf/wenquanyi_9pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_wqy12_t_chinese1
convert bdf.tga -trim u8g2_font_wqy12_t_chinese1.png
./bdfconv ../bdf/wenquanyi_9pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_wqy12_t_chinese2
convert bdf.tga -trim u8g2_font_wqy12_t_chinese2.png
./bdfconv ../bdf/wenquanyi_9pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_wqy12_t_chinese3
convert bdf.tga -trim u8g2_font_wqy12_t_chinese3.png
./bdfconv ../bdf/wenquanyi_9pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312.map -d ../bdf/7x13.bdf -n u8g2_font_wqy12_t_gb2312
convert bdf.tga -trim u8g2_font_wqy12_t_gb2312.png
./bdfconv ../bdf/wenquanyi_9pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312a.map -d ../bdf/7x13.bdf -n u8g2_font_wqy12_t_gb2312a
convert bdf.tga -trim u8g2_font_wqy12_t_gb2312a.png
./bdfconv ../bdf/wenquanyi_9pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312b.map -d ../bdf/7x13.bdf -n u8g2_font_wqy12_t_gb2312b
convert bdf.tga -trim u8g2_font_wqy12_t_gb2312b.png
./bdfconv ../bdf/wenquanyi_10pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_wqy13_t_chinese1
convert bdf.tga -trim u8g2_font_wqy13_t_chinese1.png
./bdfconv ../bdf/wenquanyi_10pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_wqy13_t_chinese2
convert bdf.tga -trim u8g2_font_wqy13_t_chinese2.png
./bdfconv ../bdf/wenquanyi_10pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_wqy13_t_chinese3
convert bdf.tga -trim u8g2_font_wqy13_t_chinese3.png
./bdfconv ../bdf/wenquanyi_10pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312.map -d ../bdf/7x13.bdf -n u8g2_font_wqy13_t_gb2312
convert bdf.tga -trim u8g2_font_wqy13_t_gb2312.png
./bdfconv ../bdf/wenquanyi_10pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312a.map -d ../bdf/7x13.bdf -n u8g2_font_wqy13_t_gb2312a
convert bdf.tga -trim u8g2_font_wqy13_t_gb2312a.png
./bdfconv ../bdf/wenquanyi_10pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312b.map -d ../bdf/7x13.bdf -n u8g2_font_wqy13_t_gb2312b
convert bdf.tga -trim u8g2_font_wqy13_t_gb2312b.png
./bdfconv ../bdf/wenquanyi_13px.bdf -g 32 -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_wqy14_t_chinese1
convert bdf.tga -trim u8g2_font_wqy14_t_chinese1.png
./bdfconv ../bdf/wenquanyi_13px.bdf -g 32 -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_wqy14_t_chinese2
convert bdf.tga -trim u8g2_font_wqy14_t_chinese2.png
./bdfconv ../bdf/wenquanyi_13px.bdf -g 32 -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_wqy14_t_chinese3
convert bdf.tga -trim u8g2_font_wqy14_t_chinese3.png
./bdfconv ../bdf/wenquanyi_13px.bdf -g 32 -b 0 -f 1 -M ../build/gb2312.map -d ../bdf/7x13.bdf -n u8g2_font_wqy14_t_gb2312
convert bdf.tga -trim u8g2_font_wqy14_t_gb2312.png
./bdfconv ../bdf/wenquanyi_13px.bdf -g 32 -b 0 -f 1 -M ../build/gb2312a.map -d ../bdf/7x13.bdf -n u8g2_font_wqy14_t_gb2312a
convert bdf.tga -trim u8g2_font_wqy14_t_gb2312a.png
./bdfconv ../bdf/wenquanyi_13px.bdf -g 32 -b 0 -f 1 -M ../build/gb2312b.map -d ../bdf/7x13.bdf -n u8g2_font_wqy14_t_gb2312b
convert bdf.tga -trim u8g2_font_wqy14_t_gb2312b.png
./bdfconv ../bdf/wenquanyi_11pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_wqy15_t_chinese1
convert bdf.tga -trim u8g2_font_wqy15_t_chinese1.png
./bdfconv ../bdf/wenquanyi_11pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_wqy15_t_chinese2
convert bdf.tga -trim u8g2_font_wqy15_t_chinese2.png
./bdfconv ../bdf/wenquanyi_11pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_wqy15_t_chinese3
convert bdf.tga -trim u8g2_font_wqy15_t_chinese3.png
./bdfconv ../bdf/wenquanyi_11pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312.map -d ../bdf/7x13.bdf -n u8g2_font_wqy15_t_gb2312
convert bdf.tga -trim u8g2_font_wqy15_t_gb2312.png
./bdfconv ../bdf/wenquanyi_11pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312a.map -d ../bdf/7x13.bdf -n u8g2_font_wqy15_t_gb2312a
convert bdf.tga -trim u8g2_font_wqy15_t_gb2312a.png
./bdfconv ../bdf/wenquanyi_11pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312b.map -d ../bdf/7x13.bdf -n u8g2_font_wqy15_t_gb2312b
convert bdf.tga -trim u8g2_font_wqy15_t_gb2312b.png
./bdfconv ../bdf/wenquanyi_12pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_wqy16_t_chinese1
convert bdf.tga -trim u8g2_font_wqy16_t_chinese1.png
./bdfconv ../bdf/wenquanyi_12pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_wqy16_t_chinese2
convert bdf.tga -trim u8g2_font_wqy16_t_chinese2.png
./bdfconv ../bdf/wenquanyi_12pt.bdf -g 32 -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_wqy16_t_chinese3
convert bdf.tga -trim u8g2_font_wqy16_t_chinese3.png
./bdfconv ../bdf/wenquanyi_12pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312.map -d ../bdf/7x13.bdf -n u8g2_font_wqy16_t_gb2312
convert bdf.tga -trim u8g2_font_wqy16_t_gb2312.png
./bdfconv ../bdf/wenquanyi_12pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312a.map -d ../bdf/7x13.bdf -n u8g2_font_wqy16_t_gb2312a
convert bdf.tga -trim u8g2_font_wqy16_t_gb2312a.png
./bdfconv ../bdf/wenquanyi_12pt.bdf -g 32 -b 0 -f 1 -M ../build/gb2312b.map -d ../bdf/7x13.bdf -n u8g2_font_wqy16_t_gb2312b
convert bdf.tga -trim u8g2_font_wqy16_t_gb2312b.png
./bdfconv ../bdf/unifont.bdf -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_unifont_t_chinese1
convert bdf.tga -trim u8g2_font_unifont_t_chinese1.png
./bdfconv ../bdf/unifont.bdf -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_unifont_t_chinese2
convert bdf.tga -trim u8g2_font_unifont_t_chinese2.png
./bdfconv ../bdf/unifont.bdf -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_unifont_t_chinese3
convert bdf.tga -trim u8g2_font_unifont_t_chinese3.png
./bdfconv ../bdf/gb16st.bdf -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_gb16st_t_1
convert bdf.tga -trim u8g2_font_gb16st_t_1.png
./bdfconv ../bdf/gb16st.bdf -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_gb16st_t_2
convert bdf.tga -trim u8g2_font_gb16st_t_2.png
./bdfconv ../bdf/gb16st.bdf -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_gb16st_t_3
convert bdf.tga -trim u8g2_font_gb16st_t_3.png
./bdfconv ../bdf/gb24st.bdf -b 0 -f 1 -M ../build/chinese1.map -d ../bdf/7x13.bdf -n u8g2_font_gb24st_t_1
convert bdf.tga -trim u8g2_font_gb24st_t_1.png
./bdfconv ../bdf/gb24st.bdf -b 0 -f 1 -M ../build/chinese2.map -d ../bdf/7x13.bdf -n u8g2_font_gb24st_t_2
convert bdf.tga -trim u8g2_font_gb24st_t_2.png
./bdfconv ../bdf/gb24st.bdf -b 0 -f 1 -M ../build/chinese3.map -d ../bdf/7x13.bdf -n u8g2_font_gb24st_t_3
convert bdf.tga -trim u8g2_font_gb24st_t_3.png
gayathri: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 24 -o gayathri.bdf Gayatri.ttf
./bdfconv -v -f 1 -m '$$21-$$1fd,$$d00-$$d7f,$$200c-$$20b9,$$10003-$$102bc>$$e003' gayathri.bdf -o u8g2_font_gayathri_tn.c -n u8g2_font_gayathri_tn -d ../bdf/helvB18.bdf
convert bdf.tga gayathri.png
meera: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 24 -o meera.bdf Meera.ttf
./bdfconv -v -f 1 -m '$$21-$$2dc,$$d02-$$d6f,$$200c-$$2215,$$10003-$$1043f>$$e003' meera.bdf -o u8g2_font_meera_tn.c -n u8g2_font_meera_tn -d ../bdf/helvB18.bdf
convert bdf.tga meera.png
gess: bdfconv
./bdfconv -v -f 1 -m '$$20-$$ffff,~1588,~65010,~65205,~65206' GESSTwoBold-Bold-75.bdf -o u8g2_font_gess.c -n u8g2_font_gess -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_gess.png
CARSYMBOL: bdfconv
./bdfconv -v -f 1 -m '$$20-$$ffff' CARSYMBOL.bdf -o u8g2_font_carsymbol.c -n u8g2_font_carsymbol -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_carsymbol.png
Aurebesh: bdfconv
./bdfconv -v -f 1 -m '$$20-$$ff' Aurebesh.bdf -o u8g2_font_aurebesh.c -n u8g2_font_aurebesh -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_aurebesh.png
aurebesh_small: bdfconv
./bdfconv -v -f 1 -m '$$20-$$ff' aurebesh_small.bdf -o u8g2_font_aurebesh_small.c -n u8g2_font_aurebesh_small -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_aurebesh_small.png
issue_1521: bdfconv
./bdfconv -v -f 1 -m '$$0000-$$3B97' ../bdf/unifont.bdf -o unifont_custom.c -n unifont_custom -d ../bdf/helvB18.bdf
convert bdf.tga unifont_custom.png
out: bdfconv
./bdfconv -v -f 1 -m '$$0000-$$3B97' out.bdf -o out.c -n out -d ../bdf/helvR14.bdf
convert bdf.tga out.png
issue833: bdfconv
./bdfconv -v -f 1 -m '19968-40959' unifont-13.0.06.bdf -o out.c -n out -d unifont-13.0.06.bdf
convert bdf.tga out.png
waffle: bdfconv
./bdfconv -v -f 1 -m '32-65535' ../bdf/waffle-10.bdf -o tmp.c -n u8g2_font_helvB18_tn -d ../bdf/helvB18.bdf
convert bdf.tga out.png
CalBlk36: bdfconv
./bdfconv -v -f 1 -m '32-65535' ../bdf/CalBlk36.bdf -o tmp.c -n u8g2_font_helvB18_tn -d ../bdf/helvB18.bdf
convert bdf.tga out.png
CalLite24: bdfconv
./bdfconv -v -f 1 -m '32-65535' ../bdf/CalLite24.bdf -o tmp.c -n u8g2_font_helvB18_tn -d ../bdf/helvB18.bdf
convert bdf.tga out.png
7seg_33x19: bdfconv
./bdfconv -v -f 1 -m '32-79' ./tmp/7_Seg_33x19.bdf -o tmp.c -n u8g2_font_helvB18_tn -d ../bdf/helvB18.bdf
convert bdf.tga out.png
notos: bdfconv
./bdfconv -v -f 1 -m '32-65535,~9939,~10084' NotoEmoji-SemiBold-32.bdf -o u8g2_font_noto_semi_32_t.c -n u8g2_font_noto_semi_32_t -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_32_t.png
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1ffff>$$f300,~127995' NotoEmoji-SemiBold-32.bdf -o u8g2_font_noto_semi_32_t2.c -n u8g2_font_noto_semi_32_t2 -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_32_t2.png
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1f32c>$$f300,$$2600-$$2604,$$2614,$$26c4,$$26c5,$$26c8,$$26f1' NotoEmoji-SemiBold-24.bdf -o u8g2_font_noto_semi_24_t_weather.c -n u8g2_font_noto_semi_24_t_weather -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_24_t_weather.png
./bdfconv -v -f 1 -m '32-127,$$1f600-$$1f637>$$f600,$$1f641-$$1f64f>$$f641, $$1f910-$$1f917>$$f910, $$1f920-$$1f92f>$$f920, $$1f970-$$1f97a>$$f970, $$1fae0-$$1fae5>$$fae0' NotoEmoji-SemiBold-24.bdf -o u8g2_font_noto_semi_24_t_emoji.c -n u8g2_font_noto_semi_24_t_emoji -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_24_t_emoji.png
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1f32c>$$f300,$$2600-$$2604,$$2614,$$26c4,$$26c5,$$26c8,$$26f1' NotoEmoji-SemiBold-32.bdf -o u8g2_font_noto_semi_32_t_weather.c -n u8g2_font_noto_semi_32_t_weather -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_32_t_weather.png
./bdfconv -v -f 1 -m '32-127,$$1f600-$$1f637>$$f600,$$1f641-$$1f64f>$$f641, $$1f910-$$1f917>$$f910, $$1f920-$$1f92f>$$f920, $$1f970-$$1f97a>$$f970, $$1fae0-$$1fae5>$$fae0' NotoEmoji-SemiBold-32.bdf -o u8g2_font_noto_semi_32_t_emoji.c -n u8g2_font_noto_semi_32_t_emoji -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_32_t_emoji.png
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1f32c>$$f300,$$2600-$$2604,$$2614,$$26c4,$$26c5,$$26c8,$$26f1,~127747,~127751' NotoEmoji-SemiBold-40.bdf -o u8g2_font_noto_semi_40_t_weather.c -n u8g2_font_noto_semi_40_t_weather -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_40_t_weather.png
./bdfconv -v -f 1 -m '32-127,$$1f600-$$1f637>$$f600,$$1f641-$$1f64f>$$f641, $$1f910-$$1f917>$$f910, $$1f920-$$1f92f>$$f920, $$1f970-$$1f97a>$$f970, $$1fae0-$$1fae5>$$fae0, ~128561, ~128576' NotoEmoji-SemiBold-40.bdf -o u8g2_font_noto_semi_40_t_emoji.c -n u8g2_font_noto_semi_40_t_emoji -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_semi_40_t_emoji.png
notob: bdfconv
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1f32c>$$f300,$$2600-$$2604,$$2614,$$26c4,$$26c5,$$26c8,$$26f1' NotoEmoji-Bold-24.bdf -o u8g2_font_noto_bold_24_t_weather.c -n u8g2_font_noto_bold_24_t_weather -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_bold_24_t_weather.png
./bdfconv -v -f 1 -m '32-127,$$1f600-$$1f637>$$f600,$$1f641-$$1f64f>$$f641, $$1f910-$$1f917>$$f910, $$1f920-$$1f92f>$$f920, $$1f970-$$1f97a>$$f970, $$1fae0-$$1fae5>$$fae0' NotoEmoji-Bold-24.bdf -o u8g2_font_noto_bold_24_t_emoji.c -n u8g2_font_noto_bold_24_t_emoji -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_bold_24_t_emoji.png
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1f32c>$$f300,$$2600-$$2604,$$2614,$$26c4,$$26c5,$$26c8,$$26f1' NotoEmoji-Bold-32.bdf -o u8g2_font_noto_bold_32_t_weather.c -n u8g2_font_noto_bold_32_t_weather -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_bold_32_t_weather.png
./bdfconv -v -f 1 -m '32-127,$$1f600-$$1f637>$$f600,$$1f641-$$1f64f>$$f641, $$1f910-$$1f917>$$f910, $$1f920-$$1f92f>$$f920, $$1f970-$$1f97a>$$f970, $$1fae0-$$1fae5>$$fae0' NotoEmoji-Bold-32.bdf -o u8g2_font_noto_bold_32_t_emoji.c -n u8g2_font_noto_bold_32_t_emoji -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_bold_32_t_emoji.png
./bdfconv -v -f 1 -m '32-127,$$1f300-$$1f32c>$$f300,$$2600-$$2604,$$2614,$$26c4,$$26c5,$$26c8,$$26f1,~127747,~127751' NotoEmoji-Bold-40.bdf -o u8g2_font_noto_bold_40_t_weather.c -n u8g2_font_noto_bold_40_t_weather -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_bold_40_t_weather.png
./bdfconv -v -f 1 -m '32-127,$$1f600-$$1f637>$$f600,$$1f641-$$1f64f>$$f641, $$1f910-$$1f917>$$f910, $$1f920-$$1f92f>$$f920, $$1f970-$$1f97a>$$f970, $$1fae0-$$1fae5>$$fae0, ~128561, ~128576, ~128588' NotoEmoji-Bold-40.bdf -o u8g2_font_noto_bold_40_t_emoji.c -n u8g2_font_noto_bold_40_t_emoji -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_noto_bold_40_t_emoji.png
mystery_quest: bdfconv
-../otf2bdf/otf2bdf -a -r 72 -p 24 -o mystery-quest.regular.bdf ../ttf/mystery-quest.regular.ttf
./bdfconv -v -f 1 -m '32-127' mystery-quest.regular.bdf -o u8g2_font_mystery_quest_24_t.c -n u8g2_font_mystery_quest_24_t -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_mystery_quest_24_t.png
-../otf2bdf/otf2bdf -a -r 72 -p 28 -o mystery-quest.regular.bdf ../ttf/mystery-quest.regular.ttf
./bdfconv -v -f 1 -m '32-127' mystery-quest.regular.bdf -o u8g2_font_mystery_quest_28_t.c -n u8g2_font_mystery_quest_28_t -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_mystery_quest_28_t.png
-../otf2bdf/otf2bdf -a -r 72 -p 32 -o mystery-quest.regular.bdf ../ttf/mystery-quest.regular.ttf
./bdfconv -v -f 1 -m '32-127' mystery-quest.regular.bdf -o u8g2_font_mystery_quest_32_t.c -n u8g2_font_mystery_quest_32_t -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_mystery_quest_32_t.png
-../otf2bdf/otf2bdf -a -r 72 -p 36 -o mystery-quest.regular.bdf ../ttf/mystery-quest.regular.ttf
./bdfconv -v -f 1 -m '32-127' mystery-quest.regular.bdf -o u8g2_font_mystery_quest_36_t.c -n u8g2_font_mystery_quest_36_t -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_mystery_quest_36_t.png
-../otf2bdf/otf2bdf -a -r 72 -p 42 -o mystery-quest.regular.bdf ../ttf/mystery-quest.regular.ttf
./bdfconv -v -f 1 -m '32-127' mystery-quest.regular.bdf -o u8g2_font_mystery_quest_42_t.c -n u8g2_font_mystery_quest_42_t -d ../bdf/helvB18.bdf
convert bdf.tga u8g2_font_mystery_quest_42_t.png

196
font/bdfconv/bdf_8x8.c Normal file
View File

@ -0,0 +1,196 @@
/*
bdf_8x8.c
unencoded font format for 8x8 pixel font
offset bytes desc
0 1 first char
1 1 last char
2 1 horizontal tile count (x), new 2019 format, issue 771
3 1 vertical tile count (y), new 2019 format, issue 771
4 n font data, n = (last char - first char + 1)*8
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "bdf_font.h"
static int bg_8x8_convert(bg_t *bg, bbx_t *bbx, int xo, int yo)
{
int x;
int y;
int d;
if ( bbx == NULL )
bbx = &(bg->bbx);
/*
if ( bbx->w != 8 )
return 0;
if ( bbx->h != 8 )
return 0;
*/
/*
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
{
d = 0;
for( x = bbx->x; x < bbx->x + bbx->w; x++)
{
d <<= 1;
if ( bg_GetBBXPixel(bg, x, y) != 0 )
{
d++;
}
}
if ( bg_AddTargetData(bg, d) < 0 )
return 0;
}
*/
for( x = bbx->x; x < bbx->x + bbx->w; x++)
{
d = 0;
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
{
d >>= 1;
if ( bg_GetBBXPixel(bg, x+xo, y+yo) != 0 )
{
d |= 128;
}
}
if ( bg_AddTargetData(bg, d) < 0 )
return 0;
}
return 1;
}
void bf_Generate8x8Font(bf_t *bf, int xo, int yo)
{
int i, j, k;
bg_t *bg;
int first, last;
bbx_t local_bbx;
int is_glyph_written;
int x, y;
/* Step 1: Generate 8x8 bitmap data */
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
bf_copy_bbx_and_update_shift(bf, &local_bbx, bg);
if ( (local_bbx.w & 7) != 0 )
{
bf_Log(bf, "Generate8x8Font: Error, glyph width is not multiple of 8, width=%d, encoding=%d", local_bbx.w, bg->encoding);
}
else
{
if ( (local_bbx.h & 7) != 0 )
{
bf_Log(bf, "Generate8x8Font: Error, glyph height is not multiple of 8, height=%d, encoding=%d", local_bbx.h, bg->encoding);
}
else
{
bg_ClearTargetData(bg);
for( y = 0; y < bf->tile_v_size; y++ )
{
for( x = 0; x < bf->tile_h_size; x++ )
{
//bf_Log(bf, "Generate8x8Font: Encoding %d, x=%d, y=%d", bg->encoding, x, y);
if ( bg_8x8_convert(bg, &local_bbx, xo+8*x, yo+8*(bf->tile_v_size-y-1)) == 0 )
{
bf_Log(bf, "Generate8x8Font: Error, 8x8 conversion, encoding=%d", bg->target_cnt, bg->encoding);
}
}
}
}
}
}
}
/* Step 2: Calculate first and last char */
first = -1;
last = -1;
for( j = 0; j < 256; j++ )
{
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to == j )
{
if ( bg->target_data != NULL )
{
//bf_Log(bf, "Generate8x8Font: Encoding %d, size=%d", bg->encoding, bg->target_cnt);
if ( bg->target_cnt != bf->tile_h_size*bf->tile_v_size*8)
{
bf_Log(bf, "Generate8x8Font: Error, glyph size incorrect, size=%d, encoding=%d", bg->target_cnt, bg->encoding);
}
else
{
if ( first < 0 )
first = j;
last = j;
}
}
}
}
}
/* Step 3: Write font data */
bf_AddTargetData(bf, first);
bf_AddTargetData(bf, last);
bf_AddTargetData(bf, bf->tile_h_size);
bf_AddTargetData(bf, bf->tile_v_size);
bf_Log(bf, "Generate8x8Font: Tile size width=%d height=%d", bf->tile_h_size, bf->tile_v_size);
for( j = first; j <= last; j++ )
{
is_glyph_written = 0;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to == j )
{
if ( bg->target_data != NULL )
{
if ( bg->target_cnt == bf->tile_h_size*bf->tile_v_size*8)
{
for( k = 0; k < bg->target_cnt; k++ )
{
bf_AddTargetData(bf, bg->target_data[k]);
}
is_glyph_written = 1;
}
}
}
}
if ( is_glyph_written == 0 )
{
for( k = 0; k < bf->tile_h_size*bf->tile_v_size*8; k++ )
{
bf_AddTargetData(bf, 0);
}
}
}
bf_Log(bf, "Generate8x8Font: Font size %d", bf->target_cnt);
}

763
font/bdfconv/bdf_font.c Normal file
View File

@ -0,0 +1,763 @@
#include <stdlib.h>
#include <stdarg.h>
#include "bdf_font.h"
void bf_Error(bf_t *bf, char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
printf("\n");
va_end(va);
}
void bf_Log(bf_t *bf, char *fmt, ...)
{
va_list va;
va_start(va, fmt);
if ( bf->is_verbose != 0 )
{
vprintf(fmt, va);
printf("\n");
}
va_end(va);
}
/*
bf_Open(0, BDF_BBX_MODE_MINIMAL)
*/
bf_t *bf_Open(int is_verbose, int bbx_mode)
{
bf_t *bf;
bf = (bf_t *)malloc(sizeof(bf_t));
if ( bf != NULL )
{
bf->is_verbose = is_verbose;
bf->glyph_list = NULL;
bf->glyph_cnt = 0;
bf->glyph_max = 0;
bf->str_font = NULL; /* argument for FONT in bdf file */
bf->str_copyright = NULL; /* argument for COPYRIGHT in bdf file */
bf->target_data = NULL;
bf->target_max = 0;
bf->target_cnt = 0;
bf->selected_glyphs = 0;
bf->enc_w = 0;
bf->enc_h = 0;
bf->enc_x = 0;
bf->enc_y = 0;
bf->bbx_mode = bbx_mode;
bf->tile_h_size = 1;
bf->tile_v_size = 1;
return bf;
}
return NULL;
}
void bf_Clear(bf_t *bf)
{
int i;
for( i = 0; i < bf->glyph_cnt; i++ )
{
free( bf->glyph_list[i] );
}
bf->glyph_cnt = 0;
if ( bf->str_font != NULL )
free(bf->str_font);
bf->str_font = NULL;
if ( bf->str_copyright != NULL )
free(bf->str_copyright);
bf->str_copyright = NULL;
}
void bf_Close(bf_t *bf)
{
bf_Clear(bf);
if ( bf->glyph_list != NULL )
free(bf->glyph_list);
if ( bf->target_data != NULL )
free(bf->target_data);
bf->glyph_list = NULL;
bf->glyph_max = 0;
free(bf);
}
static int bf_extend(bf_t *bf)
{
int extend = 16;
void *ptr;
if ( bf->glyph_list == NULL )
{
ptr = malloc(extend*sizeof(bg_t *));
bf->glyph_max = 0;
}
else
{
ptr = realloc(bf->glyph_list, (bf->glyph_max + extend)*sizeof(bg_t *));
}
if ( ptr == NULL )
return 0;
bf->glyph_max += extend;
bf->glyph_list = (bg_t **)ptr;
return 1;
}
/* returns glyph position or -1 */
int bf_AddGlyph(bf_t *bf)
{
while( bf->glyph_max <= bf->glyph_cnt )
if ( bf_extend(bf) == 0 )
return -1;
bf->glyph_list[bf->glyph_cnt] = bg_Open();
if ( bf->glyph_list[bf->glyph_cnt] == NULL )
return -1;
bf->glyph_list[bf->glyph_cnt]->bf = bf;
bf->glyph_cnt++;
return bf->glyph_cnt-1;
}
static int bf_extend_target_data(bf_t *bf)
{
int extend = 16;
int i;
void *ptr;
if ( bf->target_data == NULL )
{
ptr = malloc(extend*sizeof(uint8_t));
bf->target_max = 0;
}
else
{
ptr = realloc(bf->target_data, (bf->target_max + extend)*sizeof(uint8_t));
}
if ( ptr == NULL )
return 0;
bf->target_data = (uint8_t *)ptr;
for( i = bf->target_max; i < bf->target_max + extend; i++ )
bf->target_data[i] = 0;
bf->target_max += extend;
return 1;
}
int bf_AddTargetData(bf_t *bf, uint8_t data)
{
while( bf->target_max <= bf->target_cnt )
if ( bf_extend_target_data(bf) == 0 )
return -1;
bf->target_data[bf->target_cnt] = data;
bf->target_cnt++;
return bf->target_cnt-1;
}
void bf_ClearTargetData(bf_t *bf)
{
int i;
for( i = 0; i < bf->target_max; i++ )
bf->target_data[i] = 0;
bf->target_cnt = 0;
}
void bf_CalculateSelectedNumberOfGlyphs(bf_t *bf)
{
int i;
bg_t *bg;
bf->selected_glyphs = 0;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
bf->selected_glyphs++;
}
}
}
void bf_ReduceAllGlyph(bf_t *bf)
{
int i;
bg_t *bg;
int red_x, red_y;
bf_Log(bf, "Reduce: Start");
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
bg_ReduceGlyph(bg);
//bg_ShowBitmap(bg, &(bg->bbx));
red_x = bg->bitmap_width - bg->bbx.w;
red_y = bg->bitmap_height - bg->bbx.h;
if ( red_x > 0 || red_y > 0 )
{
//bf_Log(bf, "Reduce: Encoding %ld, x by %d, y by %d", bg->encoding, red_x, red_y);
}
}
}
bf_Log(bf, "Reduce: End");
}
void bf_ShowAllGlyphs(bf_t *bf, bbx_t *bbx)
{
int i;
bg_t *bg;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
bg_ShowBitmap(bg, bbx);
}
}
}
int bf_GetIndexByEncoding(bf_t *bf, long encoding)
{
int i;
bg_t *bg;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->encoding == encoding )
return i;
}
return -1;
}
void bf_CalculateMaxBBX(bf_t *bf)
{
int i;
int is_first = 1;
int enc_idx;
bg_t *bg;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
if ( is_first != 0 )
{
bf->max = bg->bbx;
bf->enc_x = bg->encoding;
bf->enc_y = bg->encoding;
bf->enc_w = bg->encoding;
bf->enc_h = bg->encoding;
is_first = 0;
}
else
{
enc_idx = bg_Max(bg, &(bf->max));
switch(enc_idx)
{
case 1:
bf->enc_w = bg->encoding;
break;
case 2:
bf->enc_h = bg->encoding;
break;
case 3:
bf->enc_x = bg->encoding;
break;
case 4:
bf->enc_y = bg->encoding;
break;
}
}
}
}
if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
{
/* old
bf->max.w = ( bf->max.w + 7 ) & ~7;
bf->max.h = ( bf->max.h + 7 ) & ~7;
*/
bf->max.w = 8;
bf->max.h = 7;
}
bf_Log(bf, "CalculateMaxBBX: x=%ld, y=%ld, w=%ld, h=%ld", bf->max.x, bf->max.y, bf->max.w, bf->max.h);
bf_Log(bf, "CalculateMaxBBX: Encodings x=%ld, y=%ld, w=%ld, h=%ld", bf->enc_x, bf->enc_y, bf->enc_w, bf->enc_h);
}
void bf_CalculateMinMaxDWidth(bf_t *bf)
{
int i;
bg_t *bg;
bf->dx_min = 0x07fff;
bf->dx_max = -0x07fff;
bf->x_min = 0x07fff;
bf->x_max = -0x07fff;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
if ( bf->dx_min > bg->dwidth_x )
bf->dx_min = bg->dwidth_x;
if ( bf->dx_max < bg->dwidth_x )
bf->dx_max = bg->dwidth_x;
if ( bf->x_min > bg->bbx.x )
bf->x_min = bg->bbx.x;
if ( bf->x_max < bg->bbx.x )
bf->x_max = bg->bbx.x;
}
}
bf_Log(bf, "bf_CalculateMinMaxDWidth: dx_min=%ld, dx_max=%ld", bf->dx_min, bf->dx_max);
bf_Log(bf, "bf_CalculateMinMaxDWidth: x_min=%ld, x_max=%ld", bf->x_min, bf->x_max);
if ( bf->dx_min == bf->dx_max && bf->x_min >= 0 )
{
bf_Log(bf, "bf_CalculateMinMaxDWidth: Monospaced font."); /* not sufficient: also bbx.x must be >= 0 for all glyphs */
/* for a monospaced font, dx must be identical to bbx.w */
}
}
int get_unsigned_bit_size(unsigned long v)
{
int i = 0;
while( v != 0 )
{
v = v / 2;
i++;
}
return i;
}
int get_signed_bit_size(long v)
{
if ( v < 0 )
return get_unsigned_bit_size(-v-1) + 1;
return get_unsigned_bit_size(v) + 1;
}
/*
#define BDF_BBX_MODE_MINIMAL 0
#define BDF_BBX_MODE_HEIGHT 1
#define BDF_BBX_MODE_MAX 2
#define BDF_BBX_MODE_M8 3
*/
void bf_copy_bbx_and_update_shift(bf_t *bf, bbx_t *target_bbx, bg_t *bg)
{
/* modifing the following code requires update ind bdf_rle.c also */
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL ) // mode 0
{
*target_bbx = bg->bbx;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX ) // mode 2 (monospace)
{
*target_bbx = bf->max;
target_bbx->x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
if ( target_bbx->w < bg->dwidth_x )
target_bbx->w = bg->dwidth_x;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_5X7 ) // mode 4 (5x7 displays)
{
*target_bbx = bf->max;
target_bbx->x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
target_bbx->w = 5;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
{
/* old
target_bbx->w = bf->max.w;
if ( target_bbx->w < bg->dwidth_x )
target_bbx->w = bg->dwidth_x;
target_bbx->w = (target_bbx->w+7) & ~7;
target_bbx->h = (bf->max.h+7) & ~7;
*/
target_bbx->w = 8;
target_bbx->h = 8;
target_bbx->x = bf->max.x;
target_bbx->y = bf->max.y;
target_bbx->x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
}
else
{
*target_bbx = bf->max;
target_bbx->w = bg->bbx.w;
target_bbx->x = bg->bbx.x;
target_bbx->x = 0;
if ( bg->bbx.x < 0 )
{
/* e.g. "j" */
target_bbx->w -= bg->bbx.x;
bg->shift_x = bg->bbx.x;
}
else
{
/* e.g. "B" */
target_bbx->w += bg->bbx.x;
//bg->shift_x = bg->bbx.x;
}
if ( target_bbx->w < bg->dwidth_x )
target_bbx->w = bg->dwidth_x;
}
bg->width_deviation = target_bbx->w - bg->bbx.w;
}
void bf_CalculateMaxBitFieldSize(bf_t *bf)
{
int i;
bg_t *bg;
int bs;
bbx_t local_bbx;
bf->bbx_x_max_bit_size = 0;
bf->bbx_y_max_bit_size = 0;
bf->bbx_w_max_bit_size = 0;
bf->bbx_h_max_bit_size = 0;
bf->dx_max_bit_size = 0;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
bf_copy_bbx_and_update_shift(bf, &local_bbx, bg);
#ifdef OLD_CLODE
/* modifing the following code requires update ind bdf_rle.c also */
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
{
local_bbx = bg->bbx;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
{
local_bbx = bf->max;
local_bbx.x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
if ( local_bbx.w < bg->dwidth_x )
local_bbx.w = bg->dwidth_x;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
{
local_bbx.w = bf->max.w;
if ( local_bbx.w < bg->dwidth_x )
local_bbx.w = bg->dwidth_x;
local_bbx.w = (local_bbx.w+7) & ~7;
local_bbx.h = (bf->max.h+7) & ~7;
local_bbx.x = bf->max.x;
local_bbx.y = bf->max.y;
local_bbx.x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
}
else
{
local_bbx = bf->max;
local_bbx.w = bg->bbx.w;
local_bbx.x = bg->bbx.x;
local_bbx.x = 0;
if ( bg->bbx.x < 0 )
{
/* e.g. "j" */
local_bbx.w -= bg->bbx.x;
bg->shift_x = bg->bbx.x;
}
else
{
/* e.g. "B" */
local_bbx.w += bg->bbx.x;
//bg->shift_x = bg->bbx.x;
}
if ( local_bbx.w < bg->dwidth_x )
local_bbx.w = bg->dwidth_x;
}
#endif
bs = get_unsigned_bit_size(local_bbx.w);
if ( bf->bbx_w_max_bit_size < bs )
bf->bbx_w_max_bit_size = bs;
bs = get_unsigned_bit_size(local_bbx.h);
if ( bf->bbx_h_max_bit_size < bs )
bf->bbx_h_max_bit_size = bs;
//printf("%ld ", local_bbx.x);
bs = get_signed_bit_size(local_bbx.x);
if ( bf->bbx_x_max_bit_size < bs )
bf->bbx_x_max_bit_size = bs;
//printf("%d:%d ",(int)local_bbx->x, (int)bs);
bs = get_signed_bit_size(local_bbx.y);
if ( bf->bbx_y_max_bit_size < bs )
bf->bbx_y_max_bit_size = bs;
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
{
bs = get_signed_bit_size(bg->dwidth_x);
}
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
{
bs = get_signed_bit_size(local_bbx.w);
}
else
{
bs = get_signed_bit_size(local_bbx.w);
}
if ( bf->dx_max_bit_size < bs )
bf->dx_max_bit_size = bs;
}
}
bf_Log(bf, "bf_CalculateMaxBitFieldSize: bbx.x=%d, bbx.y=%d, bbx.w=%d, bbx.h=%d, dwidth=%d",
bf->bbx_x_max_bit_size, bf->bbx_y_max_bit_size, bf->bbx_w_max_bit_size, bf->bbx_h_max_bit_size, bf->dx_max_bit_size);
}
void bf_ShowMonospaceStatistics(bf_t *bf)
{
int i;
bg_t *bg;
long cnt = 0;
long max = 0;
long sum = 0;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
if ( max < bg->width_deviation )
max = bg->width_deviation;
sum += bg->width_deviation;
cnt++;
}
}
if ( cnt == 0 )
cnt++;
bf_Log(bf, "Monospace Statistics: Max width extention %ld, average width extention %ld.%ld", max, sum/cnt, (sum*10/cnt) % 10 );
/*
Monospaced font: average width extention does not differ much between -b 1 and --b 2
Variable width font: big difference for the average width extention between modes 1 and 2.
Examples:
./bdfconv -b 1 -v ../bdf/profont12.bdf
Monospace Statistics: Max width extention 6, average width extention 1.7
./bdfconv -b 2 -v ../bdf/profont12.bdf
Monospace Statistics: Max width extention 6, average width extention 1.7
--> profont12.bdf is a monospaced font
./bdfconv -b 1 -v ../bdf/helvR12.bdf
Monospace Statistics: Max width extention 6, average width extention 1.9
./bdfconv -b 2 -v ../bdf/helvR12.bdf
Monospace Statistics: Max width extention 15, average width extention 8.0
--> helvR12.bdf is not a monospaced font
*/
}
int bf_WriteUCGCByFP(bf_t *bf, FILE *out_fp, const char *fontname, const char *indent)
{
int i;
int bytes_per_line = 16;
fprintf(out_fp, "/*\n");
fprintf(out_fp, " Fontname: %s\n", bf->str_font);
fprintf(out_fp, " Copyright: %s\n", bf->str_copyright);
fprintf(out_fp, " Glyphs: %d/%d\n", (int)bf->selected_glyphs, (int)bf->glyph_cnt );
fprintf(out_fp, " BBX Build Mode: %d\n", (int)bf->bbx_mode);
fprintf(out_fp, "*/\n");
fprintf(out_fp, "#include \"ucg.h\"\n");
fprintf(out_fp, "const ucg_fntpgm_uint8_t %s[%d] UCG_FONT_SECTION(\"%s\") = {\n", fontname, bf->target_cnt, fontname);
fprintf(out_fp, " ");
for( i = 0; i < bf->target_cnt; i++ )
{
fprintf(out_fp, "%d", bf->target_data[i]);
if ( i+1 != bf->target_cnt )
fprintf(out_fp, ",");
if ( (i+1) % bytes_per_line == 0 )
fprintf(out_fp, "\n%s", indent);
}
fprintf(out_fp, "};\n");
return 1;
}
int bf_WriteU8G2CByFP(bf_t *bf, FILE *out_fp, const char *fontname, const char *indent)
{
int i;
int bytes_per_line = 32;
int extra1;
fprintf(out_fp, "/*\n");
fprintf(out_fp, " Fontname: %s\n", bf->str_font);
fprintf(out_fp, " Copyright: %s\n", bf->str_copyright);
fprintf(out_fp, " Glyphs: %d/%d\n", (int)bf->selected_glyphs, (int)bf->glyph_cnt );
fprintf(out_fp, " BBX Build Mode: %d\n", (int)bf->bbx_mode);
fprintf(out_fp, "*/\n");
if ( bf->target_data[bf->target_cnt-1] == 0 )
extra1 = 0;
else
extra1 = 1;
if ( bf->target_cnt-1+extra1 > 32760 )
{
fprintf(out_fp, "#ifdef U8G2_USE_LARGE_FONTS\n");
}
if ( bf->bbx_mode == 3 ) // maybe better check for the font_format
{
//fprintf(out_fp, "#include \"u8x8.h\"\n");
fprintf(out_fp, "const uint8_t %s[%d] U8X8_FONT_SECTION(\"%s\") = \n", fontname, bf->target_cnt+extra1, fontname);
}
else
{
//fprintf(out_fp, "#include \"u8g2.h\"\n");
fprintf(out_fp, "const uint8_t %s[%d] U8G2_FONT_SECTION(\"%s\") = \n", fontname, bf->target_cnt+extra1, fontname);
}
fprintf(out_fp, "%s\"", indent);
for( i = 0; i < bf->target_cnt-1+extra1; i++ )
{
if ( bf->target_data[i] < 32 || bf->target_data[i] == '\"' || bf->target_data[i] == '\\' || bf->target_data[i] == '?' || ( bf->target_data[i] >= '0' && bf->target_data[i] <= '9' ))
{
fprintf(out_fp, "\\%o", bf->target_data[i]);
//fprintf(out_fp, "\\x%02x", bf->target_data[i]);
}
else if ( bf->target_data[i] < 127 ) /* issue 482, do not output ASCII char 127, instead use octal code for 127 */
{
fprintf(out_fp, "%c", bf->target_data[i]);
}
else
{
fprintf(out_fp, "\\%o", bf->target_data[i]);
}
if ( (i+1) % bytes_per_line == 0 )
fprintf(out_fp, "\"\n%s\"", indent);
}
fprintf(out_fp, "\";\n");
if ( bf->target_cnt-1+extra1 > 32760 )
{
fprintf(out_fp, "#endif /* U8G2_USE_LARGE_FONTS */\n");
}
return 1;
}
int bf_WriteUCGCByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent)
{
FILE *fp;
fp = fopen(filename, "wb");
if ( fp == NULL )
{
bf_Log(bf, "bf_WriteUCGCByFilename: Open error '%s'", filename);
return 0;
}
bf_WriteUCGCByFP(bf, fp, fontname, indent);
bf_Log(bf, "bf_WriteUCGCByFilename: Write file '%s'", filename);
fclose(fp);
return 1;
}
/* called from main() */
int bf_WriteU8G2CByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent)
{
FILE *fp;
fp = fopen(filename, "wb");
if ( fp == NULL )
{
bf_Log(bf, "bf_WriteU8G2CByFilename: Open error '%s'", filename);
return 0;
}
bf_WriteU8G2CByFP(bf, fp, fontname, indent);
bf_Log(bf, "bf_WriteU8G2CByFilename: Write file '%s'", filename);
fclose(fp);
return 1;
}
/*
xo, yo: offset for 8x8 fonts (font_format==2)
called from main()
*/
bf_t *bf_OpenFromFile(const char *bdf_filename, int is_verbose, int bbx_mode, const char *map_str, const char *map_file_name, int font_format, int xo, int yo, int th, int tv)
{
bf_t *bf;
bf = bf_Open(is_verbose, bbx_mode);
if ( bf != NULL )
{
bf->tile_h_size = th;
bf->tile_v_size = tv;
if ( bf_ParseFile(bf, bdf_filename) != 0 )
{
if ( map_file_name[0] != '\0' )
{
bf_MapFile(bf, map_file_name);
}
else
{
bf_Map(bf, map_str);
}
bf_CalculateSelectedNumberOfGlyphs(bf);
bf_ReduceAllGlyph(bf);
bf_CalculateMaxBBX(bf);
//bf_ShowAllGlyphs(bf, &(bf->max));
bf_CalculateMinMaxDWidth(bf);
/* issue 669 */
if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
if ( bf->max.w < bf->dx_max )
bf->max.w = bf->dx_max;
bf_CalculateMaxBitFieldSize(bf);
if ( font_format == 0 || font_format == 1 )
{
bf_RLECompressAllGlyphs(bf);
}
else
{
bf_Generate8x8Font(bf, xo, yo); /* bdf_8x8.c */
}
if ( bf->bbx_mode != BDF_BBX_MODE_MINIMAL )
bf_ShowMonospaceStatistics(bf); /* Show stats only for none minimal mode. For minimal mode it will always be zero */
return bf;
}
bf_Close(bf);
}
return NULL;
}

162
font/bdfconv/bdf_font.h Normal file
View File

@ -0,0 +1,162 @@
/*
bdf_font.h
*/
#ifndef _BDF_FONT_H
#define _BDF_FONT_H
#include <stdio.h>
#include "bdf_glyph.h"
#define BDF_LINE_LEN 1024
#define BDF_BBX_MODE_MINIMAL 0
#define BDF_BBX_MODE_HEIGHT 1
#define BDF_BBX_MODE_MAX 2
#define BDF_BBX_MODE_M8 3
#define BDF_BBX_MODE_5X7 4
struct _bdf_font_struct
{
int is_verbose;
bg_t **glyph_list;
int glyph_cnt;
int glyph_max;
/* variables for the parser */
char line_buf[BDF_LINE_LEN];
int line_pos;
int is_bitmap_parsing;
long encoding;
long dwidth_x;
long dwidth_y;
long bbx_w;
long bbx_h;
long bbx_x;
long bbx_y;
int bitmap_x; /* x position within bitmap parsing */
int bitmap_y; /* y position within bitmap parsing */
int glyph_pos; /* the position to which the glyph has been added in the list */
FILE *fp;
char *str_font; /* argument for FONT in bdf file */
char *str_copyright; /* argument for COPYRIGHT in bdf file */
long selected_glyphs; /* number of mapped glyphs */
int bbx_mode; /* bounding box mode, one of BDF_BBX_MODE_xxx */
/* bf_CalculateMaxBBX */
bbx_t max; /* max bbx, calculated from the mapped glyphs by bf_CalculateMaxBBX */
/* remember which encoding has caused the max value */
long enc_w;
long enc_h;
long enc_x;
long enc_y;
/* bf_CalculateMinMaxDWidth */
long dx_min; /* calculated minimum and maximum dwidth value from the mapped glyphs by bf_CalculateMinMaxDWidth */
long dx_max; /* it is a monospaced font if max and min values are identical */
/* bf_CalculateMinMaxDWidth */
long x_min; /* calculated minimum and maximum bbx.x value from the mapped glyphs by bf_CalculateMinMaxDWidth */
long x_max; /* it is a monospaced font if x_min >= 0 */
/* bf_CalculateMaxBitFieldSize */
int bbx_x_max_bit_size;
int bbx_y_max_bit_size;
int bbx_w_max_bit_size;
int bbx_h_max_bit_size;
int dx_max_bit_size;
/* font target data */
uint8_t *target_data;
int target_max;
int target_cnt;
int tile_h_size; // new 2019 8x8 font format
int tile_v_size; // new 2019 8x8 font format
};
/* bdf_font.c */
/* output error & log messages */
void bf_Error(bf_t *bf, char *fmt, ...);
void bf_Log(bf_t *bf, char *fmt, ...);
/* constructor/destructor */
bf_t *bf_Open(int is_verbose, int bbx_mode);
void bf_Close(bf_t *bf);
/* returns glyph position or -1 */
int bf_AddGlyph(bf_t *bf);
/* add binary data */
void bf_ClearTargetData(bf_t *bf);
int bf_AddTargetData(bf_t *bf, uint8_t data);
void bf_CalculateSelectedNumberOfGlyphs(bf_t *bf);
void bf_ReduceAllGlyph(bf_t *bf);
int bf_GetIndexByEncoding(bf_t *bf, long encoding);
/* only shows glyphs, which will be mapped (call bf_Map() first) */
void bf_ShowAllGlyphs(bf_t *bf, bbx_t *bbx);
void bf_ShowMonospaceStatistics(bf_t *bf);
/* calculate the max bbx for all mapped glyphs (call bf_Map() first) */
void bf_CalculateMaxBBX(bf_t *bf);
void bf_CalculateMinMaxDWidth(bf_t *bf);
void bf_copy_bbx_and_update_shift(bf_t *bf, bbx_t *target_bbx, bg_t *bg);
void bf_CalculateMaxBitFieldSize(bf_t *bf);
void bf_RLECompressAllGlyphs(bf_t *bf);
void bf_Generate8x8Font(bf_t *bf, int xo, int yo);
int bf_WriteUCGCByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent);
int bf_WriteU8G2CByFilename(bf_t *bf, const char *filename, const char *fontname, const char *indent);
bf_t *bf_OpenFromFile(const char *bdf_filename, int is_verbose, int bbx_mode, const char *map_str, const char *map_file_name, int font_format, int xo, int yo, int th, int tv);
/* bdf_parser.c */
int bf_ParseFile(bf_t *bf, const char *name);
/* bdf_map.c */
void bf_Map(bf_t *bf, const char *map_cmd_list);
int bf_MapFile(bf_t *bf, const char *map_file_name);
/* bdf_tga.c */
int tga_init(uint16_t w, uint16_t h);
void tga_clear(void);
void tga_set_pixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
void tga_save(const char *name);
void tga_set_font(uint8_t *font);
uint8_t *tga_get_glyph_data(uint16_t encoding);
int tga_get_char_width(void);
int tga_get_char_height(void);
unsigned tga_draw_glyph(unsigned x, unsigned y, uint16_t encoding, int is_hints);
unsigned tga_draw_string(unsigned x, unsigned y, const char *s, int is_hints, unsigned max_dx);
int tga_is_pixel_intersection(void);
void tga_clear_pixel_intersection(void);
/* bdf_kern.c */
unsigned bdf_calculate_kerning(uint8_t *font, uint16_t e1, uint16_t e2, uint8_t min_distance_in_per_cent_of_char_width);
void bdf_calculate_all_kerning(bf_t *bf, const char *filename, const char *fontname, uint8_t min_distance_in_per_cent_of_char_width);
#endif

439
font/bdfconv/bdf_glyph.c Normal file
View File

@ -0,0 +1,439 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "bdf_glyph.h"
bg_t *bg_Open(void)
{
bg_t *bg;
bg = (bg_t *)malloc(sizeof(bg_t));
if ( bg != NULL )
{
bg->encoding = 0;
bg->map_to = -1;
bg->bitmap_data = NULL;
bg->target_data = NULL;
bg->target_max = 0;
bg->target_cnt = 0;
bg->shift_x = 0;
bg->is_excluded_from_kerning = 0;
return bg;
}
return NULL;
}
void bg_Close(bg_t *bg)
{
if ( bg->bitmap_data != NULL )
free(bg->bitmap_data);
if ( bg->target_data != NULL )
free(bg->target_data);
bg->bitmap_data = NULL;
bg->target_data =NULL;
bg->target_max = 0;
bg->target_cnt = 0;
bg->target_bit_pos = 0;
bg->encoding = 0;
free(bg);
}
static int bg_extend_target_data(bg_t *bg)
{
int extend = 16;
int i;
void *ptr;
if ( bg->target_data == NULL )
{
ptr = malloc(extend*sizeof(uint8_t));
bg->target_max = 0;
}
else
{
ptr = realloc(bg->target_data, (bg->target_max + extend)*sizeof(uint8_t));
}
if ( ptr == NULL )
return 0;
bg->target_data = (uint8_t *)ptr;
for( i = bg->target_max; i < bg->target_max + extend; i++ )
bg->target_data[i] = 0;
bg->target_max += extend;
return 1;
}
int bg_AddTargetData(bg_t *bg, uint8_t data)
{
while( bg->target_max <= bg->target_cnt )
if ( bg_extend_target_data(bg) == 0 )
return -1;
bg->target_data[bg->target_cnt] = data;
bg->target_cnt++;
return bg->target_cnt-1;
}
void bg_ClearTargetData(bg_t *bg)
{
int i;
for( i = 0; i < bg->target_max; i++ )
bg->target_data[i] = 0;
bg->target_cnt = 0;
bg->target_bit_pos = 0;
}
/*
Desc:
Output a field to the target bitstream. The field size in bits is given by "cnt" and
the value of the field is "val".
Args:
cnt: Fieldsize in bits, must be lower or equal to 8
val: The value (content) of the field. Side condition: val < (1<<cnt) && val >= 0
*/
int bg_AddTargetBits(bg_t *bg, unsigned cnt, unsigned val)
{
assert( val < (1<<cnt) );
while( bg->target_max <= bg->target_cnt+1 )
if ( bg_extend_target_data(bg) == 0 )
return 0;
bg->target_data[bg->target_cnt] |= (val << bg->target_bit_pos);
if ( bg->target_bit_pos+cnt >= 8 )
{
bg->target_cnt++;
val >>= 8-bg->target_bit_pos;
bg->target_data[bg->target_cnt] = val;
bg->target_bit_pos+=cnt;
bg->target_bit_pos-=8;
}
else
{
bg->target_bit_pos+=cnt;
}
return 1;
}
int bg_FlushTargetBits(bg_t *bg)
{
while( bg->target_bit_pos != 0 )
if ( bg_AddTargetBits(bg, 1, 0) == 0 )
return 0;
return 1;
}
int bg_SetBitmapSizeInBytes(bg_t *bg, size_t bytes)
{
if ( bg->bitmap_data != NULL )
free(bg->bitmap_data);
bg->bitmap_data = (uint8_t *)malloc(bytes);
if ( bg->bitmap_data == NULL )
return 0;
memset(bg->bitmap_data, 0, bytes);
return 1;
}
int bg_SetBitmapSize(bg_t *bg, int w, int h)
{
return bg_SetBitmapSizeInBytes(bg, w*h);
}
void bg_SetBitmapPixel(bg_t *bg, int x, int y, int value)
{
static long last_encoding = 0xffffffff;
static long biggest_x = -1;
if ( x >= bg->bitmap_width || y >= bg->bitmap_height )
{
if ( last_encoding != bg->encoding )
{
biggest_x = x;
printf("Glyph size problem: ");
printf("encoding=%ld/0x%lx, ", bg->encoding, bg->encoding);
printf("width=%d, height=%d, ", bg->bitmap_width, bg->bitmap_height);
printf("requested position x=%d, y=%d (use BBX %d ...?)\n", x, y, x+1);
last_encoding = bg->encoding;
}
else if ( biggest_x < x )
{
biggest_x = x;
printf("Glyph size problem: ");
printf("encoding=%ld/0x%lx, ", bg->encoding, bg->encoding);
printf("width=%d, height=%d, ", bg->bitmap_width, bg->bitmap_height);
printf("requested position x=%d, y=%d (use BBX %d ...?)\n", x, y, x+1);
}
}
assert( x < ((bg->bitmap_width+7)/8)*8 );
assert( y < bg->bitmap_height );
assert( x >= 0 );
assert( y >= 0 );
bg->bitmap_data[y*bg->bitmap_width + x] = value;
}
int bg_GetBitmapPixel(bg_t *bg, int x, int y)
{
if ( x >= bg->bitmap_width )
return 0;
if ( y >= bg->bitmap_height )
return 0;
if ( x < 0 )
return 0;
if ( y < 0 )
return 0;
return bg->bitmap_data[y*bg->bitmap_width + x];
}
/*
Return a pixel with the provided bbx
Coordinates are within the bbx.
*/
int bg_GetBBXPixel(bg_t *bg, int x, int y)
{
/* glyph rectangle */
long glyph_x0, glyph_x1, glyph_y0, glyph_y1;
/* local bitmap coordinates */
long bitmap_x, bitmap_y;
/* perform x offset alignment (used in BDF_BBX_MODE_HEIGHT mode only)*/
x += bg->shift_x;
/* calculate the rectangle for the glyph */
glyph_x0 = bg->bbx.x;
glyph_y0 = bg->bbx.y;
glyph_x1 = bg->bbx.x+bg->bbx.w;
glyph_y1 = bg->bbx.y+bg->bbx.h;
if ( x < glyph_x0 )
return 0;
if ( x >= glyph_x1 )
return 0;
if ( y < glyph_y0 )
return 0;
if ( y >= glyph_y1 )
return 0;
bitmap_x = x - glyph_x0;
bitmap_y = bg->bbx.h - 1 - ( y - glyph_y0);
return bg_GetBitmapPixel( bg, bitmap_x, bitmap_y );
}
void bg_ShowBitmap(bg_t *bg, bbx_t *bbx)
{
int x, y;
if ( bbx == NULL )
bbx = &(bg->bbx);
printf("Encoding %ld, mapped to %ld, w=%ld, h=%ld, x=%ld, y=%ld\n", bg->encoding, bg->map_to, bg->bbx.w, bg->bbx.h, bg->bbx.x, bg->bbx.y);
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
{
printf("%03d ", y);
for( x = bbx->x; x < bbx->x + bbx->w; x++)
{
if ( bg_GetBBXPixel(bg, x, y) == 0 )
{
printf(" .");
}
else
{
printf(" #");
}
}
printf("\n");
}
}
int bg_IsColZero(bg_t *bg, int x)
{
int y;
for( y = 0; y < bg->bitmap_height; y++ )
{
if ( bg_GetBitmapPixel(bg, x, y) != 0 )
return 0;
}
return 1;
}
int bg_IsRowZero(bg_t *bg, int y)
{
int x;
for( x = 0; x < bg->bitmap_width; x++ )
{
if ( bg_GetBitmapPixel(bg, x, y) != 0 )
return 0;
}
return 1;
}
void bg_DeleteFirstCol(bg_t *bg)
{
int x,y;
for( y = 0; y < bg->bitmap_height; y++ )
for( x = 0; x+1 < bg->bitmap_width; x++ )
{
bg_SetBitmapPixel(bg, x, y, bg_GetBitmapPixel(bg, x+1, y));
}
}
void bg_DeleteFirstRow(bg_t *bg)
{
int x,y;
for( y = 0; y+1 < bg->bitmap_height; y++ )
for( x = 0; x < bg->bitmap_width; x++ )
{
bg_SetBitmapPixel(bg, x, y, bg_GetBitmapPixel(bg, x, y+1));
}
}
void bg_ReduceGlyph(bg_t *bg)
{
//long w;
/* assign bitmap dimension (should be done already) */
//bg->bbx.w = bg->bitmap_width;
//bg->bbx.h = bg->bitmap_height;
/* do not assign x,y because they are already set correctly */
//w = bg->bbx.w;
while( bg->bbx.w > 0 )
{
if ( bg_IsColZero(bg, bg->bbx.w-1) == 0 )
break;
bg->bbx.w--;
}
while( bg->bbx.h > 0 )
{
if ( bg_IsRowZero(bg, bg->bbx.h-1) == 0 )
break;
bg->bbx.y++;
bg->bbx.h--;
}
while( bg->bbx.w > 0)
{
if ( bg_IsColZero(bg, 0) == 0 )
break;
bg_DeleteFirstCol(bg);
bg->bbx.x++;
bg->bbx.w--;
}
while( bg->bbx.h > 0 )
{
if ( bg_IsRowZero(bg, 0) == 0 )
break;
bg_DeleteFirstRow(bg);
bg->bbx.h--;
}
/*
problem: pixel width calculation failes, because a blank at
the end is not calculated correctly.
analysis:
- bbx.w is reduced to 0
- original bbx.w is sometimes identical to dwidth_x (6x10.bdf)
or is 1 (helvR10.bdf)
-the bdf file for helvR10.bdf does not contain any other information then
delta x, so this should be used as bbx.w
solution:
Nothing done on the converter side, but handle this as a special case in the
pixel width calculation
*/
//if ( bg->bbx.w == 0 && bg->bbx.h == 0 )
//{
//printf("enc=%ld, new bbx,w=%ld, original width=%ld, dx=%ld\n", bg->encoding, bg->bbx.w, w, bg->dwidth_x);
//printf("enc=%ld, new bbx.w=%ld, original width=%ld, dx=%ld\n", bg->encoding, bg->bbx.w, w, bg->dwidth_x);
//}
}
/*
maximize the provided bbx so that the bbxof the glyph completly is covered by the max bbx
*/
int bg_Max(bg_t *bg, bbx_t *max)
{
int r = 0;
/* glyph rectangle */
long glyph_x0, glyph_x1, glyph_y0, glyph_y1;
/* max rectangle */
long max_x0, max_x1, max_y0, max_y1;
// printf("Encoding %ld, mapped to %ld, w=%ld, h=%ld, x=%ld, y=%ld\n", bg->encoding, bg->map_to, bg->bbx.w, bg->bbx.h, bg->bbx.x, bg->bbx.y);
/* calculate the rectangle for the glyph */
glyph_x0 = bg->bbx.x;
glyph_y0 = bg->bbx.y;
glyph_x1 = bg->bbx.x+bg->bbx.w;
glyph_y1 = bg->bbx.y+bg->bbx.h;
/* calculate the rectangle for the max bbx */
max_x0 = max->x;
max_y0 = max->y;
max_x1 = max->x+max->w;
max_y1 = max->y+max->h;
/* maximize the max rectrangle so that the glyph rectangle full fits inside */
if ( max_x0 > glyph_x0 )
{
max_x0 = glyph_x0;
r = 3;
}
/* 28 Mar dwidth_x and x0???? */
if ( max_x0 > bg->dwidth_x ) /* include dwidth_x into the box */
{
max_x0 = bg->dwidth_x; /* is this correct??? */
r = 3;
}
if ( max_x1 < glyph_x1 )
{
r = 1;
max_x1 = glyph_x1;
}
if ( max_y0 > glyph_y0 )
{
r = 4;
max_y0 = glyph_y0;
}
if ( max_y1 < glyph_y1 )
{
r = 2;
max_y1 = glyph_y1;
}
/* reconstruct the max bbx from the max rectangle */
max->x = max_x0;
max->y = max_y0;
max->w = max_x1 - max->x;
max->h = max_y1 - max->y;
return r;
}

85
font/bdfconv/bdf_glyph.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef _BDF_GLYPH_H
#define _BDF_GLYPH_H
#include <stdint.h>
#include <stddef.h>
/* forward def */
typedef struct _bdf_font_struct bf_t;
struct _bbx_struct
{
long w;
long h;
long x;
long y;
};
typedef struct _bbx_struct bbx_t;
struct _bdf_glyph_struct
{
bf_t *bf;
long encoding;
long map_to;
long dwidth_x;
long dwidth_y;
bbx_t bbx; /* x,y are delta x,y from glyph, w,h start wth bitmap dimension, but may be reduced */
long shift_x; /* extra shift for BDF_BBX_MODE_HEIGHT alignment */
int is_excluded_from_kerning;
uint8_t *bitmap_data;
int bitmap_width; /* the physical width within "bitmap_data", will be larger than or equal to bbx.w */
int bitmap_height;
//int actual_bitmap_width; /* identical to bbx.w, maybe replace actual_bitmap_width by bbx.w */
//int actual_bitmap_height; /* identical to bbx.h, maybe replace actual_bitmap_height by bbx.h */
uint8_t *target_data; /* if this is not NULL, then there is a valid glyph */
int target_max; /* 32 bit value */
int target_cnt; /* 32 bit value */
int target_bit_pos;
/* rle data */
unsigned rle_bits_per_0;
unsigned rle_bits_per_1;
int rle_is_first;
unsigned rle_bitcnt;
unsigned rle_last_0;
unsigned rle_last_1;
long width_deviation; /* filled by bf_copy_bbx_and_update_shift for statistics */
};
typedef struct _bdf_glyph_struct bg_t;
bg_t *bg_Open(void);
void bg_Close(bg_t *bg);
int bg_AddTargetData(bg_t *bg, uint8_t data);
void bg_ClearTargetData(bg_t *bg);
int bg_AddTargetBits(bg_t *bg, unsigned cnt, unsigned val);
int bg_FlushTargetBits(bg_t *bg);
int bg_SetBitmapSizeInBytes(bg_t *bg, size_t bytes);
int bg_SetBitmapSize(bg_t *bg, int w, int h);
void bg_SetBitmapPixel(bg_t *bg, int x, int y, int value);
int bg_GetBitmapPixel(bg_t *bg, int x, int y);
int bg_GetBBXPixel(bg_t *bg, int x, int y);
void bg_ShowBitmap(bg_t *bg, bbx_t *bbx);
void bg_ReduceGlyph(bg_t *bg);
int bg_Max(bg_t *bg, bbx_t *max); /* returns idx which describes glyph expansion */
/* bdf_rle.c */
int bg_rle_compress(bg_t *bg, bbx_t *bbx, unsigned rle_bits_per_0, unsigned rle_bits_per_1, int is_output);
#endif

217
font/bdfconv/bdf_kern.c Normal file
View File

@ -0,0 +1,217 @@
/*
bdf_kern.c
*/
#include "bdf_font.h"
#include <assert.h>
#define BDF_KERNING_MAX (1024*60)
/* the following tables contain the first encodings if they do contain any kernings */
uint16_t bdf_first_table_cnt;
uint16_t bdf_first_encoding_table[BDF_KERNING_MAX];
uint16_t bdf_index_to_second_table[BDF_KERNING_MAX];
/* the index from bdf_index_to_second_table can be used to jump into the following table */
uint16_t bdf_second_table_cnt;
uint16_t bdf_second_encoding_table[BDF_KERNING_MAX];
uint8_t bdf_kerning_values[BDF_KERNING_MAX];
/*
struct u8g2_kerning
{
uint16_t first_table_cnt;
uint16_t second_table_cnt;
uint16_t *first_encoding_table;
uint16_t *index_to_second_table;
uin16_t *second_encoding_table;
uint8_t *kerning_values;
}
*/
static void bdf_write_uint16_array(FILE *fp, const char *pre, const char *post, uint16_t cnt, const uint16_t *a)
{
uint16_t i;
fprintf(fp, "static const uint16_t %s_%s[%u] = {\n ", pre, post, cnt);
for( i = 0; i < cnt; i++ )
{
fprintf(fp, "%u", a[i]);
if ( i+1 < cnt )
{
fprintf(fp, ", ");
if ( i % 16 == 0 && i > 0 )
{
fprintf(fp, "\n ");
}
}
}
fprintf(fp, "};\n");
}
static void bdf_write_uint8_array(FILE *fp, const char *pre, const char *post, uint16_t cnt, const uint8_t *a)
{
uint16_t i;
fprintf(fp, "static const uint8_t %s_%s[%u] = {\n ", pre, post, cnt);
for( i = 0; i < cnt; i++ )
{
fprintf(fp, "%u", a[i]);
if ( i+1 < cnt )
{
fprintf(fp, ", ");
if ( i % 16 == 0 && i > 0 )
{
fprintf(fp, "\n ");
}
}
}
fprintf(fp, "};\n");
}
void bdf_write_kerning_file(const char *kernfile, const char *name)
{
FILE *fp;
fp = fopen(kernfile, "w");
fprintf(fp, "/* %s, Size: %u Bytes */\n", name, bdf_first_table_cnt*4 + bdf_second_table_cnt*3 + 4 + 8); // size calculation for 16 bit controller
bdf_write_uint16_array(fp, name, "first_encoding_table", bdf_first_table_cnt, bdf_first_encoding_table);
bdf_write_uint16_array(fp, name, "index_to_second_table", bdf_first_table_cnt, bdf_index_to_second_table);
bdf_write_uint16_array(fp, name, "second_encoding_table", bdf_second_table_cnt, bdf_second_encoding_table);
bdf_write_uint8_array(fp, name, "kerning_values", bdf_second_table_cnt, bdf_kerning_values);
fprintf(fp, "u8g2_kerning_t %s_k = {\n", name);
fprintf(fp, " %u, %u,\n", bdf_first_table_cnt, bdf_second_table_cnt);
fprintf(fp, " %s_%s,\n", name, "first_encoding_table");
fprintf(fp, " %s_%s,\n", name, "index_to_second_table");
fprintf(fp, " %s_%s,\n", name, "second_encoding_table");
fprintf(fp, " %s_%s};\n\n", name, "kerning_values");
fclose(fp);
}
/*
assumes
tga_set_font(font);
and
tga_init((tga_get_char_width()+16)*3, ((tga_get_char_height()+8)*2));
is called before
*/
static int bdf_is_glyph_overlap(uint8_t *font, uint16_t e1, uint16_t e2, uint8_t kerning_test, int is_save)
{
unsigned int x, y;
tga_clear();
x = 8;
y = tga_get_char_height();
x += tga_draw_glyph(x, y, e1, 0);
x -= kerning_test;
tga_clear_pixel_intersection();
x += tga_draw_glyph(x, y, e2, 0);
if ( is_save )
{
//char buf[64];
//sprintf(buf, "glyph_intersection_%u_%u_%u.tga", e1, e2, kerning_test);
//tga_save(buf);
}
return tga_is_pixel_intersection();
}
unsigned bdf_calculate_kerning(uint8_t *font, uint16_t e1, uint16_t e2, uint8_t min_distance_in_per_cent_of_char_width)
{
uint8_t upper_bound;
uint8_t kerning;
uint8_t min_distance_in_pixel;
tga_set_font(font);
tga_init((tga_get_char_width()+16)*3, ((tga_get_char_height()+8)*2));
min_distance_in_pixel = ((unsigned)tga_get_char_width()*(unsigned)min_distance_in_per_cent_of_char_width) / 100;
upper_bound = tga_get_char_width();
for( kerning = 0; kerning < upper_bound; kerning++ )
{
if ( bdf_is_glyph_overlap(font, e1, e2, kerning, 0) != 0 )
break;
}
if ( kerning >= upper_bound )
kerning = 0; /* maybe "." compared against "-" */
if ( kerning < min_distance_in_pixel )
kerning = 0;
else
kerning -= min_distance_in_pixel;
if ( kerning != 0 )
{
bdf_is_glyph_overlap(font, e1, e2, kerning, 1);
//printf("bdf_calculate_kerning %u %u ", e1, e2);
//printf("result: %d\n", kerning);
}
return kerning;
}
void bdf_calculate_all_kerning(bf_t *bf, const char *filename, const char *fontname, uint8_t min_distance_in_per_cent_of_char_width)
{
int first, second;
bg_t *bg_first;
bg_t *bg_second;
uint8_t kerning;
int is_first_encoding_added;
bdf_first_table_cnt = 0;
bdf_second_table_cnt = 0;
for( first= 0; first < bf->glyph_cnt; first++ )
{
is_first_encoding_added = 0;
bg_first = bf->glyph_list[first];
if ( bg_first->target_data != NULL && bg_first->is_excluded_from_kerning == 0 )
{
for( second= 0; second < bf->glyph_cnt; second++ )
{
bg_second = bf->glyph_list[second];
if ( bg_second->target_data != NULL && bg_second->is_excluded_from_kerning == 0 )
{
kerning = bdf_calculate_kerning(bf->target_data, bg_first->encoding, bg_second->encoding, min_distance_in_per_cent_of_char_width);
if ( kerning > 1 )
{
if ( is_first_encoding_added == 0 )
{
bdf_first_encoding_table[bdf_first_table_cnt] = bg_first->encoding;
bdf_index_to_second_table[bdf_first_table_cnt] = bdf_second_table_cnt;
bdf_first_table_cnt++;
if (bdf_first_table_cnt > BDF_KERNING_MAX)
{
fprintf(stderr, "Kerning calculation aborted: bdf_first_table_cnt > BDF_KERNING_MAX\n");
return;
}
is_first_encoding_added = 1;
}
bdf_second_encoding_table[bdf_second_table_cnt] = bg_second->encoding;
bdf_kerning_values[bdf_second_table_cnt] = kerning;
bdf_second_table_cnt++;
if (bdf_second_table_cnt > BDF_KERNING_MAX)
{
fprintf(stderr, "Kerning calculation aborted: bdf_second_table_cnt > BDF_KERNING_MAX\n");
return;
}
}
}
}
}
}
/* add a final entry for more easier calculation in u8g2 */
bdf_first_encoding_table[bdf_first_table_cnt] = 0x0ffff;
bdf_index_to_second_table[bdf_first_table_cnt] = bdf_second_table_cnt;
bdf_first_table_cnt++;
bdf_write_kerning_file(filename, fontname);
}

323
font/bdfconv/bdf_map.c Normal file
View File

@ -0,0 +1,323 @@
/*
bdf_map.c
select and map glyphs
Syntax:
maplist := <mapcmd> { "," <mapcmd> }
mapcmd := <default> | <maprange> | <exclude>
default := "*"
maprange := <range> [ ">" <num> ]
exclude := "~" <range>
kern_exclude := "x" <range>
range := <num> [ "-" <num> ]
num := <hexnum> | <decnum>
hexnum := "$" <hexdigit> { <hexdigit> }
decnum := <decdigit> { <decdigit> }
decdigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
hexdigit := "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | <decdigit>
{ }: zero, one ore more
[ ]: zero or once
|: alternative
*/
#include "bdf_font.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
static long range_from;
static long range_to;
static int is_exclude;
static int is_kern_exclude;
static long map_to;
static void skip_space(const char **s)
{
for(;;)
{
if ( **s == '\0' )
break;
if ( **s > ' ' )
break;
(*s)++;
}
}
static long get_dec(const char **s)
{
long v = 0;
for(;;)
{
if ( (**s) >= '0' && (**s) <= '9' )
{
v*=10;
v+= (**s)-'0';
(*s)++;
}
else
{
break;
}
}
skip_space(s);
return v;
}
static long get_hex(const char **s)
{
long v = 0;
for(;;)
{
if ( (**s) >= '0' && (**s) <= '9' )
{
v*=16;
v+= (**s)-'0';
(*s)++;
}
else if ( (**s) >= 'a' && (**s) <= 'f' )
{
v*=16;
v+= (**s)-'a'+10;
(*s)++;
}
else if ( (**s) >= 'A' && (**s) <= 'F' )
{
v*=16;
v+= (**s)-'A'+10;
(*s)++;
}
else
{
break;
}
}
skip_space(s);
return v;
}
static long get_num(const char **s)
{
if ( (**s) != '$' )
return get_dec(s);
(*s)++;
skip_space(s);
return get_hex(s);
}
static long get_mul(const char **s)
{
long v;
v = get_num(s);
while ( (**s) == '*' )
{
(*s)++;
skip_space(s);
v *= get_num(s);
}
return v;
}
static long get_add(const char **s)
{
long v;
v = get_mul(s);
while ( (**s) == '+' )
{
(*s)++;
skip_space(s);
v += get_mul(s);
}
return v;
}
static long get_addsub(const char **s)
{
long v;
int op;
v = get_mul(s);
while ( (**s) == '+' || (**s) == '-' )
{
op = **s;
(*s)++;
skip_space(s);
if ( op == '+' )
v += get_mul(s);
else
v -= get_mul(s);
}
return v;
}
static void get_range(const char **s)
{
range_from = get_add(s);
if ( **s != '-' )
{
range_to = range_from;
}
else
{
(*s)++;
skip_space(s);
range_to = get_add(s);
}
}
static void map_cmd(const char **s)
{
if ( **s == '*' )
{
range_from = 32;
range_to = 255;
map_to = 32;
is_exclude = 0;
is_kern_exclude = 0;
(*s)++;
skip_space(s);
}
else if ( **s == '~' )
{
is_exclude = 1;
map_to = 0; /*will be ignored */
(*s)++;
skip_space(s);
get_range(s);
}
else if ( **s == 'x' )
{
is_kern_exclude = 1;
map_to = 0; /*will be ignored */
(*s)++;
skip_space(s);
get_range(s);
}
else
{
is_exclude = 0;
get_range(s);
map_to = range_from;
if ( **s == '>')
{
(*s)++;
skip_space(s);
map_to = get_addsub(s);
}
}
}
void bf_map_cmd(bf_t *bf, const char **s)
{
int i;
bg_t *bg;
static int is_log_disabled_for_single_glyphs = 0;
if ( **s == ',' || **s == '\0' )
return;
map_cmd(s);
if ( range_from != range_to )
{
bf_Log(bf, "Map: exclude=%d from=%ld/$%lx to=%ld/$%lx map=%ld/$%lx", is_exclude, range_from, range_from, range_to, range_to, map_to, map_to);
}
else if ( is_log_disabled_for_single_glyphs == 0 )
{
bf_Log(bf, "Map: exclude=%d from=%ld/$%lx to=%ld/$%lx map=%ld/$%lx (further single glyph logs disabled)", is_exclude, range_from, range_from, range_to, range_to, map_to, map_to);
is_log_disabled_for_single_glyphs = 1;
}
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->encoding >= range_from && bg->encoding <= range_to )
{
if ( is_kern_exclude != 0 )
{
bg->is_excluded_from_kerning = 1;
}
else
{
if ( is_exclude != 0 )
{
bg->map_to = -1;
}
else
{
bg->map_to = bg->encoding - range_from + map_to;
}
}
}
}
}
void bf_map_list(bf_t *bf, const char **s)
{
int i;
bg_t *bg;
/* exclude everything first */
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
bg->map_to = -1;
}
/* process the mapping list list */
skip_space(s);
for(;;)
{
bf_map_cmd(bf, s);
if ( **s != ',' )
break;
(*s)++;
skip_space(s);
}
}
void bf_Map(bf_t *bf, const char *map_cmd_list)
{
if ( strlen(map_cmd_list) < 1024 )
bf_Log(bf, "Map: map_cmd_list='%s'", map_cmd_list);
bf_map_list(bf, &map_cmd_list);
}
int bf_MapFile(bf_t *bf, const char *map_file_name)
{
struct stat buf;
char *s;
FILE *fp;
if ( map_file_name == NULL )
return 1;
if ( map_file_name[0] == '\0' )
return 1;
if ( stat(map_file_name, &buf) != 0 )
return 0;
fp = fopen(map_file_name, "r");
if ( fp == NULL )
return 0;
s = malloc(buf.st_size+1);
if ( s == NULL )
return 0;
fread(s, buf.st_size, 1, fp);
s[buf.st_size] = '\0';
fclose(fp);
bf_Map(bf, s);
free(s);
return 1;
}

478
font/bdfconv/bdf_parser.c Normal file
View File

@ -0,0 +1,478 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "bdf_font.h"
static int bf_curr(bf_t * bf)
{
if ( bf->line_pos >= BDF_LINE_LEN )
return '\0';
return bf->line_buf[bf->line_pos];
}
static void bf_next(bf_t *bf)
{
if ( bf_curr(bf) == '\0' )
return;
if ( bf->line_pos >= BDF_LINE_LEN )
return;
bf->line_pos++;
}
static void bf_skipspace(bf_t *bf)
{
int c;
for(;;)
{
c = bf_curr(bf);
if ( c == '\0' )
return;
if ( c > ' ' )
return;
bf_next(bf);
}
}
static const char *bf_get_identifier(bf_t *bf)
{
static char buf[BDF_LINE_LEN];
int c;
int i = 0;
buf[0] = '\0';
for(;;)
{
c = bf_curr(bf);
if ( c <= ' ' )
break;
if ( i >= BDF_LINE_LEN-2 )
break;
buf[i++] = c;
buf[i] = '\0';
bf_next(bf);
}
bf_skipspace(bf);
return buf;
}
static const char *bf_get_string(bf_t *bf)
{
static char buf[BDF_LINE_LEN];
int i = 0;
int c;
buf[0] = '\0';
if ( bf_curr(bf) != '\"' )
return bf_get_identifier(bf);
bf_next(bf);
for(;;)
{
c = bf_curr(bf);
if ( c == '\0' )
break;
if ( c == '\"' )
break;
if ( i >= BDF_LINE_LEN-2 )
break;
if ( c != '\r' && c != '\n' ) /* skip \r and \n, see https://github.com/olikraus/u8g2/pull/1361, https://github.com/olikraus/u8g2/issues/1379 */
{
buf[i++] = c;
buf[i] = '\0';
}
bf_next(bf);
}
if ( bf_curr(bf) == '\"' )
bf_next(bf);
bf_skipspace(bf);
return buf;
}
static const char *bf_get_eol_string(bf_t *bf)
{
static char buf[BDF_LINE_LEN];
int i = 0;
int c;
buf[0] = '\0';
if ( bf_curr(bf) == '\"' )
return bf_get_string(bf);
//bf_next(bf);
for(;;)
{
c = bf_curr(bf);
if ( c == '\0' )
break;
if ( c == '\n' || c == '\r' )
break;
if ( i >= BDF_LINE_LEN-2 )
break;
buf[i++] = c;
buf[i] = '\0';
bf_next(bf);
}
bf_skipspace(bf);
return buf;
}
static long bf_get_long(bf_t *bf)
{
int c;
long v = 0;
long sign = 1;
if ( bf_curr(bf) == '-' )
{
sign = -1;
bf_next(bf);
bf_skipspace(bf);
}
for(;;)
{
c = bf_curr(bf);
if ( c < '0' )
break;
if ( c > '9' )
break;
v *= 10L;
v += (long)(c-'0');
bf_next(bf);
}
bf_skipspace(bf);
return v*sign;
}
/*
static long bf_get_mul(bf_t *bf)
{
long v;
v = bf_get_long(bf);
if ( bf_curr(bf) == '*' )
{
bf_next(bf);
bf_skipspace(bf);
v *= bf_get_long(bf);
}
return v;
}
static long bf_get_add(bf_t *bf)
{
long v;
v = bf_get_mul(bf);
if ( bf_curr(bf) == '+' )
{
bf_next(bf);
bf_skipspace(bf);
v += bf_get_mul(bf);
}
return v;
}
*/
static int bf_add_glyph_to_list(bf_t *bf)
{
bg_t *bg;
bf->glyph_pos = bf_AddGlyph(bf);
if ( bf->glyph_pos < 0 )
{
bf_Error(bf, "Can not add glyph (memory error?)");
return 0;
}
bg = bf->glyph_list[bf->glyph_pos];
/* copy the values from the parser to the glyph record */
bg->encoding = bf->encoding;
bg->dwidth_x = bf->dwidth_x;
bg->dwidth_y = bf->dwidth_y;
bg->bbx.w = bf->bbx_w;
bg->bbx.h = bf->bbx_h;
bg->bbx.x = bf->bbx_x;
bg->bbx.y = bf->bbx_y;
if ( bg_SetBitmapSize(bg, bf->bbx_w, bf->bbx_h) == 0 )
{
bf_Error(bf, "Can not create bitmap (memory error?)");
return 0;
}
bg->bitmap_width = bf->bbx_w;
bg->bitmap_height = bf->bbx_h;
// bg->actual_bitmap_width = bf->bbx_w;
// bg->actual_bitmap_height = bf->bbx_h;
//bf_Log(bf, "BDF File: Create glyph glyph_pos=%d bbx_w=%d bbx_h=%d bbx_x=%d bbx_y=%d", bf->glyph_pos, bf->bbx_w, bf->bbx_h, bf->bbx_x, bf->bbx_y);
return 1;
}
static void bf_set_pixel_by_halfbyte(bf_t *bf, int halfbyte)
{
int i;
bg_t *bg;
assert( bf->glyph_list != NULL );
bg = bf->glyph_list[bf->glyph_pos];
for ( i = 0; i < 4; i++ )
{
if ( (halfbyte & 8) != 0 )
{
bg_SetBitmapPixel(bg, bf->bitmap_x, bf->bitmap_y, 1);
}
halfbyte<<=1;
bf->bitmap_x++;
}
}
static void bf_set_pixel_by_hex_char(bf_t *bf, int hex)
{
if ( hex >= '0' && hex <= '9' )
return bf_set_pixel_by_halfbyte(bf, hex-'0');
if ( hex >= 'a' && hex <= 'f' )
return bf_set_pixel_by_halfbyte(bf, hex-'a'+10);
if ( hex >= 'A' && hex <= 'F' )
return bf_set_pixel_by_halfbyte(bf, hex-'A'+10);
return bf_set_pixel_by_halfbyte(bf, 0);
}
static int bf_parse_line(bf_t *bf)
{
static char cmd[BDF_LINE_LEN];
bf->line_pos = 0;
bf_skipspace(bf);
if ( bf->is_bitmap_parsing == 0 )
{
/* regular command */
bf->bitmap_y = 0;
strcpy(cmd, bf_get_string(bf));
if ( strcmp(cmd, "" ) == 0 )
{
return 1;
}
else if ( strcmp(cmd, "STARTFONT" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "FONT" ) == 0 ) /* args: s */
{
if ( bf->str_font != NULL )
free(bf->str_font);
bf->str_font = strdup(bf_get_eol_string(bf));
}
else if ( strcmp(cmd, "SIZE" ) == 0 ) /* args: lll */
{
}
else if ( strcmp(cmd, "FONTBOUNDINGBOX" ) == 0 ) /* args: llll */
{
}
else if ( strcmp(cmd, "STARTPROPERTIES" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "FONTNAME_REGISTRY" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "FOUNDRY" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "FAMILY_NAME" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "WEIGHT_NAME" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "SLANT" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "SETWIDTH_NAME" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "ADD_STYLE_NAME" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "PIXEL_SIZE" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "POINT_SIZE" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "RESOLUTION_X" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "RESOLUTION_Y" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "SPACING" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "AVERAGE_WIDTH" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "CHARSET_REGISTRY" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "CHARSET_ENCODING" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "DESTINATION" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "COPYRIGHT" ) == 0 ) /* args: s */
{
if ( bf->str_copyright != NULL )
free(bf->str_copyright);
bf->str_copyright = strdup(bf_get_eol_string(bf));
}
else if ( strcmp(cmd, "_XMBDFED_INFO" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "CAP_HEIGHT" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "X_HEIGHT" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "WEIGHT" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "QUAD_WIDTH" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "DEFAULT_CHAR" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "FONT_DESCENT" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "FONT_ASCENT" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "ENDPROPERTIES" ) == 0 ) /* args: - */
{
}
else if ( strcmp(cmd, "CHARS" ) == 0 ) /* args: l */
{
}
else if ( strcmp(cmd, "STARTCHAR" ) == 0 ) /* args: s */
{
}
else if ( strcmp(cmd, "ENCODING" ) == 0 ) /* args: l */
{
bf->encoding = bf_get_long(bf);
//bf_Log(bf, "BDF File: ENCODING %d", bf->encoding);
}
else if ( strcmp(cmd, "SWIDTH" ) == 0 ) /* args: ll */
{
}
else if ( strcmp(cmd, "DWIDTH" ) == 0 ) /* args: ll */
{
bf->dwidth_x = bf_get_long(bf);
bf->dwidth_y = bf_get_long(bf);
}
else if ( strcmp(cmd, "BBX" ) == 0 ) /* args: llll */
{
bf->bbx_w = bf_get_long(bf);
bf->bbx_h = bf_get_long(bf);
bf->bbx_x = bf_get_long(bf);
bf->bbx_y = bf_get_long(bf);
}
else if ( strcmp(cmd, "BITMAP" ) == 0 ) /* args: - */
{
if ( bf_add_glyph_to_list(bf) == 0 )
return 0;
bf->is_bitmap_parsing = 1;
}
else if ( strcmp(cmd, "ENDCHAR" ) == 0 ) /* args: - */
{
bf_Error(bf, "Unexpected ENDCHAR found");
return 0;
}
}
else
{
/* a line of the glyph bitmap */
int c;
strcpy(cmd, bf_get_string(bf));
if ( cmd[0] != '\0' )
{
if ( strcmp(cmd, "ENDCHAR" ) == 0 ) /* args: - */
{
bf->is_bitmap_parsing = 0;
/* bg_ShowBitmap(bf->glyph_list[bf->glyph_pos]); */
}
else
{
bf->line_pos = 0;
bf_skipspace(bf);
bf->bitmap_x = 0;
for(;;)
{
c = bf_curr(bf);
if ( c < '0' )
break;
bf_set_pixel_by_hex_char(bf, c);
bf_next(bf);
}
bf->bitmap_y++;
}
}
}
return 1;
}
static int bf_parse_file(bf_t *bf)
{
long line_cnt = 0;
bf->is_bitmap_parsing = 0;
for(;;)
{
line_cnt++;
if ( fgets(bf->line_buf, BDF_LINE_LEN, bf->fp) == NULL )
break;
if ( bf_parse_line(bf) == 0 )
{
bf_Error(bf, "perse error in line %ld", line_cnt);
return 0;
}
}
return 1;
}
int bf_ParseFile(bf_t *bf, const char *name)
{
int r;
bf->fp = fopen(name, "r");
if ( bf->fp == NULL )
{
bf_Error(bf, "Can not open bdf file '%s'", name);
return 0;
}
r = bf_parse_file(bf);
fclose(bf->fp);
bf_Log(bf, "Parse File %s: %d glyph(s) found", name, bf->glyph_cnt);
return r;
}

932
font/bdfconv/bdf_rle.c Normal file
View File

@ -0,0 +1,932 @@
/*
bdf_rle.c
run length glyph encoding
size comparison with old and new font format
4x6 1500 1469
4x6r 734 726
6x10 1866 2009
6x10r 889 971
7x13B 2172 2253
7x13Br 1041 1017
9x15 2959 2649
9x15r 1427 1242
10x20 3453 3053
10x20r 1667 1417 85%
courB12 3959 3312
courB12r 1857 1538
courB24 10502 6661
courB24r 4775 3015 63%
helvB24 10931 6904 63%
helvB24r 4992 3166 63%
logisoso50r 14375 5248 36%
*/
/* font information */
/*
glyph_cnt = *font++;
bits_per_0 = *font++;
bits_per_1 = *font++;
bits_per_char_width = *font++;
bits_per_char_height = *font++;
bits_per_char_x = *font++;
bits_per_char_y = *font++;
bits_per_delta_x = *font++;
*/
/* apply glyph information */
/*
~ encoding unsigned, 1 or 2 byte (high byte first in two byte version)
~ total size unsigned, 1 byte
~ BBX width unsigned 5
~ BBX height unsigned 5
~ BBX xoffset signed 2
~ BBX yoffset signed 5
~ DWIDTH unsigned 3
*/
#define BDF_RLE_FONT_GLYPH_START 23
/* max glyphs count is around 7500, 7500/100 = 75 */
/* changed 100 to 101 due to off by one error in the code and in order to keep the current binary data identical https://github.com/olikraus/u8g2/issues/1521 */
#define UNICODE_GLYPHS_PER_LOOKUP_TABLE_ENTRY 101
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "bdf_font.h"
#ifdef OLD_CODE
#define SCREEN_W 140
#define SCREEN_H 140
uint8_t screen_buf[SCREEN_H][SCREEN_W];
unsigned screen_max_y;
void screen_init(void)
{
unsigned x, y;
screen_max_y = 0;
for( y = 0; y < SCREEN_H; y++ )
{
for( x = 0; x < SCREEN_W; x++ )
{
screen_buf[y][x] = '.';
}
}
}
void screen_set_pixel(unsigned x, unsigned y, uint8_t c)
{
if ( screen_max_y < y)
screen_max_y = y;
screen_buf[y][x] = c;
}
void screen_show(void)
{
unsigned x, y;
printf("\n");
for( y = 0; y <= screen_max_y; y++ )
{
for( x = 0; x < SCREEN_W; x++ )
{
printf("%c", screen_buf[y][x]);
}
printf("\n");
}
}
/*===================================================*/
/* font decode */
struct fd_struct
{
unsigned x; /* local coordinates, (0,0) is upper left */
unsigned y;
unsigned glyph_width;
unsigned glyph_height;
const uint8_t *decode_ptr; /* pointer to the compressed data */
unsigned decode_bit_pos; /* bitpos inside a byte of the compressed data */
uint8_t bbx_x_max_bit_size;
uint8_t bbx_y_max_bit_size;
uint8_t bbx_w_max_bit_size;
uint8_t bbx_h_max_bit_size;
uint8_t dx_max_bit_size;
};
typedef struct fd_struct fd_t;
/* increment x and consider line wrap (inc y)*/
static void fd_inc(fd_t *f)
{
unsigned x = f->x;
x++;
if ( x == f->glyph_width )
{
x = 0;
f->y++;
}
f->x = x;
}
static unsigned fd_get_unsigned_bits(fd_t *f, unsigned cnt)
{
unsigned val;
unsigned bit_pos = f->decode_bit_pos;
val = *(f->decode_ptr);
val >>= bit_pos;
if ( bit_pos + cnt >= 8 )
{
f->decode_ptr++;
val |= *(f->decode_ptr) << (8-bit_pos);
bit_pos -= 8;
}
val &= (1U<<cnt)-1;
bit_pos += cnt;
f->decode_bit_pos = bit_pos;
return val;
}
/*
2 bit --> cnt = 2
-2,-1,0. 1
3 bit --> cnt = 3
-2,-1,0. 1
-4,-3,-2,-1,0,1,2,3
if ( x < 0 )
r = bits(x-1)+1;
else
r = bits(x)+1;
*/
static int fd_get_signed_bits(fd_t *t, int cnt)
{
return (int)fd_get_unsigned_bits(t, cnt) - ((1<<cnt)>>1);
}
static void fd_draw_pixel(fd_t *f)
{
screen_set_pixel(f->x, f->y, '#');
}
static void fd_decode(bg_t *bg, bbx_t *bbx, fd_t *f, unsigned rle_bits_per_0, unsigned rle_bits_per_1)
{
unsigned a, b;
unsigned i;
screen_init();
if ( bbx == NULL )
bbx = &(bg->bbx);
/* init decode algorithm */
f->decode_ptr = bg->target_data;
f->decode_bit_pos = 0;
f->glyph_width = bbx->w;
f->glyph_height = bbx->h;
/* read glyph info */
f->decode_ptr += 2;
fd_get_unsigned_bits(f, f->bbx_w_max_bit_size);
fd_get_unsigned_bits(f, f->bbx_h_max_bit_size);
fd_get_signed_bits(f, f->bbx_x_max_bit_size);
fd_get_signed_bits(f, f->bbx_y_max_bit_size);
fd_get_signed_bits(f, f->dx_max_bit_size);
/* reset local x/y position */
f->x = 0;
f->y = 0;
//puts("");
/* decode glyph */
for(;;)
{
a = fd_get_unsigned_bits(f, rle_bits_per_0);
b = fd_get_unsigned_bits(f, rle_bits_per_1);
//printf("[%u %u]", a, b);
do
{
for( i = 0; i < a; i++ )
{
fd_inc(f);
}
for( i = 0; i < b; i++ )
{
fd_draw_pixel(f);
fd_inc(f);
}
} while( fd_get_unsigned_bits(f, 1) != 0 );
if ( f->y >= f->glyph_height )
break;
}
screen_show();
}
#endif
/*===================================================*/
/*
Desc:
Output a and b to the stream.
a and b must fit to the target size in bits.
Additionally a repeat code r (one bit) is generated:
It may look like this:
r = 0: 0aaaabb
or
r = 1: 1
If r is 0, then the number of zeros (a) and ones (b) will follow and both
values must be stored as in the decoder.
If r os 1, then the number of zeros and ones is repeated once
Args:
a: number of 0 bits, log2(a) must be smaller or equal to the fieldsize
b: number of 1 bits, log2(b) must be smaller or equal to the fieldsize
*/
static void bg_err(const char *s)
{
puts(s);
}
static void bg_init_rle(bg_t *bg, unsigned rle_bits_per_0, unsigned rle_bits_per_1)
{
bg->rle_bitcnt = 0;
bg->rle_is_first = 1;
bg->rle_bits_per_0 = rle_bits_per_0;
bg->rle_bits_per_1 = rle_bits_per_1;
bg->rle_last_0 = 0;
bg->rle_last_1 = 1;
bg_ClearTargetData(bg);
}
static int bg_01_rle(bg_t *bg, unsigned a, unsigned b)
{
if ( bg->rle_is_first == 0 && bg->rle_last_0 == a && bg->rle_last_1 == b )
{
bg->rle_bitcnt++;
if ( bg_AddTargetBits(bg, 1, 1) == 0 )
return bg_err("error in bg_01_rle 1 0"), 0;
}
else
{
if ( bg->rle_is_first == 0 )
{
if ( bg_AddTargetBits(bg, 1, 0) == 0 )
return bg_err("error in bg_01_rle 1 0"), 0;
bg->rle_bitcnt++;
}
if ( bg_AddTargetBits(bg, bg->rle_bits_per_0, a) == 0 )
return bg_err("error in bg_01_rle 1 a"), 0;
if ( bg_AddTargetBits(bg, bg->rle_bits_per_1, b) == 0 )
return bg_err("error in bg_01_rle 1 b"), 0;
/*
if ( bg->encoding == ' ' )
{
printf("[%u %u]", a, b);
}
*/
bg->rle_is_first = 0;
bg->rle_bitcnt +=bg->rle_bits_per_0;
bg->rle_bitcnt +=bg->rle_bits_per_1;
bg->rle_last_0 = a;
bg->rle_last_1 = b;
}
return 1;
}
/*
Desc:
Write the number of zeros and ones to the bit stream.
There is no restriction on the size of a and b.
Args:
a: number of 0 bits
b: number of 1 bits
*/
static int bg_prepare_01_rle(bg_t *bg, unsigned a, unsigned b)
{
//printf("[%u %u]", a, b);
while( a > (1<<bg->rle_bits_per_0) -1 )
{
if ( bg_01_rle(bg, (1<<bg->rle_bits_per_0) -1, 0) == 0 )
return 0;
a -= (1<<bg->rle_bits_per_0) -1;
}
while( b > (1<<bg->rle_bits_per_1) -1 )
{
if ( bg_01_rle(bg, a, (1<<bg->rle_bits_per_1) -1) == 0 )
return 0;
a = 0;
b -= (1<<bg->rle_bits_per_1) -1;
}
if ( a != 0 || b != 0 )
if ( bg_01_rle(bg, a, b) == 0 )
return 0;
return 1;
}
int bg_rle_compress(bg_t *bg, bbx_t *bbx, unsigned rle_bits_per_0, unsigned rle_bits_per_1, int is_output)
{
int x;
int y;
int i;
int bd_is_one; /* bit delta */
int bd_curr_len;
int bd_max_len;
int bd_chg_cnt;
static int bd_list[1024*2];
if ( bbx == NULL )
bbx = &(bg->bbx);
bg_init_rle(bg, rle_bits_per_0, rle_bits_per_1);
/* step 0: output initial information */
//printf("%ld %ld\n", (long)bg->encoding, (long)bg->map_to);
if ( bg->map_to <= 255 )
{
if ( bg_AddTargetData(bg, bg->map_to) < 0 )
return bg_err("error in bg_rle_compress"), 0;
}
else
{
if ( bg_AddTargetData(bg, bg->map_to >> 8) < 0 )
return bg_err("error in bg_rle_compress"), 0;
if ( bg_AddTargetData(bg, bg->map_to & 255 ) < 0 )
return bg_err("error in bg_rle_compress"), 0;
}
/* size, will be added later */
if ( bg_AddTargetData(bg, 0) < 0 )
return bg_err("error in bg_rle_compress"), 0;
// if ( bbx->w == 0 && bbx->h == 0 )
// {
// printf("blank char: enc=%ld\n", bg->encoding);
// }
// w & h is 0 for the space glyphe (encoding 32)
if ( bg_AddTargetBits(bg, bg->bf->bbx_w_max_bit_size, bbx->w) == 0 )
return bg_err("error in bg_rle_compress"), 0;
if ( bg_AddTargetBits(bg, bg->bf->bbx_h_max_bit_size, bbx->h) == 0 )
return bg_err("error in bg_rle_compress"), 0;
if ( bg_AddTargetBits(bg, bg->bf->bbx_x_max_bit_size, bbx->x + (1<<(bg->bf->bbx_x_max_bit_size-1))) == 0 )
return bg_err("error in bg_rle_compress"), 0;
if ( bg_AddTargetBits(bg, bg->bf->bbx_y_max_bit_size, bbx->y + (1<<(bg->bf->bbx_y_max_bit_size-1))) == 0 )
return bg_err("error in bg_rle_compress"), 0;
if ( bg->bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
{
if ( bg_AddTargetBits(bg, bg->bf->dx_max_bit_size, bg->dwidth_x + (1<<(bg->bf->dx_max_bit_size-1))) == 0 )
return bg_err("error in bg_rle_compress"), 0;
}
else if ( bg->bf->bbx_mode == BDF_BBX_MODE_MAX )
{
if ( bg_AddTargetBits(bg, bg->bf->dx_max_bit_size, bbx->w+ (1<<(bg->bf->dx_max_bit_size-1))) == 0 )
return bg_err("error in bg_rle_compress"), 0;
}
else
{
if ( bg_AddTargetBits(bg, bg->bf->dx_max_bit_size, bbx->w+ (1<<(bg->bf->dx_max_bit_size-1))) == 0 )
return bg_err("error in bg_rle_compress"), 0;
}
bd_is_one = 0;
bd_curr_len = 0;
bd_max_len = 0;
bd_chg_cnt = 0;
/* step 1: build array with pairs of a (number of zero bits) and b (number of one bits) */
for( y = bbx->y+bbx->h-1; y >= bbx->y; y--)
{
for( x = bbx->x; x < bbx->x + bbx->w; x++)
{
if ( bg_GetBBXPixel(bg, x, y) == 0 )
{
if ( bd_is_one != 0 )
{
bd_list[bd_chg_cnt] = bd_curr_len;
bd_is_one = 0;
bd_chg_cnt++;
bd_curr_len = 0;
}
bd_curr_len++;
}
else
{
if ( bd_is_one == 0 )
{
bd_list[bd_chg_cnt] = bd_curr_len;
bd_is_one = 1;
bd_chg_cnt++;
bd_curr_len = 0;
}
bd_curr_len++;
}
if ( bd_max_len < bd_curr_len )
bd_max_len = bd_curr_len;
}
}
bd_list[bd_chg_cnt] = bd_curr_len;
bd_chg_cnt++;
if ( (bd_chg_cnt & 1) == 1 )
{
assert(bd_is_one == 0);
bd_list[bd_chg_cnt] = 0;
bd_chg_cnt++;
}
//printf("01 pairs = %d\n", bd_chg_cnt/2);
/* step 2: convert the array into bit stream */
//if ( bg->encoding == ' ' )
// printf("Encoding list, pairs = %d\n", bd_chg_cnt/2);
for( i = 0; i < bd_chg_cnt; i+=2 )
{
//if ( bg->encoding == ' ' )
// printf("(%d %d)", bd_list[i], bd_list[i+1]);
if ( bg_prepare_01_rle(bg, bd_list[i], bd_list[i+1]) == 0 )
return 0;
}
//if ( bg->encoding == 'B' )
// printf("\nEncoding list end\n");
if ( bg_AddTargetBits(bg, 1, 0) == 0 ) // ensure that there is a 0 bit at the end. This will simplify decoding loop
return 0;
if ( bg_FlushTargetBits(bg) == 0 ) // finish the last byte and update bg->target_cnt
return 0;
if ( bg->map_to <= 255 )
{
bg->target_data[1] = bg->target_cnt;
}
else
{
bg->target_data[2] = bg->target_cnt;
}
/*
{
fd_t f;
f.bbx_x_max_bit_size = bg->bf->bbx_x_max_bit_size;
f.bbx_y_max_bit_size = bg->bf->bbx_y_max_bit_size;
f.bbx_w_max_bit_size = bg->bf->bbx_w_max_bit_size;
f.bbx_h_max_bit_size = bg->bf->bbx_h_max_bit_size;
f.dx_max_bit_size = bg->bf->dx_max_bit_size;
fd_decode(bg, bbx, &f, rle_bits_per_0, rle_bits_per_1);
}
*/
return 1;
}
unsigned long bf_RLECompressAllGlyphsWithFieldSize(bf_t *bf, int rle_0, int rle_1, int is_output)
{
int i;
bg_t *bg;
unsigned long total_bits = 0;
bbx_t local_bbx;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 )
{
bf_copy_bbx_and_update_shift(bf, &local_bbx, bg);
#ifdef OLD_CLODE
/* modifing the following code requires update ind bdf_font.c also */
if ( bf->bbx_mode == BDF_BBX_MODE_MINIMAL )
{
local_bbx = bg->bbx;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_MAX )
{
local_bbx = bf->max;
local_bbx.x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
if ( local_bbx.w < bg->dwidth_x )
local_bbx.w = bg->dwidth_x;
}
else if ( bf->bbx_mode == BDF_BBX_MODE_M8 )
{
local_bbx.w = bf->max.w;
if ( local_bbx.w < bg->dwidth_x )
local_bbx.w = bg->dwidth_x;
local_bbx.w = (local_bbx.w+7) & ~7;
local_bbx.h = (bf->max.h+7) & ~7;
local_bbx.x = bf->max.x;
local_bbx.y = bf->max.y;
local_bbx.x = 0;
if ( bg->bbx.x < 0 )
bg->shift_x = bg->bbx.x;
}
else
{
local_bbx = bf->max;
local_bbx.w = bg->bbx.w;
local_bbx.x = bg->bbx.x;
local_bbx.x = 0;
if ( bg->bbx.x < 0 )
{
/* e.g. "j" */
local_bbx.w -= bg->bbx.x;
bg->shift_x = bg->bbx.x;
}
else
{
/* e.g. "B" */
local_bbx.w += bg->bbx.x;
//bg->shift_x = bg->bbx.x;
}
if ( local_bbx.w < bg->dwidth_x )
local_bbx.w = bg->dwidth_x;
}
#endif
bg_rle_compress(bg, &local_bbx, rle_0, rle_1, is_output);
total_bits += bg->target_cnt*8+bg->target_bit_pos;
if ( is_output != 0 )
{
bf_Log(bf, "RLE Compress: Encoding %ld bits %u/%u", bg->encoding, bg->rle_bitcnt, bg->target_cnt*8+bg->target_bit_pos);
}
}
}
//bf_Log(bf, "RLE Compress: zero bits %d, one bits %d, total bit size %lu", rle_0, rle_1, total_bits);
return total_bits;
}
unsigned bf_RLE_get_glyph_data(bf_t *bf, uint8_t encoding)
{
uint8_t *font = bf->target_data;
font += BDF_RLE_FONT_GLYPH_START;
for(;;)
{
if ( font[1] == 0 )
break;
if ( font[0] == encoding )
{
return (font-bf->target_data)-BDF_RLE_FONT_GLYPH_START;
}
font += font[1];
}
return 0;
}
void bf_RLECompressAllGlyphs(bf_t *bf)
{
int i, j;
bg_t *bg;
int rle_0, rle_1;
int best_rle_0=0, best_rle_1= 0;
unsigned long total_bits = 0;
unsigned long min_total_bits = 0xffffffff;
int idx_cap_a;
int idx_cap_a_ascent;
int idx_1;
int idx_1_ascent;
int idx_g;
int idx_g_descent;
int idx_para;
int idx_para_ascent;
int idx_para_descent;
unsigned pos;
unsigned ascii_glyphs;
unsigned unicode_start_pos;
unsigned unicode_lookup_table_len;
uint32_t unicode_lookup_table_start;
uint32_t unicode_last_delta;
uint32_t unicode_last_target_cnt;
unsigned unicode_lookup_table_pos;
unsigned unicode_lookup_table_glyph_cnt;
uint32_t unicode_glyph_cnt = 0;
idx_cap_a_ascent = 0;
idx_cap_a = bf_GetIndexByEncoding(bf, 'A');
if ( idx_cap_a >= 0 )
{
idx_cap_a_ascent = bf->glyph_list[idx_cap_a]->bbx.h+bf->glyph_list[idx_cap_a]->bbx.y;
}
idx_1_ascent = 0;
idx_1 = bf_GetIndexByEncoding(bf, '1');
if ( idx_1 >= 0 )
{
idx_1_ascent = bf->glyph_list[idx_1]->bbx.h+bf->glyph_list[idx_1]->bbx.y;
}
idx_g_descent = 0;
idx_g = bf_GetIndexByEncoding(bf, 'g');
if ( idx_g >= 0 )
{
idx_g_descent = bf->glyph_list[idx_g]->bbx.y;
}
idx_para_ascent = 0;
idx_para = bf_GetIndexByEncoding(bf, '(');
if ( idx_para >= 0 )
{
idx_para_ascent = bf->glyph_list[idx_para]->bbx.h+bf->glyph_list[idx_para]->bbx.y;
idx_para_descent = bf->glyph_list[idx_para]->bbx.y;
}
else
{
idx_para_ascent = idx_cap_a_ascent;
if ( idx_para_ascent == 0 )
idx_para_ascent = idx_1_ascent;
idx_para_descent = idx_g_descent;
}
for( rle_0 = 2; rle_0 < 9; rle_0++ )
{
for( rle_1 = 2; rle_1 < 7; rle_1++ )
{
total_bits = bf_RLECompressAllGlyphsWithFieldSize(bf, rle_0, rle_1, 0);
if ( min_total_bits > total_bits )
{
min_total_bits = total_bits;
best_rle_0 = rle_0;
best_rle_1 = rle_1;
}
}
}
bf_Log(bf, "RLE Compress: best zero bits %d, one bits %d, total bit size %lu", best_rle_0, best_rle_1, min_total_bits);
bf_RLECompressAllGlyphsWithFieldSize(bf, best_rle_0, best_rle_1, 0);
bf_ClearTargetData(bf);
/*
glyph_cnt = *font++;
bits_per_0 = *font++;
bits_per_1 = *font++;
bits_per_char_width = *font++;
bits_per_char_height = *font++;
bits_per_char_x = *font++;
bits_per_char_y = *font++;
bits_per_delta_x = *font++;
*/
bf_Log(bf, "RLE Compress: Font code generation, selected glyphs=%d, total glyphs=%d", bf->selected_glyphs, bf->glyph_cnt);
/* 0 */
bf_AddTargetData(bf, bf->selected_glyphs);
bf_AddTargetData(bf, bf->bbx_mode);
bf_AddTargetData(bf, best_rle_0);
bf_AddTargetData(bf, best_rle_1);
/* 4 */
bf_AddTargetData(bf, bf->bbx_w_max_bit_size);
bf_AddTargetData(bf, bf->bbx_h_max_bit_size);
bf_AddTargetData(bf, bf->bbx_x_max_bit_size);
bf_AddTargetData(bf, bf->bbx_y_max_bit_size);
bf_AddTargetData(bf, bf->dx_max_bit_size);
/* 9 */
bf_AddTargetData(bf, bf->max.w);
bf_AddTargetData(bf, bf->max.h);
bf_AddTargetData(bf, bf->max.x);
bf_AddTargetData(bf, bf->max.y);
/* 13 */
if ( idx_cap_a_ascent > 0 )
bf_AddTargetData(bf, idx_cap_a_ascent);
else
bf_AddTargetData(bf, idx_1_ascent);
bf_AddTargetData(bf, idx_g_descent);
/* 15 */
bf_AddTargetData(bf, idx_para_ascent);
bf_AddTargetData(bf, idx_para_descent);
/* 17 */
bf_AddTargetData(bf, 0); /* start pos 'A', high/low */
bf_AddTargetData(bf, 0);
/* 19 */
bf_AddTargetData(bf, 0); /* start pos 'a', high/low */
bf_AddTargetData(bf, 0);
/* 21 */
bf_AddTargetData(bf, 0); /* start pos unicode, high/low */
bf_AddTargetData(bf, 0);
/* assumes, that map_to is sorted */
ascii_glyphs = 0;
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 0 && bg->map_to <= 255L )
{
if ( bg->target_data != NULL )
{
if ( bg->target_cnt >= 255 )
{
bf_Error(bf, "RLE Compress: Error, glyph too large, encoding=%ld cnt=%d", (long)bg->encoding, (int)bg->target_cnt);
exit(1);
}
for( j = 0; j < bg->target_cnt; j++ )
{
bf_AddTargetData(bf, bg->target_data[j]);
}
ascii_glyphs++; /* calculate the numner of ascii glyphs, this is required later for the unicode index table */
}
}
}
/* add empty glyph as end of font marker for the ASCII part (chars from 0 to 255) */
bf_AddTargetData(bf, 0);
bf_AddTargetData(bf, 0);
unicode_start_pos = bf->target_cnt-BDF_RLE_FONT_GLYPH_START;
/*
1 May 2018: Unicode lookup table
*/
bf_Log(bf, "RLE Compress: ASCII gylphs=%d, Unicode glyphs=%d", ascii_glyphs, bf->selected_glyphs-ascii_glyphs);
unicode_lookup_table_len = (bf->selected_glyphs-ascii_glyphs) / UNICODE_GLYPHS_PER_LOOKUP_TABLE_ENTRY;
//if ( unicode_lookup_table_len > 1 )
// unicode_lookup_table_len--;
bf_Log(bf, "RLE Compress: Glyphs per unicode lookup table entry=%d", UNICODE_GLYPHS_PER_LOOKUP_TABLE_ENTRY);
unicode_lookup_table_start = bf->target_cnt;
/* write n-1 entries */
for( i = 1; i < unicode_lookup_table_len; i++ )
{
bf_AddTargetData(bf, 0); /* offset */
bf_AddTargetData(bf, 0);
bf_AddTargetData(bf, 0); /* encoding */
bf_AddTargetData(bf, 0);
}
/* the last entry is special, it contains the encoding 0xffff */
bf_AddTargetData(bf, 0); /* offset */
bf_AddTargetData(bf, 4); /* default, if the table has only one entry, then just skip the table */
bf_AddTargetData(bf, 0xff); /* encoding */
bf_AddTargetData(bf, 0xff);
unicode_lookup_table_pos = 0;
unicode_lookup_table_glyph_cnt = 0;
unicode_last_delta = bf->target_cnt-unicode_lookup_table_start; /* should be 4 if unicode_lookup_table_len == 0 */
unicode_last_target_cnt = bf->target_cnt;
unicode_glyph_cnt = 0;
/* now write chars with code >= 256 from the BMP */
/* assumes, that map_to is sorted */
for( i = 0; i < bf->glyph_cnt; i++ )
{
bg = bf->glyph_list[i];
if ( bg->map_to >= 256 )
{
if ( bg->target_data != NULL )
{
if ( bg->target_cnt >= 255 )
{
bf_Error(bf, "RLE Compress: Error, glyph too large, encoding=%ld", (long)bg->encoding);
exit(1);
}
for( j = 0; j < bg->target_cnt; j++ )
{
bf_AddTargetData(bf, bg->target_data[j]);
}
// Debug output issue 1521
//bf_Log(bf, "RLE Compress: Unicode glyph pos=%d, lookup table=%d, glyph within lut=%d", unicode_glyph_cnt, unicode_lookup_table_pos, unicode_lookup_table_glyph_cnt);
/* update the unicode lookup table entry counter */
unicode_lookup_table_glyph_cnt++;
if ( unicode_lookup_table_glyph_cnt >= UNICODE_GLYPHS_PER_LOOKUP_TABLE_ENTRY )
{
/* ensure, that there is a table entry available */
if ( unicode_lookup_table_pos < unicode_lookup_table_len )
{
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+0] = unicode_last_delta>>8;
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+1] = unicode_last_delta&255;
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+2] |= bg->encoding>>8; // ensure to keep the 0x0ffff encoding at the end
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+3] |= bg->encoding&255; // ensure to keep the 0x0ffff encoding at the end
unicode_lookup_table_pos++;
unicode_lookup_table_glyph_cnt = 0;
unicode_last_delta = bf->target_cnt - unicode_last_target_cnt;
unicode_last_target_cnt = bf->target_cnt;
}
}
unicode_glyph_cnt++;
}
}
}
/* write pending block to the unicode lookup table, ensure, that there is a table entry available */
if ( unicode_lookup_table_pos < unicode_lookup_table_len )
{
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+0] = unicode_last_delta>>8;
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+1] = unicode_last_delta&255;
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+2] = 0xff;
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4+3] = 0xff;
unicode_lookup_table_pos++;
}
/* add empty encoding as end of font marker (note: this differs from the ASCII section) */
bf_AddTargetData(bf, 0);
bf_AddTargetData(bf, 0);
bf_Log(bf, "RLE Compress: Unicode lookup table len=%d, written entries=%d", unicode_lookup_table_len, unicode_lookup_table_pos);
bf_Log(bf, "RLE Compress: Unicode lookup table first entry: delta=%d, encoding=%d",
bf->target_data[unicode_lookup_table_start+0]*256+bf->target_data[unicode_lookup_table_start+1],
bf->target_data[unicode_lookup_table_start+2]*256+bf->target_data[unicode_lookup_table_start+3]);
bf_Log(bf, "RLE Compress: Unicode lookup table last entry: delta=%d, encoding=%d",
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4-4+0]*256+bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4-4+1],
bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4-4+2]*256+bf->target_data[unicode_lookup_table_start+unicode_lookup_table_pos*4-4+3]);
bf_Log(bf, "RLE Compress: Unicode glyphs written=%d", unicode_glyph_cnt);
assert(unicode_lookup_table_len == unicode_lookup_table_pos ); // ensure that all table entries are filled
pos = bf_RLE_get_glyph_data(bf, 'A');
bf->target_data[17] = pos >> 8;
bf->target_data[18] = pos & 255;
pos = bf_RLE_get_glyph_data(bf, 'a');
bf->target_data[19] = pos >> 8;
bf->target_data[20] = pos & 255;
bf->target_data[21] = unicode_start_pos >> 8;
bf->target_data[22] = unicode_start_pos & 255;
bf_Log(bf, "RLE Compress: 'A' pos = %u, 'a' pos = %u", bf_RLE_get_glyph_data(bf, 'A'), bf_RLE_get_glyph_data(bf, 'a'));
bf_Log(bf, "RLE Compress: Font size %d", bf->target_cnt);
}

523
font/bdfconv/bdf_tga.c Normal file
View File

@ -0,0 +1,523 @@
/*
bdf_tga.c
Modes:
BDF_BBX_MODE_MINIMAL 0
BDF_BBX_MODE_MAX 1
BDF_BBX_MODE_HEIGHT 2
For all modes, default reference should be the baseline.
This is required for mode 0, but may be optional for 1 and 2
If (x,y) is the user provided baseline point for the glyph, then
the decoding mus tbe start at
(x..., y-h-descent)
BDF_BBX_MODE_MINIMAL
- exact space as intended by the font author
- glyphs my overlap ("mj" with osb18)
BDF_BBX_MODE_MAX
- extra space may be added
- glyphs do not overlap
BDF_BBX_MODE_HEIGHT
- extra space may be added
- glyphs do not overlap
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "fd.h"
static uint16_t tga_width;
static uint16_t tga_height;
static uint16_t tga_used_height;
static uint8_t *tga_data = NULL;
static uint8_t *tga_font;
static int glyph_cnt;
static int bits_per_0;
static int bits_per_1;
static int bits_per_char_width;
static int bits_per_char_height;
static int bits_per_char_x;
static int bits_per_char_y;
static int bits_per_delta_x;
static int char_width;
static int char_height;
static int char_descent;
static unsigned unicode_start_pos;
static int tga_pixel_intersection;
int tga_get_char_width(void)
{
return char_width;
}
int tga_get_char_height(void)
{
return char_height;
}
int tga_init(uint16_t w, uint16_t h)
{
tga_width = 0;
tga_height = 0;
tga_used_height = 0;
tga_pixel_intersection = 0;
if ( tga_data != NULL )
free(tga_data);
tga_data = (uint8_t *)malloc((size_t)w*(size_t)h*3);
if ( tga_data == NULL )
return 0;
tga_width = w;
tga_height = h;
memset(tga_data, 255, tga_width*tga_height*3);
return 1;
}
void tga_clear(void)
{
memset(tga_data, 255, tga_width*tga_height*3);
}
void tga_set_pixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
{
uint8_t *p;
if ( y>= tga_height)
return;
if ( x>= tga_width)
return;
if ( tga_used_height < y )
tga_used_height = y;
p = tga_data + (tga_height-y-1)*(size_t)tga_width*3 + (size_t)x*3;
if ( p[0] != 255 || p[1] != 255 || p[2] != 255 )
tga_pixel_intersection = 1;
//printf("tga_set_pixel %d %d\n", x, y);
*p++ = b;
*p++ = g;
*p++ = r;
}
int tga_is_pixel_intersection(void)
{
return tga_pixel_intersection;
}
void tga_clear_pixel_intersection(void)
{
tga_pixel_intersection = 0;
}
void tga_write_byte(FILE *fp, uint8_t byte)
{
fputc(byte, fp);
}
void tga_write_word(FILE *fp, uint16_t word)
{
tga_write_byte(fp, word&255);
tga_write_byte(fp, word>>8);
}
void tga_save(const char *name)
{
FILE *fp;
fp = fopen(name, "wb");
if ( fp != NULL )
{
tga_write_byte(fp, 0); /* no ID */
tga_write_byte(fp, 0); /* no color map */
tga_write_byte(fp, 2); /* uncompressed true color */
tga_write_word(fp, 0);
tga_write_word(fp, 0);
tga_write_byte(fp, 0);
tga_write_word(fp, 0); /* x origin */
tga_write_word(fp, 0); /* y origin */
tga_write_word(fp, tga_width); /* width */
tga_write_word(fp, tga_used_height+1); /* height */
tga_write_byte(fp, 24); /* color depth */
tga_write_byte(fp, 0);
fwrite(tga_data + (tga_height - (tga_used_height+1))*tga_width*3 , tga_width*3, tga_used_height+1, fp);
tga_write_word(fp, 0);
tga_write_word(fp, 0);
tga_write_word(fp, 0);
tga_write_word(fp, 0);
fwrite("TRUEVISION-XFILE.", 18, 1, fp);
fclose(fp);
}
}
/*
font data:
offset bytes description
0 1 glyph_cnt number of glyphs
1 1 bbx_mode 0: proportional, 1: common height, 2: monospace, 3: multiple of 8
2 1 bits_per_0 glyph rle parameter
3 1 bits_per_1 glyph rle parameter
4 1 bits_per_char_width glyph rle parameter
5 1 bits_per_char_height glyph rle parameter
6 1 bits_per_char_x glyph rle parameter
7 1 bits_per_char_y glyph rle parameter
8 1 bits_per_delta_x glyph rle parameter
9 1 max_char_width
10 1 max_char_height
11 1 x offset
12 1 y offset (descent)
13 1 ascent (capital A)
14 1 descent (lower g)
15 1 ascent '('
16 1 descent ')'
17 1 start pos 'A' high byte
18 1 start pos 'A' low byte
19 1 start pos 'a' high byte
20 1 start pos 'a' low byte
21 1 start pos unicode high byte
22 1 start pos unicode low byte
*/
void tga_set_font(uint8_t *font)
{
glyph_cnt = *font++;
font++; /* bbx mode */
bits_per_0 = *font++;
bits_per_1 = *font++;
bits_per_char_width = *font++;
bits_per_char_height = *font++;
bits_per_char_x = *font++;
bits_per_char_y = *font++;
bits_per_delta_x = *font++;
char_width = *font++;
char_height = *font++;
font++; /* x offset */
char_descent = *(int8_t *)font;
font++;
font++;
font++;
font++;
font++;
font++;
font++;
font++;
font++;
unicode_start_pos = *font++;
unicode_start_pos <<= 8;
unicode_start_pos |= *font++;
tga_font = font;
}
uint8_t *tga_get_glyph_data(uint16_t encoding)
{
uint8_t *font = tga_font;
if ( encoding <= 255 )
{
for(;;)
{
if ( font[1] == 0 )
break;
if ( font[0] == encoding )
{
return font;
}
font += font[1];
}
}
else
{
uint16_t e;
uint8_t *unicode_lookup_table;
font += unicode_start_pos;
unicode_lookup_table = font;
/* search for the glyph start in the unicode lookup table */
do
{
font += ((unicode_lookup_table[0]<<8)|unicode_lookup_table[1]);
unicode_lookup_table+=2;
e = (unicode_lookup_table[0]<<8)|unicode_lookup_table[1];
unicode_lookup_table+=2;
} while( e < encoding );
/* continue with the search in the font */
for(;;)
{
e = ((font[0]<<8)|font[1]);
if ( e == 0 )
break;
if ( e == encoding )
{
return font;
}
font += font[2];
}
}
return NULL;
}
/* font decode */
struct tga_fd_struct
{
unsigned target_x;
unsigned target_y;
unsigned is_transparent;
unsigned x; /* local coordinates, (0,0) is upper left */
unsigned y;
unsigned glyph_width;
unsigned glyph_height;
const uint8_t *decode_ptr; /* pointer to the compressed data */
unsigned decode_bit_pos; /* bitpos inside a byte of the compressed data */
uint8_t bbx_x_max_bit_size;
uint8_t bbx_y_max_bit_size;
uint8_t bbx_w_max_bit_size;
uint8_t bbx_h_max_bit_size;
uint8_t dx_max_bit_size;
};
typedef struct tga_fd_struct tga_fd_t;
/* increment x and consider line wrap (inc y)*/
/* old procedure */
void tga_fd_inc(tga_fd_t *f)
{
unsigned x = f->x;
x++;
if ( x == f->glyph_width )
{
x = 0;
f->y++;
}
f->x = x;
}
unsigned tga_fd_get_unsigned_bits(tga_fd_t *f, unsigned cnt)
{
unsigned val;
unsigned bit_pos = f->decode_bit_pos;
val = *(f->decode_ptr);
val >>= bit_pos;
if ( bit_pos + cnt >= 8 )
{
f->decode_ptr++;
val |= *(f->decode_ptr) << (8-bit_pos);
bit_pos -= 8;
}
val &= (1U<<cnt)-1;
bit_pos += cnt;
f->decode_bit_pos = bit_pos;
return val;
}
/*
2 bit --> cnt = 2
-2,-1,0. 1
3 bit --> cnt = 3
-2,-1,0. 1
-4,-3,-2,-1,0,1,2,3
if ( x < 0 )
r = bits(x-1)+1;
else
r = bits(x)+1;
*/
int tga_fd_get_signed_bits(tga_fd_t *t, int cnt)
{
return (int)tga_fd_get_unsigned_bits(t, cnt) - ((1<<cnt)>>1);
}
void tga_fd_draw_fg_pixel(tga_fd_t *f, unsigned cnt)
{
//printf("%d ", cnt);
/* cnt can be zero */
while( cnt > 0 )
{
cnt--;
tga_set_pixel(f->target_x+f->x+cnt, f->target_y+f->y, 0,0,0);
}
}
void tga_fd_draw_bg_pixel(tga_fd_t *f, unsigned cnt)
{
//printf("%d ", cnt);
/* cnt can be zero */
while( cnt > 0 )
{
cnt--;
if ( f->is_transparent == 0 )
tga_set_pixel(f->target_x+f->x+cnt, f->target_y+f->y, 0x0e8,0x0e8,0x0e8);
}
}
void tga_draw_hline(unsigned x,unsigned y, unsigned cnt, unsigned is_foreground)
{
while( cnt > 0 )
{
cnt--;
if ( is_foreground == 0 )
tga_set_pixel(x+cnt, y, 0x0e8,0x0e8,0x0e8);
else
tga_set_pixel(x+cnt, y, 255,0,0);
}
}
void tga_fd_draw_pixel(tga_fd_t *f, unsigned cnt, unsigned is_foreground)
{
if ( is_foreground )
{
tga_fd_draw_fg_pixel(f, cnt);
}
else
{
tga_fd_draw_bg_pixel(f, cnt);
}
}
void tga_fd_decode_len(tga_fd_t *f, unsigned len, unsigned is_foreground)
{
unsigned cnt, rem;
cnt = len;
for(;;)
{
rem = f->glyph_width;
rem -= f->x;
if ( cnt < rem )
break;
tga_fd_draw_pixel(f,rem, is_foreground);
cnt -= rem;
f->x = 0;
f->y++;
}
tga_fd_draw_pixel(f, cnt, is_foreground);
f->x += cnt;
}
unsigned tga_fd_decode(tga_fd_t *f, uint8_t *glyph_data, int is_unicode)
{
unsigned a, b;
//unsigned cnt, rem;
int x, y;
unsigned d = 0;
f->decode_ptr = glyph_data;
f->decode_bit_pos = 0;
f->decode_ptr += 1;
f->decode_ptr += 1;
if ( is_unicode != 0 )
f->decode_ptr += 1;
f->glyph_width = tga_fd_get_unsigned_bits(f, bits_per_char_width);
f->glyph_height = tga_fd_get_unsigned_bits(f, bits_per_char_height);
x = tga_fd_get_signed_bits(f, bits_per_char_x);
y = tga_fd_get_signed_bits(f, bits_per_char_y);
d = tga_fd_get_signed_bits(f, bits_per_delta_x);
if ( f->glyph_width > 0 )
{
f->target_x += x;
f->target_y -= f->glyph_height ;
f->target_y -=y ;
/* reset local x/y position */
f->x = 0;
f->y = 0;
/* decode glyph */
for(;;)
{
a = tga_fd_get_unsigned_bits(f, bits_per_0);
b = tga_fd_get_unsigned_bits(f, bits_per_1);
do
{
tga_fd_decode_len(f, a, 0);
tga_fd_decode_len(f, b, 1);
} while( tga_fd_get_unsigned_bits(f, 1) != 0 );
if ( f->y >= f->glyph_height )
break;
}
}
return d;
}
unsigned tga_draw_glyph(unsigned x, unsigned y, uint16_t encoding, int is_hints)
{
unsigned dx = 0;
tga_fd_t f;
f.target_x = x;
f.target_y = y;
f.is_transparent = !is_hints;
uint8_t *glyph_data = tga_get_glyph_data(encoding); /* better skip the first 2 or 3 bytes */
if ( glyph_data != NULL )
{
dx = tga_fd_decode(&f, glyph_data, encoding >= 255 ? 1 : 0);
if ( is_hints )
{
tga_set_pixel(x+dx, y, 28,133,240); /* orange: reference point */
tga_set_pixel(x, y, 255,164,0); /* blue: delta x (width) for this glyph */
}
}
return dx;
}
unsigned tga_draw_string(unsigned x, unsigned y, const char *s, int is_hints, unsigned max_dx)
{
unsigned dx = 0;
while( *s != '\0' )
{
dx += tga_draw_glyph(x+dx,y,*s, is_hints);
if ( max_dx > 0 )
if ( dx > max_dx )
break;
s++;
}
return dx;
}

226
font/bdfconv/fd.c Normal file
View File

@ -0,0 +1,226 @@
/*
fd.c
font decode
(obsolete? does not support unicode)
*/
#include "fd.h"
#include <stddef.h>
void fd_init(fd_t *fd)
{
fd->is_transparent = 1;
}
void fd_set_font(fd_t *fd, uint8_t *font)
{
fd->glyph_cnt = *font++;
font++; /* bbx mode */
fd->bits_per_0 = *font++;
fd->bits_per_1 = *font++;
fd->bits_per_char_width = *font++;
fd->bits_per_char_height = *font++;
fd->bits_per_char_x = *font++;
fd->bits_per_char_y = *font++;
fd->bits_per_delta_x = *font++;
fd->char_width = *font++;
fd->char_height = *font++;
font++; /* x offset */
fd->char_descent = *(int8_t *)font;
font++;
font++;
font++;
font++;
font++;
fd->capital_a_pos= *font++;
fd->capital_a_pos <<= 8;
fd->capital_a_pos |= *font++;
fd->small_a_pos = *font++;
fd->small_a_pos <<= 8;
fd->small_a_pos |= *font++;
/* TODO: proper unicode update */
font++;
font++;
fd->font = font;
}
uint8_t *fd_get_glyph_data(fd_t *fd, uint8_t encoding)
{
uint8_t *font = fd->font;
if ( encoding >= 'a' ) /* assumes 'a' > 'A' */
{
font += fd->small_a_pos;
}
else if ( encoding >= 'A' )
{
font += fd->capital_a_pos;
}
for(;;)
{
if ( font[1] == 0 )
break;
if ( font[0] == encoding )
{
return font;
}
font += font[1];
}
return NULL;
}
__attribute__((noinline)) unsigned fd_get_unsigned_bits(fd_t *f, unsigned cnt)
{
unsigned val;
unsigned bit_pos = f->decode_bit_pos;
unsigned rem_bits;
val = f->decode_byte;
rem_bits = 8;
rem_bits -= bit_pos;
bit_pos += cnt;
if ( cnt >= rem_bits )
{
f->decode_ptr++;
f->decode_byte = *(f->decode_ptr);
val |= f->decode_byte << (rem_bits);
bit_pos -= 8;
f->decode_byte >>= bit_pos;
}
else
{
f->decode_byte >>= cnt;
}
val &= (1U<<cnt)-1;
f->decode_bit_pos = bit_pos;
return val;
}
int fd_get_signed_bits(fd_t *fd, int cnt)
{
return (int)fd_get_unsigned_bits(fd, cnt) - ((1<<cnt)>>1);
}
void tga_draw_hline(unsigned x,unsigned y, unsigned cnt, unsigned is_foreground);
void fd_draw_pixel(fd_t *f, unsigned cnt, unsigned is_foreground)
{
if ( f->is_transparent != 0 && is_foreground == 0 )
return;
tga_draw_hline(f->target_x+f->x, f->target_y+f->y, cnt, is_foreground);
}
void fd_decode_len(fd_t *fd, unsigned len, unsigned is_foreground)
{
unsigned cnt, rem;
cnt = len;
for(;;)
{
rem = fd->glyph_width;
rem -= fd->x;
if ( cnt < rem )
break;
fd_draw_pixel(fd,rem, is_foreground);
cnt -= rem;
fd->x = 0;
fd->y++;
}
fd_draw_pixel(fd, cnt, is_foreground);
fd->x += cnt;
}
/*
expects:
unsigned target_x;
unsigned target_y;
unsigned is_transparent;
const uint8_t *decode_ptr;
*/
unsigned fd_decode(fd_t *f)
{
unsigned a, b;
int x, y;
unsigned d = 0;
f->decode_bit_pos = 0;
f->decode_ptr += 1;
f->decode_ptr += 1;
f->decode_byte = *(f->decode_ptr); /* init decoder */
f->glyph_width = fd_get_unsigned_bits(f, f->bits_per_char_width);
f->glyph_height = fd_get_unsigned_bits(f, f->bits_per_char_height);
x = fd_get_signed_bits(f, f->bits_per_char_x);
y = fd_get_signed_bits(f, f->bits_per_char_y);
d = fd_get_signed_bits(f, f->bits_per_delta_x);
if ( f->glyph_width > 0 )
{
f->target_x += x;
f->target_y -= f->glyph_height ;
f->target_y -=y ;
f->x = 0;
f->y = 0;
for(;;)
{
a = fd_get_unsigned_bits(f, f->bits_per_0);
b = fd_get_unsigned_bits(f, f->bits_per_1);
do
{
fd_decode_len(f, a, 0);
fd_decode_len(f, b, 1);
} while( fd_get_unsigned_bits(f, 1) != 0 );
if ( f->y >= f->glyph_height )
break;
}
}
return d;
}
unsigned fd_draw_glyph(fd_t *fd, unsigned x, unsigned y, uint8_t encoding)
{
unsigned dx = 0;
fd->target_x = x;
fd->target_y = y;
fd->decode_ptr = fd_get_glyph_data(fd, encoding);
if ( fd->decode_ptr != NULL )
{
dx = fd_decode(fd);
}
return dx;
}
unsigned fd_draw_string(fd_t *fd, unsigned x, unsigned y, const char *s)
{
unsigned dx = 0;
while( *s != '\0' )
{
dx += fd_draw_glyph(fd, x+dx,y,*s);
s++;
}
return dx;
}

49
font/bdfconv/fd.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef _FD_H
#define _FD_H
#include <stdint.h>
/* font decode */
struct fd_struct
{
unsigned target_x;
unsigned target_y;
unsigned is_transparent;
unsigned x; /* local coordinates, (0,0) is upper left */
unsigned y;
unsigned glyph_width;
unsigned glyph_height;
const uint8_t *decode_ptr; /* pointer to the compressed data */
unsigned decode_bit_pos; /* bitpos inside a byte of the compressed data */
unsigned decode_byte;
uint8_t glyph_cnt;
uint8_t bits_per_0;
uint8_t bits_per_1;
uint8_t bits_per_char_width;
uint8_t bits_per_char_height;
uint8_t bits_per_char_x;
uint8_t bits_per_char_y;
uint8_t bits_per_delta_x;
uint8_t char_width;
uint8_t char_height;
uint8_t char_descent;
unsigned capital_a_pos;
unsigned small_a_pos;
uint8_t *font;
};
typedef struct fd_struct fd_t;
void fd_init(fd_t *fd);
void fd_set_font(fd_t *fd, uint8_t *font);
unsigned fd_draw_glyph(fd_t *fd, unsigned x, unsigned y, uint8_t encoding);
unsigned fd_draw_string(fd_t *fd, unsigned x, unsigned y, const char *s);
#endif /* _FD_H */

529
font/bdfconv/main.c Normal file
View File

@ -0,0 +1,529 @@
/*
main.c (bdfconv)
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "bdf_font.h"
#include "fd.h"
/*================================================*/
int get_str_arg(char ***argv, int c, char **result)
{
if ( (**argv)[0] == '-' )
{
if ( (**argv)[1] == c )
{
if ( (**argv)[2] == '\0' )
{
(*argv)++;
*result = **argv;
}
else
{
*result = (**argv)+2;
}
(*argv)++;
return 1;
}
}
return 0;
}
int get_num_arg(char ***argv, int c, unsigned long *result)
{
if ( (**argv)[0] == '-' )
{
if ( (**argv)[1] == c )
{
if ( (**argv)[2] == '\0' )
{
if ( *((*argv)+1) != NULL )
{
(*argv)++;
*result = strtoul((**argv), NULL, 10);
}
}
else
{
*result = strtoul((**argv)+2, NULL, 10);
}
(*argv)++;
return 1;
}
}
return 0;
}
int get_num_strarg(char ***argv, const char *s, unsigned long *result)
{
if ( (**argv)[0] == '-' )
{
//printf("get_num_strarg %s: match %s\n", **argv, s);
if ( strcmp( (**argv)+1, s ) == 0 )
{
//printf("get_num_strarg %s: match %s found\n", **argv, s);
if ( *((*argv)+1) != NULL )
{
(*argv)++;
*result = strtoul((**argv), NULL, 10);
}
(*argv)++;
return 1;
}
}
return 0;
}
int is_arg(char ***argv, int c)
{
if ( (**argv)[0] == '-' )
{
if ( (**argv)[1] == c )
{
(*argv)++;
return 1;
}
}
return 0;
}
/*================================================*/
void help(void)
{
printf("bdfconv [options] filename\n");
printf("-h Display this help\n");
printf("-v Print log messages\n");
printf("-b <n> Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8, 4: 5x7 mode\n");
printf("-f <n> Font format, 0: ucglib font, 1: u8g2 font, 2: u8g2 uncompressed 8x8 font (enforces -b 3)\n");
printf("-m 'map' Unicode ASCII mapping\n");
printf("-M 'mapfile' Read Unicode ASCII mapping from file 'mapname'\n");
printf("-o <file> C output font file\n");
printf("-k <file> C output file with kerning information\n");
printf("-p <%%> Minimum distance for kerning in percent of the global char width (lower values: Smaller gaps, more data)\n");
printf("-x <n> X-Offset for 8x8 font sub-glyph extraction (requires -f 2, default 0)\n");
printf("-y <n> Y-Offset for 8x8 font sub-glyph extraction (requires -f 2, default 0)\n");
printf("-th <n> Horizontal size of the 8x8 glyphs (requires -f 2, default 1)\n");
printf("-tv <n> Vertical size of the 8x8 glyphs (requires -f 2, default 1)\n");
printf("-n <name> C indentifier (font name)\n");
printf("-d <file> Overview picture: Enable generation of bdf.tga and assign BDF font <file> for description\n");
printf("-l <margin> Overview picture: Set left margin\n");
printf("-g <glyphs> Overview picture: Set glyphs per line (default: 16)\n");
printf("-a Overview picture: Additional font information (background, orange&blue dot)\n");
printf("-t Overview picture: Test string (Woven silk pyjamas exchanged for blue quartz.)\n");
printf("-r Runtime test\n");
printf("\n");
printf("map := <mapcmd> { \",\" <mapcmd> }\n");
printf("mapcmd := <default> | <maprange> | <exclude> | <exclude-kerning>\n");
printf("default := \"*\"\n");
printf("maprange := <range> [ \">\" <addexpr> ] Move specified glyph <range> to target code <num>\n");
printf("exclude := \"~\" <range> \n");
printf("exclude-kerning:= \"x\" <range> \n");
printf("range := <addexpr> [ \"-\" <addexpr> ] Select glyphs within specified range\n");
printf("addexpr := <mulexpr> [ \"+\" <mulexpr> ]\n");
printf("mulexpr := <num> [ \"*\" <num> ]\n");
printf("num := <hexnum> | <decnum>\n");
printf("hexnum := \"$\" <hexdigit> { <hexdigit> }\n");
printf("decnum := <decdigit> { <decdigit> }\n");
printf("decdigit := \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\"\n");
printf("hexdigit := \"a\" | \"b\" | \"c\" | \"d\" | \"e\" | \"f\" | \"A\" | \"B\" | \"C\" | \"D\" | \"E\" | \"F\" | <decdigit>\n");
printf("{ } zero, one ore more, [ ] zero or once, | alternative\n");
printf("example:\n");
printf(" -m '32-255' select gylphs from encoding 32 to 255\n");
printf(" -m '32-255,~64' select gylphs from encoding 32 to 255, exclude '@'\n");
printf(" -m '32,48-57' select space, '1', '2', ... '9'\n");
printf("build modes:\n");
printf(" -b 0: Most compact, glyph bitmap is minimal\n");
printf(" -b 1: Like -b 0, but glyph bitmap is extended to the height of the largest glyph within the selected glyph list.\n");
printf(" Also the width of the gylphs is extended to cover the delta x advance.\n");
printf(" -b 2: Like -b 1, but glyph width is set to the width of the largest glyph within the selected gylph list.\n");
printf(" -b 3: Like -b 2, but width and height are forced to be a multiple of 8.\n");
}
/*================================================*/
unsigned long left_margin = 1;
unsigned long build_bbx_mode = 0;
unsigned long font_format = 0;
unsigned long min_distance_in_per_cent_of_char_width = 25;
unsigned long cmdline_glyphs_per_line = 16;
unsigned long xoffset = 0;
unsigned long yoffset = 0;
unsigned long tile_h_size = 1;
unsigned long tile_v_size = 1;
int font_picture_extra_info = 0;
int font_picture_test_string = 0;
int runtime_test = 0;
char *c_filename = NULL;
char *k_filename = NULL;
char *target_fontname = "bdf_font";
/*================================================*/
unsigned tga_get_line_height(bf_t *bf_desc_font, bf_t *bf)
{
unsigned h;
tga_set_font(bf_desc_font->target_data);
h = tga_get_char_height();
tga_set_font(bf->target_data);
if ( h < tga_get_char_height() )
return tga_get_char_height();
return h;
}
unsigned tga_draw_font_line(unsigned y, long enc_start, bf_t *bf_desc_font, bf_t *bf, long glyphs_per_line)
{
long i;
unsigned x;
int is_empty;
char pre[32];
is_empty = 1;
for( i = 0; i< 16 && is_empty != 0; i++ )
{
if ( tga_get_glyph_data(i+enc_start) != NULL )
is_empty = 0;
}
if ( is_empty != 0 )
return 0;
sprintf(pre, "%5ld/0x%04lx", enc_start, enc_start);
x = left_margin;
if ( bf_desc_font != NULL )
{
if ( bf_desc_font->target_data != NULL )
{
tga_set_font(bf_desc_font->target_data);
x += tga_draw_string(x, y, pre, 0, 0);
}
}
x += 4;
tga_set_font(bf->target_data);
for( i = 0; i< glyphs_per_line; i++ )
{
tga_draw_glyph(x + (tga_get_char_width()+2)*i,y,enc_start+i, font_picture_extra_info);
}
return left_margin + x + (tga_get_char_width()+2)*glyphs_per_line;
}
unsigned tga_draw_font_info(unsigned y, const char *fontname, bf_t *bf_desc_font, bf_t *bf)
{
unsigned x;
int cap_a, cap_a_height;
static char s[256];
cap_a_height = 0;
cap_a = bf_GetIndexByEncoding(bf, 'A');
if ( cap_a >= 0 )
{
cap_a_height = bf->glyph_list[cap_a]->bbx.h+bf->glyph_list[cap_a]->bbx.y;
}
if ( bf_desc_font != NULL )
{
if ( bf_desc_font->target_data != NULL )
{
tga_set_font(bf_desc_font->target_data);
y += tga_get_char_height()+1;
x = left_margin;
x += tga_draw_string(x, y, fontname, 0, 0);
y += tga_get_char_height()+1;
sprintf(s, "Max width %u, max height %u", tga_get_char_width(), tga_get_char_height());
x = left_margin;
x += tga_draw_string(x, y, s, 0, 0);
y += tga_get_char_height()+1;
sprintf(s, "'A' height %d, font size %d ", cap_a_height, bf->target_cnt);
x = left_margin;
x += tga_draw_string(x, y, s, 0, 0);
return (tga_get_char_height()+1)*3;
}
}
return 0;
}
unsigned tga_draw_font(unsigned y, const char *fontname, bf_t *bf_desc_font, bf_t *bf, long glyphs_per_line)
{
long i;
unsigned x, xmax;
xmax = 0;
bf_Log(bf, "Draw TGA, line height %d", tga_get_line_height(bf_desc_font, bf));
y += tga_draw_font_info( y, fontname, bf_desc_font, bf);
y += tga_get_line_height(bf_desc_font, bf)+1;
for( i = 0; i <= 0x0ffff; i+=glyphs_per_line )
{
x = tga_draw_font_line(y, i, bf_desc_font, bf, glyphs_per_line);
if ( x > 0 )
{
if ( xmax < x )
xmax = x;
y += tga_get_line_height(bf_desc_font, bf)+1;
//bf_Log(bf, "Draw TGA, encoding %04x, y %d", i, y);
}
}
bf_Log(bf, "Draw TGA, xmax %d", xmax);
tga_set_font(bf->target_data);
//tga_draw_string(0, y, "Woven silk pyjamas exchanged for blue quartz", 1, xmax);
//y += tga_get_char_height()+1;
if ( font_picture_test_string != 0 )
{
tga_draw_string(left_margin, y, "Woven silk pyjamas exchanged for blue quartz.", 0, xmax);
y += tga_get_line_height(bf_desc_font, bf)+1;
}
return y;
}
/*================================================*/
/* main */
int main(int argc, char **argv)
{
bf_t *bf_desc_font;
bf_t *bf;
char *bdf_filename = NULL;
int is_verbose = 0;
char *map_str ="*";
char *map_filename ="";
char *desc_font_str = "";
unsigned y;
argv++;
/*
if ( *argv == NULL )
{
help();
exit(1);
}
*/
for(;;)
{
if ( *argv == NULL )
break;
if ( is_arg(&argv, 'h') != 0 )
{
help();
exit(1);
}
else if ( is_arg(&argv, 'v') != 0 )
{
is_verbose = 1;
}
else if ( is_arg(&argv, 'a') != 0 )
{
font_picture_extra_info = 1;
}
else if ( get_num_strarg(&argv, "th", &tile_h_size) != 0 )
{
}
else if ( get_num_strarg(&argv, "tv", &tile_v_size) != 0 )
{
}
else if ( is_arg(&argv, 't') != 0 )
{
font_picture_test_string = 1;
}
else if ( is_arg(&argv, 'r') != 0 )
{
runtime_test = 1;
}
else if ( get_num_arg(&argv, 'g', &cmdline_glyphs_per_line) != 0 )
{
}
else if ( get_num_arg(&argv, 'b', &build_bbx_mode) != 0 )
{
}
else if ( get_num_arg(&argv, 'f', &font_format) != 0 )
{
}
else if ( get_num_arg(&argv, 'x', &xoffset) != 0 )
{
}
else if ( get_num_arg(&argv, 'y', &yoffset) != 0 )
{
}
else if ( get_num_arg(&argv, 'l', &left_margin) != 0 )
{
}
else if ( get_num_arg(&argv, 'p', &min_distance_in_per_cent_of_char_width) != 0 )
{
}
else if ( get_str_arg(&argv, 'd', &desc_font_str) != 0 )
{
}
else if ( get_str_arg(&argv, 'o', &c_filename) != 0 )
{
}
else if ( get_str_arg(&argv, 'n', &target_fontname) != 0 )
{
}
else if ( get_str_arg(&argv, 'm', &map_str) != 0 )
{
}
else if ( get_str_arg(&argv, 'k', &k_filename) != 0 )
{
}
else if ( get_str_arg(&argv, 'M', &map_filename) != 0 )
{
}
else
{
bdf_filename = *argv;
argv++;
}
}
if ( bdf_filename == NULL )
{
help();
exit(1);
}
bf_desc_font = NULL;
if ( desc_font_str[0] != '\0' )
{
bf_desc_font = bf_OpenFromFile(desc_font_str, 0, BDF_BBX_MODE_MINIMAL, "*", "", 0, 0, 0, 1, 1); /* assume format 0 for description */
if ( bf_desc_font == NULL )
{
exit(1);
}
}
if ( font_format == 2 )
{
build_bbx_mode = BDF_BBX_MODE_M8;
/* issue the following log message later, when there is a valid bf object */
/* bf_Log(bf, "Font mode 1: BBX mode set to 3"); */
}
/* render the complete font */
bf = bf_OpenFromFile(bdf_filename, is_verbose, build_bbx_mode, map_str, map_filename, font_format, xoffset, yoffset, tile_h_size, tile_v_size);
if ( bf == NULL )
{
exit(1);
}
if ( font_format == 2 )
{
/* now generate the log message */
bf_Log(bf, "Note: For font format 2 BBX mode has been set to 3");
}
if ( bf_desc_font != NULL )
{
if ( font_format == 2 )
{
bf_Log(bf, "Note: Overview Picture not possible for font format 2, option -d ignored.");
}
else
{
tga_init(1024, 1024*12);
if ( target_fontname[0] != '\0' )
y = tga_draw_font(0, target_fontname, bf_desc_font, bf, cmdline_glyphs_per_line);
else
y = tga_draw_font(0, bdf_filename, bf_desc_font, bf, cmdline_glyphs_per_line);
if ( runtime_test != 0 )
{
long i;
clock_t c = clock();
fd_t fd;
fd_init(&fd);
fd_set_font(&fd, bf->target_data);
for( i = 0; i < 10000; i++ )
fd_draw_string(&fd, left_margin, y, "Woven silk pyjamas exchanged for blue quartz.");
bf_Log(bf, "Runtime test: %.2lf sec", (double)(clock()-c)/(double)CLOCKS_PER_SEC);
}
tga_set_pixel(1, 1, 0, 0, 0);
tga_save("bdf.tga");
}
}
if ( c_filename != NULL )
{
/* write the encoded data in bf->target_data */
if ( font_format == 0 )
{
bf_WriteUCGCByFilename(bf, c_filename, target_fontname, " ");
}
else
{
/* font format >= 1 are for u8g2, the following procedure just writes the content to the file */
bf_WriteU8G2CByFilename(bf, c_filename, target_fontname, " "); /* bdf_font.c */
}
}
if ( k_filename != NULL )
{
bdf_calculate_all_kerning(bf, k_filename, target_fontname, min_distance_in_per_cent_of_char_width);
}
bf_Close(bf);
return 0;
}