diff --git a/bedstead.c b/bedstead.c index 27c12d7..7601d32 100644 --- a/bedstead.c +++ b/bedstead.c @@ -2929,19 +2929,50 @@ static void dopanose(void) { /* - * PANOSE is a complex font categorisation scheme. I suspect - * no-one uses it, but it's a mandatory part of the 'OS/2' + * PANOSE is a complex font categorisation scheme. It's not + * entirely unused, and is 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. + * + * PANOSE has some rules that divert Latin Text fonts into the + * Latin Decorative category. One applies if ConRat > 1. + * However, by definition ConRat is at most 1, so this never + * applies. The other case is for very wide or narrow fonts, + * but this is checked after checking for monospaced fonts, + * and Bedstead is monospaced. Thus all Bedstead variants can + * be treated as Latin Text fonts. */ int panose[10]; int stdvw; - /* Common digits */ - /* WeightRat == 700/StdVW */ + assert(YPIX == 100); /* Make sums easier. */ + panose[0] = 2; /* Latin Text */ + /* + * WStem(I) = stdvw + * FootWid = 2 * XPIX + stdvw + * FootRat = 2 * XPIX / stdvw + * FootRat exceeds 1.6, but A, E, H and N are sans-serif + * So re-calculate FootRat based on H + * WStem(H) = stdvw + * FootWid(H) = stdvw + * FootRat(H) = 1 + * So Bedstead is Sans Serif + * Flared excluded by FootRat + * StemCor = 0 + * RonRat = 0 + * Rounded excluded by RonRat + * FootPitch = 0 deg + * Perpendicular Sans Serif excluded by FootPitch + * EWid = 4 * XPIX + stdvw + * EOut = 4 * XPIX + stdvw + * SerOb = 1 + * So Normal Sans Serif. + */ + panose[1] = 11; /* Normal Sans Serif */ stdvw = XPIX * (100 + weight->weight) / 100; + /* WeightRat == 700/StdVW */ if (stdvw <= 20) /* WeightRat >= 35 */ panose[2] = 2; /* Very Light */ else if (stdvw < 39) /* WeightRat > 17.9 */ @@ -2966,6 +2997,8 @@ dopanose(void) * To make life simpler, ignore diagonals when calculating * ConRat. */ + /* J and M are the same width. */ + panose[3] = 9; /* Monospaced */ /* ConRat == min(StdVW / 100, 100 / StdVW) */ if (stdvw > 80 && stdvw < 125) panose[4] = 2; /* None */ @@ -2984,53 +3017,49 @@ dopanose(void) 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. + * Trying to work out Speed values by algebra made my head + * hurt, as did learning enough Maxima to get it to help. So + * I sketched it in GeoGebra and played with the numbers. + * Speed varies with weight, but seems to be independent of + * XPIX. */ - if (stdvw < 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 */ + assert(XQTR_S == 29 && YQTR_S == 29); /* Only tested these values. */ + if (panose[4] == 2) + panose[5] = 2; /* No Variation */ + else if (weight->weight < 12) { /* Speed < ~0.9602 */ + if (stdvw > YPIX) + panose[5] = 7; /* Rapid/Vertical */ 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 */ + panose[5] = 8; /* Rapid/Horizontal */ } 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 (stdvw > 100) + if (stdvw > YPIX) 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 */ + panose[5] = 6; /* Gradual/Horizontal */ } + /* Unusually shaped 'A' means no fit here. */ + panose[6] = 1; /* No Fit */ + /* + * We declare that our O is not Off Center. + * + * OutCurv similarly seems to be independent of XPIX, and for + * all reasonable weights it falls within the "Boxed" range. + */ + panose[7] = 5; /* Normal/Boxed */ + /* + * TrimRat is independent of XPIX. + * TrimRat = ((100-2*XQTR_S) + weight->weight) / (100 + weight->weight) + * = (42 + weight->weight) / (100 + weight->weight) + * So between 0 and 0.613. + */ + if (weight->weight >= 45) + panose[8] = 2; /* Standard/Trimmed */ + else + panose[8] = 3; /* Standard/Pointed */ + /* + * DuckRat = XRat = 5/7 + */ + 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]);