1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qlibraryinfo.h"
43 #include <QtCore/qsettings.h>
45 #include "qfontengine_qpa_p.h"
46 #include "qplatformdefs.h"
48 #include <QtGui/private/qapplication_p.h>
49 #include <QtGui/qplatformfontdatabase_qpa.h>
51 #include <QtCore/qmath.h>
55 Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &foundryname, int weight,
56 QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize,
57 const QSupportedWritingSystems &writingSystems, void *handle)
59 QFontDatabasePrivate *d = privateDb();
60 // qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
61 QtFontStyle::Key styleKey;
62 styleKey.style = style;
63 styleKey.weight = weight;
64 styleKey.stretch = stretch;
65 QtFontFamily *f = d->family(familyName, true);
67 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
68 if (writingSystems.supported(QFontDatabase::WritingSystem(i))) {
69 f->writingSystems[i] = QtFontFamily::Supported;
71 f->writingSystems[i] = QtFontFamily::Unsupported;
75 QtFontFoundry *foundry = f->foundry(foundryname, true);
76 QtFontStyle *fontStyle = foundry->style(styleKey, QString(), true);
77 fontStyle->smoothScalable = scalable;
78 fontStyle->antialiased = antialiased;
79 QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
80 size->handle = handle;
83 static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script)
85 QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
86 QFontDatabasePrivate *db = privateDb();
88 QStringList::iterator i;
89 for (i = retList.begin(); i != retList.end(); ++i) {
90 bool contains = false;
91 for (int j = 0; j < db->count; j++) {
92 QtFontFamily *qtFamily = db->families[j];
93 if (!(i->compare(qtFamily->name,Qt::CaseInsensitive))) {
106 static void initializeDb()
108 static int initialized = false;
111 //init by asking for the platformfontdb for the first time :)
112 QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
117 #ifndef QT_NO_SETTINGS
118 // called from qapplication_qws.cpp
119 void qt_applyFontDatabaseSettings(const QSettings &settings)
122 QFontDatabasePrivate *db = privateDb();
123 for (int i = 0; i < db->count; ++i) {
124 QtFontFamily *family = db->families[i];
125 if (settings.contains(family->name))
126 family->fallbackFamilies = settings.value(family->name).toStringList();
129 if (settings.contains(QLatin1String("Global Fallbacks")))
130 db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList();
132 #endif // QT_NO_SETTINGS
134 static inline void load(const QString & = QString(), int = -1)
140 QFontEngine *loadSingleEngine(int script,
141 const QFontDef &request,
142 QtFontFoundry *foundry,
143 QtFontStyle *style, QtFontSize *size)
148 int pixelSize = size->pixelSize;
149 if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE))
150 pixelSize = request.pixelSize;
152 QFontDef def = request;
153 def.pixelSize = pixelSize;
155 QFontCache::Key key(def,script);
156 QFontEngine *engine = QFontCache::instance()->findEngine(key);
158 QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase();
159 engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle);
161 QFontCache::Key key(def,script);
162 QFontCache::instance()->instance()->insertEngine(key,engine);
169 QFontEngine *loadEngine(int script, const QFontDef &request,
170 QtFontFamily *family, QtFontFoundry *foundry,
171 QtFontStyle *style, QtFontSize *size)
174 QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
175 //make sure that the db has all fallback families
177 && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {
179 if (family && !family->askedForFallback) {
180 QFont::Style fontStyle = QFont::Style(style->key.style);
181 QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
182 if (styleHint == QFont::AnyStyle && request.fixedPitch)
183 styleHint = QFont::TypeWriter;
184 family->fallbackFamilies = fallbackFamilies(family->name,fontStyle,styleHint,QUnicodeTables::Script(script));
186 family->askedForFallback = true;
189 QStringList fallbacks = privateDb()->fallbackFamilies;
190 if (family && !family->fallbackFamilies.isEmpty())
191 fallbacks = family->fallbackFamilies;
193 engine = new QFontEngineMultiQPA(engine, script, fallbacks);
199 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
201 QFontDatabasePrivate *db = privateDb();
203 fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName);
205 db->reregisterAppFonts = true;
208 bool QFontDatabase::removeApplicationFont(int handle)
210 QMutexLocker locker(fontDatabaseMutex());
212 QFontDatabasePrivate *db = privateDb();
213 if (handle < 0 || handle >= db->applicationFonts.count())
216 db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
218 db->reregisterAppFonts = true;
223 bool QFontDatabase::removeAllApplicationFonts()
225 QMutexLocker locker(fontDatabaseMutex());
227 QFontDatabasePrivate *db = privateDb();
228 if (db->applicationFonts.isEmpty())
231 db->applicationFonts.clear();
236 bool QFontDatabase::supportsThreadedFontRendering()
245 QFontDatabase::findFont(int script, const QFontPrivate *fp,
246 const QFontDef &request)
248 QMutexLocker locker(fontDatabaseMutex());
250 const int force_encoding_id = -1;
252 if (!privateDb()->count)
256 QFontCache::Key key(request, script);
257 engine = QFontCache::instance()->findEngine(key);
259 qDebug() << "Cache hit level 1";
263 QString family_name, foundry_name;
265 parseFontName(request.family, foundry_name, family_name);
267 if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
268 engine =new QTestFontEngine(request.pixelSize);
269 engine->fontDef = request;
273 match(script, request, family_name, foundry_name, force_encoding_id, &desc);
274 if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) {
275 engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
277 FM_DEBUG(" NO MATCH FOUND\n");
281 initFontDef(desc, request, &engine->fontDef);
284 QFontDef def = request;
285 if (def.family.isEmpty()) {
286 def.family = fp->request.family;
287 def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
293 if (!request.family.isEmpty()) {
294 QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QFont::StyleHint(request.styleHint),QUnicodeTables::Script(script));
295 for (int i = 0; i < fallbacks.size(); i++) {
296 QFontDef def = request;
297 def.family = fallbacks.at(i);
298 QFontCache::Key key(def,script);
299 engine = QFontCache::instance()->findEngine(key);
302 match(script, def, def.family, QLatin1String(""), 0, &desc);
303 if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) {
306 engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size);
308 initFontDef(desc, def, &engine->fontDef);
316 engine = new QFontEngineBox(request.pixelSize);
318 FM_DEBUG("returning box engine");
321 if (fp && fp->dpi > 0) {
322 engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
324 engine->fontDef.pointSize = request.pointSize;
330 void QFontDatabase::load(const QFontPrivate *d, int script)
332 QFontDef req = d->request;
334 if (req.pixelSize == -1) {
335 req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
336 req.pixelSize = qRound(req.pixelSize);
338 if (req.pointSize < 0)
339 req.pointSize = req.pixelSize*72.0/d->dpi;
341 req.weight = QFont::Normal;
342 if (req.stretch == 0)
345 QFontCache::Key key(req, script);
348 getEngineData(d, key);
350 // the cached engineData could have already loaded the engine we want
351 if (d->engineData->engines[script])
354 QFontEngine *fe = QFontCache::instance()->findEngine(key);
356 // list of families to try
357 QStringList family_list;
359 if (!req.family.isEmpty()) {
360 family_list = familyList(req);
362 // add the default family
363 QString defaultFamily = QApplication::font().family();
364 if (! family_list.contains(defaultFamily))
365 family_list << defaultFamily;
369 // null family means find the first font matching the specified script
370 family_list << QString();
372 QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
373 for (; !fe && it != end; ++it) {
376 fe = QFontDatabase::findFont(script, d, req);
377 if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty())
381 if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
382 for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
383 if (!d->engineData->engines[i]) {
384 d->engineData->engines[i] = fe;
389 d->engineData->engines[script] = fe;