From aea0b12ba2e4c2a0b56a8ba79f7659574bc075d0 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 3 Mar 2025 22:57:37 +0000 Subject: [PATCH] Don't emit counter hints for horizontal stems Microsoft Windows 11 pays some attention to counter hints, and the results are disastrous. Specifically, at awkward ppem, characters with counter hints end up one pixel smaller that characters without them. That makes the counters the same size, and puts every horizontal stem squarely on a pixel, but means that cap height is all wobbly, which looks horrible. Additionally, some characters ('2' and '3', at least) end up grossly distorted, with the top of the character either stretched way above the character cell or squashed down to the centre line. Turning off the counter hints solves these problems. Windows does then draw the 'B' with its centre-line below the centre rather than above it, but that's not a regression from 002.009. As far as I can tell, FreeType 2.12.1 ignores counter hints entirely. At least, the output of ftlint at 11 ppem is the same before and after this change. Vertical counter hints survive. They're also ignored by FreeType 2.12.1 (as are all vertical stem hints), but they seem to have a broadly positive effect in Windows. --- bedstead.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bedstead.c b/bedstead.c index e0b12af..a875585 100644 --- a/bedstead.c +++ b/bedstead.c @@ -4472,12 +4472,21 @@ emit_hints(int vstems[XSIZE], int ledges[XSIZE], int redges[XSIZE], enum hint_type vhints[XSIZE], hhints[YSIZE]; bool printed, need_cntrmask = false; + /* + * We don't emit any counter hints for horizontal stems. On + * Microsoft Windows 11, such counter hints are treated as + * more important than alignment zones, so when the cap height + * is an even number of pixels you end up with 'B' being one + * pixel smaller than 'C' to ensure that the two counters are + * the same size. This is not actually what we want. + * FreeType 2.12.1 appears to entirely ignore those counter + * hints, so discarding them has no effect there. + */ select_hints(YSIZE, hstems, tedges, bedges, hhints); cur = DESCENT * YPIX; printed = false; for (i = 0; i < YSIZE; i++) { switch (hhints[YSIZE - 1 - i]) { case hint_counter_stem: - need_cntrmask = true; if (middle_stem_tweak_wanted(hhints, YSIZE - 1 - i)) { start = i * YPIX; size = YPIX + 1; @@ -4535,7 +4544,7 @@ emit_hints(int vstems[XSIZE], int ledges[XSIZE], int redges[XSIZE], printf(" cntrmask "); for (i = 0; i < YSIZE; i++) if (hhints[i]) { - printf("%c", "X0100"[hhints[i]]); + printf("0"); nhints++; } for (i = 0; i < XSIZE; i++) -- 2.30.2