Skip to content

Commit

Permalink
Merge pull request #5777 from hugovk/rm-freetype-2.7
Browse files Browse the repository at this point in the history
Remove support for FreeType 2.7 and older
  • Loading branch information
radarhere committed Oct 19, 2021
2 parents 44a61bb + 66ad6ff commit cf757e6
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 98 deletions.
Binary file modified Tests/images/multiline_text.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/multiline_text_center.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/multiline_text_right.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/multiline_text_spacing.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 14 additions & 39 deletions Tests/test_imagefont.py
Expand Up @@ -155,7 +155,6 @@ def test_textsize_equal(self):
draw.text((10, 10), txt, font=ttf)
draw.rectangle((10, 10, 10 + size[0], 10 + size[1]))

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

# Epsilon ~.5 fails with FreeType 2.7
assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 6.2)
assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 0.01)

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

# Epsilon ~.5 fails with FreeType 2.7
assert_image_similar_tofile(
im, "Tests/images/multiline_text" + ext + ".png", 6.2
im, "Tests/images/multiline_text" + ext + ".png", 0.01
)

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

# Epsilon ~.5 fails with FreeType 2.7
assert_image_similar_tofile(im, "Tests/images/multiline_text_spacing.png", 6.2)
assert_image_similar_tofile(im, "Tests/images/multiline_text_spacing.png", 2.5)

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

@pytest.mark.parametrize(
"anchor, left, left_old, top",
"anchor, left, top",
(
# test horizontal anchors
("ls", 0, 0, -36),
("ms", -64, -65, -36),
("rs", -128, -129, -36),
("ls", 0, -36),
("ms", -64, -36),
("rs", -128, -36),
# test vertical anchors
("ma", -64, -65, 16),
("mt", -64, -65, 0),
("mm", -64, -65, -17),
("mb", -64, -65, -44),
("md", -64, -65, -51),
("ma", -64, 16),
("mt", -64, 0),
("mm", -64, -17),
("mb", -64, -44),
("md", -64, -51),
),
ids=("ls", "ms", "rs", "ma", "mt", "mm", "mb", "md"),
)
def test_anchor(self, anchor, left, left_old, top):
def test_anchor(self, anchor, left, top):
name, text = "quick", "Quick"
path = f"Tests/images/test_anchor_{name}_{anchor}.png"

freetype = parse_version(features.version_module("freetype2"))
if freetype < parse_version("2.4"):
width, height = (129, 44)
left = left_old
elif self.LAYOUT_ENGINE == ImageFont.LAYOUT_RAQM:
if self.LAYOUT_ENGINE == ImageFont.LAYOUT_RAQM:
width, height = (129, 44)
else:
width, height = (128, 44)
Expand Down Expand Up @@ -894,7 +886,6 @@ def test_standard_embedded_color(self):

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

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

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

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

@skip_unless_feature_version("freetype2", "2.5.1")
def test_sbix_mask(self):
try:
font = ImageFont.truetype(
Expand Down Expand Up @@ -1008,7 +996,6 @@ class TestImageFont_RaqmLayout(TestImageFont):
LAYOUT_ENGINE = ImageFont.LAYOUT_RAQM


@skip_unless_feature_version("freetype2", "2.4", "Different metrics")
def test_render_mono_size():
# issue 4177

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


def test_freetype_deprecation(monkeypatch):
# Arrange: mock features.version_module to return fake FreeType version
def fake_version_module(module):
return "2.7"

monkeypatch.setattr(features, "version_module", fake_version_module)

# Act / Assert
with pytest.warns(DeprecationWarning):
ImageFont.truetype(FONT_PATH, FONT_SIZE)


@pytest.mark.parametrize(
"test_file",
[
Expand Down
22 changes: 2 additions & 20 deletions Tests/test_imagefontctl.py
@@ -1,13 +1,8 @@
import pytest
from packaging.version import parse as parse_version

from PIL import Image, ImageDraw, ImageFont, features
from PIL import Image, ImageDraw, ImageFont

from .helper import (
assert_image_similar_tofile,
skip_unless_feature,
skip_unless_feature_version,
)
from .helper import assert_image_similar_tofile, skip_unless_feature

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


# FreeType 2.5.1 README: Miscellaneous Changes:
# Improved computation of emulated vertical metrics for TrueType fonts.
@skip_unless_feature_version(
"freetype2", "2.5.1", "FreeType <2.5.1 has incompatible ttb metrics"
)
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
def test_anchor_ttb(anchor):
text = "f"
Expand Down Expand Up @@ -315,14 +305,6 @@ def test_anchor_ttb(anchor):
"name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
)
def test_combine(name, text, dir, anchor, epsilon):
if (
parse_version(features.version_module("freetype2")) < parse_version("2.5.1")
and dir == "ttb"
):
# FreeType 2.5.1 README: Miscellaneous Changes:
# Improved computation of emulated vertical metrics for TrueType fonts.
pytest.skip("FreeType <2.5.1 has incompatible ttb metrics")

path = f"Tests/images/test_combine_{name}.png"
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)

Expand Down
26 changes: 13 additions & 13 deletions docs/deprecations.rst
Expand Up @@ -12,19 +12,6 @@ Deprecated features
Below are features which are considered deprecated. Where appropriate,
a ``DeprecationWarning`` is issued.

FreeType 2.7
~~~~~~~~~~~~

.. deprecated:: 8.1.0

Support for FreeType 2.7 is deprecated and will be removed in Pillow 9.0.0 (2022-01-02),
when FreeType 2.8 will be the minimum supported.

We recommend upgrading to at least FreeType `2.10.4`_, which fixed a severe
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).

.. _2.10.4: https://sourceforge.net/projects/freetype/files/freetype2/2.10.4/

Tk/Tcl 8.4
~~~~~~~~~~

Expand Down Expand Up @@ -111,6 +98,19 @@ ImageFile.raise_ioerror
So, ``ImageFile.raise_ioerror`` has been removed.
Use ``ImageFile.raise_oserror`` instead.

FreeType 2.7
~~~~~~~~~~~~

.. deprecated:: 8.1.0
.. versionremoved:: 9.0.0

Support for FreeType 2.7 has been removed.

We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).

.. _FreeType: https://www.freetype.org

im.offset
~~~~~~~~~

Expand Down
25 changes: 22 additions & 3 deletions docs/releasenotes/9.0.0.rst
Expand Up @@ -9,25 +9,44 @@ PILLOW_VERSION constant

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

FreeType 2.7
^^^^^^^^^^^^

Support for FreeType 2.7 has been removed; FreeType 2.8 is the minimum supported.

We recommend upgrading to at least `FreeType`_ 2.10.4, which fixed a severe
vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).

.. _FreeType: https://www.freetype.org

Image.show command parameter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

Image._showxv
~~~~~~~~~~~~~
^^^^^^^^^^^^^

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

ImageFile.raise_ioerror
~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^

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


Deprecations
============

TODO
^^^^

TODO

API Changes
===========

Expand Down
3 changes: 3 additions & 0 deletions docs/releasenotes/template.rst
Expand Up @@ -34,6 +34,9 @@ TODO
Security
========

TODO
^^^^

TODO

Other Changes
Expand Down
20 changes: 1 addition & 19 deletions src/PIL/ImageFont.py
Expand Up @@ -28,10 +28,9 @@
import base64
import os
import sys
import warnings
from io import BytesIO

from . import Image, features
from . import Image
from ._util import isDirectory, isPath

LAYOUT_BASIC = 0
Expand Down Expand Up @@ -165,23 +164,6 @@ def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None)
self.index = index
self.encoding = encoding

try:
from packaging.version import parse as parse_version
except ImportError:
pass
else:
freetype_version = features.version_module("freetype2")
if freetype_version is not None and parse_version(
freetype_version
) < parse_version("2.8"):
warnings.warn(
"Support for FreeType 2.7 is deprecated and will be removed"
" in Pillow 9 (2022-01-02). Please upgrade to FreeType 2.8 "
"or newer, preferably FreeType 2.10.4 which fixes "
"CVE-2020-15999.",
DeprecationWarning,
)

if layout_engine not in (LAYOUT_BASIC, LAYOUT_RAQM):
layout_engine = LAYOUT_BASIC
if core.HAVE_RAQM:
Expand Down
4 changes: 0 additions & 4 deletions src/_imagingft.c
Expand Up @@ -933,11 +933,7 @@ font_render(FontObject *self, PyObject *args) {
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
if (!bitmap_converted_ready) {
#if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 6)
FT_Bitmap_Init(&bitmap_converted);
#else
FT_Bitmap_New(&bitmap_converted);
#endif
bitmap_converted_ready = 1;
}
error = FT_Bitmap_Convert(library, &bitmap, &bitmap_converted, 1);
Expand Down

0 comments on commit cf757e6

Please sign in to comment.