Code to list fontconfig fonts
This commit is contained in:
parent
6d02e884d8
commit
e15bc71930
@ -8,6 +8,97 @@
|
||||
#include "data-types.h"
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
static inline PyObject*
|
||||
pybool(FcBool x) { PyObject *ans = x ? Py_True: Py_False; Py_INCREF(ans); return ans; }
|
||||
|
||||
static inline PyObject*
|
||||
pyspacing(int val) {
|
||||
#define S(x) case FC_##x: return PyUnicode_FromString(#x)
|
||||
switch(val) { S(PROPORTIONAL); S(DUAL); S(MONO); S(CHARCELL); default: return PyUnicode_FromString("UNKNOWN"); }
|
||||
#undef S
|
||||
}
|
||||
|
||||
static inline PyObject*
|
||||
pattern_as_dict(FcPattern *pat) {
|
||||
PyObject *ans = PyDict_New();
|
||||
if (ans == NULL) return NULL;
|
||||
#define PS(x) PyUnicode_FromString((char*)x)
|
||||
#define G(type, get, which, conv, name) { \
|
||||
type out; PyObject *p; \
|
||||
if (get(pat, which, 0, &out) == FcResultMatch) { p = conv(out); if (p == NULL) { Py_CLEAR(ans); return NULL; } \
|
||||
} else { p = Py_None; Py_INCREF(p); } \
|
||||
if (PyDict_SetItemString(ans, #name, p) != 0) { Py_CLEAR(p); Py_CLEAR(ans); return NULL; } \
|
||||
Py_CLEAR(p); \
|
||||
}
|
||||
#define S(which, key) G(FcChar8*, FcPatternGetString, which, PS, key)
|
||||
#define I(which, key) G(int, FcPatternGetInteger, which, PyLong_FromLong, key)
|
||||
#define B(which, key) G(int, FcPatternGetInteger, which, pybool, key)
|
||||
#define E(which, key, conv) G(int, FcPatternGetInteger, which, conv, key)
|
||||
S(FC_FILE, path);
|
||||
S(FC_FAMILY, family);
|
||||
S(FC_STYLE, style);
|
||||
S(FC_FULLNAME, fullname);
|
||||
S(FC_POSTSCRIPT_NAME, psname);
|
||||
I(FC_WEIGHT, weight);
|
||||
I(FC_SLANT, slant);
|
||||
I(FC_HINT_STYLE, hint_style);
|
||||
I(FC_INDEX, index);
|
||||
B(FC_HINTING, hinting);
|
||||
B(FC_SCALABLE, scalable);
|
||||
B(FC_OUTLINE, outline);
|
||||
B(FC_COLOR, color);
|
||||
E(FC_SPACING, spacing, pyspacing);
|
||||
|
||||
return ans;
|
||||
#undef PS
|
||||
#undef S
|
||||
#undef I
|
||||
#undef B
|
||||
#undef E
|
||||
#undef G
|
||||
}
|
||||
|
||||
static inline PyObject*
|
||||
font_set(FcFontSet *fs) {
|
||||
PyObject *ans = PyTuple_New(fs->nfont);
|
||||
if (ans == NULL) return NULL;
|
||||
for (int i = 0; i < fs->nfont; i++) {
|
||||
PyObject *d = pattern_as_dict(fs->fonts[i]);
|
||||
if (d == NULL) { Py_CLEAR(ans); break; }
|
||||
PyTuple_SET_ITEM(ans, i, d);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
list_fontconfig_fonts(PyObject UNUSED *self, PyObject *args) {
|
||||
int allow_bitmapped_fonts = 0, only_monospaced_fonts = 1;
|
||||
PyObject *ans = NULL;
|
||||
FcObjectSet *os = NULL;
|
||||
FcPattern *pat = NULL;
|
||||
FcFontSet *fs = NULL;
|
||||
if (!PyArg_ParseTuple(args, "|pp", &only_monospaced_fonts, &allow_bitmapped_fonts)) return NULL;
|
||||
pat = FcPatternCreate();
|
||||
if (pat == NULL) return PyErr_NoMemory();
|
||||
#define AP(func, which, in, desc) if (!func(pat, which, in)) { PyErr_Format(PyExc_ValueError, "Failed to add %s to fontconfig pattern", desc, NULL); goto end; }
|
||||
if (!allow_bitmapped_fonts) {
|
||||
AP(FcPatternAddBool, FC_OUTLINE, true, "outline");
|
||||
AP(FcPatternAddBool, FC_SCALABLE, true, "scalable");
|
||||
}
|
||||
if (only_monospaced_fonts) AP(FcPatternAddInteger, FC_SPACING, FC_MONO, "spacing");
|
||||
#undef AP
|
||||
os = FcObjectSetBuild(FC_FILE, FC_POSTSCRIPT_NAME, FC_FAMILY, FC_STYLE, FC_FULLNAME, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_HINT_STYLE, FC_INDEX, FC_HINTING, FC_SCALABLE, FC_OUTLINE, FC_COLOR, FC_SPACING, NULL);
|
||||
if (!os) { PyErr_SetString(PyExc_ValueError, "Failed to create fontconfig object set"); goto end; }
|
||||
fs = FcFontList(NULL, pat, os);
|
||||
if (!fs) { PyErr_SetString(PyExc_ValueError, "Failed to create fontconfig font set"); goto end; }
|
||||
ans = font_set(fs);
|
||||
end:
|
||||
if (pat != NULL) FcPatternDestroy(pat);
|
||||
if (os != NULL) FcObjectSetDestroy(os);
|
||||
if (fs != NULL) FcFontSetDestroy(fs);
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
get_fontconfig_font(PyObject UNUSED *self, PyObject *args) {
|
||||
char *family;
|
||||
@ -82,7 +173,8 @@ end:
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
{"get_fontconfig_font", (PyCFunction)get_fontconfig_font, METH_VARARGS, ""},
|
||||
METHODB(list_fontconfig_fonts, METH_VARARGS),
|
||||
METHODB(get_fontconfig_font, METH_VARARGS),
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user