diff --git a/PIL/ImageColor.py b/PIL/ImageColor.py index 2a190fc66ca..86f221adca2 100644 --- a/PIL/ImageColor.py +++ b/PIL/ImageColor.py @@ -102,6 +102,8 @@ def getcolor(color, mode): if mode == "RGB": return color if mode == "RGBA": + if len(color) == 3: + color = (color + (255,)) r, g, b, a = color return r, g, b, a if Image.getmodebase(mode) == "L": diff --git a/PIL/ImageFont.py b/PIL/ImageFont.py index 2cb9c41d21d..826b37d5c38 100644 --- a/PIL/ImageFont.py +++ b/PIL/ImageFont.py @@ -157,6 +157,9 @@ def getmetrics(self): def getsize(self, text): return self.font.getsize(text)[0] + def getoffset(self, text): + return self.font.getsize(text)[1] + def getmask(self, text, mode=""): return self.getmask2(text, mode)[0] @@ -183,7 +186,7 @@ def __init__(self, font, orientation=None): self.orientation = orientation # any 'transpose' argument, or None def getsize(self, text): - w, h = self.font.getsize(text) + w, h = self.font.getsize(text)[0] if self.orientation in (Image.ROTATE_90, Image.ROTATE_270): return h, w return w, h diff --git a/Tests/images/multiline_text.png b/Tests/images/multiline_text.png new file mode 100644 index 00000000000..ff1308c5ef2 Binary files /dev/null and b/Tests/images/multiline_text.png differ diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index fad7970ccef..838075c4cc2 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -35,7 +35,7 @@ def test_font_with_filelike(): #shared_bytes = _font_as_bytes() #assert_no_exception(lambda: _render(shared_bytes)) #assert_exception(Exception, lambda: _render(shared_bytes)) - _clean + _clean() def test_font_with_open_file(): with open(font_path, 'rb') as f: @@ -67,3 +67,21 @@ def test_render_equal(): assert_image_equal(img_path, img_filelike) _clean() + + +def test_render_multiline(): + im = Image.new(mode='RGB', size=(300,100)) + ttf = ImageFont.truetype(font_path, font_size) + draw = ImageDraw.Draw(im) + line_spacing = draw.textsize('A', font=ttf)[1] + 8 + lines = ['hey you', 'you are awesome', 'this looks awkward'] + y = 0 + for line in lines: + draw.text((0, y), line, font=ttf) + y += line_spacing + + target = 'Tests/images/multiline_text.png' + target_img = Image.open(target) + + assert_image_equal(im, target_img) + diff --git a/_imagingft.c b/_imagingft.c index 9dcc8318395..47d50bdca20 100644 --- a/_imagingft.c +++ b/_imagingft.c @@ -183,7 +183,7 @@ font_getsize(FontObject* self, PyObject* args) int i, x, y_max, y_min; FT_ULong ch; FT_Face face; - int xoffset; + int xoffset, yoffset; FT_Bool kerning = FT_HAS_KERNING(self->face); FT_UInt last_index = 0; @@ -203,7 +203,7 @@ font_getsize(FontObject* self, PyObject* args) } face = NULL; - xoffset = 0; + xoffset = yoffset = 0; y_max = y_min = 0; for (x = i = 0; font_getchar(string, i, &ch); i++) { @@ -231,7 +231,11 @@ font_getsize(FontObject* self, PyObject* args) y_max = bbox.yMax; if (bbox.yMin < y_min) y_min = bbox.yMin; - + + /* find max distance of baseline from top */ + if (face->glyph->metrics.horiBearingY > yoffset) + yoffset = face->glyph->metrics.horiBearingY; + last_index = index; } @@ -248,12 +252,15 @@ font_getsize(FontObject* self, PyObject* args) face->glyph->metrics.horiBearingX; if (offset < 0) x -= offset; + /* difference between the font ascender and the distance of + * the baseline from the top */ + yoffset = PIXEL(self->face->size->metrics.ascender - yoffset); } return Py_BuildValue( "(ii)(ii)", PIXEL(x), PIXEL(y_max - y_min), - PIXEL(xoffset), 0 + PIXEL(xoffset), yoffset ); }