1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "bmtrimpath_p.h"
5
6#include <QtGlobal>
7#include <private/qpainterpath_p.h>
8#include <private/qbezier_p.h>
9
10#include "bmconstants_p.h"
11#include "trimpath_p.h"
12
13BMTrimPath::BMTrimPath()
14{
15 m_appliedTrim = this;
16}
17
18BMTrimPath::BMTrimPath(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
19{
20 m_appliedTrim = this;
21
22 setParent(parent);
23 construct(definition, version);
24}
25
26BMTrimPath::BMTrimPath(const BMTrimPath &other)
27 : BMShape(other)
28{
29 m_start = other.m_start;
30 m_end = other.m_end;
31 m_offset = other.m_offset;
32 m_simultaneous = other.m_simultaneous;
33}
34
35BMBase *BMTrimPath::clone() const
36{
37 return new BMTrimPath(*this);
38}
39
40void BMTrimPath::construct(const QJsonObject &definition, const QVersionNumber &version)
41{
42 BMBase::parse(definition);
43 if (m_hidden)
44 return;
45
46 qCDebug(lcLottieQtBodymovinParser) << "BMTrimPath::construct():" << m_name;
47
48 QJsonObject start = definition.value(key: QLatin1String("s")).toObject();
49 start = resolveExpression(definition: start);
50 m_start.construct(definition: start, version);
51
52 QJsonObject end = definition.value(key: QLatin1String("e")).toObject();
53 end = resolveExpression(definition: end);
54 m_end.construct(definition: end, version);
55
56 QJsonObject offset = definition.value(key: QLatin1String("o")).toObject();
57 offset = resolveExpression(definition: offset);
58 m_offset.construct(definition: offset, version);
59
60 int simultaneous = true;
61 if (definition.contains(key: QLatin1String("m"))) {
62 simultaneous = definition.value(key: QLatin1String("m")).toInt();
63 }
64 m_simultaneous = (simultaneous == 1);
65
66 if (strcmp(s1: qgetenv(varName: "QLOTTIE_FORCE_TRIM_MODE"), s2: "simultaneous") == 0) {
67 qCDebug(lcLottieQtBodymovinRender) << "Forcing trim mode to Simultaneous";
68 m_simultaneous = true;
69 } else if (strcmp(s1: qgetenv(varName: "QLOTTIE_FORCE_TRIM_MODE"), s2: "individual") == 0) {
70 qCDebug(lcLottieQtBodymovinRender) << "Forcing trim mode to Individual";
71 m_simultaneous = false;
72 }
73}
74
75void BMTrimPath::updateProperties(int frame)
76{
77 m_start.update(frame);
78 m_end.update(frame);
79 m_offset.update(frame);
80
81 qCDebug(lcLottieQtBodymovinUpdate) << name() << frame << m_start.value()
82 << m_end.value() << m_offset.value();
83
84 BMShape::updateProperties(frame);
85}
86
87void BMTrimPath::render(LottieRenderer &renderer) const
88{
89 if (m_appliedTrim) {
90 if (m_appliedTrim->simultaneous())
91 renderer.setTrimmingState(LottieRenderer::Simultaneous);
92 else
93 renderer.setTrimmingState(LottieRenderer::Individual);
94 } else
95 renderer.setTrimmingState(LottieRenderer::Off);
96
97 renderer.render(trans: *this);
98}
99
100bool BMTrimPath::acceptsTrim() const
101{
102 return true;
103}
104
105void BMTrimPath::applyTrim(const BMTrimPath &other)
106{
107 qCDebug(lcLottieQtBodymovinUpdate) << "Join trim paths:"
108 << other.name() << "into:" << name();
109
110 m_name = m_name + QStringLiteral(" & ") + other.name();
111 qreal newStart = other.start() + (m_start.value() / 100.0) *
112 (other.end() - other.start());
113 qreal newEnd = other.start() + (m_end.value() / 100.0) *
114 (other.end() - other.start());
115
116 m_start.setValue(newStart);
117 m_end.setValue(newEnd);
118 m_offset.setValue(m_offset.value() + other.offset());
119}
120
121qreal BMTrimPath::start() const
122{
123 return m_start.value();
124}
125
126qreal BMTrimPath::end() const
127{
128 return m_end.value();
129}
130
131qreal BMTrimPath::offset() const
132{
133 return m_offset.value();
134}
135
136bool BMTrimPath::simultaneous() const
137{
138 return m_simultaneous;
139}
140
141QPainterPath BMTrimPath::trim(const QPainterPath &path) const
142{
143 TrimPath trimmer;
144 trimmer.setPath(path);
145 qreal offset = m_offset.value() / 360.0;
146 qreal start = m_start.value() / 100.0;
147 qreal end = m_end.value() / 100.0;
148 QPainterPath trimmedPath;
149 if (!qFuzzyIsNull(d: start - end))
150 trimmedPath = trimmer.trimmed(f1: start, f2: end, offset);
151 return trimmedPath;
152}
153

source code of qtlottie/src/bodymovin/bmtrimpath.cpp