2
2
* PIL FreeType Driver
3
* $Id: //modules/pil/_imagingft.c#7 $
3
* $Id: _imagingft.c 2025 2004-09-14 08:28:54Z fredrik $
5
* a FreeType 2.0 driver for PIL
5
* a FreeType 2.X driver for PIL
8
8
* 2001-02-17 fl Created (based on old experimental freetype 1.0 code)
9
9
* 2001-04-18 fl Fixed some egcs compiler nits
10
10
* 2002-11-08 fl Added unicode support; more font metrics, etc
11
* 2003-05-20 fl Fixed compilation under 1.5.2 and newer non-unicode builds
12
* 2003-09-27 fl Added charmap encoding support
13
* 2004-05-15 fl Fixed compilation for FreeType 2.1.8
14
* 2004-09-10 fl Added support for monochrome bitmaps
12
* Copyright (c) 1998-2001 by Secret Labs AB
16
* Copyright (c) 1998-2004 by Secret Labs AB
15
19
#include "Python.h"
16
20
#include "Imaging.h"
22
#ifndef USE_FREETYPE_2_0
23
/* undef/comment out to use freetype 2.0 */
24
#define USE_FREETYPE_2_1
27
#if defined(USE_FREETYPE_2_1)
28
/* freetype 2.1 and newer */
18
29
#include <ft2build.h>
19
30
#include FT_FREETYPE_H
33
#include <freetype/freetype.h>
21
#if PY_VERSION_HEX < 0x01060000
36
#if defined(PY_VERSION_HEX) && PY_VERSION_HEX < 0x01060000
22
37
#define PyObject_DEL(op) PyMem_DEL((op))
40
#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x01060000
41
#if PY_VERSION_HEX < 0x02020000 || defined(Py_USING_UNICODE)
42
/* defining this enables unicode support (default under 1.6a1 and later) */
47
#ifndef FT_LOAD_TARGET_MONO
48
#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
51
/* -------------------------------------------------------------------- */
57
#define FT_ERRORDEF( e, v, s ) { e, s },
58
#define FT_ERROR_START_LIST {
59
#define FT_ERROR_END_LIST { 0, 0 } };
66
#include <freetype/fterrors.h>
25
68
/* -------------------------------------------------------------------- */
37
80
/* round a 26.6 pixel coordinate to the nearest larger integer */
38
81
#define PIXEL(x) ((((x)+63) & -64)>>6)
88
for (i = 0; ft_errors[i].message; i++)
89
if (ft_errors[i].code == code) {
90
PyErr_SetString(PyExc_IOError, ft_errors[i].message);
94
PyErr_SetString(PyExc_IOError, "unknown freetype error");
41
99
getfont(PyObject* self_, PyObject* args, PyObject* kw)
43
101
/* create a font object from a file name and a size (in pixels) */
51
static char* kwlist[] = { "filename", "size", "index", NULL };
52
if (!PyArg_ParseTupleAndKeywords(args, kw, "si|i", kwlist,
53
&filename, &size, &index))
109
unsigned char* encoding = NULL;
110
static char* kwlist[] = {
111
"filename", "size", "index", "encoding", NULL
113
if (!PyArg_ParseTupleAndKeywords(args, kw, "si|is", kwlist,
114
&filename, &size, &index, &encoding))
57
error = FT_Init_FreeType(&library);
61
"cannot initialize FreeType library"
117
if (!library && FT_Init_FreeType(&library)) {
120
"cannot initialize FreeType library"
67
125
self = PyObject_NEW(FontObject, &Font_Type);
74
132
error = FT_Set_Pixel_Sizes(self->face, 0, size);
134
if (!error && encoding && strlen((char*) encoding) == 4) {
135
FT_Encoding encoding_tag = FT_MAKE_TAG(
136
encoding[0], encoding[1], encoding[2], encoding[3]
138
error = FT_Select_Charmap(self->face, encoding_tag);
77
142
PyObject_DEL(self);
78
PyErr_SetString(PyExc_IOError, "cannot load font");
143
return geterror(error);
82
146
return (PyObject*) self;
86
150
font_getchar(PyObject* string, int index, FT_ULong* char_out)
88
#if PY_VERSION_HEX >= 0x01060000
152
#if defined(HAVE_UNICODE)
89
153
if (PyUnicode_Check(string)) {
90
154
Py_UNICODE* p = PyUnicode_AS_UNICODE(string);
91
155
int size = PyUnicode_GET_SIZE(string);
160
222
the right size, or this will crash) */
161
223
PyObject* string;
163
if (!PyArg_ParseTuple(args, "Ol:render", &string, &id))
226
if (!PyArg_ParseTuple(args, "Ol|i:render", &string, &id, &mask))
166
#if PY_VERSION_HEX >= 0x01060000
229
#if defined(HAVE_UNICODE)
167
230
if (!PyUnicode_Check(string) && !PyString_Check(string)) {
169
232
if (!PyString_Check(string)) {
175
238
im = (Imaging) id;
240
load_flags = FT_LOAD_RENDER;
242
load_flags |= FT_LOAD_TARGET_MONO;
177
244
for (x = i = 0; font_getchar(string, i, &ch); i++) {
178
245
index = FT_Get_Char_Index(self->face, ch);
179
error = FT_Load_Glyph(self->face, index, FT_LOAD_RENDER);
246
error = FT_Load_Glyph(self->face, index, load_flags);
248
return geterror(error);
182
249
glyph = self->face->glyph;
183
source = (unsigned char*) glyph->bitmap.buffer;
184
ascender = PIXEL(self->face->size->metrics.ascender);
185
for (y = 0; y < glyph->bitmap.rows; y++) {
186
int xx = PIXEL(x) + glyph->bitmap_left;
187
int yy = y + ascender - glyph->bitmap_top;
188
if (yy >= 0 && yy < im->ysize) {
189
/* blend this glyph into the buffer */
191
unsigned char *target = im->image8[yy] + xx;
192
for (i = 0; i < glyph->bitmap.width; i++)
193
if (target[i] < source[i])
194
target[i] = source[i];
196
source += glyph->bitmap.pitch;
251
/* use monochrome mask (on palette images, etc) */
252
source = (unsigned char*) glyph->bitmap.buffer;
253
ascender = PIXEL(self->face->size->metrics.ascender);
254
for (y = 0; y < glyph->bitmap.rows; y++) {
255
int xx = PIXEL(x) + glyph->bitmap_left;
256
int yy = y + ascender - glyph->bitmap_top;
257
if (yy >= 0 && yy < im->ysize) {
258
/* blend this glyph into the buffer */
260
unsigned char *target = im->image8[yy] + xx;
262
for (i = j = 0; j < glyph->bitmap.width; j++) {
271
source += glyph->bitmap.pitch;
274
/* use antialiased rendering */
275
source = (unsigned char*) glyph->bitmap.buffer;
276
ascender = PIXEL(self->face->size->metrics.ascender);
277
for (y = 0; y < glyph->bitmap.rows; y++) {
278
int xx = PIXEL(x) + glyph->bitmap_left;
279
int yy = y + ascender - glyph->bitmap_top;
280
if (yy >= 0 && yy < im->ysize) {
281
/* blend this glyph into the buffer */
283
unsigned char *target = im->image8[yy] + xx;
284
for (i = 0; i < glyph->bitmap.width; i++)
285
if (target[i] < source[i])
286
target[i] = source[i];
288
source += glyph->bitmap.pitch;
198
291
x += glyph->metrics.horiAdvance;
201
294
Py_INCREF(Py_None);
205
PyErr_SetString(PyExc_IOError, "cannot render character");