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