Fix uses of qRound on non-floating-point types.
[profile/ivi/qtbase.git] / src / gui / text / qfontdatabase_qpa.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qlibraryinfo.h"
43 #include <QtCore/qsettings.h>
44
45 #include "qfontengine_qpa_p.h"
46 #include "qplatformdefs.h"
47
48 #include <QtGui/private/qapplication_p.h>
49 #include <QtGui/qplatformfontdatabase_qpa.h>
50
51 #include <QtCore/qmath.h>
52
53 QT_BEGIN_NAMESPACE
54
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)
58 {
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);
66
67         for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
68             if (writingSystems.supported(QFontDatabase::WritingSystem(i))) {
69                 f->writingSystems[i] = QtFontFamily::Supported;
70             } else {
71                 f->writingSystems[i] = QtFontFamily::Unsupported;
72             }
73         }
74
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;
81 }
82
83 static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script)
84 {
85     QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
86     QFontDatabasePrivate *db = privateDb();
87
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))) {
94                 contains = true;
95                 break;
96             }
97         }
98         if (!contains) {
99             i = retList.erase(i);
100             i--;
101         }
102     }
103     return retList;
104 }
105
106 static void initializeDb()
107 {
108     static int initialized = false;
109
110     if (!initialized) {
111         //init by asking for the platformfontdb for the first time :)
112         QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
113         initialized = true;
114     }
115 }
116
117 #ifndef QT_NO_SETTINGS
118 // called from qapplication_qws.cpp
119 void qt_applyFontDatabaseSettings(const QSettings &settings)
120 {
121     initializeDb();
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();
127     }
128
129     if (settings.contains(QLatin1String("Global Fallbacks")))
130         db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList();
131 }
132 #endif // QT_NO_SETTINGS
133
134 static inline void load(const QString & = QString(), int = -1)
135 {
136     initializeDb();
137 }
138
139 static
140 QFontEngine *loadSingleEngine(int script,
141                               const QFontDef &request,
142                               QtFontFoundry *foundry,
143                               QtFontStyle *style, QtFontSize *size)
144 {
145     Q_UNUSED(foundry);
146
147     Q_ASSERT(size);
148     int pixelSize = size->pixelSize;
149     if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE))
150         pixelSize = request.pixelSize;
151
152     QFontDef def = request;
153     def.pixelSize = pixelSize;
154
155     QFontCache::Key key(def,script);
156     QFontEngine *engine = QFontCache::instance()->findEngine(key);
157     if (!engine) {
158         QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase();
159         engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle);
160         if (engine) {
161             QFontCache::Key key(def,script);
162             QFontCache::instance()->instance()->insertEngine(key,engine);
163         }
164     }
165     return engine;
166 }
167
168 static
169 QFontEngine *loadEngine(int script, const QFontDef &request,
170                         QtFontFamily *family, QtFontFoundry *foundry,
171                         QtFontStyle *style, QtFontSize *size)
172 {
173
174     QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
175     //make sure that the db has all fallback families
176     if (engine
177         && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {
178
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));
185
186             family->askedForFallback = true;
187         }
188
189         QStringList fallbacks = privateDb()->fallbackFamilies;
190         if (family && !family->fallbackFamilies.isEmpty())
191             fallbacks = family->fallbackFamilies;
192
193         engine = new QFontEngineMultiQPA(engine, script, fallbacks);
194     }
195
196     return engine;
197 }
198
199 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
200 {
201     QFontDatabasePrivate *db = privateDb();
202
203     fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName);
204
205     db->reregisterAppFonts = true;
206 }
207
208 bool QFontDatabase::removeApplicationFont(int handle)
209 {
210     QMutexLocker locker(fontDatabaseMutex());
211
212     QFontDatabasePrivate *db = privateDb();
213     if (handle < 0 || handle >= db->applicationFonts.count())
214         return false;
215
216     db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
217
218     db->reregisterAppFonts = true;
219     db->invalidate();
220     return true;
221 }
222
223 bool QFontDatabase::removeAllApplicationFonts()
224 {
225     QMutexLocker locker(fontDatabaseMutex());
226
227     QFontDatabasePrivate *db = privateDb();
228     if (db->applicationFonts.isEmpty())
229         return false;
230
231     db->applicationFonts.clear();
232     db->invalidate();
233     return true;
234 }
235
236 bool QFontDatabase::supportsThreadedFontRendering()
237 {
238     return true;
239 }
240
241 /*!
242     \internal
243 */
244 QFontEngine *
245 QFontDatabase::findFont(int script, const QFontPrivate *fp,
246                         const QFontDef &request)
247 {
248     QMutexLocker locker(fontDatabaseMutex());
249
250     const int force_encoding_id = -1;
251
252     if (!privateDb()->count)
253         initializeDb();
254
255     QFontEngine *engine;
256     QFontCache::Key key(request, script);
257     engine = QFontCache::instance()->findEngine(key);
258     if (engine) {
259         qDebug() << "Cache hit level 1";
260         return engine;
261     }
262
263     QString family_name, foundry_name;
264
265     parseFontName(request.family, foundry_name, family_name);
266
267     if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
268         engine =new QTestFontEngine(request.pixelSize);
269         engine->fontDef = request;
270     }
271
272     QtFontDesc desc;
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);
276     } else {
277         FM_DEBUG("  NO MATCH FOUND\n");
278     }
279
280     if (engine) {
281         initFontDef(desc, request, &engine->fontDef);
282
283         if (fp) {
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(',')));
288             }
289         }
290     }
291
292     if (!engine) {
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);
300                 if (!engine) {
301                     QtFontDesc desc;
302                     match(script, def, def.family, QLatin1String(""), 0, &desc);
303                     if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) {
304                         continue;
305                     }
306                     engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size);
307                     if (engine) {
308                         initFontDef(desc, def, &engine->fontDef);
309                         break;
310                     }
311                 }
312             }
313         }
314
315         if (!engine)
316             engine = new QFontEngineBox(request.pixelSize);
317
318         FM_DEBUG("returning box engine");
319     }
320
321     if (fp && fp->dpi > 0) {
322         engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
323     } else {
324         engine->fontDef.pointSize = request.pointSize;
325     }
326
327     return engine;
328 }
329
330 void QFontDatabase::load(const QFontPrivate *d, int script)
331 {
332     QFontDef req = d->request;
333
334     if (req.pixelSize == -1) {
335         req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
336         req.pixelSize = qRound(req.pixelSize);
337     }
338     if (req.pointSize < 0)
339         req.pointSize = req.pixelSize*72.0/d->dpi;
340     if (req.weight == 0)
341         req.weight = QFont::Normal;
342     if (req.stretch == 0)
343         req.stretch = 100;
344
345     QFontCache::Key key(req, script);
346
347     if (!d->engineData)
348         getEngineData(d, key);
349
350     // the cached engineData could have already loaded the engine we want
351     if (d->engineData->engines[script])
352         return;
353
354     QFontEngine *fe = QFontCache::instance()->findEngine(key);
355
356     // list of families to try
357     QStringList family_list;
358
359     if (!req.family.isEmpty()) {
360         family_list = familyList(req);
361
362         // add the default family
363         QString defaultFamily = QApplication::font().family();
364         if (! family_list.contains(defaultFamily))
365             family_list << defaultFamily;
366
367     }
368
369     // null family means find the first font matching the specified script
370     family_list << QString();
371
372     QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
373     for (; !fe && it != end; ++it) {
374         req.family = *it;
375
376         fe = QFontDatabase::findFont(script, d, req);
377         if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty())
378             fe = 0;
379     }
380
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;
385                 fe->ref.ref();
386             }
387         }
388     } else {
389         d->engineData->engines[script] = fe;
390         fe->ref.ref();
391     }
392 }
393
394 QT_END_NAMESPACE