chiark / gitweb /
Record proper left sidebearings in 'hmtx' table
authorBen Harris <bjh21@bjh21.me.uk>
Sun, 3 Nov 2024 17:37:44 +0000 (17:37 +0000)
committerBen Harris <bjh21@bjh21.me.uk>
Thu, 14 Nov 2024 22:27:18 +0000 (22:27 +0000)
That change was more invasive than I was expecting.

bedstead.c

index 706adf1b191d83e95eab4e33b794d3e616106aa9..f70f601c0ecf1298fadc1246da08b6f1381905b5 100644 (file)
@@ -213,6 +213,7 @@ static struct glyph {
 #define SEP4 (SEP | MOS4)
 #define IS_ALIAS 0x08
 #define IS_SUBR  0x10
+       uint_least16_t left_sidebearing; /* Set when outline generated. */
 } glyphs[] = {
  /*
   * The first batch of glyphs comes from the code tables at the end of
@@ -2619,16 +2620,16 @@ static int const nglyphs = NGLYPHS;
 
 static struct glyph const *glyphs_by_name[NGLYPHS];
 
-static void dochar(char const data[YSIZE], unsigned flags);
-static void dochar_plotter(char const data[YSIZE], unsigned flags);
-static void domosaic(unsigned code, bool sep);
-static void domosaic4(unsigned code, bool sep);
+static void dochar(struct glyph *g);
+static void dochar_plotter(struct glyph *g);
+static void domosaic(struct glyph *g);
+static void domosaic4(struct glyph *g);
 static void dopanose(void);
 static void docmap(int pid, int eid, int format);
 static void glyph_complement(void);
 static void bdf_gen(int size);
-static void dolookups(struct glyph const *);
-static void doglyph(struct glyph const *);
+static void dolookups(struct glyph *);
+static void doglyph(struct glyph *);
 
 static bool
 getpix(char const data[YSIZE - 1], int x, int y, unsigned flags)
@@ -2739,6 +2740,13 @@ get_glyph_by_name(char const *name)
        return *gp;
 }
 
+static struct glyph *
+realglyph(struct glyph *g)
+{
+       while (g->flags & IS_ALIAS) g = get_glyph_by_name(g->alias_of);
+       return g;
+}
+
 /*
  * Compare glyphs in a way that will put them in an order that
  * FontForge wouldn't change.  We don't actually use FontForge any
@@ -2819,12 +2827,12 @@ main(int argc, char **argv)
        }
 
        if (argc > 1) {
-               char data[YSIZE];
+               struct glyph g = { .flags = 0 };
                int i, y;
                unsigned long u;
 
-               for (y = 0; y < YSIZE; y++)
-                       data[y] = 0;
+               for (y = 0; y < YSIZE - 1; y++)
+                       g.data[y] = 0;
 
                y = 0;
                for (i = 1; i < argc; i++) {
@@ -2838,9 +2846,9 @@ main(int argc, char **argv)
                                        argv[i]);
                                return EXIT_FAILURE;
                        }
-                       data[y++] = u;
+                       g.data[y++] = u;
                }
-               dochar(data, 0);
+               dochar(&g);
                return EXIT_SUCCESS;
        }
 
@@ -3082,8 +3090,7 @@ main(int argc, char **argv)
        for (i = 0; i < nglyphs; i++) {
                struct glyph *g = &glyphs[i];
                if (g->flags & IS_ALIAS) {
-                       while (g->flags & IS_ALIAS)
-                               g = get_glyph_by_name(g->alias_of);
+                       g = realglyph(g);
                        if (g->flags & IS_SUBR) continue;
                        printf("     <CharString> <!-- %s -->", g->name);
                        doglyph(g);
@@ -3110,7 +3117,8 @@ main(int argc, char **argv)
        printf(" <hmtx>\n");
        for (i = 0; i < nglyphs; i++)
                printf("  <mtx name='%s' width='%d' lsb='%d'/>\n",
-                      glyphs[i].name, (int)(XSIZE * XPIX), 0 /* XXX */);       
+                      glyphs[i].name, (int)(XSIZE * XPIX),
+                      (int)realglyph(&glyphs[i])->left_sidebearing);
        printf(" </hmtx>\n");
        printf("</ttFont>\n");
        return EXIT_SUCCESS;
@@ -3290,33 +3298,31 @@ docmap(int pid, int eid, int format)
 
 /* Emit a charstring for a glyph. */
 static void
-doglyph(struct glyph const *g)
+doglyph(struct glyph *g)
 {
 
-       while (g->flags & IS_ALIAS)
-               g = get_glyph_by_name(g->alias_of);
+       g = realglyph(g);
        if (g->flags & IS_SUBR)
                printf(" %d callsubr",
                       g->subr_idx - (nsubrs < 1240 ? 107 : 1131));
        else if (g->flags & MOS6)
-               domosaic(g->data[0], (g->flags & SEP) != 0);
+               domosaic(g);
        else if (g->flags & MOS4)
-               domosaic4(g->data[0], (g->flags & SEP) != 0);
+               domosaic4(g);
        else if (plottermode)
-               dochar_plotter(g->data, g->flags);
+               dochar_plotter(g);
        else
-               dochar(g->data, g->flags);
+               dochar(g);
 }
 
 static void
-dopalt(struct glyph const *g)
+dopalt(struct glyph *g)
 {
        int i;
        unsigned char cols = 0;
        int dx = 0, dh = 0;
 
-       while (g->flags & IS_ALIAS)
-               g = get_glyph_by_name(g->alias_of);
+       g = realglyph(g);
        if (g->flags & (MOS6|MOS4)) return;
        /*
         * For proportional layout, we'd like a left side-bearing of
@@ -3344,7 +3350,7 @@ dopalt(struct glyph const *g)
 
 
 static void
-dolookups(struct glyph const *g)
+dolookups(struct glyph *g)
 {
        char prefix[32];
        struct glyph const **found, **gp;
@@ -3742,11 +3748,26 @@ whitepixel(int x, int y, bool bl, bool br, bool tr, bool tl)
 }
 
 static void
-dochar(char const data[YSIZE], unsigned flags)
+record_lsb(struct glyph *g)
+{
+       int i;
+       int lsb = XPIX_S * XSIZE;
+
+       for (i = 0; i < nextpoint; i++) {
+               if (points[i].next == NULL) continue;
+               if (points[i].v.x < lsb) lsb = points[i].v.x;
+       }
+       /* A glyph with no contours has an lsb of zero. */
+       if (lsb < XPIX_S * XSIZE)
+               g->left_sidebearing = lsb / XSCALE;
+}
+
+static void
+dochar(struct glyph *g)
 {
        int x, y;
 
-#define GETPIX(x,y) (getpix(data, (x), (y), flags))
+#define GETPIX(x,y) (getpix(g->data, (x), (y), g->flags))
 #define L GETPIX(x-1, y)
 #define R GETPIX(x+1, y)
 #define U GETPIX(x, y-1)
@@ -3791,6 +3812,7 @@ dochar(char const data[YSIZE], unsigned flags)
        }
        clean_path();
        adjust_weight();
+       record_lsb(g);
        emit_path();
 }
 
@@ -3883,7 +3905,7 @@ clean_skeleton()
 }
 
 static void
-dochar_plotter(char const data[YSIZE], unsigned flags)
+dochar_plotter(struct glyph *g)
 {
        int x, y;
 
@@ -3922,8 +3944,10 @@ tile(int x0, int y0, int x1, int y1)
 }
        
 static void
-domosaic(unsigned code, bool sep)
+domosaic(struct glyph *g)
 {
+       unsigned code = g->data[0];
+       bool sep = (g->flags & SEP) != 0;
 
        clearpath();
        if (code & 1)  tile(0 + sep, 7 + sep, 3, 10);
@@ -3933,12 +3957,15 @@ domosaic(unsigned code, bool sep)
        if (code & 16) tile(0 + sep, 0 + sep, 3, 3);
        if (code & 32) tile(3 + sep, 0 + sep, 6, 3);
        clean_path();
+       record_lsb(g);
        emit_path();
 }
 
 static void
-domosaic4(unsigned code, bool sep)
+domosaic4(struct glyph *g)
 {
+       unsigned code = g->data[0];
+       bool sep = (g->flags & SEP) != 0;
 
        clearpath();
        if (code & 1) tile(0 + sep, 5 + sep, 3, 10);
@@ -3946,6 +3973,7 @@ domosaic4(unsigned code, bool sep)
        if (code & 4) tile(0 + sep, 0 + sep, 3, 5);
        if (code & 8) tile(3 + sep, 0 + sep, 6, 5);
        clean_path();
+       record_lsb(g);
        emit_path();
 }