Skip to content

Commit cf757e6

Browse files
authored
Merge pull request #5777 from hugovk/rm-freetype-2.7
Remove support for FreeType 2.7 and older
2 parents 44a61bb + 66ad6ff commit cf757e6

11 files changed

+55
-98
lines changed

Tests/images/multiline_text.png

354 Bytes
Loading
358 Bytes
Loading

Tests/images/multiline_text_right.png

354 Bytes
Loading
357 Bytes
Loading

Tests/test_imagefont.py

+14-39
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ def test_textsize_equal(self):
155155
draw.text((10, 10), txt, font=ttf)
156156
draw.rectangle((10, 10, 10 + size[0], 10 + size[1]))
157157

158-
# Epsilon ~.5 fails with FreeType 2.7
159158
assert_image_similar_tofile(
160159
im, "Tests/images/rectangle_surrounding_text.png", 2.5
161160
)
@@ -216,8 +215,7 @@ def test_render_multiline_text(self):
216215
draw = ImageDraw.Draw(im)
217216
draw.text((0, 0), TEST_TEXT, font=ttf)
218217

219-
# Epsilon ~.5 fails with FreeType 2.7
220-
assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 6.2)
218+
assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 0.01)
221219

222220
# Test that text() can pass on additional arguments
223221
# to multiline_text()
@@ -232,9 +230,8 @@ def test_render_multiline_text(self):
232230
draw = ImageDraw.Draw(im)
233231
draw.multiline_text((0, 0), TEST_TEXT, font=ttf, align=align)
234232

235-
# Epsilon ~.5 fails with FreeType 2.7
236233
assert_image_similar_tofile(
237-
im, "Tests/images/multiline_text" + ext + ".png", 6.2
234+
im, "Tests/images/multiline_text" + ext + ".png", 0.01
238235
)
239236

240237
def test_unknown_align(self):
@@ -289,8 +286,7 @@ def test_multiline_spacing(self):
289286
draw = ImageDraw.Draw(im)
290287
draw.multiline_text((0, 0), TEST_TEXT, font=ttf, spacing=10)
291288

292-
# Epsilon ~.5 fails with FreeType 2.7
293-
assert_image_similar_tofile(im, "Tests/images/multiline_text_spacing.png", 6.2)
289+
assert_image_similar_tofile(im, "Tests/images/multiline_text_spacing.png", 2.5)
294290

295291
def test_rotated_transposed_font(self):
296292
img_grey = Image.new("L", (100, 100))
@@ -738,30 +734,26 @@ def test_textbbox_non_freetypefont(self):
738734
d.textbbox((0, 0), "test", font=default_font)
739735

740736
@pytest.mark.parametrize(
741-
"anchor, left, left_old, top",
737+
"anchor, left, top",
742738
(
743739
# test horizontal anchors
744-
("ls", 0, 0, -36),
745-
("ms", -64, -65, -36),
746-
("rs", -128, -129, -36),
740+
("ls", 0, -36),
741+
("ms", -64, -36),
742+
("rs", -128, -36),
747743
# test vertical anchors
748-
("ma", -64, -65, 16),
749-
("mt", -64, -65, 0),
750-
("mm", -64, -65, -17),
751-
("mb", -64, -65, -44),
752-
("md", -64, -65, -51),
744+
("ma", -64, 16),
745+
("mt", -64, 0),
746+
("mm", -64, -17),
747+
("mb", -64, -44),
748+
("md", -64, -51),
753749
),
754750
ids=("ls", "ms", "rs", "ma", "mt", "mm", "mb", "md"),
755751
)
756-
def test_anchor(self, anchor, left, left_old, top):
752+
def test_anchor(self, anchor, left, top):
757753
name, text = "quick", "Quick"
758754
path = f"Tests/images/test_anchor_{name}_{anchor}.png"
759755

760-
freetype = parse_version(features.version_module("freetype2"))
761-
if freetype < parse_version("2.4"):
762-
width, height = (129, 44)
763-
left = left_old
764-
elif self.LAYOUT_ENGINE == ImageFont.LAYOUT_RAQM:
756+
if self.LAYOUT_ENGINE == ImageFont.LAYOUT_RAQM:
765757
width, height = (129, 44)
766758
else:
767759
width, height = (128, 44)
@@ -894,7 +886,6 @@ def test_standard_embedded_color(self):
894886

895887
assert_image_similar_tofile(im, "Tests/images/standard_embedded.png", 6.2)
896888

897-
@skip_unless_feature_version("freetype2", "2.5.0")
898889
def test_cbdt(self):
899890
try:
900891
font = ImageFont.truetype(
@@ -913,7 +904,6 @@ def test_cbdt(self):
913904
assert str(e) in ("unimplemented feature", "unknown file format")
914905
pytest.skip("freetype compiled without libpng or CBDT support")
915906

916-
@skip_unless_feature_version("freetype2", "2.5.0")
917907
def test_cbdt_mask(self):
918908
try:
919909
font = ImageFont.truetype(
@@ -934,7 +924,6 @@ def test_cbdt_mask(self):
934924
assert str(e) in ("unimplemented feature", "unknown file format")
935925
pytest.skip("freetype compiled without libpng or CBDT support")
936926

937-
@skip_unless_feature_version("freetype2", "2.5.1")
938927
def test_sbix(self):
939928
try:
940929
font = ImageFont.truetype(
@@ -953,7 +942,6 @@ def test_sbix(self):
953942
assert str(e) in ("unimplemented feature", "unknown file format")
954943
pytest.skip("freetype compiled without libpng or SBIX support")
955944

956-
@skip_unless_feature_version("freetype2", "2.5.1")
957945
def test_sbix_mask(self):
958946
try:
959947
font = ImageFont.truetype(
@@ -1008,7 +996,6 @@ class TestImageFont_RaqmLayout(TestImageFont):
1008996
LAYOUT_ENGINE = ImageFont.LAYOUT_RAQM
1009997

1010998

1011-
@skip_unless_feature_version("freetype2", "2.4", "Different metrics")
1012999
def test_render_mono_size():
10131000
# issue 4177
10141001

@@ -1024,18 +1011,6 @@ def test_render_mono_size():
10241011
assert_image_equal_tofile(im, "Tests/images/text_mono.gif")
10251012

10261013

1027-
def test_freetype_deprecation(monkeypatch):
1028-
# Arrange: mock features.version_module to return fake FreeType version
1029-
def fake_version_module(module):
1030-
return "2.7"
1031-
1032-
monkeypatch.setattr(features, "version_module", fake_version_module)
1033-
1034-
# Act / Assert
1035-
with pytest.warns(DeprecationWarning):
1036-
ImageFont.truetype(FONT_PATH, FONT_SIZE)
1037-
1038-
10391014
@pytest.mark.parametrize(
10401015
"test_file",
10411016
[

Tests/test_imagefontctl.py

+2-20
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
import pytest
2-
from packaging.version import parse as parse_version
32

4-
from PIL import Image, ImageDraw, ImageFont, features
3+
from PIL import Image, ImageDraw, ImageFont
54

6-
from .helper import (
7-
assert_image_similar_tofile,
8-
skip_unless_feature,
9-
skip_unless_feature_version,
10-
)
5+
from .helper import assert_image_similar_tofile, skip_unless_feature
116

127
FONT_SIZE = 20
138
FONT_PATH = "Tests/fonts/DejaVuSans/DejaVuSans.ttf"
@@ -252,11 +247,6 @@ def test_getlength_combine(mode, direction, text):
252247
pytest.skip("libraqm 0.7 or greater not available")
253248

254249

255-
# FreeType 2.5.1 README: Miscellaneous Changes:
256-
# Improved computation of emulated vertical metrics for TrueType fonts.
257-
@skip_unless_feature_version(
258-
"freetype2", "2.5.1", "FreeType <2.5.1 has incompatible ttb metrics"
259-
)
260250
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
261251
def test_anchor_ttb(anchor):
262252
text = "f"
@@ -315,14 +305,6 @@ def test_anchor_ttb(anchor):
315305
"name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
316306
)
317307
def test_combine(name, text, dir, anchor, epsilon):
318-
if (
319-
parse_version(features.version_module("freetype2")) < parse_version("2.5.1")
320-
and dir == "ttb"
321-
):
322-
# FreeType 2.5.1 README: Miscellaneous Changes:
323-
# Improved computation of emulated vertical metrics for TrueType fonts.
324-
pytest.skip("FreeType <2.5.1 has incompatible ttb metrics")
325-
326308
path = f"Tests/images/test_combine_{name}.png"
327309
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
328310

docs/deprecations.rst

+13-13
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,6 @@ Deprecated features
1212
Below are features which are considered deprecated. Where appropriate,
1313
a ``DeprecationWarning`` is issued.
1414

15-
FreeType 2.7
16-
~~~~~~~~~~~~
17-
18-
.. deprecated:: 8.1.0
19-
20-
Support for FreeType 2.7 is deprecated and will be removed in Pillow 9.0.0 (2022-01-02),
21-
when FreeType 2.8 will be the minimum supported.
22-
23-
We recommend upgrading to at least FreeType `2.10.4`_, which fixed a severe
24-
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).
25-
26-
.. _2.10.4: https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/
27-
2815
Tk/Tcl 8.4
2916
~~~~~~~~~~
3017

@@ -111,6 +98,19 @@ ImageFile.raise_ioerror
11198
So, ``ImageFile.raise_ioerror`` has been removed.
11299
Use ``ImageFile.raise_oserror`` instead.
113100

101+
FreeType 2.7
102+
~~~~~~~~~~~~
103+
104+
.. deprecated:: 8.1.0
105+
.. versionremoved:: 9.0.0
106+
107+
Support for FreeType 2.7 has been removed.
108+
109+
We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe
110+
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).
111+
112+
.. _FreeType: https://www.freetype.org
113+
114114
im.offset
115115
~~~~~~~~~
116116

docs/releasenotes/9.0.0.rst

+22-3
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,44 @@ PILLOW_VERSION constant
99

1010
``PILLOW_VERSION`` has been removed. Use ``__version__`` instead.
1111

12+
FreeType 2.7
13+
^^^^^^^^^^^^
14+
15+
Support for FreeType 2.7 has been removed; FreeType 2.8 is the minimum supported.
16+
17+
We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe
18+
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).
19+
20+
.. _FreeType: https://www.freetype.org
21+
1222
Image.show command parameter
13-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1424

1525
The ``command`` parameter has been removed. Use a subclass of
1626
:py:class:`PIL.ImageShow.Viewer` instead.
1727

1828
Image._showxv
19-
~~~~~~~~~~~~~
29+
^^^^^^^^^^^^^
2030

2131
``Image._showxv`` has been removed. Use :py:meth:`~PIL.Image.Image.show`
2232
instead. If custom behaviour is required, use :py:meth:`~PIL.ImageShow.register` to add
2333
a custom :py:class:`~PIL.ImageShow.Viewer` class.
2434

2535
ImageFile.raise_ioerror
26-
~~~~~~~~~~~~~~~~~~~~~~~
36+
^^^^^^^^^^^^^^^^^^^^^^^
2737

2838
``IOError`` was merged into ``OSError`` in Python 3.3. So, ``ImageFile.raise_ioerror``
2939
has been removed. Use ``ImageFile.raise_oserror`` instead.
3040

41+
42+
Deprecations
43+
============
44+
45+
TODO
46+
^^^^
47+
48+
TODO
49+
3150
API Changes
3251
===========
3352

docs/releasenotes/template.rst

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ TODO
3434
Security
3535
========
3636

37+
TODO
38+
^^^^
39+
3740
TODO
3841

3942
Other Changes

src/PIL/ImageFont.py

+1-19
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@
2828
import base64
2929
import os
3030
import sys
31-
import warnings
3231
from io import BytesIO
3332

34-
from . import Image, features
33+
from . import Image
3534
from ._util import isDirectory, isPath
3635

3736
LAYOUT_BASIC = 0
@@ -165,23 +164,6 @@ def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None)
165164
self.index = index
166165
self.encoding = encoding
167166

168-
try:
169-
from packaging.version import parse as parse_version
170-
except ImportError:
171-
pass
172-
else:
173-
freetype_version = features.version_module("freetype2")
174-
if freetype_version is not None and parse_version(
175-
freetype_version
176-
) < parse_version("2.8"):
177-
warnings.warn(
178-
"Support for FreeType 2.7 is deprecated and will be removed"
179-
" in Pillow 9 (2022-01-02). Please upgrade to FreeType 2.8 "
180-
"or newer, preferably FreeType 2.10.4 which fixes "
181-
"CVE-2020-15999.",
182-
DeprecationWarning,
183-
)
184-
185167
if layout_engine not in (LAYOUT_BASIC, LAYOUT_RAQM):
186168
layout_engine = LAYOUT_BASIC
187169
if core.HAVE_RAQM:

src/_imagingft.c

-4
Original file line numberDiff line numberDiff line change
@@ -933,11 +933,7 @@ font_render(FontObject *self, PyObject *args) {
933933
case FT_PIXEL_MODE_GRAY2:
934934
case FT_PIXEL_MODE_GRAY4:
935935
if (!bitmap_converted_ready) {
936-
#if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 6)
937936
FT_Bitmap_Init(&bitmap_converted);
938-
#else
939-
FT_Bitmap_New(&bitmap_converted);
940-
#endif
941937
bitmap_converted_ready = 1;
942938
}
943939
error = FT_Bitmap_Convert(library, &bitmap, &bitmap_converted, 1);

0 commit comments

Comments
 (0)