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 | |
13 | BMTrimPath::BMTrimPath() |
14 | { |
15 | m_appliedTrim = this; |
16 | } |
17 | |
18 | BMTrimPath::BMTrimPath(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent) |
19 | { |
20 | m_appliedTrim = this; |
21 | |
22 | setParent(parent); |
23 | construct(definition, version); |
24 | } |
25 | |
26 | BMTrimPath::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 | |
35 | BMBase *BMTrimPath::clone() const |
36 | { |
37 | return new BMTrimPath(*this); |
38 | } |
39 | |
40 | void 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 | |
75 | void 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 | |
87 | void 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 | |
100 | bool BMTrimPath::acceptsTrim() const |
101 | { |
102 | return true; |
103 | } |
104 | |
105 | void 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 | |
121 | qreal BMTrimPath::start() const |
122 | { |
123 | return m_start.value(); |
124 | } |
125 | |
126 | qreal BMTrimPath::end() const |
127 | { |
128 | return m_end.value(); |
129 | } |
130 | |
131 | qreal BMTrimPath::offset() const |
132 | { |
133 | return m_offset.value(); |
134 | } |
135 | |
136 | bool BMTrimPath::simultaneous() const |
137 | { |
138 | return m_simultaneous; |
139 | } |
140 | |
141 | QPainterPath 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 | |