source: trunk/src/declarative/util/qdeclarativefontloader.cpp@ 1119

Last change on this file since 1119 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 10.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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 QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
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.
23**
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.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativefontloader_p.h"
43
44#include <qdeclarativecontext.h>
45#include <qdeclarativeengine.h>
46
47#include <QStringList>
48#include <QUrl>
49#include <QDebug>
50#include <QNetworkRequest>
51#include <QNetworkReply>
52#include <QFontDatabase>
53
54#include <private/qobject_p.h>
55#include <private/qdeclarativeengine_p.h>
56#include <qdeclarativeinfo.h>
57
58QT_BEGIN_NAMESPACE
59
60#define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16
61
62class QDeclarativeFontObject : public QObject
63{
64Q_OBJECT
65
66public:
67 QDeclarativeFontObject(int _id);
68
69 void download(const QUrl &url, QNetworkAccessManager *manager);
70
71Q_SIGNALS:
72 void fontDownloaded(const QString&, QDeclarativeFontLoader::Status);
73
74private Q_SLOTS:
75 void replyFinished();
76
77public:
78 int id;
79
80private:
81 QNetworkReply *reply;
82 int redirectCount;
83
84 Q_DISABLE_COPY(QDeclarativeFontObject)
85};
86
87QDeclarativeFontObject::QDeclarativeFontObject(int _id = -1)
88 : QObject(0), id(_id), reply(0), redirectCount(0) {}
89
90
91void QDeclarativeFontObject::download(const QUrl &url, QNetworkAccessManager *manager)
92{
93 QNetworkRequest req(url);
94 req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
95 reply = manager->get(req);
96 QObject::connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
97}
98
99void QDeclarativeFontObject::replyFinished()
100{
101 if (reply) {
102 redirectCount++;
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();
109 reply = 0;
110 download(url, manager);
111 return;
112 }
113 }
114 redirectCount = 0;
115
116 if (!reply->error()) {
117 id = QFontDatabase::addApplicationFontFromData(reply->readAll());
118 if (id != -1)
119 emit fontDownloaded(QFontDatabase::applicationFontFamilies(id).at(0), QDeclarativeFontLoader::Ready);
120 else
121 emit fontDownloaded(QString(), QDeclarativeFontLoader::Error);
122 } else {
123 emit fontDownloaded(QString(), QDeclarativeFontLoader::Error);
124 }
125 reply->deleteLater();
126 reply = 0;
127 }
128}
129
130
131class QDeclarativeFontLoaderPrivate : public QObjectPrivate
132{
133 Q_DECLARE_PUBLIC(QDeclarativeFontLoader)
134
135public:
136 QDeclarativeFontLoaderPrivate() : status(QDeclarativeFontLoader::Null) {}
137
138 QUrl url;
139 QString name;
140 QDeclarativeFontLoader::Status status;
141 static QHash<QUrl, QDeclarativeFontObject*> fonts;
142};
143
144QHash<QUrl, QDeclarativeFontObject*> QDeclarativeFontLoaderPrivate::fonts;
145
146/*!
147 \qmlclass FontLoader QDeclarativeFontLoader
148 \ingroup qml-utility-elements
149 \since 4.7
150 \brief The FontLoader element allows fonts to be loaded by name or URL.
151
152 The FontLoader element is used to load fonts by name or URL.
153
154 The \l status indicates when the font has been loaded, which is useful
155 for fonts loaded from remote sources.
156
157 For example:
158 \qml
159 import QtQuick 1.0
160
161 Column {
162 FontLoader { id: fixedFont; name: "Courier" }
163 FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
164
165 Text { text: "Fixed-size font"; font.family: fixedFont.name }
166 Text { text: "Fancy font"; font.family: webFont.name }
167 }
168 \endqml
169
170 \sa {declarative/text/fonts}{Fonts example}
171*/
172QDeclarativeFontLoader::QDeclarativeFontLoader(QObject *parent)
173 : QObject(*(new QDeclarativeFontLoaderPrivate), parent)
174{
175}
176
177QDeclarativeFontLoader::~QDeclarativeFontLoader()
178{
179}
180
181/*!
182 \qmlproperty url FontLoader::source
183 The url of the font to load.
184*/
185QUrl QDeclarativeFontLoader::source() const
186{
187 Q_D(const QDeclarativeFontLoader);
188 return d->url;
189}
190
191void QDeclarativeFontLoader::setSource(const QUrl &url)
192{
193 Q_D(QDeclarativeFontLoader);
194 if (url == d->url)
195 return;
196 d->url = qmlContext(this)->resolvedUrl(url);
197 emit sourceChanged();
198
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);
204 if (id != -1) {
205 updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready);
206 QDeclarativeFontObject *fo = new QDeclarativeFontObject(id);
207 d->fonts[d->url] = fo;
208 } else {
209 updateFontInfo(QString(), Error);
210 }
211 } else {
212 updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready);
213 }
214 } else
215#endif
216 {
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());
221 d->status = Loading;
222 emit statusChanged();
223 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QDeclarativeFontLoader::Status)),
224 this, SLOT(updateFontInfo(QString,QDeclarativeFontLoader::Status)));
225 } else {
226 QDeclarativeFontObject *fo = d->fonts[d->url];
227 if (fo->id == -1) {
228 d->status = Loading;
229 emit statusChanged();
230 QObject::connect(fo, SIGNAL(fontDownloaded(QString,QDeclarativeFontLoader::Status)),
231 this, SLOT(updateFontInfo(QString,QDeclarativeFontLoader::Status)));
232 }
233 else
234 updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready);
235 }
236 }
237}
238
239void QDeclarativeFontLoader::updateFontInfo(const QString& name, QDeclarativeFontLoader::Status status)
240{
241 Q_D(QDeclarativeFontLoader);
242
243 if (name != d->name) {
244 d->name = name;
245 emit nameChanged();
246 }
247 if (status != d->status) {
248 if (status == Error)
249 qmlInfo(this) << "Cannot load font: \"" << d->url.toString() << "\"";
250 d->status = status;
251 emit statusChanged();
252 }
253}
254
255/*!
256 \qmlproperty string FontLoader::name
257
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.
260
261 Use this to set the \c font.family property of a \c Text item.
262
263 Example:
264 \qml
265 FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
266 Text { text: "Fancy font"; font.family: webFont.name }
267 \endqml
268*/
269QString QDeclarativeFontLoader::name() const
270{
271 Q_D(const QDeclarativeFontLoader);
272 return d->name;
273}
274
275void QDeclarativeFontLoader::setName(const QString &name)
276{
277 Q_D(QDeclarativeFontLoader);
278 if (d->name == name)
279 return;
280 d->name = name;
281 emit nameChanged();
282 d->status = Ready;
283 emit statusChanged();
284}
285
286/*!
287 \qmlproperty enumeration FontLoader::status
288
289 This property holds the status of font loading. It can be one of:
290 \list
291 \o FontLoader.Null - no font has been set
292 \o FontLoader.Ready - the font has been loaded
293 \o FontLoader.Loading - the font is currently being loaded
294 \o FontLoader.Error - an error occurred while loading the font
295 \endlist
296
297 Use this status to provide an update or respond to the status change in some way.
298 For example, you could:
299
300 \list
301 \o Trigger a state change:
302 \qml
303 State { name: 'loaded'; when: loader.status == FontLoader.Ready }
304 \endqml
305
306 \o Implement an \c onStatusChanged signal handler:
307 \qml
308 FontLoader {
309 id: loader
310 onStatusChanged: if (loader.status == FontLoader.Ready) console.log('Loaded')
311 }
312 \endqml
313
314 \o Bind to the status value:
315 \qml
316 Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' }
317 \endqml
318 \endlist
319*/
320QDeclarativeFontLoader::Status QDeclarativeFontLoader::status() const
321{
322 Q_D(const QDeclarativeFontLoader);
323 return d->status;
324}
325
326QT_END_NAMESPACE
327
328#include <qdeclarativefontloader.moc>
Note: See TracBrowser for help on using the repository browser.