1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include <QtQuickVectorImageGenerator/private/qquickvectorimageplugin_p.h>
5#include <QtLottieVectorImageGenerator/private/qlottievisitor_p.h>
6#include <QtLottie/private/qlottieroot_p.h>
7#include <QtCore/qfile.h>
8#include <QtCore/qscopeguard.h>
9
10#include <QtQuick/private/qquickanimation_p.h>
11
12QT_BEGIN_NAMESPACE
13
14class QLottieVectorImagePlugin : public QObject, public QQuickVectorImagePlugin
15{
16 Q_OBJECT
17 Q_PLUGIN_METADATA(IID QQuickVectorImageFormatsPluginFactory_iid FILE "lottie.json")
18 Q_INTERFACES(QQuickVectorImagePlugin)
19public:
20 QLottieVectorImagePlugin();
21 ~QLottieVectorImagePlugin();
22
23 bool generate(const QString &fileName, QQuickItemGenerator *generator) override;
24
25private:
26 bool canRead(QIODevice &input) const;
27};
28
29QLottieVectorImagePlugin::QLottieVectorImagePlugin()
30{
31}
32
33QLottieVectorImagePlugin::~QLottieVectorImagePlugin()
34{
35}
36
37bool QLottieVectorImagePlugin::generate(const QString &fileName, QQuickItemGenerator *generator)
38{
39 QFile f(fileName);
40 QLottieRoot root;
41
42 if (f.open(flags: QIODevice::ReadOnly) && canRead(input&: f)) {
43 QByteArray jsonSource = f.readAll();
44
45 static int frameNo = qEnvironmentVariableIntValue(varName: "QLT_FRAMENO");
46
47 if (!root.parseSource(jsonSource, fileSource: fileName)) {
48 if (frameNo < 0)
49 frameNo = root.startFrame() + (root.endFrame() - root.startFrame()) / 2;
50
51 root.setStructureDumping(true);
52 for (QLottieBase *elem : root.children()) {
53 if (elem->active(frame: 0))
54 elem->updateProperties(frame: 0);
55 }
56
57 generator->addExtraImport(import: QLatin1String("Qt.labs.lottieqt.VectorImageHelpers"));
58 QLottieVisitor visitor(fileName, generator);
59 visitor.render(layer: root);
60
61 if (frameNo > 0) {
62 QQuickItem *item = generator->parentItem();
63 const int seekTime = qRound(d: 1000.0 * frameNo / root.frameRate());
64
65 QList<QQuickAbstractAnimation *> animations = item->findChildren<QQuickAbstractAnimation *>();
66 for (QQuickAbstractAnimation *animation : animations) {
67 if (animation->group() == nullptr)
68 animation->setCurrentTime(seekTime);
69 }
70 }
71
72 return true;
73 }
74 }
75
76 return false;
77}
78
79bool QLottieVectorImagePlugin::canRead(QIODevice &input) const
80{
81 const qint64 pos = input.pos();
82 auto cleanup = qScopeGuard(f: [&] { input.seek(pos); });
83 QTextStream s(&input);
84 const QString head = s.read(maxlen: 256);
85 bool res = QStringView(head).trimmed().startsWith(c: QChar::fromLatin1(c: '{'));
86 return res;
87}
88
89QT_END_NAMESPACE
90
91#include "main.moc"
92

source code of qtlottie/src/plugins/vectorimageformats/lottie/main.cpp