Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qtbase-staging
[profile/ivi/qtbase.git] / src / gui / text / qfontengine_ft.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdir.h"
43 #include "qmetatype.h"
44 #include "qtextstream.h"
45 #include "qvariant.h"
46 #include "qfontengine_ft_p.h"
47
48 #ifndef QT_NO_FREETYPE
49
50 #include "qfile.h"
51 #include "qabstractfileengine.h"
52 #include "qthreadstorage.h"
53 #include <qmath.h>
54 #include <private/qharfbuzz_p.h>
55
56 #include "qfontengine_ft_p.h"
57 #include <ft2build.h>
58 #include FT_FREETYPE_H
59 #include FT_OUTLINE_H
60 #include FT_SYNTHESIS_H
61 #include FT_TRUETYPE_TABLES_H
62 #include FT_TYPE1_TABLES_H
63 #include FT_GLYPH_H
64
65 #if defined(FT_LCD_FILTER_H)
66 #include FT_LCD_FILTER_H
67 #endif
68
69 #if defined(FT_CONFIG_OPTIONS_H)
70 #include FT_CONFIG_OPTIONS_H
71 #endif
72
73 #if defined(FT_LCD_FILTER_H) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
74 #define QT_USE_FREETYPE_LCDFILTER
75 #endif
76
77 #ifdef QT_LINUXBASE
78 #include FT_ERRORS_H
79 #endif
80
81 QT_BEGIN_NAMESPACE
82
83 /*
84  * Freetype 2.1.7 and earlier used width/height
85  * for matching sizes in the BDF and PCF loaders.
86  * This has been fixed for 2.1.8.
87  */
88 #if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20105
89 #define X_SIZE(face,i) ((face)->available_sizes[i].x_ppem)
90 #define Y_SIZE(face,i) ((face)->available_sizes[i].y_ppem)
91 #else
92 #define X_SIZE(face,i) ((face)->available_sizes[i].width << 6)
93 #define Y_SIZE(face,i) ((face)->available_sizes[i].height << 6)
94 #endif
95
96 /* FreeType 2.1.10 starts to provide FT_GlyphSlot_Embolden */
97 #if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20110
98 #define Q_FT_GLYPHSLOT_EMBOLDEN(slot)   FT_GlyphSlot_Embolden(slot)
99 #else
100 #define Q_FT_GLYPHSLOT_EMBOLDEN(slot)
101 #endif
102
103 #define FLOOR(x)    ((x) & -64)
104 #define CEIL(x)     (((x)+63) & -64)
105 #define TRUNC(x)    ((x) >> 6)
106 #define ROUND(x)    (((x)+32) & -64)
107
108 static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
109 {
110 #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103
111     FT_Face face = (FT_Face)font;
112     FT_ULong ftlen = *length;
113     FT_Error error = 0;
114
115     if ( !FT_IS_SFNT(face) )
116         return HB_Err_Invalid_Argument;
117
118     error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
119     *length = ftlen;
120     return (HB_Error)error;
121 #else
122     return HB_Err_Invalid_Argument;
123 #endif
124 }
125
126 // -------------------------- Freetype support ------------------------------
127
128 class QtFreetypeData
129 {
130 public:
131     QtFreetypeData()
132         : library(0)
133     { }
134
135     FT_Library library;
136     QHash<QFontEngine::FaceId, QFreetypeFace *> faces;
137 };
138
139 #ifdef QT_NO_THREAD
140 Q_GLOBAL_STATIC(QtFreetypeData, theFreetypeData)
141
142 QtFreetypeData *qt_getFreetypeData()
143 {
144     return theFreetypeData();
145 }
146 #else
147 Q_GLOBAL_STATIC(QThreadStorage<QtFreetypeData *>, theFreetypeData)
148
149 QtFreetypeData *qt_getFreetypeData()
150 {
151     QtFreetypeData *&freetypeData = theFreetypeData()->localData();
152     if (!freetypeData)
153         freetypeData = new QtFreetypeData;
154     return freetypeData;
155 }
156 #endif
157
158 FT_Library qt_getFreetype()
159 {
160     QtFreetypeData *freetypeData = qt_getFreetypeData();
161     if (!freetypeData->library)
162         FT_Init_FreeType(&freetypeData->library);
163     return freetypeData->library;
164 }
165
166 int QFreetypeFace::fsType() const
167 {
168     int fsType = 0;
169     TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
170     if (os2)
171         fsType = os2->fsType;
172     return fsType;
173 }
174
175 HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
176 {
177     if (HB_Error error = (HB_Error)FT_Load_Glyph(face, glyph, flags))
178         return error;
179
180     if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
181         return HB_Err_Invalid_SubTable;
182
183     *nPoints = face->glyph->outline.n_points;
184     if (!(*nPoints))
185         return HB_Err_Ok;
186
187     if (point > *nPoints)
188         return HB_Err_Invalid_SubTable;
189
190     *xpos = face->glyph->outline.points[point].x;
191     *ypos = face->glyph->outline.points[point].y;
192
193     return HB_Err_Ok;
194 }
195
196 /*
197  * One font file can contain more than one font (bold/italic for example)
198  * find the right one and return it.
199  *
200  * Returns the freetype face or 0 in case of an empty file or any other problems
201  * (like not being able to open the file)
202  */
203 QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
204                                       const QByteArray &fontData)
205 {
206     if (face_id.filename.isEmpty() && fontData.isEmpty())
207         return 0;
208
209     QtFreetypeData *freetypeData = qt_getFreetypeData();
210     if (!freetypeData->library)
211         FT_Init_FreeType(&freetypeData->library);
212
213     QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
214     if (freetype) {
215         freetype->ref.ref();
216     } else {
217         QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
218         FT_Face face;
219         if (!face_id.filename.isEmpty()) {
220             QFile file(QString::fromUtf8(face_id.filename));
221             if (face_id.filename.startsWith(":qmemoryfonts/")) {
222                 // from qfontdatabase.cpp
223                 extern QByteArray qt_fontdata_from_index(int);
224                 QByteArray idx = face_id.filename;
225                 idx.remove(0, 14); // remove ':qmemoryfonts/'
226                 bool ok = false;
227                 newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
228                 if (!ok)
229                     newFreetype->fontData = QByteArray();
230             } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
231                 if (!file.open(QIODevice::ReadOnly)) {
232                     return 0;
233                 }
234                 newFreetype->fontData = file.readAll();
235             }
236         } else {
237             newFreetype->fontData = fontData;
238         }
239         if (!newFreetype->fontData.isEmpty()) {
240             if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) {
241                 return 0;
242             }
243         } else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) {
244             return 0;
245         }
246         newFreetype->face = face;
247
248         newFreetype->hbFace = qHBNewFace(face, hb_getSFntTable);
249         Q_CHECK_PTR(newFreetype->hbFace);
250         newFreetype->ref = 1;
251         newFreetype->xsize = 0;
252         newFreetype->ysize = 0;
253         newFreetype->matrix.xx = 0x10000;
254         newFreetype->matrix.yy = 0x10000;
255         newFreetype->matrix.xy = 0;
256         newFreetype->matrix.yx = 0;
257         newFreetype->unicode_map = 0;
258         newFreetype->symbol_map = 0;
259 #ifndef QT_NO_FONTCONFIG
260         newFreetype->charset = 0;
261 #endif
262
263         memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache));
264
265         for (int i = 0; i < newFreetype->face->num_charmaps; ++i) {
266             FT_CharMap cm = newFreetype->face->charmaps[i];
267             switch(cm->encoding) {
268             case FT_ENCODING_UNICODE:
269                 newFreetype->unicode_map = cm;
270                 break;
271             case FT_ENCODING_APPLE_ROMAN:
272             case FT_ENCODING_ADOBE_LATIN_1:
273                 if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE)
274                     newFreetype->unicode_map = cm;
275                 break;
276             case FT_ENCODING_ADOBE_CUSTOM:
277             case FT_ENCODING_MS_SYMBOL:
278                 if (!newFreetype->symbol_map)
279                     newFreetype->symbol_map = cm;
280                 break;
281             default:
282                 break;
283             }
284         }
285
286         if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
287             FT_Set_Char_Size (face, X_SIZE(newFreetype->face, 0), Y_SIZE(newFreetype->face, 0), 0, 0);
288 # if 0
289         FcChar8 *name;
290         FcPatternGetString(pattern, FC_FAMILY, 0, &name);
291         qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name,
292                newFreetype->face->charmap ? newFreetype->face->charmap->encoding : 0,
293                newFreetype->unicode_map ? newFreetype->unicode_map->encoding : 0,
294                newFreetype->symbol_map ? newFreetype->symbol_map->encoding : 0);
295
296         for (int i = 0; i < 256; i += 8)
297             qDebug("    %x: %d %d %d %d %d %d %d %d", i,
298                    FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
299                    FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
300                    FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
301                    FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i));
302 #endif
303
304         FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
305         QT_TRY {
306             freetypeData->faces.insert(face_id, newFreetype.data());
307         } QT_CATCH(...) {
308             newFreetype.take()->release(face_id);
309             // we could return null in principle instead of throwing
310             QT_RETHROW;
311         }
312         freetype = newFreetype.take();
313     }
314     return freetype;
315 }
316
317 void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
318 {
319     QtFreetypeData *freetypeData = qt_getFreetypeData();
320     if (!ref.deref()) {
321         qHBFreeFace(hbFace);
322         FT_Done_Face(face);
323 #ifndef QT_NO_FONTCONFIG
324         if (charset)
325             FcCharSetDestroy(charset);
326 #endif
327         if(freetypeData->faces.contains(face_id))
328             freetypeData->faces.take(face_id);
329         delete this;
330     }
331     if (freetypeData->faces.isEmpty()) {
332         FT_Done_FreeType(freetypeData->library);
333         freetypeData->library = 0;
334     }
335 }
336
337
338 void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing)
339 {
340     *ysize = qRound(fontDef.pixelSize * 64);
341     *xsize = *ysize * fontDef.stretch / 100;
342     *outline_drawing = false;
343
344     /*
345      * Bitmap only faces must match exactly, so find the closest
346      * one (height dominant search)
347      */
348     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
349         int best = 0;
350         for (int i = 1; i < face->num_fixed_sizes; i++) {
351             if (qAbs(*ysize -  Y_SIZE(face,i)) <
352                 qAbs (*ysize - Y_SIZE(face, best)) ||
353                 (qAbs (*ysize - Y_SIZE(face, i)) ==
354                  qAbs (*ysize - Y_SIZE(face, best)) &&
355                  qAbs (*xsize - X_SIZE(face, i)) <
356                  qAbs (*xsize - X_SIZE(face, best)))) {
357                 best = i;
358             }
359         }
360         if (FT_Set_Char_Size (face, X_SIZE(face, best), Y_SIZE(face, best), 0, 0) == 0) {
361             *xsize = X_SIZE(face, best);
362             *ysize = Y_SIZE(face, best);
363         } else {
364             int err = 1;
365             if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) && ysize == 0 && face->num_fixed_sizes >= 1) {
366                 // work around FT 2.1.10 problem with BDF without PIXEL_SIZE property
367                 err = FT_Set_Pixel_Sizes(face, face->available_sizes[0].width, face->available_sizes[0].height);
368                 if (err && face->num_fixed_sizes == 1)
369                     err = 0; //even more of a workaround...
370             }
371
372             if (err)
373                 *xsize = *ysize = 0;
374         }
375     } else {
376         *outline_drawing = (*xsize > (64<<6) || *ysize > (64<<6));
377     }
378 }
379
380 QFontEngine::Properties QFreetypeFace::properties() const
381 {
382     QFontEngine::Properties p;
383     p.postscriptName = FT_Get_Postscript_Name(face);
384     PS_FontInfoRec font_info;
385     if (FT_Get_PS_Font_Info(face, &font_info) == 0)
386         p.copyright = font_info.notice;
387     if (FT_IS_SCALABLE(face)) {
388         p.ascent = face->ascender;
389         p.descent = -face->descender;
390         p.leading = face->height - face->ascender + face->descender;
391         p.emSquare = face->units_per_EM;
392         p.boundingBox = QRectF(face->bbox.xMin, -face->bbox.yMax,
393                                face->bbox.xMax - face->bbox.xMin,
394                                face->bbox.yMax - face->bbox.yMin);
395     } else {
396         p.ascent = QFixed::fromFixed(face->size->metrics.ascender);
397         p.descent = QFixed::fromFixed(-face->size->metrics.descender);
398         p.leading = QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender);
399         p.emSquare = face->size->metrics.y_ppem;
400 //        p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.);
401         p.boundingBox = QRectF(0, -p.ascent.toReal(),
402                                face->size->metrics.max_advance/64, (p.ascent + p.descent).toReal() );
403     }
404     p.italicAngle = 0;
405     p.capHeight = p.ascent;
406     p.lineWidth = face->underline_thickness;
407     return p;
408 }
409
410 bool QFreetypeFace::getSfntTable(uint tag, uchar *buffer, uint *length) const
411 {
412     bool result = false;
413 #if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103
414     if (FT_IS_SFNT(face)) {
415         FT_ULong len = *length;
416         result = FT_Load_Sfnt_Table(face, tag, 0, buffer, &len) == FT_Err_Ok;
417         *length = len;
418     }
419 #endif
420     return result;
421 }
422
423 /* Some fonts (such as MingLiu rely on hinting to scale different
424    components to their correct sizes. While this is really broken (it
425    should be done in the component glyph itself, not the hinter) we
426    will have to live with it.
427
428    This means we can not use FT_LOAD_NO_HINTING to get the glyph
429    outline. All we can do is to load the unscaled glyph and scale it
430    down manually when required.
431 */
432 static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixed y_scale)
433 {
434     x_scale = FT_MulDiv(x_scale, 1 << 10, face->units_per_EM);
435     y_scale = FT_MulDiv(y_scale, 1 << 10, face->units_per_EM);
436     FT_Vector *p = g->outline.points;
437     const FT_Vector *e = p + g->outline.n_points;
438     while (p < e) {
439         p->x = FT_MulFix(p->x, x_scale);
440         p->y = FT_MulFix(p->y, y_scale);
441         ++p;
442     }
443 }
444
445 void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale)
446 {
447     const qreal factor = 1/64.;
448     scaleOutline(face, g, x_scale, y_scale);
449
450     QPointF cp = point.toPointF();
451
452     // convert the outline to a painter path
453     int i = 0;
454     for (int j = 0; j < g->outline.n_contours; ++j) {
455         int last_point = g->outline.contours[j];
456         QPointF start = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
457         if(!(g->outline.tags[i] & 1)) {
458             start += cp + QPointF(g->outline.points[last_point].x*factor, -g->outline.points[last_point].y*factor);
459             start /= 2;
460         }
461 //         qDebug("contour: %d -- %d", i, g->outline.contours[j]);
462 //         qDebug("first point at %f %f", start.x(), start.y());
463         path->moveTo(start);
464
465         QPointF c[4];
466         c[0] = start;
467         int n = 1;
468         while (i < last_point) {
469             ++i;
470             c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
471 //             qDebug() << "    i=" << i << " flag=" << (int)g->outline.tags[i] << "point=" << c[n];
472             ++n;
473             switch (g->outline.tags[i] & 3) {
474             case 2:
475                 // cubic bezier element
476                 if (n < 4)
477                     continue;
478                 c[3] = (c[3] + c[2])/2;
479                 --i;
480                 break;
481             case 0:
482                 // quadratic bezier element
483                 if (n < 3)
484                     continue;
485                 c[3] = (c[1] + c[2])/2;
486                 c[2] = (2*c[1] + c[3])/3;
487                 c[1] = (2*c[1] + c[0])/3;
488                 --i;
489                 break;
490             case 1:
491             case 3:
492                 if (n == 2) {
493 //                     qDebug() << "lineTo" << c[1];
494                     path->lineTo(c[1]);
495                     c[0] = c[1];
496                     n = 1;
497                     continue;
498                 } else if (n == 3) {
499                     c[3] = c[2];
500                     c[2] = (2*c[1] + c[3])/3;
501                     c[1] = (2*c[1] + c[0])/3;
502                 }
503                 break;
504             }
505 //             qDebug() << "cubicTo" << c[1] << c[2] << c[3];
506             path->cubicTo(c[1], c[2], c[3]);
507             c[0] = c[3];
508             n = 1;
509         }
510         if (n == 1) {
511 //             qDebug() << "closeSubpath";
512             path->closeSubpath();
513         } else {
514             c[3] = start;
515             if (n == 2) {
516                 c[2] = (2*c[1] + c[3])/3;
517                 c[1] = (2*c[1] + c[0])/3;
518             }
519 //             qDebug() << "cubicTo" << c[1] << c[2] << c[3];
520             path->cubicTo(c[1], c[2], c[3]);
521         }
522         ++i;
523     }
524 }
525
526 extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path);
527
528 void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool)
529 {
530     if (slot->format != FT_GLYPH_FORMAT_BITMAP
531         || slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
532         return;
533
534     QPointF cp = point.toPointF();
535     qt_addBitmapToPath(cp.x() + TRUNC(slot->metrics.horiBearingX), cp.y() - TRUNC(slot->metrics.horiBearingY),
536                        slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path);
537 }
538
539 QFontEngineFT::Glyph::~Glyph()
540 {
541     delete [] data;
542 }
543
544 static const uint subpixel_filter[3][3] = {
545     { 180, 60, 16 },
546     { 38, 180, 38 },
547     { 16, 60, 180 }
548 };
549
550 static inline uint filterPixel(uint red, uint green, uint blue, bool legacyFilter)
551 {
552     uint res;
553     if (legacyFilter) {
554         uint high = (red*subpixel_filter[0][0] + green*subpixel_filter[0][1] + blue*subpixel_filter[0][2]) >> 8;
555         uint mid = (red*subpixel_filter[1][0] + green*subpixel_filter[1][1] + blue*subpixel_filter[1][2]) >> 8;
556         uint low = (red*subpixel_filter[2][0] + green*subpixel_filter[2][1] + blue*subpixel_filter[2][2]) >> 8;
557         res = (mid << 24) + (high << 16) + (mid << 8) + low;
558     } else {
559         uint alpha = green;
560         res = (alpha << 24) + (red << 16) + (green << 8) + blue;
561     }
562     return res;
563 }
564
565 static void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
566 {
567     int h = height;
568     const int offs = bgr ? -1 : 1;
569     const int w = width * 3;
570     while (h--) {
571         uint *dd = dst;
572         for (int x = 0; x < w; x += 3) {
573             uint red = src[x+1-offs];
574             uint green = src[x+1];
575             uint blue = src[x+1+offs];
576             *dd = filterPixel(red, green, blue, legacyFilter);
577             ++dd;
578         }
579         dst += width;
580         src += src_pitch;
581     }
582 }
583
584 static void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
585 {
586     int h = height;
587     const int offs = bgr ? -src_pitch : src_pitch;
588     while (h--) {
589         for (int x = 0; x < width; x++) {
590             uint red = src[x+src_pitch-offs];
591             uint green = src[x+src_pitch];
592             uint blue = src[x+src_pitch+offs];
593             dst[x] = filterPixel(red, green, blue, legacyFilter);
594         }
595         dst += width;
596         src += 3*src_pitch;
597     }
598 }
599
600 static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, int pitch)
601 {
602     // convolute the bitmap with a triangle filter to get rid of color fringes
603     // If we take account for a gamma value of 2, we end up with
604     // weights of 1, 4, 9, 4, 1. We use an approximation of 1, 3, 8, 3, 1 here,
605     // as this nicely sums up to 16 :)
606     int h = height;
607     while (h--) {
608         dst[0] = dst[1] = 0;
609         //
610         for (int x = 2; x < width - 2; ++x) {
611             uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2];
612             dst[x] = (uchar) (sum >> 4);
613         }
614         dst[width - 2] = dst[width - 1] = 0;
615         src += pitch;
616         dst += pitch;
617     }
618 }
619
620 QFontEngineFT::QFontEngineFT(const QFontDef &fd)
621 {
622     fontDef = fd;
623     matrix.xx = 0x10000;
624     matrix.yy = 0x10000;
625     matrix.xy = 0;
626     matrix.yx = 0;
627     cache_cost = 100;
628     kerning_pairs_loaded = false;
629     transform = false;
630     embolden = false;
631     antialias = true;
632     freetype = 0;
633     default_load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
634     default_hint_style = HintNone;
635     subpixelType = Subpixel_None;
636     lcdFilterType = 0;
637 #if defined(FT_LCD_FILTER_H)
638     lcdFilterType = (int)((quintptr) FT_LCD_FILTER_DEFAULT);
639 #endif
640     defaultFormat = Format_None;
641     canUploadGlyphsToServer = false;
642     embeddedbitmap = false;
643 }
644
645 QFontEngineFT::~QFontEngineFT()
646 {
647     if (freetype)
648         freetype->release(face_id);
649     hbFace = 0; // we share the face in QFreeTypeFace, don't let ~QFontEngine delete it
650 }
651
652 void QFontEngineFT::freeGlyphSets()
653 {
654     freeServerGlyphSet(defaultGlyphSet.id);
655     for (int i = 0; i < transformedGlyphSets.count(); ++i)
656         freeServerGlyphSet(transformedGlyphSets.at(i).id);
657 }
658
659 bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
660                          const QByteArray &fontData)
661 {
662     return init(faceId, antialias, format, QFreetypeFace::getFace(faceId, fontData));
663 }
664
665 bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
666                          QFreetypeFace *freetypeFace)
667 {
668     freetype = freetypeFace;
669     if (!freetype) {
670         xsize = 0;
671         ysize = 0;
672         return false;
673     }
674     defaultFormat = format;
675     this->antialias = antialias;
676
677     if (!antialias)
678         glyphFormat = QFontEngineGlyphCache::Raster_Mono;
679     else if (format == Format_A8)
680         glyphFormat = QFontEngineGlyphCache::Raster_A8;
681     else if (format == Format_A32)
682         glyphFormat = QFontEngineGlyphCache::Raster_RGBMask;
683
684     face_id = faceId;
685
686     symbol = freetype->symbol_map != 0;
687     PS_FontInfoRec psrec;
688     // don't assume that type1 fonts are symbol fonts by default
689     if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) {
690         symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive));
691     }
692     // #####
693     freetype->hbFace->isSymbolFont = symbol;
694
695     lbearing = rbearing = SHRT_MIN;
696     freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
697
698     FT_Face face = lockFace();
699
700     if (FT_IS_SCALABLE(face)) {
701         bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC);
702         if (fake_oblique)
703             matrix.xy = 0x10000*3/10;
704         FT_Set_Transform(face, &matrix, 0);
705         freetype->matrix = matrix;
706         if (fake_oblique)
707             transform = true;
708         // fake bold
709         if ((fontDef.weight == QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face))
710             embolden = true;
711         // underline metrics
712         line_thickness =  QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale));
713         underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale));
714     } else {
715         // copied from QFontEngineQPF
716         // ad hoc algorithm
717         int score = fontDef.weight * fontDef.pixelSize;
718         line_thickness = score / 700;
719         // looks better with thicker line for small pointsizes
720         if (line_thickness < 2 && score >= 1050)
721             line_thickness = 2;
722         underline_position =  ((line_thickness * 2) + 3) / 6;
723     }
724     if (line_thickness < 1)
725         line_thickness = 1;
726
727     hbFont.x_ppem  = face->size->metrics.x_ppem;
728     hbFont.y_ppem  = face->size->metrics.y_ppem;
729     hbFont.x_scale = face->size->metrics.x_scale;
730     hbFont.y_scale = face->size->metrics.y_scale;
731
732     hbFace = freetype->hbFace;
733
734     metrics = face->size->metrics;
735
736 #if defined(Q_WS_QWS) || defined(Q_WS_QPA)
737     /*
738        TrueType fonts with embedded bitmaps may have a bitmap font specific
739        ascent/descent in the EBLC table. There is no direct public API
740        to extract those values. The only way we've found is to trick freetype
741        into thinking that it's not a scalable font in FT_SelectSize so that
742        the metrics are retrieved from the bitmap strikes.
743     */
744     if (FT_IS_SCALABLE(face)) {
745         for (int i = 0; i < face->num_fixed_sizes; ++i) {
746             if (xsize == X_SIZE(face, i) && ysize == Y_SIZE(face, i)) {
747                 face->face_flags &= ~FT_FACE_FLAG_SCALABLE;
748
749                 FT_Select_Size(face, i);
750                 metrics.ascender = face->size->metrics.ascender;
751                 metrics.descender = face->size->metrics.descender;
752                 FT_Set_Char_Size(face, xsize, ysize, 0, 0);
753
754                 face->face_flags |= FT_FACE_FLAG_SCALABLE;
755                 break;
756             }
757         }
758     }
759 #endif
760
761     unlockFace();
762
763     fsType = freetype->fsType();
764     defaultGlyphSet.id = allocateServerGlyphSet();
765     return true;
766 }
767
768 void QFontEngineFT::setDefaultHintStyle(HintStyle style)
769 {
770     default_hint_style = style;
771 }
772
773 int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
774                              bool &hsubpixel, int &vfactor) const
775 {
776     int load_flags = FT_LOAD_DEFAULT | default_load_flags;
777     int load_target = default_hint_style == HintLight
778                       ? FT_LOAD_TARGET_LIGHT
779                       : FT_LOAD_TARGET_NORMAL;
780
781     if (format == Format_Mono) {
782         load_target = FT_LOAD_TARGET_MONO;
783     } else if (format == Format_A32) {
784         if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) {
785             if (default_hint_style == HintFull)
786                 load_target = FT_LOAD_TARGET_LCD;
787             hsubpixel = true;
788         } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
789             if (default_hint_style == HintFull)
790                 load_target = FT_LOAD_TARGET_LCD_V;
791             vfactor = 3;
792         }
793     }
794
795     if (set && set->outline_drawing)
796         load_flags = FT_LOAD_NO_BITMAP;
797
798     if (default_hint_style == HintNone || (flags & HB_ShaperFlag_UseDesignMetrics))
799         load_flags |= FT_LOAD_NO_HINTING;
800     else
801         load_flags |= load_target;
802
803     return load_flags;
804 }
805
806 QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
807                                                QFixed subPixelPosition,
808                                                GlyphFormat format,
809                                                bool fetchMetricsOnly) const
810 {
811 //     Q_ASSERT(freetype->lock == 1);
812
813     bool uploadToServer = false;
814     if (format == Format_None) {
815         if (defaultFormat != Format_None) {
816             format = defaultFormat;
817             if (canUploadGlyphsToServer)
818                 uploadToServer = true;
819         } else {
820             format = Format_Mono;
821         }
822     }
823
824     Glyph *g = set->getGlyph(glyph, subPixelPosition);
825     if (g && g->format == format) {
826         if (uploadToServer && !g->uploadedToServer) {
827             set->setGlyph(glyph, subPixelPosition, 0);
828             delete g;
829             g = 0;
830         } else {
831             return g;
832         }
833     }
834
835     QFontEngineFT::GlyphInfo info;
836
837     Q_ASSERT(format != Format_None);
838     bool hsubpixel = false;
839     int vfactor = 1;
840     int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
841
842 #ifndef Q_WS_QWS
843     if (format != Format_Mono && !embeddedbitmap)
844         load_flags |= FT_LOAD_NO_BITMAP;
845 #endif
846
847     FT_Matrix matrix = freetype->matrix;
848     bool transform = matrix.xx != 0x10000
849                      || matrix.yy != 0x10000
850                      || matrix.xy != 0
851                      || matrix.yx != 0;
852
853     if (transform)
854         load_flags |= FT_LOAD_NO_BITMAP;
855
856     FT_Face face = freetype->face;
857
858     FT_Vector v;
859     v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.toReal() * 64);
860     v.y = 0;
861     FT_Set_Transform(face, &freetype->matrix, &v);
862
863     FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
864     if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
865         load_flags &= ~FT_LOAD_NO_BITMAP;
866         err = FT_Load_Glyph(face, glyph, load_flags);
867     }
868     if (err == FT_Err_Too_Few_Arguments) {
869         // this is an error in the bytecode interpreter, just try to run without it
870         load_flags |= FT_LOAD_FORCE_AUTOHINT;
871         err = FT_Load_Glyph(face, glyph, load_flags);
872     }
873     if (err != FT_Err_Ok)
874         qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
875
876     if (set->outline_drawing && fetchMetricsOnly)
877         return 0;
878
879     FT_GlyphSlot slot = face->glyph;
880     if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot);
881     FT_Library library = qt_getFreetype();
882
883     info.xOff = TRUNC(ROUND(slot->advance.x));
884     info.yOff = 0;
885
886     uchar *glyph_buffer = 0;
887     int glyph_buffer_size = 0;
888 #if defined(QT_USE_FREETYPE_LCDFILTER)
889     bool useFreetypeRenderGlyph = false;
890     if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) {
891         err = FT_Library_SetLcdFilter(library, (FT_LcdFilter)lcdFilterType);
892         if (err == FT_Err_Ok)
893             useFreetypeRenderGlyph = true;
894     }
895
896     if (useFreetypeRenderGlyph) {
897         err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V);
898
899         if (err != FT_Err_Ok)
900             qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
901
902         FT_Library_SetLcdFilter(library, FT_LCD_FILTER_NONE);
903
904         info.height = slot->bitmap.rows / vfactor;
905         info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
906         info.x = -slot->bitmap_left;
907         info.y = slot->bitmap_top;
908
909         glyph_buffer_size = info.width * info.height * 4;
910         glyph_buffer = new uchar[glyph_buffer_size];
911
912         if (hsubpixel)
913             convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, false);
914         else if (vfactor != 1)
915             convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, false);
916     } else
917 #endif
918     {
919     int left  = slot->metrics.horiBearingX;
920     int right = slot->metrics.horiBearingX + slot->metrics.width;
921     int top    = slot->metrics.horiBearingY;
922     int bottom = slot->metrics.horiBearingY - slot->metrics.height;
923     if(transform && slot->format != FT_GLYPH_FORMAT_BITMAP) {
924         int l, r, t, b;
925         FT_Vector vector;
926         vector.x = left;
927         vector.y = top;
928         FT_Vector_Transform(&vector, &matrix);
929         l = r = vector.x;
930         t = b = vector.y;
931         vector.x = right;
932         vector.y = top;
933         FT_Vector_Transform(&vector, &matrix);
934         if (l > vector.x) l = vector.x;
935         if (r < vector.x) r = vector.x;
936         if (t < vector.y) t = vector.y;
937         if (b > vector.y) b = vector.y;
938         vector.x = right;
939         vector.y = bottom;
940         FT_Vector_Transform(&vector, &matrix);
941         if (l > vector.x) l = vector.x;
942         if (r < vector.x) r = vector.x;
943         if (t < vector.y) t = vector.y;
944         if (b > vector.y) b = vector.y;
945         vector.x = left;
946         vector.y = bottom;
947         FT_Vector_Transform(&vector, &matrix);
948         if (l > vector.x) l = vector.x;
949         if (r < vector.x) r = vector.x;
950         if (t < vector.y) t = vector.y;
951         if (b > vector.y) b = vector.y;
952         left = l;
953         right = r;
954         top = t;
955         bottom = b;
956     }
957     left = FLOOR(left);
958     right = CEIL(right);
959     bottom = FLOOR(bottom);
960     top = CEIL(top);
961
962     int hpixels = TRUNC(right - left);
963     // subpixel position requires one more pixel
964     if (subPixelPosition > 0 && format != Format_Mono)
965         hpixels++;
966
967     if (hsubpixel)
968         hpixels = hpixels*3 + 8;
969     info.width = hpixels;
970     info.height = TRUNC(top - bottom);
971     info.x = -TRUNC(left);
972     info.y = TRUNC(top);
973     if (hsubpixel) {
974         info.width /= 3;
975         info.x += 1;
976     }
977
978     bool large_glyph = (((short)(slot->linearHoriAdvance>>10) != slot->linearHoriAdvance>>10)
979                         || ((uchar)(info.width) != info.width)
980                         || ((uchar)(info.height) != info.height)
981                         || ((signed char)(info.x) != info.x)
982                         || ((signed char)(info.y) != info.y)
983                         || ((signed char)(info.xOff) != info.xOff));
984
985     if (large_glyph) {
986         delete [] glyph_buffer;
987         return 0;
988     }
989
990     int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
991                  (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
992     glyph_buffer_size = pitch * info.height;
993     glyph_buffer = new uchar[glyph_buffer_size];
994
995     if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
996         FT_Bitmap bitmap;
997         bitmap.rows = info.height*vfactor;
998         bitmap.width = hpixels;
999         bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3);
1000         if (!hsubpixel && vfactor == 1)
1001             bitmap.buffer = glyph_buffer;
1002         else
1003             bitmap.buffer = new uchar[bitmap.rows*bitmap.pitch];
1004         memset(bitmap.buffer, 0, bitmap.rows*bitmap.pitch);
1005         bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY;
1006         FT_Matrix matrix;
1007         matrix.xx = (hsubpixel ? 3 : 1) << 16;
1008         matrix.yy = vfactor << 16;
1009         matrix.yx = matrix.xy = 0;
1010
1011         FT_Outline_Transform(&slot->outline, &matrix);
1012         FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor);
1013         FT_Outline_Get_Bitmap(library, &slot->outline, &bitmap);
1014         if (hsubpixel) {
1015             Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
1016             Q_ASSERT(antialias);
1017             uchar *convoluted = new uchar[bitmap.rows*bitmap.pitch];
1018             bool useLegacyLcdFilter = false;
1019 #if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H)
1020             useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY);
1021 #endif
1022             uchar *buffer = bitmap.buffer;
1023             if (!useLegacyLcdFilter) {
1024                 convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch);
1025                 buffer = convoluted;
1026             }
1027             convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, useLegacyLcdFilter);
1028             delete [] convoluted;
1029         } else if (vfactor != 1) {
1030             convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, true);
1031         }
1032
1033         if (bitmap.buffer != glyph_buffer)
1034             delete [] bitmap.buffer;
1035     } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
1036         Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
1037         uchar *src = slot->bitmap.buffer;
1038         uchar *dst = glyph_buffer;
1039         int h = slot->bitmap.rows;
1040         if (format == Format_Mono) {
1041             int bytes = ((info.width + 7) & ~7) >> 3;
1042             while (h--) {
1043                 memcpy (dst, src, bytes);
1044                 dst += pitch;
1045                 src += slot->bitmap.pitch;
1046             }
1047         } else {
1048             if (hsubpixel) {
1049                 while (h--) {
1050                     uint *dd = (uint *)dst;
1051                     *dd++ = 0;
1052                     for (int x = 0; x < slot->bitmap.width; x++) {
1053                         uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
1054                         *dd++ = a;
1055                     }
1056                     *dd++ = 0;
1057                     dst += pitch;
1058                     src += slot->bitmap.pitch;
1059                 }
1060             } else if (vfactor != 1) {
1061                 while (h--) {
1062                     uint *dd = (uint *)dst;
1063                     for (int x = 0; x < slot->bitmap.width; x++) {
1064                         uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
1065                         *dd++ = a;
1066                     }
1067                     dst += pitch;
1068                     src += slot->bitmap.pitch;
1069                 }
1070             } else {
1071                 while (h--) {
1072                     for (int x = 0; x < slot->bitmap.width; x++) {
1073                         unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00);
1074                         dst[x] = a;
1075                     }
1076                     dst += pitch;
1077                     src += slot->bitmap.pitch;
1078                 }
1079             }
1080         }
1081     } else {
1082         qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format);
1083         delete [] glyph_buffer;
1084         return 0;
1085     }
1086     }
1087
1088
1089     if (!g) {
1090         g = new Glyph;
1091         g->uploadedToServer = false;
1092         g->data = 0;
1093     }
1094
1095     g->linearAdvance = slot->linearHoriAdvance >> 10;
1096     g->width = info.width;
1097     g->height = info.height;
1098     g->x = -info.x;
1099     g->y = info.y;
1100     g->advance = info.xOff;
1101     g->format = format;
1102     delete [] g->data;
1103     g->data = glyph_buffer;
1104
1105     if (uploadToServer) {
1106         uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
1107     }
1108
1109     set->setGlyph(glyph, subPixelPosition, g);
1110
1111     return g;
1112 }
1113
1114 bool QFontEngineFT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const
1115 {
1116     Q_UNUSED(set);
1117     Q_UNUSED(glyphid);
1118     Q_UNUSED(g);
1119     Q_UNUSED(info);
1120     Q_UNUSED(glyphDataSize);
1121     return false;
1122 }
1123
1124 QFontEngine::FaceId QFontEngineFT::faceId() const
1125 {
1126     return face_id;
1127 }
1128
1129 QFontEngine::Properties QFontEngineFT::properties() const
1130 {
1131     Properties p = freetype->properties();
1132     if (p.postscriptName.isEmpty()) {
1133         p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8());
1134     }
1135
1136     return freetype->properties();
1137 }
1138
1139 QFixed QFontEngineFT::emSquareSize() const
1140 {
1141     if (FT_IS_SCALABLE(freetype->face))
1142         return freetype->face->units_per_EM;
1143     else
1144         return freetype->face->size->metrics.y_ppem;
1145 }
1146
1147 bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const
1148 {
1149     return freetype->getSfntTable(tag, buffer, length);
1150 }
1151
1152 int QFontEngineFT::synthesized() const
1153 {
1154     int s = 0;
1155     if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC))
1156         s = SynthesizedItalic;
1157     if ((fontDef.weight == QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD))
1158         s |= SynthesizedBold;
1159     if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face))
1160         s |= SynthesizedStretch;
1161     return s;
1162 }
1163
1164 QFixed QFontEngineFT::ascent() const
1165 {
1166     return QFixed::fromFixed(metrics.ascender);
1167 }
1168
1169 QFixed QFontEngineFT::descent() const
1170 {
1171     // subtract a pixel to work around QFontMetrics's built-in + 1
1172     return QFixed::fromFixed(-metrics.descender - 64);
1173 }
1174
1175 QFixed QFontEngineFT::leading() const
1176 {
1177     return QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);
1178 }
1179
1180 QFixed QFontEngineFT::xHeight() const
1181 {
1182     TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
1183     if (os2 && os2->sxHeight) {
1184         lockFace();
1185         QFixed answer = QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM;
1186         unlockFace();
1187         return answer;
1188     }
1189     return QFontEngine::xHeight();
1190 }
1191
1192 QFixed QFontEngineFT::averageCharWidth() const
1193 {
1194     TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
1195     if (os2 && os2->xAvgCharWidth) {
1196         lockFace();
1197         QFixed answer = QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM;
1198         unlockFace();
1199         return answer;
1200     }
1201     return QFontEngine::averageCharWidth();
1202 }
1203
1204 qreal QFontEngineFT::maxCharWidth() const
1205 {
1206     return metrics.max_advance >> 6;
1207 }
1208
1209 static const ushort char_table[] = {
1210         40,
1211         67,
1212         70,
1213         75,
1214         86,
1215         88,
1216         89,
1217         91,
1218         102,
1219         114,
1220         124,
1221         127,
1222         205,
1223         645,
1224         884,
1225         922,
1226         1070,
1227         12386
1228 };
1229
1230 static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
1231
1232
1233 qreal QFontEngineFT::minLeftBearing() const
1234 {
1235     if (lbearing == SHRT_MIN)
1236         (void) minRightBearing(); // calculates both
1237     return lbearing.toReal();
1238 }
1239
1240 qreal QFontEngineFT::minRightBearing() const
1241 {
1242     if (rbearing == SHRT_MIN) {
1243         lbearing = rbearing = 0;
1244         const QChar *ch = (const QChar *)(const void*)char_table;
1245         QGlyphLayoutArray<char_table_entries> glyphs;
1246         int ng = char_table_entries;
1247         stringToCMap(ch, char_table_entries, &glyphs, &ng, QTextEngine::GlyphIndicesOnly);
1248         while (--ng) {
1249             if (glyphs.glyphs[ng]) {
1250                 glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs.glyphs[ng]);
1251                 lbearing = qMin(lbearing, gi.x);
1252                 rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
1253             }
1254         }
1255     }
1256     return rbearing.toReal();
1257 }
1258
1259 QFixed QFontEngineFT::lineThickness() const
1260 {
1261     return line_thickness;
1262 }
1263
1264 QFixed QFontEngineFT::underlinePosition() const
1265 {
1266     return underline_position;
1267 }
1268
1269 void QFontEngineFT::doKerning(QGlyphLayout *g, QTextEngine::ShaperFlags flags) const
1270 {
1271     if (!kerning_pairs_loaded) {
1272         kerning_pairs_loaded = true;
1273         lockFace();
1274         if (freetype->face->size->metrics.x_ppem != 0) {
1275             QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem);
1276             unlockFace();
1277             const_cast<QFontEngineFT *>(this)->loadKerningPairs(scalingFactor);
1278         } else {
1279             unlockFace();
1280         }
1281     }
1282     QFontEngine::doKerning(g, flags);
1283 }
1284
1285 QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransform &matrix)
1286 {
1287     if (matrix.type() > QTransform::TxShear)
1288         return 0;
1289
1290     // FT_Set_Transform only supports scalable fonts
1291     if (!FT_IS_SCALABLE(freetype->face))
1292         return 0;
1293
1294     FT_Matrix m;
1295     m.xx = FT_Fixed(matrix.m11() * 65536);
1296     m.xy = FT_Fixed(-matrix.m21() * 65536);
1297     m.yx = FT_Fixed(-matrix.m12() * 65536);
1298     m.yy = FT_Fixed(matrix.m22() * 65536);
1299
1300     QGlyphSet *gs = 0;
1301
1302     for (int i = 0; i < transformedGlyphSets.count(); ++i) {
1303         const QGlyphSet &g = transformedGlyphSets.at(i);
1304         if (g.transformationMatrix.xx == m.xx
1305             && g.transformationMatrix.xy == m.xy
1306             && g.transformationMatrix.yx == m.yx
1307             && g.transformationMatrix.yy == m.yy) {
1308
1309             // found a match, move it to the front
1310             transformedGlyphSets.move(i, 0);
1311             gs = &transformedGlyphSets[0];
1312             break;
1313         }
1314     }
1315
1316     if (!gs) {
1317         // don't try to load huge fonts
1318         bool draw_as_outline = fontDef.pixelSize * qSqrt(qAbs(matrix.det())) >= 64;
1319         if (draw_as_outline)
1320             return 0;
1321
1322         // don't cache more than 10 transformations
1323         if (transformedGlyphSets.count() >= 10) {
1324             transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
1325             freeServerGlyphSet(transformedGlyphSets.at(0).id);
1326         } else {
1327             transformedGlyphSets.prepend(QGlyphSet());
1328         }
1329         gs = &transformedGlyphSets[0];
1330
1331         gs->clear();
1332
1333         gs->id = allocateServerGlyphSet();
1334
1335         gs->transformationMatrix = m;
1336         gs->outline_drawing = draw_as_outline;
1337     }
1338
1339     return gs;
1340 }
1341
1342 QFixed QFontEngineFT::subPixelPositionForX(QFixed x)
1343 {
1344     int m_subPixelPositionCount = 4;
1345     if (!supportsSubPixelPositions())
1346         return 0;
1347
1348     QFixed subPixelPosition;
1349     if (x != 0) {
1350         subPixelPosition = x - x.floor();
1351         QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
1352         subPixelPosition = fraction / QFixed(m_subPixelPositionCount);
1353     }
1354     return subPixelPosition;
1355 }
1356
1357 bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
1358                                const QFixedPoint *positions,
1359                                GlyphFormat format)
1360 {
1361     FT_Face face = 0;
1362
1363     for (int i = 0; i < num_glyphs; ++i) {
1364         QFixed spp = subPixelPositionForX(positions[i].x);
1365         Glyph *glyph = gs->getGlyph(glyphs[i], spp);
1366         if (glyph == 0 || glyph->format != format) {
1367             if (!face) {
1368                 face = lockFace();
1369                 FT_Matrix m = matrix;
1370                 FT_Matrix_Multiply(&gs->transformationMatrix, &m);
1371                 FT_Set_Transform(face, &m, 0);
1372                 freetype->matrix = m;
1373             }
1374             if (!loadGlyph(gs, glyphs[i], spp, format)) {
1375                 unlockFace();
1376                 return false;
1377             }
1378         }
1379     }
1380
1381     if (face)
1382         unlockFace();
1383
1384     return true;
1385 }
1386
1387 void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
1388 {
1389     FT_Face face = lockFace(Unscaled);
1390     FT_Set_Transform(face, 0, 0);
1391     FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
1392
1393     int left  = face->glyph->metrics.horiBearingX;
1394     int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width;
1395     int top    = face->glyph->metrics.horiBearingY;
1396     int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
1397
1398     QFixedPoint p;
1399     p.x = 0;
1400     p.y = 0;
1401
1402     metrics->width = QFixed::fromFixed(right-left);
1403     metrics->height = QFixed::fromFixed(top-bottom);
1404     metrics->x = QFixed::fromFixed(left);
1405     metrics->y = QFixed::fromFixed(-top);
1406     metrics->xoff = QFixed::fromFixed(face->glyph->advance.x);
1407
1408     if (!FT_IS_SCALABLE(freetype->face))
1409         QFreetypeFace::addBitmapToPath(face->glyph, p, path);
1410     else
1411         QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6);
1412
1413     FT_Set_Transform(face, &freetype->matrix, 0);
1414     unlockFace();
1415 }
1416
1417 static inline unsigned int getChar(const QChar *str, int &i, const int len)
1418 {
1419     unsigned int uc = str[i].unicode();
1420     if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {
1421         uint low = str[i+1].unicode();
1422        if (low >= 0xdc00 && low < 0xe000) {
1423             uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
1424             ++i;
1425         }
1426     }
1427     return uc;
1428 }
1429
1430 bool QFontEngineFT::canRender(const QChar *string, int len)
1431 {
1432     FT_Face face = freetype->face;
1433 #if 0
1434     if (_cmap != -1) {
1435         lockFace();
1436         for ( int i = 0; i < len; i++ ) {
1437             unsigned int uc = getChar(string, i, len);
1438             if (!FcCharSetHasChar (_font->charset, uc) && getAdobeCharIndex(face, _cmap, uc) == 0) {
1439                 allExist = false;
1440                 break;
1441             }
1442         }
1443         unlockFace();
1444     } else
1445 #endif
1446     {
1447         for ( int i = 0; i < len; i++ ) {
1448             unsigned int uc = getChar(string, i, len);
1449             if (!FT_Get_Char_Index(face, uc))
1450                     return false;
1451         }
1452     }
1453     return true;
1454 }
1455
1456 void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
1457 {
1458     if (!glyphs.numGlyphs)
1459         return;
1460
1461     if (FT_IS_SCALABLE(freetype->face)) {
1462         QFontEngine::addOutlineToPath(x, y, glyphs, path, flags);
1463     } else {
1464         QVarLengthArray<QFixedPoint> positions;
1465         QVarLengthArray<glyph_t> positioned_glyphs;
1466         QTransform matrix;
1467         matrix.translate(x, y);
1468         getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
1469
1470         FT_Face face = lockFace(Unscaled);
1471         for (int gl = 0; gl < glyphs.numGlyphs; gl++) {
1472             FT_UInt glyph = positioned_glyphs[gl];
1473             FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO);
1474             freetype->addBitmapToPath(face->glyph, positions[gl], path);
1475         }
1476         unlockFace();
1477     }
1478 }
1479
1480 void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
1481                                     QPainterPath *path, QTextItem::RenderFlags)
1482 {
1483     FT_Face face = lockFace(Unscaled);
1484
1485     for (int gl = 0; gl < numGlyphs; gl++) {
1486         FT_UInt glyph = glyphs[gl];
1487
1488         FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
1489
1490         FT_GlyphSlot g = face->glyph;
1491         if (g->format != FT_GLYPH_FORMAT_OUTLINE)
1492             continue;
1493         QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize);
1494     }
1495     unlockFace();
1496 }
1497
1498 bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
1499                                  QTextEngine::ShaperFlags flags) const
1500 {
1501     if (*nglyphs < len) {
1502         *nglyphs = len;
1503         return false;
1504     }
1505
1506 #if !defined(QT_NO_FONTCONFIG)
1507     extern QMutex *qt_fontdatabase_mutex();
1508     QMutex *mtx = 0;
1509 #endif
1510
1511     bool mirrored = flags & QTextEngine::RightToLeft;
1512     int glyph_pos = 0;
1513     if (freetype->symbol_map) {
1514         FT_Face face = freetype->face;
1515         for ( int i = 0; i < len; ++i ) {
1516             unsigned int uc = getChar(str, i, len);
1517             glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
1518             if ( !glyphs->glyphs[glyph_pos] ) {
1519                 glyph_t glyph;
1520 #if !defined(QT_NO_FONTCONFIG)
1521                 if (!mtx) {
1522                     mtx = qt_fontdatabase_mutex();
1523                     mtx->lock();
1524                 }
1525
1526                 if (freetype->charset != 0 && FcCharSetHasChar(freetype->charset, uc)) {
1527 #else
1528                 if (false) {
1529 #endif
1530                 redo0:
1531                     glyph = FT_Get_Char_Index(face, uc);
1532                     if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1533                         uc = 0x20;
1534                         goto redo0;
1535                     }
1536                 } else {
1537                     FT_Set_Charmap(face, freetype->symbol_map);
1538                     glyph = FT_Get_Char_Index(face, uc);
1539                     FT_Set_Charmap(face, freetype->unicode_map);
1540                 }
1541                 glyphs->glyphs[glyph_pos] = glyph;
1542                 if (uc < QFreetypeFace::cmapCacheSize)
1543                     freetype->cmapCache[uc] = glyph;
1544             }
1545             ++glyph_pos;
1546         }
1547     } else {
1548         FT_Face face = freetype->face;
1549         for (int i = 0; i < len; ++i) {
1550             unsigned int uc = getChar(str, i, len);
1551             if (mirrored)
1552                 uc = QChar::mirroredChar(uc);
1553             glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
1554             if (!glyphs->glyphs[glyph_pos]) {
1555 #if !defined(QT_NO_FONTCONFIG)
1556                 if (!mtx) {
1557                     mtx = qt_fontdatabase_mutex();
1558                     mtx->lock();
1559                 }
1560
1561                 if (freetype->charset == 0 || FcCharSetHasChar(freetype->charset, uc))
1562 #endif
1563                 {
1564                 redo:
1565                     glyph_t glyph = FT_Get_Char_Index(face, uc);
1566                     if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1567                         uc = 0x20;
1568                         goto redo;
1569                     }
1570                     glyphs->glyphs[glyph_pos] = glyph;
1571                     if (uc < QFreetypeFace::cmapCacheSize)
1572                         freetype->cmapCache[uc] = glyph;
1573                 }
1574             }
1575             ++glyph_pos;
1576         }
1577     }
1578
1579     *nglyphs = glyph_pos;
1580     glyphs->numGlyphs = glyph_pos;
1581
1582 #if !defined(QT_NO_FONTCONFIG)
1583     if (mtx)
1584         mtx->unlock();
1585 #endif
1586
1587     if (flags & QTextEngine::GlyphIndicesOnly)
1588         return true;
1589
1590     recalcAdvances(glyphs, flags);
1591
1592     return true;
1593 }
1594
1595 void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
1596 {
1597     FT_Face face = 0;
1598     bool design = (default_hint_style == HintNone ||
1599                    default_hint_style == HintLight ||
1600                    (flags & HB_ShaperFlag_UseDesignMetrics));
1601     for (int i = 0; i < glyphs->numGlyphs; i++) {
1602         Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
1603         if (g) {
1604             glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
1605         } else {
1606             if (!face)
1607                 face = lockFace();
1608             g = loadGlyph(glyphs->glyphs[i], 0, Format_None, true);
1609             glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
1610                                            : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
1611         }
1612         if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
1613             glyphs->advances_x[i] = glyphs->advances_x[i].round();
1614         glyphs->advances_y[i] = 0;
1615     }
1616     if (face)
1617         unlockFace();
1618 }
1619
1620 glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
1621 {
1622
1623     FT_Face face = 0;
1624
1625     glyph_metrics_t overall;
1626     // initialize with line height, we get the same behaviour on all platforms
1627     overall.y = -ascent();
1628     overall.height = ascent() + descent() + 1;
1629
1630     QFixed ymax = 0;
1631     QFixed xmax = 0;
1632     for (int i = 0; i < glyphs.numGlyphs; i++) {
1633         Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]);
1634         if (!g) {
1635             if (!face)
1636                 face = lockFace();
1637             g = loadGlyph(glyphs.glyphs[i], 0, Format_None, true);
1638         }
1639         if (g) {
1640             QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
1641             QFixed y = overall.yoff + glyphs.offsets[i].y - g->y;
1642             overall.x = qMin(overall.x, x);
1643             overall.y = qMin(overall.y, y);
1644             xmax = qMax(xmax, x + g->width);
1645             ymax = qMax(ymax, y + g->height);
1646             overall.xoff += qRound(g->advance);
1647         } else {
1648             int left  = FLOOR(face->glyph->metrics.horiBearingX);
1649             int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1650             int top    = CEIL(face->glyph->metrics.horiBearingY);
1651             int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1652
1653             QFixed x = overall.xoff + glyphs.offsets[i].x - (-TRUNC(left));
1654             QFixed y = overall.yoff + glyphs.offsets[i].y - TRUNC(top);
1655             overall.x = qMin(overall.x, x);
1656             overall.y = qMin(overall.y, y);
1657             xmax = qMax(xmax, x + TRUNC(right - left));
1658             ymax = qMax(ymax, y + TRUNC(top - bottom));
1659             overall.xoff += qRound(TRUNC(ROUND(face->glyph->advance.x)));
1660         }
1661     }
1662     overall.height = qMax(overall.height, ymax - overall.y);
1663     overall.width = xmax - overall.x;
1664
1665     if (face)
1666         unlockFace();
1667
1668     return overall;
1669 }
1670
1671 glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
1672 {
1673     FT_Face face = 0;
1674     glyph_metrics_t overall;
1675     Glyph *g = defaultGlyphSet.getGlyph(glyph);
1676     if (!g) {
1677         face = lockFace();
1678         g = loadGlyph(glyph, 0, Format_None, true);
1679     }
1680     if (g) {
1681         overall.x = g->x;
1682         overall.y = -g->y;
1683         overall.width = g->width;
1684         overall.height = g->height;
1685         overall.xoff = g->advance;
1686         if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
1687             overall.xoff = overall.xoff.round();
1688     } else {
1689         int left  = FLOOR(face->glyph->metrics.horiBearingX);
1690         int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1691         int top    = CEIL(face->glyph->metrics.horiBearingY);
1692         int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1693
1694         overall.width = TRUNC(right-left);
1695         overall.height = TRUNC(top-bottom);
1696         overall.x = TRUNC(left);
1697         overall.y = -TRUNC(top);
1698         overall.xoff = TRUNC(ROUND(face->glyph->advance.x));
1699     }
1700     if (face)
1701         unlockFace();
1702     return overall;
1703 }
1704
1705 glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix)
1706 {
1707     return alphaMapBoundingBox(glyph, 0, matrix, QFontEngine::Format_None);
1708 }
1709
1710 glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format)
1711 {
1712     FT_Face face = 0;
1713     glyph_metrics_t overall;
1714     QGlyphSet *glyphSet = 0;
1715     if (matrix.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
1716         // TODO move everything here to a method of its own to access glyphSets
1717         // to be shared with a new method that will replace loadTransformedGlyphSet()
1718         FT_Matrix m;
1719         m.xx = FT_Fixed(matrix.m11() * 65536);
1720         m.xy = FT_Fixed(-matrix.m21() * 65536);
1721         m.yx = FT_Fixed(-matrix.m12() * 65536);
1722         m.yy = FT_Fixed(matrix.m22() * 65536);
1723         for (int i = 0; i < transformedGlyphSets.count(); ++i) {
1724             const QGlyphSet &g = transformedGlyphSets.at(i);
1725             if (g.transformationMatrix.xx == m.xx
1726                 && g.transformationMatrix.xy == m.xy
1727                 && g.transformationMatrix.yx == m.yx
1728                 && g.transformationMatrix.yy == m.yy) {
1729
1730                 // found a match, move it to the front
1731                 transformedGlyphSets.move(i, 0);
1732                 glyphSet = &transformedGlyphSets[0];
1733                 break;
1734             }
1735         }
1736
1737         if (!glyphSet) {
1738             // don't cache more than 10 transformations
1739             if (transformedGlyphSets.count() >= 10) {
1740                 transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
1741                 freeServerGlyphSet(transformedGlyphSets.at(0).id);
1742             } else {
1743                 transformedGlyphSets.prepend(QGlyphSet());
1744             }
1745             glyphSet = &transformedGlyphSets[0];
1746             glyphSet->clear();
1747             glyphSet->id = allocateServerGlyphSet();
1748             glyphSet->transformationMatrix = m;
1749         }
1750         Q_ASSERT(glyphSet);
1751     } else {
1752         glyphSet = &defaultGlyphSet;
1753     }
1754     Glyph * g = glyphSet->getGlyph(glyph);
1755     if (!g || g->format != format) {
1756         face = lockFace();
1757         FT_Matrix m = this->matrix;
1758         FT_Matrix_Multiply(&glyphSet->transformationMatrix, &m);
1759         freetype->matrix = m;
1760         g = loadGlyph(glyphSet, glyph, subPixelPosition, format);
1761     }
1762
1763     if (g) {
1764         overall.x = g->x;
1765         overall.y = -g->y;
1766         overall.width = g->width;
1767         overall.height = g->height;
1768         overall.xoff = g->advance;
1769     } else {
1770         int left  = FLOOR(face->glyph->metrics.horiBearingX);
1771         int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1772         int top    = CEIL(face->glyph->metrics.horiBearingY);
1773         int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1774
1775         overall.width = TRUNC(right-left);
1776         overall.height = TRUNC(top-bottom);
1777         overall.x = TRUNC(left);
1778         overall.y = -TRUNC(top);
1779         overall.xoff = TRUNC(ROUND(face->glyph->advance.x));
1780     }
1781     if (face)
1782         unlockFace();
1783     return overall;
1784 }
1785
1786 QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
1787 {
1788     lockFace();
1789
1790     GlyphFormat glyph_format = antialias ? Format_A8 : Format_Mono;
1791
1792     Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
1793     if (!glyph) {
1794         unlockFace();
1795         return QFontEngine::alphaMapForGlyph(g);
1796     }
1797
1798     const int pitch = antialias ? (glyph->width + 3) & ~3 : ((glyph->width + 31)/32) * 4;
1799
1800     QImage img(glyph->width, glyph->height, antialias ? QImage::Format_Indexed8 : QImage::Format_Mono);
1801     if (antialias) {
1802         QVector<QRgb> colors(256);
1803         for (int i=0; i<256; ++i)
1804             colors[i] = qRgba(0, 0, 0, i);
1805         img.setColorTable(colors);
1806     } else {
1807         QVector<QRgb> colors(2);
1808         colors[0] = qRgba(0, 0, 0, 0);
1809         colors[1] = qRgba(0, 0, 0, 255);
1810         img.setColorTable(colors);
1811     }
1812     Q_ASSERT(img.bytesPerLine() == pitch);
1813     if (glyph->width) {
1814         for (int y = 0; y < glyph->height; ++y)
1815             memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
1816     }
1817     unlockFace();
1818
1819     return img;
1820 }
1821
1822 QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t)
1823 {
1824     if (t.type() > QTransform::TxTranslate)
1825         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
1826
1827     lockFace();
1828
1829     GlyphFormat glyph_format = Format_A32;
1830
1831     Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
1832     if (!glyph) {
1833         unlockFace();
1834         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
1835     }
1836
1837     QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
1838     memcpy(img.bits(), glyph->data, 4 * glyph->width * glyph->height);
1839     unlockFace();
1840
1841     return img;
1842 }
1843
1844 void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
1845 {
1846     defaultGlyphSet.removeGlyphFromCache(glyph, 0);
1847 }
1848
1849 int QFontEngineFT::glyphCount() const
1850 {
1851     int count = 0;
1852     FT_Face face = lockFace();
1853     if (face) {
1854         count = face->num_glyphs;
1855         unlockFace();
1856     }
1857     return count;
1858 }
1859
1860 FT_Face QFontEngineFT::lockFace(Scaling scale) const
1861 {
1862     freetype->lock();
1863     FT_Face face = freetype->face;
1864     if (scale == Unscaled) {
1865         FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0);
1866         freetype->xsize = face->units_per_EM << 6;
1867         freetype->ysize = face->units_per_EM << 6;
1868     } else if (freetype->xsize != xsize || freetype->ysize != ysize) {
1869         FT_Set_Char_Size(face, xsize, ysize, 0, 0);
1870         freetype->xsize = xsize;
1871         freetype->ysize = ysize;
1872     }
1873     if (freetype->matrix.xx != matrix.xx ||
1874         freetype->matrix.yy != matrix.yy ||
1875         freetype->matrix.xy != matrix.xy ||
1876         freetype->matrix.yx != matrix.yx) {
1877         freetype->matrix = matrix;
1878         FT_Set_Transform(face, &freetype->matrix, 0);
1879     }
1880
1881     return face;
1882 }
1883
1884 void QFontEngineFT::unlockFace() const
1885 {
1886     freetype->unlock();
1887 }
1888
1889 FT_Face QFontEngineFT::non_locked_face() const
1890 {
1891     return freetype->face;
1892 }
1893
1894
1895 QFontEngineFT::QGlyphSet::QGlyphSet()
1896     : id(0), outline_drawing(false)
1897 {
1898     transformationMatrix.xx = 0x10000;
1899     transformationMatrix.yy = 0x10000;
1900     transformationMatrix.xy = 0;
1901     transformationMatrix.yx = 0;
1902     memset(fast_glyph_data, 0, sizeof(fast_glyph_data));
1903     fast_glyph_count = 0;
1904 }
1905
1906 QFontEngineFT::QGlyphSet::~QGlyphSet()
1907 {
1908     clear();
1909 }
1910
1911 void QFontEngineFT::QGlyphSet::clear()
1912 {
1913     if (fast_glyph_count > 0) {
1914         for (int i = 0; i < 256; ++i) {
1915             if (fast_glyph_data[i]) {
1916                 delete fast_glyph_data[i];
1917                 fast_glyph_data[i] = 0;
1918             }
1919         }
1920         fast_glyph_count = 0;
1921     }
1922     qDeleteAll(glyph_data);
1923     glyph_data.clear();
1924 }
1925
1926 void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition)
1927 {
1928     if (useFastGlyphData(index, subPixelPosition)) {
1929         if (fast_glyph_data[index]) {
1930             delete fast_glyph_data[index];
1931             fast_glyph_data[index] = 0;
1932             if (fast_glyph_count > 0)
1933                 --fast_glyph_count;
1934         }
1935     } else {
1936         delete glyph_data.take(GlyphAndSubPixelPosition(index, subPixelPosition));
1937     }
1938 }
1939
1940 void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph)
1941 {
1942     if (useFastGlyphData(index, subPixelPosition)) {
1943         if (!fast_glyph_data[index])
1944             ++fast_glyph_count;
1945         fast_glyph_data[index] = glyph;
1946     } else {
1947         glyph_data.insert(GlyphAndSubPixelPosition(index, subPixelPosition), glyph);
1948     }
1949 }
1950
1951 unsigned long QFontEngineFT::allocateServerGlyphSet()
1952 {
1953     return 0;
1954 }
1955
1956 void QFontEngineFT::freeServerGlyphSet(unsigned long id)
1957 {
1958     Q_UNUSED(id);
1959 }
1960
1961 HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
1962 {
1963     lockFace();
1964     bool hsubpixel = true;
1965     int vfactor = 1;
1966     int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor);
1967     HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints);
1968     unlockFace();
1969     return result;
1970 }
1971
1972 bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe)
1973 {
1974     if (!init(fe->faceId(), fe->antialias, fe->defaultFormat, fe->freetype))
1975         return false;
1976
1977     // Increase the reference of this QFreetypeFace since one more QFontEngineFT
1978     // will be using it
1979     freetype->ref.ref();
1980
1981     default_load_flags = fe->default_load_flags;
1982     default_hint_style = fe->default_hint_style;
1983     antialias = fe->antialias;
1984     transform = fe->transform;
1985     embolden = fe->embolden;
1986     subpixelType = fe->subpixelType;
1987     lcdFilterType = fe->lcdFilterType;
1988     canUploadGlyphsToServer = fe->canUploadGlyphsToServer;
1989     embeddedbitmap = fe->embeddedbitmap;
1990
1991     return true;
1992 }
1993
1994 QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const
1995 {
1996     QFontDef fontDef;
1997     fontDef.pixelSize = pixelSize;
1998     QFontEngineFT *fe = new QFontEngineFT(fontDef);
1999     if (!fe->initFromFontEngine(this)) {
2000         delete fe;
2001         return 0;
2002     } else {
2003         return fe;
2004     }
2005 }
2006
2007 QT_END_NAMESPACE
2008
2009 #endif // QT_NO_FREETYPE