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, char_map);
750            if(m_last_error == 0)
751            {
752                m_char_map = char_map;
753                update_signature();
754                return true;
755            }
756        }
757        return false;
758    }
759
760    //------------------------------------------------------------------------
761    bool font_engine_freetype_base::height(double h)
762    {
763        m_height = int(h * 64.0);
764        if(m_cur_face)
765        {
766            update_char_size();
767            return true;
768        }
769        return false;
770    }
771
772    //------------------------------------------------------------------------
773    bool font_engine_freetype_base::width(double w)
774    {
775        m_width = int(w * 64.0);
776        if(m_cur_face)
777        {
778            update_char_size();
779            return true;
780        }
781        return false;
782    }
783
784    //------------------------------------------------------------------------
785    void font_engine_freetype_base::hinting(bool h)
786    {
787        m_hinting = h;
788        if(m_cur_face)
789        {
790            update_signature();
791        }
792    }
793
794    //------------------------------------------------------------------------
795    void font_engine_freetype_base::flip_y(bool f)
796    {
797        m_flip_y = f;
798        if(m_cur_face)
799        {
800            update_signature();
801        }
802    }
803
804    //------------------------------------------------------------------------
805    void font_engine_freetype_base::transform(const trans_affine& affine)
806    {
807        m_affine = affine;
808        if(m_cur_face)
809        {
810            update_signature();
811        }
812    }
813
814    //------------------------------------------------------------------------
815    void font_engine_freetype_base::update_signature()
816    {
817        if(m_cur_face && m_name)
818        {
819            unsigned name_len = strlen(m_name);
820            if(name_len > m_name_len)
821            {
822                delete [] m_signature;
823                m_signature = new char [name_len + 32 + 256];
824                m_name_len = name_len + 32 - 1;
825            }
826
827            unsigned gamma_hash = 0;
828            if(m_glyph_rendering == glyph_ren_native_gray8 ||
829               m_glyph_rendering == glyph_ren_agg_mono ||
830               m_glyph_rendering == glyph_ren_agg_gray8)
831            {
832                unsigned char gamma_table[rasterizer_scanline_aa<>::aa_scale];
833                unsigned i;
834                for(i = 0; i < rasterizer_scanline_aa<>::aa_scale; ++i)
835                {
836                    gamma_table[i] = m_rasterizer.apply_gamma(i);
837                }
838                gamma_hash = calc_crc32(gamma_table, sizeof(gamma_table));
839            }
840
841            sprintf(m_signature,
842                    "%s,%u,%d,%d,%d:%dx%d,%d,%d,%08X",
843                    m_name,
844                    m_char_map,
845                    m_face_index,
846                    int(m_glyph_rendering),
847                    m_resolution,
848                    m_height,
849                    m_width,
850                    int(m_hinting),
851                    int(m_flip_y),
852                    gamma_hash);
853            if(m_glyph_rendering == glyph_ren_outline ||
854               m_glyph_rendering == glyph_ren_agg_mono ||
855               m_glyph_rendering == glyph_ren_agg_gray8)
856            {
857                double mtx[6];
858                char buf[100];
859                m_affine.store_to(mtx);
860                sprintf(buf, ",%08X%08X%08X%08X%08X%08X",
861                    dbl_to_plain_fx(mtx[0]),
862                    dbl_to_plain_fx(mtx[1]),
863                    dbl_to_plain_fx(mtx[2]),
864                    dbl_to_plain_fx(mtx[3]),
865                    dbl_to_plain_fx(mtx[4]),
866                    dbl_to_plain_fx(mtx[5]));
867                strcat(m_signature, buf);
868            }
869            ++m_change_stamp;
870        }
871    }
872
873
874    //------------------------------------------------------------------------
875    void font_engine_freetype_base::update_char_size()
876    {
877        if(m_cur_face)
878        {
879            if(m_resolution)
880            {
881                FT_Set_Char_Size(m_cur_face,
882                                 m_width,       // char_width in 1/64th of points
883                                 m_height,      // char_height in 1/64th of points
884                                 m_resolution,  // horizontal device resolution
885                                 m_resolution); // vertical device resolution
886            }
887            else
888            {
889                FT_Set_Pixel_Sizes(m_cur_face,
890                                   m_width >> 6,    // pixel_width
891                                   m_height >> 6);  // pixel_height
892            }
893            update_signature();
894        }
895    }
896
897
898
899
900
901    //------------------------------------------------------------------------
902    bool font_engine_freetype_base::prepare_glyph(unsigned glyph_code)
903    {
904        m_glyph_index = FT_Get_Char_Index(m_cur_face, glyph_code);
905        m_last_error = FT_Load_Glyph(m_cur_face,
906                                     m_glyph_index,
907                                     m_hinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING);
908//                                     m_hinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING);
909        if(m_last_error == 0)
910        {
911            switch(m_glyph_rendering)
912            {
913            case glyph_ren_native_mono:
914                m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_MONO);
915                if(m_last_error == 0)
916                {
917                    decompose_ft_bitmap_mono(m_cur_face->glyph->bitmap,
918                                             m_cur_face->glyph->bitmap_left,
919                                             m_flip_y ? -m_cur_face->glyph->bitmap_top :
920                                                         m_cur_face->glyph->bitmap_top,
921                                             m_flip_y,
922                                             m_scanline_bin,
923                                             m_scanlines_bin);
924                    m_bounds.x1 = m_scanlines_bin.min_x();
925                    m_bounds.y1 = m_scanlines_bin.min_y();
926                    m_bounds.x2 = m_scanlines_bin.max_x() + 1;
927                    m_bounds.y2 = m_scanlines_bin.max_y() + 1;
928                    m_data_size = m_scanlines_bin.byte_size();
929                    m_data_type = glyph_data_mono;
930                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
931                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
932                    return true;
933                }
934                break;
935
936
937            case glyph_ren_native_gray8:
938                m_last_error = FT_Render_Glyph(m_cur_face->glyph, FT_RENDER_MODE_NORMAL);
939                if(m_last_error == 0)
940                {
941                    decompose_ft_bitmap_gray8(m_cur_face->glyph->bitmap,
942                                              m_cur_face->glyph->bitmap_left,
943                                              m_flip_y ? -m_cur_face->glyph->bitmap_top :
944                                                          m_cur_face->glyph->bitmap_top,
945                                              m_flip_y,
946                                              m_rasterizer,
947                                              m_scanline_aa,
948                                              m_scanlines_aa);
949                    m_bounds.x1 = m_scanlines_aa.min_x();
950                    m_bounds.y1 = m_scanlines_aa.min_y();
951                    m_bounds.x2 = m_scanlines_aa.max_x() + 1;
952                    m_bounds.y2 = m_scanlines_aa.max_y() + 1;
953                    m_data_size = m_scanlines_aa.byte_size();
954                    m_data_type = glyph_data_gray8;
955                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
956                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
957                    return true;
958                }
959                break;
960
961
962            case glyph_ren_outline:
963                if(m_last_error == 0)
964                {
965                    if(m_flag32)
966                    {
967                        m_path32.remove_all();
968                        if(decompose_ft_outline(m_cur_face->glyph->outline,
969                                                m_flip_y,
970                                                m_affine,
971                                                m_path32))
972                        {
973                            rect_d bnd  = m_path32.bounding_rect();
974                            m_data_size = m_path32.byte_size();
975                            m_data_type = glyph_data_outline;
976                            m_bounds.x1 = int(floor(bnd.x1));
977                            m_bounds.y1 = int(floor(bnd.y1));
978                            m_bounds.x2 = int(ceil(bnd.x2));
979                            m_bounds.y2 = int(ceil(bnd.y2));
980                            m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
981                            m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
982                            m_affine.transform(&m_advance_x, &m_advance_y);
983                            return true;
984                        }
985                    }
986                    else
987                    {
988                        m_path16.remove_all();
989                        if(decompose_ft_outline(m_cur_face->glyph->outline,
990                                                m_flip_y,
991                                                m_affine,
992                                                m_path16))
993                        {
994                            rect_d bnd  = m_path16.bounding_rect();
995                            m_data_size = m_path16.byte_size();
996                            m_data_type = glyph_data_outline;
997                            m_bounds.x1 = int(floor(bnd.x1));
998                            m_bounds.y1 = int(floor(bnd.y1));
999                            m_bounds.x2 = int(ceil(bnd.x2));
1000                            m_bounds.y2 = int(ceil(bnd.y2));
1001                            m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1002                            m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1003                            m_affine.transform(&m_advance_x, &m_advance_y);
1004                            return true;
1005                        }
1006                    }
1007                }
1008                return false;
1009
1010            case glyph_ren_agg_mono:
1011                if(m_last_error == 0)
1012                {
1013                    m_rasterizer.reset();
1014                    if(m_flag32)
1015                    {
1016                        m_path32.remove_all();
1017                        decompose_ft_outline(m_cur_face->glyph->outline,
1018                                             m_flip_y,
1019                                             m_affine,
1020                                             m_path32);
1021                        m_rasterizer.add_path(m_curves32);
1022                    }
1023                    else
1024                    {
1025                        m_path16.remove_all();
1026                        decompose_ft_outline(m_cur_face->glyph->outline,
1027                                             m_flip_y,
1028                                             m_affine,
1029                                             m_path16);
1030                        m_rasterizer.add_path(m_curves16);
1031                    }
1032                    m_scanlines_bin.prepare(); // Remove all
1033                    render_scanlines(m_rasterizer, m_scanline_bin, m_scanlines_bin);
1034                    m_bounds.x1 = m_scanlines_bin.min_x();
1035                    m_bounds.y1 = m_scanlines_bin.min_y();
1036                    m_bounds.x2 = m_scanlines_bin.max_x() + 1;
1037                    m_bounds.y2 = m_scanlines_bin.max_y() + 1;
1038                    m_data_size = m_scanlines_bin.byte_size();
1039                    m_data_type = glyph_data_mono;
1040                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1041                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1042                    m_affine.transform(&m_advance_x, &m_advance_y);
1043                    return true;
1044                }
1045                return false;
1046
1047
1048            case glyph_ren_agg_gray8:
1049                if(m_last_error == 0)
1050                {
1051                    m_rasterizer.reset();
1052                    if(m_flag32)
1053                    {
1054                        m_path32.remove_all();
1055                        decompose_ft_outline(m_cur_face->glyph->outline,
1056                                             m_flip_y,
1057                                             m_affine,
1058                                             m_path32);
1059                        m_rasterizer.add_path(m_curves32);
1060                    }
1061                    else
1062                    {
1063                        m_path16.remove_all();
1064                        decompose_ft_outline(m_cur_face->glyph->outline,
1065                                             m_flip_y,
1066                                             m_affine,
1067                                             m_path16);
1068                        m_rasterizer.add_path(m_curves16);
1069                    }
1070                    m_scanlines_aa.prepare(); // Remove all
1071                    render_scanlines(m_rasterizer, m_scanline_aa, m_scanlines_aa);
1072                    m_bounds.x1 = m_scanlines_aa.min_x();
1073                    m_bounds.y1 = m_scanlines_aa.min_y();
1074                    m_bounds.x2 = m_scanlines_aa.max_x() + 1;
1075                    m_bounds.y2 = m_scanlines_aa.max_y() + 1;
1076                    m_data_size = m_scanlines_aa.byte_size();
1077                    m_data_type = glyph_data_gray8;
1078                    m_advance_x = int26p6_to_dbl(m_cur_face->glyph->advance.x);
1079                    m_advance_y = int26p6_to_dbl(m_cur_face->glyph->advance.y);
1080                    m_affine.transform(&m_advance_x, &m_advance_y);
1081                    return true;
1082                }
1083                return false;
1084            }
1085        }
1086        return false;
1087    }
1088
1089
1090
1091
1092    //------------------------------------------------------------------------
1093    void font_engine_freetype_base::write_glyph_to(int8u* data) const
1094    {
1095        if(data && m_data_size)
1096        {
1097            switch(m_data_type)
1098            {
1099            default: return;
1100            case glyph_data_mono:    m_scanlines_bin.serialize(data); break;
1101            case glyph_data_gray8:   m_scanlines_aa.serialize(data);  break;
1102            case glyph_data_outline:
1103                if(m_flag32)
1104                {
1105                    m_path32.serialize(data);
1106                }
1107                else
1108                {
1109                    m_path16.serialize(data);
1110                }
1111                break;
1112            case glyph_data_invalid: break;
1113            }
1114        }
1115    }
1116
1117
1118
1119    //------------------------------------------------------------------------
1120    bool font_engine_freetype_base::add_kerning(unsigned first, unsigned second,
1121                                           double* x, double* y)
1122    {
1123        if(m_cur_face && first && second && FT_HAS_KERNING(m_cur_face))
1124        {
1125            FT_Vector delta;
1126            FT_Get_Kerning(m_cur_face, first, second,
1127                           FT_KERNING_DEFAULT, &delta);
1128            double dx = int26p6_to_dbl(delta.x);
1129            double dy = int26p6_to_dbl(delta.y);
1130            if(m_glyph_rendering == glyph_ren_outline ||
1131               m_glyph_rendering == glyph_ren_agg_mono ||
1132               m_glyph_rendering == glyph_ren_agg_gray8)
1133            {
1134                m_affine.transform_2x2(&dx, &dy);
1135            }
1136            *x += dx;
1137            *y += dy;
1138
1139            return true;
1140        }
1141        return false;
1142    }
1143
1144
1145
1146}
1147
1148
1149