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