diff --git a/Tests/images/test_arabictext_features.png b/Tests/images/test_arabictext_features.png index cb9a07443..a03845ace 100644 Binary files a/Tests/images/test_arabictext_features.png 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 index 3501b2a34..61174d75f 100644 Binary files a/Tests/images/test_complex_unicode_text.png and b/Tests/images/test_complex_unicode_text.png differ diff --git a/Tests/images/test_complex_unicode_text2.png b/Tests/images/test_complex_unicode_text2.png index c295321db..0526233c0 100644 Binary files a/Tests/images/test_complex_unicode_text2.png and b/Tests/images/test_complex_unicode_text2.png differ diff --git a/Tests/images/test_direction_ltr.png b/Tests/images/test_direction_ltr.png index 1cbc1bad9..b30fcd5d8 100644 Binary files a/Tests/images/test_direction_ltr.png 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 index 7ab6bdc19..282eed883 100644 Binary files a/Tests/images/test_direction_rtl.png and b/Tests/images/test_direction_rtl.png differ diff --git a/Tests/images/test_direction_ttb.png b/Tests/images/test_direction_ttb.png index a112eb4c6..52dbf5723 100644 Binary files a/Tests/images/test_direction_ttb.png and b/Tests/images/test_direction_ttb.png differ diff --git a/Tests/images/test_direction_ttb_stroke.png b/Tests/images/test_direction_ttb_stroke.png index 288792cc4..4b689c38e 100644 Binary files a/Tests/images/test_direction_ttb_stroke.png and b/Tests/images/test_direction_ttb_stroke.png differ diff --git a/Tests/images/test_kerning_features.png b/Tests/images/test_kerning_features.png index bded50557..78bcd951b 100644 Binary files a/Tests/images/test_kerning_features.png and b/Tests/images/test_kerning_features.png differ diff --git a/Tests/images/test_language.png b/Tests/images/test_language.png index 15ef7f93a..c77215318 100644 Binary files a/Tests/images/test_language.png and b/Tests/images/test_language.png differ diff --git a/Tests/images/test_ligature_features.png b/Tests/images/test_ligature_features.png index 9d0882124..89ea648bf 100644 Binary files a/Tests/images/test_ligature_features.png and b/Tests/images/test_ligature_features.png differ diff --git a/Tests/images/test_text.png b/Tests/images/test_text.png index 2841da66f..5888e52e5 100644 Binary files a/Tests/images/test_text.png and b/Tests/images/test_text.png differ diff --git a/Tests/images/test_x_max_and_y_offset.png b/Tests/images/test_x_max_and_y_offset.png index 9cb176b9f..21401813f 100644 Binary files a/Tests/images/test_x_max_and_y_offset.png 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 b65fe8e47..bda2490df 100644 Binary files a/Tests/images/test_y_offset.png and b/Tests/images/test_y_offset.png differ diff --git a/Tests/images/variation_adobe.png b/Tests/images/variation_adobe.png index 3ac326f51..e9cfafb48 100644 Binary files a/Tests/images/variation_adobe.png and b/Tests/images/variation_adobe.png differ diff --git a/Tests/images/variation_adobe_axes.png b/Tests/images/variation_adobe_axes.png index 93cad98ff..ad3a3a960 100644 Binary files a/Tests/images/variation_adobe_axes.png and b/Tests/images/variation_adobe_axes.png differ diff --git a/Tests/images/variation_adobe_name.png b/Tests/images/variation_adobe_name.png index acb0df63c..11ceaf6e6 100644 Binary files a/Tests/images/variation_adobe_name.png and b/Tests/images/variation_adobe_name.png differ diff --git a/Tests/images/variation_adobe_older_harfbuzz.png b/Tests/images/variation_adobe_older_harfbuzz.png index 71b879bc5..5abc907ca 100644 Binary files a/Tests/images/variation_adobe_older_harfbuzz.png and b/Tests/images/variation_adobe_older_harfbuzz.png differ diff --git a/Tests/images/variation_adobe_older_harfbuzz_axes.png b/Tests/images/variation_adobe_older_harfbuzz_axes.png index 9376c1d7b..b39d460f9 100644 Binary files a/Tests/images/variation_adobe_older_harfbuzz_axes.png and b/Tests/images/variation_adobe_older_harfbuzz_axes.png differ diff --git a/Tests/images/variation_adobe_older_harfbuzz_name.png b/Tests/images/variation_adobe_older_harfbuzz_name.png index 9e5fe70e5..2adb517a7 100644 Binary files a/Tests/images/variation_adobe_older_harfbuzz_name.png and b/Tests/images/variation_adobe_older_harfbuzz_name.png differ diff --git a/Tests/images/variation_tiny_axes.png b/Tests/images/variation_tiny_axes.png index d06ac7a60..8cb6d1f62 100644 Binary files a/Tests/images/variation_tiny_axes.png and b/Tests/images/variation_tiny_axes.png differ diff --git a/Tests/images/variation_tiny_name.png b/Tests/images/variation_tiny_name.png index a0c6ffe3f..69f1550db 100644 Binary files a/Tests/images/variation_tiny_name.png and b/Tests/images/variation_tiny_name.png differ diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 0dc515224..9ded460d3 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -704,10 +704,10 @@ class TestImageFont: font.set_variation_by_name("Bold") font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf", 36) - self._check_text(font, "Tests/images/variation_adobe.png", 11.2) + self._check_text(font, "Tests/images/variation_adobe.png", 11) for name in ["Bold", b"Bold"]: font.set_variation_by_name(name) - self._check_text(font, "Tests/images/variation_adobe_name.png", 11.3) + self._check_text(font, "Tests/images/variation_adobe_name.png", 11) font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf", 36) self._check_text(font, "Tests/images/variation_tiny.png", 40) @@ -729,7 +729,7 @@ class TestImageFont: font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf", 36) font.set_variation_by_axes([500, 50]) - self._check_text(font, "Tests/images/variation_adobe_axes.png", 5.8) + self._check_text(font, "Tests/images/variation_adobe_axes.png", 11.05) font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf", 36) font.set_variation_by_axes([100]) diff --git a/src/_imagingft.c b/src/_imagingft.c index 4cdde9a64..70817002e 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -131,8 +131,8 @@ typedef struct { static p_raqm_func p_raqm; -/* round a 26.6 pixel coordinate to the nearest larger integer */ -#define PIXEL(x) ((((x)+63) & -64)>>6) +/* round a 26.6 pixel coordinate to the nearest integer */ +#define PIXEL(x) ((((x)+32) & -64)>>6) static PyObject* geterror(int code) @@ -612,6 +612,7 @@ font_getsize(FontObject* self, PyObject* args) { int position; /* pen position along primary axis, in 26.6 precision */ int advanced; /* pen position along primary axis, in pixels */ + int px, py; /* position of current glyph, in pixels */ int x_min, x_max, y_min, y_max; /* text bounding box, in pixels */ int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */ int load_flags; /* FreeType load_flags parameter */ @@ -619,7 +620,6 @@ font_getsize(FontObject* self, PyObject* args) FT_Face face; FT_Glyph glyph; FT_BBox bbox; /* glyph bounding box */ - FT_Vector pen; GlyphInfo *glyph_info = NULL; /* computed text layout */ size_t i, count; /* glyph_info index and length */ int horizontal_dir; /* is primary axis horizontal? */ @@ -662,8 +662,8 @@ font_getsize(FontObject* self, PyObject* args) face = self->face; if (horizontal_dir) { - pen.x = position + glyph_info[i].x_offset; - pen.y = glyph_info[i].y_offset; + px = PIXEL(position + glyph_info[i].x_offset); + py = PIXEL(glyph_info[i].y_offset); position += glyph_info[i].x_advance; advanced = PIXEL(position); @@ -671,8 +671,8 @@ font_getsize(FontObject* self, PyObject* args) x_max = advanced; } } else { - pen.x = glyph_info[i].x_offset; - pen.y = position + glyph_info[i].y_offset; + px = PIXEL(glyph_info[i].x_offset); + py = PIXEL(position + glyph_info[i].y_offset); position += glyph_info[i].y_advance; advanced = PIXEL(position); @@ -680,7 +680,6 @@ font_getsize(FontObject* self, PyObject* args) y_min = advanced; } } - FT_Set_Transform(face, NULL, &pen); error = FT_Load_Glyph(face, glyph_info[i].index, load_flags); if (error) { @@ -693,15 +692,19 @@ font_getsize(FontObject* self, PyObject* args) } FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox); + bbox.xMax += px; if (bbox.xMax > x_max) { x_max = bbox.xMax; } + bbox.xMin += px; if (bbox.xMin < x_min) { x_min = bbox.xMin; } + bbox.yMax += py; if (bbox.yMax > y_max) { y_max = bbox.yMax; } + bbox.yMin += py; if (bbox.yMin < y_min) { y_min = bbox.yMin; } @@ -716,7 +719,6 @@ font_getsize(FontObject* self, PyObject* args) x_anchor = y_anchor = 0; if (face) { - FT_Set_Transform(face, NULL, NULL); if (horizontal_dir) { x_anchor = 0; y_anchor = PIXEL(self->face->size->metrics.ascender); @@ -737,6 +739,7 @@ static PyObject* font_render(FontObject* self, PyObject* args) { int x, y; /* pen position, in 26.6 precision */ + int px, py; /* position of current glyph, in pixels */ int x_min, y_max; /* text offset in 26.6 precision */ int load_flags; /* FreeType load_flags parameter */ int error; @@ -744,7 +747,6 @@ font_render(FontObject* self, PyObject* args) FT_GlyphSlot glyph_slot; FT_Bitmap bitmap; FT_BitmapGlyph bitmap_glyph; - FT_Vector pen; FT_Stroker stroker = NULL; GlyphInfo *glyph_info = NULL; /* computed text layout */ size_t i, count; /* glyph_info index and length */ @@ -803,9 +805,8 @@ font_render(FontObject* self, PyObject* args) */ x = y = x_min = y_max = 0; for (i = 0; i < count; i++) { - pen.x = x + glyph_info[i].x_offset; - pen.y = y + glyph_info[i].y_offset; - FT_Set_Transform(self->face, NULL, &pen); + px = PIXEL(x + glyph_info[i].x_offset); + py = PIXEL(y + glyph_info[i].y_offset); error = FT_Load_Glyph(self->face, glyph_info[i].index, load_flags | FT_LOAD_RENDER); if (error) { @@ -815,11 +816,11 @@ font_render(FontObject* self, PyObject* args) glyph_slot = self->face->glyph; bitmap = glyph_slot->bitmap; - if (glyph_slot->bitmap_top > y_max) { - y_max = glyph_slot->bitmap_top; + if (glyph_slot->bitmap_top + py > y_max) { + y_max = glyph_slot->bitmap_top + py; } - if (glyph_slot->bitmap_left < x_min) { - x_min = glyph_slot->bitmap_left; + if (glyph_slot->bitmap_left + px < x_min) { + x_min = glyph_slot->bitmap_left + px; } x += glyph_info[i].x_advance; @@ -827,17 +828,16 @@ font_render(FontObject* self, PyObject* args) } /* set pen position to text origin */ - x = (-x_min + stroke_width) * 64; - y = (-y_max + (-stroke_width)) * 64; + x = (-x_min + stroke_width) << 6; + y = (-y_max + (-stroke_width)) << 6; if (stroker == NULL) { load_flags |= FT_LOAD_RENDER; } for (i = 0; i < count; i++) { - pen.x = x + glyph_info[i].x_offset; - pen.y = y + glyph_info[i].y_offset; - FT_Set_Transform(self->face, NULL, &pen); + px = PIXEL(x + glyph_info[i].x_offset); + py = PIXEL(y + glyph_info[i].y_offset); error = FT_Load_Glyph(self->face, glyph_info[i].index, load_flags); if (error) { @@ -861,12 +861,12 @@ font_render(FontObject* self, PyObject* args) bitmap_glyph = (FT_BitmapGlyph)glyph; bitmap = bitmap_glyph->bitmap; - xx = bitmap_glyph->left; - yy = -bitmap_glyph->top; + xx = px + bitmap_glyph->left; + yy = -(py + bitmap_glyph->top); } else { bitmap = glyph_slot->bitmap; - xx = glyph_slot->bitmap_left; - yy = -glyph_slot->bitmap_top; + xx = px + glyph_slot->bitmap_left; + yy = -(py + glyph_slot->bitmap_top); } /* clip glyph bitmap width to target image bounds */ @@ -916,7 +916,6 @@ font_render(FontObject* self, PyObject* args) } } - FT_Set_Transform(self->face, NULL, NULL); FT_Stroker_Done(stroker); PyMem_Del(glyph_info); Py_RETURN_NONE;