Skip to content

Commit

Permalink
Merge pull request #5826 from hugovk/pickle-font
Browse files Browse the repository at this point in the history
Add support for pickling TrueType fonts
  • Loading branch information
radarhere committed Nov 12, 2021
2 parents 4fca3b4 + 9f7f340 commit 937be34
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
52 changes: 50 additions & 2 deletions Tests/test_pickle.py
Expand Up @@ -2,9 +2,12 @@

import pytest

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

from .helper import skip_unless_feature
from .helper import assert_image_equal, skip_unless_feature

FONT_SIZE = 20
FONT_PATH = "Tests/fonts/DejaVuSans/DejaVuSans.ttf"


def helper_pickle_file(tmp_path, pickle, protocol, test_file, mode):
Expand Down Expand Up @@ -92,3 +95,48 @@ def test_pickle_tell():

# Assert
assert unpickled_image.tell() == 0


def helper_assert_pickled_font_images(font1, font2):
# Arrange
im1 = Image.new(mode="RGBA", size=(300, 100))
im2 = Image.new(mode="RGBA", size=(300, 100))
draw1 = ImageDraw.Draw(im1)
draw2 = ImageDraw.Draw(im2)
txt = "Hello World!"

# Act
draw1.text((10, 10), txt, font=font1)
draw2.text((10, 10), txt, font=font2)

# Assert
assert_image_equal(im1, im2)


@pytest.mark.parametrize("protocol", list(range(0, pickle.HIGHEST_PROTOCOL + 1)))
def test_pickle_font_string(protocol):
# Arrange
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)

# Act: roundtrip
pickled_font = pickle.dumps(font, protocol)
unpickled_font = pickle.loads(pickled_font)

# Assert
helper_assert_pickled_font_images(font, unpickled_font)


@pytest.mark.parametrize("protocol", list(range(0, pickle.HIGHEST_PROTOCOL + 1)))
def test_pickle_font_file(tmp_path, protocol):
# Arrange
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
filename = str(tmp_path / "temp.pkl")

# Act: roundtrip
with open(filename, "wb") as f:
pickle.dump(font, f, protocol)
with open(filename, "rb") as f:
unpickled_font = pickle.load(f)

# Assert
helper_assert_pickled_font_images(font, unpickled_font)
17 changes: 14 additions & 3 deletions docs/releasenotes/9.0.0.rst
Expand Up @@ -83,7 +83,18 @@ TODO
Other Changes
=============

TODO
^^^^
Added support for pickling TrueType fonts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

TODO
TrueType fonts may now be pickled and unpickled. For example:

.. code-block:: python
import pickle
from PIL import ImageFont
font = ImageFont.truetype("arial.ttf", size=30)
pickled_font = pickle.dumps(font, protocol=pickle.HIGHEST_PROTOCOL)
# Later...
unpickled_font = pickle.loads(pickled_font)
7 changes: 7 additions & 0 deletions src/PIL/ImageFont.py
Expand Up @@ -196,6 +196,13 @@ def load_from_bytes(f):
else:
load_from_bytes(font)

def __getstate__(self):
return [self.path, self.size, self.index, self.encoding, self.layout_engine]

def __setstate__(self, state):
path, size, index, encoding, layout_engine = state
self.__init__(path, size, index, encoding, layout_engine)

def _multiline_split(self, text):
split_character = "\n" if isinstance(text, str) else b"\n"
return text.split(split_character)
Expand Down

0 comments on commit 937be34

Please sign in to comment.