1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qlottiegroup_p.h"
5
6#include <QJsonObject>
7#include <QJsonArray>
8
9#include "qlottiebase_p.h"
10#include "qlottieshape_p.h"
11#include "qlottietrimpath_p.h"
12#include "qlottiebasictransform_p.h"
13
14QT_BEGIN_NAMESPACE
15
16QLottieGroup::QLottieGroup(const QJsonObject &definition, QLottieBase *parent)
17{
18 setParent(parent);
19 construct(definition);
20}
21
22QLottieBase *QLottieGroup::clone() const
23{
24 return new QLottieGroup(*this);
25}
26
27void QLottieGroup::construct(const QJsonObject &definition)
28{
29 QLottieBase::parse(definition);
30 if (m_hidden)
31 return;
32
33 qCDebug(lcLottieQtLottieParser) << "QLottieGroup::construct()"
34 << m_name;
35
36 QJsonArray groupItems = definition.value(key: QLatin1String("it")).toArray();
37 QJsonArray::const_iterator itemIt = groupItems.constEnd();
38 while (itemIt != groupItems.constBegin()) {
39 itemIt--;
40 QLottieShape *shape = QLottieShape::construct(definition: (*itemIt).toObject(), parent: this);
41 if (shape) {
42 // Transform affects how group contents are drawn.
43 // It must be traversed first when drawing
44 if (shape->type() == LOTTIE_SHAPE_TRANS_IX)
45 prependChild(child: shape);
46 else
47 appendChild(child: shape);
48 }
49 }
50}
51
52void QLottieGroup::updateProperties(int frame)
53{
54 QLottieShape::updateProperties(frame);
55
56 for (QLottieBase *child : children()) {
57 if (child->hidden())
58 continue;
59
60 QLottieShape *shape = static_cast<QLottieShape*>(child);
61 if (shape->type() == LOTTIE_SHAPE_TRIM_IX) {
62 QLottieTrimPath *trim = static_cast<QLottieTrimPath*>(shape);
63 if (m_appliedTrim)
64 m_appliedTrim->applyTrim(trimmer: *trim);
65 else
66 m_appliedTrim = trim;
67 } else if (m_appliedTrim && shape->acceptsTrim())
68 shape->applyTrim(trimmer: *m_appliedTrim);
69 }
70}
71
72void QLottieGroup::render(QLottieRenderer &renderer) const
73{
74 qCDebug(lcLottieQtLottieRender) << "Group:" << name();
75
76 renderer.saveState();
77
78 renderer.render(*this);
79
80 if (m_appliedTrim && !m_appliedTrim->hidden()) {
81 if (m_appliedTrim->isParallel())
82 renderer.setTrimmingState(QLottieRenderer::Parallel);
83 else
84 renderer.setTrimmingState(QLottieRenderer::Sequential);
85 } else
86 renderer.setTrimmingState(QLottieRenderer::Off);
87
88 for (QLottieBase *child : children()) {
89 if (child->hidden())
90 continue;
91 child->render(renderer);
92 }
93
94 if (m_appliedTrim && !m_appliedTrim->hidden() && !m_appliedTrim->isParallel())
95 m_appliedTrim->render(renderer);
96
97 renderer.finish(*this);
98
99 renderer.restoreState();
100}
101
102bool QLottieGroup::acceptsTrim() const
103{
104 return true;
105}
106
107void QLottieGroup::applyTrim(const QLottieTrimPath &trimmer)
108{
109 Q_ASSERT_X(!m_appliedTrim, "QLottieGroup", "A trim already assigned");
110
111 m_appliedTrim = static_cast<QLottieTrimPath*>(trimmer.clone());
112 m_appliedTrim->setParent(parent());
113 // Setting a friendly name helps in testing
114 m_appliedTrim->setName(QStringLiteral("Inherited from") + trimmer.name());
115
116 for (QLottieBase *child : children()) {
117 QLottieShape *shape = static_cast<QLottieShape*>(child);
118 if (shape->acceptsTrim())
119 shape->applyTrim(trimmer: *m_appliedTrim);
120 }
121}
122
123QT_END_NAMESPACE
124

source code of qtlottie/src/lottie/qlottiegroup.cpp