Testing complex text layout.
|
@ -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()
|
||||
|
|
|
@ -5,6 +5,7 @@ modules = {
|
|||
"tkinter": "PIL._tkinter_finder",
|
||||
"freetype2": "PIL._imagingft",
|
||||
"littlecms2": "PIL._imagingcms",
|
||||
"raqm": "PIL._imagingft",
|
||||
"webp": "PIL._webp",
|
||||
}
|
||||
|
||||
|
|
BIN
Tests/fonts/NotoNastaliqUrdu-Regular.ttf
Normal file
BIN
Tests/images/test_Nastalifont_text.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
Tests/images/test_arabictext_features.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Tests/images/test_complex_unicode_text.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
Tests/images/test_direction_ltr.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
Tests/images/test_direction_rtl.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Tests/images/test_kerning_features.png
Normal file
After Width: | Height: | Size: 963 B |
BIN
Tests/images/test_ligature_features.png
Normal file
After Width: | Height: | Size: 605 B |
BIN
Tests/images/test_text.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Tests/images/test_y_offset.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
136
Tests/test_imagefontctl.py
Normal file
|
@ -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
|
10
_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;
|
||||
|
|
|
@ -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")
|
||||
|
|