mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-27 02:16:19 +03:00
Add support for pickling TrueType fonts
This commit is contained in:
parent
24f0bbf5ec
commit
18d34b287f
|
@ -2,9 +2,12 @@ import pickle
|
||||||
|
|
||||||
import pytest
|
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):
|
def helper_pickle_file(tmp_path, pickle, protocol, test_file, mode):
|
||||||
|
@ -92,3 +95,48 @@ def test_pickle_tell():
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert unpickled_image.tell() == 0
|
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)
|
||||||
|
|
|
@ -72,6 +72,21 @@ Support has been added for the "title" argument in
|
||||||
argument will also now be supported, e.g. ``im.show(title="My Image")`` and
|
argument will also now be supported, e.g. ``im.show(title="My Image")`` and
|
||||||
``ImageShow.show(im, title="My Image")``.
|
``ImageShow.show(im, title="My Image")``.
|
||||||
|
|
||||||
|
Added support for pickling TrueType fonts
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
TrueType fonts may now be pickled and unpickled. For example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
font = ImageFont.truetype("arial.ttf", size=30)
|
||||||
|
pickled_font = pickle.dumps(font1, protocol=pickle.HIGHEST_PROTOCOL)
|
||||||
|
|
||||||
|
# Later...
|
||||||
|
unpickled_font = pickle.loads(pickled_font)
|
||||||
|
|
||||||
Security
|
Security
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,13 @@ class FreeTypeFont:
|
||||||
else:
|
else:
|
||||||
load_from_bytes(font)
|
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):
|
def _multiline_split(self, text):
|
||||||
split_character = "\n" if isinstance(text, str) else b"\n"
|
split_character = "\n" if isinstance(text, str) else b"\n"
|
||||||
return text.split(split_character)
|
return text.split(split_character)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user