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