mirror of
https://bjh21.me.uk/bedstead/.git
synced 2026-07-30 15:33:25 -04:00
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:
parent
805dfe5437
commit
e40c1419a3
119
bedstead.c
119
bedstead.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user