26 glyph_t glyph = { .encoding = -1, .bytes = (int[...]){}, .width = 0 };
28 while (!File::end(f)) {
31 string[*] tokens = String::split(l, " ");
37 glyph.encoding = atoi(tokens[1]);
40 glyph.advance = atoi(tokens[1]);
43 glyph.width = atoi(tokens[1]);
44 glyph.height = atoi(tokens[2]);
45 glyph.x_off = atoi(tokens[3]);
46 glyph.y_off = glyph.height + atoi(tokens[4]);
51 int byte_stride = ceil(glyph.width/8);
52 for (int y = 0; y < glyph.height; y++) {
54 for (int x = 0; x < byte_stride; x++) {
55 string v = String::substr(l, x * 2, 2);
56 glyph.bytes[dim(glyph.bytes)] = atoi(v, 16);
65 font_t read_font(file f) {
66 font_t font = { .glyphs = {}, .default_char = -1 };
69 while (in_head && !File::end(f)) {
70 string l = File::fgets(f);
72 string[*] tokens = String::split(l, " ");
75 font.default_char = atoi(tokens[1]);
78 font.ascent = atoi(tokens[1]);
85 while (!File::end(f)) {
86 glyph_t glyph = read_glyph(f);
87 if (glyph.encoding == -1)
89 font.glyphs[dim(font.glyphs)] = glyph;
99 for (int i = 0; i < 8; i++)
100 dest |= ((x >> (7 - i)) & 1) << i;
104 void print_font(file out, font_t font, string font_name) {
105 int width = font.glyphs[0].width;
106 int height = font.glyphs[0].height;
107 int max_width = width;
108 int max_height = height;
109 int[128] pos = { 0 ... };
111 bool fixed_size = true;
113 for (int i = 1; i < dim(font.glyphs); i++) {
114 if (font.glyphs[i].width != width ||
115 font.glyphs[i].height != height)
119 max_width = max(max_width, font.glyphs[i].width);
120 max_height = max(max_height, font.glyphs[i].height);
123 if (font.default_char == -1)
124 font.default_char = font.glyphs[0].encoding;
126 /* build byte array */
127 for (int i = 0; i < dim(font.glyphs); i++) {
128 if (font.glyphs[i].encoding < dim(pos))
130 pos[font.glyphs[i].encoding] = dim(bytes);
131 for (int b = 0; b < dim(font.glyphs[i].bytes); b++)
132 bytes[dim(bytes)] = font.glyphs[i].bytes[b];
136 /* Fill in default glyph */
137 for (int i = 0; i < dim(pos); i++)
139 pos[i] = pos[font.default_char];
141 fprintf(out, "#include <ao_draw.h>\n");
142 fprintf(out, "static const uint8_t %s_bytes[%d] = {", font_name, dim(bytes));
143 for (int b = 0; b < dim(bytes); b++) {
145 fprintf(out, "\n\t");
148 fprintf(out, "0x%02x,", flip_byte(bytes[b]));
150 fprintf(out, "\n};\n\n");
152 fprintf(out, "static const uint16_t %s_pos[%d] = {", font_name, dim(pos));
153 for (int i = 0; i < dim(pos); i++) {
155 fprintf(out, "\n\t");
158 fprintf(out, "%6d,", pos[i]);
160 fprintf(out, "\n};\n\n");
162 fprintf(out, "#define GLYPH_WIDTH_MAX %d\n", max_width);
163 fprintf(out, "#define GLYPH_HEIGHT_MAX %d\n", max_height);
165 fprintf(out, "#define GLYPH_WIDTH %d\n", width);
166 fprintf(out, "#define GLYPH_HEIGHT %d\n", height);
167 fprintf(out, "#define GLYPH_ASCENT %d\n", font.ascent);
169 fprintf(out, "static const struct ao_glyph_metrics %s_metrics[%d] = {\n", font_name, dim(pos));
170 for (int i = 0; i < dim(pos); i++) {
172 for (int j = 0; j < dim(font.glyphs); j++) {
173 if (font.glyphs[j].encoding == i) {
179 if (' ' <= i && i <= '~')
180 c = sprintf("%c", i);
182 c = sprintf("%02x", i);
183 fprintf(out, " { .width = %d, .height = %d, .x_off = %d, .y_off = %d, .advance = %d }, /* %s */\n",
184 font.glyphs[g].width, font.glyphs[g].height,
185 font.glyphs[g].x_off, font.glyphs[g].y_off, font.glyphs[g].advance, c);
187 fprintf(out, "};\n");
189 fprintf(out, "const struct ao_font %s_font = {\n", font_name);
190 fprintf(out, "\t.bytes = %s_bytes,\n", font_name);
191 fprintf(out, "\t.pos = %s_pos,\n", font_name);
193 fprintf(out, "\t.metrics = %s_metrics,\n", font_name);
194 fprintf(out, "\t.max_width = %d,\n", max_width);
195 fprintf(out, "\t.max_height = %d,\n", max_height);
196 fprintf(out, "\t.ascent = %d,\n", font.ascent);
197 fprintf(out, "};\n");
204 for (int i = String::rindex(a, "/") + 1; i < String::length(a); i++) {
208 if (!(Ctype::isalnum(c) || c == '_'))
212 if (!Ctype::isalpha(r[0]))
218 do_font(string name, file out)
220 twixt (file f = File::open(name, "r"); File::close(f)) {
221 font_t font = read_font(f);
222 print_font(out, font, to_c(name));
229 .var = (arg_var.arg_string) &(string output),
233 .desc = "Output file name"
238 var = (arg_var.arg_string) &(string input),
244 parseargs(&argd, &argv)
246 if (is_uninit(&output))
247 do_font(input, stdout);
249 twixt(file f = File::open(output, "w"); File::close(f))