diff --git a/PIL/ImageDraw.py b/PIL/ImageDraw.py index 5902405a4..969537a4b 100644 --- a/PIL/ImageDraw.py +++ b/PIL/ImageDraw.py @@ -203,12 +203,10 @@ class ImageDraw(object): return text.split(split_character) def text(self, xy, text, fill=None, font=None, anchor=None, - *args, **kwargs, direction=None, features=None): - + direction=None, features=None, *args, **kwargs): if self._multiline_check(text): return self.multiline_text(xy, text, fill, font, anchor, - *args, **kwargs, direction=direction, features=features) - + direction=direction, features=features, *args, **kwargs) ink, fill = self._getink(fill) if font is None: font = self.getfont() diff --git a/PIL/features.py b/PIL/features.py index e01a32193..11b1fe058 100644 --- a/PIL/features.py +++ b/PIL/features.py @@ -5,6 +5,7 @@ modules = { "tkinter": "PIL._tkinter_finder", "freetype2": "PIL._imagingft", "littlecms2": "PIL._imagingcms", + "raqm": "PIL._imagingft", "webp": "PIL._webp", } diff --git a/Tests/fonts/NotoNastaliqUrdu-Regular.ttf b/Tests/fonts/NotoNastaliqUrdu-Regular.ttf new file mode 100644 index 000000000..891f633d8 Binary files /dev/null and b/Tests/fonts/NotoNastaliqUrdu-Regular.ttf differ diff --git a/Tests/images/test_Nastalifont_text.png b/Tests/images/test_Nastalifont_text.png new file mode 100644 index 000000000..51d56a0de Binary files /dev/null and b/Tests/images/test_Nastalifont_text.png differ diff --git a/Tests/images/test_arabictext_features.png b/Tests/images/test_arabictext_features.png new file mode 100644 index 000000000..9bfa5a931 Binary files /dev/null and b/Tests/images/test_arabictext_features.png differ diff --git a/Tests/images/test_complex_unicode_text.png b/Tests/images/test_complex_unicode_text.png new file mode 100644 index 000000000..565a2f932 Binary files /dev/null and b/Tests/images/test_complex_unicode_text.png differ diff --git a/Tests/images/test_direction_ltr.png b/Tests/images/test_direction_ltr.png new file mode 100644 index 000000000..42239334d Binary files /dev/null and b/Tests/images/test_direction_ltr.png differ diff --git a/Tests/images/test_direction_rtl.png b/Tests/images/test_direction_rtl.png new file mode 100644 index 000000000..966b67d6b Binary files /dev/null and b/Tests/images/test_direction_rtl.png differ diff --git a/Tests/images/test_kerning_features.png b/Tests/images/test_kerning_features.png new file mode 100644 index 000000000..ca895735c Binary files /dev/null and b/Tests/images/test_kerning_features.png differ diff --git a/Tests/images/test_ligature_features.png b/Tests/images/test_ligature_features.png new file mode 100644 index 000000000..664e9929d Binary files /dev/null and b/Tests/images/test_ligature_features.png differ diff --git a/Tests/images/test_text.png b/Tests/images/test_text.png new file mode 100644 index 000000000..c156399cd Binary files /dev/null and b/Tests/images/test_text.png differ diff --git a/Tests/images/test_y_offset.png b/Tests/images/test_y_offset.png new file mode 100644 index 000000000..bcf07b51c Binary files /dev/null and b/Tests/images/test_y_offset.png differ diff --git a/Tests/test_imagefontctl.py b/Tests/test_imagefontctl.py new file mode 100644 index 000000000..02c432527 --- /dev/null +++ b/Tests/test_imagefontctl.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +from helper import unittest, PillowTestCase +from PIL import Image +from PIL import ImageDraw + +FONT_SIZE = 20 +FONT_PATH = "Tests/fonts/DejaVuSans.ttf" + +try: + from PIL import ImageFont + + # check if raqm is available + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'TEST', font=ttf, fill=500, direction='ltr') + + class TestImagecomplextext(PillowTestCase): + + def test_complex_text(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'اهلا عمان', font=ttf, fill=500) + + target = 'Tests/images/test_text.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_y_offset(self): + ttf = ImageFont.truetype("Tests/fonts/NotoNastaliqUrdu-Regular.ttf", FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'هنا عمان', font=ttf, fill=500) + + target = 'Tests/images/test_y_offset.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_complex_unicode_text(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), u'مرحبا بكم', font=ttf, fill=500) + + target = 'Tests/images/test_complex_unicode_text.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_text_direction_rtl(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'English عربي', font=ttf, fill=500, direction='rtl') + + target = 'Tests/images/test_direction_rtl.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_text_direction_ltr(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'سلطنة عمان Oman', font=ttf, fill=500, direction='ltr') + + target = 'Tests/images/test_direction_ltr.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_text_direction_rtl2(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'Oman سلطنة عمان', font=ttf, fill=500, direction='rtl') + + target = 'Tests/images/test_direction_ltr.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_ligature_features(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'filling', font=ttf, fill=500, features=['-liga']) + + target = 'Tests/images/test_ligature_features.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_kerning_features(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'TeToAV', font=ttf, fill=500, features=['-kern']) + + target = 'Tests/images/test_kerning_features.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + + def test_arabictext_features(self): + ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) + + im = Image.new(mode='RGB', size=(300, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'اللغة العربية', font=ttf, fill=500, features=['-fina','-init','-medi']) + + target = 'Tests/images/test_arabictext_features.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + +except (KeyError, ImportError): + class TestImagecomplextext(PillowTestCase): + def test_skip(self): + self.skipTest("KeyError") + +if __name__ == '__main__': + unittest.main() + +# End of file diff --git a/_imagingft.c b/_imagingft.c index e1130b016..201782143 100644 --- a/_imagingft.c +++ b/_imagingft.c @@ -588,17 +588,21 @@ font_render(FontObject* self, PyObject* args) for (x = i = 0; i < count; i++) { if (i == 0 && self->face->glyph->metrics.horiBearingX < 0) - x = -PIXEL(self->face->glyph->metrics.horiBearingX); + x = -self->face->glyph->metrics.horiBearingX; index = glyph_info[i].index; error = FT_Load_Glyph(self->face, index, load_flags); if (error) return geterror(error); + if (i == 0 && self->face->glyph->metrics.horiBearingX < 0) { + x = -self->face->glyph->metrics.horiBearingX; + } + glyph = self->face->glyph; source = (unsigned char*) glyph->bitmap.buffer; - xx = x + glyph->bitmap_left; + xx = PIXEL(x) + glyph->bitmap_left; xx += PIXEL(glyph_info[i].x_offset); x0 = 0; x1 = glyph->bitmap.width; @@ -644,7 +648,7 @@ font_render(FontObject* self, PyObject* args) source += glyph->bitmap.pitch; } } - x += PIXEL(glyph_info[i].x_advance); + x += glyph_info[i].x_advance; } PyMem_Del(glyph_info); Py_RETURN_NONE; diff --git a/selftest.py b/selftest.py index f6e8e5ed8..e28aaa305 100755 --- a/selftest.py +++ b/selftest.py @@ -183,7 +183,8 @@ if __name__ == "__main__": ("jpg", "JPEG"), ("jpg_2000", "OPENJPEG (JPEG2000)"), ("zlib", "ZLIB (PNG/ZIP)"), - ("libtiff", "LIBTIFF") + ("libtiff", "LIBTIFF"), + ("raqm", "RAQM") ]: if features.check(name): print("---", feature, "support ok")