226 static size_t
227 text_layout_raqm(
228 PyObject *string,
229 FontObject *self,
230 const char *dir,
231 PyObject *features,
232 const char *lang,
233 GlyphInfo **glyph_info,
234 int mask,
235 int color) {
236 size_t i = 0, count = 0, start = 0;
237 raqm_t *rq;
238 raqm_glyph_t *glyphs = NULL;
239 raqm_direction_t direction;
240
241 rq = raqm_create();
242 if (rq == NULL) {
when treating unknown struct raqm_t * from src/_imagingft.c:241 as non-NULL
taking False path
243 PyErr_SetString(PyExc_ValueError, "raqm_create() failed.");
244 goto failed;
245 }
246
247 if (PyUnicode_Check(string)) {
when considering range: 1 <= value <= 0x10000000
taking True path
248 Py_UCS4 *text = PyUnicode_AsUCS4Copy(string);
249 Py_ssize_t size = PyUnicode_GET_LENGTH(string);
250 if (!text || !size) {
when treating unknown Py_UCS4 * from src/_imagingft.c:248 as non-NULL
when considering range: -0x8000000000000000 <= value <= -1
taking False path
251 /* return 0 and clean up, no glyphs==no size,
252 and raqm fails with empty strings */
253 goto failed;
254 }
255 int set_text = raqm_set_text(rq, text, size);
256 PyMem_Free(text);
calling PyMem_Free on Region('heap-region-26')
257 if (!set_text) {
when taking False path
258 PyErr_SetString(PyExc_ValueError, "raqm_set_text() failed");
259 goto failed;
260 }
261 if (lang) {
when taking True path
262 if (!raqm_set_language(rq, lang, start, size)) {
when taking False path
263 PyErr_SetString(PyExc_ValueError, "raqm_set_language() failed");
264 goto failed;
265 }
266 }
267 } else {
268 PyErr_SetString(PyExc_TypeError, "expected string");
269 goto failed;
270 }
271
272 direction = RAQM_DIRECTION_DEFAULT;
273 if (dir) {
when taking True path
274 if (strcmp(dir, "rtl") == 0) {
when considering range: -0x80000000 <= value <= -1
taking False path
275 direction = RAQM_DIRECTION_RTL;
276 } else if (strcmp(dir, "ltr") == 0) {
when considering value == (int)0 from src/_imagingft.c:276
taking True path
277 direction = RAQM_DIRECTION_LTR;
278 } else if (strcmp(dir, "ttb") == 0) {
279 direction = RAQM_DIRECTION_TTB;
280 #if !defined(RAQM_VERSION_ATLEAST)
281 /* RAQM_VERSION_ATLEAST was added in Raqm 0.7.0 */
282 PyErr_SetString(
283 PyExc_ValueError,
284 "libraqm 0.7 or greater required for 'ttb' direction");
285 goto failed;
286 #endif
287 } else {
288 PyErr_SetString(
289 PyExc_ValueError, "direction must be either 'rtl', 'ltr' or 'ttb'");
290 goto failed;
291 }
292 }
293
294 if (!raqm_set_par_direction(rq, direction)) {
when taking False path
295 PyErr_SetString(PyExc_ValueError, "raqm_set_par_direction() failed");
296 goto failed;
297 }
298
299 if (features != Py_None) {
taking True path
300 int j, len;
301 PyObject *seq = PySequence_Fast(features, "expected a sequence");
when PySequence_Fast() succeeds
'*seq' was allocated at: PyObject *seq = PySequence_Fast(features, "expected a sequence");
ob_refcnt is now refs: 1 owned
302 if (!seq) {
taking False path
303 goto failed;
304 }
305
306 len = PySequence_Size(seq);
when PySequence_Size() succeeds
307 for (j = 0; j < len; j++) {
when considering len == (Py_ssize_t)0 from src/_imagingft.c:306
taking False path
308 PyObject *item = PySequence_Fast_GET_ITEM(seq, j);
309 char *feature = NULL;
310 Py_ssize_t size = 0;
311 PyObject *bytes;
312
313 if (!PyUnicode_Check(item)) {
314 PyErr_SetString(PyExc_TypeError, "expected a string");
315 goto failed;
316 }
317
318 if (PyUnicode_Check(item)) {
319 bytes = PyUnicode_AsUTF8String(item);
320 if (bytes == NULL) {
321 goto failed;
322 }
323 feature = PyBytes_AS_STRING(bytes);
324 size = PyBytes_GET_SIZE(bytes);
325 }
326 if (!raqm_add_font_feature(rq, feature, size)) {
327 PyErr_SetString(PyExc_ValueError, "raqm_add_font_feature() failed");
328 goto failed;
329 }
330 }
331 }
332
333 if (!raqm_set_freetype_face(rq, self->face)) {
when taking True path
334 PyErr_SetString(PyExc_RuntimeError, "raqm_set_freetype_face() failed.");
calling PyErr_SetString()
335 goto failed;
336 }
337
338 if (!raqm_layout(rq)) {
339 PyErr_SetString(PyExc_RuntimeError, "raqm_layout() failed.");
340 goto failed;
341 }
342
343 glyphs = raqm_get_glyphs(rq, &count);
344 if (glyphs == NULL) {
345 PyErr_SetString(PyExc_ValueError, "raqm_get_glyphs() failed.");
346 count = 0;
347 goto failed;
348 }
349
350 (*glyph_info) = PyMem_New(GlyphInfo, count);
351 if ((*glyph_info) == NULL) {
352 PyErr_SetString(PyExc_MemoryError, "PyMem_New() failed");
353 count = 0;
354 goto failed;
355 }
356
357 for (i = 0; i < count; i++) {
358 (*glyph_info)[i].index = glyphs[i].index;
359 (*glyph_info)[i].x_offset = glyphs[i].x_offset;
360 (*glyph_info)[i].x_advance = glyphs[i].x_advance;
361 (*glyph_info)[i].y_offset = glyphs[i].y_offset;
362 (*glyph_info)[i].y_advance = glyphs[i].y_advance;
363 (*glyph_info)[i].cluster = glyphs[i].cluster;
364 }
365
366 failed:
367 raqm_destroy(rq);
368 return count;
returning
memory leak: ob_refcnt of '*seq' is 1 too high
was expecting final owned ob_refcnt of '*seq' to be 0 since nothing references it but final ob_refcnt is refs: 1 owned
found 6 similar trace(s) to this
369 }