Export QTextImageHandler and add accessor for image
[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/qguiapplication_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 = QGuiApplicationPrivate::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         QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
113         initialized = true;
114     }
115 }
116
117 static inline void load(const QString & = QString(), int = -1)
118 {
119     initializeDb();
120 }
121
122 static
123 QFontEngine *loadSingleEngine(int script,
124                               const QFontDef &request,
125                               QtFontFoundry *foundry,
126                               QtFontStyle *style, QtFontSize *size)
127 {
128     Q_UNUSED(foundry);
129
130     Q_ASSERT(size);
131     int pixelSize = size->pixelSize;
132     if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE))
133         pixelSize = request.pixelSize;
134
135     QFontDef def = request;
136     def.pixelSize = pixelSize;
137
138     QFontCache::Key key(def,script);
139     QFontEngine *engine = QFontCache::instance()->findEngine(key);
140     if (!engine) {
141         QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
142         engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle);
143         if (engine) {
144             QFontCache::Key key(def,script);
145             QFontCache::instance()->instance()->insertEngine(key,engine);
146         }
147     }
148     return engine;
149 }
150
151 static
152 QFontEngine *loadEngine(int script, const QFontDef &request,
153                         QtFontFamily *family, QtFontFoundry *foundry,
154                         QtFontStyle *style, QtFontSize *size)
155 {
156
157     QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size);
158     //make sure that the db has all fallback families
159     if (engine && engine->type() != QFontEngine::Multi
160         && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) {
161
162         if (family && !family->askedForFallback) {
163             QFont::Style fontStyle = QFont::Style(style->key.style);
164             QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint);
165             if (styleHint == QFont::AnyStyle && request.fixedPitch)
166                 styleHint = QFont::TypeWriter;
167             family->fallbackFamilies = fallbackFamilies(family->name,fontStyle,styleHint,QUnicodeTables::Script(script));
168
169             family->askedForFallback = true;
170         }
171
172         QStringList fallbacks = privateDb()->fallbackFamilies;
173         if (family && !family->fallbackFamilies.isEmpty())
174             fallbacks = family->fallbackFamilies;
175
176         engine = new QFontEngineMultiQPA(engine, script, fallbacks);
177     }
178
179     return engine;
180 }
181
182 static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
183 {
184     QFontDatabasePrivate *db = privateDb();
185
186     fnt->families = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName);
187
188     db->reregisterAppFonts = true;
189 }
190
191 bool QFontDatabase::removeApplicationFont(int handle)
192 {
193     QMutexLocker locker(fontDatabaseMutex());
194
195     QFontDatabasePrivate *db = privateDb();
196     if (handle < 0 || handle >= db->applicationFonts.count())
197         return false;
198
199     db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
200
201     db->reregisterAppFonts = true;
202     db->invalidate();
203     return true;
204 }
205
206 bool QFontDatabase::removeAllApplicationFonts()
207 {
208     QMutexLocker locker(fontDatabaseMutex());
209
210     QFontDatabasePrivate *db = privateDb();
211     if (db->applicationFonts.isEmpty())
212         return false;
213
214     db->applicationFonts.clear();
215     db->invalidate();
216     return true;
217 }
218
219 bool QFontDatabase::supportsThreadedFontRendering()
220 {
221     return true;
222 }
223
224 /*!
225     \internal
226 */
227 QFontEngine *
228 QFontDatabase::findFont(int script, const QFontPrivate *fp,
229                         const QFontDef &request)
230 {
231     QMutexLocker locker(fontDatabaseMutex());
232
233     const int force_encoding_id = -1;
234
235     if (!privateDb()->count)
236         initializeDb();
237
238     QFontEngine *engine;
239     QFontCache::Key key(request, script);
240     engine = QFontCache::instance()->findEngine(key);
241     if (engine) {
242         qDebug() << "Cache hit level 1";
243         return engine;
244     }
245
246     QString family_name, foundry_name;
247
248     parseFontName(request.family, foundry_name, family_name);
249
250     if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) {
251         engine =new QTestFontEngine(request.pixelSize);
252         engine->fontDef = request;
253     }
254
255     QtFontDesc desc;
256     match(script, request, family_name, foundry_name, force_encoding_id, &desc);
257     if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) {
258         engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size);
259     } else {
260         FM_DEBUG("  NO MATCH FOUND\n");
261     }
262
263     if (engine && engine->type() != QFontEngine::TestFontEngine) {
264         initFontDef(desc, request, &engine->fontDef);
265
266         if (fp) {
267             QFontDef def = request;
268             if (def.family.isEmpty()) {
269                 def.family = fp->request.family;
270                 def.family = def.family.left(def.family.indexOf(QLatin1Char(',')));
271             }
272         }
273     }
274
275     if (!engine) {
276         if (!request.family.isEmpty()) {
277             QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QFont::StyleHint(request.styleHint),QUnicodeTables::Script(script));
278             for (int i = 0; !engine && i < fallbacks.size(); i++) {
279                 QFontDef def = request;
280                 def.family = fallbacks.at(i);
281                 QFontCache::Key key(def,script);
282                 engine = QFontCache::instance()->findEngine(key);
283                 if (!engine) {
284                     QtFontDesc desc;
285                     match(script, def, def.family, QLatin1String(""), 0, &desc);
286                     if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) {
287                         continue;
288                     }
289                     engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size);
290                     if (engine) {
291                         initFontDef(desc, def, &engine->fontDef);
292                     }
293                 }
294             }
295         }
296
297         if (!engine)
298             engine = new QFontEngineBox(request.pixelSize);
299
300         FM_DEBUG("returning box engine");
301     }
302
303     if (fp && fp->dpi > 0) {
304         engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi));
305     } else {
306         engine->fontDef.pointSize = request.pointSize;
307     }
308
309     return engine;
310 }
311
312 void QFontDatabase::load(const QFontPrivate *d, int script)
313 {
314     QFontDef req = d->request;
315
316     if (req.pixelSize == -1) {
317         req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100;
318         req.pixelSize = qRound(req.pixelSize);
319     }
320     if (req.pointSize < 0)
321         req.pointSize = req.pixelSize*72.0/d->dpi;
322     if (req.weight == 0)
323         req.weight = QFont::Normal;
324     if (req.stretch == 0)
325         req.stretch = 100;
326
327     QFontCache::Key key(req, script);
328
329     if (!d->engineData)
330         getEngineData(d, key);
331
332     // the cached engineData could have already loaded the engine we want
333     if (d->engineData->engines[script])
334         return;
335
336     QFontEngine *fe = QFontCache::instance()->findEngine(key);
337
338     // list of families to try
339     QStringList family_list;
340
341     if (!req.family.isEmpty()) {
342         family_list = familyList(req);
343
344         // add the default family
345         QString defaultFamily = QGuiApplication::font().family();
346         if (! family_list.contains(defaultFamily))
347             family_list << defaultFamily;
348
349     }
350
351     // null family means find the first font matching the specified script
352     family_list << QString();
353
354     QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
355     for (; !fe && it != end; ++it) {
356         req.family = *it;
357
358         fe = QFontDatabase::findFont(script, d, req);
359         if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty())
360             fe = 0;
361     }
362
363     if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) {
364         for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) {
365             if (!d->engineData->engines[i]) {
366                 d->engineData->engines[i] = fe;
367                 fe->ref.ref();
368             }
369         }
370     } else {
371         d->engineData->engines[script] = fe;
372         fe->ref.ref();
373     }
374 }
375
376 QT_END_NAMESPACE