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 "qquickvectorimage_p.h"
5#include "qquickvectorimage_p_p.h"
6#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
7#include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h>
8#include <QtCore/qloggingcategory.h>
9
10#include <private/qquicktranslate_p.h>
11
12QT_BEGIN_NAMESPACE
13
14/*!
15 \qmlmodule QtQuick.VectorImage
16 \title Qt Quick Vector Image QML Types
17 \ingroup qmlmodules
18 \brief Provides QML types for displaying vector image files.
19 \since 6.8
20
21 To use the types in this module, import the module with the following line:
22
23 \qml
24 import QtQuick.VectorImage
25 \endqml
26
27 Qt Quick Vector Image provides support for displaying vector image files in a Qt Quick
28 scene.
29
30 It currently supports the \c SVG file format.
31
32 Qt supports multiple options for displaying SVG files. For an overview and comparison of the
33 different ones, see the documentation of the \l{svgtoqml} tool.
34
35 \section1 QML Types
36*/
37
38Q_LOGGING_CATEGORY(lcQuickVectorImage, "qt.quick.vectorimage", QtWarningMsg)
39
40void QQuickVectorImagePrivate::setSource(const QUrl &source)
41{
42 Q_Q(QQuickVectorImage);
43 if (sourceFile == source)
44 return;
45
46 sourceFile = source;
47 loadSvg();
48 emit q->sourceChanged();
49}
50
51void QQuickVectorImagePrivate::loadSvg()
52{
53 Q_Q(QQuickVectorImage);
54
55 QUrl resolvedUrl = qmlContext(q)->resolvedUrl(sourceFile);
56 QString localFile = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
57
58 if (localFile.isEmpty())
59 return;
60
61 QQuickVectorImagePrivate::Format fileFormat = formatFromFilePath(filePath: localFile);
62
63 if (fileFormat != QQuickVectorImagePrivate::Format::Svg) {
64 qCWarning(lcQuickVectorImage) << "Unsupported file format";
65 return;
66 }
67
68 if (svgItem)
69 svgItem->deleteLater();
70
71 svgItem = new QQuickItem(q);
72
73 QQuickVectorImageGenerator::GeneratorFlags flags;
74 if (preferredRendererType == QQuickVectorImage::CurveRenderer)
75 flags.setFlag(flag: QQuickVectorImageGenerator::CurveRenderer);
76 QQuickItemGenerator generator(localFile, flags, svgItem);
77 generator.generate();
78
79 svgItem->setParentItem(q);
80 q->setImplicitWidth(svgItem->width());
81 q->setImplicitHeight(svgItem->height());
82
83 q->updateSvgItemScale();
84
85 q->update();
86}
87
88QQuickVectorImagePrivate::Format QQuickVectorImagePrivate::formatFromFilePath(const QString &filePath)
89{
90 Q_UNUSED(filePath)
91
92 QQuickVectorImagePrivate::Format res = QQuickVectorImagePrivate::Format::Unknown;
93
94 if (filePath.endsWith(s: QLatin1String(".svg")) || filePath.endsWith(s: QLatin1String(".svgz"))
95 || filePath.endsWith(s: QLatin1String(".svg.gz"))) {
96 res = QQuickVectorImagePrivate::Format::Svg;
97 }
98
99 return res;
100}
101
102/*!
103 \qmltype VectorImage
104 \inqmlmodule QtQuick.VectorImage
105 \inherits Item
106 \brief Loads a vector image file and displays it in a Qt Quick scene.
107 \since 6.8
108
109 The VectorImage can be used to load a vector image file and display this as an item in a Qt
110 Quick scene. It currently supports the \c SVG file format.
111
112 \note This complements the approach of loading the vector image file through an \l Image
113 element: \l Image creates a raster version of the image at the requested size. VectorImage
114 builds a Qt Quick scene that represents the image. This means the resulting item can be scaled
115 and rotated without losing quality, and it will typically consume less memory than the
116 rasterized version.
117*/
118QQuickVectorImage::QQuickVectorImage(QQuickItem *parent)
119 : QQuickItem(*(new QQuickVectorImagePrivate), parent)
120{
121 setFlag(flag: QQuickItem::ItemHasContents, enabled: true);
122
123 QObject::connect(sender: this, signal: &QQuickItem::widthChanged, context: this, slot: &QQuickVectorImage::updateSvgItemScale);
124 QObject::connect(sender: this, signal: &QQuickItem::heightChanged, context: this, slot: &QQuickVectorImage::updateSvgItemScale);
125 QObject::connect(sender: this, signal: &QQuickVectorImage::fillModeChanged, context: this, slot: &QQuickVectorImage::updateSvgItemScale);
126}
127
128/*!
129 \qmlproperty url QtQuick.VectorImage::VectorImage::source
130
131 This property holds the URL of the vector image file to load.
132
133 VectorImage currently only supports the \c SVG file format.
134*/
135QUrl QQuickVectorImage::source() const
136{
137 Q_D(const QQuickVectorImage);
138 return d->sourceFile;
139}
140
141void QQuickVectorImage::setSource(const QUrl &source)
142{
143 Q_D(QQuickVectorImage);
144 d->setSource(source);
145}
146
147void QQuickVectorImage::updateSvgItemScale()
148{
149 Q_D(QQuickVectorImage);
150
151 if (d->svgItem == nullptr
152 || qFuzzyIsNull(d: d->svgItem->width())
153 || qFuzzyIsNull(d: d->svgItem->height())) {
154 return;
155 }
156
157 auto xformProp = d->svgItem->transform();
158 QQuickScale *scaleTransform = nullptr;
159 if (xformProp.count(&xformProp) == 0) {
160 scaleTransform = new QQuickScale;
161 scaleTransform->setParent(d->svgItem);
162 xformProp.append(&xformProp, scaleTransform);
163 } else {
164 scaleTransform = qobject_cast<QQuickScale *>(object: xformProp.at(&xformProp, 0));
165 }
166
167 if (scaleTransform != nullptr) {
168 qreal xScale = width() / d->svgItem->width();
169 qreal yScale = height() / d->svgItem->height();
170
171 switch (d->fillMode) {
172 case QQuickVectorImage::NoResize:
173 xScale = yScale = 1.0;
174 break;
175 case QQuickVectorImage::PreserveAspectFit:
176 xScale = yScale = qMin(a: xScale, b: yScale);
177 break;
178 case QQuickVectorImage::PreserveAspectCrop:
179 xScale = yScale = qMax(a: xScale, b: yScale);
180 break;
181 case QQuickVectorImage::Stretch:
182 // Already correct
183 break;
184 };
185
186 scaleTransform->setXScale(xScale);
187 scaleTransform->setYScale(yScale);
188 }
189}
190
191/*!
192 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::fillMode
193
194 This property defines what happens if the width and height of the VectorImage differs from
195 the implicit size of its contents.
196
197 \value VectorImage.NoResize The contents are still rendered at the size provided by
198 the input.
199 \value VectorImage.Stretch The contents are scaled to match the width and height of
200 the \c{VectorImage}. (This is the default.)
201 \value VectorImage.PreserveAspectFit The contents are scaled to fit inside the bounds of the
202 \c VectorImage, while preserving aspect ratio. The
203 actual bounding rect of the contents will sometimes be
204 smaller than the \c VectorImage item.
205 \value VectorImage.PreserveAspectCrop The contents are scaled to fill the \c VectorImage item,
206 while preserving the aspect ratio. The actual bounds of
207 the contents will sometimes be larger than the
208 \c VectorImage item.
209*/
210
211QQuickVectorImage::FillMode QQuickVectorImage::fillMode() const
212{
213 Q_D(const QQuickVectorImage);
214 return d->fillMode;
215}
216
217void QQuickVectorImage::setFillMode(FillMode newFillMode)
218{
219 Q_D(QQuickVectorImage);
220 if (d->fillMode == newFillMode)
221 return;
222 d->fillMode = newFillMode;
223 emit fillModeChanged();
224}
225
226/*!
227 \qmlproperty enumeration QtQuick.VectorImage::VectorImage::preferredRendererType
228
229 Requests a specific backend to use for rendering shapes in the \c VectorImage.
230
231 \value VectorImage.GeometryRenderer Equivalent to Shape.GeometryRenderer. This backend flattens
232 curves and triangulates the result. It will give aliased results unless multi-sampling is
233 enabled, and curve flattening may be visible when the item is scaled.
234 \value VectorImage.CurveRenderer Equivalent to Shape.CurveRenderer. With this backend, curves
235 are rendered on the GPU and anti-aliasing is built in. Will typically give better visual
236 results, but at some extra cost to performance.
237
238 The default is \c{VectorImage.GeometryRenderer}.
239*/
240
241QQuickVectorImage::RendererType QQuickVectorImage::preferredRendererType() const
242{
243 Q_D(const QQuickVectorImage);
244 return d->preferredRendererType;
245}
246
247void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRendererType)
248{
249 Q_D(QQuickVectorImage);
250 if (d->preferredRendererType == newPreferredRendererType)
251 return;
252 d->preferredRendererType = newPreferredRendererType;
253 d->loadSvg();
254 emit preferredRendererTypeChanged();
255}
256
257QT_END_NAMESPACE
258

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtdeclarative/src/quickvectorimage/qquickvectorimage.cpp