diff --git a/Tests/fonts/10x20-ISO8859-1.pcf b/Tests/fonts/10x20-ISO8859-1.pcf new file mode 100644 index 000000000..d0d7ed921 Binary files /dev/null and b/Tests/fonts/10x20-ISO8859-1.pcf differ diff --git a/Tests/fonts/10x20.pbm b/Tests/fonts/10x20.pbm new file mode 100644 index 000000000..42c38eeb0 Binary files /dev/null and b/Tests/fonts/10x20.pbm differ diff --git a/Tests/fonts/10x20.pil b/Tests/fonts/10x20.pil new file mode 100644 index 000000000..14d6e8be7 Binary files /dev/null and b/Tests/fonts/10x20.pil differ diff --git a/Tests/fonts/LICENSE.txt b/Tests/fonts/LICENSE.txt index 223c2aecf..ee9daee59 100644 --- a/Tests/fonts/LICENSE.txt +++ b/Tests/fonts/LICENSE.txt @@ -4,3 +4,10 @@ NotoNastaliqUrdu-Regular.ttf: (from https://github.com/googlei18n/noto-fonts) All Noto 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. + + +10x20-ISO8859-1.pcf + +(from https://packages.ubuntu.com/xenial/xfonts-base) + +"Public domain font. Share and enjoy." diff --git a/Tests/fonts/helvO18.pcf b/Tests/fonts/helvO18.pcf deleted file mode 100644 index f5e68ae9c..000000000 Binary files a/Tests/fonts/helvO18.pcf and /dev/null differ diff --git a/Tests/images/high_ascii_chars.png b/Tests/images/high_ascii_chars.png index fc9ab8401..81cf810af 100644 Binary files a/Tests/images/high_ascii_chars.png and b/Tests/images/high_ascii_chars.png differ diff --git a/Tests/images/test_draw_pbm_target.png b/Tests/images/test_draw_pbm_target.png new file mode 100644 index 000000000..38323f45a Binary files /dev/null and b/Tests/images/test_draw_pbm_target.png differ diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py index 90e204303..dc4c586c0 100644 --- a/Tests/test_font_pcf.py +++ b/Tests/test_font_pcf.py @@ -5,7 +5,7 @@ from PIL import ImageFont, ImageDraw codecs = dir(Image.core) -fontname = "Tests/fonts/helvO18.pcf" +fontname = "Tests/fonts/10x20-ISO8859-1.pcf" message = "hello, world" @@ -20,11 +20,20 @@ class TestFontPcf(PillowTestCase): with open(fontname, "rb") as test_file: font = PcfFontFile.PcfFontFile(test_file) self.assertIsInstance(font, FontFile.FontFile) - self.assertEqual(len([_f for _f in font.glyph if _f]), 192) + #check the number of characters in the font + self.assertEqual(len([_f for _f in font.glyph if _f]), 223) tempname = self.tempfile("temp.pil") self.addCleanup(self.delete_tempfile, tempname[:-4]+'.pbm') font.save(tempname) + + with Image.open(tempname.replace('.pil', '.pbm')) as loaded: + with Image.open('Tests/fonts/10x20.pbm') as target: + self.assert_image_equal(loaded, target) + + with open(tempname, 'rb') as f_loaded: + with open('Tests/fonts/10x20.pil', 'rb') as f_target: + self.assertEqual(f_loaded.read(), f_target.read()) return tempname def test_sanity(self): @@ -34,25 +43,35 @@ class TestFontPcf(PillowTestCase): with open("Tests/images/flower.jpg", "rb") as fp: self.assertRaises(SyntaxError, PcfFontFile.PcfFontFile, fp) - def xtest_draw(self): - + def test_draw(self): tempname = self.save_font() font = ImageFont.load(tempname) - image = Image.new("L", font.getsize(message), "white") - draw = ImageDraw.Draw(image) - draw.text((0, 0), message, font=font) - # assert_signature(image, "7216c60f988dea43a46bb68321e3c1b03ec62aee") + im = Image.new("L", (130,30), "white") + draw = ImageDraw.Draw(im) + draw.text((0, 0), message, 'black', font=font) + with Image.open('Tests/images/test_draw_pbm_target.png') as target: + self.assert_image_similar(im, target, 0) + + def test_textsize(self): + tempname = self.save_font() + font = ImageFont.load(tempname) + for i in range(255): + (dx,dy) = font.getsize(chr(i)) + self.assertEqual(dy, 20) + self.assertIn(dx, (0,10)) + for l in range(len(message)): + msg = message[:l+1] + self.assertEqual(font.getsize(msg), (len(msg)*10,20)) def _test_high_characters(self, message): - tempname = self.save_font() font = ImageFont.load(tempname) - image = Image.new("L", font.getsize(message), "white") - draw = ImageDraw.Draw(image) - draw.text((0, 0), message, font=font) + im = Image.new("L", (750,30) , "white") + draw = ImageDraw.Draw(im) + draw.text((0, 0), message, "black", font=font) + with Image.open('Tests/images/high_ascii_chars.png') as target: + self.assert_image_similar(im, target, 0) - compare = Image.open('Tests/images/high_ascii_chars.png') - self.assert_image_equal(image, compare) def test_high_characters(self): message = "".join(chr(i+1) for i in range(140, 232)) diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 68757ff3f..c437e76b2 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from helper import unittest, PillowTestCase from PIL import Image, ImageDraw, ImageFont, features @@ -409,8 +410,13 @@ class TestImageFont(PillowTestCase): draw.text((10, 10), '', font=font) self.assert_image_equal(im, target) - - + def test_unicode_pilfont(self): + # should not segfault, should return UnicodeDecodeError + # issue #2826 + font = ImageFont.load_default() + with self.assertRaises(UnicodeEncodeError): + font.getsize(u"’") + def _test_fake_loading_font(self, path_to_fake, fontname): # Make a copy of FreeTypeFont so we can patch the original diff --git a/_imaging.c b/_imaging.c index ec90e1f7f..8abb7afa8 100644 --- a/_imaging.c +++ b/_imaging.c @@ -2207,35 +2207,25 @@ void _font_text_asBytes(PyObject* encoded_string, unsigned char** text){ if (PyUnicode_CheckExact(encoded_string)){ bytes = PyUnicode_AsLatin1String(encoded_string); + if (!bytes) { + return; + } PyBytes_AsStringAndSize(bytes, &buffer, &len); } else if (PyBytes_Check(encoded_string)) { PyBytes_AsStringAndSize(encoded_string, &buffer, &len); } - *text = calloc(len,1); + *text = calloc(len+1,1); if (*text) { memcpy(*text, buffer, len); + } else { + ImagingError_MemoryError(); } - if(bytes) { + if (bytes) { Py_DECREF(bytes); } return; - - -#if PY_VERSION_HEX < 0x03000000 - /* likely case here is py2.x with an ordinary string. - but this isn't defined in Py3.x */ - if (PyString_Check(encoded_string)) { - PyString_AsStringAndSize(encoded_string, &buffer, &len); - *text = calloc(len,1); - if (*text) { - memcpy(*text, buffer, len); - } - return; - } - -#endif } @@ -2260,7 +2250,6 @@ _font_getmask(ImagingFontObject* self, PyObject* args) _font_text_asBytes(encoded_string, &text); if (!text) { - ImagingError_MemoryError(); return NULL; } @@ -2314,7 +2303,6 @@ _font_getsize(ImagingFontObject* self, PyObject* args) _font_text_asBytes(encoded_string, &text); if (!text) { - ImagingError_MemoryError(); return NULL; }