diff options
-rw-r--r-- | src/gui/text/qfont.cpp | 14 | ||||
-rw-r--r-- | src/gui/text/qfont_p.h | 1 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase_qpa.cpp | 3 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 37 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft_p.h | 1 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 3 | ||||
-rw-r--r-- | src/gui/text/qfontengine_qpa_p.h | 5 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase_qpa.cpp | 12 | ||||
-rw-r--r-- | src/gui/text/qplatformfontdatabase_qpa.h | 2 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/fontconfig/fontconfig.pri | 6 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp | 11 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h | 1 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp | 87 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h | 60 |
14 files changed, 235 insertions, 8 deletions
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index a347c62629..ee833a06cf 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2729,6 +2729,20 @@ QFontEngine *QFontCache::findEngine(const Key &key) return it.value().data; } +void QFontCache::removeEngine(QFontEngine *engine) +{ + EngineCache::iterator it = engineCache.begin(); + while (it != engineCache.end()) { + if (it.value().data == engine) { + it = engineCache.erase(it); + if (--engine->cache_count == 0) + decreaseCost(engine->cache_cost); + } else { + ++it; + } + } +} + void QFontCache::insertEngine(const Key &key, QFontEngine *engine) { FC_DEBUG("QFontCache: inserting new engine %p", engine); diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index e26a98aaf2..d10249201a 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -243,6 +243,7 @@ public: QFontEngine *findEngine(const Key &key); void insertEngine(const Key &key, QFontEngine *engine); + void removeEngine(QFontEngine *engine); private: diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index 2a9c37fb13..1a1f08f73d 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -206,7 +206,8 @@ QFontEngine *loadEngine(int script, const QFontDef &request, if (family && !family->fallbackFamilies.isEmpty()) fallbacks = family->fallbackFamilies; - engine = new QFontEngineMultiQPA(engine, script, fallbacks); + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); + engine = pfdb->fontEngineMulti(engine, QUnicodeTables::Script(script), fallbacks); // Cache Multi font engine as well in case we got the FT single // font engine when we are actually looking for a Multi one diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 156a4a1e59..a084a3dd8c 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1379,18 +1379,24 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, int glyph_pos = 0; for (int i = 0; i < len; ++i) { bool surrogate = (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()); - + uint ucs4 = surrogate ? QChar::surrogateToUcs4(str[i], str[i+1]) : str[i].unicode(); if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) { QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos); - for (int x = 1; x < engines.size(); ++x) { + for (int x=1; x < engines.size(); ++x) { + if (!shouldLoadFontEngineForCharacter(x, ucs4)) + continue; + QFontEngine *engine = engines.at(x); + bool deleteThisEngine = false; if (!engine) { const_cast<QFontEngineMulti *>(this)->loadEngine(x); engine = engines.at(x); + deleteThisEngine = true; } Q_ASSERT(engine != 0); if (engine->type() == Box) continue; + glyphs->advances_x[glyph_pos] = glyphs->advances_y[glyph_pos] = 0; glyphs->offsets[glyph_pos] = QFixedPoint(); int num = 2; @@ -1401,13 +1407,17 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, // set the high byte to indicate which engine the glyph came from glyphs->glyphs[glyph_pos] |= (x << 24); break; + } else if (deleteThisEngine) { + const_cast<QFontEngineMulti *>(this)->unloadEngine(x); } } + // ensure we use metrics from the 1st font when we use the fallback image. if (!glyphs->glyphs[glyph_pos]) { glyphs->setInstance(glyph_pos, tmp); } } + if (surrogate) ++i; ++glyph_pos; @@ -1418,6 +1428,29 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, return true; } +bool QFontEngineMulti::shouldLoadFontEngineForCharacter(int at, uint ucs4) const +{ + Q_UNUSED(at); + Q_UNUSED(ucs4); + return true; +} + +void QFontEngineMulti::unloadEngine(int at) +{ + QFontEngine *fontEngine = engines.at(at); + if (fontEngine == 0) + return; + + // If there are other references to the engine, keep it around and keep the reference + if (fontEngine->ref.load() == 1) { + QFontCache::instance()->removeEngine(fontEngine); + if (fontEngine->cache_count == 0) { + delete fontEngine; + engines[at] = 0; + } + } +} + glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs) { if (glyphs.numGlyphs <= 0) diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index a9e67c10e8..83b51685c0 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -328,6 +328,7 @@ protected: private: friend class QFontEngineFTRawFont; friend class QFontconfigDatabase; + friend class QFontEngineMultiFontConfig; int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index c0bd1afb80..023882d560 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -392,11 +392,14 @@ public: loadEngine(at); } + virtual bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const; + protected: friend class QPSPrintEnginePrivate; friend class QPSPrintEngineFontMulti; friend class QRawFont; virtual void loadEngine(int at) = 0; + virtual void unloadEngine(int at); QVector<QFontEngine *> engines; }; diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h index 6a73b9d309..ed2e071ac2 100644 --- a/src/gui/text/qfontengine_qpa_p.h +++ b/src/gui/text/qfontengine_qpa_p.h @@ -243,13 +243,16 @@ struct QPAGenerator QFontEngine *fe; }; -class QFontEngineMultiQPA : public QFontEngineMulti +class Q_GUI_EXPORT QFontEngineMultiQPA : public QFontEngineMulti { public: QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); void loadEngine(int at); + int fallbackFamilyCount() const { return fallbackFamilies.size(); } + QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); } + private: QStringList fallbackFamilies; int script; diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp index f9cc97cbc7..8fcf421330 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.cpp +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -271,6 +271,18 @@ void QPlatformFontDatabase::populateFontDatabase() } /*! + Returns a multi font engine in the specified \a script to encapsulate \a fontEngine with the + option to fall back to to the fonts given by \a fallbacks if \a fontEngine does not support + a certain character. +*/ +QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine, + QUnicodeTables::Script script, + const QStringList &fallbacks) +{ + return new QFontEngineMultiQPA(fontEngine, script, fallbacks); +} + +/*! Returns the font engine that can be used to render the font described by the font definition, \a fontDef, in the specified \a script. */ diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h index 151442c5e1..6a58a3106c 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.h +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -82,12 +82,14 @@ Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedW Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); class QFontRequestPrivate; +class QFontEngineMulti; class Q_GUI_EXPORT QPlatformFontDatabase { public: virtual ~QPlatformFontDatabase(); virtual void populateFontDatabase(); + virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QUnicodeTables::Script script, const QStringList &fallbacks); virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); diff --git a/src/platformsupport/fontdatabases/fontconfig/fontconfig.pri b/src/platformsupport/fontdatabases/fontconfig/fontconfig.pri index 7ea1c64e33..2c896ef2cc 100644 --- a/src/platformsupport/fontdatabases/fontconfig/fontconfig.pri +++ b/src/platformsupport/fontdatabases/fontconfig/fontconfig.pri @@ -1,3 +1,5 @@ -HEADERS += $$PWD/qfontconfigdatabase_p.h -SOURCES += $$PWD/qfontconfigdatabase.cpp +HEADERS += $$PWD/qfontconfigdatabase_p.h \ + fontdatabases/fontconfig/qfontenginemultifontconfig_p.h +SOURCES += $$PWD/qfontconfigdatabase.cpp \ + fontdatabases/fontconfig/qfontenginemultifontconfig.cpp DEFINES -= QT_NO_FONTCONFIG diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index f048ed91de..8a9670118f 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qfontconfigdatabase_p.h" +#include "qfontenginemultifontconfig_p.h" #include <QtCore/QList> #include <QtGui/private/qfont_p.h> @@ -50,8 +51,7 @@ #include <QtGui/private/qfontengine_ft_p.h> #include <QtGui/private/qfontengine_p.h> - - +#include <QtGui/private/qfontengine_qpa_p.h> #include <ft2build.h> #include FT_TRUETYPE_TABLES_H @@ -471,6 +471,13 @@ void QFontconfigDatabase::populateFontDatabase() // QApplication::setFont(font); } +QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, + QUnicodeTables::Script script, + const QStringList &fallbacks) +{ + return new QFontEngineMultiFontConfig(fontEngine, script, fallbacks); +} + QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) { if (!usrPtr) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index 77509f76e5..d4742167e9 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -51,6 +51,7 @@ class QFontconfigDatabase : public QBasicFontDatabase { public: void populateFontDatabase(); + QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QUnicodeTables::Script script, const QStringList &fallbacks); QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp new file mode 100644 index 0000000000..7b28b20bcb --- /dev/null +++ b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfontenginemultifontconfig_p.h" + +#include <QtGui/private/qfontengine_ft_p.h> +#include <fontconfig/fontconfig.h> +#include <QtGui/private/qfontengine_ft_p.h> + +QT_BEGIN_NAMESPACE + +QFontEngineMultiFontConfig::QFontEngineMultiFontConfig(QFontEngine *fe, int script, + const QStringList &fallbacks) + : QFontEngineMultiQPA(fe, script, fallbacks) +{ +} + +bool QFontEngineMultiFontConfig::shouldLoadFontEngineForCharacter(int at, uint ucs4) const +{ + QFontEngineFT *fontEngine = static_cast<QFontEngineFT *>(engines.at(at)); + bool charSetHasChar = true; + if (fontEngine != 0) { + FcCharSet *charSet = fontEngine->freetype->charset; + charSetHasChar = FcCharSetHasChar(charSet, ucs4); + } else { + FcPattern *requestPattern = FcPatternCreate(); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fallbackFamilyAt(at-1).toUtf8(); + value.u.s = reinterpret_cast<const FcChar8 *>(cs.data()); + FcPatternAdd(requestPattern, FC_FAMILY, value, true); + + FcResult result; + FcPattern *matchPattern = FcFontMatch(0, requestPattern, &result); + if (matchPattern != 0) { + FcCharSet *charSet; + FcPatternGetCharSet(matchPattern, FC_CHARSET, 0, &charSet); + charSetHasChar = FcCharSetHasChar(charSet, ucs4); + FcPatternDestroy(matchPattern); + } + + FcPatternDestroy(requestPattern); + } + + return charSetHasChar; +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h new file mode 100644 index 0000000000..4323cb7d2e --- /dev/null +++ b/src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFONTENGINEMULTIFONTCONFIG_H +#define QFONTENGINEMULTIFONTCONFIG_H + +#include <QtGui/private/qfontengine_qpa_p.h> + +QT_BEGIN_NAMESPACE + +class QFontEngineMultiFontConfig : public QFontEngineMultiQPA +{ + Q_OBJECT +public: + explicit QFontEngineMultiFontConfig(QFontEngine *fe, int script, const QStringList &fallbacks); + + bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const; +}; + +QT_END_NAMESPACE + +#endif // QFONTENGINEMULTIFONTCONFIG_H |