Skip to content

Commit 842a19f

Browse files
committed
Wheels: link FreeType against the bundled HarfBuzz
FreeType's autofitter can use HarfBuzz to work out which glyphs a script covers, so it can derive blue zones for scripts such as Arabic. Only the Windows wheels were built to allow that. macOS passed --with-harfbuzz=no, and Linux left it unconfigured, which meant FreeType defaulted to `dlopen`ing HarfBuzz at runtime with the name "libharfbuzz.so.0". `auditwheel`, part of the wheeling process, renames shared libraries to avoid conflicts, so the Linux wheels ended up with a FreeType that would only find HarfBuzz if the system had its own copy with the name "libharfbuzz.so.0"; the bundled copy was never used.
1 parent df9ced4 commit 842a19f

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

.github/workflows/wheels-dependencies.sh

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ function build_brotli {
159159
touch brotli-stamp
160160
}
161161

162+
function build_freetype { # overrides multibuild's function so we can add "$@" args
163+
build_libpng
164+
build_bzip2
165+
build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz "$@"
166+
}
167+
162168
function build_harfbuzz {
163169
if [ -e harfbuzz-stamp ]; then return; fi
164170
python3 -m pip install meson ninja
@@ -304,17 +310,19 @@ function build {
304310

305311
build_brotli
306312

307-
if [[ -n "$IS_MACOS" ]]; then
308-
# Custom freetype build
309-
build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz --with-harfbuzz=no
310-
else
311-
build_freetype
312-
fi
313+
# FreeType and HarfBuzz each want the other:
314+
# HarfBuzz reads font data through FreeType, and FreeType's autofitter asks HarfBuzz which glyphs a script covers.
315+
# Break the cycle by building FreeType twice, so that the FreeType we ship is linked against the HarfBuzz we ship.
316+
build_freetype --with-harfbuzz=no
313317

314318
if [[ -z "$IOS_SDK" ]]; then
315319
# On iOS, there's no vendor-provided raqm, and we can't ship it due to
316320
# licensing, so there's no point building harfbuzz.
317321
build_harfbuzz
322+
323+
# Now that HarfBuzz exists, build FreeType again against it.
324+
rm -rf freetype-$FREETYPE_VERSION freetype-stamp
325+
build_freetype --with-harfbuzz=yes
318326
fi
319327
}
320328

docs/releasenotes/13.0.0.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,25 @@ that share a local name across different namespaces.
9797
Other changes
9898
=============
9999

100+
Wheels now use HarfBuzz for hinting
101+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
102+
103+
FreeType can use HarfBuzz to work out which glyphs a script covers,
104+
so that its autofitter can derive hinting "Blue Zones" for scripts such as Arabic.
105+
106+
Only the Windows wheels were actually built with this support.
107+
The macOS wheels disabled HarfBuzz intreop outright,
108+
and the Linux wheels left it up to FreeType's ``configure``,
109+
which in turn fell back to loading HarfBuzz by its unversioned name at
110+
runtime.
111+
112+
Since the bundled copy of HarfBuzz is renamed when the wheel is audited and repaired
113+
for distribution, that lookup only succeeded if a separate copy happened to be
114+
installed on the system with the expected name (e.g. ``libharfbuzz.so.0``).
115+
116+
All wheels are now linked against the HarfBuzz that Pillow ships,
117+
which may slightly change how text is rendered in scripts that rely on the autofitter.
118+
100119
Python 3.15
101120
^^^^^^^^^^^
102121

0 commit comments

Comments
 (0)