1
/****************************************************************************
2
**
3
** Copyright (C) 2012 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 "qplatformfontdatabase_qpa.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,bool scalable, int pixelSize,
52
                                         const QSupportedWritingSystems &writingSystems, void *hanlde);
53
54
/*!
55
    \fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *)
56
57
    Registers the pre-rendered QPF2 font contained in the given \a dataArray.
58
59
    \sa registerFont()
60
*/
61
void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
62
{
63
    if (dataArray.size() == 0)
64
        return;
65
66
    const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData());
67
    if (QFontEngineQPA::verifyHeader(data, dataArray.size())) {
68
        QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString();
69
        int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt();
70
        QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight);
71
        QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style);
72
        QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray();
73
74
        if (!fontName.isEmpty() && pixelSize) {
75
            QFont::Weight fontWeight = QFont::Normal;
76
            if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt)
77
                fontWeight = QFont::Weight(weight.toInt());
78
79
            QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt());
80
81
            QSupportedWritingSystems writingSystems;
82
            for (int i = 0; i < writingSystemBits.count(); ++i) {
83
                uchar currentByte = writingSystemBits.at(i);
84
                for (int j = 0; j < 8; ++j) {
85
                    if (currentByte & 1)
86
                        writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j));
87
                    currentByte >>= 1;
88
                }
89
            }
90
            QFont::Stretch stretch = QFont::Unstretched;
91
            registerFont(fontName,QString(),fontWeight,fontStyle,stretch,true,false,pixelSize,writingSystems,handle);
92
        }
93
    } else {
94
        qDebug() << "header verification of QPF2 font failed. maybe it is corrupt?";
95
    }
96
}
97
98
/*!
99
    \fn void QPlatformFontDatabase::registerFont(const QString &familyName,
100
        const QString &foundryName, QFont::Weight weight, QFont::Style style,
101
        QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize,
102
        const QSupportedWritingSystems &writingSystems, void *usrPtr)
103
104
    Registers a font with the given set of attributes describing the font's
105
    foundry, family name, style and stretch information, pixel size, and
106
    supported writing systems. Additional information about whether the font
107
    can be scaled and antialiased can also be provided.
108
109
    The foundry name and font family are described by \a foundryName and
110
    \a familyName. The font weight (light, normal, bold, etc.), style (normal,
111
    oblique, italic) and stretch information (condensed, expanded, unstretched,
112
    etc.) are specified by \a weight, \a style and \a stretch.
113
114
    Some fonts can be antialiased and scaled; \a scalable and \a antialiased
115
    can be set to true for fonts with these attributes. The intended pixel
116
    size of non-scalable fonts is specified by \a pixelSize; this value will be
117
    ignored for scalable fonts.
118
119
    The writing systems supported by the font are specified by the
120
    \a writingSystems argument.
121
122
    \sa registerQPF2Font()
123
*/
124
void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &foundryname, QFont::Weight weight,
125
                                         QFont::Style style, QFont::Stretch stretch, bool antialiased, bool scalable, int pixelSize,
126
                                         const QSupportedWritingSystems &writingSystems, void *usrPtr)
127
{
128
    if (scalable)
129
        pixelSize = 0;
130
    qt_registerFont(familyname,foundryname,weight,style,stretch,antialiased,scalable,pixelSize,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
QSupportedWritingSystems::QSupportedWritingSystems()
153
{
154
    d = new QWritingSystemsPrivate;
155
}
156
157
QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other)
158
{
159
    d = other.d;
160
    d->ref.ref();
161
}
162
163
/*!
164
    Assigns the \a other supported writing systems object to this object.
165
*/
166
QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other)
167
{
168
    if (d != other.d) {
169
        other.d->ref.ref();
170
        if (!d->ref.deref())
171
            delete d;
172
        d = other.d;
173
    }
174
    return *this;
175
}
176
177
/*!
178
    Destroys the object.
179
*/
180
QSupportedWritingSystems::~QSupportedWritingSystems()
181
{
182
    if (!d->ref.deref())
183
        delete d;
184
}
185
186
void QSupportedWritingSystems::detach()
187
{
188
    if (d->ref != 1) {
189
        QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d);
190
        if (!d->ref.deref())
191
            delete d;
192
        d = newd;
193
    }
194
}
195
196
/*!
197
    Sets the supported state of the writing system given by \a writingSystem to
198
    the value specified by \a support. A value of true indicates that the
199
    writing system is supported; a value of false indicates that it is
200
    unsupported.
201
202
    \sa supported()
203
*/
204
void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support)
205
{
206
    detach();
207
    d->vector[writingSystem] = support;
208
}
209
210
/*!
211
    Returns true if the writing system given by \a writingSystem is supported;
212
    otherwise returns false.
213
214
    \sa setSupported()
215
*/
216
bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const
217
{
218
    return d->vector.at(writingSystem);
219
}
220
221
/*!
222
    \class QSupportedWritingSystems
223
    \brief The QSupportedWritingSystems class is used when registering fonts with the internal Qt
224
    fontdatabase
225
    \ingroup painting
226
    \since 4.8
227
228
    Its to provide an easy to use interface for indicating what writing systems a specific font
229
    supports.
230
231
*/
232
233
/*!
234
  This function is called once at startup by Qts internal fontdatabase. Reimplement this function
235
  in a subclass for a convenient place to initialise the internal fontdatabase.
236
237
  The default implementation looks in the fontDir() location and registers all qpf2 fonts.
238
*/
239
void QPlatformFontDatabase::populateFontDatabase()
240
{
241
    QString fontpath = fontDir();
242
243
    if(!QFile::exists(fontpath)) {
244
        qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?",
245
               qPrintable(fontpath));
246
    }
247
248
    QDir dir(fontpath);
249
    dir.setNameFilters(QStringList() << QLatin1String("*.qpf2"));
250
    dir.refresh();
251
    for (int i = 0; i < int(dir.count()); ++i) {
252
        const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
253
        QFile file(QString::fromLocal8Bit(fileName));
254
        if (file.open(QFile::ReadOnly)) {
255
            const QByteArray fileData = file.readAll();
256
            QByteArray *fileDataPtr = new QByteArray(fileData);
257
            registerQPF2Font(fileData, fileDataPtr);
258
        }
259
    }
260
}
261
262
/*!
263
    Returns the font engine that can be used to render the font described by
264
    the font definition, \a fontDef, in the specified \a script.
265
*/
266
QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle)
267
{
268
    Q_UNUSED(script);
269
    Q_UNUSED(handle);
270
    QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
271
    QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr);
272
    //qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script;
273
    return engine;
274
}
275
276
QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
277
                                               QFont::HintingPreference hintingPreference)
278
{
279
    Q_UNUSED(fontData);
280
    Q_UNUSED(pixelSize);
281
    Q_UNUSED(hintingPreference);
282
    qWarning("This plugin does not support font engines created directly from font data");
283
    return 0;
284
}
285
286
/*!
287
    Returns a list of alternative fonts for the specified \a family and
288
    \a style and \a script using the \a styleHint given.
289
*/
290
QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const
291
{
292
    Q_UNUSED(family);
293
    Q_UNUSED(style);
294
    Q_UNUSED(styleHint);
295
    Q_UNUSED(script);
296
    return QStringList();
297
}
298
299
/*!
300
    Adds an application font described by the font contained supplied \a fontData
301
    or using the font contained in the file referenced by \a fileName. Returns
302
    a list of family names, or an empty list if the font could not be added.
303
304
    \note The default implementation of this function does not add an application
305
    font. Subclasses should reimplement this function to perform the necessary
306
    loading and registration of fonts.
307
*/
308
QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
309
{
310
    Q_UNUSED(fontData);
311
    Q_UNUSED(fileName);
312
313
    qWarning("This plugin does not support application fonts");
314
    return QStringList();
315
}
316
317
/*!
318
    Releases the font handle and deletes any associated data loaded from a file.
319
*/
320
void QPlatformFontDatabase::releaseHandle(void *handle)
321
{
322
    QByteArray *fileDataPtr = static_cast<QByteArray *>(handle);
323
    delete fileDataPtr;
324
}
325
326
/*!
327
    Returns the path to the font directory.
328
329
    The font directory is stored in the general Qt settings unless it has been
330
    overridden by the \c QT_QPA_FONTDIR environment variable.
331
332
    When using builds of Qt that do not support settings, the \c QT_QPA_FONTDIR
333
    environment variable is the only way to specify the font directory.
334
*/
335
QString QPlatformFontDatabase::fontDir() const
336
{
337
    QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR"));
338
    if (fontpath.isEmpty()) {
339
#ifndef QT_NO_SETTINGS
340
        fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath);
341
        fontpath += QLatin1String("/fonts");
342
#endif
343
    }
344
345
    return fontpath;
346
}
347
348
/*!
349
    \class QPlatformFontDatabase
350
    \brief The QPlatformFontDatabase class makes it possible to customize how fonts
351
    are discovered and how they are rendered
352
    \since 4.8
353
354
    \ingroup painting
355
356
    QPlatformFontDatabase is the superclass which is intended to let platform implementations use
357
    native font handling.
358
359
    Qt has its internal font database which it uses to discover available fonts on the
360
    user's system. To be able to populate this database subclass this class, and
361
    reimplement populateFontDatabase().
362
363
    Use the function registerFont() to populate the internal font database.
364
365
    Sometimes a specified font does not have the required glyphs; in such a case, the
366
    fallbackForFamily() function is called automatically to find alternative font
367
    families that can supply alternatives to the missing glyphs.
368
369
    \sa QSupportedWritingSystems
370
*/
371
QT_END_NAMESPACE