summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/text/qfont.cpp14
-rw-r--r--src/gui/text/qfont_p.h1
-rw-r--r--src/gui/text/qfontdatabase_qpa.cpp3
-rw-r--r--src/gui/text/qfontengine.cpp37
-rw-r--r--src/gui/text/qfontengine_ft_p.h1
-rw-r--r--src/gui/text/qfontengine_p.h3
-rw-r--r--src/gui/text/qfontengine_qpa_p.h5
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.cpp12
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.h2
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/fontconfig.pri6
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp11
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h1
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig.cpp87
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontenginemultifontconfig_p.h60
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