1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15
16
17#include <stdio.h>
18#include "agg_font_freetype.h"
19#include "agg_bitset_iterator.h"
20#include "agg_renderer_scanline.h"
21
22
23namespace agg
24{
25
26    //------------------------------------------------------------------------------
27    //
28    // This code implements the AUTODIN II polynomial
29    // The variable corresponding to the macro argument "crc" should
30    // be an unsigned long.
31    // Oroginal code  by Spencer Garrett <srg@quick.com>
32    //
33
34    // generated using the AUTODIN II polynomial
35    //   x^32 + x^26 + x^23 + x^22 + x^16 +
36    //   x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
37    //
38    //------------------------------------------------------------------------------
39
40    static const unsigned crc32tab[256] =
41    {
42       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
43       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
44       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
45       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
46       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
47       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
48       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
49       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
50       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
51       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
52       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
53       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
54       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
55       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
56       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
57       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
58       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
59       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
60       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
61       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
62       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
63       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
64       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
65       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
66       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
67       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
68       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
69       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
70       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
71       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
72       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
73       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
74       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
75       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
76       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
77       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
78       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
79       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
80       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
81       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
82       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
83       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
84       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
85       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
86       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
87       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
88       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
89       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
90       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
91       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
92       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
93       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
94       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
95       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
96       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
97       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
98       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
99       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
100       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
101       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
102       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
103       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
104       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
105       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
106    };
107
108
109    //------------------------------------------------------------------------------
110
111    static unsigned calc_crc32(const unsigned char* buf, unsigned size)
112    {
113        unsigned crc = (unsigned)~0;
114        const unsigned char* p;
115        unsigned len = 0;
116        unsigned nr = size;
117
118        for (len += nr, p = buf; nr--; ++p)
119        {
120            crc = (crc >> 8) ^ crc32tab[(crc ^ *p) & 0xff];
121        }
122        return ~crc;
123    }
124
125    //------------------------------------------------------------------------
126    static inline int dbl_to_plain_fx(double d)
127    {
128        return int(d * 65536.0);
129    }
130
131    //------------------------------------------------------------------------
132    static inline double int26p6_to_dbl(int p)
133    {
134        return double(p) / 64.0;
135    }
136
137    //------------------------------------------------------------------------
138    static inline int dbl_to_int26p6(double p)
139    {
140        return int(p * 64.0 + 0.5);
141    }
142
143
144    //------------------------------------------------------------------------
145    template<class PathStorage>
146    bool decompose_ft_outline(const FT_Outline& outline,
147                              bool flip_y,
148                              const trans_affine& mtx,
149                              PathStorage& path)
150    {
151        typedef typename PathStorage::value_type value_type;
152
153        FT_Vector   v_last;
154        FT_Vector   v_control;
155        FT_Vector   v_start;
156        double x1, y1, x2, y2, x3, y3;
157
158        FT_Vector*  point;
159        FT_Vector*  limit;
160        char*       tags;
161
162        int   n;         // index of contour in outline
163        int   first;     // index of first point in contour
164        char  tag;       // current point's state
165
166        first = 0;
167
168        for(n = 0; n < outline.n_contours; n++)
169        {
170            int  last;  // index of last point in contour
171
172            last  = outline.contours[n];
173            limit = outline.points + last;
174
175            v_start = outline.points[first];
176            v_last  = outline.points[last];
177
178            v_control = v_start;
179
180            point = outline.points + first;
181            tags  = outline.tags  + first;
182            tag   = FT_CURVE_TAG(tags[0]);
183
184            // A contour cannot start with a cubic control point!
185            if(tag == FT_CURVE_TAG_CUBIC) return false;
186
187            // check first point to determine origin
188            if( tag == FT_CURVE_TAG_CONIC)
189            {
190                // first point is conic control.  Yes, this happens.
191                if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON)
192                {
193                    // start at last point if it is on the curve
194                    v_start = v_last;
195                    limit--;
196                }
197                else
198                {
199                    // if both first and last points are conic,
200                    // start at their middle and record its position
201                    // for closure
202                    v_start.x = (v_start.x + v_last.x) / 2;
203                    v_start.y = (v_start.y + v_last.y) / 2;
204
205                    v_last = v_start;
206                }
207                point--;
208                tags--;
209            }
210
211            x1 = int26p6_to_dbl(v_start.x);
212            y1 = int26p6_to_dbl(v_start.y);
213            if(flip_y) y1 = -y1;
214            mtx.transform(&x1, &y1);
215            path.move_to(value_type(dbl_to_int26p6(x1)),
216                         value_type(dbl_to_int26p6(y1)));
217
218            while(point < limit)
219            {
220                point++;
221                tags++;
222
223                tag = FT_CURVE_TAG(tags[0]);
224                switch(tag)
225                {
226                    case FT_CURVE_TAG_ON:  // emit a single line_to
227                    {
228                        x1 = int26p6_to_dbl(point->x);
229                        y1 = int26p6_to_dbl(point->y);
230                        if(flip_y) y1 = -y1;
231                        mtx.transform(&x1, &y1);
232                        path.line_to(value_type(dbl_to_int26p6(x1)),
233                                     value_type(dbl_to_int26p6(y1)));
234                        //path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y));
235                        continue;
236                    }
237
238                    case FT_CURVE_TAG_CONIC:  // consume conic arcs
239                    {
240                        v_control.x = point->x;
241                        v_control.y = point->y;
242
243                    Do_Conic:
244                        if(point < limit)
245                        {
246                            FT_Vector vec;
247                            FT_Vector v_middle;
248
249                            point++;
250                            tags++;
251                            tag = FT_CURVE_TAG(tags[0]);
252
253                            vec.x = point->x;
254                            vec.y = point->y;
255
256                            if(tag == FT_CURVE_TAG_ON)
257                            {
258                                x1 = int26p6_to_dbl(v_control.x);
259                                y1 = int26p6_to_dbl(v_control.y);
260                                x2 = int26p6_to_dbl(vec.x);
261                                y2 = int26p6_to_dbl(vec.y);
262                                if(flip_y) { y1 = -y1; y2 = -y2; }
263                                mtx.transform(&x1, &y1);
264                                mtx.transform(&x2, &y2);
265                                path.curve3(value_type(dbl_to_int26p6(x1)),
266                                            value_type(dbl_to_int26p6(y1)),
267                                            value_type(dbl_to_int26p6(x2)),
268                                            value_type(dbl_to_int26p6(y2)));
269                                continue;
270                            }
271
272                            if(tag != FT_CURVE_TAG_CONIC) return false;
273
274                            v_middle.x = (v_control.x + vec.x) / 2;
275                            v_middle.y = (v_control.y + vec.y) / 2;
276
277                            x1 = int26p6_to_dbl(v_control.x);
278                            y1 = int26p6_to_dbl(v_control.y);
279                            x2 = int26p6_to_dbl(v_middle.x);
280                            y2 = int26p6_to_dbl(v_middle.y);
281                            if(flip_y) { y1 = -y1; y2 = -y2; }
282                            mtx.transform(&x1, &y1);
283                            mtx.transform(&x2, &y2);
284                            path.curve3(value_type(dbl_to_int26p6(x1)),
285                                        value_type(dbl_to_int26p6(y1)),
286                                        value_type(dbl_to_int26p6(x2)),
287                                        value_type(dbl_to_int26p6(y2)));
288
289                            //path.curve3(conv(v_control.x),
290                            //            flip_y ? -conv(v_control.y) : conv(v_control.y),
291                            //            conv(v_middle.x),
292                            //            flip_y ? -conv(v_middle.y) : conv(v_middle.y));
293
294                            v_control = vec;
295                            goto Do_Conic;
296                        }
297
298                        x1 = int26p6_to_dbl(v_control.x);
299                        y1 = int26p6_to_dbl(v_control.y);
300                        x2 = int26p6_to_dbl(v_start.x);
301                        y2 = int26p6_to_dbl(v_start.y);
302                        if(flip_y) { y1 = -y1; y2 = -y2; }
303                        mtx.transform(&x1, &y1);
304                        mtx.transform(&x2, &y2);
305                        path.curve3(value_type(dbl_to_int26p6(x1)),
306                                    value_type(dbl_to_int26p6(y1)),
307                                    value_type(dbl_to_int26p6(x2)),
308                                    value_type(dbl_to_int26p6(y2)));
309
310                        //path.curve3(conv(v_control.x),
311                        //            flip_y ? -conv(v_control.y) : conv(v_control.y),
312                        //            conv(v_start.x),
313                        //            flip_y ? -conv(v_start.y) : conv(v_start.y));
314                        goto Close;
315                    }
316
317                    default:  // FT_CURVE_TAG_CUBIC
318                    {
319                        FT_Vector vec1, vec2;
320
321                        if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
322                        {
323                            return false;
324                        }
325
326                        vec1.x = point[0].x;
327                        vec1.y = point[0].y;
328                        vec2.x = point[1].x;
329                        vec2.y = point[1].y;
330
331                        point += 2;
332                        tags  += 2;
333
334                        if(point <= limit)
335                        {
336                            FT_Vector vec;
337
338                            vec.x = point->x;
339                            vec.y = point->y;
340
341                            x1 = int26p6_to_dbl(vec1.x);
342                            y1 = int26p6_to_dbl(vec1.y);
343                            x2 = int26p6_to_dbl(vec2.x);
344                            y2 = int26p6_to_dbl(vec2.y);
345                            x3 = int26p6_to_dbl(vec.x);
346                            y3 = int26p6_to_dbl(vec.y);
347                            if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; }
348                            mtx.transform(&x1, &y1);
349                            mtx.transform(&x2, &y2);
350                            mtx.transform(&x3, &y3);
351                            path.curve4(value_type(dbl_to_int26p6(x1)),
352                                        value_type(dbl_to_int26p6(y1)),
353                                        value_type(dbl_to_int26p6(x2)),
354                                        value_type(dbl_to_int26p6(y2)),
355                                        value_type(dbl_to_int26p6(x3)),
356                                        value_type(dbl_to_int26p6(y3)));
357
358                            //path.curve4(conv(vec1.x),
359                            //            flip_y ? -conv(vec1.y) : conv(vec1.y),
360                            //            conv(vec2.x),
361                            //            flip_y ? -conv(vec2.y) : conv(vec2.y),
362                            //            conv(vec.x),
363                            //            flip_y ? -conv(vec.y) : conv(vec.y));
364                            continue;
365                        }
366
367                        x1 = int26p6_to_dbl(vec1.x);
368                        y1 = int26p6_to_dbl(vec1.y);
369                        x2 = int26p6_to_dbl(vec2.x);
370                        y2 = int26p6_to_dbl(vec2.y);
371                        x3 = int26p6_to_dbl(v_start.x);
372                        y3 = int26p6_to_dbl(v_start.y);
373                        if(flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; }
374                        mtx.transform(&x1, &y1);
375                        mtx.transform(&x2, &y2);
376                        mtx.transform(&x3, &y3);
377                        path.curve4(value_type(dbl_to_int26p6(x1)),
378                                    value_type(dbl_to_int26p6(y1)),
379                                    value_type(dbl_to_int26p6(x2)),
380                                    value_type(dbl_to_int26p6(y2)),
381                                    value_type(dbl_to_int26p6(x3)),
382                                    value_type(dbl_to_int26p6(y3)));
383
384                        //path.curve4(conv(vec1.x),
385                        //            flip_y ? -conv(vec1.y) : conv(vec1.y),
386                        //            conv(vec2.x),
387                        //            flip_y ? -conv(vec2.y) : conv(vec2.y),
388                        //            conv(v_start.x),
389                        //            flip_y ? -conv(v_start.y) : conv(v_start.y));
390                        goto Close;
391                    }
392                }
393            }
394
395            path.close_polygon();
396
397       Close:
398            first = last + 1;
399        }
400
401        return true;
402    }
403
404
405
406    //------------------------------------------------------------------------
407    template<class Scanline, class ScanlineStorage>
408    void decompose_ft_bitmap_mono(const FT_Bitmap& bitmap,
409                                  int x, int y,
410                                  bool flip_y,
411                                  Scanline& sl,
412                                  ScanlineStorage& storage)
413    {
414        int i;
415        const int8u* buf = (const int8u*)bitmap.buffer;
416        int pitch = bitmap.pitch;
417        sl.reset(x, x + bitmap.width);
418        storage.prepare();
419        if(flip_y)
420        {
421            buf += bitmap.pitch * (bitmap.rows - 1);
422            y += bitmap.rows;
423            pitch = -pitch;
424        }
425        for(i = 0; i < bitmap.rows; i++)
426        {
427            sl.reset_spans();
428            bitset_iterator bits(buf, 0);
429            int j;
430            for(j = 0; j < bitmap.width; j++)
431            {
432                if(bits.bit()) sl.add_cell(x + j, cover_full);
433                ++bits;
434            }
435            buf += pitch;
436            if(sl.num_spans())
437            {
438                sl.finalize(y - i - 1);
439                storage.render(sl);
440            }
441        }
442    }
443
444
445
446    //------------------------------------------------------------------------
447    template<class Rasterizer, class Scanline, class ScanlineStorage>
448    void decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap,
449                                   int x, int y,
450                                   bool flip_y,
451                                   Rasterizer& ras,
452                                   Scanline& sl,
453                                   ScanlineStorage& storage)
454    {
455        int i, j;
456        const int8u* buf = (const int8u*)bitmap.buffer;
457        int pitch = bitmap.pitch;
458        sl.reset(x, x + bitmap.width);
459        storage.prepare();
460        if(flip_y)
461        {
462            buf += bitmap.pitch * (bitmap.rows - 1);
463            y += bitmap.rows;
464            pitch = -pitch;
465        }
466        for(i = 0; i < bitmap.rows; i++)
467        {
468            sl.reset_spans();
469            const int8u* p = buf;
470            for(j = 0; j < bitmap.width; j++)
471            {
472                if(*p) sl.add_cell(x + j, ras.apply_gamma(*p));
473                ++p;
474            }
475            buf += pitch;
476            if(sl.num_spans())
477            {
478                sl.finalize(y - i - 1);
479                storage.render(sl);
480            }
481        }
482    }
483
484
485
486
487
488
489
490
491
492
493
494
495
496    //------------------------------------------------------------------------
497    font_engine_freetype_base::~font_engine_freetype_base()
498    {
499        unsigned i;
500        for(i = 0; i < m_num_faces; ++i)
501        {
502            delete [] m_face_names[i];
503            FT_Done_Face(m_faces[i]);
504        }
505        delete [] m_face_names;
506        delete [] m_faces;
507        delete [] m_signature;
508        if(m_library_initialized) FT_Done_FreeType(m_library);
509    }
510
511
512    //------------------------------------------------------------------------
513    font_engine_freetype_base::font_engine_freetype_base(bool flag32,
514                                                         unsigned max_faces) :
515        m_flag32(flag32),
516        m_change_stamp(0),
517        m_last_error(0),
518        m_name(0),
519        m_name_len(256-16-1),
520        m_face_index(0),
521        m_char_map(FT_ENCODING_NONE),
522        m_signature(new char [256+256-16]),
523        m_height(0),
524        m_width(0),
525        m_hinting(true),
526        m_flip_y(false),
527        m_library_initialized(false),
528        m_library(0),
529        m_faces(new FT_Face [max_faces]),
530        m_face_names(new char* [max_faces]),
531        m_num_faces(0),
532        m_max_faces(max_faces),
533        m_cur_face(0),
534        m_resolution(0),
535        m_glyph_rendering(glyph_ren_native_gray8),
536        m_glyph_index(0),
537        m_data_size(0),
538        m_data_type(glyph_data_invalid),
539        m_bounds(1,1,0,0),
540        m_advance_x(0.0),
541        m_advance_y(0.0),
542
543        m_path16(),
544        m_path32(),
545        m_curves16(m_path16),
546        m_curves32(m_path32),
547        m_scanline_aa(),
548        m_scanline_bin(),
549        m_scanlines_aa(),
550        m_scanlines_bin(),
551        m_rasterizer()
552    {
553        m_curves16.approximation_scale(4.0);
554        m_curves32.approximation_scale(4.0);
555        m_last_error = FT_Init_FreeType(&m_library);
556        if(m_last_error == 0) m_library_initialized = true;
557    }
558
559
560
561    //------------------------------------------------------------------------
562    void font_engine_freetype_base::resolution(unsigned dpi)
563    {
564        m_resolution = dpi;
565        update_char_size();
566    }
567
568
569    //------------------------------------------------------------------------
570    int font_engine_freetype_base::find_face(const char* face_name) const
571    {
572        unsigned i;
573        for(i = 0; i < m_num_faces; ++i)
574        {
575            if(strcmp(face_name, m_face_names[i]) == 0) return i;
576        }
577        return -1;
578    }
579
580
581    //------------------------------------------------------------------------
582    double font_engine_freetype_base::ascender() const
583    {
584        if(m_cur_face)
585        {
586            return m_cur_face->ascender * height() / m_cur_face->height;
587        }
588        return 0.0;
589    }
590
591    //------------------------------------------------------------------------
592    double font_engine_freetype_base::descender() const
593    {
594        if(m_cur_face)
595        {
596            return m_cur_face->descender * height() / m_cur_face->height;
597        }
598        return 0.0;
599    }
600
601
602    //------------------------------------------------------------------------
603    bool font_engine_freetype_base::load_font(const char* font_name,
604                                              unsigned face_index,
605                                              glyph_rendering ren_type,
606                                              const char* font_mem,
607                                              const long font_mem_size)
608    {
609        bool ret = false;
610
611        if(m_library_initialized)
612        {
613            m_last_error = 0;
614
615            int idx = find_face(font_name);
616            if(idx >= 0)
617            {
618                m_cur_face = m_faces[idx];
619                m_name     = m_face_names[idx];
620            }
621            else
622            {
623                if(m_num_faces >= m_max_faces)
624                {
625                    delete [] m_face_names[0];
626                    FT_Done_Face(m_faces[0]);
627                    memcpy(m_faces,
628                           m_faces + 1,
629                           (m_max_faces - 1) * sizeof(FT_Face));
630                    memcpy(m_face_names,
631                           m_face_names + 1,
632                           (m_max_faces - 1) * sizeof(char*));
633                    m_num_faces = m_max_faces - 1;
634                }
635
636                if (font_mem && font_mem_size)
637                {
638                    m_last_error = FT_New_Memory_Face(m_library,
639                                                      (const FT_Byte*)font_mem,
640                                                      font_mem_size,
641                                                      face_index,
642                                                      &m_faces[m_num_faces]);
643                }
644                else
645                {
646                    m_last_error = FT_New_Face(m_library,
647                                               font_name,
648                                               face_index,
649                                               &m_faces[m_num_faces]);
650                }
651
652                if(m_last_error == 0)
653                {
654                    m_face_names[m_num_faces] = new char [strlen(font_name) + 1];
655                    strcpy(m_face_names[m_num_faces], font_name);
656                    m_cur_face = m_faces[m_num_faces];
657                    m_name     = m_face_names[m_num_faces];
658                    ++m_num_faces;
659                }
660                else
661                {
662                    m_face_names[m_num_faces] = 0;
663                    m_cur_face = 0;
664                    m_name = 0;
665                }
666            }
667
668
669            if(m_last_error == 0)
670            {
671                ret = true;
672
673                switch(ren_type)
674                {
675                case glyph_ren_native_mono:
676                    m_glyph_rendering = glyph_ren_native_mono;
677                    break;
678
679                case glyph_ren_native_gray8:
680                    m_glyph_rendering = glyph_ren_native_gray8;
681                    break;
682
683                case glyph_ren_outline:
684                    if(FT_IS_SCALABLE(m_cur_face))
685                    {
686                        m_glyph_rendering = glyph_ren_outline;
687                    }
688                    else
689                    {
690                        m_glyph_rendering = glyph_ren_native_gray8;
691                    }
692                    break;
693
694                case glyph_ren_agg_mono:
695                    if(FT_IS_SCALABLE(m_cur_face))
696                    {
697                        m_glyph_rendering = glyph_ren_agg_mono;
698                    }
699                    else
700                    {
701                        m_glyph_rendering = glyph_ren_native_mono;
702                    }
703                    break;
704
705                case glyph_ren_agg_gray8:
706                    if(FT_IS_SCALABLE(m_cur_face))
707                    {
708                        m_glyph_rendering = glyph_ren_agg_gray8;
709                    }
710                    else
711                    {
712                        m_glyph_rendering = glyph_ren_native_gray8;
713                    }
714                    break;
715                }
716                update_signature();
717            }
718        }
719        return ret;
720    }
721
722
723    //------------------------------------------------------------------------
724    bool font_engine_freetype_base::attach(const char* file_name)
725    {
726        if(m_cur_face)
727        {
728            m_last_error = FT_Attach_File(m_cur_face, file_name);
729            return m_last_error == 0;
730        }
731        return false;
732    }
733
734    //------------------------------------------------------------------------
735    unsigned font_engine_freetype_base::num_faces() const
736    {
737        if(m_cur_face)
738        {
739            return m_cur_face->num_faces;
740        }
741        return 0;
742    }
743
744    //------------------------------------------------------------------------
745    bool font_engine_freetype_base::char_map(FT_Encoding char_map)
746    {
747        if(m_cur_face)
748        {
749            m_last_error = FT_Select_Charmap(m_cur_face, m_char_map);
750            if(m_last_error == 0)
751            {
752                update_signature();
753                return true;
754            }
755        }
756        return false;
757    }
758
759    //------------------------------------------------------------------------
760    bool font_engine_freetype_base::height(double h)
761    {
762        m_height = int(h * 64.0);
763        if(m_cur_face)
764        {
765            update_char_size();
766            return true;
767        }
768        return false;
769    }
770
771    //------------------------------------------------------------------------
772    bool font_engine_freetype_base::width(double w)
773    {
774        m_width = int(w * 64.0);
775        if(m_cur_face)
776        {
777            update_char_size();
778            return true;
779        }
780        return false;
781    }
782
783    //------------------------------------------------------------------------
784    void font_engine_freetype_base::hinting(bool h)
785    {
786        m_hinting = h;
787        if(m_cur_face)
788        {
789            update_signature();
790        }
791    }
792
793    //------------------------------------------------------------------------
794    void font_engine_freetype_base::flip_y(bool f)
795    {
796        m_flip_y = f;
797        if(m_cur_face)
798        {
799            update_signature();
800        }
801    }
802
803    //------------------------------------------------------------------------
804    void font_engine_freetype_base::transform(const trans_affine& affine)
805    {
806        m_affine = affine;
807        if(m_cur_face)
808        {
809            update_signature();
810        }
811    }
812
813    //------------------------------------------------------------------------
814    void font_engine_freetype_base::update_signature()
815    {
816        if(m_cur_face && m_name)
817        {
818            unsigned name_len = strlen(m_name);
819            if(name_len > m_name_len)
820            {
821                delete [] m_signature;
822                m_signature = new char [name_len + 32 + 256];
823                m_name_len = name_len + 32 - 1;
824            }
825
826            unsigned gamma_hash = 0;
827            if(m_glyph_rendering == glyph_ren_native_gray8 ||
828               m_glyph_rendering == glyph_ren_agg_mono ||
829               m_glyph_rendering == glyph_ren_agg_gray8)
830            {
831                unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale];
832                unsigned i;
833                for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i)
834                {
835                    gamma_table[i] = m_rasterizer.apply_gamma(i);
836                }
837                gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table));
838            }
839
840            sprintf(m_signature,
841                    "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X",
842                    m_name,
843                    m_char_map,
844                    m_face_index,
845                    int(m_glyph_rendering),
846                    m_resolution,
847                    m_height,
848                    m_width,
849                    int(m_hinting),
850                    int(m_flip_y),
851                    gamma_hash);
852            if(m_glyph_rendering == glyph_ren_outline ||
853               m_glyph_rendering == glyph_ren_agg_mono ||
854               m_glyph_rendering == glyph_ren_agg_gray8)
855            {
856                double mtx[6];
857                char buf[100];
858                m_affine.store_to(mtx);
859                sprintf(buf, ",%08X%08X%08X%08X%08X%08X",
860                    dbl_to_plain_fx(mtx[0]),
861                    dbl_to_plain_fx(mtx[1]),
862                    dbl_to_plain_fx(mtx[2]),
863                    dbl_to_plain_fx(mtx[3]),
864                    dbl_to_plain_fx(mtx[4]),
865                    dbl_to_plain_fx(mtx[5]));
866                strcat(m_signature, buf);
867            }
868            ++m_change_stamp;
869        }
870    }
871
872
873    //------------------------------------------------------------------------
874    void font_engine_freetype_base::update_char_size()
875    {
876        if(m_cur_face)
877        {
878            if(m_resolution)
879            {
880                FT_Set_Char_Size(m_cur_face,
881                                 m_width,       // char_width in 1/64th of points
882                                 m_height,      // char_height in 1/64th of points
883                                 m_resolution,  // horizontal device resolution
884                                 m_resolution); // vertical device resolution
885            }
886            else
887            {
888                FT_Set_Pixel_Sizes(m_cur_face,
889                                   m_width >> 6,    // pixel_width
890                                   m_height >> 6);  // pixel_height
891            }
892            update_signature();
893        }
894    }
895
896
897
898
899
900    //------------------------------------------------------------------------
901    bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code)
902    {
903        m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code);
904        m_last_error = FT_Load_Glyph(m_cur_face,
905                                     m_glyph_index,
906                                     m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING);
907//                                     m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING);
908        if(m_last_error == 0)
909        {
910            switch(m_glyph_rendering)
911            {
912            case glyph_ren_native_mono:
913                m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO);
914                if(m_last_error == 0)
915                {
916                    decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap,
917                                             m_cur_face->glyph->bitmap_left,
918                                             m_flip_y ? -m_cur_face->glyph->bitmap_top :
919                                                         m_cur_face->glyph->bitmap_top,
920                                             m_flip_y,
921                                             m_scanline_bin,
922                                             m_scanlines_bin);
923                    m_bounds.x1 = m_scanlines_bin.min_x();
924                    m_bounds.y1 = m_scanlines_bin.min_y();
925                    m_bounds.x2 = m_scanlines_bin.max_x() + 1;
926                    m_bounds.y2 = m_scanlines_bin.max_y() + 1;
927                    m_data_size = m_scanlines_bin.byte_size();
928                    m_data_type = glyph_data_mono;
929                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
930                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
931                    return true;
932                }
933                break;
934
935
936            case glyph_ren_native_gray8:
937                m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL);
938                if(m_last_error == 0)
939                {
940                    decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap,
941                                              m_cur_face->glyph->bitmap_left,
942                                              m_flip_y ? -m_cur_face->glyph->bitmap_top :
943                                                          m_cur_face->glyph->bitmap_top,
944                                              m_flip_y,
945                                              m_rasterizer,
946                                              m_scanline_aa,
947                                              m_scanlines_aa);
948                    m_bounds.x1 = m_scanlines_aa.min_x();
949                    m_bounds.y1 = m_scanlines_aa.min_y();
950                    m_bounds.x2 = m_scanlines_aa.max_x() + 1;
951                    m_bounds.y2 = m_scanlines_aa.max_y() + 1;
952                    m_data_size = m_scanlines_aa.byte_size();
953                    m_data_type = glyph_data_gray8;
954                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
955                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
956                    return true;
957                }
958                break;
959
960
961            case glyph_ren_outline:
962                if(m_last_error == 0)
963                {
964                    if(m_flag32)
965                    {
966                        m_path32.remove_all();
967                        if(decompose_ft_outline(m_cur_face->glyph->outline,
968                                                m_flip_y,
969                                                m_affine,
970                                                m_path32))
971                        {
972                            rect_d bnd  = m_path32.bounding_rect();
973                            m_data_size = m_path32.byte_size();
974                            m_data_type = glyph_data_outline;
975                            m_bounds.x1 = int(floor(bnd.x1));
976                            m_bounds.y1 = int(floor(bnd.y1));
977                            m_bounds.x2 = int(ceil(bnd.x2));
978                            m_bounds.y2 = int(ceil(bnd.y2));
979                            m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
980                            m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
981                            m_affine.transform(&m_advance_x, &m_advance_y);
982                            return true;
983                        }
984                    }
985                    else
986                    {
987                        m_path16.remove_all();
988                        if(decompose_ft_outline(m_cur_face->glyph->outline,
989                                                m_flip_y,
990                                                m_affine,
991                                                m_path16))
992                        {
993                            rect_d bnd  = m_path16.bounding_rect();
994                            m_data_size = m_path16.byte_size();
995                            m_data_type = glyph_data_outline;
996                            m_bounds.x1 = int(floor(bnd.x1));
997                            m_bounds.y1 = int(floor(bnd.y1));
998                            m_bounds.x2 = int(ceil(bnd.x2));
999                            m_bounds.y2 = int(ceil(bnd.y2));
1000                            m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1001                            m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1002                            m_affine.transform(&m_advance_x, &m_advance_y);
1003                            return true;
1004                        }
1005                    }
1006                }
1007                return false;
1008
1009            case glyph_ren_agg_mono:
1010                if(m_last_error == 0)
1011                {
1012                    m_rasterizer.reset();
1013                    if(m_flag32)
1014                    {
1015                        m_path32.remove_all();
1016                        decompose_ft_outline(m_cur_face->glyph->outline,
1017                                             m_flip_y,
1018                                             m_affine,
1019                                             m_path32);
1020                        m_rasterizer.add_path(m_curves32);
1021                    }
1022                    else
1023                    {
1024                        m_path16.remove_all();
1025                        decompose_ft_outline(m_cur_face->glyph->outline,
1026                                             m_flip_y,
1027                                             m_affine,
1028                                             m_path16);
1029                        m_rasterizer.add_path(m_curves16);
1030                    }
1031                    m_scanlines_bin.prepare(); // Remove all
1032                    render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin);
1033                    m_bounds.x1 = m_scanlines_bin.min_x();
1034                    m_bounds.y1 = m_scanlines_bin.min_y();
1035                    m_bounds.x2 = m_scanlines_bin.max_x() + 1;
1036                    m_bounds.y2 = m_scanlines_bin.max_y() + 1;
1037                    m_data_size = m_scanlines_bin.byte_size();
1038                    m_data_type = glyph_data_mono;
1039                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1040                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1041                    m_affine.transform(&m_advance_x, &m_advance_y);
1042                    return true;
1043                }
1044                return false;
1045
1046
1047            case glyph_ren_agg_gray8:
1048                if(m_last_error == 0)
1049                {
1050                    m_rasterizer.reset();
1051                    if(m_flag32)
1052                    {
1053                        m_path32.remove_all();
1054                        decompose_ft_outline(m_cur_face->glyph->outline,
1055                                             m_flip_y,
1056                                             m_affine,
1057                                             m_path32);
1058                        m_rasterizer.add_path(m_curves32);
1059                    }
1060                    else
1061                    {
1062                        m_path16.remove_all();
1063                        decompose_ft_outline(m_cur_face->glyph->outline,
1064                                             m_flip_y,
1065                                             m_affine,
1066                                             m_path16);
1067                        m_rasterizer.add_path(m_curves16);
1068                    }
1069                    m_scanlines_aa.prepare(); // Remove all
1070                    render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa);
1071                    m_bounds.x1 = m_scanlines_aa.min_x();
1072                    m_bounds.y1 = m_scanlines_aa.min_y();
1073                    m_bounds.x2 = m_scanlines_aa.max_x() + 1;
1074                    m_bounds.y2 = m_scanlines_aa.max_y() + 1;
1075                    m_data_size = m_scanlines_aa.byte_size();
1076                    m_data_type = glyph_data_gray8;
1077                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1078                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1079                    m_affine.transform(&m_advance_x, &m_advance_y);
1080                    return true;
1081                }
1082                return false;
1083            }
1084        }
1085        return false;
1086    }
1087
1088
1089
1090
1091    //------------------------------------------------------------------------
1092    void font_engine_freetype_base::write_glyph_to(int8u* data) const
1093    {
1094        if(data && m_data_size)
1095        {
1096            switch(m_data_type)
1097            {
1098            default: return;
1099            case glyph_data_mono:    m_scanlines_bin.serialize(data); break;
1100            case glyph_data_gray8:   m_scanlines_aa.serialize(data);  break;
1101            case glyph_data_outline:
1102                if(m_flag32)
1103                {
1104                    m_path32.serialize(data);
1105                }
1106                else
1107                {
1108                    m_path16.serialize(data);
1109                }
1110                break;
1111            case glyph_data_invalid: break;
1112            }
1113        }
1114    }
1115
1116
1117
1118    //------------------------------------------------------------------------
1119    bool font_engine_freetype_base::add_kerning(unsigned first, unsigned second,
1120                                           double* x, double* y)
1121    {
1122        if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face))
1123        {
1124            FT_Vector delta;
1125            FT_Get_Kerning(m_cur_face, first, second,
1126                           FT_KERNING_DEFAULT, &delta);
1127            double dx = int26p6_to_dbl(delta.x);
1128            double dy = int26p6_to_dbl(delta.y);
1129            if(m_glyph_rendering == glyph_ren_outline ||
1130               m_glyph_rendering == glyph_ren_agg_mono ||
1131               m_glyph_rendering == glyph_ren_agg_gray8)
1132            {
1133                m_affine.transform_2x2(&dx, &dy);
1134            }
1135            *x += dx;
1136            *y += dy;
1137
1138            return true;
1139        }
1140        return false;
1141    }
1142
1143
1144
1145}
1146
1147
1148