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 emit fontDownloaded(QString(), QQuickFontLoader::Error);
125 reply->deleteLater();
131 class QQuickFontLoaderPrivate : public QObjectPrivate
133 Q_DECLARE_PUBLIC(QQuickFontLoader)
136 QQuickFontLoaderPrivate() : status(QQuickFontLoader::Null) {}
140 QQuickFontLoader::Status status;
141 static QHash<QUrl, QQuickFontObject*> fonts;
144 QHash<QUrl, QQuickFontObject*> QQuickFontLoaderPrivate::fonts;
147 \qmlclass FontLoader QQuickFontLoader
148 \inqmlmodule QtQuick 2
149 \ingroup qml-utility-elements
150 \brief The FontLoader element allows fonts to be loaded by name or URL.
152 The FontLoader element is used to load fonts by name or URL.
154 The \l status indicates when the font has been loaded, which is useful
155 for fonts loaded from remote sources.
162 FontLoader { id: fixedFont; name: "Courier" }
163 FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
165 Text { text: "Fixed-size font"; font.family: fixedFont.name }
166 Text { text: "Fancy font"; font.family: webFont.name }
170 \sa {declarative/text/fonts}{Fonts example}
172 QQuickFontLoader::QQuickFontLoader(QObject *parent)
173 : QObject(*(new QQuickFontLoaderPrivate), parent)
177 QQuickFontLoader::~QQuickFontLoader()
182 \qmlproperty url QtQuick2::FontLoader::source
183 The url of the font to load.
185 QUrl QQuickFontLoader::source() const
187 Q_D(const QQuickFontLoader);
191 void QQuickFontLoader::setSource(const QUrl &url)
193 Q_D(QQuickFontLoader);
197 emit sourceChanged();
199 QString localFile = QQmlFile::urlToLocalFileOrQrc(d->url);
200 if (!localFile.isEmpty()) {
201 if (!d->fonts.contains(d->url)) {
202 int id = QFontDatabase::addApplicationFont(localFile);
204 updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready);
205 QQuickFontObject *fo = new QQuickFontObject(id);
206 d->fonts[d->url] = fo;
208 updateFontInfo(QString(), Error);
211 updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready);
214 if (!d->fonts.contains(d->url)) {
215 QQuickFontObject *fo = new QQuickFontObject;
216 d->fonts[d->url] = fo;
217 fo->download(d->url, qmlEngine(this)->networkAccessManager());
219 emit statusChanged();
220 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
221 this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
223 QQuickFontObject *fo = d->fonts[d->url];
226 emit statusChanged();
227 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)),
228 this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status)));
231 updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready);
236 void QQuickFontLoader::updateFontInfo(const QString& name, QQuickFontLoader::Status status)
238 Q_D(QQuickFontLoader);
240 if (name != d->name) {
244 if (status != d->status) {
246 qmlInfo(this) << "Cannot load font: \"" << d->url.toString() << "\"";
248 emit statusChanged();
253 \qmlproperty string QtQuick2::FontLoader::name
255 This property holds the name of the font family.
256 It is set automatically when a font is loaded using the \c url property.
258 Use this to set the \c font.family property of a \c Text item.
263 width: 200; height: 50
267 source: "http://www.mysite.com/myfont.ttf"
271 font.family: webFont.name
276 QString QQuickFontLoader::name() const
278 Q_D(const QQuickFontLoader);
282 void QQuickFontLoader::setName(const QString &name)
284 Q_D(QQuickFontLoader);
290 emit statusChanged();
294 \qmlproperty enumeration QtQuick2::FontLoader::status
296 This property holds the status of font loading. It can be one of:
298 \li FontLoader.Null - no font has been set
299 \li FontLoader.Ready - the font has been loaded
300 \li FontLoader.Loading - the font is currently being loaded
301 \li FontLoader.Error - an error occurred while loading the font
304 Use this status to provide an update or respond to the status change in some way.
305 For example, you could:
308 \li Trigger a state change:
310 State { name: 'loaded'; when: loader.status == FontLoader.Ready }
313 \li Implement an \c onStatusChanged signal handler:
317 onStatusChanged: if (loader.status == FontLoader.Ready) console.log('Loaded')
321 \li Bind to the status value:
323 Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' }
327 QQuickFontLoader::Status QQuickFontLoader::status() const
329 Q_D(const QQuickFontLoader);
335 #include <qquickfontloader.moc>