Get family and style names from FreeType

This commit is contained in:
Kovid Goyal 2012-10-20 14:14:24 +05:30
parent 42f2f945e7
commit 407cd60dda
2 changed files with 41 additions and 19 deletions

View File

@ -17,7 +17,7 @@ static PyObject *FreeTypeError = NULL;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
FT_Face *face; FT_Face face;
// Every face must keep a reference to the FreeType library object to // Every face must keep a reference to the FreeType library object to
// ensure it is garbage collected before the library object, to prevent // ensure it is garbage collected before the library object, to prevent
// segfaults. // segfaults.
@ -26,7 +26,7 @@ typedef struct {
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
FT_Library *library; FT_Library library;
} FreeType; } FreeType;
// Face.__init__() {{{ // Face.__init__() {{{
@ -35,8 +35,7 @@ Face_dealloc(Face* self)
{ {
if (self->face != NULL) { if (self->face != NULL) {
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
FT_Done_Face(*(self->face)); FT_Done_Face(self->face);
free(self->face);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
} }
self->face = NULL; self->face = NULL;
@ -56,17 +55,15 @@ Face_init(Face *self, PyObject *args, PyObject *kwds)
PyObject *ft; PyObject *ft;
if (!PyArg_ParseTuple(args, "Os#", &ft, &data, &sz)) return -1; if (!PyArg_ParseTuple(args, "Os#", &ft, &data, &sz)) return -1;
self->face = (FT_Face*)calloc(1, sizeof(FT_Face));
if (self->face == NULL) { PyErr_NoMemory(); return -1; }
self->library = ft; self->library = ft;
Py_XINCREF(ft); Py_XINCREF(ft);
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
error = FT_New_Memory_Face( *(( (FreeType*)ft )->library), error = FT_New_Memory_Face( ( (FreeType*)ft )->library,
(const FT_Byte*)data, (FT_Long)sz, 0, self->face); (const FT_Byte*)data, (FT_Long)sz, 0, &self->face);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (error) { if (error) {
free(self->face); self->face = NULL; self->face = NULL;
if ( error == FT_Err_Unknown_File_Format || error == FT_Err_Invalid_Stream_Operation) if ( error == FT_Err_Unknown_File_Format || error == FT_Err_Invalid_Stream_Operation)
PyErr_SetString(FreeTypeError, "Not a supported font format"); PyErr_SetString(FreeTypeError, "Not a supported font format");
else else
@ -78,22 +75,30 @@ Face_init(Face *self, PyObject *args, PyObject *kwds)
// }}} // }}}
static PyObject *
family_name(Face *self, void *closure) {
return Py_BuildValue("s", self->face->family_name);
}
static PyObject *
style_name(Face *self, void *closure) {
return Py_BuildValue("s", self->face->style_name);
}
static PyObject* static PyObject*
supports_text(Face *self, PyObject *args) { supports_text(Face *self, PyObject *args) {
PyObject *chars, *fast, *ret = Py_True; PyObject *chars, *fast, *ret = Py_True;
Py_ssize_t sz, i; Py_ssize_t sz, i;
FT_ULong code; FT_ULong code;
FT_Face face;
if (!PyArg_ParseTuple(args, "O", &chars)) return NULL; if (!PyArg_ParseTuple(args, "O", &chars)) return NULL;
fast = PySequence_Fast(chars, "List of chars is not a sequence"); fast = PySequence_Fast(chars, "List of chars is not a sequence");
if (fast == NULL) return NULL; if (fast == NULL) return NULL;
sz = PySequence_Fast_GET_SIZE(fast); sz = PySequence_Fast_GET_SIZE(fast);
face = *(self->face);
for (i = 0; i < sz; i++) { for (i = 0; i < sz; i++) {
code = (FT_ULong)PyNumber_AsSsize_t(PySequence_Fast_GET_ITEM(fast, i), NULL); code = (FT_ULong)PyNumber_AsSsize_t(PySequence_Fast_GET_ITEM(fast, i), NULL);
if (FT_Get_Char_Index(face, code) == 0) { if (FT_Get_Char_Index(self->face, code) == 0) {
ret = Py_False; ret = Py_False;
break; break;
} }
@ -104,6 +109,20 @@ supports_text(Face *self, PyObject *args) {
return ret; return ret;
} }
static PyGetSetDef Face_getsetters[] = {
{(char *)"family_name",
(getter)family_name, NULL,
(char *)"The family name of this font.",
NULL},
{(char *)"style_name",
(getter)style_name, NULL,
(char *)"The style name of this font.",
NULL},
{NULL} /* Sentinel */
};
static PyMethodDef Face_methods[] = { static PyMethodDef Face_methods[] = {
{"supports_text", (PyCFunction)supports_text, METH_VARARGS, {"supports_text", (PyCFunction)supports_text, METH_VARARGS,
"supports_text(sequence of unicode character codes) -> Return True iff this font has glyphs for all the specified characters." "supports_text(sequence of unicode character codes) -> Return True iff this font has glyphs for all the specified characters."
@ -118,8 +137,7 @@ dealloc(FreeType* self)
{ {
if (self->library != NULL) { if (self->library != NULL) {
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
FT_Done_FreeType(*(self->library)); FT_Done_FreeType(self->library);
free(self->library);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
} }
self->library = NULL; self->library = NULL;
@ -131,13 +149,10 @@ static int
init(FreeType *self, PyObject *args, PyObject *kwds) init(FreeType *self, PyObject *args, PyObject *kwds)
{ {
FT_Error error = 0; FT_Error error = 0;
self->library = (FT_Library*)calloc(1, sizeof(FT_Library));
if (self->library == NULL) { PyErr_NoMemory(); return -1; }
Py_BEGIN_ALLOW_THREADS; Py_BEGIN_ALLOW_THREADS;
error = FT_Init_FreeType(self->library); error = FT_Init_FreeType(&self->library);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (error) { if (error) {
free(self->library);
self->library = NULL; self->library = NULL;
PyErr_Format(FreeTypeError, "Failed to initialize the FreeType library with error: %d", error); PyErr_Format(FreeTypeError, "Failed to initialize the FreeType library with error: %d", error);
return -1; return -1;
@ -178,7 +193,7 @@ static PyTypeObject FaceType = { // {{{
0, /* tp_iternext */ 0, /* tp_iternext */
Face_methods, /* tp_methods */ Face_methods, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ Face_getsetters, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */

View File

@ -33,6 +33,13 @@ class Face(object):
def __init__(self, face): def __init__(self, face):
self.start_thread = threading.current_thread() self.start_thread = threading.current_thread()
self.face = face self.face = face
for x in ('family_name', 'style_name'):
val = getattr(self.face, x)
try:
val = val.decode('utf-8')
except UnicodeDecodeError:
val = repr(val).decode('utf-8')
setattr(self, x, val)
@same_thread @same_thread
def supports_text(self, text): def supports_text(self, text):