fix(gui): route emoji through Cairo/Pango when Qt render is transparent (tincan-jyhkd)#47
Merged
Conversation
…transparent (tincan-jyhkd) Qt 6's software rasterizer does not paint COLRv1 glyphs (Noto Color Emoji format) to QImage — painter.drawText() produces all-transparent pixels. The resulting PNG is a valid file but shows nothing in the QLabel HTML renderer. Fix: after Qt renders, check pixel alpha. If all transparent (COLRv1 render failed), fall back to Cairo + PangoCairo which calls FreeType directly and handles COLRv1 natively. Last resort: plain HTML-escaped text so the Qt HTML renderer can at least show a monochrome glyph. Tests (§5 pixel visibility, 4 new): - parametrized test confirms 😀 / 👍 / ❤️ all produce non-transparent PNGs - interaction test confirms _render_emoji_cairo is called when Qt fails - fallback test updated to mock both Qt save and Cairo paths Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Auto-fixed F401/I001 across test files; manually fixed remaining E501 (line-length), F841 (unused `color` variables), and F811 (duplicate register_backend definition shadowing the first). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…failure (tincan-n3fxc) Mock _has_visible_pixels to return False so the test forces the Cairo path regardless of whether Qt can render COLRv1 glyphs on CI. Clear _EMOJI_CACHE explicitly to prevent cross-test pollution from the parametrized pixel-visibility test that runs earlier with the same (😀, 16) key. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Qt 6's software rasterizer does not paint COLRv1 glyphs (Noto Color Emoji format) to
QImage—painter.drawText()produces all-transparent pixels, so encoded emoji PNGs are valid files but display nothing in theQLabelHTML renderer.This fix adds a pixel-alpha check after Qt renders. When all pixels are transparent (COLRv1 render failed), it falls back to
_render_emoji_cairo()which uses Cairo + PangoCairo → FreeType 2.11+ and handles COLRv1 natively. If Cairo is unavailable (pycairo/pygobject not installed), it falls back tohtml.escape(emoji)so the Qt HTML renderer shows a monochrome glyph rather than nothing.Review notes
_has_visible_pixels(qimage)checks alpha channel — replaces the implicit "Qt always works" assumptionpycairo+pygobject; absent libraries degrade gracefully to texttest_transparent_qt_render_triggers_cairo_fallbackmocks_has_visible_pixels=Falseto force the Cairo branch independent of CI Qt capability — without this the test was environment-dependent and failed on CI hosts where Qt can render COLRv1Test plan
pytest tests/tincan_gui/test_emoji_img_tag.py— 15 tests pass (4 new in §5 pixel visibility)pytest tests/— 1054 passed, 1 warning, 0 failuresruff check .— All checks passedrelease-gates/tincan-jyhkd-gate.md