Skip to content

Vertical text alignment ignores yOffset #4553

@nulano

Description

@nulano

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:
image

But I get the following image (with master):
image

This is because when raqm support was added, the yoffset variable was not updated to look at the glyphinfo[i].y_offset value:

Pillow/src/_imagingft.c

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).

Pillow/src/_imagingft.c

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;

Pillow/src/_imagingft.c

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugAny unexpected behavior, until confirmed feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions