Bug Summary

File:_imagingft.c
Warning:line 1124, column 35
PyObject ownership leak with reference count of 1

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name _imagingft.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/Pillow/csa-scan,ctu-index-name=/tmp/pyrefcon/Pillow/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/Pillow/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/pyrefcon/Pillow -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -D NDEBUG -D _FORTIFY_SOURCE=2 -D HAVE_RAQM -D HAVE_RAQM_SYSTEM -I /usr/include/freetype2 -I /usr/include/openjpeg-2.3 -I /tmp/pyrefcon/Pillow -I /usr/include/x86_64-linux-gnu -I /usr/include/fribidi -I /usr/include -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wsign-compare -Wall -Wformat -Werror=format-security -Wformat -Werror=format-security -Wdate-time -fdebug-compilation-dir=/tmp/pyrefcon/Pillow -ferror-limit 19 -fwrapv -pthread -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/Pillow/csa-scan/reports -x c src/_imagingft.c

src/_imagingft.c

1/*
2 * PIL FreeType Driver
3 *
4 * a FreeType 2.X driver for PIL
5 *
6 * history:
7 * 2001-02-17 fl Created (based on old experimental freetype 1.0 code)
8 * 2001-04-18 fl Fixed some egcs compiler nits
9 * 2002-11-08 fl Added unicode support; more font metrics, etc
10 * 2003-05-20 fl Fixed compilation under 1.5.2 and newer non-unicode builds
11 * 2003-09-27 fl Added charmap encoding support
12 * 2004-05-15 fl Fixed compilation for FreeType 2.1.8
13 * 2004-09-10 fl Added support for monochrome bitmaps
14 * 2006-06-18 fl Fixed glyph bearing calculation
15 * 2007-12-23 fl Fixed crash in family/style attribute fetch
16 * 2008-01-02 fl Handle Unicode filenames properly
17 *
18 * Copyright (c) 1998-2007 by Secret Labs AB
19 */
20
21#define PY_SSIZE_T_CLEAN
22#include "Python.h"
23#include "libImaging/Imaging.h"
24
25#include <ft2build.h>
26#include FT_FREETYPE_H<freetype/freetype.h>
27#include FT_GLYPH_H<freetype/ftglyph.h>
28#include FT_BITMAP_H<freetype/ftbitmap.h>
29#include FT_STROKER_H<freetype/ftstroke.h>
30#include FT_MULTIPLE_MASTERS_H<freetype/ftmm.h>
31#include FT_SFNT_NAMES_H<freetype/ftsnames.h>
32#ifdef FT_COLOR_H<freetype/ftcolor.h>
33#include FT_COLOR_H<freetype/ftcolor.h>
34#endif
35
36#define KEEP_PY_UNICODE
37
38#if !defined(FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 ))
39#define FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 ) FT_LOAD_MONOCHROME( 1L << 12 )
40#endif
41
42/* -------------------------------------------------------------------- */
43/* error table */
44
45#undef FTERRORS_H
46#undef __FTERRORS_H__
47
48#define FT_ERRORDEF(e, v, s) {e, s},
49#define FT_ERROR_START_LIST {
50#define FT_ERROR_END_LIST \
51 { 0, 0 } \
52 } \
53 ;
54
55#ifdef HAVE_RAQM1
56# ifdef HAVE_RAQM_SYSTEM1
57# include <raqm.h>
58# else
59# include "thirdparty/raqm/raqm.h"
60# ifdef HAVE_FRIBIDI_SYSTEM
61# include <fribidi.h>
62# else
63# include "thirdparty/fribidi-shim/fribidi.h"
64# include <hb.h>
65# endif
66# endif
67#endif
68
69static int have_raqm = 0;
70
71#define LAYOUT_FALLBACK0 0
72#define LAYOUT_RAQM1 1
73
74typedef struct {
75 int index, x_offset, x_advance, y_offset, y_advance;
76 unsigned int cluster;
77} GlyphInfo;
78
79struct {
80 int code;
81 const char *message;
82} ft_errors[] =
83
84#include FT_ERRORS_H<freetype/fterrors.h>
85
86 /* -------------------------------------------------------------------- */
87 /* font objects */
88
89 static FT_Library library;
90
91typedef struct {
92 PyObject_HEADPyObject ob_base; FT_Face face;
93 unsigned char *font_bytes;
94 int layout_engine;
95} FontObject;
96
97static PyTypeObject Font_Type;
98
99/* round a 26.6 pixel coordinate to the nearest integer */
100#define PIXEL(x)((((x) + 32) & -64) >> 6) ((((x) + 32) & -64) >> 6)
101
102static PyObject *
103geterror(int code) {
104 int i;
105
106 for (i = 0; ft_errors[i].message; i++) {
107 if (ft_errors[i].code == code) {
108 PyErr_SetString(PyExc_OSError, ft_errors[i].message);
109 return NULL((void*)0);
110 }
111 }
112
113 PyErr_SetString(PyExc_OSError, "unknown freetype error");
114 return NULL((void*)0);
115}
116
117static PyObject *
118getfont(PyObject *self_, PyObject *args, PyObject *kw) {
119 /* create a font object from a file name and a size (in pixels) */
120
121 FontObject *self;
122 int error = 0;
123
124 char *filename = NULL((void*)0);
125 Py_ssize_t size;
126 Py_ssize_t index = 0;
127 Py_ssize_t layout_engine = 0;
128 unsigned char *encoding;
129 unsigned char *font_bytes;
130 Py_ssize_t font_bytes_size = 0;
131 static char *kwlist[] = {
132 "filename", "size", "index", "encoding", "font_bytes", "layout_engine", NULL((void*)0)};
133
134 if (!library) {
135 PyErr_SetString(PyExc_OSError, "failed to initialize FreeType library");
136 return NULL((void*)0);
137 }
138
139 if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(
140 args,
141 kw,
142 "etn|nsy#n",
143 kwlist,
144 Py_FileSystemDefaultEncoding,
145 &filename,
146 &size,
147 &index,
148 &encoding,
149 &font_bytes,
150 &font_bytes_size,
151 &layout_engine)) {
152 return NULL((void*)0);
153 }
154
155 self = PyObject_New(FontObject, &Font_Type)( (FontObject *) _PyObject_New(&Font_Type) );
156 if (!self) {
157 if (filename) {
158 PyMem_Free(filename);
159 }
160 return NULL((void*)0);
161 }
162
163 self->face = NULL((void*)0);
164 self->layout_engine = layout_engine;
165
166 if (filename && font_bytes_size <= 0) {
167 self->font_bytes = NULL((void*)0);
168 error = FT_New_Face(library, filename, index, &self->face);
169 } else {
170 /* need to have allocated storage for font_bytes for the life of the object.*/
171 /* Don't free this before FT_Done_Face */
172 self->font_bytes = PyMem_Malloc(font_bytes_size);
173 if (!self->font_bytes) {
174 error = 65; // Out of Memory in Freetype.
175 }
176 if (!error) {
177 memcpy(self->font_bytes, font_bytes, (size_t)font_bytes_size);
178 error = FT_New_Memory_Face(
179 library,
180 (FT_Byte *)self->font_bytes,
181 font_bytes_size,
182 index,
183 &self->face);
184 }
185 }
186
187 if (!error) {
188 error = FT_Set_Pixel_Sizes(self->face, 0, size);
189 }
190
191 if (!error && encoding && strlen((char *)encoding) == 4) {
192 FT_Encoding encoding_tag =
193 FT_MAKE_TAG(encoding[0], encoding[1], encoding[2], encoding[3])(FT_Tag) ( ( (FT_ULong)encoding[0] << 24 ) | ( (FT_ULong
)encoding[1] << 16 ) | ( (FT_ULong)encoding[2] <<
8 ) | (FT_ULong)encoding[3] )
;
194 error = FT_Select_Charmap(self->face, encoding_tag);
195 }
196 if (filename) {
197 PyMem_Free(filename);
198 }
199
200 if (error) {
201 if (self->font_bytes) {
202 PyMem_Free(self->font_bytes);
203 self->font_bytes = NULL((void*)0);
204 }
205 Py_DECREF(self)_Py_DECREF(((PyObject*)(self)));
206 return geterror(error);
207 }
208
209 return (PyObject *)self;
210}
211
212static int
213font_getchar(PyObject *string, int index, FT_ULong *char_out) {
214 if (PyUnicode_Check(string)((((((PyObject*)(string))->ob_type))->tp_flags & ((
1UL << 28))) != 0)
) {
215 if (index >= PyUnicode_GET_LENGTH(string)(((void) (0)), ((void) (0)), ((PyASCIIObject *)(string))->
length)
) {
216 return 0;
217 }
218 *char_out = PyUnicode_READ_CHAR(string, index)(((void) (0)), ((void) (0)), (Py_UCS4) ((((void) (0)), ((void
) (0)), ((PyASCIIObject *)((string)))->state.kind) == PyUnicode_1BYTE_KIND
? ((const Py_UCS1 *)((((void) (0)), (((PyASCIIObject*)((string
)))->state.compact) ? ((((void) (0)), ((void) (0)), ((PyASCIIObject
*)(string))->state.ascii) ? ((void*)((PyASCIIObject*)((string
)) + 1)) : ((void*)((PyCompactUnicodeObject*)((string)) + 1))
) : (((void) (0)), ((((PyUnicodeObject *)((string)))->data
.any))))))[(index)] : ((((void) (0)), ((void) (0)), ((PyASCIIObject
*)((string)))->state.kind) == PyUnicode_2BYTE_KIND ? ((const
Py_UCS2 *)((((void) (0)), (((PyASCIIObject*)((string)))->
state.compact) ? ((((void) (0)), ((void) (0)), ((PyASCIIObject
*)(string))->state.ascii) ? ((void*)((PyASCIIObject*)((string
)) + 1)) : ((void*)((PyCompactUnicodeObject*)((string)) + 1))
) : (((void) (0)), ((((PyUnicodeObject *)((string)))->data
.any))))))[(index)] : ((const Py_UCS4 *)((((void) (0)), (((PyASCIIObject
*)((string)))->state.compact) ? ((((void) (0)), ((void) (0
)), ((PyASCIIObject*)(string))->state.ascii) ? ((void*)((PyASCIIObject
*)((string)) + 1)) : ((void*)((PyCompactUnicodeObject*)((string
)) + 1))) : (((void) (0)), ((((PyUnicodeObject *)((string)))->
data.any))))))[(index)] ) ))
;
219 return 1;
220 }
221 return 0;
222}
223
224#ifdef HAVE_RAQM1
225
226static size_t
227text_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((void*)0);
239 raqm_direction_t direction;
240
241 rq = raqm_create();
242 if (rq == NULL((void*)0)) {
243 PyErr_SetString(PyExc_ValueError, "raqm_create() failed.");
244 goto failed;
245 }
246
247 if (PyUnicode_Check(string)((((((PyObject*)(string))->ob_type))->tp_flags & ((
1UL << 28))) != 0)
) {
248 Py_UCS4 *text = PyUnicode_AsUCS4Copy(string);
249 Py_ssize_t size = PyUnicode_GET_LENGTH(string)(((void) (0)), ((void) (0)), ((PyASCIIObject *)(string))->
length)
;
250 if (!text || !size) {
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);
257 if (!set_text) {
258 PyErr_SetString(PyExc_ValueError, "raqm_set_text() failed");
259 goto failed;
260 }
261 if (lang) {
262 if (!raqm_set_language(rq, lang, start, size)) {
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) {
274 if (strcmp(dir, "rtl") == 0) {
275 direction = RAQM_DIRECTION_RTL;
276 } else if (strcmp(dir, "ltr") == 0) {
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)) {
295 PyErr_SetString(PyExc_ValueError, "raqm_set_par_direction() failed");
296 goto failed;
297 }
298
299 if (features != Py_None(&_Py_NoneStruct)) {
300 int j, len;
301 PyObject *seq = PySequence_Fast(features, "expected a sequence");
302 if (!seq) {
303 goto failed;
304 }
305
306 len = PySequence_Size(seq);
307 for (j = 0; j < len; j++) {
308 PyObject *item = PySequence_Fast_GET_ITEM(seq, j)(((((((PyObject*)(seq))->ob_type))->tp_flags & ((1UL
<< 25))) != 0) ? (((PyListObject *)(seq))->ob_item[
j]) : ((((void) (0)), (PyTupleObject *)(seq))->ob_item[j])
)
;
309 char *feature = NULL((void*)0);
310 Py_ssize_t size = 0;
311 PyObject *bytes;
312
313 if (!PyUnicode_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL
<< 28))) != 0)
) {
314 PyErr_SetString(PyExc_TypeError, "expected a string");
315 goto failed;
316 }
317
318 if (PyUnicode_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL
<< 28))) != 0)
) {
319 bytes = PyUnicode_AsUTF8String(item);
320 if (bytes == NULL((void*)0)) {
321 goto failed;
322 }
323 feature = PyBytes_AS_STRING(bytes)(((void) (0)), (((PyBytesObject *)(bytes))->ob_sval));
324 size = PyBytes_GET_SIZE(bytes)(((void) (0)),(((PyVarObject*)(bytes))->ob_size));
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)) {
334 PyErr_SetString(PyExc_RuntimeError, "raqm_set_freetype_face() failed.");
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((void*)0)) {
345 PyErr_SetString(PyExc_ValueError, "raqm_get_glyphs() failed.");
346 count = 0;
347 goto failed;
348 }
349
350 (*glyph_info) = PyMem_New(GlyphInfo, count)( ((size_t)(count) > ((Py_ssize_t)(((size_t)-1)>>1))
/ sizeof(GlyphInfo)) ? ((void*)0) : ( (GlyphInfo *) PyMem_Malloc
((count) * sizeof(GlyphInfo)) ) )
;
351 if ((*glyph_info) == NULL((void*)0)) {
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
366failed:
367 raqm_destroy(rq);
368 return count;
369}
370
371#endif
372
373static size_t
374text_layout_fallback(
375 PyObject *string,
376 FontObject *self,
377 const char *dir,
378 PyObject *features,
379 const char *lang,
380 GlyphInfo **glyph_info,
381 int mask,
382 int color) {
383 int error, load_flags;
384 FT_ULong ch;
385 Py_ssize_t count;
386 FT_GlyphSlot glyph;
387 FT_Bool kerning = FT_HAS_KERNING(self->face)( (self->face)->face_flags & ( 1L << 6 ) );
388 FT_UInt last_index = 0;
389 int i;
390
391 if (features != Py_None(&_Py_NoneStruct) || dir != NULL((void*)0) || lang != NULL((void*)0)) {
392 PyErr_SetString(
393 PyExc_KeyError,
394 "setting text direction, language or font features is not supported "
395 "without libraqm");
396 }
397 if (!PyUnicode_Check(string)((((((PyObject*)(string))->ob_type))->tp_flags & ((
1UL << 28))) != 0)
) {
398 PyErr_SetString(PyExc_TypeError, "expected string");
399 return 0;
400 }
401
402 count = 0;
403 while (font_getchar(string, count, &ch)) {
404 count++;
405 }
406 if (count == 0) {
407 return 0;
408 }
409
410 (*glyph_info) = PyMem_New(GlyphInfo, count)( ((size_t)(count) > ((Py_ssize_t)(((size_t)-1)>>1))
/ sizeof(GlyphInfo)) ? ((void*)0) : ( (GlyphInfo *) PyMem_Malloc
((count) * sizeof(GlyphInfo)) ) )
;
411 if ((*glyph_info) == NULL((void*)0)) {
412 PyErr_SetString(PyExc_MemoryError, "PyMem_New() failed");
413 return 0;
414 }
415
416 load_flags = FT_LOAD_DEFAULT0x0;
417 if (mask) {
418 load_flags |= FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 );
419 }
420#ifdef FT_LOAD_COLOR( 1L << 20 )
421 if (color) {
422 load_flags |= FT_LOAD_COLOR( 1L << 20 );
423 }
424#endif
425 for (i = 0; font_getchar(string, i, &ch); i++) {
426 (*glyph_info)[i].index = FT_Get_Char_Index(self->face, ch);
427 error = FT_Load_Glyph(self->face, (*glyph_info)[i].index, load_flags);
428 if (error) {
429 geterror(error);
430 return 0;
431 }
432 glyph = self->face->glyph;
433 (*glyph_info)[i].x_offset = 0;
434 (*glyph_info)[i].y_offset = 0;
435 if (kerning && last_index && (*glyph_info)[i].index) {
436 FT_Vector delta;
437 if (FT_Get_Kerning(
438 self->face,
439 last_index,
440 (*glyph_info)[i].index,
441 ft_kerning_defaultFT_KERNING_DEFAULT,
442 &delta) == 0) {
443 (*glyph_info)[i - 1].x_advance += PIXEL(delta.x)((((delta.x) + 32) & -64) >> 6);
444 (*glyph_info)[i - 1].y_advance += PIXEL(delta.y)((((delta.y) + 32) & -64) >> 6);
445 }
446 }
447
448 (*glyph_info)[i].x_advance = glyph->metrics.horiAdvance;
449 // y_advance is only used in ttb, which is not supported by basic layout
450 (*glyph_info)[i].y_advance = 0;
451 last_index = (*glyph_info)[i].index;
452 (*glyph_info)[i].cluster = ch;
453 }
454 return count;
455}
456
457static size_t
458text_layout(
459 PyObject *string,
460 FontObject *self,
461 const char *dir,
462 PyObject *features,
463 const char *lang,
464 GlyphInfo **glyph_info,
465 int mask,
466 int color) {
467 size_t count;
468#ifdef HAVE_RAQM1
469 if (have_raqm && self->layout_engine == LAYOUT_RAQM1) {
470 count = text_layout_raqm(
471 string, self, dir, features, lang, glyph_info, mask, color);
472 } else
473#endif
474 {
475 count = text_layout_fallback(
476 string, self, dir, features, lang, glyph_info, mask, color);
477 }
478 return count;
479}
480
481static PyObject *
482font_getlength(FontObject *self, PyObject *args) {
483 int length; /* length along primary axis, in 26.6 precision */
484 GlyphInfo *glyph_info = NULL((void*)0); /* computed text layout */
485 size_t i, count; /* glyph_info index and length */
486 int horizontal_dir; /* is primary axis horizontal? */
487 int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
488 int color = 0; /* is FT_LOAD_COLOR enabled? */
489 const char *mode = NULL((void*)0);
490 const char *dir = NULL((void*)0);
491 const char *lang = NULL((void*)0);
492 PyObject *features = Py_None(&_Py_NoneStruct);
493 PyObject *string;
494
495 /* calculate size and bearing for a given string */
496
497 if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(
498 args, "O|zzOz:getlength", &string, &mode, &dir, &features, &lang)) {
499 return NULL((void*)0);
500 }
501
502 horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
503
504 mask = mode && strcmp(mode, "1") == 0;
505 color = mode && strcmp(mode, "RGBA") == 0;
506
507 count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
508 if (PyErr_Occurred()) {
509 return NULL((void*)0);
510 }
511
512 length = 0;
513 for (i = 0; i < count; i++) {
514 if (horizontal_dir) {
515 length += glyph_info[i].x_advance;
516 } else {
517 length -= glyph_info[i].y_advance;
518 }
519 }
520
521 if (glyph_info) {
522 PyMem_Free(glyph_info);
523 glyph_info = NULL((void*)0);
524 }
525
526 return PyLong_FromLong(length);
527}
528
529static PyObject *
530font_getsize(FontObject *self, PyObject *args) {
531 int position; /* pen position along primary axis, in 26.6 precision */
532 int advanced; /* pen position along primary axis, in pixels */
533 int px, py; /* position of current glyph, in pixels */
534 int x_min, x_max, y_min, y_max; /* text bounding box, in pixels */
535 int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */
536 int load_flags; /* FreeType load_flags parameter */
537 int error;
538 FT_Face face;
539 FT_Glyph glyph;
540 FT_BBox bbox; /* glyph bounding box */
541 GlyphInfo *glyph_info = NULL((void*)0); /* computed text layout */
542 size_t i, count; /* glyph_info index and length */
543 int horizontal_dir; /* is primary axis horizontal? */
544 int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
545 int color = 0; /* is FT_LOAD_COLOR enabled? */
546 const char *mode = NULL((void*)0);
547 const char *dir = NULL((void*)0);
548 const char *lang = NULL((void*)0);
549 const char *anchor = NULL((void*)0);
550 PyObject *features = Py_None(&_Py_NoneStruct);
551 PyObject *string;
552
553 /* calculate size and bearing for a given string */
554
555 if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(
556 args, "O|zzOzz:getsize", &string, &mode, &dir, &features, &lang, &anchor)) {
557 return NULL((void*)0);
558 }
559
560 horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
561
562 mask = mode && strcmp(mode, "1") == 0;
563 color = mode && strcmp(mode, "RGBA") == 0;
564
565 if (anchor == NULL((void*)0)) {
566 anchor = horizontal_dir ? "la" : "lt";
567 }
568 if (strlen(anchor) != 2) {
569 goto bad_anchor;
570 }
571
572 count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
573 if (PyErr_Occurred()) {
574 return NULL((void*)0);
575 }
576
577 load_flags = FT_LOAD_DEFAULT0x0;
578 if (mask) {
579 load_flags |= FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 );
580 }
581#ifdef FT_LOAD_COLOR( 1L << 20 )
582 if (color) {
583 load_flags |= FT_LOAD_COLOR( 1L << 20 );
584 }
585#endif
586
587 /*
588 * text bounds are given by:
589 * - bounding boxes of individual glyphs
590 * - pen line, i.e. 0 to `advanced` along primary axis
591 * this means point (0, 0) is part of the text bounding box
592 */
593 face = NULL((void*)0);
594 position = x_min = x_max = y_min = y_max = 0;
595 for (i = 0; i < count; i++) {
596 face = self->face;
597
598 if (horizontal_dir) {
599 px = PIXEL(position + glyph_info[i].x_offset)((((position + glyph_info[i].x_offset) + 32) & -64) >>
6)
;
600 py = PIXEL(glyph_info[i].y_offset)((((glyph_info[i].y_offset) + 32) & -64) >> 6);
601
602 position += glyph_info[i].x_advance;
603 advanced = PIXEL(position)((((position) + 32) & -64) >> 6);
604 if (advanced > x_max) {
605 x_max = advanced;
606 }
607 } else {
608 px = PIXEL(glyph_info[i].x_offset)((((glyph_info[i].x_offset) + 32) & -64) >> 6);
609 py = PIXEL(position + glyph_info[i].y_offset)((((position + glyph_info[i].y_offset) + 32) & -64) >>
6)
;
610
611 position += glyph_info[i].y_advance;
612 advanced = PIXEL(position)((((position) + 32) & -64) >> 6);
613 if (advanced < y_min) {
614 y_min = advanced;
615 }
616 }
617
618 error = FT_Load_Glyph(face, glyph_info[i].index, load_flags);
619 if (error) {
620 return geterror(error);
621 }
622
623 error = FT_Get_Glyph(face->glyph, &glyph);
624 if (error) {
625 return geterror(error);
626 }
627
628 FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
629 bbox.xMax += px;
630 if (bbox.xMax > x_max) {
631 x_max = bbox.xMax;
632 }
633 bbox.xMin += px;
634 if (bbox.xMin < x_min) {
635 x_min = bbox.xMin;
636 }
637 bbox.yMax += py;
638 if (bbox.yMax > y_max) {
639 y_max = bbox.yMax;
640 }
641 bbox.yMin += py;
642 if (bbox.yMin < y_min) {
643 y_min = bbox.yMin;
644 }
645
646 FT_Done_Glyph(glyph);
647 }
648
649 if (glyph_info) {
650 PyMem_Free(glyph_info);
651 glyph_info = NULL((void*)0);
652 }
653
654 x_anchor = y_anchor = 0;
655 if (face) {
656 if (horizontal_dir) {
657 switch (anchor[0]) {
658 case 'l': // left
659 x_anchor = 0;
660 break;
661 case 'm': // middle (left + right) / 2
662 x_anchor = PIXEL(position / 2)((((position / 2) + 32) & -64) >> 6);
663 break;
664 case 'r': // right
665 x_anchor = PIXEL(position)((((position) + 32) & -64) >> 6);
666 break;
667 case 's': // vertical baseline
668 default:
669 goto bad_anchor;
670 }
671 switch (anchor[1]) {
672 case 'a': // ascender
673 y_anchor = PIXEL(self->face->size->metrics.ascender)((((self->face->size->metrics.ascender) + 32) & -
64) >> 6)
;
674 break;
675 case 't': // top
676 y_anchor = y_max;
677 break;
678 case 'm': // middle (ascender + descender) / 2
679 y_anchor = PIXEL((((((self->face->size->metrics.ascender + self->face
->size->metrics.descender) / 2) + 32) & -64) >>
6)
680 (self->face->size->metrics.ascender +(((((self->face->size->metrics.ascender + self->face
->size->metrics.descender) / 2) + 32) & -64) >>
6)
681 self->face->size->metrics.descender) /(((((self->face->size->metrics.ascender + self->face
->size->metrics.descender) / 2) + 32) & -64) >>
6)
682 2)(((((self->face->size->metrics.ascender + self->face
->size->metrics.descender) / 2) + 32) & -64) >>
6)
;
683 break;
684 case 's': // horizontal baseline
685 y_anchor = 0;
686 break;
687 case 'b': // bottom
688 y_anchor = y_min;
689 break;
690 case 'd': // descender
691 y_anchor = PIXEL(self->face->size->metrics.descender)((((self->face->size->metrics.descender) + 32) &
-64) >> 6)
;
692 break;
693 default:
694 goto bad_anchor;
695 }
696 } else {
697 switch (anchor[0]) {
698 case 'l': // left
699 x_anchor = x_min;
700 break;
701 case 'm': // middle (left + right) / 2
702 x_anchor = (x_min + x_max) / 2;
703 break;
704 case 'r': // right
705 x_anchor = x_max;
706 break;
707 case 's': // vertical baseline
708 x_anchor = 0;
709 break;
710 default:
711 goto bad_anchor;
712 }
713 switch (anchor[1]) {
714 case 't': // top
715 y_anchor = 0;
716 break;
717 case 'm': // middle (top + bottom) / 2
718 y_anchor = PIXEL(position / 2)((((position / 2) + 32) & -64) >> 6);
719 break;
720 case 'b': // bottom
721 y_anchor = PIXEL(position)((((position) + 32) & -64) >> 6);
722 break;
723 case 'a': // ascender
724 case 's': // horizontal baseline
725 case 'd': // descender
726 default:
727 goto bad_anchor;
728 }
729 }
730 }
731
732 return Py_BuildValue_Py_BuildValue_SizeT(
733 "(ii)(ii)",
734 (x_max - x_min),
735 (y_max - y_min),
736 (-x_anchor + x_min),
737 -(-y_anchor + y_max));
738
739bad_anchor:
740 PyErr_Format(PyExc_ValueError, "bad anchor specified: %s", anchor);
741 return NULL((void*)0);
742}
743
744static PyObject *
745font_render(FontObject *self, PyObject *args) {
746 int x, y; /* pen position, in 26.6 precision */
747 int px, py; /* position of current glyph, in pixels */
748 int x_min, y_max; /* text offset in 26.6 precision */
749 int load_flags; /* FreeType load_flags parameter */
750 int error;
751 FT_Glyph glyph;
752 FT_GlyphSlot glyph_slot;
753 FT_Bitmap bitmap;
754 FT_Bitmap bitmap_converted; /* initialized lazily, for non-8bpp fonts */
755 FT_BitmapGlyph bitmap_glyph;
756 FT_Stroker stroker = NULL((void*)0);
757 int bitmap_converted_ready = 0; /* has bitmap_converted been initialized */
758 GlyphInfo *glyph_info = NULL((void*)0); /* computed text layout */
759 size_t i, count; /* glyph_info index and length */
760 int xx, yy; /* pixel offset of current glyph bitmap */
761 int x0, x1; /* horizontal bounds of glyph bitmap to copy */
762 unsigned int bitmap_y; /* glyph bitmap y index */
763 unsigned char *source; /* glyph bitmap source buffer */
764 unsigned char convert_scale; /* scale factor for non-8bpp bitmaps */
765 Imaging im;
766 Py_ssize_t id;
767 int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
768 int color = 0; /* is FT_LOAD_COLOR enabled? */
769 int stroke_width = 0;
770 PY_LONG_LONGlong long foreground_ink_long = 0;
771 unsigned int foreground_ink;
772 const char *mode = NULL((void*)0);
773 const char *dir = NULL((void*)0);
774 const char *lang = NULL((void*)0);
775 PyObject *features = Py_None(&_Py_NoneStruct);
776 PyObject *string;
777
778 /* render string into given buffer (the buffer *must* have
779 the right size, or this will crash) */
780
781 if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(
782 args,
783 "On|zzOziL:render",
784 &string,
785 &id,
786 &mode,
787 &dir,
788 &features,
789 &lang,
790 &stroke_width,
791 &foreground_ink_long)) {
792 return NULL((void*)0);
793 }
794
795 mask = mode && strcmp(mode, "1") == 0;
796 color = mode && strcmp(mode, "RGBA") == 0;
797
798 foreground_ink = foreground_ink_long;
799
800#ifdef FT_COLOR_H<freetype/ftcolor.h>
801 if (color) {
802 FT_Color foreground_color;
803 FT_Byte *ink = (FT_Byte *)&foreground_ink;
804 foreground_color.red = ink[0];
805 foreground_color.green = ink[1];
806 foreground_color.blue = ink[2];
807 foreground_color.alpha =
808 (FT_Byte)255; /* ink alpha is handled in ImageDraw.text */
809 FT_Palette_Set_Foreground_Color(self->face, foreground_color);
810 }
811#endif
812
813 count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
814 if (PyErr_Occurred()) {
815 return NULL((void*)0);
816 }
817 if (count == 0) {
818 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
819 }
820
821 if (stroke_width) {
822 error = FT_Stroker_New(library, &stroker);
823 if (error) {
824 return geterror(error);
825 }
826
827 FT_Stroker_Set(
828 stroker,
829 (FT_Fixed)stroke_width * 64,
830 FT_STROKER_LINECAP_ROUND,
831 FT_STROKER_LINEJOIN_ROUND,
832 0);
833 }
834
835 im = (Imaging)id;
836 load_flags = FT_LOAD_DEFAULT0x0;
837 if (mask) {
838 load_flags |= FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 );
839 }
840#ifdef FT_LOAD_COLOR( 1L << 20 )
841 if (color) {
842 load_flags |= FT_LOAD_COLOR( 1L << 20 );
843 }
844#endif
845
846 /*
847 * calculate x_min and y_max
848 * must match font_getsize or there may be clipping!
849 */
850 x = y = x_min = y_max = 0;
851 for (i = 0; i < count; i++) {
852 px = PIXEL(x + glyph_info[i].x_offset)((((x + glyph_info[i].x_offset) + 32) & -64) >> 6);
853 py = PIXEL(y + glyph_info[i].y_offset)((((y + glyph_info[i].y_offset) + 32) & -64) >> 6);
854
855 error =
856 FT_Load_Glyph(self->face, glyph_info[i].index, load_flags | FT_LOAD_RENDER( 1L << 2 ));
857 if (error) {
858 return geterror(error);
859 }
860
861 glyph_slot = self->face->glyph;
862 bitmap = glyph_slot->bitmap;
863
864 if (glyph_slot->bitmap_top + py > y_max) {
865 y_max = glyph_slot->bitmap_top + py;
866 }
867 if (glyph_slot->bitmap_left + px < x_min) {
868 x_min = glyph_slot->bitmap_left + px;
869 }
870
871 x += glyph_info[i].x_advance;
872 y += glyph_info[i].y_advance;
873 }
874
875 /* set pen position to text origin */
876 x = (-x_min + stroke_width) << 6;
877 y = (-y_max + (-stroke_width)) << 6;
878
879 if (stroker == NULL((void*)0)) {
880 load_flags |= FT_LOAD_RENDER( 1L << 2 );
881 }
882
883 for (i = 0; i < count; i++) {
884 px = PIXEL(x + glyph_info[i].x_offset)((((x + glyph_info[i].x_offset) + 32) & -64) >> 6);
885 py = PIXEL(y + glyph_info[i].y_offset)((((y + glyph_info[i].y_offset) + 32) & -64) >> 6);
886
887 error = FT_Load_Glyph(self->face, glyph_info[i].index, load_flags);
888 if (error) {
889 return geterror(error);
890 }
891
892 glyph_slot = self->face->glyph;
893 if (stroker != NULL((void*)0)) {
894 error = FT_Get_Glyph(glyph_slot, &glyph);
895 if (!error) {
896 error = FT_Glyph_Stroke(&glyph, stroker, 1);
897 }
898 if (!error) {
899 FT_Vector origin = {0, 0};
900 error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, &origin, 1);
901 }
902 if (error) {
903 return geterror(error);
904 }
905
906 bitmap_glyph = (FT_BitmapGlyph)glyph;
907
908 bitmap = bitmap_glyph->bitmap;
909 xx = px + bitmap_glyph->left;
910 yy = -(py + bitmap_glyph->top);
911 } else {
912 bitmap = glyph_slot->bitmap;
913 xx = px + glyph_slot->bitmap_left;
914 yy = -(py + glyph_slot->bitmap_top);
915 }
916
917 /* convert non-8bpp bitmaps */
918 switch (bitmap.pixel_mode) {
919 case FT_PIXEL_MODE_MONO:
920 convert_scale = 255;
921 break;
922 case FT_PIXEL_MODE_GRAY2:
923 convert_scale = 255 / 3;
924 break;
925 case FT_PIXEL_MODE_GRAY4:
926 convert_scale = 255 / 15;
927 break;
928 default:
929 convert_scale = 1;
930 }
931 switch (bitmap.pixel_mode) {
932 case FT_PIXEL_MODE_MONO:
933 case FT_PIXEL_MODE_GRAY2:
934 case FT_PIXEL_MODE_GRAY4:
935 if (!bitmap_converted_ready) {
936#if FREETYPE_MAJOR2 > 2 || (FREETYPE_MAJOR2 == 2 && FREETYPE_MINOR10 > 6)
937 FT_Bitmap_Init(&bitmap_converted);
938#else
939 FT_Bitmap_New(&bitmap_converted);
940#endif
941 bitmap_converted_ready = 1;
942 }
943 error = FT_Bitmap_Convert(library, &bitmap, &bitmap_converted, 1);
944 if (error) {
945 geterror(error);
946 goto glyph_error;
947 }
948 bitmap = bitmap_converted;
949 /* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
950 case FT_PIXEL_MODE_GRAY:
951 break;
952#ifdef FT_LOAD_COLOR( 1L << 20 )
953 case FT_PIXEL_MODE_BGRA:
954 if (color) {
955 break;
956 }
957 /* we didn't ask for color, fall through to default */
958#endif
959 default:
960 PyErr_SetString(PyExc_IOError, "unsupported bitmap pixel mode");
961 goto glyph_error;
962 }
963
964 /* clip glyph bitmap width to target image bounds */
965 x0 = 0;
966 x1 = bitmap.width;
967 if (xx < 0) {
968 x0 = -xx;
969 }
970 if (xx + x1 > im->xsize) {
971 x1 = im->xsize - xx;
972 }
973
974 source = (unsigned char *)bitmap.buffer;
975 for (bitmap_y = 0; bitmap_y < bitmap.rows; bitmap_y++, yy++) {
976 /* clip glyph bitmap height to target image bounds */
977 if (yy >= 0 && yy < im->ysize) {
978 /* blend this glyph into the buffer */
979 int k;
980 unsigned char v;
981 unsigned char *target;
982 if (color) {
983 /* target[RGB] returns the color, target[A] returns the mask */
984 /* target bands get split again in ImageDraw.text */
985 target = (unsigned char *)im->image[yy] + xx * 4;
986 } else {
987 target = im->image8[yy] + xx;
988 }
989#ifdef FT_LOAD_COLOR( 1L << 20 )
990 if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
991 /* paste color glyph */
992 for (k = x0; k < x1; k++) {
993 if (target[k * 4 + 3] < source[k * 4 + 3]) {
994 /* unpremultiply BGRa to RGBA */
995 target[k * 4 + 0] = CLIP8((((255 * (int)source[k * 4 + 2]) / source[k * 4 + 3]) <= 0
? 0 : ((255 * (int)source[k * 4 + 2]) / source[k * 4 + 3]) <
256 ? ((255 * (int)source[k * 4 + 2]) / source[k * 4 + 3]) :
255)
996 (255 * (int)source[k * 4 + 2]) / source[k * 4 + 3])(((255 * (int)source[k * 4 + 2]) / source[k * 4 + 3]) <= 0
? 0 : ((255 * (int)source[k * 4 + 2]) / source[k * 4 + 3]) <
256 ? ((255 * (int)source[k * 4 + 2]) / source[k * 4 + 3]) :
255)
;
997 target[k * 4 + 1] = CLIP8((((255 * (int)source[k * 4 + 1]) / source[k * 4 + 3]) <= 0
? 0 : ((255 * (int)source[k * 4 + 1]) / source[k * 4 + 3]) <
256 ? ((255 * (int)source[k * 4 + 1]) / source[k * 4 + 3]) :
255)
998 (255 * (int)source[k * 4 + 1]) / source[k * 4 + 3])(((255 * (int)source[k * 4 + 1]) / source[k * 4 + 3]) <= 0
? 0 : ((255 * (int)source[k * 4 + 1]) / source[k * 4 + 3]) <
256 ? ((255 * (int)source[k * 4 + 1]) / source[k * 4 + 3]) :
255)
;
999 target[k * 4 + 2] = CLIP8((((255 * (int)source[k * 4 + 0]) / source[k * 4 + 3]) <= 0
? 0 : ((255 * (int)source[k * 4 + 0]) / source[k * 4 + 3]) <
256 ? ((255 * (int)source[k * 4 + 0]) / source[k * 4 + 3]) :
255)
1000 (255 * (int)source[k * 4 + 0]) / source[k * 4 + 3])(((255 * (int)source[k * 4 + 0]) / source[k * 4 + 3]) <= 0
? 0 : ((255 * (int)source[k * 4 + 0]) / source[k * 4 + 3]) <
256 ? ((255 * (int)source[k * 4 + 0]) / source[k * 4 + 3]) :
255)
;
1001 target[k * 4 + 3] = source[k * 4 + 3];
1002 }
1003 }
1004 } else
1005#endif
1006 if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
1007 if (color) {
1008 unsigned char *ink = (unsigned char *)&foreground_ink;
1009 for (k = x0; k < x1; k++) {
1010 v = source[k] * convert_scale;
1011 if (target[k * 4 + 3] < v) {
1012 target[k * 4 + 0] = ink[0];
1013 target[k * 4 + 1] = ink[1];
1014 target[k * 4 + 2] = ink[2];
1015 target[k * 4 + 3] = v;
1016 }
1017 }
1018 } else {
1019 for (k = x0; k < x1; k++) {
1020 v = source[k] * convert_scale;
1021 if (target[k] < v) {
1022 target[k] = v;
1023 }
1024 }
1025 }
1026 } else {
1027 PyErr_SetString(PyExc_IOError, "unsupported bitmap pixel mode");
1028 goto glyph_error;
1029 }
1030 }
1031 source += bitmap.pitch;
1032 }
1033 x += glyph_info[i].x_advance;
1034 y += glyph_info[i].y_advance;
1035 if (stroker != NULL((void*)0)) {
1036 FT_Done_Glyph(glyph);
1037 }
1038 }
1039
1040 if (bitmap_converted_ready) {
1041 FT_Bitmap_Done(library, &bitmap_converted);
1042 }
1043 FT_Stroker_Done(stroker);
1044 PyMem_DelPyMem_Free(glyph_info);
1045 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1046
1047glyph_error:
1048 if (stroker != NULL((void*)0)) {
1049 FT_Done_Glyph(glyph);
1050 }
1051 if (bitmap_converted_ready) {
1052 FT_Bitmap_Done(library, &bitmap_converted);
1053 }
1054 FT_Stroker_Done(stroker);
1055 PyMem_DelPyMem_Free(glyph_info);
1056 return NULL((void*)0);
1057}
1058
1059#if FREETYPE_MAJOR2 > 2 || (FREETYPE_MAJOR2 == 2 && FREETYPE_MINOR10 > 9) || \
1060 (FREETYPE_MAJOR2 == 2 && FREETYPE_MINOR10 == 9 && FREETYPE_PATCH1 == 1)
1061static PyObject *
1062font_getvarnames(FontObject *self) {
1063 int error;
1064 FT_UInt i, j, num_namedstyles, name_count;
1065 FT_MM_Var *master;
1066 FT_SfntName name;
1067 PyObject *list_names, *list_name;
1068
1069 error = FT_Get_MM_Var(self->face, &master);
1070 if (error) {
1071 return geterror(error);
1072 }
1073
1074 num_namedstyles = master->num_namedstyles;
1075 list_names = PyList_New(num_namedstyles);
1076
1077 name_count = FT_Get_Sfnt_Name_Count(self->face);
1078 for (i = 0; i < name_count; i++) {
1079 error = FT_Get_Sfnt_Name(self->face, i, &name);
1080 if (error) {
1081 return geterror(error);
1082 }
1083
1084 for (j = 0; j < num_namedstyles; j++) {
1085 if (PyList_GetItem(list_names, j) != NULL((void*)0)) {
1086 continue;
1087 }
1088
1089 if (master->namedstyle[j].strid == name.name_id) {
1090 list_name = Py_BuildValue_Py_BuildValue_SizeT("y#", name.string, name.string_len);
1091 PyList_SetItem(list_names, j, list_name);
1092 break;
1093 }
1094 }
1095 }
1096
1097 FT_Done_MM_Var(library, master);
1098
1099 return list_names;
1100}
1101
1102static PyObject *
1103font_getvaraxes(FontObject *self) {
1104 int error;
1105 FT_UInt i, j, num_axis, name_count;
1106 FT_MM_Var *master;
1107 FT_Var_Axis axis;
1108 FT_SfntName name;
1109 PyObject *list_axes, *list_axis, *axis_name;
1110 error = FT_Get_MM_Var(self->face, &master);
1111 if (error) {
1
Assuming 'error' is 0
2
Taking false branch
1112 return geterror(error);
1113 }
1114
1115 num_axis = master->num_axis;
1116 name_count = FT_Get_Sfnt_Name_Count(self->face);
1117
1118 list_axes = PyList_New(num_axis);
1119 for (i = 0; i < num_axis; i++) {
3
Assuming 'i' is < 'num_axis'
4
Loop condition is true. Entering loop body
1120 axis = master->axis[i];
1121
1122 list_axis = PyDict_New();
1123 PyDict_SetItemString(
1124 list_axis, "minimum", PyLong_FromLong(axis.minimum / 65536));
5
Calling 'PyLong_FromLong'
7
Returning from 'PyLong_FromLong'
8
PyObject ownership leak with reference count of 1
1125 PyDict_SetItemString(list_axis, "default", PyLong_FromLong(axis.def / 65536));
1126 PyDict_SetItemString(
1127 list_axis, "maximum", PyLong_FromLong(axis.maximum / 65536));
1128
1129 for (j = 0; j < name_count; j++) {
1130 error = FT_Get_Sfnt_Name(self->face, j, &name);
1131 if (error) {
1132 return geterror(error);
1133 }
1134
1135 if (name.name_id == axis.strid) {
1136 axis_name = Py_BuildValue_Py_BuildValue_SizeT("y#", name.string, name.string_len);
1137 PyDict_SetItemString(list_axis, "name", axis_name);
1138 break;
1139 }
1140 }
1141
1142 PyList_SetItem(list_axes, i, list_axis);
1143 }
1144
1145 FT_Done_MM_Var(library, master);
1146
1147 return list_axes;
1148}
1149
1150static PyObject *
1151font_setvarname(FontObject *self, PyObject *args) {
1152 int error;
1153
1154 int instance_index;
1155 if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "i", &instance_index)) {
1156 return NULL((void*)0);
1157 }
1158
1159 error = FT_Set_Named_Instance(self->face, instance_index);
1160 if (error) {
1161 return geterror(error);
1162 }
1163
1164 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
1165 return Py_None(&_Py_NoneStruct);
1166}
1167
1168static PyObject *
1169font_setvaraxes(FontObject *self, PyObject *args) {
1170 int error;
1171
1172 PyObject *axes, *item;
1173 Py_ssize_t i, num_coords;
1174 FT_Fixed *coords;
1175 FT_Fixed coord;
1176 if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O", &axes)) {
1177 return NULL((void*)0);
1178 }
1179
1180 if (!PyList_Check(axes)((((((PyObject*)(axes))->ob_type))->tp_flags & ((1UL
<< 25))) != 0)
) {
1181 PyErr_SetString(PyExc_TypeError, "argument must be a list");
1182 return NULL((void*)0);
1183 }
1184
1185 num_coords = PyObject_LengthPyObject_Size(axes);
1186 coords = malloc(2 * sizeof(coords));
1187 if (coords == NULL((void*)0)) {
1188 return PyErr_NoMemory();
1189 }
1190 for (i = 0; i < num_coords; i++) {
1191 item = PyList_GET_ITEM(axes, i)(((PyListObject *)(axes))->ob_item[i]);
1192 if (PyFloat_Check(item)((((PyObject*)(item))->ob_type) == (&PyFloat_Type) || PyType_IsSubtype
((((PyObject*)(item))->ob_type), (&PyFloat_Type)))
) {
1193 coord = PyFloat_AS_DOUBLE(item)(((PyFloatObject *)(item))->ob_fval);
1194 } else if (PyLong_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL
<< 24))) != 0)
) {
1195 coord = (float)PyLong_AS_LONG(item)PyLong_AsLong(item);
1196 } else if (PyNumber_Check(item)) {
1197 coord = PyFloat_AsDouble(item);
1198 } else {
1199 free(coords);
1200 PyErr_SetString(PyExc_TypeError, "list must contain numbers");
1201 return NULL((void*)0);
1202 }
1203 coords[i] = coord * 65536;
1204 }
1205
1206 error = FT_Set_Var_Design_Coordinates(self->face, num_coords, coords);
1207 free(coords);
1208 if (error) {
1209 return geterror(error);
1210 }
1211
1212 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
1213 return Py_None(&_Py_NoneStruct);
1214}
1215#endif
1216
1217static void
1218font_dealloc(FontObject *self) {
1219 if (self->face) {
1220 FT_Done_Face(self->face);
1221 }
1222 if (self->font_bytes) {
1223 PyMem_Free(self->font_bytes);
1224 }
1225 PyObject_DelPyObject_Free(self);
1226}
1227
1228static PyMethodDef font_methods[] = {
1229 {"render", (PyCFunction)font_render, METH_VARARGS0x0001},
1230 {"getsize", (PyCFunction)font_getsize, METH_VARARGS0x0001},
1231 {"getlength", (PyCFunction)font_getlength, METH_VARARGS0x0001},
1232#if FREETYPE_MAJOR2 > 2 || (FREETYPE_MAJOR2 == 2 && FREETYPE_MINOR10 > 9) || \
1233 (FREETYPE_MAJOR2 == 2 && FREETYPE_MINOR10 == 9 && FREETYPE_PATCH1 == 1)
1234 {"getvarnames", (PyCFunction)font_getvarnames, METH_NOARGS0x0004},
1235 {"getvaraxes", (PyCFunction)font_getvaraxes, METH_NOARGS0x0004},
1236 {"setvarname", (PyCFunction)font_setvarname, METH_VARARGS0x0001},
1237 {"setvaraxes", (PyCFunction)font_setvaraxes, METH_VARARGS0x0001},
1238#endif
1239 {NULL((void*)0), NULL((void*)0)}};
1240
1241static PyObject *
1242font_getattr_family(FontObject *self, void *closure) {
1243 if (self->face->family_name) {
1244 return PyUnicode_FromString(self->face->family_name);
1245 }
1246 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1247}
1248
1249static PyObject *
1250font_getattr_style(FontObject *self, void *closure) {
1251 if (self->face->style_name) {
1252 return PyUnicode_FromString(self->face->style_name);
1253 }
1254 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1255}
1256
1257static PyObject *
1258font_getattr_ascent(FontObject *self, void *closure) {
1259 return PyLong_FromLong(PIXEL(self->face->size->metrics.ascender)((((self->face->size->metrics.ascender) + 32) & -
64) >> 6)
);
1260}
1261
1262static PyObject *
1263font_getattr_descent(FontObject *self, void *closure) {
1264 return PyLong_FromLong(-PIXEL(self->face->size->metrics.descender)((((self->face->size->metrics.descender) + 32) &
-64) >> 6)
);
1265}
1266
1267static PyObject *
1268font_getattr_height(FontObject *self, void *closure) {
1269 return PyLong_FromLong(PIXEL(self->face->size->metrics.height)((((self->face->size->metrics.height) + 32) & -64
) >> 6)
);
1270}
1271
1272static PyObject *
1273font_getattr_x_ppem(FontObject *self, void *closure) {
1274 return PyLong_FromLong(self->face->size->metrics.x_ppem);
1275}
1276
1277static PyObject *
1278font_getattr_y_ppem(FontObject *self, void *closure) {
1279 return PyLong_FromLong(self->face->size->metrics.y_ppem);
1280}
1281
1282static PyObject *
1283font_getattr_glyphs(FontObject *self, void *closure) {
1284 return PyLong_FromLong(self->face->num_glyphs);
1285}
1286
1287static struct PyGetSetDef font_getsetters[] = {
1288 {"family", (getter)font_getattr_family},
1289 {"style", (getter)font_getattr_style},
1290 {"ascent", (getter)font_getattr_ascent},
1291 {"descent", (getter)font_getattr_descent},
1292 {"height", (getter)font_getattr_height},
1293 {"x_ppem", (getter)font_getattr_x_ppem},
1294 {"y_ppem", (getter)font_getattr_y_ppem},
1295 {"glyphs", (getter)font_getattr_glyphs},
1296 {NULL((void*)0)}};
1297
1298static PyTypeObject Font_Type = {
1299 PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, "Font",
1300 sizeof(FontObject),
1301 0,
1302 /* methods */
1303 (destructor)font_dealloc, /* tp_dealloc */
1304 0, /* tp_print */
1305 0, /*tp_getattr*/
1306 0, /*tp_setattr*/
1307 0, /*tp_compare*/
1308 0, /*tp_repr*/
1309 0, /*tp_as_number */
1310 0, /*tp_as_sequence */
1311 0, /*tp_as_mapping */
1312 0, /*tp_hash*/
1313 0, /*tp_call*/
1314 0, /*tp_str*/
1315 0, /*tp_getattro*/
1316 0, /*tp_setattro*/
1317 0, /*tp_as_buffer*/
1318 Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/
1319 0, /*tp_doc*/
1320 0, /*tp_traverse*/
1321 0, /*tp_clear*/
1322 0, /*tp_richcompare*/
1323 0, /*tp_weaklistoffset*/
1324 0, /*tp_iter*/
1325 0, /*tp_iternext*/
1326 font_methods, /*tp_methods*/
1327 0, /*tp_members*/
1328 font_getsetters, /*tp_getset*/
1329};
1330
1331static PyMethodDef _functions[] = {
1332 {"getfont", (PyCFunction)getfont, METH_VARARGS0x0001 | METH_KEYWORDS0x0002}, {NULL((void*)0), NULL((void*)0)}};
1333
1334static int
1335setup_module(PyObject *m) {
1336 PyObject *d;
1337 PyObject *v;
1338 int major, minor, patch;
1339
1340 d = PyModule_GetDict(m);
1341
1342 /* Ready object type */
1343 PyType_Ready(&Font_Type);
1344
1345 if (FT_Init_FreeType(&library)) {
1346 return 0; /* leave it uninitialized */
1347 }
1348
1349 FT_Library_Version(library, &major, &minor, &patch);
1350
1351 v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch);
1352 PyDict_SetItemString(d, "freetype2_version", v);
1353
1354#ifdef HAVE_RAQM1
1355#if defined(HAVE_RAQM_SYSTEM1) || defined(HAVE_FRIBIDI_SYSTEM)
1356 have_raqm = 1;
1357#else
1358 load_fribidi();
1359 have_raqm = !!p_fribidi;
1360#endif
1361#else
1362 have_raqm = 0;
1363#endif
1364
1365 /* if we have Raqm, we have all three (but possibly no version info) */
1366 v = PyBool_FromLong(have_raqm);
1367 PyDict_SetItemString(d, "HAVE_RAQM", v);
1368 PyDict_SetItemString(d, "HAVE_FRIBIDI", v);
1369 PyDict_SetItemString(d, "HAVE_HARFBUZZ", v);
1370 if (have_raqm) {
1371#ifdef RAQM_VERSION_MAJOR0
1372 v = PyUnicode_FromString(raqm_version_string());
1373#else
1374 v = Py_None(&_Py_NoneStruct);
1375#endif
1376 PyDict_SetItemString(d, "raqm_version", v);
1377
1378#ifdef FRIBIDI_MAJOR_VERSION
1379 {
1380 const char *a = strchr(fribidi_version_info, ')');
1381 const char *b = strchr(fribidi_version_info, '\n');
1382 if (a && b && a + 2 < b) {
1383 v = PyUnicode_FromStringAndSize(a + 2, b - (a + 2));
1384 } else {
1385 v = Py_None(&_Py_NoneStruct);
1386 }
1387 }
1388#else
1389 v = Py_None(&_Py_NoneStruct);
1390#endif
1391 PyDict_SetItemString(d, "fribidi_version", v);
1392
1393#ifdef HB_VERSION_STRING
1394 v = PyUnicode_FromString(hb_version_string());
1395#else
1396 v = Py_None(&_Py_NoneStruct);
1397#endif
1398 PyDict_SetItemString(d, "harfbuzz_version", v);
1399 }
1400
1401 return 0;
1402}
1403
1404PyMODINIT_FUNCPyObject*
1405PyInit__imagingft(void) {
1406 PyObject *m;
1407
1408 static PyModuleDef module_def = {
1409 PyModuleDef_HEAD_INIT{ { 1, ((void*)0) }, ((void*)0), 0, ((void*)0), },
1410 "_imagingft", /* m_name */
1411 NULL((void*)0), /* m_doc */
1412 -1, /* m_size */
1413 _functions, /* m_methods */
1414 };
1415
1416 m = PyModule_Create(&module_def)PyModule_Create2(&module_def, 1013);
1417
1418 if (setup_module(m) < 0) {
1419 return NULL((void*)0);
1420 }
1421
1422 return m;
1423}

/opt/pyrefcon/lib/pyrefcon/models/models/PyLong_FromLong.model

1#ifndef PyLong_FromLong
2struct _object;
3typedef struct _object PyObject;
4PyObject* clang_analyzer_PyObject_New_Reference();
5PyObject* PyLong_FromLong(long v) {
6 return clang_analyzer_PyObject_New_Reference();
6
Setting reference count to 1
7}
8#else
9#warning "API PyLong_FromLong is defined as a macro."
10#endif