From fc23ef57ecb9b839ce8a464e6983f06bb2343487 Mon Sep 17 00:00:00 2001 From: Strykar <2946372+Strykar@users.noreply.github.com> Date: Sun, 14 Jun 2026 21:00:12 +0530 Subject: [PATCH] fonts: make the color emoji regression test environment-independent The coverage threshold (0.5 in fbd4e5ad1, lowered to 0.3 in d4106ef2d to get CI green) is environment-dependent: a correctly sized emoji covers ~0.84 of its cell on one box but ~0.39 in CI, while the buggy render is ~0.28, so the margin is thin and font/cell dependent. Render the same font two ways at one size instead: via its fontconfig descriptor (which carries the size-fixup matrix) and via its file path (which does not). They must come out the same size; the bug shrinks the descriptor one. Only the matrix differs, so the check no longer depends on the environment or the emoji artwork. --- kitty_tests/fonts.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/kitty_tests/fonts.py b/kitty_tests/fonts.py index c9f1db988..268497407 100644 --- a/kitty_tests/fonts.py +++ b/kitty_tests/fonts.py @@ -392,28 +392,27 @@ class Rendering(FontBaseTest): def test_color_emoji_not_shrunk(self): # Regression test for https://github.com/kovidgoyal/kitty/issues/10144. - # fontconfig encodes the pixel-size fixup of fixed-size color faces (such - # as Noto Color Emoji, a ~109px bitmap strike) as FC_MATRIX. That scale - # must not reach the cairo font matrix, where glyph size is owned by - # cairo_set_font_size() + fit_cairo_glyph(); applying it there shrinks the - # glyph by the fixup factor (requested_px / strike_px), and fit_cairo_glyph() - # only shrinks so it never grows it back (ee937bdd1b). The shrink ranges - # from ~9x at tiny cells to ~1x near the strike; at 48pt/96dpi (~64px) the - # bug gives ~0.28 coverage versus ~0.84 when correct. + # fontconfig gives fixed-size color faces (e.g. Noto Color Emoji) a + # pixel-size fixup encoded as FC_MATRIX. That scale must not reach the + # cairo font matrix used for color glyphs; applying it shrinks color emoji + # to a dot (ee937bdd1b). Render the same font two ways at the same size: + # from its fontconfig descriptor, which carries the fixup matrix, and from + # its file path, which does not. A correct build renders both at the same + # size; the bug shrinks the descriptor one. Comparing the two is + # environment-independent since only the matrix differs. if is_macos: - self.skipTest('this is a fontconfig FC_MATRIX issue, not present on macOS') + self.skipTest('FC_MATRIX is a fontconfig feature, not used on macOS') from kitty.fonts.fontconfig import fc_match - emoji = fc_match('emoji', False, False, 0) - if not (emoji.get('color') and emoji.get('matrix')): - # Only a fixed-size color face that fontconfig gives a fixup matrix can - # trigger this. A scalable COLR emoji font has none, so a pass there - # would be a false negative rather than a real check. + desc = dict(fc_match('emoji', False, False, 0)) + if not (desc.get('color') and desc.get('matrix')): self.skipTest('no fixed-size color emoji font with a fontconfig fixup matrix') - cells = render_string('\U0001F40D', 'monospace', 48.0, 96.0)[2] - pixels = array.array('I', b''.join(cells)) - coverage = sum(1 for p in pixels if p) / max(len(pixels), 1) - del cells, pixels - self.assertGreater(coverage, 0.3, f'color emoji coverage {coverage:.2f} too low, likely shrunk (#10144)') + with_matrix = face_from_descriptor(desc) + with_matrix.set_size(64, 96, 96) + without_matrix = create_face(desc['path']) + without_matrix.set_size(64, 96, 96) + _, mw, mh = with_matrix.render_codepoint(0x1F40D) + _, rw, rh = without_matrix.render_codepoint(0x1F40D) + self.assertGreater(mh, 0.5 * rh, f'color emoji shrunk by FC_MATRIX: {mh}px vs {rh}px (#10144)') def test_shaping(self):