Support synthesized oblique and bold in SceneGraph
[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) Q_FT_GLYPHSLOT_OBLIQUE(slot);
896     FT_Library library = qt_getFreetype();
897
898     info.xOff = TRUNC(ROUND(slot->advance.x));
899     info.yOff = 0;
900
901     uchar *glyph_buffer = 0;
902     int glyph_buffer_size = 0;
903 #if defined(QT_USE_FREETYPE_LCDFILTER)
904     bool useFreetypeRenderGlyph = false;
905     if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) {
906         err = FT_Library_SetLcdFilter(library, (FT_LcdFilter)lcdFilterType);
907         if (err == FT_Err_Ok)
908             useFreetypeRenderGlyph = true;
909     }
910
911     if (useFreetypeRenderGlyph) {
912         err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V);
913
914         if (err != FT_Err_Ok)
915             qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
916
917         FT_Library_SetLcdFilter(library, FT_LCD_FILTER_NONE);
918
919         info.height = slot->bitmap.rows / vfactor;
920         info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
921         info.x = -slot->bitmap_left;
922         info.y = slot->bitmap_top;
923
924         glyph_buffer_size = info.width * info.height * 4;
925         glyph_buffer = new uchar[glyph_buffer_size];
926
927         if (hsubpixel)
928             convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, false);
929         else if (vfactor != 1)
930             convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, false);
931     } else
932 #endif
933     {
934     int left  = slot->metrics.horiBearingX;
935     int right = slot->metrics.horiBearingX + slot->metrics.width;
936     int top    = slot->metrics.horiBearingY;
937     int bottom = slot->metrics.horiBearingY - slot->metrics.height;
938     if(transform && slot->format != FT_GLYPH_FORMAT_BITMAP) {
939         int l, r, t, b;
940         FT_Vector vector;
941         vector.x = left;
942         vector.y = top;
943         FT_Vector_Transform(&vector, &matrix);
944         l = r = vector.x;
945         t = b = vector.y;
946         vector.x = right;
947         vector.y = top;
948         FT_Vector_Transform(&vector, &matrix);
949         if (l > vector.x) l = vector.x;
950         if (r < vector.x) r = vector.x;
951         if (t < vector.y) t = vector.y;
952         if (b > vector.y) b = vector.y;
953         vector.x = right;
954         vector.y = bottom;
955         FT_Vector_Transform(&vector, &matrix);
956         if (l > vector.x) l = vector.x;
957         if (r < vector.x) r = vector.x;
958         if (t < vector.y) t = vector.y;
959         if (b > vector.y) b = vector.y;
960         vector.x = left;
961         vector.y = bottom;
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         left = l;
968         right = r;
969         top = t;
970         bottom = b;
971     }
972     left = FLOOR(left);
973     right = CEIL(right);
974     bottom = FLOOR(bottom);
975     top = CEIL(top);
976
977     int hpixels = TRUNC(right - left);
978     // subpixel position requires one more pixel
979     if (subPixelPosition > 0 && format != Format_Mono)
980         hpixels++;
981
982     if (hsubpixel)
983         hpixels = hpixels*3 + 8;
984     info.width = hpixels;
985     info.height = TRUNC(top - bottom);
986     info.x = -TRUNC(left);
987     info.y = TRUNC(top);
988     if (hsubpixel) {
989         info.width /= 3;
990         info.x += 1;
991     }
992
993     bool large_glyph = (((short)(slot->linearHoriAdvance>>10) != slot->linearHoriAdvance>>10)
994                         || ((uchar)(info.width) != info.width)
995                         || ((uchar)(info.height) != info.height)
996                         || ((signed char)(info.x) != info.x)
997                         || ((signed char)(info.y) != info.y)
998                         || ((signed char)(info.xOff) != info.xOff));
999
1000     if (large_glyph) {
1001         delete [] glyph_buffer;
1002         return 0;
1003     }
1004
1005     int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
1006                  (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
1007     glyph_buffer_size = pitch * info.height;
1008     glyph_buffer = new uchar[glyph_buffer_size];
1009
1010     if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
1011         FT_Bitmap bitmap;
1012         bitmap.rows = info.height*vfactor;
1013         bitmap.width = hpixels;
1014         bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3);
1015         if (!hsubpixel && vfactor == 1)
1016             bitmap.buffer = glyph_buffer;
1017         else
1018             bitmap.buffer = new uchar[bitmap.rows*bitmap.pitch];
1019         memset(bitmap.buffer, 0, bitmap.rows*bitmap.pitch);
1020         bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY;
1021         FT_Matrix matrix;
1022         matrix.xx = (hsubpixel ? 3 : 1) << 16;
1023         matrix.yy = vfactor << 16;
1024         matrix.yx = matrix.xy = 0;
1025
1026         FT_Outline_Transform(&slot->outline, &matrix);
1027         FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor);
1028         FT_Outline_Get_Bitmap(library, &slot->outline, &bitmap);
1029         if (hsubpixel) {
1030             Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
1031             Q_ASSERT(antialias);
1032             uchar *convoluted = new uchar[bitmap.rows*bitmap.pitch];
1033             bool useLegacyLcdFilter = false;
1034 #if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H)
1035             useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY);
1036 #endif
1037             uchar *buffer = bitmap.buffer;
1038             if (!useLegacyLcdFilter) {
1039                 convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch);
1040                 buffer = convoluted;
1041             }
1042             convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, useLegacyLcdFilter);
1043             delete [] convoluted;
1044         } else if (vfactor != 1) {
1045             convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, true);
1046         }
1047
1048         if (bitmap.buffer != glyph_buffer)
1049             delete [] bitmap.buffer;
1050     } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
1051         Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
1052         uchar *src = slot->bitmap.buffer;
1053         uchar *dst = glyph_buffer;
1054         int h = slot->bitmap.rows;
1055         if (format == Format_Mono) {
1056             int bytes = ((info.width + 7) & ~7) >> 3;
1057             while (h--) {
1058                 memcpy (dst, src, bytes);
1059                 dst += pitch;
1060                 src += slot->bitmap.pitch;
1061             }
1062         } else {
1063             if (hsubpixel) {
1064                 while (h--) {
1065                     uint *dd = (uint *)dst;
1066                     *dd++ = 0;
1067                     for (int x = 0; x < slot->bitmap.width; x++) {
1068                         uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
1069                         *dd++ = a;
1070                     }
1071                     *dd++ = 0;
1072                     dst += pitch;
1073                     src += slot->bitmap.pitch;
1074                 }
1075             } else if (vfactor != 1) {
1076                 while (h--) {
1077                     uint *dd = (uint *)dst;
1078                     for (int x = 0; x < slot->bitmap.width; x++) {
1079                         uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
1080                         *dd++ = a;
1081                     }
1082                     dst += pitch;
1083                     src += slot->bitmap.pitch;
1084                 }
1085             } else {
1086                 while (h--) {
1087                     for (int x = 0; x < slot->bitmap.width; x++) {
1088                         unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00);
1089                         dst[x] = a;
1090                     }
1091                     dst += pitch;
1092                     src += slot->bitmap.pitch;
1093                 }
1094             }
1095         }
1096     } else {
1097         qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format);
1098         delete [] glyph_buffer;
1099         return 0;
1100     }
1101     }
1102
1103
1104     if (!g) {
1105         g = new Glyph;
1106         g->uploadedToServer = false;
1107         g->data = 0;
1108     }
1109
1110     g->linearAdvance = slot->linearHoriAdvance >> 10;
1111     g->width = info.width;
1112     g->height = info.height;
1113     g->x = -info.x;
1114     g->y = info.y;
1115     g->advance = info.xOff;
1116     g->format = format;
1117     delete [] g->data;
1118     g->data = glyph_buffer;
1119
1120     if (uploadToServer) {
1121         uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
1122     }
1123
1124     set->setGlyph(glyph, subPixelPosition, g);
1125
1126     return g;
1127 }
1128
1129 bool QFontEngineFT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const
1130 {
1131     Q_UNUSED(set);
1132     Q_UNUSED(glyphid);
1133     Q_UNUSED(g);
1134     Q_UNUSED(info);
1135     Q_UNUSED(glyphDataSize);
1136     return false;
1137 }
1138
1139 QFontEngine::FaceId QFontEngineFT::faceId() const
1140 {
1141     return face_id;
1142 }
1143
1144 QFontEngine::Properties QFontEngineFT::properties() const
1145 {
1146     Properties p = freetype->properties();
1147     if (p.postscriptName.isEmpty()) {
1148         p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.family.toUtf8());
1149     }
1150
1151     return freetype->properties();
1152 }
1153
1154 QFixed QFontEngineFT::emSquareSize() const
1155 {
1156     if (FT_IS_SCALABLE(freetype->face))
1157         return freetype->face->units_per_EM;
1158     else
1159         return freetype->face->size->metrics.y_ppem;
1160 }
1161
1162 bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const
1163 {
1164     return freetype->getSfntTable(tag, buffer, length);
1165 }
1166
1167 int QFontEngineFT::synthesized() const
1168 {
1169     int s = 0;
1170     if ((fontDef.style != QFont::StyleNormal) && !(freetype->face->style_flags & FT_STYLE_FLAG_ITALIC))
1171         s = SynthesizedItalic;
1172     if ((fontDef.weight == QFont::Bold) && !(freetype->face->style_flags & FT_STYLE_FLAG_BOLD))
1173         s |= SynthesizedBold;
1174     if (fontDef.stretch != 100 && FT_IS_SCALABLE(freetype->face))
1175         s |= SynthesizedStretch;
1176     return s;
1177 }
1178
1179 QFixed QFontEngineFT::ascent() const
1180 {
1181     return QFixed::fromFixed(metrics.ascender);
1182 }
1183
1184 QFixed QFontEngineFT::descent() const
1185 {
1186     // subtract a pixel to work around QFontMetrics's built-in + 1
1187     return QFixed::fromFixed(-metrics.descender - 64);
1188 }
1189
1190 QFixed QFontEngineFT::leading() const
1191 {
1192     return QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);
1193 }
1194
1195 QFixed QFontEngineFT::xHeight() const
1196 {
1197     TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
1198     if (os2 && os2->sxHeight) {
1199         lockFace();
1200         QFixed answer = QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM;
1201         unlockFace();
1202         return answer;
1203     }
1204     return QFontEngine::xHeight();
1205 }
1206
1207 QFixed QFontEngineFT::averageCharWidth() const
1208 {
1209     TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
1210     if (os2 && os2->xAvgCharWidth) {
1211         lockFace();
1212         QFixed answer = QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM;
1213         unlockFace();
1214         return answer;
1215     }
1216     return QFontEngine::averageCharWidth();
1217 }
1218
1219 qreal QFontEngineFT::maxCharWidth() const
1220 {
1221     return metrics.max_advance >> 6;
1222 }
1223
1224 static const ushort char_table[] = {
1225         40,
1226         67,
1227         70,
1228         75,
1229         86,
1230         88,
1231         89,
1232         91,
1233         102,
1234         114,
1235         124,
1236         127,
1237         205,
1238         645,
1239         884,
1240         922,
1241         1070,
1242         12386
1243 };
1244
1245 static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
1246
1247
1248 qreal QFontEngineFT::minLeftBearing() const
1249 {
1250     if (lbearing == SHRT_MIN)
1251         (void) minRightBearing(); // calculates both
1252     return lbearing.toReal();
1253 }
1254
1255 qreal QFontEngineFT::minRightBearing() const
1256 {
1257     if (rbearing == SHRT_MIN) {
1258         lbearing = rbearing = 0;
1259         const QChar *ch = (const QChar *)(const void*)char_table;
1260         QGlyphLayoutArray<char_table_entries> glyphs;
1261         int ng = char_table_entries;
1262         stringToCMap(ch, char_table_entries, &glyphs, &ng, QTextEngine::GlyphIndicesOnly);
1263         while (--ng) {
1264             if (glyphs.glyphs[ng]) {
1265                 glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs.glyphs[ng]);
1266                 lbearing = qMin(lbearing, gi.x);
1267                 rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
1268             }
1269         }
1270     }
1271     return rbearing.toReal();
1272 }
1273
1274 QFixed QFontEngineFT::lineThickness() const
1275 {
1276     return line_thickness;
1277 }
1278
1279 QFixed QFontEngineFT::underlinePosition() const
1280 {
1281     return underline_position;
1282 }
1283
1284 void QFontEngineFT::doKerning(QGlyphLayout *g, QTextEngine::ShaperFlags flags) const
1285 {
1286     if (!kerning_pairs_loaded) {
1287         kerning_pairs_loaded = true;
1288         lockFace();
1289         if (freetype->face->size->metrics.x_ppem != 0) {
1290             QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem);
1291             unlockFace();
1292             const_cast<QFontEngineFT *>(this)->loadKerningPairs(scalingFactor);
1293         } else {
1294             unlockFace();
1295         }
1296     }
1297     QFontEngine::doKerning(g, flags);
1298 }
1299
1300 QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransform &matrix)
1301 {
1302     if (matrix.type() > QTransform::TxShear)
1303         return 0;
1304
1305     // FT_Set_Transform only supports scalable fonts
1306     if (!FT_IS_SCALABLE(freetype->face))
1307         return 0;
1308
1309     FT_Matrix m;
1310     m.xx = FT_Fixed(matrix.m11() * 65536);
1311     m.xy = FT_Fixed(-matrix.m21() * 65536);
1312     m.yx = FT_Fixed(-matrix.m12() * 65536);
1313     m.yy = FT_Fixed(matrix.m22() * 65536);
1314
1315     QGlyphSet *gs = 0;
1316
1317     for (int i = 0; i < transformedGlyphSets.count(); ++i) {
1318         const QGlyphSet &g = transformedGlyphSets.at(i);
1319         if (g.transformationMatrix.xx == m.xx
1320             && g.transformationMatrix.xy == m.xy
1321             && g.transformationMatrix.yx == m.yx
1322             && g.transformationMatrix.yy == m.yy) {
1323
1324             // found a match, move it to the front
1325             transformedGlyphSets.move(i, 0);
1326             gs = &transformedGlyphSets[0];
1327             break;
1328         }
1329     }
1330
1331     if (!gs) {
1332         // don't try to load huge fonts
1333         bool draw_as_outline = fontDef.pixelSize * qSqrt(qAbs(matrix.det())) >= 64;
1334         if (draw_as_outline)
1335             return 0;
1336
1337         // don't cache more than 10 transformations
1338         if (transformedGlyphSets.count() >= 10) {
1339             transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
1340             freeServerGlyphSet(transformedGlyphSets.at(0).id);
1341         } else {
1342             transformedGlyphSets.prepend(QGlyphSet());
1343         }
1344         gs = &transformedGlyphSets[0];
1345
1346         gs->clear();
1347
1348         gs->id = allocateServerGlyphSet();
1349
1350         gs->transformationMatrix = m;
1351         gs->outline_drawing = draw_as_outline;
1352     }
1353
1354     return gs;
1355 }
1356
1357 QFixed QFontEngineFT::subPixelPositionForX(QFixed x)
1358 {
1359     int m_subPixelPositionCount = 4;
1360     if (!supportsSubPixelPositions())
1361         return 0;
1362
1363     QFixed subPixelPosition;
1364     if (x != 0) {
1365         subPixelPosition = x - x.floor();
1366         QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
1367         subPixelPosition = fraction / QFixed(m_subPixelPositionCount);
1368     }
1369     return subPixelPosition;
1370 }
1371
1372 bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
1373                                const QFixedPoint *positions,
1374                                GlyphFormat format)
1375 {
1376     FT_Face face = 0;
1377
1378     for (int i = 0; i < num_glyphs; ++i) {
1379         QFixed spp = subPixelPositionForX(positions[i].x);
1380         Glyph *glyph = gs->getGlyph(glyphs[i], spp);
1381         if (glyph == 0 || glyph->format != format) {
1382             if (!face) {
1383                 face = lockFace();
1384                 FT_Matrix m = matrix;
1385                 FT_Matrix_Multiply(&gs->transformationMatrix, &m);
1386                 FT_Set_Transform(face, &m, 0);
1387                 freetype->matrix = m;
1388             }
1389             if (!loadGlyph(gs, glyphs[i], spp, format)) {
1390                 unlockFace();
1391                 return false;
1392             }
1393         }
1394     }
1395
1396     if (face)
1397         unlockFace();
1398
1399     return true;
1400 }
1401
1402 void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
1403 {
1404     FT_Face face = lockFace(Unscaled);
1405     FT_Set_Transform(face, 0, 0);
1406     FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
1407
1408     int left  = face->glyph->metrics.horiBearingX;
1409     int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width;
1410     int top    = face->glyph->metrics.horiBearingY;
1411     int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
1412
1413     QFixedPoint p;
1414     p.x = 0;
1415     p.y = 0;
1416
1417     metrics->width = QFixed::fromFixed(right-left);
1418     metrics->height = QFixed::fromFixed(top-bottom);
1419     metrics->x = QFixed::fromFixed(left);
1420     metrics->y = QFixed::fromFixed(-top);
1421     metrics->xoff = QFixed::fromFixed(face->glyph->advance.x);
1422
1423     if (!FT_IS_SCALABLE(freetype->face))
1424         QFreetypeFace::addBitmapToPath(face->glyph, p, path);
1425     else
1426         QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6);
1427
1428     FT_Set_Transform(face, &freetype->matrix, 0);
1429     unlockFace();
1430 }
1431
1432 static inline unsigned int getChar(const QChar *str, int &i, const int len)
1433 {
1434     uint ucs4 = str[i].unicode();
1435     if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()) {
1436         ++i;
1437         ucs4 = QChar::surrogateToUcs4(ucs4, str[i].unicode());
1438     }
1439     return ucs4;
1440 }
1441
1442 bool QFontEngineFT::canRender(const QChar *string, int len)
1443 {
1444     FT_Face face = freetype->face;
1445 #if 0
1446     if (_cmap != -1) {
1447         lockFace();
1448         for ( int i = 0; i < len; i++ ) {
1449             unsigned int uc = getChar(string, i, len);
1450             if (!FcCharSetHasChar (_font->charset, uc) && getAdobeCharIndex(face, _cmap, uc) == 0) {
1451                 allExist = false;
1452                 break;
1453             }
1454         }
1455         unlockFace();
1456     } else
1457 #endif
1458     {
1459         for ( int i = 0; i < len; i++ ) {
1460             unsigned int uc = getChar(string, i, len);
1461             if (!FT_Get_Char_Index(face, uc))
1462                     return false;
1463         }
1464     }
1465     return true;
1466 }
1467
1468 void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
1469 {
1470     if (!glyphs.numGlyphs)
1471         return;
1472
1473     if (FT_IS_SCALABLE(freetype->face)) {
1474         QFontEngine::addOutlineToPath(x, y, glyphs, path, flags);
1475     } else {
1476         QVarLengthArray<QFixedPoint> positions;
1477         QVarLengthArray<glyph_t> positioned_glyphs;
1478         QTransform matrix;
1479         matrix.translate(x, y);
1480         getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
1481
1482         FT_Face face = lockFace(Unscaled);
1483         for (int gl = 0; gl < glyphs.numGlyphs; gl++) {
1484             FT_UInt glyph = positioned_glyphs[gl];
1485             FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO);
1486             freetype->addBitmapToPath(face->glyph, positions[gl], path);
1487         }
1488         unlockFace();
1489     }
1490 }
1491
1492 void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
1493                                     QPainterPath *path, QTextItem::RenderFlags)
1494 {
1495     FT_Face face = lockFace(Unscaled);
1496
1497     for (int gl = 0; gl < numGlyphs; gl++) {
1498         FT_UInt glyph = glyphs[gl];
1499
1500         FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
1501
1502         FT_GlyphSlot g = face->glyph;
1503         if (g->format != FT_GLYPH_FORMAT_OUTLINE)
1504             continue;
1505         if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(g);
1506         if (obliquen) Q_FT_GLYPHSLOT_OBLIQUE(g);
1507         QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize);
1508     }
1509     unlockFace();
1510 }
1511
1512 bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
1513                                  QTextEngine::ShaperFlags flags) const
1514 {
1515     if (*nglyphs < len) {
1516         *nglyphs = len;
1517         return false;
1518     }
1519
1520 #if !defined(QT_NO_FONTCONFIG)
1521     extern QMutex *qt_fontdatabase_mutex();
1522     QMutex *mtx = 0;
1523 #endif
1524
1525     bool mirrored = flags & QTextEngine::RightToLeft;
1526     int glyph_pos = 0;
1527     if (freetype->symbol_map) {
1528         FT_Face face = freetype->face;
1529         for ( int i = 0; i < len; ++i ) {
1530             unsigned int uc = getChar(str, i, len);
1531             glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
1532             if ( !glyphs->glyphs[glyph_pos] ) {
1533                 glyph_t glyph;
1534 #if !defined(QT_NO_FONTCONFIG)
1535                 if (!mtx) {
1536                     mtx = qt_fontdatabase_mutex();
1537                     mtx->lock();
1538                 }
1539
1540                 if (freetype->charset != 0 && FcCharSetHasChar(freetype->charset, uc)) {
1541 #else
1542                 if (false) {
1543 #endif
1544                 redo0:
1545                     glyph = FT_Get_Char_Index(face, uc);
1546                     if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1547                         uc = 0x20;
1548                         goto redo0;
1549                     }
1550                 } else {
1551                     FT_Set_Charmap(face, freetype->symbol_map);
1552                     glyph = FT_Get_Char_Index(face, uc);
1553                     FT_Set_Charmap(face, freetype->unicode_map);
1554                 }
1555                 glyphs->glyphs[glyph_pos] = glyph;
1556                 if (uc < QFreetypeFace::cmapCacheSize)
1557                     freetype->cmapCache[uc] = glyph;
1558             }
1559             ++glyph_pos;
1560         }
1561     } else {
1562         FT_Face face = freetype->face;
1563         for (int i = 0; i < len; ++i) {
1564             unsigned int uc = getChar(str, i, len);
1565             if (mirrored)
1566                 uc = QChar::mirroredChar(uc);
1567             glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
1568             if (!glyphs->glyphs[glyph_pos]) {
1569 #if !defined(QT_NO_FONTCONFIG)
1570                 if (!mtx) {
1571                     mtx = qt_fontdatabase_mutex();
1572                     mtx->lock();
1573                 }
1574
1575                 if (freetype->charset == 0 || FcCharSetHasChar(freetype->charset, uc))
1576 #endif
1577                 {
1578                 redo:
1579                     glyph_t glyph = FT_Get_Char_Index(face, uc);
1580                     if (!glyph && (uc == 0xa0 || uc == 0x9)) {
1581                         uc = 0x20;
1582                         goto redo;
1583                     }
1584                     glyphs->glyphs[glyph_pos] = glyph;
1585                     if (uc < QFreetypeFace::cmapCacheSize)
1586                         freetype->cmapCache[uc] = glyph;
1587                 }
1588             }
1589             ++glyph_pos;
1590         }
1591     }
1592
1593     *nglyphs = glyph_pos;
1594     glyphs->numGlyphs = glyph_pos;
1595
1596 #if !defined(QT_NO_FONTCONFIG)
1597     if (mtx)
1598         mtx->unlock();
1599 #endif
1600
1601     if (flags & QTextEngine::GlyphIndicesOnly)
1602         return true;
1603
1604     recalcAdvances(glyphs, flags);
1605
1606     return true;
1607 }
1608
1609 void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
1610 {
1611     FT_Face face = 0;
1612     bool design = (default_hint_style == HintNone ||
1613                    default_hint_style == HintLight ||
1614                    (flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(freetype->face);
1615     for (int i = 0; i < glyphs->numGlyphs; i++) {
1616         Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
1617         if (g) {
1618             glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
1619         } else {
1620             if (!face)
1621                 face = lockFace();
1622             g = loadGlyph(glyphs->glyphs[i], 0, Format_None, true);
1623             glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
1624                                            : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
1625         }
1626         if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
1627             glyphs->advances_x[i] = glyphs->advances_x[i].round();
1628         glyphs->advances_y[i] = 0;
1629     }
1630     if (face)
1631         unlockFace();
1632 }
1633
1634 glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
1635 {
1636
1637     FT_Face face = 0;
1638
1639     glyph_metrics_t overall;
1640     // initialize with line height, we get the same behaviour on all platforms
1641     overall.y = -ascent();
1642     overall.height = ascent() + descent() + 1;
1643
1644     QFixed ymax = 0;
1645     QFixed xmax = 0;
1646     for (int i = 0; i < glyphs.numGlyphs; i++) {
1647         Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]);
1648         if (!g) {
1649             if (!face)
1650                 face = lockFace();
1651             g = loadGlyph(glyphs.glyphs[i], 0, Format_None, true);
1652         }
1653         if (g) {
1654             QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
1655             QFixed y = overall.yoff + glyphs.offsets[i].y - g->y;
1656             overall.x = qMin(overall.x, x);
1657             overall.y = qMin(overall.y, y);
1658             xmax = qMax(xmax, x + g->width);
1659             ymax = qMax(ymax, y + g->height);
1660             overall.xoff += g->advance;
1661         } else {
1662             int left  = FLOOR(face->glyph->metrics.horiBearingX);
1663             int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1664             int top    = CEIL(face->glyph->metrics.horiBearingY);
1665             int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1666
1667             QFixed x = overall.xoff + glyphs.offsets[i].x - (-TRUNC(left));
1668             QFixed y = overall.yoff + glyphs.offsets[i].y - TRUNC(top);
1669             overall.x = qMin(overall.x, x);
1670             overall.y = qMin(overall.y, y);
1671             xmax = qMax(xmax, x + TRUNC(right - left));
1672             ymax = qMax(ymax, y + TRUNC(top - bottom));
1673             overall.xoff += int(TRUNC(ROUND(face->glyph->advance.x)));
1674         }
1675     }
1676     overall.height = qMax(overall.height, ymax - overall.y);
1677     overall.width = xmax - overall.x;
1678
1679     if (face)
1680         unlockFace();
1681
1682     return overall;
1683 }
1684
1685 glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
1686 {
1687     FT_Face face = 0;
1688     glyph_metrics_t overall;
1689     Glyph *g = defaultGlyphSet.getGlyph(glyph);
1690     if (!g) {
1691         face = lockFace();
1692         g = loadGlyph(glyph, 0, Format_None, true);
1693     }
1694     if (g) {
1695         overall.x = g->x;
1696         overall.y = -g->y;
1697         overall.width = g->width;
1698         overall.height = g->height;
1699         overall.xoff = g->advance;
1700         if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
1701             overall.xoff = overall.xoff.round();
1702     } else {
1703         int left  = FLOOR(face->glyph->metrics.horiBearingX);
1704         int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1705         int top    = CEIL(face->glyph->metrics.horiBearingY);
1706         int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1707
1708         overall.width = TRUNC(right-left);
1709         overall.height = TRUNC(top-bottom);
1710         overall.x = TRUNC(left);
1711         overall.y = -TRUNC(top);
1712         overall.xoff = TRUNC(ROUND(face->glyph->advance.x));
1713     }
1714     if (face)
1715         unlockFace();
1716     return overall;
1717 }
1718
1719 glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix)
1720 {
1721     return alphaMapBoundingBox(glyph, 0, matrix, QFontEngine::Format_None);
1722 }
1723
1724 glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format)
1725 {
1726     FT_Face face = 0;
1727     glyph_metrics_t overall;
1728     QGlyphSet *glyphSet = 0;
1729     if (matrix.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
1730         // TODO move everything here to a method of its own to access glyphSets
1731         // to be shared with a new method that will replace loadTransformedGlyphSet()
1732         FT_Matrix m;
1733         m.xx = FT_Fixed(matrix.m11() * 65536);
1734         m.xy = FT_Fixed(-matrix.m21() * 65536);
1735         m.yx = FT_Fixed(-matrix.m12() * 65536);
1736         m.yy = FT_Fixed(matrix.m22() * 65536);
1737         for (int i = 0; i < transformedGlyphSets.count(); ++i) {
1738             const QGlyphSet &g = transformedGlyphSets.at(i);
1739             if (g.transformationMatrix.xx == m.xx
1740                 && g.transformationMatrix.xy == m.xy
1741                 && g.transformationMatrix.yx == m.yx
1742                 && g.transformationMatrix.yy == m.yy) {
1743
1744                 // found a match, move it to the front
1745                 transformedGlyphSets.move(i, 0);
1746                 glyphSet = &transformedGlyphSets[0];
1747                 break;
1748             }
1749         }
1750
1751         if (!glyphSet) {
1752             // don't cache more than 10 transformations
1753             if (transformedGlyphSets.count() >= 10) {
1754                 transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
1755                 freeServerGlyphSet(transformedGlyphSets.at(0).id);
1756             } else {
1757                 transformedGlyphSets.prepend(QGlyphSet());
1758             }
1759             glyphSet = &transformedGlyphSets[0];
1760             glyphSet->clear();
1761             glyphSet->id = allocateServerGlyphSet();
1762             glyphSet->transformationMatrix = m;
1763         }
1764         Q_ASSERT(glyphSet);
1765     } else {
1766         glyphSet = &defaultGlyphSet;
1767     }
1768     Glyph * g = glyphSet->getGlyph(glyph);
1769     if (!g || g->format != format) {
1770         face = lockFace();
1771         FT_Matrix m = this->matrix;
1772         FT_Matrix_Multiply(&glyphSet->transformationMatrix, &m);
1773         freetype->matrix = m;
1774         g = loadGlyph(glyphSet, glyph, subPixelPosition, format);
1775     }
1776
1777     if (g) {
1778         overall.x = g->x;
1779         overall.y = -g->y;
1780         overall.width = g->width;
1781         overall.height = g->height;
1782         overall.xoff = g->advance;
1783     } else {
1784         int left  = FLOOR(face->glyph->metrics.horiBearingX);
1785         int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
1786         int top    = CEIL(face->glyph->metrics.horiBearingY);
1787         int bottom = FLOOR(face->glyph->metrics.horiBearingY - face->glyph->metrics.height);
1788
1789         overall.width = TRUNC(right-left);
1790         overall.height = TRUNC(top-bottom);
1791         overall.x = TRUNC(left);
1792         overall.y = -TRUNC(top);
1793         overall.xoff = TRUNC(ROUND(face->glyph->advance.x));
1794     }
1795     if (face)
1796         unlockFace();
1797     return overall;
1798 }
1799
1800 QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
1801 {
1802     lockFace();
1803
1804     GlyphFormat glyph_format = antialias ? Format_A8 : Format_Mono;
1805
1806     Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
1807     if (!glyph) {
1808         unlockFace();
1809         return QFontEngine::alphaMapForGlyph(g);
1810     }
1811
1812     const int pitch = antialias ? (glyph->width + 3) & ~3 : ((glyph->width + 31)/32) * 4;
1813
1814     QImage img(glyph->width, glyph->height, antialias ? QImage::Format_Indexed8 : QImage::Format_Mono);
1815     if (antialias) {
1816         QVector<QRgb> colors(256);
1817         for (int i=0; i<256; ++i)
1818             colors[i] = qRgba(0, 0, 0, i);
1819         img.setColorTable(colors);
1820     } else {
1821         QVector<QRgb> colors(2);
1822         colors[0] = qRgba(0, 0, 0, 0);
1823         colors[1] = qRgba(0, 0, 0, 255);
1824         img.setColorTable(colors);
1825     }
1826     Q_ASSERT(img.bytesPerLine() == pitch);
1827     if (glyph->width) {
1828         for (int y = 0; y < glyph->height; ++y)
1829             memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
1830     }
1831     unlockFace();
1832
1833     return img;
1834 }
1835
1836 QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t)
1837 {
1838     if (t.type() > QTransform::TxTranslate)
1839         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
1840
1841     lockFace();
1842
1843     GlyphFormat glyph_format = Format_A32;
1844
1845     Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
1846     if (!glyph) {
1847         unlockFace();
1848         return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
1849     }
1850
1851     QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
1852     memcpy(img.bits(), glyph->data, 4 * glyph->width * glyph->height);
1853     unlockFace();
1854
1855     return img;
1856 }
1857
1858 void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
1859 {
1860     defaultGlyphSet.removeGlyphFromCache(glyph, 0);
1861 }
1862
1863 int QFontEngineFT::glyphCount() const
1864 {
1865     int count = 0;
1866     FT_Face face = lockFace();
1867     if (face) {
1868         count = face->num_glyphs;
1869         unlockFace();
1870     }
1871     return count;
1872 }
1873
1874 FT_Face QFontEngineFT::lockFace(Scaling scale) const
1875 {
1876     freetype->lock();
1877     FT_Face face = freetype->face;
1878     if (scale == Unscaled) {
1879         FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0);
1880         freetype->xsize = face->units_per_EM << 6;
1881         freetype->ysize = face->units_per_EM << 6;
1882     } else if (freetype->xsize != xsize || freetype->ysize != ysize) {
1883         FT_Set_Char_Size(face, xsize, ysize, 0, 0);
1884         freetype->xsize = xsize;
1885         freetype->ysize = ysize;
1886     }
1887     if (freetype->matrix.xx != matrix.xx ||
1888         freetype->matrix.yy != matrix.yy ||
1889         freetype->matrix.xy != matrix.xy ||
1890         freetype->matrix.yx != matrix.yx) {
1891         freetype->matrix = matrix;
1892         FT_Set_Transform(face, &freetype->matrix, 0);
1893     }
1894
1895     return face;
1896 }
1897
1898 void QFontEngineFT::unlockFace() const
1899 {
1900     freetype->unlock();
1901 }
1902
1903 FT_Face QFontEngineFT::non_locked_face() const
1904 {
1905     return freetype->face;
1906 }
1907
1908
1909 QFontEngineFT::QGlyphSet::QGlyphSet()
1910     : id(0), outline_drawing(false)
1911 {
1912     transformationMatrix.xx = 0x10000;
1913     transformationMatrix.yy = 0x10000;
1914     transformationMatrix.xy = 0;
1915     transformationMatrix.yx = 0;
1916     memset(fast_glyph_data, 0, sizeof(fast_glyph_data));
1917     fast_glyph_count = 0;
1918 }
1919
1920 QFontEngineFT::QGlyphSet::~QGlyphSet()
1921 {
1922     clear();
1923 }
1924
1925 void QFontEngineFT::QGlyphSet::clear()
1926 {
1927     if (fast_glyph_count > 0) {
1928         for (int i = 0; i < 256; ++i) {
1929             if (fast_glyph_data[i]) {
1930                 delete fast_glyph_data[i];
1931                 fast_glyph_data[i] = 0;
1932             }
1933         }
1934         fast_glyph_count = 0;
1935     }
1936     qDeleteAll(glyph_data);
1937     glyph_data.clear();
1938 }
1939
1940 void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition)
1941 {
1942     if (useFastGlyphData(index, subPixelPosition)) {
1943         if (fast_glyph_data[index]) {
1944             delete fast_glyph_data[index];
1945             fast_glyph_data[index] = 0;
1946             if (fast_glyph_count > 0)
1947                 --fast_glyph_count;
1948         }
1949     } else {
1950         delete glyph_data.take(GlyphAndSubPixelPosition(index, subPixelPosition));
1951     }
1952 }
1953
1954 void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph)
1955 {
1956     if (useFastGlyphData(index, subPixelPosition)) {
1957         if (!fast_glyph_data[index])
1958             ++fast_glyph_count;
1959         fast_glyph_data[index] = glyph;
1960     } else {
1961         glyph_data.insert(GlyphAndSubPixelPosition(index, subPixelPosition), glyph);
1962     }
1963 }
1964
1965 unsigned long QFontEngineFT::allocateServerGlyphSet()
1966 {
1967     return 0;
1968 }
1969
1970 void QFontEngineFT::freeServerGlyphSet(unsigned long id)
1971 {
1972     Q_UNUSED(id);
1973 }
1974
1975 HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
1976 {
1977     lockFace();
1978     bool hsubpixel = true;
1979     int vfactor = 1;
1980     int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor);
1981     HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints);
1982     unlockFace();
1983     return result;
1984 }
1985
1986 bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe)
1987 {
1988     if (!init(fe->faceId(), fe->antialias, fe->defaultFormat, fe->freetype))
1989         return false;
1990
1991     // Increase the reference of this QFreetypeFace since one more QFontEngineFT
1992     // will be using it
1993     freetype->ref.ref();
1994
1995     default_load_flags = fe->default_load_flags;
1996     default_hint_style = fe->default_hint_style;
1997     antialias = fe->antialias;
1998     transform = fe->transform;
1999     embolden = fe->embolden;
2000     obliquen = fe->obliquen;
2001     subpixelType = fe->subpixelType;
2002     lcdFilterType = fe->lcdFilterType;
2003     canUploadGlyphsToServer = fe->canUploadGlyphsToServer;
2004     embeddedbitmap = fe->embeddedbitmap;
2005
2006     return true;
2007 }
2008
2009 QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const
2010 {
2011     QFontDef fontDef;
2012     fontDef.pixelSize = pixelSize;
2013     QFontEngineFT *fe = new QFontEngineFT(fontDef);
2014     if (!fe->initFromFontEngine(this)) {
2015         delete fe;
2016         return 0;
2017     } else {
2018         return fe;
2019     }
2020 }
2021
2022 QT_END_NAMESPACE
2023
2024 #endif // QT_NO_FREETYPE