Support specifying fallbacks in font request on QPA
[profile/ivi/qtbase.git] / src / gui / text / qplatformfontdatabase_qpa.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qplatformfontdatabase.h"
43 #include <QtGui/private/qfontengine_p.h>
44 #include <QtGui/private/qfontengine_qpa_p.h>
45 #include <QtCore/QLibraryInfo>
46 #include <QtCore/QDir>
47
48 QT_BEGIN_NAMESPACE
49
50 extern void qt_registerFont(const QString &familyname, const QString &foundryname, int weight,
51                             QFont::Style style, int stretch, bool antialiased,
52                             bool scalable, int pixelSize, bool fixedPitch,
53                             const QSupportedWritingSystems &writingSystems, void *hanlde);
54
55 /*!
56     \fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
57
58     Registers the pre-rendered QPF2 font contained in the given \a dataArray.
59
60     \sa registerFont()
61 */
62 void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
63 {
64     if (dataArray.size() == 0)
65         return;
66
67     const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
68     if (QFontEngineQPA::verifyHeader(data, dataArray.size())) {
69         QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString();
70         int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt();
71         QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight);
72         QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style);
73         QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray();
74
75         if (!fontName.isEmpty() && pixelSize) {
76             QFont::Weight fontWeight = QFont::Normal;
77             if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt)
78                 fontWeight = QFont::Weight(weight.toInt());
79
80             QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt());
81
82             QSupportedWritingSystems writingSystems;
83             for (int i = 0; i < writingSystemBits.count(); ++i) {
84                 uchar currentByte = writingSystemBits.at(i);
85                 for (int j = 0; j < 8; ++j) {
86                     if (currentByte & 1)
87                         writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j));
88                     currentByte >>= 1;
89                 }
90             }
91             QFont::Stretch stretch = QFont::Unstretched;
92             registerFont(fontName,QString(),fontWeight,fontStyle,stretch,true,false,pixelSize,false,writingSystems,handle);
93         }
94     } else {
95         qDebug() << "header verification of QPF2 font failed. maybe it is corrupt?";
96     }
97 }
98
99 /*!
100     Registers a font with the given set of attributes describing the font's
101     foundry, family name, style and stretch information, pixel size, and
102     supported writing systems. Additional information about whether the font
103     can be scaled and antialiased can also be provided.
104
105     The foundry name and font family are described by \a foundryName and
106     \a familyName. The font weight (light, normal, bold, etc.), style (normal,
107     oblique, italic) and stretch information (condensed, expanded, unstretched,
108     etc.) are specified by \a weight, \a style and \a stretch.
109
110     Some fonts can be antialiased and scaled; \a scalable and \a antialiased
111     can be set to true for fonts with these attributes. The intended pixel
112     size of non-scalable fonts is specified by \a pixelSize; this value will be
113     ignored for scalable fonts.
114
115     The writing systems supported by the font are specified by the
116     \a writingSystems argument.
117
118     \sa registerQPF2Font()
119 */
120 void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &foundryname, QFont::Weight weight,
121                                          QFont::Style style, QFont::Stretch stretch, bool antialiased,
122                                          bool scalable, int pixelSize, bool fixedPitch,
123                                          const QSupportedWritingSystems &writingSystems, void *usrPtr)
124 {
125     if (scalable)
126         pixelSize = 0;
127
128     qt_registerFont(familyname, foundryname, weight, style,
129                     stretch, antialiased, scalable, pixelSize,
130                     fixedPitch, writingSystems, usrPtr);
131 }
132
133 class QWritingSystemsPrivate
134 {
135 public:
136     QWritingSystemsPrivate()
137         : ref(1)
138         , vector(QFontDatabase::WritingSystemsCount,false)
139     {
140     }
141
142     QWritingSystemsPrivate(const QWritingSystemsPrivate *other)
143         : ref(1)
144         , vector(other->vector)
145     {
146     }
147
148     QAtomicInt ref;
149     QVector<bool> vector;
150 };
151
152 /*!
153     Constructs a new object to handle supported writing systems.
154 */
155 QSupportedWritingSystems::QSupportedWritingSystems()
156 {
157     d = new QWritingSystemsPrivate;
158 }
159
160 /*!
161     Constructs a copy of the \a other writing systems object.
162 */
163 QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other)
164 {
165     d = other.d;
166     d->ref.ref();
167 }
168
169 /*!
170     Constructs a copy of the \a other writing systems object.
171 */
172 QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other)
173 {
174     if (d != other.d) {
175         other.d->ref.ref();
176         if (!d->ref.deref())
177             delete d;
178         d = other.d;
179     }
180     return *this;
181 }
182
183 /*!
184     Destroys the supported writing systems object.
185 */
186 QSupportedWritingSystems::~QSupportedWritingSystems()
187 {
188     if (!d->ref.deref())
189         delete d;
190 }
191
192 /*!
193     \internal
194 */
195 void QSupportedWritingSystems::detach()
196 {
197     if (d->ref.load() != 1) {
198         QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d);
199         if (!d->ref.deref())
200             delete d;
201         d = newd;
202     }
203 }
204
205 /*!
206     Sets or clears support for the specified \a writingSystem based on the
207     value given by \a support.
208 */
209 void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support)
210 {
211     detach();
212     d->vector[writingSystem] = support;
213 }
214
215 /*!
216     Returns true if the writing system specified by \a writingSystem is
217     supported; otherwise returns false.
218 */
219 bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const
220 {
221     return d->vector.at(writingSystem);
222 }
223
224 /*!
225     \class QSupportedWritingSystems
226     \brief The QSupportedWritingSystems class is used when registering fonts with the internal Qt
227     fontdatabase
228     \ingroup painting
229
230     Its to provide an easy to use interface for indicating what writing systems a specific font
231     supports.
232
233 */
234
235 /*!
236     \internal
237  */
238 QPlatformFontDatabase::~QPlatformFontDatabase()
239 {
240 }
241
242 /*!
243   This function is called once at startup by Qt's internal font database.
244   Reimplement this function in a subclass for a convenient place to initialize
245   the internal font database.
246
247   The default implementation looks in the fontDir() location and registers all
248   QPF2 fonts.
249 */
250 void QPlatformFontDatabase::populateFontDatabase()
251 {
252     QString fontpath = fontDir();
253     if(!QFile::exists(fontpath)) {
254         qWarning("QFontDatabase: Cannot find font directory '%s' - is Qt installed correctly?",
255                  qPrintable(QDir::toNativeSeparators(fontpath)));
256         return;
257     }
258
259     QDir dir(fontpath);
260     dir.setNameFilters(QStringList() << QLatin1String("*.qpf2"));
261     dir.refresh();
262     for (int i = 0; i < int(dir.count()); ++i) {
263         const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
264         QFile file(QString::fromLocal8Bit(fileName));
265         if (file.open(QFile::ReadOnly)) {
266             const QByteArray fileData = file.readAll();
267             QByteArray *fileDataPtr = new QByteArray(fileData);
268             registerQPF2Font(fileData, fileDataPtr);
269         }
270     }
271 }
272
273 /*!
274     Returns a multi font engine in the specified \a script to encapsulate \a fontEngine with the
275     option to fall back to to the fonts given by \a fallbacks if \a fontEngine does not support
276     a certain character.
277 */
278 QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine,
279                                                          QUnicodeTables::Script script)
280 {
281     return new QFontEngineMultiQPA(fontEngine, script);
282 }
283
284 /*!
285     Returns the font engine that can be used to render the font described by
286     the font definition, \a fontDef, in the specified \a script.
287 */
288 QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle)
289 {
290     Q_UNUSED(script);
291     Q_UNUSED(handle);
292     QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
293     QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr);
294     //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script;
295     return engine;
296 }
297
298 QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
299                                                QFont::HintingPreference hintingPreference)
300 {
301     Q_UNUSED(fontData);
302     Q_UNUSED(pixelSize);
303     Q_UNUSED(hintingPreference);
304     qWarning("This plugin does not support font engines created directly from font data");
305     return 0;
306 }
307
308 /*!
309     Returns a list of alternative fonts for the specified \a family and
310     \a style and \a script using the \a styleHint given.
311 */
312 QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
313 {
314     Q_UNUSED(family);
315     Q_UNUSED(style);
316     Q_UNUSED(styleHint);
317     Q_UNUSED(script);
318     return QStringList();
319 }
320
321 /*!
322     Adds an application font described by the font contained supplied \a fontData
323     or using the font contained in the file referenced by \a fileName. Returns
324     a list of family names, or an empty list if the font could not be added.
325
326     \note The default implementation of this function does not add an application
327     font. Subclasses should reimplement this function to perform the necessary
328     loading and registration of fonts.
329 */
330 QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
331 {
332     Q_UNUSED(fontData);
333     Q_UNUSED(fileName);
334
335     qWarning("This plugin does not support application fonts");
336     return QStringList();
337 }
338
339 /*!
340     Releases the specified font \a handle.
341 */
342 void QPlatformFontDatabase::releaseHandle(void *handle)
343 {
344     QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
345     delete fileDataPtr;
346 }
347
348 /*!
349     Returns the directory containing the fonts used by the database.
350 */
351 QString QPlatformFontDatabase::fontDir() const
352 {
353     QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR"));
354     if (fontpath.isEmpty()) {
355 #ifndef QT_NO_SETTINGS
356         fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath);
357         fontpath += QLatin1String("/fonts");
358 #endif
359     }
360
361     return fontpath;
362 }
363
364 /*!
365     Returns the default system font.
366
367     \sa QGuiApplication::font()
368     \since 5.0
369 */
370
371 QFont QPlatformFontDatabase::defaultFont() const
372 {
373     return QFont(QLatin1String("Helvetica"));
374 }
375
376 /*!
377     Resolve alias to actual font family names.
378
379     \since 5.0
380  */
381
382 QString QPlatformFontDatabase::resolveFontFamilyAlias(const QString &family) const
383 {
384     return family;
385 }
386
387 /*!
388     Return true if all fonts are considered scalable when using this font database.
389     Defaults to false.
390
391     \since 5.0
392  */
393
394 bool QPlatformFontDatabase::fontsAlwaysScalable() const
395 {
396     return false;
397 }
398
399 /*!
400     Return list of standard font sizes when using this font database.
401
402     \since 5.0
403  */
404
405  QList<int> QPlatformFontDatabase::standardSizes() const
406 {
407     QList<int> ret;
408     static const unsigned short standard[] =
409         { 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 };
410     ret.reserve(int(sizeof(standard) / sizeof(standard[0])));
411     const unsigned short *sizes = standard;
412     while (*sizes) ret << *sizes++;
413     return ret;
414 }
415
416 /*!
417     \class QPlatformFontDatabase
418     \since 5.0
419     \internal
420     \preliminary
421     \ingroup qpa
422     \ingroup painting
423
424     \brief The QPlatformFontDatabase class makes it possible to customize how fonts
425     are discovered and how they are rendered
426
427     QPlatformFontDatabase is the superclass which is intended to let platform implementations use
428     native font handling.
429
430     Qt has its internal font database which it uses to discover available fonts on the
431     user's system. To be able to populate this database subclass this class, and
432     reimplement populateFontDatabase().
433
434     Use the function registerFont() to populate the internal font database.
435
436     Sometimes a specified font does not have the required glyphs; in such a case, the
437     fallbackForFamily() function is called automatically to find alternative font
438     families that can supply alternatives to the missing glyphs.
439
440     \sa QSupportedWritingSystems
441 */
442 QT_END_NAMESPACE