#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <ft2build.h> #include FT_FREETYPE_H #define array_size(a) (sizeof(a) / sizeof((a)[0])) #define FONT "FiraMonoOT-Regular.otf" static FT_Library freetype; static FT_Face font_face; static _Noreturn void die(const char *fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "Error: "); vfprintf(stderr, fmt, args); va_end(args); fputc('\n', stderr); exit(1); } enum { MODE_C, MODE_84, }; static uint16_t interval_starts[128]; static uint8_t interval_sizes[128]; static int num_intervals; static uint16_t charcodes[1024]; static uint32_t bitmap_offsets[1024]; static int num_glyphs; static uint8_t bitmap_bytes[1024 * 1024]; static int num_bitmap_bytes; void write_c(void) { int fds[2]; pipe(fds); if (fork() == 0) { close(fds[1]); dup2(fds[0], 0); close(fds[0]); execlp("fmt", "fmt", "--prefix= ", (char *)NULL); } close(fds[0]); dup2(fds[1], 1); close(fds[1]); printf("static const uint16_t interval_starts[%d] = {\n\n ", num_intervals); for (int i = 0; i < num_intervals; i++) { printf("%u, ", (unsigned)interval_starts[i]); } printf("\n\n};\n\n"); printf("static const uint8_t interval_sizes[%d] = {\n\n ", num_intervals); for (int i = 0; i < num_intervals; i++) { printf("%u, ", (unsigned)interval_sizes[i]); } printf("\n\n};\n\n"); printf("static const uint16_t bitmap_offsets[%d] = {\n\n ", num_glyphs); for (int i = 0; i < num_glyphs; i++) { printf("%u, ", (unsigned)bitmap_offsets[i]); } printf("\n\n};\n\n"); printf("static const uint8_t bitmap_bytes[%d] = {\n\n ", num_bitmap_bytes); for (int i = 0; i < num_bitmap_bytes; i++) { printf("%u, ", (unsigned)bitmap_bytes[i]); } printf("\n\n};\n"); fflush(stdout); close(1); wait(NULL); } void write_84(void) { for (int i = 0; i < num_intervals;) { int begin = i; printf(" (load 0 %5d \"", begin * 2); for (; i < num_intervals && i - begin < 16; i++) { printf("%02x", (unsigned)(interval_starts[i] & 0xff)); printf("%02x", (unsigned)(interval_starts[i] >> 8)); } printf("\")\n"); } printf("\n"); for (int i = 0; i < num_intervals;) { int begin = i; printf(" (load 1 %5d \"", begin); for (; i < num_intervals && i - begin < 32; i++) { printf("%02x", (unsigned)interval_sizes[i]); } printf("\")\n"); } printf("\n"); for (int i = 0; i < num_glyphs;) { int begin = i; printf(" (load 2 %5d \"", begin * 2); for (; i < num_glyphs && i - begin < 16; i++) { printf("%02x", (unsigned)(bitmap_offsets[i] & 0xff)); printf("%02x", (unsigned)(bitmap_offsets[i] >> 8)); } printf("\")\n"); } printf("\n"); for (int i = 0; i < num_bitmap_bytes;) { int begin = i; printf(" (load 3 %5d \"", begin); for (; i < num_bitmap_bytes && i - begin < 32; i++) { printf("%02x", (unsigned)bitmap_bytes[i]); } printf("\")\n"); } printf("\n"); } int main(int argc, const char *argv[]) { int err; const char *usage = "usage: build_fira_mono_table <mode>"; if (argc != 2) die(usage); int mode; if (strcmp(argv[1], "c") == 0) mode = MODE_C; else if (strcmp(argv[1], "84") == 0) mode = MODE_84; else die(usage); err = FT_Init_FreeType(&freetype); if (err) die("Failed to initialize freetype."); err = FT_New_Face(freetype, FONT, 0, &font_face); if (err) die("Failed to open font."); err = FT_Set_Pixel_Sizes(font_face, 16, 16); if (err) die("Failed to set font size."); FT_ULong charcode; FT_UInt index; FT_GlyphSlot slot = font_face->glyph; charcode = FT_Get_First_Char(font_face, &index); while (index != 0) { bool choose = (charcode == 0) || (32 <= charcode && charcode <= 126) || (0x80 <= charcode && charcode <= 0xff) || (0x2000 <= charcode && charcode <= 0x206f) || (0x2500 <= charcode && charcode <= 0x257f) || (charcode == 0x25c9); if (choose) { charcodes[num_glyphs] = charcode; err = FT_Load_Glyph(font_face, index, FT_LOAD_RENDER); if (err) die("Failed to load glyph."); bitmap_offsets[num_glyphs] = num_bitmap_bytes; num_glyphs++; bitmap_bytes[num_bitmap_bytes++] = (uint8_t)slot->bitmap_top; bitmap_bytes[num_bitmap_bytes++] = (uint8_t)slot->bitmap_left; bitmap_bytes[num_bitmap_bytes++] = (uint8_t)slot->bitmap.rows; bitmap_bytes[num_bitmap_bytes++] = (uint8_t)slot->bitmap.width; int num_pixels = slot->bitmap.rows * slot->bitmap.width; for (int i = 0; i < num_pixels; i++) bitmap_bytes[num_bitmap_bytes++] = slot->bitmap.buffer[i]; } charcode = FT_Get_Next_Char(font_face, charcode, &index); } if (num_glyphs > 0) { interval_starts[0] = charcodes[0]; interval_sizes[0] = 1; for (int i = 1; i < num_glyphs; i++) { if (charcodes[i - 1] + 1 != charcodes[i]) { num_intervals++; interval_starts[num_intervals] = charcodes[i]; } interval_sizes[num_intervals]++; } num_intervals++; } if (mode == MODE_C) write_c(); else if (mode == MODE_84) write_84(); return 0; }