aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2025-06-18 08:38:33 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2025-06-19 10:44:44 +0200
commit4154d2538419476ceaa3107dc417160f89c7eedc (patch)
tree45c01e471db1df660c6095f06b53fdc38d6cb6c3 /src
parentcd89ebc95f76923a3b81389b9a63a21987602873 (diff)
Add private plugin architecture to VectorImage
This will allow us to load Lottie files by creating a plugin in the Lottie module. The plugins are currently only queried if the opt-in "trusted content" flag is set. Pick-to: 6.10 Fixes: QTBUG-135266 Change-Id: I4901636e41f3bb73a78cbceb312f6cad9e96c5d2 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> Reviewed-by: Hatem ElKharashy <hatem.elkharashy@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quickvectorimage/CMakeLists.txt2
-rw-r--r--src/quickvectorimage/qquickvectorimage.cpp110
-rw-r--r--src/quickvectorimage/qquickvectorimage_p.h4
-rw-r--r--src/quickvectorimage/qquickvectorimage_p_p.h10
-rw-r--r--src/quickvectorimage/qquickvectorimageplugin.cpp14
-rw-r--r--src/quickvectorimage/qquickvectorimageplugin_p.h39
6 files changed, 122 insertions, 57 deletions
diff --git a/src/quickvectorimage/CMakeLists.txt b/src/quickvectorimage/CMakeLists.txt
index 50ed370304..5c1dce4cb5 100644
--- a/src/quickvectorimage/CMakeLists.txt
+++ b/src/quickvectorimage/CMakeLists.txt
@@ -6,6 +6,7 @@
#####################################################################
qt_internal_add_module(QuickVectorImageGeneratorPrivate
+ PLUGIN_TYPES vectorimageformats
INTERNAL_MODULE
SOURCES
generator/qsvgvisitorimpl_p.h generator/qsvgvisitorimpl.cpp
@@ -16,6 +17,7 @@ qt_internal_add_module(QuickVectorImageGeneratorPrivate
generator/qquicknodeinfo_p.h
generator/utils_p.h
qquickvectorimageglobal_p.h
+ qquickvectorimageplugin_p.h qquickvectorimageplugin.cpp
LIBRARIES
Qt::Core
Qt::QuickPrivate
diff --git a/src/quickvectorimage/qquickvectorimage.cpp b/src/quickvectorimage/qquickvectorimage.cpp
index bcddf810d9..07c30412cc 100644
--- a/src/quickvectorimage/qquickvectorimage.cpp
+++ b/src/quickvectorimage/qquickvectorimage.cpp
@@ -6,12 +6,21 @@
#include "qquickvectorimage_p_p.h"
#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
#include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h>
+#include <QtQuickVectorImageGenerator/private/qquickvectorimageplugin_p.h>
#include <QtCore/qloggingcategory.h>
#include <private/qquicktranslate_p.h>
+#include <private/qfactoryloader_p.h>
+
QT_BEGIN_NAMESPACE
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, vectorImagePluginLoader,
+ (QQuickVectorImageFormatsPluginFactory_iid,
+ QLatin1String("/vectorimageformats"),
+ Qt::CaseInsensitive))
+
+
/*!
\qmlmodule QtQuick.VectorImage
\title Qt Quick Vector Image QML Types
@@ -43,32 +52,28 @@ void QQuickVectorImagePrivate::setSource(const QUrl &source)
return;
sourceFile = source;
- loadSvg();
+ loadFile();
emit q->sourceChanged();
}
-void QQuickVectorImagePrivate::loadSvg()
+void QQuickVectorImagePrivate::loadFile()
{
Q_Q(QQuickVectorImage);
+ if (!q->isComponentComplete())
+ return;
+
QUrl resolvedUrl = qmlContext(q)->resolvedUrl(sourceFile);
QString localFile = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
if (localFile.isEmpty())
return;
- QQuickVectorImagePrivate::Format fileFormat = formatFromFilePath(localFile);
-
- if (fileFormat != QQuickVectorImagePrivate::Format::Svg) {
- qCWarning(lcQuickVectorImage) << "Unsupported file format";
- return;
- }
-
- if (svgItem)
- svgItem->deleteLater();
+ if (rootItem)
+ rootItem->deleteLater();
- svgItem = new QQuickItem(q);
- svgItem->setParentItem(q);
+ rootItem = new QQuickItem(q);
+ rootItem->setParentItem(q);
QQuickVectorImageGenerator::GeneratorFlags flags;
if (preferredRendererType == QQuickVectorImage::CurveRenderer)
@@ -76,29 +81,30 @@ void QQuickVectorImagePrivate::loadSvg()
if (assumeTrustedSource)
flags.setFlag(QQuickVectorImageGenerator::AssumeTrustedSource);
- QQuickItemGenerator generator(localFile, flags, svgItem, qmlContext(q));
- generator.generate();
+ QQuickItemGenerator generator(localFile, flags, rootItem, qmlContext(q));
- q->setImplicitWidth(svgItem->width());
- q->setImplicitHeight(svgItem->height());
+ // If we assume trusted source, we try plugins first
+ bool generatedWithPlugin = false;
+ if (assumeTrustedSource) {
+ QFactoryLoader *loader = vectorImagePluginLoader();
- q->updateAnimationProperties();
- q->updateSvgItemScale();
- q->update();
-}
-
-QQuickVectorImagePrivate::Format QQuickVectorImagePrivate::formatFromFilePath(const QString &filePath)
-{
- Q_UNUSED(filePath)
+ const qsizetype count = loader->keyMap().size();
+ for (qsizetype i = 0; i <= count && !generatedWithPlugin; ++i) {
+ QQuickVectorImagePlugin *plugin = qobject_cast<QQuickVectorImagePlugin *>(loader->instance(i));
+ if (plugin != nullptr)
+ generatedWithPlugin = plugin->generate(localFile, &generator);
+ }
+ }
- QQuickVectorImagePrivate::Format res = QQuickVectorImagePrivate::Format::Unknown;
+ if (!generatedWithPlugin)
+ generator.generate();
- if (filePath.endsWith(QLatin1String(".svg")) || filePath.endsWith(QLatin1String(".svgz"))
- || filePath.endsWith(QLatin1String(".svg.gz"))) {
- res = QQuickVectorImagePrivate::Format::Svg;
- }
+ q->setImplicitWidth(rootItem->width());
+ q->setImplicitHeight(rootItem->height());
- return res;
+ q->updateAnimationProperties();
+ q->updateRootItemScale();
+ q->update();
}
/*!
@@ -122,9 +128,9 @@ QQuickVectorImage::QQuickVectorImage(QQuickItem *parent)
{
setFlag(QQuickItem::ItemHasContents, true);
- QObject::connect(this, &QQuickItem::widthChanged, this, &QQuickVectorImage::updateSvgItemScale);
- QObject::connect(this, &QQuickItem::heightChanged, this, &QQuickVectorImage::updateSvgItemScale);
- QObject::connect(this, &QQuickVectorImage::fillModeChanged, this, &QQuickVectorImage::updateSvgItemScale);
+ QObject::connect(this, &QQuickItem::widthChanged, this, &QQuickVectorImage::updateRootItemScale);
+ QObject::connect(this, &QQuickItem::heightChanged, this, &QQuickVectorImage::updateRootItemScale);
+ QObject::connect(this, &QQuickVectorImage::fillModeChanged, this, &QQuickVectorImage::updateRootItemScale);
}
/*!
@@ -146,29 +152,29 @@ void QQuickVectorImage::setSource(const QUrl &source)
d->setSource(source);
}
-void QQuickVectorImage::updateSvgItemScale()
+void QQuickVectorImage::updateRootItemScale()
{
Q_D(QQuickVectorImage);
- if (d->svgItem == nullptr
- || qFuzzyIsNull(d->svgItem->width())
- || qFuzzyIsNull(d->svgItem->height())) {
+ if (d->rootItem == nullptr
+ || qFuzzyIsNull(d->rootItem->width())
+ || qFuzzyIsNull(d->rootItem->height())) {
return;
}
- auto xformProp = d->svgItem->transform();
+ auto xformProp = d->rootItem->transform();
QQuickScale *scaleTransform = nullptr;
if (xformProp.count(&xformProp) == 0) {
scaleTransform = new QQuickScale;
- scaleTransform->setParent(d->svgItem);
+ scaleTransform->setParent(d->rootItem);
xformProp.append(&xformProp, scaleTransform);
} else {
scaleTransform = qobject_cast<QQuickScale *>(xformProp.at(&xformProp, 0));
}
if (scaleTransform != nullptr) {
- qreal xScale = width() / d->svgItem->width();
- qreal yScale = height() / d->svgItem->height();
+ qreal xScale = width() / d->rootItem->width();
+ qreal yScale = height() / d->rootItem->height();
switch (d->fillMode) {
case QQuickVectorImage::NoResize:
@@ -193,10 +199,10 @@ void QQuickVectorImage::updateSvgItemScale()
void QQuickVectorImage::updateAnimationProperties()
{
Q_D(QQuickVectorImage);
- if (Q_UNLIKELY(d->svgItem == nullptr || d->svgItem->childItems().isEmpty()))
+ if (Q_UNLIKELY(d->rootItem == nullptr || d->rootItem->childItems().isEmpty()))
return;
- QQuickItem *childItem = d->svgItem->childItems().first();
+ QQuickItem *childItem = d->rootItem->childItems().first();
if (Q_LIKELY(d->animations != nullptr)) {
childItem->setProperty("loops", d->animations->loops());
childItem->setProperty("paused", d->animations->paused());
@@ -278,7 +284,7 @@ void QQuickVectorImage::setPreferredRendererType(RendererType newPreferredRender
if (d->preferredRendererType == newPreferredRendererType)
return;
d->preferredRendererType = newPreferredRendererType;
- d->loadSvg();
+ d->loadFile();
emit preferredRendererTypeChanged();
}
@@ -307,10 +313,18 @@ void QQuickVectorImage::setAssumeTrustedSource(bool assumeTrustedSource)
if (d->assumeTrustedSource == assumeTrustedSource)
return;
d->assumeTrustedSource = assumeTrustedSource;
- d->loadSvg();
+ d->loadFile();
emit assumeTrustedSourceChanged();
}
+void QQuickVectorImage::componentComplete()
+{
+ Q_D(QQuickVectorImage);
+ QQuickItem::componentComplete();
+
+ d->loadFile();
+}
+
/*!
\qmlpropertygroup QtQuick.VectorImage::VectorImage::animations
\qmlproperty bool QtQuick.VectorImage::VectorImage::animations.paused
@@ -364,10 +378,10 @@ void QQuickVectorImageAnimations::restart()
QQuickVectorImagePrivate *d = QQuickVectorImagePrivate::get(parentVectorImage);
- if (Q_UNLIKELY(d->svgItem == nullptr || d->svgItem->childItems().isEmpty()))
+ if (Q_UNLIKELY(d->rootItem == nullptr || d->rootItem->childItems().isEmpty()))
return;
- QQuickItem *childItem = d->svgItem->childItems().first();
+ QQuickItem *childItem = d->rootItem->childItems().first();
QMetaObject::invokeMethod(childItem, "restart");
}
diff --git a/src/quickvectorimage/qquickvectorimage_p.h b/src/quickvectorimage/qquickvectorimage_p.h
index dc7caeed11..f5d3aa0f51 100644
--- a/src/quickvectorimage/qquickvectorimage_p.h
+++ b/src/quickvectorimage/qquickvectorimage_p.h
@@ -66,6 +66,8 @@ public:
bool assumeTrustedSource() const;
void setAssumeTrustedSource(bool assumeTrustedSource);
+ void componentComplete() override;
+
signals:
void sourceChanged();
void fillModeChanged();
@@ -74,7 +76,7 @@ signals:
void assumeTrustedSourceChanged();
private slots:
- void updateSvgItemScale();
+ void updateRootItemScale();
void updateAnimationProperties();
private:
diff --git a/src/quickvectorimage/qquickvectorimage_p_p.h b/src/quickvectorimage/qquickvectorimage_p_p.h
index 6779666457..6018e7ae58 100644
--- a/src/quickvectorimage/qquickvectorimage_p_p.h
+++ b/src/quickvectorimage/qquickvectorimage_p_p.h
@@ -30,21 +30,15 @@ public:
virtual ~QQuickVectorImagePrivate() = default;
void setSource(const QUrl &source);
- void loadSvg();
+ void loadFile();
static QQuickVectorImagePrivate *get(QQuickVectorImage *q)
{
return q->d_func();
}
- enum Format {
- Unknown,
- Svg
- };
- QQuickVectorImagePrivate::Format formatFromFilePath(const QString &filePath);
-
QUrl sourceFile;
- QQuickItem *svgItem = nullptr;
+ QQuickItem *rootItem = nullptr;
QQuickVectorImage::FillMode fillMode = QQuickVectorImage::Stretch;
QQuickVectorImage::RendererType preferredRendererType = QQuickVectorImage::GeometryRenderer;
QQuickVectorImageAnimations *animations = nullptr;
diff --git a/src/quickvectorimage/qquickvectorimageplugin.cpp b/src/quickvectorimage/qquickvectorimageplugin.cpp
new file mode 100644
index 0000000000..0fc2ae9e24
--- /dev/null
+++ b/src/quickvectorimage/qquickvectorimageplugin.cpp
@@ -0,0 +1,14 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickvectorimageplugin_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQuickVectorImagePlugin::QQuickVectorImagePlugin()
+{}
+
+QQuickVectorImagePlugin::~QQuickVectorImagePlugin()
+{}
+
+QT_END_NAMESPACE
diff --git a/src/quickvectorimage/qquickvectorimageplugin_p.h b/src/quickvectorimage/qquickvectorimageplugin_p.h
new file mode 100644
index 0000000000..02f62a5caf
--- /dev/null
+++ b/src/quickvectorimage/qquickvectorimageplugin_p.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQUICKVECTORIMAGEPLUGIN_P_H
+#define QQUICKVECTORIMAGEPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QObject>
+#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
+
+#define QQuickVectorImageFormatsPluginFactory_iid "org.qt-project.Qt.QVectorImageFormatsPluginFactory"
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICKVECTORIMAGEGENERATOR_EXPORT QQuickVectorImagePlugin
+{
+public:
+ QQuickVectorImagePlugin();
+ virtual ~QQuickVectorImagePlugin();
+
+ virtual bool generate(const QString &fileName, QQuickItemGenerator *generator) = 0;
+};
+
+#define QQuickVectorImageFormatsPluginInterface_iid "org.qt-project.Qt.QVectorImageFormatsPluginInterface"
+Q_DECLARE_INTERFACE(QQuickVectorImagePlugin, QQuickVectorImageFormatsPluginInterface_iid)
+
+QT_END_NAMESPACE
+
+#endif // QQUICKVECTORIMAGEPLUGIN_P_H