~ubuntu-branches/ubuntu/natty/ntop/natty

« back to all changes in this revision

Viewing changes to gdchart0.94c/gd-1.8.3/gdttf.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-01-30 21:59:13 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050130215913-xc3ke963bw49b3k4
Tags: 2:3.0-5
* Updated README.Debian file so users will understand what to do at
  install, closes: #291794, #287802.
* Updated ntop init script to give better output.
* Also changed log directory from /var/lib/ntop to /var/log/ntop,
  closes: #252352.
* Quoted the interface list to allow whitespace, closes: #267248.
* Added a couple of logcheck ignores, closes: #269321, #269319.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/********************************************/
2
 
/* gd interface to freetype library         */
3
 
/*                                          */
4
 
/* John Ellson   ellson@lucent.com          */
5
 
/********************************************/
6
 
 
7
 
#include <stdio.h>
8
 
#include <stdlib.h>
9
 
#include <string.h>
10
 
#include <math.h>
11
 
#include "gd.h"
12
 
#ifndef HAVE_LIBTTF
13
 
char * gdImageStringTTF(gdImage *im, int *brect, int fg, char *fontname,
14
 
                double ptsize, double angle, int x, int y, char *string)
15
 
{
16
 
        return "libgd was not built with TrueType font support\n";
17
 
}
18
 
#else
19
 
 
20
 
#include "gdcache.h"
21
 
#include "freetype.h"
22
 
 
23
 
/* number of fonts cached before least recently used is replaced */
24
 
#define FONTCACHESIZE 6
25
 
 
26
 
/* number of character glyphs cached per font before 
27
 
        least-recently-used is replaced */
28
 
#define GLYPHCACHESIZE 120
29
 
 
30
 
/* number of bitmaps cached per glyph before 
31
 
        least-recently-used is replaced */
32
 
#define BITMAPCACHESIZE 8
33
 
 
34
 
/* number of antialias color lookups cached */
35
 
#define TWEENCOLORCACHESIZE 32
36
 
 
37
 
/* ptsize below which anti-aliasing is ineffective */
38
 
#define MINANTIALIASPTSIZE 0
39
 
 
40
 
/* display resolution - (Not really.  This has to be 96 or hinting is wrong) */ 
41
 
#define RESOLUTION 96
42
 
 
43
 
/* Number of colors used for anti-aliasing */
44
 
#define NUMCOLORS 4
45
 
 
46
 
/* Line separation as a factor of font height.  
47
 
        No space between if LINESPACE = 1.00 
48
 
        Line separation will be rounded up to next pixel row*/
49
 
#define LINESPACE 1.05
50
 
 
51
 
#ifndef TRUE
52
 
#define FALSE 0
53
 
#define TRUE !FALSE
54
 
#endif
55
 
 
56
 
#define MAX(a,b) ((a)>(b)?(a):(b))
57
 
#define MIN(a,b) ((a)<(b)?(a):(b))
58
 
 
59
 
typedef struct {
60
 
        char                            *fontname;      /* key */
61
 
        double                          ptsize;         /* key */
62
 
        double                          angle;          /* key */
63
 
        double                          sin_a, cos_a;
64
 
        TT_Engine           *engine;
65
 
        TT_Face                         face;
66
 
        TT_Face_Properties  properties;
67
 
        TT_Instance                     instance;
68
 
        TT_CharMap                      char_map_Unicode, char_map_Big5, char_map_Sjis, char_map_Roman;
69
 
        int                                     have_char_map_Unicode, have_char_map_Big5, have_char_map_Sjis, have_char_map_Roman;
70
 
        TT_Matrix                       matrix;
71
 
        TT_Instance_Metrics     imetrics;
72
 
        gdCache_head_t          *glyphCache;
73
 
} font_t;
74
 
 
75
 
typedef struct {
76
 
        char                            *fontname;      /* key */
77
 
        double                          ptsize;         /* key */
78
 
        double                          angle;          /* key */
79
 
        TT_Engine                       *engine;
80
 
} fontkey_t;
81
 
 
82
 
typedef struct {
83
 
        int                                     character;      /* key */
84
 
        int                                     hinting;        /* key */
85
 
        TT_Glyph                        glyph;
86
 
        TT_Glyph_Metrics        metrics;
87
 
        TT_Outline                      outline;
88
 
        TT_Pos                          oldx, oldy;
89
 
        TT_Raster_Map           Bit;
90
 
        int                                     gray_render;
91
 
        int                                     xmin, xmax, ymin, ymax;
92
 
        gdCache_head_t          *bitmapCache;
93
 
} glyph_t;
94
 
 
95
 
typedef struct {
96
 
        int                                     character;      /* key */
97
 
        int                                     hinting;        /* key */
98
 
        font_t                          *font;
99
 
} glyphkey_t;
100
 
 
101
 
typedef struct {
102
 
        int                                     xoffset;        /* key */
103
 
        int                                     yoffset;        /* key */
104
 
        char                            *bitmap;
105
 
} bitmap_t;
106
 
 
107
 
typedef struct {
108
 
        int                                     xoffset;        /* key */
109
 
        int                                     yoffset;        /* key */
110
 
        glyph_t                         *glyph;
111
 
} bitmapkey_t;
112
 
 
113
 
typedef struct { 
114
 
    unsigned char       pixel;          /* key */
115
 
    unsigned char       bgcolor;        /* key */
116
 
    int                                 fgcolor;        /* key */ /* -ve means no antialias */
117
 
    gdImagePtr          im;                     /* key */
118
 
    unsigned char       tweencolor;
119
 
} tweencolor_t;
120
 
 
121
 
typedef struct {
122
 
    unsigned char       pixel;      /* key */
123
 
    unsigned char       bgcolor;    /* key */
124
 
    int                                 fgcolor;    /* key */ /* -ve means no antialias */
125
 
    gdImagePtr          im;                     /* key */
126
 
} tweencolorkey_t;  
127
 
 
128
 
/* forward declarations so that glyphCache can be initialized by font code */
129
 
static int glyphTest ( void *element, void *key );
130
 
static void *glyphFetch ( char **error, void *key );
131
 
static void glyphRelease( void *element );
132
 
 
133
 
/* forward declarations so that bitmapCache can be initialized by glyph code */
134
 
static int bitmapTest ( void *element, void *key );
135
 
static void *bitmapFetch ( char **error, void *key );
136
 
static void bitmapRelease( void *element );
137
 
 
138
 
/********************************************************************
139
 
 * gdTcl_UtfToUniChar is borrowed from ...
140
 
 */
141
 
/*
142
 
 * tclUtf.c --
143
 
 *
144
 
 *      Routines for manipulating UTF-8 strings.
145
 
 *
146
 
 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
147
 
 *
148
 
 * See the file "license.terms" for information on usage and redistribution
149
 
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
150
 
 *
151
 
 * SCCS: @(#) tclUtf.c 1.25 98/01/28 18:02:43
152
 
 */
153
 
 
154
 
/*
155
 
 *---------------------------------------------------------------------------
156
 
 *
157
 
 * gdTcl_UtfToUniChar --
158
 
 *
159
 
 *      Extract the Tcl_UniChar represented by the UTF-8 string.  Bad
160
 
 *      UTF-8 sequences are converted to valid Tcl_UniChars and processing
161
 
 *      continues.  Equivalent to Plan 9 chartorune().
162
 
 *
163
 
 *      The caller must ensure that the source buffer is long enough that
164
 
 *      this routine does not run off the end and dereference non-existent
165
 
 *      memory looking for trail bytes.  If the source buffer is known to
166
 
 *      be '\0' terminated, this cannot happen.  Otherwise, the caller
167
 
 *      should call Tcl_UtfCharComplete() before calling this routine to
168
 
 *      ensure that enough bytes remain in the string.
169
 
 *
170
 
 * Results:
171
 
 *      *chPtr is filled with the Tcl_UniChar, and the return value is the
172
 
 *      number of bytes from the UTF-8 string that were consumed.
173
 
 *
174
 
 * Side effects:
175
 
 *      None.
176
 
 *
177
 
 *---------------------------------------------------------------------------
178
 
 */
179
 
 
180
 
#ifdef JISX0208
181
 
#include "jisx0208.h"
182
 
#endif
183
 
 
184
 
#define Tcl_UniChar int
185
 
#define TCL_UTF_MAX 3
186
 
static int
187
 
gdTcl_UtfToUniChar(char *str, Tcl_UniChar *chPtr)
188
 
/* str is the UTF8 next character pointer */
189
 
/* chPtr is the int for the result */
190
 
{
191
 
    int byte;
192
 
    
193
 
        /* HTML4.0 entities in decimal form, e.g. &#197; */
194
 
    byte = *((unsigned char *) str);
195
 
        if (byte == '&') {
196
 
                int i, n=0;
197
 
 
198
 
                byte = *((unsigned char *) (str+1));
199
 
                if (byte == '#') {
200
 
                        for (i = 2; i < 8; i++) {
201
 
                                byte = *((unsigned char *) (str+i));
202
 
                                if (byte >= '0' && byte <= '9') {
203
 
                                        n = (n * 10) + (byte - '0');
204
 
                                } 
205
 
                                else
206
 
                                        break;
207
 
                        }
208
 
                        if (byte == ';') {
209
 
                                *chPtr = (Tcl_UniChar) n;
210
 
                                return ++i;
211
 
                        }
212
 
                }
213
 
        }
214
 
         
215
 
    /*
216
 
     * Unroll 1 to 3 byte UTF-8 sequences, use loop to handle longer ones.
217
 
     */
218
 
 
219
 
    byte = *((unsigned char *) str);
220
 
#ifdef JISX0208
221
 
    if (0xA1 <= byte && byte <= 0xFE) {
222
 
        int jiscode, ku, ten;
223
 
 
224
 
        jiscode = 0x100 * (byte & 0x7F) + (str[1] & 0x7F);
225
 
        ku = (jiscode >> 8) - 0x20;
226
 
        ten = (jiscode % 256) - 0x20;
227
 
        if ( (ku < 1 || ku > 92) || (ten < 1 || ten > 94) ) {
228
 
                *chPtr = (Tcl_UniChar) byte;
229
 
                return 1;
230
 
        }
231
 
 
232
 
        *chPtr = (Tcl_UniChar) UnicodeTbl[ku - 1][ten - 1];
233
 
        return 2;
234
 
    } else
235
 
#endif /* JISX0208 */
236
 
    if (byte < 0xC0) {
237
 
        /*
238
 
         * Handles properly formed UTF-8 characters between 0x01 and 0x7F.
239
 
         * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
240
 
         * characters representing themselves.
241
 
         */
242
 
 
243
 
        *chPtr = (Tcl_UniChar) byte;
244
 
        return 1;
245
 
    } else if (byte < 0xE0) {
246
 
        if ((str[1] & 0xC0) == 0x80) {
247
 
            /*
248
 
             * Two-byte-character lead-byte followed by a trail-byte.
249
 
             */
250
 
             
251
 
            *chPtr = (Tcl_UniChar) (((byte & 0x1F) << 6) | (str[1] & 0x3F));
252
 
            return 2;
253
 
        }
254
 
        /*
255
 
         * A two-byte-character lead-byte not followed by trail-byte
256
 
         * represents itself.
257
 
         */
258
 
         
259
 
        *chPtr = (Tcl_UniChar) byte;
260
 
        return 1;
261
 
    } else if (byte < 0xF0) {
262
 
        if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) {
263
 
            /*
264
 
             * Three-byte-character lead byte followed by two trail bytes.
265
 
             */
266
 
 
267
 
            *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) 
268
 
                    | ((str[1] & 0x3F) << 6) | (str[2] & 0x3F));
269
 
            return 3;
270
 
        }
271
 
        /*
272
 
         * A three-byte-character lead-byte not followed by two trail-bytes
273
 
         * represents itself.
274
 
         */
275
 
 
276
 
        *chPtr = (Tcl_UniChar) byte;
277
 
        return 1;
278
 
    }
279
 
#if TCL_UTF_MAX > 3
280
 
    else {
281
 
        int ch, total, trail;
282
 
 
283
 
        total = totalBytes[byte];
284
 
        trail = total - 1;
285
 
        if (trail > 0) {
286
 
            ch = byte & (0x3F >> trail);
287
 
            do {
288
 
                str++;
289
 
                if ((*str & 0xC0) != 0x80) {
290
 
                    *chPtr = byte;
291
 
                    return 1;
292
 
                }
293
 
                ch <<= 6;
294
 
                ch |= (*str & 0x3F);
295
 
                trail--;
296
 
            } while (trail > 0);
297
 
            *chPtr = ch;
298
 
            return total;
299
 
        }
300
 
    }
301
 
#endif
302
 
 
303
 
    *chPtr = (Tcl_UniChar) byte;
304
 
    return 1;
305
 
}
306
 
 
307
 
/********************************************************************/
308
 
/* font cache functions                                             */
309
 
 
310
 
static int
311
 
fontTest ( void *element, void *key )
312
 
{
313
 
        font_t *a=(font_t *)element;
314
 
        fontkey_t *b=(fontkey_t *)key;
315
 
 
316
 
        return ( strcmp(a->fontname, b->fontname) == 0
317
 
                        &&      a->ptsize == b->ptsize
318
 
                        &&  a->angle == b->angle);
319
 
}
320
 
 
321
 
static void *
322
 
fontFetch ( char **error, void *key )
323
 
{
324
 
        TT_Error                err;
325
 
        font_t                  *a;
326
 
        fontkey_t               *b=(fontkey_t *)key;
327
 
        int                             i, n, map_found;
328
 
        short                   platform, encoding;
329
 
 
330
 
        a = (font_t *)malloc(sizeof(font_t));
331
 
        a->fontname = (char *)malloc(strlen(b->fontname) + 1);
332
 
        strcpy(a->fontname,b->fontname);
333
 
        a->ptsize = b->ptsize;
334
 
        a->angle = b->angle;
335
 
        a->sin_a = sin(a->angle);
336
 
        a->cos_a = cos(a->angle);
337
 
        a->engine = b->engine;
338
 
        if ((err = TT_Open_Face(*b->engine, a->fontname, &a->face))) {
339
 
                if (err == TT_Err_Could_Not_Open_File) {
340
 
                        *error = "Could not find/open font";
341
 
                }
342
 
                else {
343
 
                        *error = "Could not read font";
344
 
                }
345
 
                return NULL;
346
 
        }
347
 
        /* get face properties and allocate preload arrays */
348
 
        TT_Get_Face_Properties(a->face, &a->properties);
349
 
 
350
 
        /* create instance */
351
 
        if (TT_New_Instance(a->face, &a->instance)) {
352
 
                *error = "Could not create face instance";
353
 
                return NULL;
354
 
        }
355
 
        
356
 
        if (TT_Set_Instance_Resolutions(a->instance, RESOLUTION, RESOLUTION)) {
357
 
                *error = "Could not set device resolutions";
358
 
                return NULL;
359
 
        }
360
 
 
361
 
        if (TT_Set_Instance_CharSize(a->instance, (TT_F26Dot6)(a->ptsize*64))) {
362
 
                *error = "Could not set character size";
363
 
                return NULL;
364
 
        }
365
 
 
366
 
        TT_Get_Instance_Metrics(a->instance, &a->imetrics);
367
 
        
368
 
 
369
 
/* FIXME - This mapping stuff is imcomplete - where is the spec? */
370
 
 
371
 
        n = TT_Get_CharMap_Count(a->face);
372
 
 
373
 
        map_found = 0;
374
 
        a->have_char_map_Unicode = 0;
375
 
        a->have_char_map_Big5 = 0;
376
 
        a->have_char_map_Sjis = 0;
377
 
        a->have_char_map_Roman = 0;
378
 
        for (i = 0; i < n; i++) {
379
 
                TT_Get_CharMap_ID(a->face, i, &platform, &encoding);
380
 
                if ((platform == 3 && encoding == 1)           /* Windows Unicode */
381
 
                 || (platform == 3 && encoding == 0)           /* Windows
382
 
Symbol */
383
 
 
384
 
                 || (platform == 2 && encoding == 1)           /* ISO Unicode */
385
 
                 || (platform == 0)) {                          /* Apple Unicode */
386
 
                        TT_Get_CharMap(a->face, i, &a->char_map_Unicode);
387
 
                        a->have_char_map_Unicode = 1;
388
 
                        map_found++;
389
 
                } else if (platform == 3 && encoding == 4) {   /* Windows Big5 */
390
 
                        TT_Get_CharMap(a->face, i, &a->char_map_Big5);
391
 
                        a->have_char_map_Big5 = 1;
392
 
                        map_found++;
393
 
                } else if (platform == 3 && encoding == 2) {   /* Windows Sjis */
394
 
                        TT_Get_CharMap(a->face, i, &a->char_map_Sjis);
395
 
                        a->have_char_map_Sjis = 1;
396
 
                        map_found++;
397
 
                } else if ((platform == 1 && encoding == 0)    /* Apple Roman */
398
 
                 || (platform == 2 && encoding == 0)) {         /* ISO ASCII */
399
 
                        TT_Get_CharMap(a->face, i, &a->char_map_Roman);
400
 
                        a->have_char_map_Roman = 1;
401
 
                        map_found++;
402
 
                }
403
 
        }
404
 
 
405
 
        if (! map_found) {
406
 
                *error = "Unable to find a CharMap that I can handle";
407
 
                return NULL;
408
 
        }
409
 
 
410
 
        a->matrix.xx = (TT_Fixed) (a->cos_a * (1<<16));
411
 
        a->matrix.yx = (TT_Fixed) (a->sin_a * (1<<16));
412
 
        a->matrix.xy = - a->matrix.yx;
413
 
        a->matrix.yy = a->matrix.xx;
414
 
 
415
 
        a->glyphCache = gdCacheCreate( GLYPHCACHESIZE,
416
 
                                        glyphTest, glyphFetch, glyphRelease);
417
 
 
418
 
        return (void *)a;
419
 
}
420
 
 
421
 
static void
422
 
fontRelease( void *element )
423
 
{
424
 
        font_t *a=(font_t *)element;
425
 
 
426
 
        gdCacheDelete(a->glyphCache);
427
 
        TT_Done_Instance(a->instance);
428
 
        TT_Close_Face(a->face);
429
 
        free(a->fontname);
430
 
        free( (char *)element );
431
 
}
432
 
 
433
 
/********************************************************************/
434
 
/* glyph cache functions                                            */
435
 
 
436
 
static int
437
 
glyphTest ( void *element, void *key )
438
 
{
439
 
        glyph_t *a=(glyph_t *)element;
440
 
        glyphkey_t *b=(glyphkey_t *)key;
441
 
 
442
 
        return (a->character == b->character
443
 
                && a->hinting == b->hinting);
444
 
}
445
 
 
446
 
static void *
447
 
glyphFetch ( char **error, void *key )
448
 
{
449
 
        glyph_t                         *a;
450
 
        glyphkey_t                      *b=(glyphkey_t *)key;
451
 
        short                           glyph_code;
452
 
        int                                     flags, err;
453
 
        int                                     crect[8], xmin, xmax, ymin, ymax;
454
 
        double                          cos_a, sin_a;
455
 
 
456
 
        a = (glyph_t *)malloc(sizeof(glyph_t));
457
 
        a->character = b->character;
458
 
        a->hinting = b->hinting;
459
 
        a->gray_render = (b->font->ptsize < MINANTIALIASPTSIZE)?FALSE:TRUE;
460
 
        a->oldx = a->oldy = 0;
461
 
 
462
 
        /* create glyph container */
463
 
        if ((TT_New_Glyph(b->font->face, &a->glyph))) {
464
 
                *error = "Could not create glyph container";
465
 
                return NULL;
466
 
        }
467
 
 
468
 
        flags = TTLOAD_SCALE_GLYPH;
469
 
        if (a->hinting && b->font->angle == 0.0) {
470
 
                flags |= TTLOAD_HINT_GLYPH;
471
 
        }
472
 
        if (b->font->have_char_map_Unicode) {
473
 
                glyph_code = TT_Char_Index(b->font->char_map_Unicode, a->character);
474
 
        } else if (a->character < 161 && b->font->have_char_map_Roman) {
475
 
                glyph_code = TT_Char_Index(b->font->char_map_Roman, a->character);
476
 
        } else if ( b->font->have_char_map_Big5) {
477
 
                glyph_code = TT_Char_Index(b->font->char_map_Big5, a->character);
478
 
        } else if ( b->font->have_char_map_Sjis) {
479
 
                glyph_code = TT_Char_Index(b->font->char_map_Sjis, a->character);
480
 
        }
481
 
        if ((err=TT_Load_Glyph(b->font->instance, a->glyph, glyph_code, flags))) {
482
 
                *error = "TT_Load_Glyph problem";
483
 
                return NULL;
484
 
        }
485
 
 
486
 
        TT_Get_Glyph_Metrics(a->glyph, &a->metrics);
487
 
        if (b->font->angle != 0.0) {
488
 
                TT_Get_Glyph_Outline(a->glyph, &a->outline);
489
 
                TT_Transform_Outline(&a->outline, &b->font->matrix);
490
 
        }
491
 
 
492
 
        /* calculate bitmap size */
493
 
        xmin = a->metrics.bbox.xMin -64;
494
 
        ymin = a->metrics.bbox.yMin -64;
495
 
        xmax = a->metrics.bbox.xMax +64;
496
 
        ymax = a->metrics.bbox.yMax +64;
497
 
 
498
 
        cos_a = b->font->cos_a;
499
 
        sin_a = b->font->sin_a;
500
 
        crect[0] = (int)(xmin * cos_a - ymin * sin_a);
501
 
        crect[1] = (int)(xmin * sin_a + ymin * cos_a);
502
 
        crect[2] = (int)(xmax * cos_a - ymin * sin_a);
503
 
        crect[3] = (int)(xmax * sin_a + ymin * cos_a);
504
 
        crect[4] = (int)(xmax * cos_a - ymax * sin_a);
505
 
        crect[5] = (int)(xmax * sin_a + ymax * cos_a);
506
 
        crect[6] = (int)(xmin * cos_a - ymax * sin_a);
507
 
        crect[7] = (int)(xmin * sin_a + ymax * cos_a);
508
 
        a->xmin = MIN(MIN(crect[0],crect[2]),MIN(crect[4],crect[6]));
509
 
        a->xmax = MAX(MAX(crect[0],crect[2]),MAX(crect[4],crect[6]));
510
 
        a->ymin = MIN(MIN(crect[1],crect[3]),MIN(crect[5],crect[7]));
511
 
        a->ymax = MAX(MAX(crect[1],crect[3]),MAX(crect[5],crect[7]));
512
 
 
513
 
        /* allocate bitmap large enough for character */
514
 
        a->Bit.rows = (a->ymax - a->ymin + 32 + 64) / 64;
515
 
        a->Bit.width = (a->xmax - a->xmin + 32 + 64) / 64;
516
 
        a->Bit.flow = TT_Flow_Up;
517
 
        if (a->gray_render) {
518
 
                a->Bit.cols = a->Bit.width;               /* 1 byte per pixel */
519
 
        }
520
 
        else {
521
 
                a->Bit.cols = (a->Bit.width + 7) / 8;     /* 1 bit per pixel */
522
 
        }
523
 
        a->Bit.cols = (a->Bit.cols + 3) & ~3;         /* pad to 32 bits */
524
 
        a->Bit.size = a->Bit.rows * a->Bit.cols;      /* # of bytes in buffer */
525
 
        a->Bit.bitmap = NULL;
526
 
 
527
 
        a->bitmapCache = gdCacheCreate( BITMAPCACHESIZE,
528
 
                                        bitmapTest, bitmapFetch, bitmapRelease);
529
 
 
530
 
        return (void *)a;
531
 
}
532
 
 
533
 
static void
534
 
glyphRelease( void *element )
535
 
{
536
 
        glyph_t *a=(glyph_t *)element;
537
 
 
538
 
        gdCacheDelete(a->bitmapCache);
539
 
        TT_Done_Glyph( a->glyph );
540
 
        free( (char *)element );
541
 
}
542
 
 
543
 
/********************************************************************/
544
 
/* bitmap cache functions                                            */
545
 
 
546
 
static int
547
 
bitmapTest ( void *element, void *key )
548
 
{
549
 
        bitmap_t *a=(bitmap_t *)element;
550
 
        bitmapkey_t *b=(bitmapkey_t *)key;
551
 
 
552
 
        if (a->xoffset == b->xoffset && a->yoffset == b->yoffset) {
553
 
                b->glyph->Bit.bitmap = a->bitmap;
554
 
                return TRUE;
555
 
        }
556
 
        return FALSE;
557
 
}
558
 
 
559
 
static void *
560
 
bitmapFetch ( char **error, void *key )
561
 
{
562
 
        bitmap_t                        *a;
563
 
        bitmapkey_t                     *b=(bitmapkey_t *)key;
564
 
 
565
 
        a = (bitmap_t *)malloc(sizeof(bitmap_t));
566
 
        a->xoffset = b->xoffset;
567
 
        a->yoffset = b->yoffset;
568
 
 
569
 
        b->glyph->Bit.bitmap = a->bitmap = (char *)malloc(b->glyph->Bit.size);
570
 
        memset(a->bitmap, 0, b->glyph->Bit.size);
571
 
        /* render glyph */
572
 
        if (b->glyph->gray_render) {
573
 
                TT_Get_Glyph_Pixmap(b->glyph->glyph, &b->glyph->Bit,
574
 
                        a->xoffset, a->yoffset);
575
 
        }
576
 
        else {
577
 
                TT_Get_Glyph_Bitmap(b->glyph->glyph, &b->glyph->Bit,
578
 
                        a->xoffset, a->yoffset);
579
 
        }
580
 
        return (void *)a;
581
 
}
582
 
 
583
 
static void
584
 
bitmapRelease( void *element )
585
 
{
586
 
        bitmap_t *a=(bitmap_t *)element;
587
 
 
588
 
        free( a->bitmap );
589
 
        free( (char *)element );
590
 
}
591
 
 
592
 
/********************************************************************/
593
 
/* tweencolor cache functions                                            */
594
 
 
595
 
static int
596
 
tweenColorTest (void *element, void *key)
597
 
598
 
    tweencolor_t *a=(tweencolor_t *)element;
599
 
    tweencolorkey_t *b=(tweencolorkey_t *)key;
600
 
    
601
 
    return (a->pixel == b->pixel    
602
 
         && a->bgcolor == b->bgcolor
603
 
         && a->fgcolor == b->fgcolor
604
 
         && a->im == b->im);
605
 
606
 
 
607
 
static void *
608
 
tweenColorFetch (char **error, void *key)
609
 
{
610
 
    tweencolor_t *a;
611
 
    tweencolorkey_t *b=(tweencolorkey_t *)key;
612
 
        int pixel, npixel, bg, fg;
613
 
        gdImagePtr im;
614
 
   
615
 
    a = (tweencolor_t *)malloc(sizeof(tweencolor_t));
616
 
        pixel = a->pixel = b->pixel;
617
 
        bg = a->bgcolor = b->bgcolor;
618
 
        fg = a->fgcolor = b->fgcolor;
619
 
        im = b->im;
620
 
 
621
 
        /* if fg is specified by a negative color idx, then don't antialias */
622
 
        if (fg <0) {
623
 
                a->tweencolor = -fg;
624
 
        } else {
625
 
                npixel = NUMCOLORS - pixel;
626
 
                a->tweencolor = gdImageColorResolve(im,
627
 
                        (pixel * im->red  [fg] + npixel * im->red  [bg]) / NUMCOLORS,
628
 
                        (pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS,
629
 
                        (pixel * im->blue [fg] + npixel * im->blue [bg]) / NUMCOLORS);
630
 
        }
631
 
    *error = NULL;
632
 
    return (void *)a;
633
 
}   
634
 
        
635
 
static void
636
 
tweenColorRelease(void *element)
637
 
{   
638
 
    free((char *)element);
639
 
}   
640
 
 
641
 
/********************************************************************/
642
 
/* gdttfchar -  render one character onto a gd image                */
643
 
 
644
 
char *
645
 
gdttfchar(gdImage *im, int fg, font_t *font,
646
 
        int x, int y,                                   /* string start pos in pixels */
647
 
        TT_F26Dot6 x1,  TT_F26Dot6 y1,  /* char start offset (*64) from x,y */
648
 
        TT_F26Dot6 *advance,
649
 
        TT_BBox **bbox, 
650
 
        char **next)
651
 
{
652
 
    int pc, ch, len;
653
 
        int row, col;
654
 
        int x2, y2;     /* char start pos in pixels */ 
655
 
        int x3, y3;     /* current pixel pos */
656
 
        unsigned char *pixel;
657
 
 
658
 
    glyph_t *glyph;
659
 
    glyphkey_t glyphkey;
660
 
    bitmapkey_t bitmapkey;
661
 
        tweencolor_t *tweencolor;
662
 
        tweencolorkey_t tweencolorkey;
663
 
 
664
 
        /****** set up tweenColorCache on first call ************/
665
 
        static gdCache_head_t   *tweenColorCache;
666
 
 
667
 
        if (! tweenColorCache)
668
 
                tweenColorCache = gdCacheCreate(TWEENCOLORCACHESIZE,
669
 
                        tweenColorTest, tweenColorFetch, tweenColorRelease);
670
 
        /**************/
671
 
 
672
 
        if (font->have_char_map_Unicode) { /* use UTF-8 mapping from ASCII */
673
 
                len = gdTcl_UtfToUniChar(*next, &ch);
674
 
                *next += len;
675
 
        } else
676
 
        if (font->have_char_map_Sjis) {
677
 
                unsigned char c;
678
 
                int jiscode;
679
 
 
680
 
                c = (unsigned char)(**next);
681
 
                if ( 0xA1 <= c && c <= 0xFE ) {
682
 
                        (*next)++;
683
 
                        jiscode = 0x100 * ((c)&0x7F) + ((**next)&0x7F);
684
 
 
685
 
                        ch = (jiscode >> 8) & 0xFF;
686
 
                        jiscode &= 0xFF;
687
 
 
688
 
                        if (ch & 1) jiscode += 0x40 - 0x21;
689
 
                        else        jiscode += 0x9E - 0x21;
690
 
 
691
 
                        if (jiscode >= 0x7F) jiscode++;
692
 
                        ch = (ch - 0x21) / 2 + 0x81;
693
 
                        if (ch >= 0xA0) ch += 0x40;
694
 
 
695
 
                        ch = (ch << 8) + jiscode;
696
 
                } else
697
 
                        ch = (**next) & 255;         /* don't extend sign */
698
 
                (*next)++;
699
 
        } else {
700
 
                /*
701
 
                 * Big 5 mapping:
702
 
                 * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref:
703
 
                 * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs
704
 
                 */
705
 
                ch = (**next) & 255;         /* don't extend sign */
706
 
                (*next)++;
707
 
                if (ch >= 161                /* first code of JIS-8 pair */
708
 
                 && **next) {                            /* don't advance past '\0' */
709
 
                        ch = (ch * 256) + **next;
710
 
                        (*next)++;
711
 
            }
712
 
        }
713
 
 
714
 
        glyphkey.character = ch;
715
 
        glyphkey.hinting = 1;
716
 
    glyphkey.font = font;
717
 
    glyph = (glyph_t *)gdCacheGet(font->glyphCache, &glyphkey);
718
 
    if (! glyph)
719
 
                return font->glyphCache->error;
720
 
 
721
 
        *bbox = &glyph->metrics.bbox;
722
 
        *advance = glyph->metrics.advance;
723
 
 
724
 
        /* if null *im, or invalid color,  then assume user just wants brect */
725
 
        if (!im || fg > 255 || fg < -255)
726
 
                return (char *)NULL;
727
 
 
728
 
        /* render (via cache) a bitmap for the current fractional offset */
729
 
        bitmapkey.xoffset = ((x1+32) & 63) - 32 - ((glyph->xmin+32) & -64);
730
 
        bitmapkey.yoffset = ((y1+32) & 63) - 32 - ((glyph->ymin+32) & -64);
731
 
        bitmapkey.glyph = glyph;
732
 
        gdCacheGet(glyph->bitmapCache, &bitmapkey);
733
 
 
734
 
        /* copy to gif, mapping colors */
735
 
        x2 = x + (((glyph->xmin+32) & -64) + ((x1+32) & -64)) / 64;
736
 
        y2 = y - (((glyph->ymin+32) & -64) + ((y1+32) & -64)) / 64;
737
 
        tweencolorkey.fgcolor = fg;
738
 
        tweencolorkey.im = im;
739
 
        for (row = 0; row < glyph->Bit.rows; row++) {
740
 
                if (glyph->gray_render)
741
 
                        pc = row * glyph->Bit.cols;
742
 
                else
743
 
                        pc = row * glyph->Bit.cols * 8;
744
 
                y3 = y2 - row;
745
 
                if (y3 >= im->sy || y3 < 0) continue;
746
 
                for (col = 0; col < glyph->Bit.width; col++, pc++) {
747
 
                        if (glyph->gray_render) {
748
 
                                tweencolorkey.pixel = 
749
 
                                        *((unsigned char *)(glyph->Bit.bitmap) + pc);
750
 
                        } else {
751
 
                                tweencolorkey.pixel = 
752
 
                                        (((*((unsigned char *)(glyph->Bit.bitmap) + pc/8))
753
 
                                                <<(pc%8))&128)?4:0;
754
 
                        }
755
 
                        /* if not background */
756
 
                        if (tweencolorkey.pixel > 0) {
757
 
                                x3 = x2 + col;
758
 
                                if (x3 >= im->sx || x3 < 0) continue;
759
 
                                pixel = &im->pixels[y3][x3];
760
 
                                tweencolorkey.bgcolor = *pixel;
761
 
                                tweencolor = (tweencolor_t *)gdCacheGet(
762
 
                                        tweenColorCache, &tweencolorkey);
763
 
                                *pixel = tweencolor->tweencolor;
764
 
                        }
765
 
                }
766
 
        }
767
 
        return (char *)NULL;
768
 
}
769
 
 
770
 
extern int any2eucjp(unsigned char *, unsigned char *, unsigned int);
771
 
 
772
 
/********************************************************************/
773
 
/* gdImageStringTTF -  render a utf8 string onto a gd image         */ 
774
 
 
775
 
char * gdImageStringTTF(gdImage *im, int *brect, int fg, char *fontname,
776
 
                double ptsize, double angle, int x, int y, char *string)
777
 
{
778
 
        TT_F26Dot6 ur_x=0, ur_y=0, ll_x=0, ll_y=0;
779
 
        TT_F26Dot6 advance_x, advance_y, advance, x1, y1;
780
 
        TT_BBox *bbox;
781
 
        double sin_a, cos_a;
782
 
        int i=0, ch;
783
 
        font_t *font;
784
 
        fontkey_t fontkey;
785
 
        char *error, *next;
786
 
        /* 1.7.2: initialize this variable. */
787
 
        char *tmpstr = 0;
788
 
 
789
 
        /****** initialize font engine on first call ************/
790
 
        static gdCache_head_t   *fontCache;
791
 
        static TT_Engine        engine;
792
 
 
793
 
        if (! fontCache) {
794
 
                if (TT_Init_FreeType(&engine)) {
795
 
                        return "Failure to initialize font engine";
796
 
                }
797
 
                fontCache = gdCacheCreate( FONTCACHESIZE,
798
 
                        fontTest, fontFetch, fontRelease);
799
 
        }
800
 
        /**************/
801
 
 
802
 
        /* get the font (via font cache) */
803
 
        fontkey.fontname = fontname;
804
 
        fontkey.ptsize = ptsize;
805
 
        fontkey.angle = angle;
806
 
        fontkey.engine = &engine;
807
 
        font = (font_t *)gdCacheGet(fontCache, &fontkey);
808
 
        if (! font) {
809
 
                return fontCache->error;
810
 
        }
811
 
        sin_a = font->sin_a;
812
 
        cos_a = font->cos_a;
813
 
 
814
 
        advance_x = advance_y = 0;
815
 
 
816
 
#ifndef JISX0208
817
 
        if (font->have_char_map_Sjis) {
818
 
#endif
819
 
                if (tmpstr = (unsigned char *)malloc(BUFSIZ)) {
820
 
                        any2eucjp(tmpstr, string, BUFSIZ);
821
 
                        next=tmpstr;
822
 
                } else
823
 
                next=string;
824
 
#ifndef JISX0208
825
 
        } else
826
 
        next=string;
827
 
#endif
828
 
        while (*next) {   
829
 
                ch = *next;
830
 
 
831
 
                /* carriage returns */
832
 
                if (ch == '\r') {
833
 
                        advance_x = 0;
834
 
                        next++;
835
 
                        continue;
836
 
                }
837
 
                /* newlines */
838
 
                if (ch == '\n') {
839
 
                        advance_y -= (TT_F26Dot6)(font->imetrics.y_ppem * LINESPACE * 64);
840
 
                        advance_y = (advance_y-32) & -64; /* round to next pixel row */
841
 
                        next++;
842
 
                        continue;
843
 
                }
844
 
 
845
 
                x1 = (TT_F26Dot6)(advance_x * cos_a - advance_y * sin_a);
846
 
                y1 = (TT_F26Dot6)(advance_x * sin_a + advance_y * cos_a);
847
 
 
848
 
                if ((error=gdttfchar(im, fg, font, x, y, x1, y1, &advance, &bbox, &next)))
849
 
                        return error;
850
 
 
851
 
                if (! i++) { /* if first character, init BB corner values */
852
 
                        ll_x = bbox->xMin;
853
 
                        ll_y = bbox->yMin;
854
 
                        ur_x = bbox->xMax;
855
 
                        ur_y = bbox->yMax;
856
 
                }
857
 
                else {
858
 
                        if (! advance_x) ll_x = MIN(bbox->xMin, ll_x);
859
 
                        ll_y = MIN(advance_y + bbox->yMin, ll_y);
860
 
                        ur_x = MAX(advance_x + bbox->xMax, ur_x);
861
 
                        if (! advance_y) ur_y = MAX(bbox->yMax, ur_y);
862
 
                }
863
 
                advance_x += advance;
864
 
        }
865
 
 
866
 
        /* rotate bounding rectangle */
867
 
        brect[0] = (int)(ll_x * cos_a - ll_y * sin_a);
868
 
        brect[1] = (int)(ll_x * sin_a + ll_y * cos_a);
869
 
        brect[2] = (int)(ur_x * cos_a - ll_y * sin_a);
870
 
        brect[3] = (int)(ur_x * sin_a + ll_y * cos_a);
871
 
        brect[4] = (int)(ur_x * cos_a - ur_y * sin_a);
872
 
        brect[5] = (int)(ur_x * sin_a + ur_y * cos_a);
873
 
        brect[6] = (int)(ll_x * cos_a - ur_y * sin_a);
874
 
        brect[7] = (int)(ll_x * sin_a + ur_y * cos_a);
875
 
 
876
 
        /* scale, round and offset brect */
877
 
        i = 0;
878
 
        while (i<8) {
879
 
                brect[i] = x + (brect[i] + 32) / 64;
880
 
                i++;
881
 
                brect[i] = y - (brect[i] + 32) / 64;
882
 
                i++;
883
 
        }
884
 
 
885
 
    if ( tmpstr ) free(tmpstr);
886
 
    return (char *)NULL;
887
 
}
888
 
 
889
 
#endif /* HAVE_LIBTTF */