Some infrastructure towards edge hints

There are places to record them now, but they're ignored by
select_hints() and emit_hints().
This commit is contained in:
Ben Harris 2024-11-16 23:33:30 +00:00
parent 30d226f30f
commit 1ad04e13fa

View File

@ -3808,51 +3808,79 @@ emit_path(void)
printf(" endchar");
}
static void
select_hints(int nstems, int stems[nstems])
{
/* An "A" edge is top or left, a "Z" edge is bottom or right. */
enum hint_type {
hint_none, hint_stem, hint_aedge, hint_zedge
};
static void
select_hints(int nstems, int stems[nstems],
int aedges[nstems], int zedges[nstems],
enum hint_type hints[nstems])
{
int most = 0;
/* Find longest stems. */
for (int i = 0; i < nstems; i++) {
if (stems[i] > 0) {
stems[i] = 1;
if (i + 1 < nstems) stems[i + 1] = 0;
hints[i] = hint_none;
if (stems[i] > most) most = stems[i];
}
for (;most > 0; most--) {
/* Prefer long stems. */
for (int i = 0; i < nstems; i++) {
if (stems[i] == most) {
hints[i] = hint_stem;
stems[i] = 0;
/* Disallow overlapping stems. */
if (i >= 1) stems[i-1] = 0;
if (i < nstems - 1) stems [i+1] = 0;
}
}
}
}
static void
emit_hints(int vstems[XSIZE], int hstems[YSIZE])
emit_hints(int vstems[XSIZE], int ledges[XSIZE], int redges[XSIZE],
int hstems[YSIZE], int tedges[YSIZE], int bedges[YSIZE])
{
int i, start, size, cur;
enum hint_type vhints[XSIZE], hhints[YSIZE];
bool printed;
select_hints(YSIZE, hstems);
select_hints(YSIZE, hstems, tedges, bedges, hhints);
cur = DESCENT * YPIX; printed = false;
size = YPIX_S;
for (i = YSIZE - 1; i >= 0; i--) {
if (hstems[i] > 0) {
switch (hhints[i]) {
case hint_stem:
start = (YSIZE - i - 1) * YPIX_S;
printf(" %g %g",
(double)((start - cur) / YSCALE),
(double)(size / YSCALE));
cur = start + size;
printed = true;
size = YPIX_S;
break;
default: continue;
}
printf(" %g %g",
(double)((start - cur) / YSCALE),
(double)(size / YSCALE));
cur = start + size;
printed = true;
}
if (printed) printf(" hstem");
select_hints(XSIZE, vstems);
select_hints(XSIZE, vstems, ledges, redges, vhints);
cur = 0; printed = false;
size = XPIX_S + weight->weight;
for (i = 0; i < XSIZE; i++) {
if (vstems[i] > 0) {
switch (vhints[i]) {
case hint_stem:
start = i * XPIX_S - weight->weight;
printf(" %g %g",
(double)((start - cur) / XSCALE),
(double)(size / XSCALE));
cur = start + size;
printed = true;
size = XPIX_S + weight->weight;
break;
default: continue;
}
printf(" %g %g",
(double)((start - cur) / XSCALE),
(double)(size / XSCALE));
cur = start + size;
printed = true;
}
if (printed) printf(" vstem");
}
@ -3994,7 +4022,8 @@ static void
dochar(struct glyph *g)
{
int x, y;
int vstems[XSIZE], hstems[YSIZE];
int vstems[XSIZE], ledges[XSIZE], redges[XSIZE];
int hstems[YSIZE], tedges[YSIZE], bedges[YSIZE];
#define GETPIX(x,y) (getpix(g->data, (x), (y), g->flags))
#define L GETPIX(x-1, y)
@ -4029,11 +4058,15 @@ dochar(struct glyph *g)
blackpixel(x, YSIZE - y - 1, bl, br, tr, tl);
if (!L && !R && (U || D))
vstems[x]++;
if (!U && !D && (L || R))
hstems[y]++;
if (UL + U + UR + L + R + DL + D + DR == 0) {
vstems[x]++;
else if (!U && !D && (L || R))
hstems[y]++;
else if (UL + U + UR + L + R + DL + D + DR == 0)
vstems[x]++, hstems[y]++;
else { /* Not a stem. Maybe an edge? */
if (UL + U + UR == 0) tedges[y]++;
if (DL + D + DR == 0) bedges[y]++;
if (UL + L + DL == 0) ledges[x]++;
if (UR + R + DR == 0) redges[x]++;
}
} else {
bool tl, tr, bl, br;
@ -4052,7 +4085,7 @@ dochar(struct glyph *g)
clean_path();
adjust_weight();
record_lsb(g);
emit_hints(vstems, hstems);
emit_hints(vstems, ledges, redges, hstems, tedges, bedges);
emit_path();
}