diff options
| author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2025-06-18 08:38:33 +0200 |
|---|---|---|
| committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2025-06-19 10:44:44 +0200 |
| commit | 4154d2538419476ceaa3107dc417160f89c7eedc (patch) | |
| tree | 45c01e471db1df660c6095f06b53fdc38d6cb6c3 /src | |
| parent | cd89ebc95f76923a3b81389b9a63a21987602873 (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.txt | 2 | ||||
| -rw-r--r-- | src/quickvectorimage/qquickvectorimage.cpp | 110 | ||||
| -rw-r--r-- | src/quickvectorimage/qquickvectorimage_p.h | 4 | ||||
| -rw-r--r-- | src/quickvectorimage/qquickvectorimage_p_p.h | 10 | ||||
| -rw-r--r-- | src/quickvectorimage/qquickvectorimageplugin.cpp | 14 | ||||
| -rw-r--r-- | src/quickvectorimage/qquickvectorimageplugin_p.h | 39 |
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 |
