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