merge single font and font family code paths

This commit is contained in:
nulano 2023-02-02 00:23:33 +00:00 committed by Nulano
parent 6002b0a49e
commit 3710f2d299

View File

@ -67,9 +67,10 @@ static int have_raqm = 0;
#define LAYOUT_RAQM 1 #define LAYOUT_RAQM 1
typedef struct { typedef struct {
FT_Face face; FT_Face *faces;
unsigned char *font_bytes; int font_count;
} FontFamilyFont; int layout_engine;
} FontFamily;
typedef struct { typedef struct {
FT_Face face; FT_Face face;
@ -96,9 +97,8 @@ typedef struct {
} FontObject; } FontObject;
typedef struct { typedef struct {
PyObject_HEAD int font_count; PyObject_HEAD FontFamily data;
FontFamilyFont *fonts; unsigned char **font_bytes;
int layout_engine;
} FontFamilyObject; } FontFamilyObject;
static PyTypeObject Font_Type; static PyTypeObject Font_Type;
@ -256,6 +256,7 @@ getfamily(PyObject *self_, PyObject *args, PyObject *kw) {
/* create a font family object from a list of file names and a sizes (in pixels) */ /* create a font family object from a list of file names and a sizes (in pixels) */
FontFamilyObject *self; FontFamilyObject *self;
FontFamily *family;
int error = 0; int error = 0;
PyTupleObject *fonts_tuple = NULL; PyTupleObject *fonts_tuple = NULL;
@ -282,16 +283,23 @@ getfamily(PyObject *self_, PyObject *args, PyObject *kw) {
return NULL; return NULL;
} }
self->font_count = PyTuple_GET_SIZE(fonts_tuple); family = &self->data;
self->layout_engine = layout_engine;
self->fonts = PyMem_New(FontFamilyFont, self->font_count); family->font_count = PyTuple_GET_SIZE(fonts_tuple);
if (!self->fonts) { family->layout_engine = layout_engine;
family->faces = PyMem_New(FT_Face, family->font_count);
if (!family->faces) {
PyObject_Del(self);
return NULL;
}
self->font_bytes = PyMem_New(unsigned char *, family->font_count);
if (!self->font_bytes) {
PyMem_Free(family->faces);
PyObject_Del(self); PyObject_Del(self);
return NULL; return NULL;
} }
FontFamilyFont *font = self->fonts; for (int i = 0; i < family->font_count; i++) {
for (int i = 0; i < self->font_count; ++i, ++font) {
char *filename; char *filename;
Py_ssize_t size; Py_ssize_t size;
Py_ssize_t index; Py_ssize_t index;
@ -312,38 +320,38 @@ getfamily(PyObject *self_, PyObject *args, PyObject *kw) {
goto err; goto err;
} }
font->face = NULL; family->faces[i] = NULL;
if (filename && font_bytes_size <= 0) { if (filename && font_bytes_size <= 0) {
font->font_bytes = NULL; self->font_bytes[i] = NULL;
error = FT_New_Face(library, filename, index, &font->face); error = FT_New_Face(library, filename, index, &family->faces[i]);
} else { } else {
/* need to have allocated storage for font_bytes for the life of the /* need to have allocated storage for font_bytes for the life of the
* object.*/ * object.*/
/* Don't free this before FT_Done_Face */ /* Don't free this before FT_Done_Face */
font->font_bytes = PyMem_Malloc(font_bytes_size); self->font_bytes[i] = PyMem_Malloc(font_bytes_size);
if (!font->font_bytes) { if (!self->font_bytes[i]) {
error = FT_Err_Out_Of_Memory; error = FT_Err_Out_Of_Memory;
} }
if (!error) { if (!error) {
memcpy(font->font_bytes, font_bytes, (size_t)font_bytes_size); memcpy(self->font_bytes[i], font_bytes, (size_t)font_bytes_size);
error = FT_New_Memory_Face( error = FT_New_Memory_Face(
library, library,
(FT_Byte *)font->font_bytes, (FT_Byte *)self->font_bytes[i],
font_bytes_size, font_bytes_size,
index, index,
&font->face); &family->faces[i]);
} }
} }
if (!error) { if (!error) {
error = FT_Set_Pixel_Sizes(font->face, 0, size); error = FT_Set_Pixel_Sizes(family->faces[i], 0, size);
} }
if (!error && encoding && strlen((char *)encoding) == 4) { if (!error && encoding && strlen((char *)encoding) == 4) {
FT_Encoding encoding_tag = FT_Encoding encoding_tag =
FT_MAKE_TAG(encoding[0], encoding[1], encoding[2], encoding[3]); FT_MAKE_TAG(encoding[0], encoding[1], encoding[2], encoding[3]);
error = FT_Select_Charmap(font->face, encoding_tag); error = FT_Select_Charmap(family->faces[i], encoding_tag);
} }
if (filename) { if (filename) {
@ -351,31 +359,33 @@ getfamily(PyObject *self_, PyObject *args, PyObject *kw) {
} }
if (error) { if (error) {
if (font->font_bytes) { if (self->font_bytes[i]) {
PyMem_Free(font->font_bytes); PyMem_Free(self->font_bytes[i]);
font->font_bytes = NULL; self->font_bytes[i] = NULL;
}
if (family->faces[i]) {
FT_Done_Face(family->faces[i]);
} }
geterror(error); geterror(error);
goto err; goto err;
} }
continue;
err:
for (int j = 0; j < i; j++) {
if (family->faces[j]) {
FT_Done_Face(family->faces[j]);
}
if (self->font_bytes[j]) {
PyMem_Free(self->font_bytes[j]);
}
}
PyObject_Del(self);
return NULL;
} }
return (PyObject *)self; return (PyObject *)self;
err:
for (FontFamilyFont *f = self->fonts; f != font; ++f) {
if (f->font_bytes) {
PyMem_Free(f->font_bytes);
f->font_bytes = NULL;
}
if (f->face) {
FT_Done_Face(f->face);
f->face = NULL;
}
}
PyObject_Del(self);
return NULL;
} }
#ifdef HAVE_RAQM #ifdef HAVE_RAQM
@ -383,7 +393,7 @@ err:
static size_t static size_t
text_layout_raqm( text_layout_raqm(
PyObject *string, PyObject *string,
FontObject *self, FontFamily *family,
const char *dir, const char *dir,
PyObject *features, PyObject *features,
const char *lang, const char *lang,
@ -496,7 +506,7 @@ text_layout_raqm(
Py_DECREF(seq); Py_DECREF(seq);
} }
if (!raqm_set_freetype_face(rq, self->face)) { if (!raqm_set_freetype_face(rq, family->faces[0])) {
PyErr_SetString(PyExc_RuntimeError, "raqm_set_freetype_face() failed."); PyErr_SetString(PyExc_RuntimeError, "raqm_set_freetype_face() failed.");
goto failed; goto failed;
} }
@ -521,7 +531,7 @@ text_layout_raqm(
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
(*glyph_info)[i].face = self->face; (*glyph_info)[i].face = family->faces[0];
(*glyph_info)[i].index = glyphs[i].index; (*glyph_info)[i].index = glyphs[i].index;
(*glyph_info)[i].x_offset = glyphs[i].x_offset; (*glyph_info)[i].x_offset = glyphs[i].x_offset;
(*glyph_info)[i].x_advance = glyphs[i].x_advance; (*glyph_info)[i].x_advance = glyphs[i].x_advance;
@ -540,7 +550,7 @@ failed:
static size_t static size_t
text_layout_fallback( text_layout_fallback(
PyObject *string, PyObject *string,
FontObject *self, FontFamily *family,
const char *dir, const char *dir,
PyObject *features, PyObject *features,
const char *lang, const char *lang,
@ -553,7 +563,6 @@ text_layout_fallback(
FT_ULong ch; FT_ULong ch;
Py_ssize_t count; Py_ssize_t count;
FT_GlyphSlot glyph; FT_GlyphSlot glyph;
FT_Bool kerning = FT_HAS_KERNING(self->face);
FT_UInt last_index = 0; FT_UInt last_index = 0;
if (features != Py_None || dir != NULL || lang != NULL) { if (features != Py_None || dir != NULL || lang != NULL) {
@ -592,116 +601,27 @@ text_layout_fallback(
} else { } else {
ch = PyUnicode_READ_CHAR(string, i); ch = PyUnicode_READ_CHAR(string, i);
} }
(*glyph_info)[i].face = self->face;
(*glyph_info)[i].index = FT_Get_Char_Index(self->face, ch);
error = FT_Load_Glyph(self->face, (*glyph_info)[i].index, load_flags);
if (error) {
geterror(error);
return 0;
}
glyph = self->face->glyph;
(*glyph_info)[i].x_offset = 0;
(*glyph_info)[i].y_offset = 0;
if (kerning && last_index && (*glyph_info)[i].index) {
FT_Vector delta;
if (FT_Get_Kerning(
self->face,
last_index,
(*glyph_info)[i].index,
ft_kerning_default,
&delta
) == 0) {
(*glyph_info)[i - 1].x_advance += PIXEL(delta.x);
(*glyph_info)[i - 1].y_advance += PIXEL(delta.y);
}
}
(*glyph_info)[i].x_advance = glyph->metrics.horiAdvance;
// y_advance is only used in ttb, which is not supported by basic layout
(*glyph_info)[i].y_advance = 0;
last_index = (*glyph_info)[i].index;
(*glyph_info)[i].cluster = ch;
}
return count;
}
static size_t
text_layout_family(
PyObject *string,
FontFamilyObject *self,
const char *dir,
PyObject *features,
const char *lang,
GlyphInfo **glyph_info,
int mask,
int color) {
int error, load_flags;
FT_ULong ch;
Py_ssize_t count;
FT_GlyphSlot glyph;
FT_UInt last_index = 0;
int i;
if (features != Py_None || dir != NULL || lang != NULL) {
PyErr_SetString(
PyExc_KeyError,
"setting text direction, language or font features is not supported "
"without libraqm");
}
if (!PyUnicode_Check(string)) {
PyErr_SetString(PyExc_TypeError, "expected string");
return 0;
}
count = 0;
if (PyUnicode_Check(string)) {
count = PyUnicode_GET_LENGTH(string);
} else {
PyBytes_AsStringAndSize(string, &buffer, &count);
}
if (count == 0) {
return 0;
}
(*glyph_info) = PyMem_New(GlyphInfo, count);
if ((*glyph_info) == NULL) {
PyErr_SetString(PyExc_MemoryError, "PyMem_New() failed");
return 0;
}
load_flags = FT_LOAD_DEFAULT;
if (mask) {
load_flags |= FT_LOAD_TARGET_MONO;
}
#ifdef FT_LOAD_COLOR
if (color) {
load_flags |= FT_LOAD_COLOR;
}
#endif
for (i = 0; i < count; i++) {
if (buffer) {
ch = buffer[i];
} else {
ch = PyUnicode_READ_CHAR(string, i);
}
FontFamilyFont *font = self->fonts;
int found = 0; int found = 0;
for (int j = 0; !found && j < self->font_count; j++, font++) { for (int j = 0; !found && j < family->font_count; j++) {
(*glyph_info)[i].index = FT_Get_Char_Index(font->face, ch); FT_Face face = family->faces[j];
(*glyph_info)[i].index = FT_Get_Char_Index(face, ch);
if ((*glyph_info)[i].index != 0) { if ((*glyph_info)[i].index != 0) {
found = 1; found = 1;
} }
if (j == 0 || found) { /* use first font's missing glyph */ /* prefer first font's missing glyph if no font support this codepoint */
(*glyph_info)[i].face = font->face; if (j == 0 || found) {
error = FT_Load_Glyph(font->face, (*glyph_info)[i].index, load_flags); (*glyph_info)[i].face = face;
error = FT_Load_Glyph(face, (*glyph_info)[i].index, load_flags);
if (error) { if (error) {
geterror(error); geterror(error);
return 0; return 0;
} }
glyph = font->face->glyph; glyph = face->glyph;
(*glyph_info)[i].x_offset = 0; (*glyph_info)[i].x_offset = 0;
(*glyph_info)[i].y_offset = 0; (*glyph_info)[i].y_offset = 0;
if (FT_HAS_KERNING(font->face) && last_index &&
/* This has been broken and had no effect for many years now...
if (FT_HAS_KERNING(face) && last_index &&
(*glyph_info)[i].index) { (*glyph_info)[i].index) {
FT_Vector delta; FT_Vector delta;
if (FT_Get_Kerning( if (FT_Get_Kerning(
@ -714,9 +634,10 @@ text_layout_family(
(*glyph_info)[i - 1].y_advance += PIXEL(delta.y); (*glyph_info)[i - 1].y_advance += PIXEL(delta.y);
} }
} }
*/
(*glyph_info)[i].x_advance = glyph->metrics.horiAdvance; (*glyph_info)[i].x_advance = glyph->metrics.horiAdvance;
// y_advance is only used in ttb, which is not supported by basic layout /* y_advance is only used in ttb, which is not supported by basic layout */
(*glyph_info)[i].y_advance = 0; (*glyph_info)[i].y_advance = 0;
last_index = (*glyph_info)[i].index; last_index = (*glyph_info)[i].index;
(*glyph_info)[i].cluster = ch; (*glyph_info)[i].cluster = ch;
@ -729,7 +650,7 @@ text_layout_family(
static size_t static size_t
text_layout( text_layout(
PyObject *string, PyObject *string,
FontObject *self, FontFamily *family,
const char *dir, const char *dir,
PyObject *features, PyObject *features,
const char *lang, const char *lang,
@ -739,20 +660,20 @@ text_layout(
) { ) {
size_t count; size_t count;
#ifdef HAVE_RAQM #ifdef HAVE_RAQM
if (have_raqm && self->layout_engine == LAYOUT_RAQM) { if (have_raqm && family->layout_engine == LAYOUT_RAQM) {
count = text_layout_raqm(string, self, dir, features, lang, glyph_info); count = text_layout_raqm(string, family, dir, features, lang, glyph_info);
} else } else
#endif #endif
{ {
count = text_layout_fallback( count = text_layout_fallback(
string, self, dir, features, lang, glyph_info, mask, color string, family, dir, features, lang, glyph_info, mask, color
); );
} }
return count; return count;
} }
static PyObject * static PyObject *
text_getlength(void *self, int is_font_family, PyObject *args) { text_getlength(FontFamily *family, PyObject *args) {
int length; /* length along primary axis, in 26.6 precision */ int length; /* length along primary axis, in 26.6 precision */
GlyphInfo *glyph_info = NULL; /* computed text layout */ GlyphInfo *glyph_info = NULL; /* computed text layout */
size_t i, count; /* glyph_info index and length */ size_t i, count; /* glyph_info index and length */
@ -778,20 +699,8 @@ text_getlength(void *self, int is_font_family, PyObject *args) {
mask = mode && strcmp(mode, "1") == 0; mask = mode && strcmp(mode, "1") == 0;
color = mode && strcmp(mode, "RGBA") == 0; color = mode && strcmp(mode, "RGBA") == 0;
if (is_font_family) { count = text_layout(string, family, dir, features, lang, &glyph_info, mask, color);
count = text_layout_family(
string,
(FontFamilyObject *)self,
dir,
features,
lang,
&glyph_info,
mask,
color);
} else {
count = text_layout(
string, (FontObject *)self, dir, features, lang, &glyph_info, mask, color);
}
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} }
@ -815,18 +724,23 @@ text_getlength(void *self, int is_font_family, PyObject *args) {
static PyObject * static PyObject *
font_getlength(FontObject *self, PyObject *args) { font_getlength(FontObject *self, PyObject *args) {
return text_getlength(self, 0, args); FontFamily family;
family.faces = &self->face;
family.font_count = 1;
family.layout_engine = self->layout_engine;
return text_getlength(&family, args);
} }
static PyObject * static PyObject *
family_getlength(FontFamilyObject *self, PyObject *args) { family_getlength(FontFamilyObject *self, PyObject *args) {
return text_getlength(self, 1, args); return text_getlength(&self->data, args);
} }
static int static int
bounding_box_and_anchors( bounding_box_and_anchors(
void *self, FontFamily *family,
int is_font_family,
const char *anchor, const char *anchor,
int horizontal_dir, int horizontal_dir,
GlyphInfo *glyph_info, GlyphInfo *glyph_info,
@ -844,18 +758,9 @@ bounding_box_and_anchors(
int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */ int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */
int error; int error;
FT_Face face; FT_Face face;
FT_Face primaryFace;
FT_Glyph glyph; FT_Glyph glyph;
FT_BBox bbox; /* glyph bounding box */ FT_BBox bbox; /* glyph bounding box */
size_t i; /* glyph_info index */ size_t i; /* glyph_info index */
if (is_font_family) {
FontFamilyObject *family = (FontFamilyObject *)self;
primaryFace = family->fonts->face;
} else {
FontObject *font = (FontObject *)self;
primaryFace = font->face;
}
/* /*
* text bounds are given by: * text bounds are given by:
* - bounding boxes of individual glyphs * - bounding boxes of individual glyphs
@ -946,14 +851,14 @@ bounding_box_and_anchors(
} }
switch (anchor[1]) { switch (anchor[1]) {
case 'a': // ascender case 'a': // ascender
y_anchor = PIXEL(primaryFace->size->metrics.ascender); y_anchor = PIXEL(family->faces[0]->size->metrics.ascender);
break; break;
case 't': // top case 't': // top
y_anchor = y_max; y_anchor = y_max;
break; break;
case 'm': // middle (ascender + descender) / 2 case 'm': // middle (ascender + descender) / 2
y_anchor = PIXEL( y_anchor = PIXEL(
(primaryFace->size->metrics.ascender + primaryFace->size->metrics.descender) / (family->faces[0]->size->metrics.ascender + family->faces[0]->size->metrics.descender) /
2 2
); );
break; break;
@ -964,7 +869,7 @@ bounding_box_and_anchors(
y_anchor = y_min; y_anchor = y_min;
break; break;
case 'd': // descender case 'd': // descender
y_anchor = PIXEL(primaryFace->size->metrics.descender); y_anchor = PIXEL(family->faces[0]->size->metrics.descender);
break; break;
default: default:
goto bad_anchor; goto bad_anchor;
@ -1016,7 +921,7 @@ bad_anchor:
} }
static PyObject * static PyObject *
text_getsize(void *self, int is_font_family, PyObject *args) { text_getsize(FontFamily *family, PyObject *args) {
int width, height, x_offset, y_offset; int width, height, x_offset, y_offset;
int load_flags; /* FreeType load_flags parameter */ int load_flags; /* FreeType load_flags parameter */
int error; int error;
@ -1045,15 +950,7 @@ text_getsize(void *self, int is_font_family, PyObject *args) {
mask = mode && strcmp(mode, "1") == 0; mask = mode && strcmp(mode, "1") == 0;
color = mode && strcmp(mode, "RGBA") == 0; color = mode && strcmp(mode, "RGBA") == 0;
if (is_font_family) { count = text_layout(string, family, dir, features, lang, &glyph_info, mask, color);
FontFamilyObject *family = (FontFamilyObject *)self;
count = text_layout_family(
string, family, dir, features, lang, &glyph_info, mask, color);
} else {
FontObject *font = (FontObject *) self;
count = text_layout(
string, font, dir, features, lang, &glyph_info, mask, color);
}
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} }
@ -1067,8 +964,7 @@ text_getsize(void *self, int is_font_family, PyObject *args) {
} }
error = bounding_box_and_anchors( error = bounding_box_and_anchors(
self, family,
is_font_family,
anchor, anchor,
horizontal_dir, horizontal_dir,
glyph_info, glyph_info,
@ -1092,16 +988,22 @@ text_getsize(void *self, int is_font_family, PyObject *args) {
static PyObject * static PyObject *
font_getsize(FontObject *self, PyObject *args) { font_getsize(FontObject *self, PyObject *args) {
return text_getsize(self, 0, args); FontFamily family;
family.faces = &self->face;
family.font_count = 1;
family.layout_engine = self->layout_engine;
return text_getsize(&family, args);
} }
static PyObject * static PyObject *
family_getsize(FontFamilyObject *self, PyObject *args) { family_getsize(FontFamilyObject *self, PyObject *args) {
return text_getsize(self, 1, args); return text_getsize(&self->data, args);
} }
static PyObject * static PyObject *
text_render(void *self, int is_font_family, PyObject *args) { text_render(FontFamily *family, PyObject *args) {
int x, y; /* pen position, in 26.6 precision */ int x, y; /* pen position, in 26.6 precision */
int px, py; /* position of current glyph, in pixels */ int px, py; /* position of current glyph, in pixels */
int x_min, y_max; /* text offset in 26.6 precision */ int x_min, y_max; /* text offset in 26.6 precision */
@ -1168,30 +1070,8 @@ text_render(void *self, int is_font_family, PyObject *args) {
foreground_ink = foreground_ink_long; foreground_ink = foreground_ink_long;
if (is_font_family) {
FontFamilyObject *family = (FontFamilyObject *)self;
#ifdef FT_COLOR_H
for (int i = 0; i < family->font_count; i++) {
if (color) {
FT_Color foreground_color;
FT_Byte *ink = (FT_Byte *)&foreground_ink;
foreground_color.red = ink[0];
foreground_color.green = ink[1];
foreground_color.blue = ink[2];
foreground_color.alpha =
(FT_Byte)255; /* ink alpha is handled in ImageDraw.text */
FT_Palette_Set_Foreground_Color(family->fonts[i].face, foreground_color);
}
}
#endif
count =
text_layout_family(string, family, dir, features, lang, &glyph_info, mask, color);
} else {
FontObject *font = (FontObject *)self;
#ifdef FT_COLOR_H #ifdef FT_COLOR_H
for (int i = 0; i < family->font_count; i++) {
if (color) { if (color) {
FT_Color foreground_color; FT_Color foreground_color;
FT_Byte *ink = (FT_Byte *)&foreground_ink; FT_Byte *ink = (FT_Byte *)&foreground_ink;
@ -1200,13 +1080,13 @@ text_render(void *self, int is_font_family, PyObject *args) {
foreground_color.blue = ink[2]; foreground_color.blue = ink[2];
foreground_color.alpha = foreground_color.alpha =
(FT_Byte)255; /* ink alpha is handled in ImageDraw.text */ (FT_Byte)255; /* ink alpha is handled in ImageDraw.text */
FT_Palette_Set_Foreground_Color(font->face, foreground_color); FT_Palette_Set_Foreground_Color(family->faces[i], foreground_color);
} }
}
#endif #endif
count = count = text_layout(string, family, dir, features, lang, &glyph_info, mask, color);
text_layout(string, font, dir, features, lang, &glyph_info, mask, color);
}
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} }
@ -1222,8 +1102,7 @@ text_render(void *self, int is_font_family, PyObject *args) {
horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1; horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
error = bounding_box_and_anchors( error = bounding_box_and_anchors(
self, family,
is_font_family,
anchor, anchor,
horizontal_dir, horizontal_dir,
glyph_info, glyph_info,
@ -1544,12 +1423,18 @@ glyph_error:
static PyObject * static PyObject *
font_render(FontObject *self, PyObject *args) { font_render(FontObject *self, PyObject *args) {
return text_render(self, 0, args); FontFamily family;
family.faces = &self->face;
family.font_count = 1;
family.layout_engine = self->layout_engine;
return text_render(&family, args);
} }
static PyObject * static PyObject *
family_render(FontFamilyObject *self, PyObject *args) { family_render(FontFamilyObject *self, PyObject *args) {
return text_render(self, 1, args); return text_render(&self->data, args);
} }
#if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 9) || \ #if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 9) || \
@ -1885,16 +1770,16 @@ static PyTypeObject Font_Type = {
static void static void
family_dealloc(FontFamilyObject *self) { family_dealloc(FontFamilyObject *self) {
FontFamilyFont *font = self->fonts; for (int i = 0; i < self->data.font_count; i++) {
for (int i = 0; i < self->font_count; ++i, ++font) { if (self->data.faces[i]) {
if (font->face) { FT_Done_Face(self->data.faces[i]);
FT_Done_Face(font->face);
} }
if (font->font_bytes) { if (self->font_bytes[i]) {
PyMem_Free(font->font_bytes); PyMem_Free(self->font_bytes[i]);
} }
} }
PyMem_Free(self->fonts); PyMem_Free(self->data.faces);
PyMem_Free(self->font_bytes);
PyObject_Del(self); PyObject_Del(self);
} }