mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Get family and style names from FreeType
This commit is contained in:
parent
42f2f945e7
commit
407cd60dda
@ -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 */
|
||||||
|
@ -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):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user