1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "bmstroke_p.h"
5
6#include <QLoggingCategory>
7
8#include "bmconstants_p.h"
9
10QT_BEGIN_NAMESPACE
11
12BMStroke::BMStroke(const BMStroke &other)
13 : BMShape(other)
14{
15 m_opacity = other.m_opacity;
16 m_width = other.m_width;
17 m_color = other.m_color;
18 m_capStyle = other.m_capStyle;
19 m_joinStyle = other.m_joinStyle;
20 m_miterLimit = other.m_miterLimit;
21 m_dashOffset = other.m_dashOffset;
22 m_dashLength = other.m_dashLength;
23 m_dashGap = other.m_dashGap;
24 m_isDashed = other.m_isDashed;
25}
26
27BMStroke::BMStroke(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
28{
29 setParent(parent);
30
31 BMBase::parse(definition);
32 if (m_hidden)
33 return;
34
35 qCDebug(lcLottieQtBodymovinParser) << "BMStroke::BMStroke()" << m_name;
36
37 int lineCap = definition.value(key: QLatin1String("lc")).toVariant().toInt();
38 switch (lineCap) {
39 case 1:
40 m_capStyle = Qt::FlatCap;
41 break;
42 case 2:
43 m_capStyle = Qt::RoundCap;
44 break;
45 case 3:
46 m_capStyle = Qt::SquareCap;
47 break;
48 default:
49 qCDebug(lcLottieQtBodymovinParser) << "Unknown line cap style in BMStroke";
50 }
51
52 int lineJoin = definition.value(key: QLatin1String("lj")).toVariant().toInt();
53 switch (lineJoin) {
54 case 1:
55 m_joinStyle = Qt::MiterJoin;
56 m_miterLimit = definition.value(key: QLatin1String("ml")).toVariant().toReal();
57 break;
58 case 2:
59 m_joinStyle = Qt::RoundJoin;
60 break;
61 case 3:
62 m_joinStyle = Qt::BevelJoin;
63 break;
64 default:
65 qCDebug(lcLottieQtBodymovinParser) << "Unknown line join style in BMStroke";
66 }
67
68 QJsonObject opacity = definition.value(key: QLatin1String("o")).toObject();
69 opacity = resolveExpression(definition: opacity);
70 m_opacity.construct(definition: opacity, version);
71
72 QJsonObject width = definition.value(key: QLatin1String("w")).toObject();
73 width = resolveExpression(definition: width);
74 m_width.construct(definition: width, version);
75
76 QJsonObject color = definition.value(key: QLatin1String("c")).toObject();
77 color = resolveExpression(definition: color);
78 m_color.construct(definition: color, version);
79
80 QJsonArray dashes = definition.value(key: QLatin1String("d")).toArray();
81 if (dashes.size()) {
82 auto it = dashes.cend();
83 while (it != dashes.cbegin()) {
84 --it;
85 QJsonObject dashSpec = it->toObject();
86 QJsonObject val = resolveExpression(definition: dashSpec.value(key: QLatin1String("v")).toObject());
87 QString n = dashSpec.value(key: QLatin1String("n")).toString();
88 if (n == QLatin1String("o"))
89 m_dashOffset.construct(definition: val, version);
90 else if (n == QLatin1String("g"))
91 m_dashGap.construct(definition: val, version);
92 else if (n == QLatin1String("d"))
93 m_dashLength.construct(definition: val, version);
94 }
95 m_isDashed = true;
96 }
97}
98
99BMBase *BMStroke::clone() const
100{
101 return new BMStroke(*this);
102}
103
104void BMStroke::updateProperties(int frame)
105{
106 m_opacity.update(frame);
107 m_width.update(frame);
108 m_color.update(frame);
109 if (m_isDashed) {
110 m_dashOffset.update(frame);
111 m_dashLength.update(frame);
112 m_dashGap.update(frame);
113 }
114}
115
116void BMStroke::render(LottieRenderer &renderer) const
117{
118 renderer.render(stroke: *this);
119}
120
121QPen BMStroke::pen() const
122{
123 qreal width = m_width.value();
124 if (qFuzzyIsNull(d: width))
125 return QPen(Qt::NoPen);
126 QPen pen;
127 pen.setColor(getColor());
128 pen.setWidthF(width);
129 pen.setCapStyle(m_capStyle);
130 pen.setJoinStyle(m_joinStyle);
131 pen.setMiterLimit(m_miterLimit);
132 if (m_isDashed) {
133 pen.setDashOffset(m_dashOffset.value() / width);
134 pen.setDashPattern({m_dashLength.value() / width, m_dashGap.value() / width});
135 }
136 return pen;
137}
138
139QColor BMStroke::getColor() const
140{
141 QVector4D cVec = m_color.value();
142 QColor color;
143 qreal r = static_cast<qreal>(cVec.x());
144 qreal g = static_cast<qreal>(cVec.y());
145 qreal b = static_cast<qreal>(cVec.z());
146 qreal a = static_cast<qreal>(cVec.w());
147 color.setRgbF(r, g, b, a);
148 return color;
149}
150
151qreal BMStroke::opacity() const
152{
153 return m_opacity.value();
154}
155
156QT_END_NAMESPACE
157

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