From: Ben Harris Date: Wed, 28 Jun 2017 21:15:02 +0000 (+0100) Subject: Generate PANOSE classification. X-Git-Tag: bedstead-001.003~29 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~bjharris/git?a=commitdiff_plain;h=4ca14615e4e0d004faf26eb16780ed212f2e9384;p=bedstead.git Generate PANOSE classification. This is a mandatory part of the 'OS/2' table, so we may as well get it right. Gratuitously generalised across all possible character widths. --- diff --git a/bedstead.c b/bedstead.c index c9e445b..832a95c 100644 --- a/bedstead.c +++ b/bedstead.c @@ -157,6 +157,7 @@ struct param *param = &default_param; void doprologue(void); void dochar(char const data[YSIZE], unsigned flags); static void domosaic(unsigned code, bool sep); +static void dopanose(); struct glyph { char data[YSIZE]; @@ -1263,6 +1264,7 @@ main(int argc, char **argv) printf("OS2SubYOff: %d\n", 2 * YPIX); printf("OS2SupYOff: %d\n", 2 * YPIX); printf("TTFWidth: %d\n", param->ttfwidth); + dopanose(); printf("LayerCount: 2\n"); printf("Layer: 0 0 \"Back\" 1\n"); printf("Layer: 1 0 \"Fore\" 0\n"); @@ -1323,6 +1325,114 @@ main(int argc, char **argv) return 0; } +static void +dopanose() +{ + /* + * PANOSE is a complex font categorisation scheme. I suspect + * no-one uses it, but it's a mandatory part of the 'OS/2' + * table, so it would be nice to get it right. This procedure + * calculates the PANOSE code for a Bedstead variant based on + * its design parameters. + * + * See for the full details. + */ + int panose[10]; + /* Common digits */ + /* WeightRat == 700/XPIX */ + if (XPIX <= 20) /* WeightRat >= 35 */ + panose[2] = 2; /* Very Light */ + else if (XPIX < 39) /* WeightRat > 17.9 */ + panose[2] = 3; /* Light */ + else if (XPIX <= 70) /* WeightRat >= 10 */ + panose[2] = 4; /* Thin */ + else if (XPIX <= 94) /* WeightRat > 7.44 */ + panose[2] = 5; /* Book */ + else if (XPIX < 128) /* WeightRat > 5.5 */ + panose[2] = 6; /* Medium */ + else if (XPIX < 156) /* WeightRat > 4.5 */ + panose[2] = 7; /* Demi */ + else if (XPIX <= 200) /* WeightRat >= 3.5 */ + panose[2] = 8; /* Bold */ + else if (XPIX <= 280) /* WeightRat >= 2.5 */ + panose[2] = 9; /* Heavy */ + else if (XPIX <= 350) /* WeightRat >= 2.0 */ + panose[2] = 10; /* Black */ + else + panose[2] = 11; /* Extra Black */ + /* + * To make life simpler, ignore diagonals when calculating + * ConRat. + */ + /* ConRat == min(XPIX / 100, 100 / XPIX) */ + if (XPIX > 80 && XPIX < 125) + panose[4] = 2; /* None */ + else if (XPIX > 65 && XPIX < 154) + panose[4] = 3; /* Very Low */ + else if (XPIX > 48 && XPIX < 209) + panose[4] = 4; /* Low */ + else if (XPIX > 30 && XPIX < 334) + panose[4] = 5; /* Medium Low */ + else if (XPIX > 20 && XPIX < 500) + panose[4] = 6; /* Medium */ + else if (XPIX > 15 && XPIX < 667) + panose[4] = 7; /* Medium High */ + else if (XPIX > 8 && XPIX < 1250) + panose[4] = 8; /* High */ + else + panose[4] = 9; /* Very High */ + /* + * First digit is overall style. Bedstead is a text font, but + * PANOSE says that fonts with horizontal stress and extreme + * aspect ratios should be classified as decorative. + */ + if (XPIX < 100 || /* ConRat > 1.00 */ + XPIX > 164) { /* ORat < 0.85 */ + panose[0] = 4; /* Latin Decorative */ + panose[1] = 2; /* Derivative */ + /* ORat == 140/XPIX */ + if (XPIX <= 53) + panose[3] = 2; /* Super Condensed */ + else if (XPIX <= 66) + panose[3] = 3; /* Very Condensed */ + else if (XPIX <= 110) + panose[3] = 4; /* Condensed */ + else if (XPIX <= 152) + panose[3] = 5; /* Normal */ + else if (XPIX <= 155) + panose[3] = 6; /* Extended */ + else if (XPIX <= 164) + panose[3] = 7; /* Very Extended */ + else + panose[3] = 8; /* Super Extended */ + panose[5] = 11; /* Normal Sans Serif */ + panose[6] = 2; /* Standard Solid Fill */ + panose[7] = 2; /* No Lining */ + panose[8] = 3; /* Square */ + panose[9] = 2; /* Extended Collection */ + } else { + panose[0] = 2; /* Latin Text */ + panose[1] = 11; /* Normal Sans Serif */ + /* J and M are the same width. */ + panose[3] = 9; /* Monospaced */ + if (panose[4] == 2) + panose[5] = 2; /* No Variation */ + else if (XPIX > 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 */ + panose[7] = 5; /* Normal/Boxed */ + panose[8] = 3; /* Standard/Pointed */ + panose[9] = 7; /* Ducking/Large */ + } + printf("Panose: %d %d %d %d %d %d %d %d %d %d\n", + panose[0], panose[1], panose[2], panose[3], panose[4], + panose[5], panose[6], panose[7], panose[8], panose[9]); +} + static void dopalt(struct glyph const *g) {