chiark / gitweb /
Generate stem hints
authorBen Harris <bjh21@bjh21.me.uk>
Sat, 9 Nov 2024 23:51:36 +0000 (23:51 +0000)
committerBen Harris <bjh21@bjh21.me.uk>
Thu, 14 Nov 2024 22:27:18 +0000 (22:27 +0000)
These are generated from the glyph bitmap by a similar
pattern-matching arrangement that generates the outline.  Then, like
emit_path(), there's an emit_hints() that turns them into valid
charstrings.  The handling of overlapping hints could be cleverer: at
the moment we emit the leftmost-possible set of hints, but we collect
a histogram of where hints are needed so could instead emit the most
useful.  Or even try to do hint substitution.

This makes the Bedstead Web page at 90% zoom much prettier than
before, but it's not as good as the FontForge auto-hinter managed.
Edge hints and counter hints will probably help.

bedstead.c

index 0de87ff20ec4dcdbfb1c7f7bc50a64d20e11cb00..7522b6e3602cbf5c552209c20e2cfccc9adc5c91 100644 (file)
@@ -3746,6 +3746,43 @@ emit_path(void)
        printf(" endchar");
 }
 
+static void
+emit_hints(int vstems[XSIZE], int hstems[YSIZE])
+{
+       int i, start, size, cur;
+       bool printed;
+
+       cur = 0; printed = false;
+       size = XPIX_S + weight->weight;
+       for (i = 0; i < XSIZE; i++) {
+               if (vstems[i] > 0) {
+                       start = i * XPIX_S - weight->weight;
+                       printf(" %g %g",
+                              (double)((start - cur) / XSCALE),
+                              (double)(size / XSCALE));
+                       cur = start + size;
+                       i++; /* Avoid overlapping stems. */
+                       printed = true;
+               }
+       }
+       if (printed) printf(" vstem");
+
+       cur = DESCENT * YPIX; printed = false;
+       size = YPIX_S;
+       for (i = YSIZE - 1; i >= 0; i--) {
+               if (hstems[i] > 0) {
+                       start = (YSIZE - i - 1) * YPIX_S;
+                       printf(" %g %g",
+                              (double)((start - cur) / YSCALE),
+                              (double)(size / YSCALE));
+                       cur = start + size;
+                       i--; /* Avoid overlapping stems. */
+                       printed = true;
+               }
+       }
+       if (printed) printf(" hstem");
+}
+
 /*
  * To vary the weight of Bedstead, we just vary the thickness of
  * vertical strokes.  More precisely, we pretend that the weight
@@ -3883,6 +3920,7 @@ static void
 dochar(struct glyph *g)
 {
        int x, y;
+       int vstems[XSIZE], hstems[YSIZE];
 
 #define GETPIX(x,y) (getpix(g->data, (x), (y), g->flags))
 #define L GETPIX(x-1, y)
@@ -3894,6 +3932,8 @@ dochar(struct glyph *g)
 #define DL GETPIX(x-1, y+1)
 #define DR GETPIX(x+1, y+1)
 
+       for (x = 0; x < XSIZE; x++) vstems[x] = 0;
+       for (y = 0; y < YSIZE; y++) hstems[y] = 0;
        clearpath();
        for (x = 0; x < XSIZE; x++) {
                for (y = 0; y < YSIZE; y++) {
@@ -3913,6 +3953,14 @@ dochar(struct glyph *g)
                                if (L || DL || D) bl = true;
                                if (R || DR || D) br = true;
                                blackpixel(x, YSIZE - y - 1, bl, br, tr, tl);
+                               if (!L && !R && (U || D))
+                                       vstems[x]++;
+                               if (!U && !D && (L || R))
+                                       hstems[y]++;
+                               if (UL + U + UR + L + R + DL + D + DR == 0) {
+                                       vstems[x]++;
+                                       hstems[y]++;
+                               }
                        } else {
                                bool tl, tr, bl, br;
 
@@ -3930,6 +3978,7 @@ dochar(struct glyph *g)
        clean_path();
        adjust_weight();
        record_lsb(g);
+       emit_hints(vstems, hstems);
        emit_path();
 }