summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qfontdatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/qfontdatabase.cpp')
-rw-r--r--src/gui/text/qfontdatabase.cpp419
1 files changed, 416 insertions, 3 deletions
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 61c93dc2ac..b8ac7efb6c 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -55,6 +55,8 @@
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformtheme.h>
+#include <QtCore/qmath.h>
+
#include <stdlib.h>
#include <limits.h>
#include <algorithm>
@@ -654,9 +656,200 @@ QMutex *qt_fontdatabase_mutex()
return fontDatabaseMutex();
}
-QT_BEGIN_INCLUDE_NAMESPACE
-# include "qfontdatabase_qpa.cpp"
-QT_END_INCLUDE_NAMESPACE
+
+void qt_registerFont(const QString &familyName, const QString &stylename,
+ const QString &foundryname, int weight,
+ QFont::Style style, int stretch, bool antialiased,
+ bool scalable, int pixelSize, bool fixedPitch,
+ const QSupportedWritingSystems &writingSystems, void *handle)
+{
+ QFontDatabasePrivate *d = privateDb();
+// qDebug() << "Adding font" << familyName << weight << style << pixelSize << antialiased;
+ QtFontStyle::Key styleKey;
+ styleKey.style = style;
+ styleKey.weight = weight;
+ styleKey.stretch = stretch;
+ QtFontFamily *f = d->family(familyName, true);
+ f->fixedPitch = fixedPitch;
+
+ for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
+ if (writingSystems.supported(QFontDatabase::WritingSystem(i)))
+ f->writingSystems[i] = QtFontFamily::Supported;
+ }
+
+ QtFontFoundry *foundry = f->foundry(foundryname, true);
+ QtFontStyle *fontStyle = foundry->style(styleKey, stylename, true);
+ fontStyle->smoothScalable = scalable;
+ fontStyle->antialiased = antialiased;
+ QtFontSize *size = fontStyle->pixelSize(pixelSize ? pixelSize : SMOOTH_SCALABLE, true);
+ if (size->handle) {
+ QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration();
+ if (integration)
+ integration->fontDatabase()->releaseHandle(size->handle);
+ }
+ size->handle = handle;
+}
+
+void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
+{
+ if (alias.isEmpty())
+ return;
+
+ QFontDatabasePrivate *d = privateDb();
+ QtFontFamily *f = d->family(familyName, false);
+ if (!f)
+ return;
+
+ if (f->aliases.contains(alias, Qt::CaseInsensitive))
+ return;
+
+ f->aliases.push_back(alias);
+}
+
+QString qt_resolveFontFamilyAlias(const QString &alias)
+{
+ if (!alias.isEmpty()) {
+ const QFontDatabasePrivate *d = privateDb();
+ for (int i = 0; i < d->count; ++i)
+ if (d->families[i]->matchesFamilyName(alias))
+ return d->families[i]->name;
+ }
+ return alias;
+}
+
+static QStringList fallbackFamilies(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
+{
+ QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
+ QFontDatabasePrivate *db = privateDb();
+
+ QStringList::iterator i;
+ for (i = retList.begin(); i != retList.end(); ++i) {
+ bool contains = false;
+ for (int j = 0; j < db->count; j++) {
+ if (db->families[j]->matchesFamilyName(*i)) {
+ contains = true;
+ break;
+ }
+ }
+ if (!contains) {
+ i = retList.erase(i);
+ i--;
+ }
+ }
+ return retList;
+}
+
+static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
+
+static void initializeDb()
+{
+ QFontDatabasePrivate *db = privateDb();
+
+ // init by asking for the platformfontdb for the first time or after invalidation
+ if (!db->count)
+ QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
+
+ if (db->reregisterAppFonts) {
+ for (int i = 0; i < db->applicationFonts.count(); i++) {
+ if (!db->applicationFonts.at(i).families.isEmpty())
+ registerFont(&db->applicationFonts[i]);
+ }
+ db->reregisterAppFonts = false;
+ }
+}
+
+static inline void load(const QString & = QString(), int = -1)
+{
+ // Only initialize the database if it has been cleared or not initialized yet
+ if (!privateDb()->count)
+ initializeDb();
+}
+
+static
+QFontEngine *loadSingleEngine(int script,
+ const QFontDef &request,
+ QtFontFoundry *foundry,
+ QtFontStyle *style, QtFontSize *size)
+{
+ Q_UNUSED(foundry);
+
+ Q_ASSERT(size);
+ QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ int pixelSize = size->pixelSize;
+ if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE)
+ || pfdb->fontsAlwaysScalable()) {
+ pixelSize = request.pixelSize;
+ }
+
+ QFontDef def = request;
+ def.pixelSize = pixelSize;
+
+ QFontCache::Key key(def,script);
+ QFontEngine *engine = QFontCache::instance()->findEngine(key);
+ if (!engine) {
+ engine = pfdb->fontEngine(def, size->handle);
+ if (engine) {
+ // Also check for OpenType tables when using complex scripts
+ if (!engine->supportsScript(QChar::Script(script))) {
+ qWarning(" OpenType support missing for script %d", script);
+ if (engine->ref.load() == 0)
+ delete engine;
+ return 0;
+ }
+
+ QFontCache::instance()->insertEngine(key, engine);
+ }
+ }
+ return engine;
+}
+
+static
+QFontEngine *loadEngine(int script, const QFontDef &request,
+ QtFontFamily *family, QtFontFoundry *foundry,
+ QtFontStyle *style, QtFontSize *size)
+{
+
+ QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
+ //make sure that the db has all fallback families
+ if (engine && engine->type() != QFontEngine::Multi
+ && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {
+
+ if (family && !family->askedForFallback) {
+ QFont::Style fontStyle = QFont::Style(style->key.style);
+ QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
+ if (styleHint == QFont::AnyStyle && request.fixedPitch)
+ styleHint = QFont::TypeWriter;
+ family->fallbackFamilies = fallbackFamilies(family->name, fontStyle, styleHint, QChar::Script(script));
+
+ family->askedForFallback = true;
+ }
+
+ QStringList fallbacks = privateDb()->fallbackFamilies;
+ if (family && !family->fallbackFamilies.isEmpty())
+ fallbacks = family->fallbackFamilies;
+
+ QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
+ pfMultiEngine->setFallbackFamiliesList(fallbacks);
+ engine = pfMultiEngine;
+
+ // Cache Multi font engine as well in case we got the single
+ // font engine when we are actually looking for a Multi one
+ QFontCache::Key key(request, script, 1);
+ QFontCache::instance()->insertEngine(key, engine);
+ }
+
+ return engine;
+}
+
+static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
+{
+ QFontDatabasePrivate *db = privateDb();
+
+ fnt->families = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName);
+
+ db->reregisterAppFonts = true;
+}
static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
const QString &styleName = QString())
@@ -2146,6 +2339,20 @@ QFont QFontDatabase::systemFont(QFontDatabase::SystemFont type)
\sa removeAllApplicationFonts(), addApplicationFont(),
addApplicationFontFromData()
*/
+bool QFontDatabase::removeApplicationFont(int handle)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ QFontDatabasePrivate *db = privateDb();
+ if (handle < 0 || handle >= db->applicationFonts.count())
+ return false;
+
+ db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
+
+ db->reregisterAppFonts = true;
+ db->invalidate();
+ return true;
+}
/*!
\fn bool QFontDatabase::removeAllApplicationFonts()
@@ -2159,6 +2366,18 @@ QFont QFontDatabase::systemFont(QFontDatabase::SystemFont type)
\sa removeApplicationFont(), addApplicationFont(), addApplicationFontFromData()
*/
+bool QFontDatabase::removeAllApplicationFonts()
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ QFontDatabasePrivate *db = privateDb();
+ if (db->applicationFonts.isEmpty())
+ return false;
+
+ db->applicationFonts.clear();
+ db->invalidate();
+ return true;
+}
/*!
\fn bool QFontDatabase::supportsThreadedFontRendering()
@@ -2174,6 +2393,200 @@ QFont QFontDatabase::systemFont(QFontDatabase::SystemFont type)
\sa {Thread-Support in Qt Modules#Painting In Threads}{Painting In Threads}
*/
+// QT_DEPRECATED_SINCE(5, 2)
+bool QFontDatabase::supportsThreadedFontRendering()
+{
+ return true;
+}
+
+/*!
+ \internal
+*/
+QFontEngine *
+QFontDatabase::findFont(int script, const QFontPrivate *fp,
+ const QFontDef &request, bool multi)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ const int force_encoding_id = -1;
+
+ if (!privateDb()->count)
+ initializeDb();
+
+ QFontEngine *engine;
+ QFontCache::Key key(request, script, multi ? 1 : 0);
+ engine = QFontCache::instance()->findEngine(key);
+ if (engine) {
+ FM_DEBUG("Cache hit level 1");
+ return engine;
+ }
+
+ QString family_name, foundry_name;
+
+ parseFontName(request.family, foundry_name, family_name);
+
+ if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
+ engine =new QTestFontEngine(request.pixelSize);
+ engine->fontDef = request;
+ }
+
+ QtFontDesc desc;
+ QList<int> blackListed;
+ int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed);
+ if (index >= 0) {
+ engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
+ if (!engine)
+ blackListed.append(index);
+ } else {
+ FM_DEBUG(" NO MATCH FOUND\n");
+ }
+
+ if (engine && engine->type() != QFontEngine::TestFontEngine) {
+ initFontDef(desc, request, &engine->fontDef, engine->type() == QFontEngine::Multi);
+
+ if (fp) {
+ QFontDef def = request;
+ if (def.family.isEmpty()) {
+ def.family = fp->request.family;
+ def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
+ }
+ }
+ }
+
+ if (!engine) {
+ if (!request.family.isEmpty()) {
+ QStringList fallbacks = request.fallBackFamilies
+ + fallbackFamilies(request.family,
+ QFont::Style(request.style),
+ QFont::StyleHint(request.styleHint),
+ QChar::Script(script));
+ if (script > QChar::Script_Common)
+ fallbacks += QString(); // Find the first font matching the specified script.
+
+ for (int i = 0; !engine && i < fallbacks.size(); i++) {
+ QFontDef def = request;
+ def.family = fallbacks.at(i);
+ QFontCache::Key key(def, script, multi ? 1 : 0);
+ engine = QFontCache::instance()->findEngine(key);
+ if (!engine) {
+ QtFontDesc desc;
+ do {
+ index = match(script, def, def.family, QLatin1String(""), 0, &desc, blackListed);
+ if (index >= 0) {
+ QFontDef loadDef = def;
+ if (loadDef.family.isEmpty())
+ loadDef.family = desc.family->name;
+ engine = loadEngine(script, loadDef, desc.family, desc.foundry, desc.style, desc.size);
+ if (engine)
+ initFontDef(desc, loadDef, &engine->fontDef, engine->type() == QFontEngine::Multi);
+ else
+ blackListed.append(index);
+ }
+ } while (index >= 0 && !engine);
+ }
+ }
+ }
+
+ if (!engine)
+ engine = new QFontEngineBox(request.pixelSize);
+
+ FM_DEBUG("returning box engine");
+ }
+
+ if (fp && fp->dpi > 0) {
+ engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
+ } else {
+ engine->fontDef.pointSize = request.pointSize;
+ }
+
+ return engine;
+}
+
+void QFontDatabase::load(const QFontPrivate *d, int script)
+{
+ QFontDef req = d->request;
+
+ if (req.pixelSize == -1) {
+ req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
+ req.pixelSize = qRound(req.pixelSize);
+ }
+ if (req.pointSize < 0)
+ req.pointSize = req.pixelSize*72.0/d->dpi;
+ if (req.weight == 0)
+ req.weight = QFont::Normal;
+ if (req.stretch == 0)
+ req.stretch = 100;
+
+ // Until we specifically asked not to, try looking for Multi font engine
+ // first, the last '1' indicates that we want Multi font engine instead
+ // of single ones
+ bool multi = !(req.styleStrategy & QFont::NoFontMerging);
+ QFontCache::Key key(req, script, multi ? 1 : 0);
+
+ if (!d->engineData)
+ getEngineData(d, req);
+
+ // the cached engineData could have already loaded the engine we want
+ if (d->engineData->engines[script])
+ return;
+
+ QFontEngine *fe = QFontCache::instance()->findEngine(key);
+
+ // list of families to try
+ QStringList family_list;
+
+ if (!req.family.isEmpty()) {
+ QStringList familiesForRequest = familyList(req);
+
+ // Add primary selection
+ family_list << familiesForRequest.takeFirst();
+
+ // Fallbacks requested in font request
+ req.fallBackFamilies = familiesForRequest;
+
+ // add the default family
+ QString defaultFamily = QGuiApplication::font().family();
+ if (! family_list.contains(defaultFamily))
+ family_list << defaultFamily;
+
+ }
+
+ // null family means find the first font matching the specified script
+ family_list << QString();
+
+ QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
+ for (; !fe && it != end; ++it) {
+ req.family = *it;
+
+ fe = QFontDatabase::findFont(script, d, req, multi);
+ if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty()) {
+ if (fe->ref.load() == 0)
+ delete fe;
+
+ fe = 0;
+ }
+
+ // No need to check requested fallback families again
+ req.fallBackFamilies.clear();
+ }
+
+ if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
+ for (int i = 0; i < QChar::ScriptCount; ++i) {
+ if (!d->engineData->engines[i]) {
+ d->engineData->engines[i] = fe;
+ fe->ref.ref();
+ }
+ }
+ } else {
+ d->engineData->engines[script] = fe;
+ fe->ref.ref();
+ }
+}
+
+QString QFontDatabase::resolveFontFamilyAlias(const QString &family)
+{
+ return QGuiApplicationPrivate::platformIntegration()->fontDatabase()->resolveFontFamilyAlias(family);
+}
QT_END_NAMESPACE