chiark / gitweb /
Mechanisms to get metadata right for different weights of font.
authorBen Harris <bjh21@bjh21.me.uk>
Tue, 1 Aug 2017 22:27:22 +0000 (23:27 +0100)
committerBen Harris <bjh21@bjh21.me.uk>
Tue, 1 Aug 2017 22:27:22 +0000 (23:27 +0100)
bedstead.c can now generate Bedstead Book (and all other widths at
that weight).

bedstead.c

index 4ade039a41906c427ba396d1e0fd835187583652..722410d3712683bb69ace95450c6703e3469ef52 100644 (file)
 
 static struct width {
        char const * option;
-       char const * fullname;
+       char const * suffix;
        int xpix;
        int ttfwidth;
 } const widths[] = {
        {
                "--normal",
-               "Bedstead",
+               "",
                100,            /* xpix */
                5,              /* ttfwidth */
        },
        {
                "--ultra-condensed",
-               "Bedstead Ultra Condensed",
+               " Ultra Condensed",
                50,             /* xpix */
                1,              /* ttfwidth */
        },
        {
                "--extra-condensed",
-               "Bedstead Extra Condensed",
+               " Extra Condensed",
                62,             /* xpix */
                2,              /* ttfwidth */
        },
        {
                "--condensed",
-               "Bedstead Condensed",
+               " Condensed",
                76,             /* xpix */
                3,              /* ttfwidth */
        },
        {
                "--semi-condensed",
-               "Bedstead Semi Condensed",
+               " Semi Condensed",
                88,             /* xpix */
                4,              /* ttfwidth */
        },
        {
                "--extended",
-               "Bedstead Extended",
+               " Extended",
                124,            /* xpix */
                7,              /* ttfwidth */
        },
@@ -172,6 +172,30 @@ static int const nwidths = sizeof(widths) / sizeof(widths[0]);
 
 struct width const *width = &widths[0];
 
+static struct weight {
+       char const *option;
+       char const *suffix;
+       int weight; /* Expressed in internal units */
+       int ttfweight;
+} const weights[] = {
+       {
+               "--medium",
+               "",
+               0,
+               500,
+       },
+       {
+               "--book",
+               " Book",
+               -25,
+               400,
+       },
+};
+
+static int const nweights = sizeof(weights) / sizeof(weights[0]);
+
+struct weight const *weight = &weights[0];
+
 /* Size of output pixels in font design units (usually 1000/em) */
 #define XPIX (width->xpix)
 #define YPIX 100
@@ -1263,6 +1287,15 @@ getpix(char const data[YSIZE], int x, int y, unsigned flags)
 
 static bool plottermode = false;
 
+static char * get_fullname()
+{
+#define FULLNAME_MAX 100
+       static char fullname[FULLNAME_MAX];
+
+       sprintf(fullname, "Bedstead%s%s", weight->suffix, width->suffix);
+       return fullname;
+}
+
 static char * fullname_to_fontname(char const *fullname)
 {
 #define FONTNAME_MAX 29 /* Adobe-recommended limit */
@@ -1298,7 +1331,6 @@ main(int argc, char **argv)
                return 0;
        }
              
-       
        while (argc > 1) {
                for (i = 0; i < nwidths; i++)
                        if (strcmp(argv[1], widths[i].option) == 0) {
@@ -1306,6 +1338,12 @@ main(int argc, char **argv)
                                argv++; argc--;
                                goto next;
                        }
+               for (i = 0; i < nweights; i++)
+                       if (strcmp(argv[1], weights[i].option) == 0) {
+                               weight = &weights[i];
+                               argv++; argc--;
+                               goto next;
+                       }
                if (strcmp(argv[1], "--plotter") == 0) {
                        plottermode = true;
                        argv++; argc--;
@@ -1350,10 +1388,10 @@ main(int argc, char **argv)
                if (glyphs[i].unicode == -1)
                        extraglyphs++;
        printf("SplineFontDB: 3.0\n");
-       printf("FontName: %s\n", fullname_to_fontname(width->fullname));
-       printf("FullName: %s\n", width->fullname);
+       printf("FontName: %s\n", fullname_to_fontname(get_fullname()));
+       printf("FullName: %s\n", get_fullname());
        printf("FamilyName: Bedstead\n");
-       printf("Weight: Medium\n");
+       printf("Weight:%s\n", weight->suffix[0] ? weight->suffix : " Medium");
        printf("OS2_WeightWidthSlopeOnly: 1\n");
        printf("Copyright: Dedicated to the public domain\n");
        printf("Version: 001.003\n");
@@ -1374,7 +1412,7 @@ main(int argc, char **argv)
        printf("OS2SubYOff: %d\n", 2 * YPIX);
        printf("OS2SupYOff: %d\n", 2 * YPIX);
        printf("FSType: 0\n");
-       printf("TTFWeight: 500\n");
+       printf("TTFWeight: %d\n", weight->ttfweight);
        printf("TTFWidth: %d\n", width->ttfwidth);
        dopanose();
        printf("OS2FamilyClass: %d\n", 0x080a);
@@ -1392,7 +1430,7 @@ main(int argc, char **argv)
        }
        printf("BeginPrivate: 2\n");
        printf(" StdHW 5 [%d]\n", YPIX);
-       printf(" StdVW 5 [%d]\n", XPIX);
+       printf(" StdVW 5 [%d]\n", XPIX * (100 + weight->weight) / 100);
        printf("EndPrivate\n");
        /* Force monochrome at 10 and 20 pixels, and greyscale elsewhere. */
        printf("GaspTable: 5 9 2 10 0 19 3 20 0 65535 3\n");
@@ -1459,25 +1497,27 @@ dopanose()
         * See <http://panose.com> for the full details.
         */
        int panose[10];
+       int stdvw;
        /* Common digits */
-       /* WeightRat == 700/XPIX */
-       if (XPIX <= 20) /* WeightRat >= 35 */
+       /* WeightRat == 700/StdVW */
+       stdvw = XPIX * (100 + weight->weight) / 100;
+       if (stdvw <= 20) /* WeightRat >= 35 */
                panose[2] = 2; /* Very Light */
-       else if (XPIX < 39) /* WeightRat > 17.9 */
+       else if (stdvw < 39) /* WeightRat > 17.9 */
                panose[2] = 3; /* Light */
-       else if (XPIX <= 70) /* WeightRat >= 10 */
+       else if (stdvw <= 70) /* WeightRat >= 10 */
                panose[2] = 4; /* Thin */
-       else if (XPIX <= 94) /* WeightRat > 7.44 */
+       else if (stdvw <= 94) /* WeightRat > 7.44 */
                panose[2] = 5; /* Book */
-       else if (XPIX < 128) /* WeightRat > 5.5 */
+       else if (stdvw < 128) /* WeightRat > 5.5 */
                panose[2] = 6; /* Medium */
-       else if (XPIX < 156) /* WeightRat > 4.5 */
+       else if (stdvw < 156) /* WeightRat > 4.5 */
                panose[2] = 7; /* Demi */
-       else if (XPIX <= 200) /* WeightRat >= 3.5 */
+       else if (stdvw <= 200) /* WeightRat >= 3.5 */
                panose[2] = 8; /* Bold */
-       else if (XPIX <= 280) /* WeightRat >= 2.5 */
+       else if (stdvw <= 280) /* WeightRat >= 2.5 */
                panose[2] = 9; /* Heavy */
-       else if (XPIX <= 350) /* WeightRat >= 2.0 */
+       else if (stdvw <= 350) /* WeightRat >= 2.0 */
                panose[2] = 10; /* Black */
        else
                panose[2] = 11; /* Extra Black */
@@ -1485,20 +1525,20 @@ dopanose()
         * To make life simpler, ignore diagonals when calculating
         * ConRat.
         */
-       /* ConRat == min(XPIX / 100, 100 / XPIX) */
-       if (XPIX > 80 && XPIX < 125)
+       /* ConRat == min(StdVW / 100, 100 / StdVW) */
+       if (stdvw > 80 && stdvw < 125)
                panose[4] = 2; /* None */
-       else if (XPIX > 65 && XPIX < 154)
+       else if (stdvw > 65 && stdvw < 154)
                panose[4] = 3; /* Very Low */
-       else if (XPIX > 48 && XPIX < 209)
+       else if (stdvw > 48 && stdvw < 209)
                panose[4] = 4; /* Low */
-       else if (XPIX > 30 && XPIX < 334)
+       else if (stdvw > 30 && stdvw < 334)
                panose[4] = 5; /* Medium Low */
-       else if (XPIX > 20 && XPIX < 500)
+       else if (stdvw > 20 && stdvw < 500)
                panose[4] = 6; /* Medium */
-       else if (XPIX > 15 && XPIX < 667)
+       else if (stdvw > 15 && stdvw < 667)
                panose[4] = 7; /* Medium High */
-       else if (XPIX > 8 && XPIX < 1250)
+       else if (stdvw > 8 && stdvw < 1250)
                panose[4] = 8; /* High */
        else
                panose[4] = 9; /* Very High */
@@ -1507,7 +1547,7 @@ dopanose()
         * PANOSE says that fonts with horizontal stress and extreme
         * aspect ratios should be classified as decorative.
         */
-       if (XPIX < 100 || /* ConRat > 1.00 */
+       if (stdvw < 100 || /* ConRat > 1.00 */
            XPIX > 164) { /* ORat < 0.85 */
                panose[0] = 4; /* Latin Decorative */
                panose[1] = 2; /* Derivative */
@@ -1538,13 +1578,14 @@ dopanose()
                panose[3] = 9; /* Monospaced */
                if (panose[4] == 2)
                        panose[5] = 2; /* No Variation */
-               else if (XPIX > 100)
+               else if (stdvw > 100)
                        panose[5] = 5; /* Gradual/Vertical */
                else
                        panose[5] = 6; /* Gradual/Hoizontal */
                /* Unusually shaped 'A' means no fit here. */
                panose[6] = 1; /* No Fit */
                /* OutCurv == 0.791 */
+               /* FIXME: Only correct for weight == 0 */
                panose[7] = 5; /* Normal/Boxed */
                panose[8] = 3; /* Standard/Pointed */
                panose[9] = 7; /* Ducking/Large */
@@ -1851,8 +1892,6 @@ emit_path()
  * don't run out of slack in horizontal lines, which limits weight to
  * the range (-0.5 * XPIX) < weight < (0.25 * XPIX).
  */
-static int weight = 0;
-
 static void
 adjust_weight()
 {
@@ -1865,18 +1904,18 @@ adjust_weight()
                assert(p->prev != NULL);
                /* Move left-edge points horizontally */
                if (p->prev->v.y <= p->v.y && p->v.y <= p->next->v.y)
-                       p->v.x -= weight;
+                       p->v.x -= weight->weight;
                /* Move top inner corner points along NE/SW diagonal */
                if (p->prev->v.y < p->v.y && p->v.y > p->next->v.y &&
                    p->prev->v.x > p->v.x && p->v.x > p->next->v.x) {
-                       p->v.x -= weight/2;
-                       p->v.y -= weight/2;
+                       p->v.x -= weight->weight/2;
+                       p->v.y -= weight->weight/2;
                }
                /* Move bottom inner corner points along NW/SE diagonal */
                if (p->prev->v.y > p->v.y && p->v.y < p->next->v.y &&
                    p->prev->v.x < p->v.x && p->v.x < p->next->v.x) {
-                       p->v.x -= weight/2;
-                       p->v.y += weight/2;
+                       p->v.x -= weight->weight/2;
+                       p->v.y += weight->weight/2;
                }
        }
 }