altos: Fill in more of the draw code
[fw/altos] / src / draw / font-convert
index 1985e4180c65952b2b680eb3fd70cb3e9be15b8c..c7d9c780edcf92960b14e4ee578e884b4764f4c7 100755 (executable)
@@ -4,6 +4,9 @@ typedef struct {
        int[]   bytes;
        int     width;
        int     height;
+       int     x_off;
+       int     y_off;
+       int     advance;
        int     encoding;
        int     location;
 } glyph_t;
@@ -31,19 +34,24 @@ read_glyph(file f)
                        glyph.encoding = atoi(tokens[1]);
                        break;
                case "DWIDTH":
-                       glyph.width = atoi(tokens[1]);
+                       glyph.advance = atoi(tokens[1]);
                        break;
                case "BBX":
+                       glyph.width = atoi(tokens[1]);
                        glyph.height = atoi(tokens[2]);
+                       glyph.x_off = atoi(tokens[3]);
+                       glyph.y_off = glyph.height + atoi(tokens[4]);
                        break;
                case "ENDCHAR":
                        return glyph;
                case "BITMAP":
-                       while (!File::end(f)) {
+                       int byte_stride = ceil(glyph.width/8);
+                       for (int y = 0; y < glyph.height; y++) {
                                string l = fgets(f);
-                               if (l == "ENDCHAR")
-                                       return glyph;
-                               glyph.bytes[dim(glyph.bytes)] = atoi(l, 16);
+                               for (int x = 0; x < byte_stride; x++) {
+                                       string v = String::substr(l, x * 2, 2);
+                                       glyph.bytes[dim(glyph.bytes)] = atoi(v, 16);
+                               }
                        }
                        break;
                }
@@ -90,22 +98,23 @@ flip_byte(int x)
        return dest;
 }
 
-void print_font(font_t font) {
+void print_font(font_t font, string font_name) {
        int     width = font.glyphs[0].width;
        int     height = font.glyphs[0].height;
+       int     max_width = width;
+       int     max_height = height;
        int[256] pos = { -1 ... };
        int[...] bytes;
+       bool fixed_size = true;
 
-       if (false) {
        for (int i = 1; i < dim(font.glyphs); i++) {
                if (font.glyphs[i].width != width ||
                   font.glyphs[i].height != height)
                {
-                       File::fprintf(stderr, "font not constant size, glyph %d is %dx%d\n",
-                                     font.glyphs[i].encoding, font.glyphs[i].width, font.glyphs[i].height);
-                       exit(1);
+                       fixed_size = false;
                }
-       }
+               max_width = max(max_width, font.glyphs[i].width);
+               max_height = max(max_height, font.glyphs[i].height);
        }
 
        if (font.default_char == -1)
@@ -123,28 +132,89 @@ void print_font(font_t font) {
                if (pos[i] == -1)
                        pos[i] = pos[font.default_char];
 
-       printf("static const uint8_t glyph_bytes[%d] = {", dim(bytes));
+       printf("#include \"ao_draw.h\"\n");
+       printf("static const uint8_t %s_bytes[%d] = {", font_name, dim(bytes));
        for (int b = 0; b < dim(bytes); b++) {
                if ((b & 15) == 0)
                        printf("\n\t");
-               printf("0x%02x, ", flip_byte(bytes[b]));
+               else
+                       printf(" ");
+               printf("0x%02x,", flip_byte(bytes[b]));
        }
        printf("\n};\n\n");
 
-       printf("static const uint16_t glyph_pos[%d] = {", dim(pos));
+       printf("static const uint16_t %s_pos[%d] = {", font_name, dim(pos));
        for (int i = 0; i < dim(pos); i++) {
                if ((i & 7) == 0)
                        printf("\n\t");
-               printf("%4d, ", pos[i]);
+               else
+                       printf(" ");
+               printf("%6d,", pos[i]);
        }
        printf("\n};\n\n");
 
-       printf("#define GLYPH_WIDTH %d\n", width);
-       printf("#define GLYPH_HEIGHT %d\n", height);
-       printf("#define GLYPH_ASCENT %d\n", font.ascent);
+       printf("#define GLYPH_WIDTH_MAX %d\n", max_width);
+       printf("#define GLYPH_HEIGHT_MAX %d\n", max_height);
+       if (fixed_size) {
+               printf("#define GLYPH_WIDTH %d\n", width);
+               printf("#define GLYPH_HEIGHT %d\n", height);
+               printf("#define GLYPH_ASCENT %d\n", font.ascent);
+       } else {
+               printf("static const struct ao_glyph_metrics %s_metrics[%d] = {\n", font_name, dim(pos));
+               for (int i = 0; i < dim(pos); i++) {
+                       int g = 0;
+                       for (int j = 0; j < dim(font.glyphs); j++) {
+                               if (font.glyphs[j].encoding == i) {
+                                       g = j;
+                                       break;
+                               }
+                       }
+                       string c;
+                       if (' ' <= i && i <= '~')
+                               c = sprintf("%c", i);
+                       else
+                               c = sprintf("%02x", i);
+                       printf("    { .width = %d, .height = %d, .x_off = %d, .y_off = %d, .advance = %d }, /* %s */\n",
+                              font.glyphs[g].width, font.glyphs[g].height,
+                              font.glyphs[g].x_off, font.glyphs[g].y_off, font.glyphs[g].advance, c);
+               }
+               printf("};\n");
+       }
+       printf("const struct ao_font %s_font = {\n", font_name);
+       printf("\t.bytes = %s_bytes,\n", font_name);
+       printf("\t.pos = %s_pos,\n", font_name);
+       if (!fixed_size)
+               printf("\t.metrics = %s_metrics,\n", font_name);
+       printf("\t.max_width = %d,\n", max_width);
+       printf("\t.max_height = %d,\n", max_height);
+       printf("\t.ascent = %d,\n", font.ascent);
+       printf("};\n");
+}
+
+string
+to_c(string a)
+{
+       string r = "";
+       for (int i = String::rindex(a, "/") + 1; i < String::length(a); i++) {
+               int c = a[i];
+               if (c == '.')
+                       break;
+               if (!(Ctype::isalnum(c) || c == '_'))
+                       c = '_';
+               r += String::new(c);
+       }
+       if (!Ctype::isalpha(r[0]))
+               r = "_" + r;
+       return r;
 }
 
-twixt (file f = File::open(argv[1], "r"); File::close(f)) {
-       font_t font = read_font(f);
-       print_font(font);
+void
+do_font(string name)
+{
+       twixt (file f = File::open(name, "r"); File::close(f)) {
+               font_t font = read_font(f);
+               print_font(font, to_c(name));
+       }
 }
+
+do_font(argv[1]);