Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickvectorimage.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qurl.h>
7#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
8#include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h>
9#include <QtQuickVectorImageGenerator/private/qquickvectorimageplugin_p.h>
10#include <QtCore/qloggingcategory.h>
11
12#include <private/qquicktranslate_p.h>
13
14#include <private/qfactoryloader_p.h>
15
17
18Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, vectorImagePluginLoader,
19 (QQuickVectorImageFormatsPluginFactory_iid,
20 QLatin1String("/vectorimageformats"),
21 Qt::CaseInsensitive))
22
23
24/*!
25 \qmlmodule QtQuick.VectorImage
26 \title Qt Quick Vector Image QML Types
27 \ingroup qmlmodules
28 \brief Provides QML types for displaying vector image files.
29 \since 6.8
30
31 To use the types in this module, import the module with the following line:
32
33 \qml
34 import QtQuick.VectorImage
35 \endqml
36
37 Qt Quick Vector Image provides support for displaying vector image files in a Qt Quick
38 scene.
39
40 It currently supports the \c SVG file format. In addition, Lottie support can be enabled by
41 setting the \l{assumeTrustedSource} property to true and including the plugin from the
42 \l{Qt Lottie Animation} module. This plugin is currently considered tech preview.
43
44 Qt supports multiple options for displaying SVG files. For an overview and comparison of
45 the different ones, see the documentation of the \l{svgtoqml} tool.
46
47 \section1 QML Types
48*/
49
50void QQuickVectorImagePrivate::setSource(const QUrl &source)
51{
52 Q_Q(QQuickVectorImage);
53 if (sourceFile == source)
54 return;
55
56 sourceFile = source;
57 loadFile();
58 emit q->sourceChanged();
59}
60
62{
63 Q_Q(QQuickVectorImage);
64
65 if (!q->isComponentComplete())
66 return;
67
68 QUrl resolvedUrl = qmlContext(q)->resolvedUrl(sourceFile);
69 QString localFile = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
70
71 if (localFile.isEmpty())
72 return;
73
74 if (rootItem)
75 rootItem->deleteLater();
76
77 rootItem = new QQuickItem(q);
78 rootItem->setParentItem(q);
79
80 QQuickVectorImageGenerator::GeneratorFlags flags;
81 if (preferredRendererType == QQuickVectorImage::CurveRenderer)
82 flags.setFlag(QQuickVectorImageGenerator::CurveRenderer);
83 if (assumeTrustedSource)
84 flags.setFlag(QQuickVectorImageGenerator::AssumeTrustedSource);
85
86 QQuickItemGenerator generator(localFile, flags, rootItem, qmlContext(q));
87
88 // If we assume trusted source, we try plugins first
89 bool generatedWithPlugin = false;
91 QFactoryLoader *loader = vectorImagePluginLoader();
92
93 const qsizetype count = loader->keyMap().size();
94 for (qsizetype i = 0; i <= count && !generatedWithPlugin; ++i) {
95 QQuickVectorImagePlugin *plugin = qobject_cast<QQuickVectorImagePlugin *>(loader->instance(i));
96 if (plugin != nullptr)
97 generatedWithPlugin = plugin->generate(localFile, &generator);
98 }
99 }
100
101 if (!generatedWithPlugin)
102 generator.generate();
103
104 q->setImplicitWidth(rootItem->width());
105 q->setImplicitHeight(rootItem->height());
106
107 q->updateAnimationProperties();
108 q->updateRootItemScale();
109 q->update();
110}
111
112/*!
113 \qmltype VectorImage
114 \inqmlmodule QtQuick.VectorImage
115 \inherits Item
116 \brief Loads a vector image file and displays it in a Qt Quick scene.
117 \since 6.8
118
119 The VectorImage can be used to load a vector image file and display this as an item in a Qt
120 Quick scene.
121
122 It currently supports the \c SVG file format. In addition, Lottie support can be enabled by
123 setting the \l{assumeTrustedSource} property to true and including the plugin from the
124 \l{Qt Lottie Animation} module. This plugin is currently considered tech preview.
125
126 \note This complements the approach of loading the vector image file through an \l Image
127 element: \l Image creates a raster version of the image at the requested size. VectorImage
128 builds a Qt Quick scene that represents the image. This means the resulting item can be scaled
129 and rotated without losing quality, and it will typically consume less memory than the
130 rasterized version.
131*/
132QQuickVectorImage::QQuickVectorImage(QQuickItem *parent)
133 : QQuickItem(*(new QQuickVectorImagePrivate), parent)
134{
135 setFlag(QQuickItem::ItemHasContents, true);
136
137 QObject::connect(this, &QQuickItem::widthChanged, this, &QQuickVectorImage::updateRootItemScale);
138 QObject::connect(this, &QQuickItem::heightChanged, this, &QQuickVectorImage::updateRootItemScale);
139 QObject::connect(this, &QQuickVectorImage::fillModeChanged, this, &QQuickVectorImage::updateRootItemScale);
140}
141
142/*!
143 \qmlproperty url QtQuick.VectorImage::VectorImage::source
144
145 This property holds the URL of the vector image file to load.
146
147 VectorImage currently supports the \c SVG file format. In addition, Lottie support can be
148 enabled by setting the \l{assumeTrustedSource} property to true and including the plugin from
149 the \l{Qt Lottie Animation} module. This plugin is currently considered tech preview.
150*/
151QUrl QQuickVectorImage::source() const
152{
153 Q_D(const QQuickVectorImage);
154 return d->sourceFile;
155}
156
157void QQuickVectorImage::setSource(const QUrl &source)
158{
159 Q_D(QQuickVectorImage);
160 d->setSource(source);
161}
162
163void QQuickVectorImage::updateRootItemScale()
164{
165 Q_D(QQuickVectorImage);
166
167 if (d->rootItem == nullptr
168 || qFuzzyIsNull(d->rootItem->width())
169 || qFuzzyIsNull(d->rootItem->height())) {
170 return;
171 }
172
173 auto xformProp = d->rootItem->transform();
174 QQuickScale *scaleTransform = nullptr;
175 if (xformProp.count(&xformProp) == 0) {
176 scaleTransform = new QQuickScale;
177 scaleTransform->setParent(d->rootItem);
178 xformProp.append(&xformProp, scaleTransform);
179 } else {
180 scaleTransform = qobject_cast<QQuickScale *>(xformProp.at(&xformProp, 0));
181 }
182
183 if (scaleTransform != nullptr) {
184 qreal xScale = width() / d->rootItem->width();
185 qreal yScale = height() / d->rootItem->height();
186
187 switch (d->fillMode) {
188 case QQuickVectorImage::NoResize:
189 xScale = yScale = 1.0;
190 break;
191 case QQuickVectorImage::PreserveAspectFit:
192 xScale = yScale = qMin(xScale, yScale);
193 break;
194 case QQuickVectorImage::PreserveAspectCrop:
195 xScale = yScale = qMax(xScale, yScale);
196 break;
197 case QQuickVectorImage::Stretch:
198 // Already correct
199 break;
200 };
201
202 scaleTransform->setXScale(xScale);
203 scaleTransform->setYScale(yScale);
204 }
205}
206
207void QQuickVectorImage::updateAnimationProperties()
208{
209 Q_D(QQuickVectorImage);
210 if (Q_UNLIKELY(d->rootItem == nullptr || d->rootItem->childItems().isEmpty()))
211 return;
212
213 QQuickItem *childItem = d->rootItem->childItems().first();
214 if (Q_LIKELY(d->animations != nullptr)) {
215 childItem->setProperty("loops", d->animations->loops());
216 childItem->setProperty("paused", d->animations->paused());
217 }
218}
219
220QQuickVectorImageAnimations *QQuickVectorImage::animations()
221{
222 Q_D(QQuickVectorImage);
223 if (d->animations == nullptr) {
224 d->animations = new QQuickVectorImageAnimations;
225 QQml_setParent_noEvent(d->animations, this);
226 QObject::connect(d->animations, &QQuickVectorImageAnimations::loopsChanged, this, &QQuickVectorImage::updateAnimationProperties);
227 QObject::connect(d->animations, &QQuickVectorImageAnimations::pausedChanged, this, &QQuickVectorImage::updateAnimationProperties);
228 }
229
230 return d->animations;
231}
232
233/*!
234 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::fillMode
235
236 This property defines what happens if the width and height of the VectorImage differs from
237 the implicit size of its contents.
238
239 \value VectorImage.NoResize The contents are still rendered at the size provided by
240 the input.
241 \value VectorImage.Stretch The contents are scaled to match the width and height of
242 the \c{VectorImage}. (This is the default.)
243 \value VectorImage.PreserveAspectFit The contents are scaled to fit inside the bounds of the
244 \c VectorImage, while preserving aspect ratio. The
245 actual bounding rect of the contents will sometimes be
246 smaller than the \c VectorImage item.
247 \value VectorImage.PreserveAspectCrop The contents are scaled to fill the \c VectorImage item,
248 while preserving the aspect ratio. The actual bounds of
249 the contents will sometimes be larger than the
250 \c VectorImage item.
251*/
252
253QQuickVectorImage::FillMode QQuickVectorImage::fillMode() const
254{
255 Q_D(const QQuickVectorImage);
256 return d->fillMode;
257}
258
259void QQuickVectorImage::setFillMode(FillMode newFillMode)
260{
261 Q_D(QQuickVectorImage);
262 if (d->fillMode == newFillMode)
263 return;
264 d->fillMode = newFillMode;
265 emit fillModeChanged();
266}
267
268/*!
269 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::preferredRendererType
270
271 Requests a specific backend to use for rendering shapes in the \c VectorImage.
272
273 \value VectorImage.GeometryRenderer Equivalent to Shape.GeometryRenderer. This backend flattens
274 curves and triangulates the result. It will give aliased results unless multi-sampling is
275 enabled, and curve flattening may be visible when the item is scaled.
276 \value VectorImage.CurveRenderer Equivalent to Shape.CurveRenderer. With this backend, curves
277 are rendered on the GPU and anti-aliasing is built in. Will typically give better visual
278 results, but at some extra cost to performance.
279
280 The default is \c{VectorImage.GeometryRenderer}.
281*/
282
283QQuickVectorImage::RendererType QQuickVectorImage::preferredRendererType() const
284{
285 Q_D(const QQuickVectorImage);
286 return d->preferredRendererType;
287}
288
289void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRendererType)
290{
291 Q_D(QQuickVectorImage);
292 if (d->preferredRendererType == newPreferredRendererType)
293 return;
294 d->preferredRendererType = newPreferredRendererType;
295 d->loadFile();
296 emit preferredRendererTypeChanged();
297}
298
299/*!
300 \qmlproperty bool QtQuick.VectorImage::VectorImage::assumeTrustedSource
301 \since 6.10
302
303 Setting this to true when loading trusted source files expands support for some features that
304 may be unsafe in an uncontrolled setting. For SVG in particular, this maps to the
305 \l{QtSvg::Option}{AssumeTrustedSource option}.
306
307 When this is set to true, VectorImage will also try to load the image using the Lottie format
308 plugin if this is available. This plugin is currently considered tech preview. See
309 \l{Qt Lottie Animation} for additional information.
310
311 By default this property is \c false.
312
313 \sa svgtoqml, lottietoqml
314 */
315
316bool QQuickVectorImage::assumeTrustedSource() const
317{
318 Q_D(const QQuickVectorImage);
319 return d->assumeTrustedSource;
320}
321
322void QQuickVectorImage::setAssumeTrustedSource(bool assumeTrustedSource)
323{
324 Q_D(QQuickVectorImage);
325 if (d->assumeTrustedSource == assumeTrustedSource)
326 return;
327 d->assumeTrustedSource = assumeTrustedSource;
328 d->loadFile();
329 emit assumeTrustedSourceChanged();
330}
331
332void QQuickVectorImage::componentComplete()
333{
334 Q_D(QQuickVectorImage);
335 QQuickItem::componentComplete();
336
337 d->loadFile();
338}
339
340/*!
341 \qmlpropertygroup QtQuick.VectorImage::VectorImage::animations
342 \qmlproperty bool QtQuick.VectorImage::VectorImage::animations.paused
343 \qmlproperty int QtQuick.VectorImage::VectorImage::animations.loops
344 \since 6.10
345
346 These properties can be used to control animations in the image, if it contains any.
347
348 The \c paused property can be set to true to temporarily pause all animations. When the
349 property is reset to \c false, the animations will resume where they were. By default this
350 property is \c false.
351
352 The \c loops property defines the number of times the animations in the document will repeat.
353 By default this property is 1. Any animations that is set to loop indefinitely in the source
354 image will be unaffected by this property. To make all animations in the document repeat
355 indefinitely, the \c loops property can be set to \c{Animation.Infinite}.
356*/
357int QQuickVectorImageAnimations::loops() const
358{
359 return m_loops;
360}
361
362void QQuickVectorImageAnimations::setLoops(int loops)
363{
364 if (m_loops == loops)
365 return;
366 m_loops = loops;
367 emit loopsChanged();
368}
369
370bool QQuickVectorImageAnimations::paused() const
371{
372 return m_paused;
373}
374
375void QQuickVectorImageAnimations::setPaused(bool paused)
376{
377 if (m_paused == paused)
378 return;
379 m_paused = paused;
380 emit pausedChanged();
381}
382
383void QQuickVectorImageAnimations::restart()
384{
385 QQuickVectorImage *parentVectorImage = qobject_cast<QQuickVectorImage *>(parent());
386 if (Q_UNLIKELY(parentVectorImage == nullptr)) {
387 qCWarning(lcQuickVectorImage) << Q_FUNC_INFO << "Parent is not a VectorImage";
388 return;
389 }
390
391 QQuickVectorImagePrivate *d = QQuickVectorImagePrivate::get(parentVectorImage);
392
393 if (Q_UNLIKELY(d->rootItem == nullptr || d->rootItem->childItems().isEmpty()))
394 return;
395
396 QQuickItem *childItem = d->rootItem->childItems().first();
397 QMetaObject::invokeMethod(childItem, "restart");
398}
399
400QT_END_NAMESPACE
401
402#include <moc_qquickvectorimage_p.cpp>