Compile with clang when C++11 support is enabled
[profile/ivi/qtbase.git] / src / gui / text / qfontengine_ft.cpp
index e41c0a9..f83ddd3 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtGui module of the Qt Toolkit.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
@@ -49,7 +49,7 @@
 #ifndef QT_NO_FREETYPE
 
 #include "qfile.h"
-#include "qabstractfileengine.h"
+#include "qfileinfo.h"
 #include "qthreadstorage.h"
 #include <qmath.h>
 
@@ -205,6 +205,8 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
     return HB_Err_Ok;
 }
 
+extern QByteArray qt_fontdata_from_index(int);
+
 /*
  * One font file can contain more than one font (bold/italic for example)
  * find the right one and return it.
@@ -229,17 +231,17 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
         QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
         FT_Face face;
         if (!face_id.filename.isEmpty()) {
-            QFile file(QString::fromUtf8(face_id.filename));
+            QString fileName = QString::fromUtf8(face_id.filename);
             if (face_id.filename.startsWith(":qmemoryfonts/")) {
                 // from qfontdatabase.cpp
-                extern QByteArray qt_fontdata_from_index(int);
                 QByteArray idx = face_id.filename;
                 idx.remove(0, 14); // remove ':qmemoryfonts/'
                 bool ok = false;
                 newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
                 if (!ok)
                     newFreetype->fontData = QByteArray();
-            } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
+            } else if (!QFileInfo(fileName).isNativePath()) {
+                QFile file(fileName);
                 if (!file.open(QIODevice::ReadOnly)) {
                     return 0;
                 }
@@ -268,9 +270,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
         newFreetype->matrix.yx = 0;
         newFreetype->unicode_map = 0;
         newFreetype->symbol_map = 0;
-#ifndef QT_NO_FONTCONFIG
-        newFreetype->charset = 0;
-#endif
 
         memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache));
 
@@ -297,21 +296,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
 
         if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
             FT_Set_Char_Size (face, X_SIZE(newFreetype->face, 0), Y_SIZE(newFreetype->face, 0), 0, 0);
-# if 0
-        FcChar8 *name;
-        FcPatternGetString(pattern, FC_FAMILY, 0, &name);
-        qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name,
-               newFreetype->face->charmap ? newFreetype->face->charmap->encoding : 0,
-               newFreetype->unicode_map ? newFreetype->unicode_map->encoding : 0,
-               newFreetype->symbol_map ? newFreetype->symbol_map->encoding : 0);
-
-        for (int i = 0; i < 256; i += 8)
-            qDebug("    %x: %d %d %d %d %d %d %d %d", i,
-                   FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
-                   FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
-                   FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
-                   FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i));
-#endif
 
         FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
         QT_TRY {
@@ -332,10 +316,6 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
     if (!ref.deref()) {
         qHBFreeFace(hbFace);
         FT_Done_Face(face);
-#ifndef QT_NO_FONTCONFIG
-        if (charset)
-            FcCharSetDestroy(charset);
-#endif
         if(freetypeData->faces.contains(face_id))
             freetypeData->faces.take(face_id);
         delete this;
@@ -833,7 +813,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
     }
 
     Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0;
-    if (g && g->format == format)
+    if (g && g->format == format && (fetchMetricsOnly || g->data))
         return g;
 
     QFontEngineFT::GlyphInfo info;
@@ -875,10 +855,8 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
     if (err != FT_Err_Ok)
         qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
 
-    if ((!set || set->outline_drawing) && fetchMetricsOnly)
-        return 0;
-
     FT_GlyphSlot slot = face->glyph;
+
     if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot);
     if (obliquen) {
         Q_FT_GLYPHSLOT_OBLIQUE(slot);
@@ -900,6 +878,30 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
     info.xOff = TRUNC(ROUND(slot->advance.x));
     info.yOff = 0;
 
+    if ((set && set->outline_drawing) || fetchMetricsOnly) {
+        // If the advance doesn't fit in signed char, don't cache it
+        if (qAbs(info.xOff) >= 128)
+            return 0;
+        g = new Glyph;
+        g->data = 0;
+        g->linearAdvance = slot->linearHoriAdvance >> 10;
+        int left  = FLOOR(slot->metrics.horiBearingX);
+        int right = CEIL(slot->metrics.horiBearingX + slot->metrics.width);
+        int top    = CEIL(slot->metrics.horiBearingY);
+        int bottom = FLOOR(slot->metrics.horiBearingY - slot->metrics.height);
+        g->width = TRUNC(right-left);
+        g->height = TRUNC(top-bottom);
+        g->x = TRUNC(left);
+        g->y = TRUNC(top);
+        g->advance = TRUNC(ROUND(slot->advance.x));
+        g->format = format;
+
+        if (set)
+            set->setGlyph(glyph, subPixelPosition, g);
+
+        return g;
+    }
+
     uchar *glyph_buffer = 0;
     int glyph_buffer_size = 0;
 #if defined(QT_USE_FREETYPE_LCDFILTER)
@@ -1171,8 +1173,7 @@ QFixed QFontEngineFT::ascent() const
 
 QFixed QFontEngineFT::descent() const
 {
-    // subtract a pixel to work around QFontMetrics's built-in + 1
-    return QFixed::fromFixed(-metrics.descender - 64);
+    return QFixed::fromFixed(-metrics.descender);
 }
 
 QFixed QFontEngineFT::leading() const
@@ -1411,19 +1412,6 @@ static inline unsigned int getChar(const QChar *str, int &i, const int len)
 bool QFontEngineFT::canRender(const QChar *string, int len)
 {
     FT_Face face = freetype->face;
-#if 0
-    if (_cmap != -1) {
-        lockFace();
-        for ( int i = 0; i < len; i++ ) {
-            unsigned int uc = getChar(string, i, len);
-            if (!FcCharSetHasChar (_font->charset, uc) && getAdobeCharIndex(face, _cmap, uc) == 0) {
-                allExist = false;
-                break;
-            }
-        }
-        unlockFace();
-    } else
-#endif
     {
         for ( int i = 0; i < len; i++ ) {
             unsigned int uc = getChar(string, i, len);
@@ -1494,19 +1482,20 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
             unsigned int uc = getChar(str, i, len);
             glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
             if ( !glyphs->glyphs[glyph_pos] ) {
-                glyph_t glyph;
-#if !defined(QT_NO_FONTCONFIG)
-                if (freetype->charset != 0 && FcCharSetHasChar(freetype->charset, uc)) {
-#else
-                if (false) {
-#endif
-                redo0:
+                // Symbol fonts can have more than one CMAPs, FreeType should take the
+                // correct one for us by default, so we always try FT_Get_Char_Index
+                // first. If it didn't work (returns 0), we will explicitly set the
+                // CMAP to symbol font one and try again. symbol_map is not always the
+                // correct one because in certain fonts like Wingdings symbol_map only
+                // contains PUA codepoints instead of the common ones.
+                glyph_t glyph = FT_Get_Char_Index(face, uc);
+                // Certain symbol fonts don't have no-break space (0xa0) and tab (0x9),
+                // while we usually want to render them as space
+                if (!glyph && (uc == 0xa0 || uc == 0x9)) {
+                    uc = 0x20;
                     glyph = FT_Get_Char_Index(face, uc);
-                    if (!glyph && (uc == 0xa0 || uc == 0x9)) {
-                        uc = 0x20;
-                        goto redo0;
-                    }
-                } else {
+                }
+                if (!glyph) {
                     FT_Set_Charmap(face, freetype->symbol_map);
                     glyph = FT_Get_Char_Index(face, uc);
                     FT_Set_Charmap(face, freetype->unicode_map);
@@ -1525,9 +1514,6 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
                 uc = QChar::mirroredChar(uc);
             glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
             if (!glyphs->glyphs[glyph_pos]) {
-#if !defined(QT_NO_FONTCONFIG)
-                if (freetype->charset == 0 || FcCharSetHasChar(freetype->charset, uc))
-#endif
                 {
                 redo:
                     glyph_t glyph = FT_Get_Char_Index(face, uc);
@@ -1563,7 +1549,9 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
                    (flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(freetype->face);
     for (int i = 0; i < glyphs->numGlyphs; i++) {
         Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs->glyphs[i]) : 0;
-        if (g) {
+        // Since we are passing Format_None to loadGlyph, use same default format logic as loadGlyph
+        GlyphFormat acceptableFormat = (defaultFormat != Format_None) ? defaultFormat : Format_Mono;
+        if (g && g->format == acceptableFormat) {
             glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
         } else {
             if (!face)
@@ -1587,7 +1575,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
     glyph_metrics_t overall;
     // initialize with line height, we get the same behaviour on all platforms
     overall.y = -ascent();
-    overall.height = ascent() + descent() + 1;
+    overall.height = ascent() + descent();
 
     QFixed ymax = 0;
     QFixed xmax = 0;
@@ -1867,7 +1855,7 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
     lockFace();
 
     Glyph *glyph = loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono);
-    if (!glyph) {
+    if (!glyph || !glyph->data) {
         unlockFace();
         return QFontEngine::alphaMapForGlyph(g);
     }
@@ -1896,17 +1884,17 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
     return img;
 }
 
-QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t)
+QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
 {
     if (t.type() > QTransform::TxTranslate)
-        return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
+        return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
 
     lockFace();
 
     Glyph *glyph = loadGlyphFor(g, subPixelPosition, Format_A32);
-    if (!glyph) {
+    if (!glyph || !glyph->data) {
         unlockFace();
-        return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
+        return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
     }
 
     QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
@@ -2058,7 +2046,7 @@ bool QFontEngineFT::initFromFontEngine(const QFontEngineFT *fe)
 
 QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const
 {
-    QFontDef fontDef;
+    QFontDef fontDef(this->fontDef);
     fontDef.pixelSize = pixelSize;
     QFontEngineFT *fe = new QFontEngineFT(fontDef);
     if (!fe->initFromFontEngine(this)) {