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 <http://panose.com> 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 */
* 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 */
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]);