Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/quick/util/qquickfontloader.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||
2 | ** | - | ||||||
3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||
5 | ** | - | ||||||
6 | ** This file is part of the QtQuick module of the Qt Toolkit. | - | ||||||
7 | ** | - | ||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||
9 | ** Commercial License Usage | - | ||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||
16 | ** | - | ||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||
24 | ** | - | ||||||
25 | ** GNU General Public License Usage | - | ||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||
35 | ** | - | ||||||
36 | ** $QT_END_LICENSE$ | - | ||||||
37 | ** | - | ||||||
38 | ****************************************************************************/ | - | ||||||
39 | - | |||||||
40 | #include "qquickfontloader_p.h" | - | ||||||
41 | - | |||||||
42 | #include <qqmlcontext.h> | - | ||||||
43 | #include <qqmlengine.h> | - | ||||||
44 | - | |||||||
45 | #include <QStringList> | - | ||||||
46 | #include <QUrl> | - | ||||||
47 | #include <QDebug> | - | ||||||
48 | - | |||||||
49 | #include <QFontDatabase> | - | ||||||
50 | - | |||||||
51 | #include <private/qobject_p.h> | - | ||||||
52 | #include <qqmlinfo.h> | - | ||||||
53 | #include <qqmlfile.h> | - | ||||||
54 | - | |||||||
55 | #if QT_CONFIG(qml_network) | - | ||||||
56 | #include <QNetworkRequest> | - | ||||||
57 | #include <QNetworkReply> | - | ||||||
58 | #endif | - | ||||||
59 | - | |||||||
60 | #include <QtCore/QCoreApplication> | - | ||||||
61 | - | |||||||
62 | QT_BEGIN_NAMESPACE | - | ||||||
63 | - | |||||||
64 | #define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16 | - | ||||||
65 | - | |||||||
66 | class QQuickFontObject : public QObject | - | ||||||
67 | { | - | ||||||
68 | Q_OBJECT | - | ||||||
69 | - | |||||||
70 | public: | - | ||||||
71 | explicit QQuickFontObject(int _id = -1); | - | ||||||
72 | - | |||||||
73 | #if QT_CONFIG(qml_network) | - | ||||||
74 | void download(const QUrl &url, QNetworkAccessManager *manager); | - | ||||||
75 | - | |||||||
76 | Q_SIGNALS: | - | ||||||
77 | void fontDownloaded(const QString&, QQuickFontLoader::Status); | - | ||||||
78 | - | |||||||
79 | private: | - | ||||||
80 | int redirectCount = 0; | - | ||||||
81 | QNetworkReply *reply = nullptr; | - | ||||||
82 | - | |||||||
83 | private Q_SLOTS: | - | ||||||
84 | void replyFinished(); | - | ||||||
85 | #endif // qml_network | - | ||||||
86 | - | |||||||
87 | public: | - | ||||||
88 | int id; | - | ||||||
89 | - | |||||||
90 | Q_DISABLE_COPY(QQuickFontObject) | - | ||||||
91 | }; | - | ||||||
92 | - | |||||||
93 | QQuickFontObject::QQuickFontObject(int _id) | - | ||||||
94 | : QObject(nullptr), id(_id) | - | ||||||
95 | { | - | ||||||
96 | } executed 22 times by 3 tests: end of block Executed by:
| 22 | ||||||
97 | - | |||||||
98 | #if QT_CONFIG(qml_network) | - | ||||||
99 | void QQuickFontObject::download(const QUrl &url, QNetworkAccessManager *manager) | - | ||||||
100 | { | - | ||||||
101 | QNetworkRequest req(url); | - | ||||||
102 | req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); | - | ||||||
103 | reply = manager->get(req); | - | ||||||
104 | QObject::connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); | - | ||||||
105 | } executed 14 times by 2 tests: end of block Executed by:
| 14 | ||||||
106 | - | |||||||
107 | void QQuickFontObject::replyFinished() | - | ||||||
108 | { | - | ||||||
109 | if (reply) {
| 0-14 | ||||||
110 | redirectCount++; | - | ||||||
111 | if (redirectCount < FONTLOADER_MAXIMUM_REDIRECT_RECURSION) {
| 0-14 | ||||||
112 | QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); | - | ||||||
113 | if (redirect.isValid()) {
| 2-12 | ||||||
114 | QUrl url = reply->url().resolved(redirect.toUrl()); | - | ||||||
115 | QNetworkAccessManager *manager = reply->manager(); | - | ||||||
116 | reply->deleteLater(); | - | ||||||
117 | reply = nullptr; | - | ||||||
118 | download(url, manager); | - | ||||||
119 | return; executed 2 times by 1 test: return; Executed by:
| 2 | ||||||
120 | } | - | ||||||
121 | } executed 12 times by 2 tests: end of block Executed by:
| 12 | ||||||
122 | redirectCount = 0; | - | ||||||
123 | - | |||||||
124 | if (!reply->error()) {
| 6 | ||||||
125 | id = QFontDatabase::addApplicationFontFromData(reply->readAll()); | - | ||||||
126 | if (id != -1)
| 0-6 | ||||||
127 | emit fontDownloaded(QFontDatabase::applicationFontFamilies(id).at(0), QQuickFontLoader::Ready); executed 6 times by 1 test: fontDownloaded(QFontDatabase::applicationFontFamilies(id).at(0), QQuickFontLoader::Ready); Executed by:
| 6 | ||||||
128 | else | - | ||||||
129 | emit fontDownloaded(QString(), QQuickFontLoader::Error); never executed: fontDownloaded(QString(), QQuickFontLoader::Error); | 0 | ||||||
130 | } else { | - | ||||||
131 | qWarning("%s: Unable to load font '%s': %s", Q_FUNC_INFO, | - | ||||||
132 | qPrintable(reply->url().toString()), qPrintable(reply->errorString())); | - | ||||||
133 | emit fontDownloaded(QString(), QQuickFontLoader::Error); | - | ||||||
134 | } executed 6 times by 2 tests: end of block Executed by:
| 6 | ||||||
135 | reply->deleteLater(); | - | ||||||
136 | reply = nullptr; | - | ||||||
137 | } executed 12 times by 2 tests: end of block Executed by:
| 12 | ||||||
138 | } executed 12 times by 2 tests: end of block Executed by:
| 12 | ||||||
139 | #endif // qml_network | - | ||||||
140 | - | |||||||
141 | class QQuickFontLoaderPrivate : public QObjectPrivate | - | ||||||
142 | { | - | ||||||
143 | Q_DECLARE_PUBLIC(QQuickFontLoader) | - | ||||||
144 | - | |||||||
145 | public: | - | ||||||
146 | QQuickFontLoaderPrivate() {} | - | ||||||
147 | - | |||||||
148 | QUrl url; | - | ||||||
149 | QString name; | - | ||||||
150 | QQuickFontLoader::Status status = QQuickFontLoader::Null; | - | ||||||
151 | }; | - | ||||||
152 | - | |||||||
153 | static void q_QFontLoaderFontsStaticReset(); | - | ||||||
154 | static void q_QFontLoaderFontsAddReset() | - | ||||||
155 | { | - | ||||||
156 | qAddPostRoutine(q_QFontLoaderFontsStaticReset); | - | ||||||
157 | } executed 10 times by 3 tests: end of block Executed by:
| 10 | ||||||
158 | class QFontLoaderFonts | - | ||||||
159 | { | - | ||||||
160 | public: | - | ||||||
161 | QFontLoaderFonts() | - | ||||||
162 | { | - | ||||||
163 | qAddPostRoutine(q_QFontLoaderFontsStaticReset); | - | ||||||
164 | qAddPreRoutine(q_QFontLoaderFontsAddReset); | - | ||||||
165 | } executed 6 times by 3 tests: end of block Executed by:
| 6 | ||||||
166 | - | |||||||
167 | ~QFontLoaderFonts() | - | ||||||
168 | { | - | ||||||
169 | qRemovePostRoutine(q_QFontLoaderFontsStaticReset); | - | ||||||
170 | reset(); | - | ||||||
171 | } executed 6 times by 3 tests: end of block Executed by:
| 6 | ||||||
172 | - | |||||||
173 | - | |||||||
174 | void reset() | - | ||||||
175 | { | - | ||||||
176 | QVector<QQuickFontObject *> deleted; | - | ||||||
177 | QHash<QUrl, QQuickFontObject*>::iterator it; | - | ||||||
178 | for (it = map.begin(); it != map.end(); ++it) {
| 22 | ||||||
179 | if (!deleted.contains(it.value())) {
| 0-22 | ||||||
180 | deleted.append(it.value()); | - | ||||||
181 | delete it.value(); | - | ||||||
182 | } executed 22 times by 3 tests: end of block Executed by:
| 22 | ||||||
183 | } executed 22 times by 3 tests: end of block Executed by:
| 22 | ||||||
184 | map.clear(); | - | ||||||
185 | } executed 22 times by 3 tests: end of block Executed by:
| 22 | ||||||
186 | - | |||||||
187 | QHash<QUrl, QQuickFontObject *> map; | - | ||||||
188 | }; | - | ||||||
189 | Q_GLOBAL_STATIC(QFontLoaderFonts, fontLoaderFonts); executed 6 times by 3 tests: end of block Executed by:
executed 6 times by 3 tests: guard.store(QtGlobalStatic::Destroyed); Executed by:
executed 78 times by 3 tests: return &holder.value; Executed by:
| 0-78 | ||||||
190 | - | |||||||
191 | static void q_QFontLoaderFontsStaticReset() | - | ||||||
192 | { | - | ||||||
193 | fontLoaderFonts()->reset(); | - | ||||||
194 | } executed 16 times by 3 tests: end of block Executed by:
| 16 | ||||||
195 | - | |||||||
196 | /*! | - | ||||||
197 | \qmltype FontLoader | - | ||||||
198 | \instantiates QQuickFontLoader | - | ||||||
199 | \inqmlmodule QtQuick | - | ||||||
200 | \ingroup qtquick-text-utility | - | ||||||
201 | \brief Allows fonts to be loaded by name or URL. | - | ||||||
202 | - | |||||||
203 | The FontLoader type is used to load fonts by name or URL. | - | ||||||
204 | - | |||||||
205 | The \l status indicates when the font has been loaded, which is useful | - | ||||||
206 | for fonts loaded from remote sources. | - | ||||||
207 | - | |||||||
208 | For example: | - | ||||||
209 | \qml | - | ||||||
210 | import QtQuick 2.0 | - | ||||||
211 | - | |||||||
212 | Column { | - | ||||||
213 | FontLoader { id: fixedFont; name: "Courier" } | - | ||||||
214 | FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" } | - | ||||||
215 | - | |||||||
216 | Text { text: "Fixed-size font"; font.family: fixedFont.name } | - | ||||||
217 | Text { text: "Fancy font"; font.family: webFont.name } | - | ||||||
218 | } | - | ||||||
219 | \endqml | - | ||||||
220 | - | |||||||
221 | \sa {Qt Quick Examples - Text#Fonts}{Qt Quick Examples - Text Fonts} | - | ||||||
222 | */ | - | ||||||
223 | QQuickFontLoader::QQuickFontLoader(QObject *parent) | - | ||||||
224 | : QObject(*(new QQuickFontLoaderPrivate), parent) | - | ||||||
225 | { | - | ||||||
226 | } executed 30 times by 3 tests: end of block Executed by:
| 30 | ||||||
227 | - | |||||||
228 | QQuickFontLoader::~QQuickFontLoader() | - | ||||||
229 | { | - | ||||||
230 | } | - | ||||||
231 | - | |||||||
232 | /*! | - | ||||||
233 | \qmlproperty url QtQuick::FontLoader::source | - | ||||||
234 | The URL of the font to load. | - | ||||||
235 | */ | - | ||||||
236 | QUrl QQuickFontLoader::source() const | - | ||||||
237 | { | - | ||||||
238 | Q_D(const QQuickFontLoader); | - | ||||||
239 | return d->url; executed 20 times by 1 test: return d->url; Executed by:
| 20 | ||||||
240 | } | - | ||||||
241 | - | |||||||
242 | void QQuickFontLoader::setSource(const QUrl &url) | - | ||||||
243 | { | - | ||||||
244 | Q_D(QQuickFontLoader); | - | ||||||
245 | if (url == d->url)
| 0-32 | ||||||
246 | return; never executed: return; | 0 | ||||||
247 | d->url = url; | - | ||||||
248 | emit sourceChanged(); | - | ||||||
249 | - | |||||||
250 | QString localFile = QQmlFile::urlToLocalFileOrQrc(d->url); | - | ||||||
251 | if (!localFile.isEmpty()) {
| 14-18 | ||||||
252 | if (!fontLoaderFonts()->map.contains(d->url)) {
| 6-12 | ||||||
253 | int id = QFontDatabase::addApplicationFont(localFile); | - | ||||||
254 | if (id != -1) {
| 2-10 | ||||||
255 | updateFontInfo(QFontDatabase::applicationFontFamilies(id).at(0), Ready); | - | ||||||
256 | QQuickFontObject *fo = new QQuickFontObject(id); | - | ||||||
257 | fontLoaderFonts()->map[d->url] = fo; | - | ||||||
258 | } else { executed 10 times by 3 tests: end of block Executed by:
| 10 | ||||||
259 | updateFontInfo(QString(), Error); | - | ||||||
260 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||
261 | } else { | - | ||||||
262 | updateFontInfo(QFontDatabase::applicationFontFamilies(fontLoaderFonts()->map.value(d->url)->id).at(0), Ready); | - | ||||||
263 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||
264 | } else { | - | ||||||
265 | if (!fontLoaderFonts()->map.contains(d->url)) {
| 2-12 | ||||||
266 | #if QT_CONFIG(qml_network) | - | ||||||
267 | QQuickFontObject *fo = new QQuickFontObject; | - | ||||||
268 | fontLoaderFonts()->map[d->url] = fo; | - | ||||||
269 | fo->download(d->url, qmlEngine(this)->networkAccessManager()); | - | ||||||
270 | d->status = Loading; | - | ||||||
271 | emit statusChanged(); | - | ||||||
272 | QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)), | - | ||||||
273 | this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status))); | - | ||||||
274 | #else | - | ||||||
275 | // Silently fail if compiled with no_network | - | ||||||
276 | #endif | - | ||||||
277 | } else { executed 12 times by 2 tests: end of block Executed by:
| 12 | ||||||
278 | QQuickFontObject *fo = fontLoaderFonts()->map.value(d->url); | - | ||||||
279 | if (fo->id == -1) {
| 0-2 | ||||||
280 | #if QT_CONFIG(qml_network) | - | ||||||
281 | d->status = Loading; | - | ||||||
282 | emit statusChanged(); | - | ||||||
283 | QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)), | - | ||||||
284 | this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status))); | - | ||||||
285 | #else | - | ||||||
286 | // Silently fail if compiled with no_network | - | ||||||
287 | #endif | - | ||||||
288 | } never executed: end of block | 0 | ||||||
289 | else | - | ||||||
290 | updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready); executed 2 times by 1 test: updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready); Executed by:
| 2 | ||||||
291 | } | - | ||||||
292 | } | - | ||||||
293 | } | - | ||||||
294 | - | |||||||
295 | void QQuickFontLoader::updateFontInfo(const QString& name, QQuickFontLoader::Status status) | - | ||||||
296 | { | - | ||||||
297 | Q_D(QQuickFontLoader); | - | ||||||
298 | - | |||||||
299 | if (name != d->name) {
| 6-26 | ||||||
300 | d->name = name; | - | ||||||
301 | emit nameChanged(); | - | ||||||
302 | } executed 26 times by 3 tests: end of block Executed by:
| 26 | ||||||
303 | if (status != d->status) {
| 4-28 | ||||||
304 | if (status == Error)
| 8-20 | ||||||
305 | qmlWarning(this) << "Cannot load font: \"" << d->url.toString() << '"'; executed 8 times by 2 tests: qmlWarning(this) << "Cannot load font: \"" << d->url.toString() << '"'; Executed by:
| 8 | ||||||
306 | d->status = status; | - | ||||||
307 | emit statusChanged(); | - | ||||||
308 | } executed 28 times by 3 tests: end of block Executed by:
| 28 | ||||||
309 | } executed 32 times by 3 tests: end of block Executed by:
| 32 | ||||||
310 | - | |||||||
311 | /*! | - | ||||||
312 | \qmlproperty string QtQuick::FontLoader::name | - | ||||||
313 | - | |||||||
314 | This property holds the name of the font family. | - | ||||||
315 | It is set automatically when a font is loaded using the \l source property. | - | ||||||
316 | - | |||||||
317 | Use this to set the \c font.family property of a \c Text item. | - | ||||||
318 | - | |||||||
319 | Example: | - | ||||||
320 | \qml | - | ||||||
321 | Item { | - | ||||||
322 | width: 200; height: 50 | - | ||||||
323 | - | |||||||
324 | FontLoader { | - | ||||||
325 | id: webFont | - | ||||||
326 | source: "http://www.mysite.com/myfont.ttf" | - | ||||||
327 | } | - | ||||||
328 | Text { | - | ||||||
329 | text: "Fancy font" | - | ||||||
330 | font.family: webFont.name | - | ||||||
331 | } | - | ||||||
332 | } | - | ||||||
333 | \endqml | - | ||||||
334 | */ | - | ||||||
335 | QString QQuickFontLoader::name() const | - | ||||||
336 | { | - | ||||||
337 | Q_D(const QQuickFontLoader); | - | ||||||
338 | return d->name; executed 112 times by 3 tests: return d->name; Executed by:
| 112 | ||||||
339 | } | - | ||||||
340 | - | |||||||
341 | void QQuickFontLoader::setName(const QString &name) | - | ||||||
342 | { | - | ||||||
343 | Q_D(QQuickFontLoader); | - | ||||||
344 | if (d->name == name)
| 0-6 | ||||||
345 | return; never executed: return; | 0 | ||||||
346 | d->name = name; | - | ||||||
347 | emit nameChanged(); | - | ||||||
348 | d->status = Ready; | - | ||||||
349 | emit statusChanged(); | - | ||||||
350 | } executed 6 times by 2 tests: end of block Executed by:
| 6 | ||||||
351 | - | |||||||
352 | /*! | - | ||||||
353 | \qmlproperty enumeration QtQuick::FontLoader::status | - | ||||||
354 | - | |||||||
355 | This property holds the status of font loading. It can be one of: | - | ||||||
356 | \list | - | ||||||
357 | \li FontLoader.Null - no font has been set | - | ||||||
358 | \li FontLoader.Ready - the font has been loaded | - | ||||||
359 | \li FontLoader.Loading - the font is currently being loaded | - | ||||||
360 | \li FontLoader.Error - an error occurred while loading the font | - | ||||||
361 | \endlist | - | ||||||
362 | - | |||||||
363 | Use this status to provide an update or respond to the status change in some way. | - | ||||||
364 | For example, you could: | - | ||||||
365 | - | |||||||
366 | \list | - | ||||||
367 | \li Trigger a state change: | - | ||||||
368 | \qml | - | ||||||
369 | State { name: 'loaded'; when: loader.status == FontLoader.Ready } | - | ||||||
370 | \endqml | - | ||||||
371 | - | |||||||
372 | \li Implement an \c onStatusChanged signal handler: | - | ||||||
373 | \qml | - | ||||||
374 | FontLoader { | - | ||||||
375 | id: loader | - | ||||||
376 | onStatusChanged: if (loader.status == FontLoader.Ready) console.log('Loaded') | - | ||||||
377 | } | - | ||||||
378 | \endqml | - | ||||||
379 | - | |||||||
380 | \li Bind to the status value: | - | ||||||
381 | \qml | - | ||||||
382 | Text { text: loader.status == FontLoader.Ready ? 'Loaded' : 'Not loaded' } | - | ||||||
383 | \endqml | - | ||||||
384 | \endlist | - | ||||||
385 | */ | - | ||||||
386 | QQuickFontLoader::Status QQuickFontLoader::status() const | - | ||||||
387 | { | - | ||||||
388 | Q_D(const QQuickFontLoader); | - | ||||||
389 | return d->status; executed 728 times by 2 tests: return d->status; Executed by:
| 728 | ||||||
390 | } | - | ||||||
391 | - | |||||||
392 | QT_END_NAMESPACE | - | ||||||
393 | - | |||||||
394 | #include <qquickfontloader.moc> | - | ||||||
395 | - | |||||||
396 | #include "moc_qquickfontloader_p.cpp" | - | ||||||
Source code | Switch to Preprocessed file |