From: Ben Harris Date: Wed, 20 Nov 2024 14:25:46 +0000 (+0000) Subject: Slightly ugly hack to bias middle stems upwards X-Git-Tag: bedstead-3.246~8 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~bjharris/git?a=commitdiff_plain;h=39d7e7fbdcd9a332f5268931e477110ddcdafe78;p=bedstead.git Slightly ugly hack to bias middle stems upwards By default, FreeType 2.12.1 prefers to move the middle stems of characters like 'B' and 'e' downwards, which is ugly. By applying a tiny tweak to the "hstem" commands for such stems we can persuade FreeType to move them upwards instead. This wasn't a problem when we were using FontForge because FontForge didn't use proper stem hints on the baseline. --- diff --git a/bedstead.c b/bedstead.c index b5d3b68..193e02f 100644 --- a/bedstead.c +++ b/bedstead.c @@ -3863,6 +3863,47 @@ counters_done: printf(" -->"); } +/* + * The purpose of this function is to adjust a few hints to improve + * FreeType's rendering of certain characters at awkward sizes. The + * letters 'B' and 'e' at 11 pixels per em under FreeType 2.12.1 are a + * good test case. + * + * It appears that when rendering these characters, FreeType fixes the + * top and bottom strokes to the top and bottom alignment zones. If + * those are an even number of pixels apart, this means that the + * middle stroke falls precisely on a pixel boundary. FreeType then + * has three choices: move the stem up to the pixel row above the + * centre, move it down to the row below, or anti-alias it across the + * two rows. FreeType chooses to move the stem down, which makes the + * characters look top-heavy. We'd much prefer FreeType to move the + * stem upwards. + * + * It turns out that this can be achieved just by making the middle + * stem hint slightly closer to the stem above that to the stem below. + * This just requires adjusting the width of the stem hint by one + * design unit. As far as I can see, this is allowed by the Type 1 + * font specification. A stem hint must encompass the stem outline, + * but it's allowed to be larger than the stem. And it practice it + * seems to work fine. + * + * To avoid surprising effects on other characters, this tweak is + * applied only to two rows and only if the character looks like it + * might benefit. In particular, it's not applied to any stem hint + * that might be captured by an alignment zone. + */ +static bool +middle_stem_tweak_wanted(enum hint_type hhints[YSIZE], int row) +{ + if (row == 4 && + hhints[1] == hint_counter_stem && + hhints[7] == hint_counter_stem) return true; + if (row == 5 && + hhints[3] == hint_counter_stem && + hhints[7] == hint_counter_stem) return true; + return false; +} + static void emit_hints(int vstems[XSIZE], int ledges[XSIZE], int redges[XSIZE], int hstems[YSIZE], int tedges[YSIZE], int bedges[YSIZE]) @@ -3877,7 +3918,12 @@ emit_hints(int vstems[XSIZE], int ledges[XSIZE], int redges[XSIZE], for (i = 0; i < YSIZE; i++) { switch (hhints[YSIZE - 1 - i]) { case hint_counter_stem: - need_cntrmask = true; /* FALLTHROUGH */ + need_cntrmask = true; + if (middle_stem_tweak_wanted(hhints, YSIZE - 1 - i)) { + start = i * YPIX; + size = YPIX + 1; + break; + } /* FALLTHROUGH */ case hint_stem: start = i * YPIX; size = YPIX;