diff options
author | Pierre Rossi <pierre.rossi@nokia.com> | 2012-01-16 17:40:21 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-03-01 15:47:24 +0100 |
commit | cc78f47778de0feda95d7a85440d03ad7dcf40bd (patch) | |
tree | 9dd229f840ae887d2199bdf937a9371a8bfbfab7 /src/gui/text/qfontengine_qpa.cpp | |
parent | 10ac80708555cd0cca181e637d3a95c80826ec69 (diff) |
Allow using multi fontengine in QTextLayout with QRawFont.
This change enables us to instantiate a QFontEngineMulti that takes
the raw font's font engine as its primary engine but can use fallback
engines based on the platform. Since this can be quite expensive, we
defer the query for fallback families' names until it's needed and
we cache the resulting multi font engine.
Change-Id: I390dbc1cb2fe61d56867f29a03f313eb3eb49dc3
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Diffstat (limited to 'src/gui/text/qfontengine_qpa.cpp')
-rw-r--r-- | src/gui/text/qfontengine_qpa.cpp | 85 |
1 files changed, 78 insertions, 7 deletions
diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index 33657367fa..48679824a4 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpa.cpp @@ -46,8 +46,10 @@ #include <QtCore/QDir> #include <QtCore/QBuffer> -#include <QtGui/QPlatformFontDatabase> #include <QtGui/private/qpaintengine_raster_p.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/QPlatformFontDatabase> +#include <QtGui/QPlatformIntegration> QT_BEGIN_NAMESPACE @@ -662,6 +664,20 @@ void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks) : QFontEngineMulti(fallbacks.size() + 1), fallbackFamilies(fallbacks), script(_script) + , fallbacksQueried(true) +{ + init(fe); +} + +QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script) + : QFontEngineMulti(2) + , script(_script) + , fallbacksQueried(false) +{ + init(fe); +} + +void QFontEngineMultiQPA::init(QFontEngine *fe) { Q_ASSERT(fe && fe->type() != QFontEngine::Multi); engines[0] = fe; @@ -672,18 +688,73 @@ QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QSt void QFontEngineMultiQPA::loadEngine(int at) { + bool canLoadFallbackEngine = true; + if (!fallbacksQueried) { + // Original FontEngine to restore after the fill. + QFontEngine *fe = engines[0]; + fallbackFamilies = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(fe->fontDef.family, QFont::Style(fe->fontDef.style) + , QFont::AnyStyle, QUnicodeTables::Script(script)); + if (fallbackFamilies.size() > 1) { + engines.fill(0, fallbackFamilies.size() + 1); + engines[0] = fe; + } else { + // Turns out we lied about having any fallback at all. + canLoadFallbackEngine = false; + engines[1] = fe; + } + fallbacksQueried = true; + } Q_ASSERT(at < engines.size()); Q_ASSERT(engines.at(at) == 0); - QFontDef request = fontDef; - request.styleStrategy |= QFont::NoFontMerging; - request.family = fallbackFamilies.at(at-1); - engines[at] = QFontDatabase::findFont(script, - /*fontprivate*/0, - request, false); + if (canLoadFallbackEngine) { + request.styleStrategy |= QFont::NoFontMerging; + request.family = fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(script, + /*fontprivate = */0, + request, /*multi = */false); + } Q_ASSERT(engines[at]); engines[at]->ref.ref(); engines[at]->fontDef = request; } +/* + This is used indirectly by QtWebKit when using QTextLayout::setRawFont + + The purpose of this is to provide the necessary font fallbacks when drawing complex + text. Since QtWebKit ends up repeatedly creating QTextLayout instances and passing them + the same raw font over and over again, we want to cache the corresponding multi font engine + as it may contain fallback font engines already. +*/ +QFontEngine* QFontEngineMultiQPA::createMultiFontEngine(QFontEngine *fe, int script) +{ + QFontEngine *engine = 0; + QFontCache::Key key(fe->fontDef, script, /*multi = */true); + QFontCache *fc = QFontCache::instance(); + // We can't rely on the fontDef (and hence the cache Key) + // alone to distinguish webfonts, since these should not be + // accidentally shared, even if the resulting fontcache key + // is strictly identical. See: + // http://www.w3.org/TR/css3-fonts/#font-face-rule + const bool faceIsLocal = !fe->faceId().filename.isEmpty(); + QFontCache::EngineCache::Iterator it = fc->engineCache.find(key), + end = fc->engineCache.end(); + while (it != end && it.key() == key) { + QFontEngineMulti *cachedEngine = qobject_cast<QFontEngineMulti *>(it.value().data); + if (faceIsLocal || (cachedEngine && fe == cachedEngine->engine(0))) { + engine = cachedEngine; + fc->updateHitCountAndTimeStamp(it.value()); + break; + } + it++; + } + if (!engine) { + engine = new QFontEngineMultiQPA(fe, script); + QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal); + } + Q_ASSERT(engine); + return engine; +} + QT_END_NAMESPACE |