Skip to content

Commit

Permalink
consider all fonts when computing font family metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
nulano committed Feb 8, 2023
1 parent e0f7c73 commit 8c4c0d6
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 6 deletions.
8 changes: 8 additions & 0 deletions src/PIL/ImageFont.py
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,14 @@ def getmask2(
)
return im, offset

def getmetrics(self):
"""
:return: A tuple of the maximum font ascent (the distance from the baseline to
the highest outline point) and maximum descent (the distance from the
baseline to the lowest outline point, a negative value)
"""
return self.font.ascent, self.font.descent


class TransposedFont:
"""Wrapper for writing rotated or mirrored text"""
Expand Down
70 changes: 64 additions & 6 deletions src/_imagingft.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,36 @@ getfamily(PyObject *self_, PyObject *args, PyObject *kw) {
return NULL;
}

static FT_Pos
family_getascender(FontFamily *family) {
int i;
FT_Pos ascender = 0;
for (i = 0; i < family->font_count; i++) {
ascender = max(ascender, family->faces[i]->size->metrics.ascender);
}
return ascender;
}

static FT_Pos
family_getdescender(FontFamily *family) {
int i;
FT_Pos descender = 0;
for (i = 0; i < family->font_count; i++) {
descender = min(descender, family->faces[i]->size->metrics.descender);
}
return descender;
}

static FT_Pos
family_getheight(FontFamily *family) {
int i;
FT_Pos height = 0;
for (i = 0; i < family->font_count; i++) {
height = max(height, family->faces[i]->size->metrics.height);
}
return height;
}

static int
font_getchar(PyObject *string, int index, FT_ULong *char_out) {
if (PyUnicode_Check(string)) {
Expand Down Expand Up @@ -950,16 +980,16 @@ text_getsize(FontFamily *family, PyObject *args) {
}
switch (anchor[1]) {
case 'a': // ascender
y_anchor = PIXEL(family->faces[0]->size->metrics.ascender);
// this should be consistent with getmetrics()
y_anchor = PIXEL(family_getascender(family));
break;
case 't': // top
y_anchor = y_max;
break;
case 'm': // middle (ascender + descender) / 2
// this should be consistent with getmetrics()
y_anchor = PIXEL(
(family->faces[0]->size->metrics.ascender +
family->faces[0]->size->metrics.descender) /
2);
(family_getascender(family) + family_getdescender(family)) / 2);
break;
case 's': // horizontal baseline
y_anchor = 0;
Expand All @@ -968,7 +998,8 @@ text_getsize(FontFamily *family, PyObject *args) {
y_anchor = y_min;
break;
case 'd': // descender
y_anchor = PIXEL(family->faces[0]->size->metrics.descender);
// this should be consistent with getmetrics()
y_anchor = PIXEL(family_getdescender(family));
break;
default:
goto bad_anchor;
Expand Down Expand Up @@ -1683,6 +1714,33 @@ static PyMethodDef family_methods[] = {
*/
{NULL, NULL}};

static PyObject *
family_getattr_ascent(FontFamilyObject *self, void *closure) {
return PyLong_FromLong(PIXEL(family_getascender(&self->data)));
}

static PyObject *
family_getattr_descent(FontFamilyObject *self, void *closure) {
return PyLong_FromLong(-PIXEL(family_getdescender(&self->data)));
}

static PyObject *
family_getattr_height(FontFamilyObject *self, void *closure) {
return PyLong_FromLong(PIXEL(family_getheight(&self->data)));
}


static struct PyGetSetDef family_getsetters[] = {
//{"family", (getter)font_getattr_family},
//{"style", (getter)font_getattr_style},
{"ascent", (getter)family_getattr_ascent},
{"descent", (getter)family_getattr_descent},
{"height", (getter)family_getattr_height},
//{"x_ppem", (getter)font_getattr_x_ppem},
//{"y_ppem", (getter)font_getattr_y_ppem},
//{"glyphs", (getter)font_getattr_glyphs},
{NULL}};


static PyTypeObject FontFamily_Type = {
PyVarObject_HEAD_INIT(NULL, 0) "FontFamily",
Expand Down Expand Up @@ -1714,7 +1772,7 @@ static PyTypeObject FontFamily_Type = {
0, /*tp_iternext*/
family_methods, /*tp_methods*/
0, /*tp_members*/
0, /*TODO tp_getset*/
family_getsetters, /* tp_getset*/
};

static PyMethodDef _functions[] = {
Expand Down

0 comments on commit 8c4c0d6

Please sign in to comment.