Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Tests/fonts/LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ NotoSansJP-Thin.otf, from https://www.google.com/get/noto/help/cjk/
AdobeVFPrototype.ttf, from https://github.com/adobe-fonts/adobe-variable-font-prototype
TINY5x3GX.ttf, from http://velvetyne.fr/fonts/tiny
ArefRuqaa-Regular.ttf, from https://github.com/google/fonts/tree/master/ofl/arefruqaa
ter-x20b.pcf, from http://terminus-font.sourceforge.net/

All of the above fonts are published under the SIL Open Font License (OFL) v1.1 (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL), which allows you to copy, modify, and redistribute them if you need to.

Expand Down
Binary file added Tests/fonts/ter-x20b-cp1250.pbm
Binary file not shown.
Binary file added Tests/fonts/ter-x20b-cp1250.pil
Binary file not shown.
Binary file added Tests/fonts/ter-x20b-iso8859-1.pbm
Binary file not shown.
Binary file added Tests/fonts/ter-x20b-iso8859-1.pil
Binary file not shown.
Binary file added Tests/fonts/ter-x20b-iso8859-2.pbm
Binary file not shown.
Binary file added Tests/fonts/ter-x20b-iso8859-2.pil
Binary file not shown.
Binary file added Tests/fonts/ter-x20b.pcf
Binary file not shown.
Binary file added Tests/images/test_draw_pbm_ter_en_target.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/test_draw_pbm_ter_pl_target.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions Tests/test_font_pcf_charsets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import os

from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile

from .helper import assert_image_equal, assert_image_similar, skip_unless_feature

fontname = "Tests/fonts/ter-x20b.pcf"

charsets = {
"iso8859-1": {
"glyph_count": 223,
"message": "hello, world",
"image1": "Tests/images/test_draw_pbm_ter_en_target.png",
},
"iso8859-2": {
"glyph_count": 223,
"message": "witaj świecie",
"image1": "Tests/images/test_draw_pbm_ter_pl_target.png",
},
"cp1250": {
"glyph_count": 250,
"message": "witaj świecie",
"image1": "Tests/images/test_draw_pbm_ter_pl_target.png",
},
}


pytestmark = skip_unless_feature("zlib")


def save_font(request, tmp_path, encoding):
with open(fontname, "rb") as test_file:
font = PcfFontFile.PcfFontFile(test_file, encoding)
assert isinstance(font, FontFile.FontFile)
# check the number of characters in the font
assert len([_f for _f in font.glyph if _f]) == charsets[encoding]["glyph_count"]

tempname = str(tmp_path / "temp.pil")

def delete_tempfile():
try:
os.remove(tempname[:-4] + ".pbm")
except OSError:
pass # report?

request.addfinalizer(delete_tempfile)
font.save(tempname)

with Image.open(tempname.replace(".pil", ".pbm")) as loaded:
with Image.open("Tests/fonts/ter-x20b-%s.pbm" % encoding) as target:
assert_image_equal(loaded, target)

with open(tempname, "rb") as f_loaded:
with open("Tests/fonts/ter-x20b-%s.pil" % encoding, "rb") as f_target:
assert f_loaded.read() == f_target.read()
return tempname


def _test_sanity(request, tmp_path, encoding):
save_font(request, tmp_path, encoding)


def test_sanity_iso8859_1(request, tmp_path):
_test_sanity(request, tmp_path, "iso8859-1")


def test_sanity_iso8859_2(request, tmp_path):
_test_sanity(request, tmp_path, "iso8859-2")


def test_sanity_cp1250(request, tmp_path):
_test_sanity(request, tmp_path, "cp1250")


def _test_draw(request, tmp_path, encoding):
tempname = save_font(request, tmp_path, encoding)
font = ImageFont.load(tempname)
im = Image.new("L", (150, 30), "white")
draw = ImageDraw.Draw(im)
message = charsets[encoding]["message"].encode(encoding)
draw.text((0, 0), message, "black", font=font)
with Image.open(charsets[encoding]["image1"]) as target:
assert_image_similar(im, target, 0)


def test_draw_iso8859_1(request, tmp_path):
_test_draw(request, tmp_path, "iso8859-1")


def test_draw_iso8859_2(request, tmp_path):
_test_draw(request, tmp_path, "iso8859-2")


def test_draw_cp1250(request, tmp_path):
_test_draw(request, tmp_path, "cp1250")


def _test_textsize(request, tmp_path, encoding):
tempname = save_font(request, tmp_path, encoding)
font = ImageFont.load(tempname)
for i in range(255):
(dx, dy) = font.getsize(bytearray([i]))
assert dy == 20
assert dx in (0, 10)
message = charsets[encoding]["message"].encode(encoding)
for l in range(len(message)):
msg = message[: l + 1]
assert font.getsize(msg) == (len(msg) * 10, 20)


def test_textsize_iso8859_1(request, tmp_path):
_test_textsize(request, tmp_path, "iso8859-1")


def test_textsize_iso8859_2(request, tmp_path):
_test_textsize(request, tmp_path, "iso8859-2")


def test_textsize_cp1250(request, tmp_path):
_test_textsize(request, tmp_path, "cp1250")
23 changes: 15 additions & 8 deletions src/PIL/PcfFontFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ class PcfFontFile(FontFile.FontFile):

name = "name"

def __init__(self, fp):
def __init__(self, fp, charset_encoding="iso8859-1"):

self.charset_encoding = charset_encoding

magic = l32(fp.read(4))
if magic != PCF_MAGIC:
Expand Down Expand Up @@ -229,12 +231,17 @@ def _load_encoding(self):

nencoding = (lastCol - firstCol + 1) * (lastRow - firstRow + 1)

for i in range(nencoding):
encodingOffset = i16(fp.read(2))
if encodingOffset != 0xFFFF:
try:
encoding[i + firstCol] = encodingOffset
except IndexError:
break # only load ISO-8859-1 glyphs
encodingOffsets = [i16(fp.read(2)) for _ in range(nencoding)]

for i in range(firstCol, len(encoding)):
try:
encodingOffset = encodingOffsets[
ord(bytearray([i]).decode(self.charset_encoding))
]
if encodingOffset != 0xFFFF:
encoding[i] = encodingOffset
except UnicodeDecodeError:
# character is not supported in selected encoding
pass

return encoding