Ensure fontconfig pattern dict has all keys with default values

This commit is contained in:
Kovid Goyal 2024-04-22 19:17:28 +05:30
parent 189ec26dbc
commit 00dc8f0e23
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C

View file

@ -147,39 +147,39 @@ pyspacing(int val) {
#undef S
}
static PyObject*
increment_and_return(PyObject *x) { if (x) Py_INCREF(x); return x; }
static PyObject*
pattern_as_dict(FcPattern *pat) {
PyObject *ans = Py_BuildValue("{ss}", "descriptor_type", "fontconfig"), *p = NULL, *list = NULL;
RAII_PyObject(ans, Py_BuildValue("{ss}", "descriptor_type", "fontconfig"));
if (ans == NULL) return NULL;
#define PS(x) PyUnicode_Decode((const char*)x, strlen((const char*)x), "UTF-8", "replace")
#define G(type, get, which, conv, name) { \
#define G(type, get, which, conv, name, default) { \
type out; \
if (get(pat, which, 0, &out) == FcResultMatch) { \
p = conv(out); if (p == NULL) goto exit; \
if (PyDict_SetItemString(ans, #name, p) != 0) goto exit; \
Py_CLEAR(p); \
}}
RAII_PyObject(p, conv(out)); \
if (!p || PyDict_SetItemString(ans, #name, p) != 0) return NULL; \
} else { RAII_PyObject(d, default); if (!d || PyDict_SetItemString(ans, #name, d) != 0) return NULL; } \
}
#define L(type, get, which, conv, name) { \
type out; int n = 0; \
list = PyList_New(0); \
if (!list) goto exit; \
RAII_PyObject(list, PyList_New(0)); \
if (!list) return NULL; \
while (get(pat, which, n++, &out) == FcResultMatch) { \
p = conv(out); if (p == NULL) goto exit; \
if (PyList_Append(list, p) != 0) goto exit; \
Py_CLEAR(p); \
RAII_PyObject(p, conv(out)); \
if (!p || PyList_Append(list, p) != 0) return NULL; \
} \
if (PyDict_SetItemString(ans, #name, list) != 0) goto exit; \
Py_CLEAR(list); \
if (PyDict_SetItemString(ans, #name, list) != 0) return NULL; \
}
#define S(which, key) G(FcChar8*, FcPatternGetString, which, PS, key)
#define S(which, key) G(FcChar8*, FcPatternGetString, which, PS, key, PyUnicode_FromString(""))
#define LS(which, key) L(FcChar8*, FcPatternGetString, which, PS, key)
#define I(which, key) G(int, FcPatternGetInteger, which, PyLong_FromLong, key)
#define B(which, key) G(int, FcPatternGetBool, which, pybool, key)
#define E(which, key, conv) G(int, FcPatternGetInteger, which, conv, key)
#define I(which, key) G(int, FcPatternGetInteger, which, PyLong_FromLong, key, PyLong_FromUnsignedLong(0))
#define B(which, key) G(int, FcPatternGetBool, which, pybool, key, increment_and_return(Py_False))
#define E(which, key, conv) G(int, FcPatternGetInteger, which, conv, key, PyLong_FromUnsignedLong(0))
S(FC_FILE, path);
S(FC_FAMILY, family);
S(FC_STYLE, style);
@ -199,11 +199,8 @@ pattern_as_dict(FcPattern *pat) {
B(FC_OUTLINE, outline);
B(FC_COLOR, color);
E(FC_SPACING, spacing, pyspacing);
exit:
if (PyErr_Occurred()) Py_CLEAR(ans);
Py_CLEAR(p);
Py_CLEAR(list);
Py_INCREF(ans);
return ans;
#undef PS
#undef S