Repository navigation
fix: load Pillow's FreeType before Pango to stop symbol clash (#16) - #17
Merged
Merged
Conversation
font_configurator imports gi.repository.Pango at module level, which GI loads with RTLD_GLOBAL. Pillow's _imagingft was loaded afterwards, so its FT_*/hb_* calls (and even its bundled FreeType's internal calls) bound to the system FreeType/HarfBuzz instead of Pillow's bundled copies. Pillow's FreeType 2.14 faces were then driven by FreeType 2.13 functions - undefined behavior that showed up as garbage SignWriting glyph bboxes on CI. Importing PIL.ImageFont first makes Pillow bind to its own libraries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fy1wuWdqcKuebgj3St8dME
CI still failed when tests imported font_configurator directly (before pixel_renderer), loading Pango ahead of Pillow. Import PIL.ImageFont right before gi.repository in both modules that load Pango. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fy1wuWdqcKuebgj3St8dME
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.
Fixes #16.
Root cause
pixel_renderer/__init__→processor→font_configurator.font_configuratorimportsgi.repository.Pangoat module level. GI opens Pango (and with it the systemlibfreetype.so.6/libharfbuzz.so.0) withRTLD_GLOBAL.rendererimports Pillow'sImageFontonly afterwards, so when_imagingftloads, the dynamic linker resolves itsFT_*/hb_*symbols against the system libraries, which are already in the global scope. Pillow's bundled FreeType even resolves its own internal exported calls (e.g.TT_RunIns) there.So Pillow's FreeType 2.14 faces end up handled by system FreeType 2.13 functions. That's undefined behavior, and on CI it appears as a garbage
getbboxand a SignWriting image hundreds of thousands of pixels wide.Evidence (Ubuntu 24.04 container matching CI,
LD_DEBUG=bindings):features.version("freetype2")getbboxover all 62,592 SignWriting symbols91da38dd…import pixel_rendererfirst (main)a92a822b…(different bboxes)import pixel_rendererfirst (this PR)91da38dd…Fix
Import
PIL.ImageFontimmediately beforegi.repositoryin both modules that load Pango:font_configurator/font_configurator.pyandpixel_renderer/renderer.py. (The first version only guardedpixel_renderer/__init__.py. CI still failed because on xdist worker gw1 thetests/font_configurator/*modules importfont_configuratordirectly, beforepixel_renderer.)Test
tests/pixel_renderer/test_freetype_isolation.pyruns subprocesses and checks that Pillow reports the same FreeType version after importingpixel_renderer,pixel_renderer.rendererorfont_configurator.font_configuratoras it does alone. It fails on main and passes here. The full suite passes (458).Note: code that imports
gi.repository.Pangoitself beforepixel_rendererwill still hit this. Import order is the only lever available from Python.🤖 Generated with Claude Code
https://claude.ai/code/session_01Fy1wuWdqcKuebgj3St8dME
Note
Low Risk
Import-order-only change with no API or runtime behavior change beyond fixing incorrect FreeType binding; residual risk if callers import Pango before these modules.
Overview
Fixes SignWriting rendering corruption on CI caused by a dynamic-linker clash: GObject Introspection loads Pango with
RTLD_GLOBAL, so if Pango loads first, Pillow’s bundled FreeType/HarfBuzz can bind to the system libraries instead of its own, breakinggetbboxand producing huge bogus images.The PR forces
PIL.ImageFontto import beforegi.repositoryPango infont_configurator.font_configuratorandpixel_renderer.renderer, with comments pointing to issue #16.A new regression test
test_freetype_isolation.pyspawns subprocesses and asserts Pillow still reports the same FreeType version after importingpixel_renderer,pixel_renderer.renderer, orfont_configurator.font_configurator.Reviewed by Cursor Bugbot for commit 401210b. Bugbot is set up for automated code reviews on this repo. Configure here.