1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qquickfontloader_p.h"
44 #include <qqmlcontext.h>
45 #include <qqmlengine.h>
47 #include <QStringList>
50 #include <QNetworkRequest>
51 #include <QNetworkReply>
52 #include <QFontDatabase>
54 #include <private/qobject_p.h>
60 #define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16
62 class QQuickFontObject : public QObject
67 explicit QQuickFontObject(int _id = -1);
69 void download(const QUrl &url, QNetworkAccessManager *manager);
72 void fontDownloaded(const QString&, QQuickFontLoader::Status);
84 Q_DISABLE_COPY(QQuickFontObject)
87 QQuickFontObject::QQuickFontObject(int _id)
88 : QObject(0), id(_id), reply(0), redirectCount(0) {}
91 void QQuickFontObject::download(const QUrl &url, QNetworkAccessManager *manager)
93 QNetworkRequest req(url);
94 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
95 reply = manager->get(req);
96 QObject::connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
99 void QQuickFontObject::replyFinished()
103 if (redirectCount < FONTLOADER_MAXIMUM_REDIRECT_RECURSION) {
104 QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
105 if (redirect.isValid()) {
106 QUrl url = reply->url().resolved(redirect.toUrl());
107 QNetworkAccessManager *manager = reply->manager();
108 reply->deleteLater();
110 download(url, manager);
116 if (!reply->error()) {
117 id = QFontDatabase::addApplicationFontFromData(reply->readAll());
119 emit fontDownloaded(QFontDatabase::applicationFontFamilies(id).at(0), QQuickFontLoader::Ready);
121 emit fontDownloaded(QString(), QQuickFontLoader::Error);
123 qWarning("%s: Unable to load font '%s': %s", Q_FUNC_INFO,
124 qPrintable(reply->url().toString()), qPrintable(reply->errorString()));
125 emit fontDownloaded(QString(), QQuickFontLoader::Error);
127 reply->deleteLater();
133 class QQuickFontLoaderPrivate : public QObjectPrivate
135 Q_DECLARE_PUBLIC(QQuickFontLoader)
138 QQuickFontLoaderPrivate() : status(QQuickFontLoader::Null) {}
142 QQuickFontLoader::Status status;
143 static QHash<QUrl, QQuickFontObject*> fonts;
146 QHash<QUrl, QQuickFontObject*> QQuickFontLoaderPrivate::fonts;
150 \instantiates QQuickFontLoader
151 \inqmlmodule QtQuick 2
152 \ingroup qtquick-text-utility
153 \brief Allows fonts to be loaded by name or URL
155 The FontLoader type is used to load fonts by name or URL.
157 The \l status indicates when the font has been loaded, which is useful
158 for fonts loaded from remote sources.
165 FontLoader { id: fixedFont; name: "Courier" }
166 FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
168 Text { text: "Fixed-size font"; font.family: fixedFont.name }
169 Text { text: "Fancy font"; font.family: webFont.name }
173 \sa {declarative/text/fonts}{Fonts example}
175 QQuickFontLoader::QQuickFontLoader(QObject *parent)
176 : QObject(*(new QQuickFontLoaderPrivate), parent)
180 QQuickFontLoader::~QQuickFontLoader()
185 \qmlproperty url QtQuick2::FontLoader::source
186 The url of the font to load.
188 QUrl QQuickFontLoader::source() const
190 Q_D(const QQuickFontLoader);
194 void QQuickFontLoader::setSource(const QUrl &url)
196 Q_D(QQuickFontLoader);
200 emit sourceChanged();
202 QString localFile = QQmlFile::urlToLocalFileOrQrc(d->url);
203 if (!localFile.isEmpty()) {
204 if (!d->fonts.contains(d->url)) {
205 int id = QFontDatabase::addApplicationFont(localFile);
207 updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready);
208 QQuickFontObject *fo = new QQuickFontObject(id);
209 d->fonts[d->url] = fo;
211 updateFontInfo(QString(), Error);
214 updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready);
217 if (!d->fonts.contains(d->url)) {
218 QQuickFontObject *fo = new QQuickFontObject;
219 d->fonts[d->url] = fo;
220 fo->download(d->url, qmlEngine(this)->networkAccessManager());
222 emit statusChanged();
223 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
224 this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
226 QQuickFontObject *fo = d->fonts[d->url];
229 emit statusChanged();
230 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
231 this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
234 updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready);
239 void QQuickFontLoader::updateFontInfo(const QString& name, QQuickFontLoader::Status status)
241 Q_D(QQuickFontLoader);
243 if (name != d->name) {
247 if (status != d->status) {
249 qmlInfo(this) << "Cannot load font: \"" << d->url.toString() << '"';
251 emit statusChanged();
256 \qmlproperty string QtQuick2::FontLoader::name
258 This property holds the name of the font family.
259 It is set automatically when a font is loaded using the \c url property.
261 Use this to set the \c font.family property of a \c Text item.
266 width: 200; height: 50
270 source: "http://www.mysite.com/myfont.ttf"
274 font.family: webFont.name
279 QString QQuickFontLoader::name() const
281 Q_D(const QQuickFontLoader);
285 void QQuickFontLoader::setName(const QString &name)
287 Q_D(QQuickFontLoader);
293 emit statusChanged();
297 \qmlproperty enumeration QtQuick2::FontLoader::status
299 This property holds the status of font loading. It can be one of:
301 \li FontLoader.Null - no font has been set
302 \li FontLoader.Ready - the font has been loaded
303 \li FontLoader.Loading - the font is currently being loaded
304 \li FontLoader.Error - an error occurred while loading the font
307 Use this status to provide an update or respond to the status change in some way.
308 For example, you could:
311 \li Trigger a state change:
313 State { name: 'loaded'; when: loader.status == FontLoader.Ready }
316 \li Implement an \c onStatusChanged signal handler:
320 onStatusChanged: if (loader.status == FontLoader.Ready) console.log('Loaded')
324 \li Bind to the status value:
326 Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' }
330 QQuickFontLoader::Status QQuickFontLoader::status() const
332 Q_D(const QQuickFontLoader);
338 #include <qquickfontloader.moc>