1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "private/qdeclarativefontloader_p.h"
44 #include <qdeclarativecontext.h>
45 #include <qdeclarativeengine.h>
47 #include <QStringList>
50 #include <QNetworkRequest>
51 #include <QNetworkReply>
52 #include <QFontDatabase>
54 #include <private/qobject_p.h>
55 #include <private/qdeclarativeengine_p.h>
56 #include <qdeclarativeinfo.h>
60 #define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16
62 class QDeclarativeFontObject : public QObject
67 QDeclarativeFontObject(int _id);
69 void download(const QUrl &url, QNetworkAccessManager *manager);
72 void fontDownloaded(const QString&, QDeclarativeFontLoader::Status);
84 Q_DISABLE_COPY(QDeclarativeFontObject)
87 QDeclarativeFontObject::QDeclarativeFontObject(int _id = -1)
88 : QObject(0), id(_id), reply(0), redirectCount(0) {}
91 void QDeclarativeFontObject::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 QDeclarativeFontObject::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), QDeclarativeFontLoader::Ready);
121 emit fontDownloaded(QString(), QDeclarativeFontLoader::Error);
123 emit fontDownloaded(QString(), QDeclarativeFontLoader::Error);
125 reply->deleteLater();
131 class QDeclarativeFontLoaderPrivate : public QObjectPrivate
133 Q_DECLARE_PUBLIC(QDeclarativeFontLoader)
136 QDeclarativeFontLoaderPrivate() : status(QDeclarativeFontLoader::Null) {}
140 QDeclarativeFontLoader::Status status;
141 static QHash<QUrl, QDeclarativeFontObject*> fonts;
144 QHash<QUrl, QDeclarativeFontObject*> QDeclarativeFontLoaderPrivate::fonts;
147 \qmlclass FontLoader QDeclarativeFontLoader
148 \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 QDeclarativeFontLoader::QDeclarativeFontLoader(QObject *parent)
173 : QObject(*(new QDeclarativeFontLoaderPrivate), parent)
177 QDeclarativeFontLoader::~QDeclarativeFontLoader()
182 \qmlproperty url FontLoader::source
183 The url of the font to load.
185 QUrl QDeclarativeFontLoader::source() const
187 Q_D(const QDeclarativeFontLoader);
191 void QDeclarativeFontLoader::setSource(const QUrl &url)
193 Q_D(QDeclarativeFontLoader);
196 d->url = qmlContext(this)->resolvedUrl(url);
197 emit sourceChanged();
199 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
200 QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
201 if (!localFile.isEmpty()) {
202 if (!d->fonts.contains(d->url)) {
203 int id = QFontDatabase::addApplicationFont(localFile);
205 updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready);
206 QDeclarativeFontObject *fo = new QDeclarativeFontObject(id);
207 d->fonts[d->url] = fo;
209 updateFontInfo(QString(), Error);
212 updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready);
217 if (!d->fonts.contains(d->url)) {
218 QDeclarativeFontObject *fo = new QDeclarativeFontObject;
219 d->fonts[d->url] = fo;
220 fo->download(d->url, qmlEngine(this)->networkAccessManager());
222 emit statusChanged();
223 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QDeclarativeFontLoader::Status)),
224 this, SLOT(updateFontInfo(QString,QDeclarativeFontLoader::Status)));
226 QDeclarativeFontObject *fo = d->fonts[d->url];
229 emit statusChanged();
230 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QDeclarativeFontLoader::Status)),
231 this, SLOT(updateFontInfo(QString,QDeclarativeFontLoader::Status)));
234 updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready);
239 void QDeclarativeFontLoader::updateFontInfo(const QString& name, QDeclarativeFontLoader::Status status)
241 Q_D(QDeclarativeFontLoader);
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 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 QDeclarativeFontLoader::name() const
281 Q_D(const QDeclarativeFontLoader);
285 void QDeclarativeFontLoader::setName(const QString &name)
287 Q_D(QDeclarativeFontLoader);
293 emit statusChanged();
297 \qmlproperty enumeration FontLoader::status
299 This property holds the status of font loading. It can be one of:
301 \o FontLoader.Null - no font has been set
302 \o FontLoader.Ready - the font has been loaded
303 \o FontLoader.Loading - the font is currently being loaded
304 \o 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 \o Trigger a state change:
313 State { name: 'loaded'; when: loader.status == FontLoader.Ready }
316 \o Implement an \c onStatusChanged signal handler:
320 onStatusChanged: if (loader.status == FontLoader.Ready) console.log('Loaded')
324 \o Bind to the status value:
326 Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' }
330 QDeclarativeFontLoader::Status QDeclarativeFontLoader::status() const
332 Q_D(const QDeclarativeFontLoader);
338 #include <qdeclarativefontloader.moc>