Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra font info #1916

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions PIL/ImageFont.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from PIL._util import isDirectory, isPath
import os
import sys
import six


class _imagingft_not_installed(object):
Expand Down Expand Up @@ -169,6 +170,21 @@ def font_variant(self, font=None, size=None, index=None, encoding=None):
encoding=self.encoding if encoding is None else
encoding)

def hasglyphs(self, text):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a newline between these defs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

"""
Returns true if all the characters in the string exist in the font,
false otherwise.
"""
return self.font.hasglyphs(text)

def getglyphs(self):
"""
Return a string containing all the characters with matching glyphs in
the font
"""
codes = self.font.getglyphs()
return ''.join(six.unichr(code) for code in codes)

##
# Wrapper that creates a transposed font from any existing font
# object.
Expand Down
8 changes: 8 additions & 0 deletions Tests/test_imagefont.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ def test_font_properties(self):
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
self.assertEqual(ttf.path, FONT_PATH)
self.assertEqual(ttf.size, FONT_SIZE)
self.assertTrue(ttf.hasglyphs('a'))
self.assertFalse(ttf.hasglyphs(u'a\ueeee'))
self.assertEqual(len(ttf.getglyphs()), 4160)
self.assertIn('a', ttf.getglyphs())

ttf_copy = ttf.font_variant()
self.assertEqual(ttf_copy.path, FONT_PATH)
Expand All @@ -63,6 +67,10 @@ def test_font_properties(self):
second_font_path = "Tests/fonts/DejaVuSans.ttf"
ttf_copy = ttf.font_variant(font=second_font_path)
self.assertEqual(ttf_copy.path, second_font_path)
self.assertTrue(ttf_copy.hasglyphs('ae'))
self.assertFalse(ttf_copy.hasglyphs(u'a\ueeee'))
self.assertEqual(len(ttf.getglyphs()), 4160)
self.assertIn('a', ttf.getglyphs())

def test_font_with_name(self):
ImageFont.truetype(FONT_PATH, FONT_SIZE)
Expand Down
54 changes: 52 additions & 2 deletions _imagingft.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,11 @@ font_getsize(FontObject* self, PyObject* args)
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;

last_index = index;
FT_Done_Glyph(glyph);
}
Expand Down Expand Up @@ -319,6 +319,54 @@ font_getabc(FontObject* self, PyObject* args)
return Py_BuildValue("ddd", a, b, c);
}

static PyObject*
font_hasglyphs(FontObject* self, PyObject* args)
{
int i;
FT_ULong ch;

/* calculate ABC values for a given string */

PyObject* string;
if (!PyArg_ParseTuple(args, "O:hasglyphs", &string))
return NULL;

#if PY_VERSION_HEX >= 0x03000000
if (!PyUnicode_Check(string)) {
#else
if (!PyUnicode_Check(string) && !PyString_Check(string)) {
#endif
PyErr_SetString(PyExc_TypeError, "expected string");
return NULL;
}

for (i = 0; font_getchar(string, i, &ch); i++) {
int index;
index = FT_Get_Char_Index(self->face, ch);
if(!index)
return Py_False;
}
return Py_True;
}

static PyObject*
font_getglyphs(FontObject* self)
{
FT_UInt gindex = 0;
PyObject* characters = PyList_New(0);
if(!characters)
return PyErr_NoMemory();
FT_ULong charcode = 0;

charcode = FT_Get_First_Char(self->face, &gindex);
while( gindex != 0 ) {
PyList_Append(characters, PyLong_FromUnsignedLong(charcode));
charcode = FT_Get_Next_Char(self->face, charcode, &gindex);
}

return characters;
}

static PyObject*
font_render(FontObject* self, PyObject* args)
{
Expand Down Expand Up @@ -448,6 +496,8 @@ font_dealloc(FontObject* self)
}

static PyMethodDef font_methods[] = {
{"getglyphs", (PyCFunction) font_getglyphs, METH_VARARGS},
{"hasglyphs", (PyCFunction) font_hasglyphs, METH_VARARGS},
{"render", (PyCFunction) font_render, METH_VARARGS},
{"getsize", (PyCFunction) font_getsize, METH_VARARGS},
{"getabc", (PyCFunction) font_getabc, METH_VARARGS},
Expand Down