-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
While working on implementing the anchor parameter of ImageDraw.text (see #4511 (comment)), I noticed a bug with the handling of y_offset with raqm.
For the following code:
from PIL import Image, ImageDraw, ImageFont
font = ImageFont.truetype("segoeui.ttf", 60, layout_engine=ImageFont.LAYOUT_RAQM)
def test(text):
im = Image.new("RGB", (200,200), "white")
d = ImageDraw.Draw(im)
d.line(((0,100),(200,100)), "black")
d.line(((100,0),(100,200)), "black")
d.text((100,100),text,"black", font=font)
im.show()
test("a" + ("\u030C" * 20)) # a + 20 * Unicode Character 'COMBINING CARON' (U+030C)I expect to get the following image:

But I get the following image (with master):

This is because when raqm support was added, the yoffset variable was not updated to look at the glyphinfo[i].y_offset value:
Lines 665 to 674 in 97280a0
| 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) | |
| y_min = bbox.yMin; | |
| // find max distance of baseline from top | |
| if (face->glyph->metrics.horiBearingY > yoffset) | |
| yoffset = face->glyph->metrics.horiBearingY; |
Since font_render looks at the bitmap.top value anyway (see below), which should be equal to bbox.yMax, I believe yoffset is supposed to calculate the same value as y_max, so it can just be removed and y_max used instead (in second snippet below).
Lines 801 to 804 in 97280a0
| temp = bitmap.rows - glyph_slot->bitmap_top; | |
| temp -= PIXEL(glyph_info[i].y_offset); | |
| if (temp > ascender) | |
| ascender = temp; |
Lines 710 to 712 in 97280a0
| /* difference between the font ascender and the distance of | |
| * the baseline from the top */ | |
| yoffset = PIXEL(self->face->size->metrics.ascender - yoffset); |
I am planning to include this change in the PR implementing the anchor parameter, but I wanted to document this as a separate issue.