diff --git a/Tests/fonts/ArefRuqaa-Regular.ttf b/Tests/fonts/ArefRuqaa-Regular.ttf new file mode 100644 index 00000000000..940cb58f4dc Binary files /dev/null and b/Tests/fonts/ArefRuqaa-Regular.ttf differ diff --git a/Tests/fonts/LICENSE.txt b/Tests/fonts/LICENSE.txt index a1783e95475..0e0baaabb05 100644 --- a/Tests/fonts/LICENSE.txt +++ b/Tests/fonts/LICENSE.txt @@ -3,6 +3,7 @@ NotoNastaliqUrdu-Regular.ttf, from https://github.com/googlei18n/noto-fonts 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 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. diff --git a/Tests/images/test_x_max_and_y_offset.png b/Tests/images/test_x_max_and_y_offset.png new file mode 100644 index 00000000000..f8bec3e95e5 Binary files /dev/null and b/Tests/images/test_x_max_and_y_offset.png differ diff --git a/Tests/images/test_y_offset.png b/Tests/images/test_y_offset.png index 5a166be8c2e..2d57890cb5f 100644 Binary files a/Tests/images/test_y_offset.png and b/Tests/images/test_y_offset.png differ diff --git a/Tests/test_imagefontctl.py b/Tests/test_imagefontctl.py index 6c680308755..2127af19dd7 100644 --- a/Tests/test_imagefontctl.py +++ b/Tests/test_imagefontctl.py @@ -159,6 +159,18 @@ def test_arabictext_features(self): self.assert_image_similar(im, target_img, .5) + def test_x_max_and_y_offset(self): + ttf = ImageFont.truetype("Tests/fonts/ArefRuqaa-Regular.ttf", 40) + + im = Image.new(mode='RGB', size=(50, 100)) + draw = ImageDraw.Draw(im) + draw.text((0, 0), 'لح', font=ttf, fill=500) + + target = 'Tests/images/test_x_max_and_y_offset.png' + target_img = Image.open(target) + + self.assert_image_similar(im, target_img, .5) + def test_language(self): ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) diff --git a/src/_imagingft.c b/src/_imagingft.c index 6eebc93461c..f6bd787ef5c 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -618,7 +618,7 @@ text_layout(PyObject* string, FontObject* self, const char* dir, PyObject *featu static PyObject* font_getsize(FontObject* self, PyObject* args) { - int x_max, x_min, y_max, y_min; + int x_position, x_max, x_min, y_max, y_min; FT_Face face; int xoffset, yoffset; int horizontal_dir; @@ -634,18 +634,18 @@ font_getsize(FontObject* self, PyObject* args) if (!PyArg_ParseTuple(args, "O|zOz:getsize", &string, &dir, &features, &lang)) return NULL; - face = NULL; - xoffset = yoffset = 0; - x_max = x_min = y_max = y_min = 0; - count = text_layout(string, self, dir, features, lang, &glyph_info, 0); if (PyErr_Occurred()) { return NULL; } + face = NULL; + xoffset = yoffset = 0; + x_position = x_max = x_min = y_max = y_min = 0; + horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1; for (i = 0; i < count; i++) { - int index, error; + int index, error, offset, x_advanced; FT_BBox bbox; FT_Glyph glyph; face = self->face; @@ -661,7 +661,7 @@ font_getsize(FontObject* self, PyObject* args) if (horizontal_dir) { if (face->glyph->metrics.horiBearingX < 0) { xoffset = face->glyph->metrics.horiBearingX; - x_max -= xoffset; + x_position -= xoffset; } } else { if (face->glyph->metrics.vertBearingY < 0) { @@ -674,20 +674,19 @@ font_getsize(FontObject* self, PyObject* args) FT_Get_Glyph(face->glyph, &glyph); FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_SUBPIXELS, &bbox); if (horizontal_dir) { - x_max += glyph_info[i].x_advance; - - if (i == count - 1) { - // trim end gap from final glyph - int offset; - offset = glyph_info[i].x_advance - - face->glyph->metrics.width - - face->glyph->metrics.horiBearingX; - if (offset < 0) - x_max -= offset; - } - - bbox.yMax -= glyph_info[i].y_offset; - bbox.yMin -= glyph_info[i].y_offset; + x_position += glyph_info[i].x_advance; + + x_advanced = x_position; + offset = glyph_info[i].x_advance - + face->glyph->metrics.width - + face->glyph->metrics.horiBearingX; + if (offset < 0) + x_advanced -= offset; + if (x_advanced > x_max) + x_max = x_advanced; + + bbox.yMax += glyph_info[i].y_offset; + bbox.yMin += glyph_info[i].y_offset; if (bbox.yMax > y_max) y_max = bbox.yMax; if (bbox.yMin < y_min)