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 0000000..1bd1bdd Binary files /dev/null and b/font/tandy1k/BmPlus_Tandy1K-II_225L.otb differ diff --git a/font/tandy1k/tandy1k.data b/font/tandy1k/tandy1k.data new file mode 100644 index 0000000..abc9ce8 Binary files /dev/null and b/font/tandy1k/tandy1k.data differ diff --git a/tools/Makefile b/tools/Makefile index 1b811fa..9228609 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,8 +1,7 @@ -CFLAGS = -Og -g -gdwarf-4 -Wall -Wextra -Wno-error +CFLAGS = -Og -g -gdwarf-4 -Wall -Wextra -Wno-error -Wfatal-errors CFLAGS += -Wno-error=unused-parameter CFLAGS += -Wno-error=unused-variable CFLAGS += -Wno-error=unused-but-set-variable -CFLAGS += -Wno-vla-extension CXXFLAGS = -std=c++23 PREFIX ?= /usr/local diff --git a/tools/ttf_bitmap2.cpp b/tools/ttf_bitmap2.cpp new file mode 100644 index 0000000..0797be0 --- /dev/null +++ b/tools/ttf_bitmap2.cpp @@ -0,0 +1,140 @@ +#include +#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); +}