From 0206a5139a7e3854270e5a6b5e0c524840f84181 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 21 Jun 2025 13:50:13 -0500 Subject: [PATCH] tools: add ttf_bitmap2 --- .gitignore | 1 + font/tandy1k/BmPlus_Tandy1K-II_225L.otb | Bin 0 -> 18636 bytes font/tandy1k/tandy1k.data | Bin 0 -> 8192 bytes tools/Makefile | 3 +- tools/ttf_bitmap2.cpp | 140 ++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 font/tandy1k/BmPlus_Tandy1K-II_225L.otb create mode 100644 font/tandy1k/tandy1k.data create mode 100644 tools/ttf_bitmap2.cpp diff --git a/.gitignore b/.gitignore index 6a10363..1b5aeb2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ scramble cdi4dc tools/ttf_outline tools/ttf_bitmap +tools/ttf_bitmap2 tools/ftdi_transfer k_means_vq *.blend1 diff --git a/font/tandy1k/BmPlus_Tandy1K-II_225L.otb b/font/tandy1k/BmPlus_Tandy1K-II_225L.otb new file mode 100644 index 0000000000000000000000000000000000000000..1bd1bddc7b1ff36d6621e9045cc4a07ed4fb4d2e GIT binary patch literal 18636 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 Czd45h literal 0 HcmV?d00001 diff --git a/font/tandy1k/tandy1k.data b/font/tandy1k/tandy1k.data new file mode 100644 index 0000000000000000000000000000000000000000..abc9ce8ed781ab3e42ac8afb07c619ec2c263880 GIT binary patch literal 8192 zcmeI0TXN(e3`N^Ju=l^&x##MEu#?Grq>}k)DuqEvR}Unh^Ll+lJ6}hkTxv`YwW5vh z+2iv%uHqQ-W7w>(*Lis&eu-I`l`xV(;|z&?7`B|&&iFVO$6TC&ZjlR2cRPY-=hd9j zdCG<&NJtG)wU=DGE(Ku2X;HJv?%+jiEXkb%A3tmG;_~Yhyx5+cqD%LZ$I&&jj5I)b z?9q_I52o@)pM@9Hh1Vl-A=7h(CwX^!;FIme7x>pHpMxkNK-3*uE{H=b?Fqx0qzI70 zg^>*auGO$6_8C~gZ*%Kx`@;&v)J8mImUe#G9}L-R=WBkED_DXJ?qY@EW|hdYH5P?y zbnK7O#;TYsd_@t9i_j{>W7|d0-;l3pm4$3S_J#7{qOv1`tNIx7E$0Clgss{+mr>Ov z$(dqX9&5h@I^ZJu_%Miqc3v-OsVY(aqp+=HRjnb>)B!A8*)-+(9Q#r zM5Y%VaeGoGXfFFsVowCfS=08bC|*<54)9a=~&3g^Ks9e3)!n=P*;CCZHy?$wd-#7l%9IU(~yK&{K zQA-7-{N6!bJ^hQD@;5;6E#A8=eoY7|&kycQH{R^Dcx){Bc+Ysrooo`M4O8zsmxlT7QN-g0z+RGH*dBIqx$Zj>90emj@rH$x2+hVOOO-0>?s*W{g@6-mSk+Y34N!Xxy4l@QA^zA zO9zregxQ`Lk98!feG!9X>;Em3SkXsnjisgEfs^}6hOVRKGyj!XvjI>;{DmR>{hZYS zt~`Q2Q_48G35+8r_t=>(J?70W;%vQ>>mvHc{x$|7asDZi< z$Pm}4gEjTs +#include +#include + +#include +#include FT_FREETYPE_H + +#include "../twiddle.hpp" + +int +load_bitmap_char(FT_Face face, + FT_ULong char_code, + int buf_stride, + uint8_t * buf) +{ + FT_Error error; + FT_UInt glyph_index = FT_Get_Char_Index(face, char_code); + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) { + fprintf(stderr, "FT_Load_Glyph %s\n", FT_Error_String(error)); + return -1; + } + + assert(face->glyph->format == FT_GLYPH_FORMAT_BITMAP); + assert(face->glyph->bitmap.num_grays == 2); + + for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) { + uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch]; + for (int x = 0; x < (int)face->glyph->bitmap.width; x += 1) { + const int bit = (row[x / 8] >> (7 - (x % 8))) & 1; + //std::cerr << (bit ? "█" : " "); + buf[y * buf_stride + x] = bit; + } + //std::cerr << "|\n"; + } + + return 0; +} + +int load_font(FT_Library * library, FT_Face * face, const char * font_file_path) +{ + FT_Error error; + + error = FT_Init_FreeType(library); + if (error) { + fprintf(stderr, "FT_Init_FreeType\n"); + return -1; + } + + error = FT_New_Face(*library, font_file_path, 0, face); + if (error) { + fprintf(stderr, "FT_New_Face\n"); + return -1; + } + + error = FT_Select_Size(*face, 0); + if (error) { + fprintf(stderr, "FT_Select_Size: %d: %s\n", error, FT_Error_String(error)); + return -1; + } + + return 0; +} + +void usage(const char * argv_0) +{ + printf("%s [start-hex] [end-hex] [texture-width] [texture-height] [font-file-path] [output-file-path]\n", argv_0); +} + +int main(int argc, const char * argv[]) +{ + if (argc != 7) { + usage(argv[0]); + return -1; + } + + char * endptr; + + int start_hex = strtol(argv[1], &endptr, 16); + assert(*endptr == 0); + int end_hex = strtol(argv[2], &endptr, 16); + assert(*endptr == 0); + + int texture_width = strtol(argv[3], &endptr, 10); + assert(*endptr == 0); + int texture_height = strtol(argv[4], &endptr, 10); + assert(*endptr == 0); + + const char * font_file_path = argv[5]; + const char * output_file_path = argv[6]; + + printf("start_hex %x\n", start_hex); + printf("end_hex %x\n", start_hex); + printf("texture_width %d\n", texture_width); + printf("texture_height %d\n", texture_height); + printf("font_file_path %s\n", font_file_path); + printf("output_file_path %s\n", output_file_path); + + FT_Library library; + FT_Face face; + int res; + res = load_font(&library, &face, font_file_path); + if (res < 0) + return -1; + + int width = face->size->metrics.max_advance >> 6; + int height = face->size->metrics.height >> 6; + + int texture_buf_size = texture_width * texture_height; + uint8_t * texture = (uint8_t *)malloc(texture_buf_size); + + int x = 0; + int y = 0; + + for (int char_code = start_hex; char_code <= end_hex; char_code++) { + res = load_bitmap_char(face, + char_code, + texture_width, + &texture[y * texture_width + x]); + x += width; + if (x + width > texture_width) { + y += height; + x = 0; + assert(y + height <= texture_height); + } + } + + uint8_t * twiddle = (uint8_t *)malloc(texture_buf_size / 2); + twiddle::texture_4bpp(twiddle, texture, texture_width, texture_height); + + FILE * out = fopen(output_file_path, "w"); + if (out == NULL) { + perror("fopen(w)"); + return -1; + } + //fwrite((void *)texture, texture_buf_size, 1, out); + fwrite((void *)twiddle, texture_buf_size / 2, 1, out); + fclose(out); +}