Mechanisms to get metadata right for different weights of font.

bedstead.c can now generate Bedstead Book (and all other widths at
that weight).
This commit is contained in:
Ben Harris 2017-08-01 23:27:22 +01:00
parent 805dfe5437
commit e40c1419a3

View File

@ -127,43 +127,43 @@
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;
}
}
}