From a2e6ddbac9f1e88c781545b19c0e6ad3dfae8498 Mon Sep 17 00:00:00 2001 From: Alexander Popov Date: Tue, 2 May 2023 21:01:20 +0300 Subject: [PATCH] =?UTF-8?q?Init=20=F0=9F=8F=B4=E2=80=8D=E2=98=A0=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 20 + LICENSE | 24 + README.md | 20 + font/bdfconv/.editorconfig | 5 + font/bdfconv/Makefile | 520 +++++++++++++++++++++ font/bdfconv/bdf_8x8.c | 196 ++++++++ font/bdfconv/bdf_font.c | 763 ++++++++++++++++++++++++++++++ font/bdfconv/bdf_font.h | 162 +++++++ font/bdfconv/bdf_glyph.c | 439 +++++++++++++++++ font/bdfconv/bdf_glyph.h | 85 ++++ font/bdfconv/bdf_kern.c | 217 +++++++++ font/bdfconv/bdf_map.c | 323 +++++++++++++ font/bdfconv/bdf_parser.c | 478 +++++++++++++++++++ font/bdfconv/bdf_rle.c | 932 +++++++++++++++++++++++++++++++++++++ font/bdfconv/bdf_tga.c | 523 +++++++++++++++++++++ font/bdfconv/fd.c | 226 +++++++++ font/bdfconv/fd.h | 49 ++ font/bdfconv/main.c | 529 +++++++++++++++++++++ 18 files changed, 5511 insertions(+) create mode 100644 .editorconfig create mode 100644 LICENSE create mode 100644 README.md create mode 100644 font/bdfconv/.editorconfig create mode 100644 font/bdfconv/Makefile create mode 100644 font/bdfconv/bdf_8x8.c create mode 100644 font/bdfconv/bdf_font.c create mode 100644 font/bdfconv/bdf_font.h create mode 100644 font/bdfconv/bdf_glyph.c create mode 100644 font/bdfconv/bdf_glyph.h create mode 100644 font/bdfconv/bdf_kern.c create mode 100644 font/bdfconv/bdf_map.c create mode 100644 font/bdfconv/bdf_parser.c create mode 100644 font/bdfconv/bdf_rle.c create mode 100644 font/bdfconv/bdf_tga.c create mode 100644 font/bdfconv/fd.c create mode 100644 font/bdfconv/fd.h create mode 100644 font/bdfconv/main.c diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..324c6dd --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2d1632 --- /dev/null +++ b/README.md @@ -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 +``` diff --git a/font/bdfconv/.editorconfig b/font/bdfconv/.editorconfig new file mode 100644 index 0000000..4b3a778 --- /dev/null +++ b/font/bdfconv/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[{*.c,*.h}] +indent_style = unset +indent_size = unset diff --git a/font/bdfconv/Makefile b/font/bdfconv/Makefile new file mode 100644 index 0000000..c8d7c5b --- /dev/null +++ b/font/bdfconv/Makefile @@ -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 + diff --git a/font/bdfconv/bdf_8x8.c b/font/bdfconv/bdf_8x8.c new file mode 100644 index 0000000..394d1af --- /dev/null +++ b/font/bdfconv/bdf_8x8.c @@ -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 +#include +#include +#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); +} \ No newline at end of file diff --git a/font/bdfconv/bdf_font.c b/font/bdfconv/bdf_font.c new file mode 100644 index 0000000..cf538e2 --- /dev/null +++ b/font/bdfconv/bdf_font.c @@ -0,0 +1,763 @@ + + +#include +#include +#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; +} + diff --git a/font/bdfconv/bdf_font.h b/font/bdfconv/bdf_font.h new file mode 100644 index 0000000..7c79799 --- /dev/null +++ b/font/bdfconv/bdf_font.h @@ -0,0 +1,162 @@ +/* + + bdf_font.h + +*/ + + +#ifndef _BDF_FONT_H +#define _BDF_FONT_H + +#include +#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 diff --git a/font/bdfconv/bdf_glyph.c b/font/bdfconv/bdf_glyph.c new file mode 100644 index 0000000..7850212 --- /dev/null +++ b/font/bdfconv/bdf_glyph.c @@ -0,0 +1,439 @@ + + +#include +#include +#include +#include +#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<= 0 +*/ +int bg_AddTargetBits(bg_t *bg, unsigned cnt, unsigned val) +{ + + assert( val < (1<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; +} \ No newline at end of file diff --git a/font/bdfconv/bdf_glyph.h b/font/bdfconv/bdf_glyph.h new file mode 100644 index 0000000..5906e1e --- /dev/null +++ b/font/bdfconv/bdf_glyph.h @@ -0,0 +1,85 @@ + + +#ifndef _BDF_GLYPH_H +#define _BDF_GLYPH_H +#include +#include + +/* 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 + diff --git a/font/bdfconv/bdf_kern.c b/font/bdfconv/bdf_kern.c new file mode 100644 index 0000000..0c8bb01 --- /dev/null +++ b/font/bdfconv/bdf_kern.c @@ -0,0 +1,217 @@ +/* + + bdf_kern.c + +*/ + +#include "bdf_font.h" +#include + +#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); +} + diff --git a/font/bdfconv/bdf_map.c b/font/bdfconv/bdf_map.c new file mode 100644 index 0000000..50d414b --- /dev/null +++ b/font/bdfconv/bdf_map.c @@ -0,0 +1,323 @@ +/* + bdf_map.c + + select and map glyphs + + Syntax: + maplist := { "," } + mapcmd := | | + default := "*" + maprange := [ ">" ] + exclude := "~" + kern_exclude := "x" + range := [ "-" ] + num := | + hexnum := "$" { } + decnum := { } + decdigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + hexdigit := "a" | "b" | "c" | "d" | "e" | "f" | "A" | "B" | "C" | "D" | "E" | "F" | + + { }: zero, one ore more + [ ]: zero or once + |: alternative + +*/ + +#include "bdf_font.h" +#include +#include +#include +#include +#include +#include + +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; +} + diff --git a/font/bdfconv/bdf_parser.c b/font/bdfconv/bdf_parser.c new file mode 100644 index 0000000..df97721 --- /dev/null +++ b/font/bdfconv/bdf_parser.c @@ -0,0 +1,478 @@ + + +#include +#include +#include +#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; +} + diff --git a/font/bdfconv/bdf_rle.c b/font/bdfconv/bdf_rle.c new file mode 100644 index 0000000..4bf15c3 --- /dev/null +++ b/font/bdfconv/bdf_rle.c @@ -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 +#include +#include +#include +#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<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<>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<rle_bits_per_0) -1 ) + { + if ( bg_01_rle(bg, (1<rle_bits_per_0) -1, 0) == 0 ) + return 0; + a -= (1<rle_bits_per_0) -1; + } + while( b > (1<rle_bits_per_1) -1 ) + { + if ( bg_01_rle(bg, a, (1<rle_bits_per_1) -1) == 0 ) + return 0; + a = 0; + b -= (1<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); + +} + + + diff --git a/font/bdfconv/bdf_tga.c b/font/bdfconv/bdf_tga.c new file mode 100644 index 0000000..b2b129e --- /dev/null +++ b/font/bdfconv/bdf_tga.c @@ -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 +#include +#include +#include +#include +#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<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<>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; +} + + diff --git a/font/bdfconv/fd.c b/font/bdfconv/fd.c new file mode 100644 index 0000000..62efd84 --- /dev/null +++ b/font/bdfconv/fd.c @@ -0,0 +1,226 @@ +/* + + fd.c + + font decode + + (obsolete? does not support unicode) + +*/ + +#include "fd.h" +#include + + +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<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<>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; +} + + + + + diff --git a/font/bdfconv/fd.h b/font/bdfconv/fd.h new file mode 100644 index 0000000..a681ca1 --- /dev/null +++ b/font/bdfconv/fd.h @@ -0,0 +1,49 @@ + +#ifndef _FD_H +#define _FD_H + +#include + +/* 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 */ \ No newline at end of file diff --git a/font/bdfconv/main.c b/font/bdfconv/main.c new file mode 100644 index 0000000..fe4ca32 --- /dev/null +++ b/font/bdfconv/main.c @@ -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 +#include +#include +#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 Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8, 4: 5x7 mode\n"); + printf("-f 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 C output font file\n"); + printf("-k 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 X-Offset for 8x8 font sub-glyph extraction (requires -f 2, default 0)\n"); + printf("-y Y-Offset for 8x8 font sub-glyph extraction (requires -f 2, default 0)\n"); + printf("-th Horizontal size of the 8x8 glyphs (requires -f 2, default 1)\n"); + printf("-tv Vertical size of the 8x8 glyphs (requires -f 2, default 1)\n"); + + printf("-n C indentifier (font name)\n"); + printf("-d Overview picture: Enable generation of bdf.tga and assign BDF font for description\n"); + printf("-l Overview picture: Set left margin\n"); + printf("-g 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 := { \",\" }\n"); + printf("mapcmd := | | | \n"); + printf("default := \"*\"\n"); + printf("maprange := [ \">\" ] Move specified glyph to target code \n"); + printf("exclude := \"~\" \n"); + printf("exclude-kerning:= \"x\" \n"); + printf("range := [ \"-\" ] Select glyphs within specified range\n"); + printf("addexpr := [ \"+\" ]\n"); + printf("mulexpr := [ \"*\" ]\n"); + printf("num := | \n"); + printf("hexnum := \"$\" { }\n"); + printf("decnum := { }\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\" | \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; +}