diff --git a/.github/workflows/wheels-dependencies.sh b/.github/workflows/wheels-dependencies.sh index b3a5782091b..9be2867dfb8 100755 --- a/.github/workflows/wheels-dependencies.sh +++ b/.github/workflows/wheels-dependencies.sh @@ -159,6 +159,12 @@ function build_brotli { touch brotli-stamp } +function build_freetype { # overrides multibuild's function so we can add "$@" args + build_libpng + build_bzip2 + build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz "$@" +} + function build_harfbuzz { if [ -e harfbuzz-stamp ]; then return; fi python3 -m pip install meson ninja @@ -304,17 +310,19 @@ function build { build_brotli - if [[ -n "$IS_MACOS" ]]; then - # Custom freetype build - build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz --with-harfbuzz=no - else - build_freetype - fi + # FreeType and HarfBuzz each want the other: + # HarfBuzz reads font data through FreeType, and FreeType's autofitter asks HarfBuzz which glyphs a script covers. + # Break the cycle by building FreeType twice, so that the FreeType we ship is linked against the HarfBuzz we ship. + build_freetype --with-harfbuzz=no if [[ -z "$IOS_SDK" ]]; then # On iOS, there's no vendor-provided raqm, and we can't ship it due to # licensing, so there's no point building harfbuzz. build_harfbuzz + + # Now that HarfBuzz exists, build FreeType again against it. + rm -rf freetype-$FREETYPE_VERSION freetype-stamp + build_freetype --with-harfbuzz=yes fi } diff --git a/docs/releasenotes/13.0.0.rst b/docs/releasenotes/13.0.0.rst index 45667d9ec07..487e3ae723d 100644 --- a/docs/releasenotes/13.0.0.rst +++ b/docs/releasenotes/13.0.0.rst @@ -93,6 +93,25 @@ TODO Other changes ============= +Wheels now use HarfBuzz for hinting +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +FreeType can use HarfBuzz to work out which glyphs a script covers, +so that its autofitter can derive hinting "Blue Zones" for scripts such as Arabic. + +Only the Windows wheels were actually built with this support. +The macOS wheels disabled HarfBuzz intreop outright, +and the Linux wheels left it up to FreeType's ``configure``, +which in turn fell back to loading HarfBuzz by its unversioned name at +runtime. + +Since the bundled copy of HarfBuzz is renamed when the wheel is audited and repaired +for distribution, that lookup only succeeded if a separate copy happened to be +installed on the system with the expected name (e.g. ``libharfbuzz.so.0``). + +All wheels are now linked against the HarfBuzz that Pillow ships, +which may slightly change how text is rendered in scripts that rely on the autofitter. + Python 3.15 ^^^^^^^^^^^