~ubuntu-branches/debian/squeeze/python-imaging/squeeze

« back to all changes in this revision

Viewing changes to _imagingft.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-08-28 23:14:10 UTC
  • mfrom: (2.1.5 edgy)
  • Revision ID: james.westby@ubuntu.com-20060828231410-lca9enmne3ecmkup
Tags: 1.1.5-11
* python-imaging-sane: Depend on python-numarray. Closes: #382190.
* Add dependencies on ${shlibs:Depends}, lost in -6. Closes: #378596.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * PIL FreeType Driver
3
 
 * $Id: //modules/pil/_imagingft.c#7 $
 
3
 * $Id: _imagingft.c 2025 2004-09-14 08:28:54Z fredrik $
4
4
 *
5
 
 * a FreeType 2.0 driver for PIL
 
5
 * a FreeType 2.X driver for PIL
6
6
 *
7
7
 * history:
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
11
15
 *
12
 
 * Copyright (c) 1998-2001 by Secret Labs AB
 
16
 * Copyright (c) 1998-2004 by Secret Labs AB
13
17
 */
14
18
 
15
19
#include "Python.h"
16
20
#include "Imaging.h"
17
21
 
 
22
#ifndef USE_FREETYPE_2_0
 
23
/* undef/comment out to use freetype 2.0 */
 
24
#define USE_FREETYPE_2_1
 
25
#endif
 
26
 
 
27
#if defined(USE_FREETYPE_2_1)
 
28
/* freetype 2.1 and newer */
18
29
#include <ft2build.h>
19
30
#include FT_FREETYPE_H
 
31
#else
 
32
/* freetype 2.0 */
 
33
#include <freetype/freetype.h>
 
34
#endif
20
35
 
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))
23
38
#endif
24
39
 
 
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) */
 
43
#define HAVE_UNICODE
 
44
#endif
 
45
#endif
 
46
 
 
47
#ifndef FT_LOAD_TARGET_MONO
 
48
#define FT_LOAD_TARGET_MONO  FT_LOAD_MONOCHROME
 
49
#endif
 
50
 
 
51
/* -------------------------------------------------------------------- */
 
52
/* error table */
 
53
 
 
54
#undef FTERRORS_H
 
55
#undef __FTERRORS_H__
 
56
 
 
57
#define FT_ERRORDEF( e, v, s )  { e, s },
 
58
#define FT_ERROR_START_LIST  {
 
59
#define FT_ERROR_END_LIST    { 0, 0 } };
 
60
 
 
61
struct {
 
62
    int code;
 
63
    const char* message;
 
64
} ft_errors[] =
 
65
 
 
66
#include <freetype/fterrors.h>
 
67
 
25
68
/* -------------------------------------------------------------------- */
26
69
/* font objects */
27
70
 
37
80
/* round a 26.6 pixel coordinate to the nearest larger integer */
38
81
#define PIXEL(x) ((((x)+63) & -64)>>6)
39
82
 
40
 
static PyObject *
 
83
static PyObject*
 
84
geterror(int code)
 
85
{
 
86
    int i;
 
87
 
 
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);
 
91
            return NULL;
 
92
        }
 
93
 
 
94
    PyErr_SetString(PyExc_IOError, "unknown freetype error");
 
95
    return NULL;
 
96
}
 
97
 
 
98
static PyObject*
41
99
getfont(PyObject* self_, PyObject* args, PyObject* kw)
42
100
{
43
101
    /* create a font object from a file name and a size (in pixels) */
48
106
    char* filename;
49
107
    int size;
50
108
    int index = 0;
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
 
112
    };
 
113
    if (!PyArg_ParseTupleAndKeywords(args, kw, "si|is", kwlist,
 
114
                                     &filename, &size, &index, &encoding))
54
115
        return NULL;
55
116
 
56
 
    if (!library) {
57
 
        error = FT_Init_FreeType(&library);
58
 
        if (error) {
59
 
            PyErr_SetString(
60
 
                PyExc_IOError,
61
 
                "cannot initialize FreeType library"
62
 
                );
63
 
            return NULL;
64
 
        }
 
117
    if (!library && FT_Init_FreeType(&library)) {
 
118
        PyErr_SetString(
 
119
            PyExc_IOError,
 
120
            "cannot initialize FreeType library"
 
121
            );
 
122
        return NULL;
65
123
    }
66
124
 
67
125
    self = PyObject_NEW(FontObject, &Font_Type);
73
131
    if (!error)
74
132
        error = FT_Set_Pixel_Sizes(self->face, 0, size);
75
133
 
 
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]
 
137
            );
 
138
        error = FT_Select_Charmap(self->face, encoding_tag);
 
139
    }
 
140
 
76
141
    if (error) {
77
142
        PyObject_DEL(self);
78
 
        PyErr_SetString(PyExc_IOError, "cannot load font");
79
 
        return NULL;
 
143
        return geterror(error);
80
144
    }
81
145
 
82
146
    return (PyObject*) self;
85
149
static int
86
150
font_getchar(PyObject* string, int index, FT_ULong* char_out)
87
151
{
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);
93
157
            return 0;
94
158
        *char_out = p[index];
95
159
        return 1;
96
 
    } else
 
160
    }
97
161
#endif
98
162
    if (PyString_Check(string)) {
99
 
        unsigned char* p = PyString_AS_STRING(string);
 
163
        unsigned char* p = (unsigned char*) PyString_AS_STRING(string);
100
164
        int size = PyString_GET_SIZE(string);
101
165
        if (index >= size)
102
166
            return 0;
118
182
    if (!PyArg_ParseTuple(args, "O:getsize", &string))
119
183
        return NULL;
120
184
 
121
 
#if PY_VERSION_HEX >= 0x01060000
 
185
#if defined(HAVE_UNICODE)
122
186
    if (!PyUnicode_Check(string) && !PyString_Check(string)) {
123
187
#else
124
188
    if (!PyString_Check(string)) {
132
196
        index = FT_Get_Char_Index(self->face, ch);
133
197
        error = FT_Load_Glyph(self->face, index, FT_LOAD_DEFAULT);
134
198
        if (error)
135
 
            goto failure;
 
199
            return geterror(error);
136
200
        x += self->face->glyph->metrics.horiAdvance;
137
201
    }
138
202
 
140
204
        "ii", PIXEL(x),
141
205
        PIXEL(self->face->size->metrics.height)
142
206
        );
143
 
 
144
 
  failure:
145
 
    PyErr_SetString(PyExc_IOError, "cannot load character");
146
 
    return NULL;
147
207
}
148
208
 
149
209
static PyObject*
152
212
    int i, x, y;
153
213
    Imaging im;
154
214
    int index, error, ascender;
 
215
    int load_flags;
155
216
    unsigned char *source;
 
217
    
156
218
    FT_ULong ch;
157
219
    FT_GlyphSlot glyph;
158
220
 
160
222
       the right size, or this will crash) */
161
223
    PyObject* string;
162
224
    long id;
163
 
    if (!PyArg_ParseTuple(args, "Ol:render", &string, &id))
 
225
    int mask = 0;
 
226
    if (!PyArg_ParseTuple(args, "Ol|i:render", &string, &id, &mask))
164
227
        return NULL;
165
228
 
166
 
#if PY_VERSION_HEX >= 0x01060000
 
229
#if defined(HAVE_UNICODE)
167
230
    if (!PyUnicode_Check(string) && !PyString_Check(string)) {
168
231
#else
169
232
    if (!PyString_Check(string)) {
174
237
 
175
238
    im = (Imaging) id;
176
239
 
 
240
    load_flags = FT_LOAD_RENDER;
 
241
    if (mask)
 
242
        load_flags |= FT_LOAD_TARGET_MONO;
 
243
 
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);
180
247
        if (error)
181
 
            goto failure;
 
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 */
190
 
                int i;
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];
195
 
            }
196
 
            source += glyph->bitmap.pitch;
 
250
        if (mask) {
 
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 */
 
259
                    int i, j, m;
 
260
                    unsigned char *target = im->image8[yy] + xx;
 
261
                    m = 128;
 
262
                    for (i = j = 0; j < glyph->bitmap.width; j++) {
 
263
                        if (source[i] & m)
 
264
                            target[j] = 255;
 
265
                        if (!(m >>= 1)) {
 
266
                            m = 128;
 
267
                            i++;
 
268
                        }
 
269
                    }
 
270
                }
 
271
                source += glyph->bitmap.pitch;
 
272
            }
 
273
        } else {
 
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 */
 
282
                    int i;
 
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];
 
287
                }
 
288
                source += glyph->bitmap.pitch;
 
289
            }
197
290
        }
198
291
        x += glyph->metrics.horiAdvance;
199
292
    }
200
293
 
201
294
    Py_INCREF(Py_None);
202
295
    return Py_None;
203
 
 
204
 
  failure:
205
 
    PyErr_SetString(PyExc_IOError, "cannot render character");
206
 
    return NULL;
207
296
}
208
297
 
209
298
static void