summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKwanghyo Park <kwanghyo.park@qt.io>2022-06-21 15:50:56 +0300
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-12-14 08:05:54 +0000
commit528ca10ab1c7044ecca2ceea92fd3f73bf44e800 (patch)
tree6ffea207c545dc36e64dc8f726ead1060f4d0918 /src
parent930db8b306ce3f2fd89d05ff952020ceee988672 (diff)
Fix an error on parsing property animation keyframes
There was update on bodymovin schema on animating property. Applying those updates. Preserve old implementation for backward compatibility. Task-number: QTBUG-102550 Change-Id: I1ca18ca727e267b6e5e442e1fae4b5aa72572ece Reviewed-by: Kwanghyo Park <kwanghyo.park@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io> Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> Reviewed-by: Janne Koskinen <janne.p.koskinen@qt.io> (cherry picked from commit f467e29f74fd121b62ad66cb70da9a4b7f6e3248) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/bodymovin/bmbase_p.h3
-rw-r--r--src/bodymovin/bmbasictransform.cpp21
-rw-r--r--src/bodymovin/bmbasictransform_p.h5
-rw-r--r--src/bodymovin/bmellipse.cpp11
-rw-r--r--src/bodymovin/bmellipse_p.h5
-rw-r--r--src/bodymovin/bmfill.cpp6
-rw-r--r--src/bodymovin/bmfill_p.h2
-rw-r--r--src/bodymovin/bmfilleffect.cpp10
-rw-r--r--src/bodymovin/bmfilleffect_p.h2
-rw-r--r--src/bodymovin/bmfreeformshape.cpp14
-rw-r--r--src/bodymovin/bmfreeformshape_p.h5
-rw-r--r--src/bodymovin/bmgfill.cpp12
-rw-r--r--src/bodymovin/bmgfill_p.h2
-rw-r--r--src/bodymovin/bmgroup.cpp8
-rw-r--r--src/bodymovin/bmgroup_p.h4
-rw-r--r--src/bodymovin/bmimage.cpp10
-rw-r--r--src/bodymovin/bmimage_p.h4
-rw-r--r--src/bodymovin/bmimagelayer.cpp9
-rw-r--r--src/bodymovin/bmimagelayer_p.h2
-rw-r--r--src/bodymovin/bmlayer.cpp8
-rw-r--r--src/bodymovin/bmlayer_p.h4
-rw-r--r--src/bodymovin/bmproperty_p.h144
-rw-r--r--src/bodymovin/bmrect.cpp8
-rw-r--r--src/bodymovin/bmrect_p.h4
-rw-r--r--src/bodymovin/bmrepeater.cpp12
-rw-r--r--src/bodymovin/bmrepeater_p.h5
-rw-r--r--src/bodymovin/bmrepeatertransform.cpp13
-rw-r--r--src/bodymovin/bmrepeatertransform_p.h5
-rw-r--r--src/bodymovin/bmround.cpp10
-rw-r--r--src/bodymovin/bmround_p.h4
-rw-r--r--src/bodymovin/bmshape.cpp24
-rw-r--r--src/bodymovin/bmshape_p.h3
-rw-r--r--src/bodymovin/bmshapelayer.cpp7
-rw-r--r--src/bodymovin/bmshapelayer_p.h2
-rw-r--r--src/bodymovin/bmshapetransform.cpp13
-rw-r--r--src/bodymovin/bmshapetransform_p.h4
-rw-r--r--src/bodymovin/bmspatialproperty_p.h61
-rw-r--r--src/bodymovin/bmstroke.cpp8
-rw-r--r--src/bodymovin/bmstroke_p.h3
-rw-r--r--src/bodymovin/bmtrimpath.cpp12
-rw-r--r--src/bodymovin/bmtrimpath_p.h5
-rw-r--r--src/imports/lottieanimation.cpp11
-rw-r--r--src/imports/lottieanimation.h3
-rw-r--r--src/imports/rasterrenderer/batchrenderer.cpp7
-rw-r--r--src/imports/rasterrenderer/batchrenderer.h4
45 files changed, 362 insertions, 157 deletions
diff --git a/src/bodymovin/bmbase_p.h b/src/bodymovin/bmbase_p.h
index a2bad4e..9d39f2c 100644
--- a/src/bodymovin/bmbase_p.h
+++ b/src/bodymovin/bmbase_p.h
@@ -17,6 +17,7 @@
#include <QJsonObject>
#include <QList>
+#include <QVersionNumber>
#include <QtBodymovin/bmglobal.h>
#include <QtBodymovin/private/bmconstants_p.h>
@@ -24,7 +25,6 @@
#include <QtBodymovin/private/lottierenderer_p.h>
QT_BEGIN_NAMESPACE
-
class BODYMOVIN_EXPORT BMBase
{
public:
@@ -69,6 +69,7 @@ protected:
QJsonObject m_definition;
int m_type;
bool m_hidden = false;
+ QVersionNumber m_version;
QString m_name;
QString m_matchName;
bool m_autoOrient = false;
diff --git a/src/bodymovin/bmbasictransform.cpp b/src/bodymovin/bmbasictransform.cpp
index 025ea1d..b9ddbe3 100644
--- a/src/bodymovin/bmbasictransform.cpp
+++ b/src/bodymovin/bmbasictransform.cpp
@@ -23,10 +23,11 @@ BMBasicTransform::BMBasicTransform(const BMBasicTransform &other)
m_opacity = other.m_opacity;
}
-BMBasicTransform::BMBasicTransform(const QJsonObject &definition, BMBase *parent)
+BMBasicTransform::BMBasicTransform(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMBasicTransform::clone() const
@@ -34,7 +35,7 @@ BMBase *BMBasicTransform::clone() const
return new BMBasicTransform(*this);
}
-void BMBasicTransform::construct(const QJsonObject &definition)
+void BMBasicTransform::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
@@ -43,38 +44,38 @@ void BMBasicTransform::construct(const QJsonObject &definition)
QJsonObject anchors = definition.value(QLatin1String("a")).toObject();
anchors = resolveExpression(anchors);
- m_anchorPoint.construct(anchors);
+ m_anchorPoint.construct(anchors, version);
if (definition.value(QLatin1String("p")).toObject().contains(QLatin1String("s"))) {
QJsonObject posX = definition.value(QLatin1String("p")).toObject().value(QLatin1String("x")).toObject();
posX = resolveExpression(posX);
- m_xPos.construct(posX);
+ m_xPos.construct(posX, version);
QJsonObject posY = definition.value(QLatin1String("p")).toObject().value(QLatin1String("y")).toObject();
posY = resolveExpression(posY);
- m_yPos.construct(posY);
+ m_yPos.construct(posY, version);
m_splitPosition = true;
} else {
QJsonObject position = definition.value(QLatin1String("p")).toObject();
position = resolveExpression(position);
- m_position.construct(position);
+ m_position.construct(position, version);
}
QJsonObject scale = definition.value(QLatin1String("s")).toObject();
scale = resolveExpression(scale);
- m_scale.construct(scale);
+ m_scale.construct(scale, version);
QJsonObject rotation = definition.value(QLatin1String("r")).toObject();
rotation = resolveExpression(rotation);
- m_rotation.construct(rotation);
+ m_rotation.construct(rotation, version);
// If this is the base class for BMRepeaterTransform,
// opacity is not present
if (definition.contains(QLatin1String("o"))) {
QJsonObject opacity = definition.value(QLatin1String("o")).toObject();
opacity = resolveExpression(opacity);
- m_opacity.construct(opacity);
+ m_opacity.construct(opacity, version);
}
}
diff --git a/src/bodymovin/bmbasictransform_p.h b/src/bodymovin/bmbasictransform_p.h
index 819a6be..dff200d 100644
--- a/src/bodymovin/bmbasictransform_p.h
+++ b/src/bodymovin/bmbasictransform_p.h
@@ -30,11 +30,12 @@ class BODYMOVIN_EXPORT BMBasicTransform : public BMShape
public:
BMBasicTransform() = default;
explicit BMBasicTransform(const BMBasicTransform &other);
- BMBasicTransform(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMBasicTransform(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmellipse.cpp b/src/bodymovin/bmellipse.cpp
index e4c2e81..983c362 100644
--- a/src/bodymovin/bmellipse.cpp
+++ b/src/bodymovin/bmellipse.cpp
@@ -17,10 +17,10 @@ BMEllipse::BMEllipse(const BMEllipse &other)
m_size = other.m_size;
}
-BMEllipse::BMEllipse(const QJsonObject &definition, BMBase *parent)
+BMEllipse::BMEllipse(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMEllipse::clone() const
@@ -28,8 +28,7 @@ BMBase *BMEllipse::clone() const
return new BMEllipse(*this);
}
-
-void BMEllipse::construct(const QJsonObject &definition)
+void BMEllipse::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
if (m_hidden)
@@ -39,11 +38,11 @@ void BMEllipse::construct(const QJsonObject &definition)
QJsonObject position = definition.value(QLatin1String("p")).toObject();
position = resolveExpression(position);
- m_position.construct(position);
+ m_position.construct(position, version);
QJsonObject size = definition.value(QLatin1String("s")).toObject();
size = resolveExpression(size);
- m_size.construct(size);
+ m_size.construct(size, version);
m_direction = definition.value(QLatin1String("d")).toInt();
}
diff --git a/src/bodymovin/bmellipse_p.h b/src/bodymovin/bmellipse_p.h
index 08167b2..b4b7c47 100644
--- a/src/bodymovin/bmellipse_p.h
+++ b/src/bodymovin/bmellipse_p.h
@@ -36,11 +36,12 @@ class BODYMOVIN_EXPORT BMEllipse : public BMShape
public:
BMEllipse() = default;
explicit BMEllipse(const BMEllipse &other);
- BMEllipse(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMEllipse(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmfill.cpp b/src/bodymovin/bmfill.cpp
index 071a614..df79e05 100644
--- a/src/bodymovin/bmfill.cpp
+++ b/src/bodymovin/bmfill.cpp
@@ -12,7 +12,7 @@ BMFill::BMFill(const BMFill &other)
m_opacity = other.m_opacity;
}
-BMFill::BMFill(const QJsonObject &definition, BMBase *parent)
+BMFill::BMFill(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
BMBase::parse(definition);
@@ -22,11 +22,11 @@ BMFill::BMFill(const QJsonObject &definition, BMBase *parent)
qCDebug(lcLottieQtBodymovinParser) << "BMFill::construct():" << m_name;
QJsonObject color = definition.value(QLatin1String("c")).toObject();
- m_color.construct(color);
+ m_color.construct(color, version);
QJsonObject opacity = definition.value(QLatin1String("o")).toObject();
opacity = resolveExpression(opacity);
- m_opacity.construct(opacity);
+ m_opacity.construct(opacity, version);
}
BMBase *BMFill::clone() const
diff --git a/src/bodymovin/bmfill_p.h b/src/bodymovin/bmfill_p.h
index 67e9f27..c589e48 100644
--- a/src/bodymovin/bmfill_p.h
+++ b/src/bodymovin/bmfill_p.h
@@ -28,7 +28,7 @@ class BODYMOVIN_EXPORT BMFill : public BMShape
public:
BMFill() = default;
explicit BMFill(const BMFill &other);
- BMFill(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMFill(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent = nullptr);
BMBase *clone() const override;
diff --git a/src/bodymovin/bmfilleffect.cpp b/src/bodymovin/bmfilleffect.cpp
index 648393c..b19aba0 100644
--- a/src/bodymovin/bmfilleffect.cpp
+++ b/src/bodymovin/bmfilleffect.cpp
@@ -22,7 +22,7 @@ BMBase *BMFillEffect::clone() const
return new BMFillEffect(*this);
}
-void BMFillEffect::construct(const QJsonObject &definition)
+void BMFillEffect::construct(const QJsonObject &definition, const QVersionNumber &version)
{
m_type = BM_EFFECT_FILL;
@@ -33,8 +33,8 @@ void BMFillEffect::construct(const QJsonObject &definition)
// TODO: Check are property positions really fixed in the effect?
- m_color.construct(properties.at(2).toObject().value(QLatin1String("v")).toObject());
- m_opacity.construct(properties.at(6).toObject().value(QLatin1String("v")).toObject());
+ m_color.construct(properties.at(2).toObject().value(QLatin1String("v")).toObject(), version);
+ m_opacity.construct(properties.at(6).toObject().value(QLatin1String("v")).toObject(), version);
if (!qFuzzyCompare(properties.at(0).toObject().value(QLatin1String("v")).toObject().value(QLatin1String("k")).toDouble(), 0.0))
qCWarning(lcLottieQtBodymovinParser)<< "BMFillEffect: Property 'Fill mask' not supported";
@@ -49,8 +49,8 @@ void BMFillEffect::construct(const QJsonObject &definition)
qCWarning(lcLottieQtBodymovinParser) << "BMFillEffect: Property 'Horizontal feather' not supported";
if (!qFuzzyCompare(properties.at(5).toObject().value(QLatin1String("v")).toObject().value(QLatin1String("k")).toDouble(), 0.0))
- qCWarning(lcLottieQtBodymovinParser) << "BMFillEffect: Property 'Vertical feather' not supported";
-
+ qCWarning(lcLottieQtBodymovinParser)
+ << "BMFillEffect: Property 'Vertical feather' not supported";
}
void BMFillEffect::updateProperties(int frame)
diff --git a/src/bodymovin/bmfilleffect_p.h b/src/bodymovin/bmfilleffect_p.h
index b71dd96..a2f5043 100644
--- a/src/bodymovin/bmfilleffect_p.h
+++ b/src/bodymovin/bmfilleffect_p.h
@@ -33,7 +33,7 @@ public:
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmfreeformshape.cpp b/src/bodymovin/bmfreeformshape.cpp
index 0cfd83b..ded4e92 100644
--- a/src/bodymovin/bmfreeformshape.cpp
+++ b/src/bodymovin/bmfreeformshape.cpp
@@ -19,10 +19,11 @@ BMFreeFormShape::BMFreeFormShape(const BMFreeFormShape &other)
m_vertexMap = other.m_vertexMap;
}
-BMFreeFormShape::BMFreeFormShape(const QJsonObject &definition, BMBase *parent)
+BMFreeFormShape::BMFreeFormShape(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMFreeFormShape::clone() const
@@ -30,9 +31,10 @@ BMBase *BMFreeFormShape::clone() const
return new BMFreeFormShape(*this);
}
-void BMFreeFormShape::construct(const QJsonObject &definition)
+void BMFreeFormShape::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
+ m_version = version;
if (m_hidden)
return;
@@ -289,9 +291,9 @@ void BMFreeFormShape::finalizeVertices()
coObj.insert(QLatin1String("k"), m_vertexInfos.value(i)->coKeyframes);
VertexInfo vertexInfo;
- vertexInfo.pos.construct(posObj);
- vertexInfo.ci.construct(ciObj);
- vertexInfo.co.construct(coObj);
+ vertexInfo.pos.construct(posObj, m_version);
+ vertexInfo.ci.construct(ciObj, m_version);
+ vertexInfo.co.construct(coObj, m_version);
m_vertexList.push_back(vertexInfo);
}
qDeleteAll(m_vertexInfos);
diff --git a/src/bodymovin/bmfreeformshape_p.h b/src/bodymovin/bmfreeformshape_p.h
index 220e1b2..b46d3f7 100644
--- a/src/bodymovin/bmfreeformshape_p.h
+++ b/src/bodymovin/bmfreeformshape_p.h
@@ -35,11 +35,12 @@ class BODYMOVIN_EXPORT BMFreeFormShape : public BMShape
public:
BMFreeFormShape();
explicit BMFreeFormShape(const BMFreeFormShape &other);
- BMFreeFormShape(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMFreeFormShape(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmgfill.cpp b/src/bodymovin/bmgfill.cpp
index b2c109d..84e8f37 100644
--- a/src/bodymovin/bmgfill.cpp
+++ b/src/bodymovin/bmgfill.cpp
@@ -42,7 +42,7 @@ BMBase *BMGFill::clone() const
return new BMGFill(*this);
}
-BMGFill::BMGFill(const QJsonObject &definition, BMBase *parent)
+BMGFill::BMGFill(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
@@ -82,22 +82,22 @@ BMGFill::BMGFill(const QJsonObject &definition, BMBase *parent)
QJsonObject opacity = definition.value(QLatin1String("o")).toObject();
opacity = resolveExpression(opacity);
- m_opacity.construct(opacity);
+ m_opacity.construct(opacity, version);
QJsonObject startPoint = definition.value(QLatin1String("s")).toObject();
startPoint = resolveExpression(startPoint);
- m_startPoint.construct(startPoint);
+ m_startPoint.construct(startPoint, version);
QJsonObject endPoint = definition.value(QLatin1String("e")).toObject();
endPoint = resolveExpression(endPoint);
- m_endPoint.construct(endPoint);
+ m_endPoint.construct(endPoint, version);
QJsonObject highlight = definition.value(QLatin1String("h")).toObject();
- m_highlightLength.construct(highlight);
+ m_highlightLength.construct(highlight, version);
QJsonObject angle = definition.value(QLatin1String("a")).toObject();
angle = resolveExpression(angle);
- m_highlightAngle.construct(angle);
+ m_highlightAngle.construct(angle, version);
m_highlightAngle.setValue(0.0);
}
diff --git a/src/bodymovin/bmgfill_p.h b/src/bodymovin/bmgfill_p.h
index 532673b..2d162b8 100644
--- a/src/bodymovin/bmgfill_p.h
+++ b/src/bodymovin/bmgfill_p.h
@@ -30,7 +30,7 @@ class BODYMOVIN_EXPORT BMGFill : public BMShape
public:
BMGFill() = default;
explicit BMGFill(const BMGFill &other);
- BMGFill(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMGFill(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent = nullptr);
~BMGFill() override;
BMBase *clone() const override;
diff --git a/src/bodymovin/bmgroup.cpp b/src/bodymovin/bmgroup.cpp
index a51ae62..a8ce2bf 100644
--- a/src/bodymovin/bmgroup.cpp
+++ b/src/bodymovin/bmgroup.cpp
@@ -13,10 +13,10 @@
QT_BEGIN_NAMESPACE
-BMGroup::BMGroup(const QJsonObject &definition, BMBase *parent)
+BMGroup::BMGroup(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMGroup::clone() const
@@ -24,7 +24,7 @@ BMBase *BMGroup::clone() const
return new BMGroup(*this);
}
-void BMGroup::construct(const QJsonObject &definition)
+void BMGroup::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
if (m_hidden)
@@ -37,7 +37,7 @@ void BMGroup::construct(const QJsonObject &definition)
QJsonArray::const_iterator itemIt = groupItems.constEnd();
while (itemIt != groupItems.constBegin()) {
itemIt--;
- BMShape *shape = BMShape::construct((*itemIt).toObject(), this);
+ BMShape *shape = BMShape::construct((*itemIt).toObject(), version, this);
if (shape) {
// Transform affects how group contents are drawn.
// It must be traversed first when drawing
diff --git a/src/bodymovin/bmgroup_p.h b/src/bodymovin/bmgroup_p.h
index cc565cf..b08b46d 100644
--- a/src/bodymovin/bmgroup_p.h
+++ b/src/bodymovin/bmgroup_p.h
@@ -32,11 +32,11 @@ class BODYMOVIN_EXPORT BMGroup : public BMShape
{
public:
BMGroup() = default;
- BMGroup(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMGroup(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject& definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmimage.cpp b/src/bodymovin/bmimage.cpp
index 3b0f19c..124a1a8 100644
--- a/src/bodymovin/bmimage.cpp
+++ b/src/bodymovin/bmimage.cpp
@@ -19,10 +19,10 @@ BMImage::BMImage(const BMImage &other)
m_image = other.m_image;
}
-BMImage::BMImage(const QJsonObject &definition, BMBase *parent)
+BMImage::BMImage(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMImage::clone() const
@@ -30,7 +30,7 @@ BMBase *BMImage::clone() const
return new BMImage(*this);
}
-void BMImage::construct(const QJsonObject &definition)
+void BMImage::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
if (m_hidden)
@@ -60,11 +60,11 @@ void BMImage::construct(const QJsonObject &definition)
QJsonObject position = definition.value(QLatin1String("p")).toObject();
position = resolveExpression(position);
- m_position.construct(position);
+ m_position.construct(position, version);
QJsonObject radius = definition.value(QLatin1String("r")).toObject();
radius = resolveExpression(radius);
- m_radius.construct(radius);
+ m_radius.construct(radius, version);
}
void BMImage::updateProperties(int frame)
diff --git a/src/bodymovin/bmimage_p.h b/src/bodymovin/bmimage_p.h
index 20d4a57..d04c8b2 100644
--- a/src/bodymovin/bmimage_p.h
+++ b/src/bodymovin/bmimage_p.h
@@ -30,11 +30,11 @@ class BODYMOVIN_EXPORT BMImage : public BMBase
public:
BMImage() = default;
explicit BMImage(const BMImage &other);
- BMImage(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMImage(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmimagelayer.cpp b/src/bodymovin/bmimagelayer.cpp
index 8090132..cd675c9 100644
--- a/src/bodymovin/bmimagelayer.cpp
+++ b/src/bodymovin/bmimagelayer.cpp
@@ -24,13 +24,14 @@ BMImageLayer::BMImageLayer(const BMImageLayer &other)
m_appliedTrim = other.m_appliedTrim;
}
-BMImageLayer::BMImageLayer(const QJsonObject &definition)
+BMImageLayer::BMImageLayer(const QJsonObject &definition, const QVersionNumber &version)
{
m_type = BM_LAYER_IMAGE_IX;
+ m_version = version;
BMLayer::parse(definition);
- BMImage *image = new BMImage(definition, this);
+ BMImage *image = new BMImage(definition, version, this);
appendChild(image);
if (m_hidden)
@@ -47,13 +48,13 @@ BMImageLayer::BMImageLayer(const QJsonObject &definition)
}
QJsonObject trans = definition.value(QLatin1String("ks")).toObject();
- m_layerTransform = new BMBasicTransform(trans, this);
+ m_layerTransform = new BMBasicTransform(trans, version, this);
QJsonArray items = definition.value(QLatin1String("shapes")).toArray();
QJsonArray::const_iterator itemIt = items.constEnd();
while (itemIt != items.constBegin()) {
itemIt--;
- BMShape *shape = BMShape::construct((*itemIt).toObject(), this);
+ BMShape *shape = BMShape::construct((*itemIt).toObject(), version, this);
if (shape)
appendChild(shape);
}
diff --git a/src/bodymovin/bmimagelayer_p.h b/src/bodymovin/bmimagelayer_p.h
index 8f935a8..332f9ca 100644
--- a/src/bodymovin/bmimagelayer_p.h
+++ b/src/bodymovin/bmimagelayer_p.h
@@ -31,7 +31,7 @@ class BODYMOVIN_EXPORT BMImageLayer : public BMLayer
public:
BMImageLayer() = default;
explicit BMImageLayer(const BMImageLayer &other);
- BMImageLayer(const QJsonObject &definition);
+ BMImageLayer(const QJsonObject &definition, const QVersionNumber &version);
~BMImageLayer() override;
BMBase *clone() const override;
diff --git a/src/bodymovin/bmlayer.cpp b/src/bodymovin/bmlayer.cpp
index 533f3e7..4b3a7cc 100644
--- a/src/bodymovin/bmlayer.cpp
+++ b/src/bodymovin/bmlayer.cpp
@@ -47,7 +47,7 @@ BMBase *BMLayer::clone() const
return new BMLayer(*this);
}
-BMLayer *BMLayer::construct(QJsonObject definition)
+BMLayer *BMLayer::construct(QJsonObject definition, const QVersionNumber &version)
{
qCDebug(lcLottieQtBodymovinParser) << "BMLayer::construct()";
@@ -56,11 +56,11 @@ BMLayer *BMLayer::construct(QJsonObject definition)
switch (type) {
case 2:
qCDebug(lcLottieQtBodymovinParser) << "Parse image layer";
- layer = new BMImageLayer(definition);
+ layer = new BMImageLayer(definition, version);
break;
case 4:
qCDebug(lcLottieQtBodymovinParser) << "Parse shape layer";
- layer = new BMShapeLayer(definition);
+ layer = new BMShapeLayer(definition, version);
break;
default:
qCWarning(lcLottieQtBodymovinParser) << "Unsupported layer type:" << type;
@@ -244,7 +244,7 @@ void BMLayer::parseEffects(const QJsonArray &definition, BMBase *effectRoot)
case 21:
{
BMFillEffect *fill = new BMFillEffect;
- fill->construct(effect);
+ fill->construct(effect, m_version);
effectRoot->appendChild(fill);
break;
}
diff --git a/src/bodymovin/bmlayer_p.h b/src/bodymovin/bmlayer_p.h
index 92311bb..d32e04e 100644
--- a/src/bodymovin/bmlayer_p.h
+++ b/src/bodymovin/bmlayer_p.h
@@ -32,11 +32,11 @@ public:
BMBase *clone() const override;
- static BMLayer *construct(QJsonObject definition);
+ static BMLayer *construct(QJsonObject definition, const QVersionNumber &version);
bool active(int frame) const override;
- void parse(const QJsonObject &definition) override;
+ void parse(const QJsonObject &definition) override;
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmproperty_p.h b/src/bodymovin/bmproperty_p.h
index 89acd77..04adeb3 100644
--- a/src/bodymovin/bmproperty_p.h
+++ b/src/bodymovin/bmproperty_p.h
@@ -49,7 +49,7 @@ class BODYMOVIN_EXPORT BMProperty
public:
virtual ~BMProperty() = default;
- virtual void construct(const QJsonObject &definition)
+ virtual void construct(const QJsonObject &definition, const QVersionNumber &version)
{
if (definition.value(QLatin1String("s")).toVariant().toInt())
qCWarning(lcLottieQtBodymovinParser)
@@ -60,11 +60,25 @@ public:
if (m_animated) {
QJsonArray keyframes = definition.value(QLatin1String("k")).toArray();
QJsonArray::const_iterator it = keyframes.constBegin();
- while (it != keyframes.constEnd()) {
- EasingSegment<T> easing = parseKeyframe((*it).toObject(),
- fromExpression);
- addEasing(easing);
- ++it;
+
+ bool schemaChanged = (version >= QVersionNumber(5, 5, 0));
+
+ if (!schemaChanged) {
+ while (it != keyframes.constEnd()) {
+ EasingSegment<T> easing = parseKeyframe((*it).toObject(), fromExpression);
+ addEasing(easing);
+ ++it;
+ }
+ } else {
+ while (it != (keyframes.constEnd() - 1)) {
+ EasingSegment<T> easing =
+ parseKeyframe((*it).toObject(), (*(it + 1)).toObject(), fromExpression);
+ addEasing(easing);
+ ++it;
+ }
+ int lastFrame = (*it).toObject().value(QLatin1String("t")).toVariant().toInt();
+ m_easingCurves.last().endFrame = lastFrame;
+ this->m_endFrame = lastFrame;
}
m_value = T();
} else
@@ -138,8 +152,7 @@ protected:
return m_currentEasing;
}
- virtual EasingSegment<T> parseKeyframe(const QJsonObject keyframe,
- bool fromExpression)
+ virtual EasingSegment<T> parseKeyframe(const QJsonObject keyframe, bool fromExpression)
{
Q_UNUSED(fromExpression);
@@ -155,7 +168,7 @@ protected:
this->m_endFrame = startTime;
easing.startFrame = startTime;
easing.endFrame = startTime;
- if (m_easingCurves.size()) {
+ if (m_easingCurves.length()) {
easing.startValue = m_easingCurves.last().endValue;
easing.endValue = m_easingCurves.last().endValue;
}
@@ -188,6 +201,41 @@ protected:
return easing;
}
+ virtual EasingSegment<T> parseKeyframe(const QJsonObject keyframe,
+ const QJsonObject nextKeyframe, bool fromExpression)
+ {
+ Q_UNUSED(fromExpression);
+
+ EasingSegment<T> easing;
+
+ int startTime = keyframe.value(QLatin1String("t")).toVariant().toInt();
+
+ if (m_startFrame > startTime)
+ m_startFrame = startTime;
+
+ easing.startValue = getValue(keyframe.value(QLatin1String("s")).toArray());
+ easing.endValue = getValue(nextKeyframe.value(QLatin1String("s")).toArray());
+ easing.startFrame = startTime;
+
+ QJsonObject easingIn = keyframe.value(QLatin1String("i")).toObject();
+ QJsonObject easingOut = keyframe.value(QLatin1String("o")).toObject();
+
+ qreal eix = easingIn.value(QLatin1String("x")).toArray().at(0).toDouble();
+ qreal eiy = easingIn.value(QLatin1String("y")).toArray().at(0).toDouble();
+
+ qreal eox = easingOut.value(QLatin1String("x")).toArray().at(0).toDouble();
+ qreal eoy = easingOut.value(QLatin1String("y")).toArray().at(0).toDouble();
+
+ QPointF c1 = QPointF(eox, eoy);
+ QPointF c2 = QPointF(eix, eiy);
+
+ easing.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
+
+ easing.complete = true;
+
+ return easing;
+ }
+
virtual T getValue(const QJsonValue &value)
{
if (value.isArray())
@@ -237,8 +285,7 @@ protected:
return T();
}
- EasingSegment<T> parseKeyframe(const QJsonObject keyframe,
- bool fromExpression) override
+ EasingSegment<T> parseKeyframe(const QJsonObject keyframe, bool fromExpression) override
{
QJsonArray startValues = keyframe.value(QLatin1String("s")).toArray();
QJsonArray endValues = keyframe.value(QLatin1String("e")).toArray();
@@ -255,7 +302,7 @@ protected:
this->m_endFrame = startTime;
easingCurve.startFrame = startTime;
easingCurve.endFrame = startTime;
- if (this->m_easingCurves.size()) {
+ if (this->m_easingCurves.length()) {
easingCurve.startValue = this->m_easingCurves.last().endValue;
easingCurve.endValue = this->m_easingCurves.last().endValue;
}
@@ -300,6 +347,79 @@ protected:
qreal eix = eixArr.takeAt(0).toDouble();
qreal eiy = eiyArr.takeAt(0).toDouble();
+ qreal eox = eoxArr.takeAt(0).toDouble();
+ qreal eoy = eoyArr.takeAt(0).toDouble();
+
+ QPointF c1 = QPointF(eox, eoy);
+ QPointF c2 = QPointF(eix, eiy);
+
+ easingCurve.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
+ }
+ } else {
+ qreal eix = easingIn.value(QLatin1String("x")).toDouble();
+ qreal eiy = easingIn.value(QLatin1String("y")).toDouble();
+
+ qreal eox = easingOut.value(QLatin1String("x")).toDouble();
+ qreal eoy = easingOut.value(QLatin1String("y")).toDouble();
+
+ QPointF c1 = QPointF(eox, eoy);
+ QPointF c2 = QPointF(eix, eiy);
+
+ easingCurve.easing.addCubicBezierSegment(c1, c2, QPointF(1.0, 1.0));
+ }
+
+ easingCurve.complete = true;
+ return easingCurve;
+ }
+
+ EasingSegment<T> parseKeyframe(const QJsonObject keyframe, const QJsonObject nextKeyframe,
+ bool fromExpression) override
+ {
+ QJsonArray startValues = keyframe.value(QLatin1String("s")).toArray();
+ QJsonArray endValues = nextKeyframe.value(QLatin1String("s")).toArray();
+ int startTime = keyframe.value(QLatin1String("t")).toVariant().toInt();
+
+ EasingSegment<T> easingCurve;
+ easingCurve.startFrame = startTime;
+
+ if (this->m_startFrame > startTime)
+ this->m_startFrame = startTime;
+
+ qreal xs, ys, xe, ye;
+ // Keyframes originating from an expression use only scalar values.
+ // They must be expanded for both x and y coordinates
+ if (fromExpression) {
+ xs = startValues.at(0).toDouble();
+ ys = startValues.at(0).toDouble();
+ xe = endValues.at(0).toDouble();
+ ye = endValues.at(0).toDouble();
+ } else {
+ xs = startValues.at(0).toDouble();
+ ys = startValues.at(1).toDouble();
+ xe = endValues.at(0).toDouble();
+ ye = endValues.at(1).toDouble();
+ }
+ T s(xs, ys);
+ T e(xe, ye);
+
+ QJsonObject easingIn = keyframe.value(QLatin1String("i")).toObject();
+ QJsonObject easingOut = keyframe.value(QLatin1String("o")).toObject();
+
+ easingCurve.startFrame = startTime;
+ easingCurve.startValue = s;
+ easingCurve.endValue = e;
+
+ if (easingIn.value(QLatin1String("x")).isArray()) {
+ QJsonArray eixArr = easingIn.value(QLatin1String("x")).toArray();
+ QJsonArray eiyArr = easingIn.value(QLatin1String("y")).toArray();
+
+ QJsonArray eoxArr = easingOut.value(QLatin1String("x")).toArray();
+ QJsonArray eoyArr = easingOut.value(QLatin1String("y")).toArray();
+
+ while (!eixArr.isEmpty() && !eiyArr.isEmpty()) {
+ qreal eix = eixArr.takeAt(0).toDouble();
+ qreal eiy = eiyArr.takeAt(0).toDouble();
+
qreal eox =eoxArr.takeAt(0).toDouble();
qreal eoy = eoyArr.takeAt(0).toDouble();
diff --git a/src/bodymovin/bmrect.cpp b/src/bodymovin/bmrect.cpp
index 0deed01..754c5b8 100644
--- a/src/bodymovin/bmrect.cpp
+++ b/src/bodymovin/bmrect.cpp
@@ -21,7 +21,7 @@ BMRect::BMRect(const BMRect &other)
m_roundness = other.m_roundness;
}
-BMRect::BMRect(const QJsonObject &definition, BMBase *parent)
+BMRect::BMRect(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
BMBase::parse(definition);
@@ -32,15 +32,15 @@ BMRect::BMRect(const QJsonObject &definition, BMBase *parent)
QJsonObject position = definition.value(QLatin1String("p")).toObject();
position = resolveExpression(position);
- m_position.construct(position);
+ m_position.construct(position, version);
QJsonObject size = definition.value(QLatin1String("s")).toObject();
size = resolveExpression(size);
- m_size.construct(size);
+ m_size.construct(size, version);
QJsonObject roundness = definition.value(QLatin1String("r")).toObject();
roundness = resolveExpression(roundness);
- m_roundness.construct(roundness);
+ m_roundness.construct(roundness, version);
m_direction = definition.value(QLatin1String("d")).toInt();
}
diff --git a/src/bodymovin/bmrect_p.h b/src/bodymovin/bmrect_p.h
index 4a77485..6b32e31 100644
--- a/src/bodymovin/bmrect_p.h
+++ b/src/bodymovin/bmrect_p.h
@@ -33,11 +33,11 @@ class BODYMOVIN_EXPORT BMRect : public BMShape
public:
BMRect() = default;
explicit BMRect(const BMRect &other);
- BMRect(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMRect(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
bool setProperty(BMLiteral::PropertyType propertyType, QVariant value) override;
diff --git a/src/bodymovin/bmrepeater.cpp b/src/bodymovin/bmrepeater.cpp
index 087702b..da47ab0 100644
--- a/src/bodymovin/bmrepeater.cpp
+++ b/src/bodymovin/bmrepeater.cpp
@@ -3,11 +3,11 @@
#include "bmrepeater_p.h"
-BMRepeater::BMRepeater(const QJsonObject &definition, BMBase *parent)
+BMRepeater::BMRepeater(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
m_transform.setParent(this);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMRepeater::clone() const
@@ -15,7 +15,7 @@ BMBase *BMRepeater::clone() const
return new BMRepeater(*this);
}
-void BMRepeater::construct(const QJsonObject &definition)
+void BMRepeater::construct(const QJsonObject &definition, const QVersionNumber &version)
{
qCDebug(lcLottieQtBodymovinParser) << "BMRepeater::construct():" << m_name;
@@ -25,13 +25,13 @@ void BMRepeater::construct(const QJsonObject &definition)
QJsonObject copies = definition.value(QLatin1String("c")).toObject();
copies = resolveExpression(copies);
- m_copies.construct(copies);
+ m_copies.construct(copies, version);
QJsonObject offset = definition.value(QLatin1String("o")).toObject();
offset = resolveExpression(offset);
- m_offset.construct(offset);
+ m_offset.construct(offset, version);
- m_transform.construct(definition.value(QLatin1String("tr")).toObject());
+ m_transform.construct(definition.value(QLatin1String("tr")).toObject(), version);
}
void BMRepeater::updateProperties(int frame)
diff --git a/src/bodymovin/bmrepeater_p.h b/src/bodymovin/bmrepeater_p.h
index f30cb37..52b4ad3 100644
--- a/src/bodymovin/bmrepeater_p.h
+++ b/src/bodymovin/bmrepeater_p.h
@@ -29,11 +29,12 @@ class BODYMOVIN_EXPORT BMRepeater : public BMShape
public:
BMRepeater() = default;
explicit BMRepeater(const BMRepeater &other) = default;
- BMRepeater(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMRepeater(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject& definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmrepeatertransform.cpp b/src/bodymovin/bmrepeatertransform.cpp
index 344427d..f6c137c 100644
--- a/src/bodymovin/bmrepeatertransform.cpp
+++ b/src/bodymovin/bmrepeatertransform.cpp
@@ -13,10 +13,11 @@ BMRepeaterTransform::BMRepeaterTransform(const BMRepeaterTransform &other)
m_opacities = other.m_opacities;
}
-BMRepeaterTransform::BMRepeaterTransform(const QJsonObject &definition, BMBase *parent)
+BMRepeaterTransform::BMRepeaterTransform(const QJsonObject &definition,
+ const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMRepeaterTransform::clone() const
@@ -24,21 +25,21 @@ BMBase *BMRepeaterTransform::clone() const
return new BMRepeaterTransform(*this);
}
-void BMRepeaterTransform::construct(const QJsonObject &definition)
+void BMRepeaterTransform::construct(const QJsonObject &definition, const QVersionNumber &version)
{
qCDebug(lcLottieQtBodymovinParser) << "BMRepeaterTransform::construct():" << name();
- BMBasicTransform::construct(definition);
+ BMBasicTransform::construct(definition, version);
if (m_hidden)
return;
QJsonObject startOpacity = definition.value(QLatin1String("so")).toObject();
startOpacity = resolveExpression(startOpacity);
- m_startOpacity.construct(startOpacity);
+ m_startOpacity.construct(startOpacity, version);
QJsonObject endOpacity = definition.value(QLatin1String("eo")).toObject();
endOpacity = resolveExpression(endOpacity);
- m_endOpacity.construct(endOpacity);
+ m_endOpacity.construct(endOpacity, version);
}
void BMRepeaterTransform::updateProperties(int frame)
diff --git a/src/bodymovin/bmrepeatertransform_p.h b/src/bodymovin/bmrepeatertransform_p.h
index 1d29768..456e32c 100644
--- a/src/bodymovin/bmrepeatertransform_p.h
+++ b/src/bodymovin/bmrepeatertransform_p.h
@@ -26,11 +26,12 @@ class BODYMOVIN_EXPORT BMRepeaterTransform : public BMBasicTransform
public:
BMRepeaterTransform() = default;
explicit BMRepeaterTransform(const BMRepeaterTransform &other);
- BMRepeaterTransform(const QJsonObject &definition, BMBase *parent);
+ BMRepeaterTransform(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmround.cpp b/src/bodymovin/bmround.cpp
index 3e6a5ec..46bb860 100644
--- a/src/bodymovin/bmround.cpp
+++ b/src/bodymovin/bmround.cpp
@@ -16,10 +16,10 @@ BMRound::BMRound(const BMRound &other)
m_radius = other.m_radius;
}
-BMRound::BMRound(const QJsonObject &definition, BMBase *parent)
+BMRound::BMRound(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMRound::clone() const
@@ -27,7 +27,7 @@ BMBase *BMRound::clone() const
return new BMRound(*this);
}
-void BMRound::construct(const QJsonObject &definition)
+void BMRound::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
if (m_hidden)
@@ -37,11 +37,11 @@ void BMRound::construct(const QJsonObject &definition)
QJsonObject position = definition.value(QLatin1String("p")).toObject();
position = resolveExpression(position);
- m_position.construct(position);
+ m_position.construct(position, version);
QJsonObject radius = definition.value(QLatin1String("r")).toObject();
radius = resolveExpression(radius);
- m_radius.construct(radius);
+ m_radius.construct(radius, version);
}
void BMRound::updateProperties(int frame)
diff --git a/src/bodymovin/bmround_p.h b/src/bodymovin/bmround_p.h
index 952d7c8..8ebe9a3 100644
--- a/src/bodymovin/bmround_p.h
+++ b/src/bodymovin/bmround_p.h
@@ -35,11 +35,11 @@ class BODYMOVIN_EXPORT BMRound : public BMShape
public:
BMRound() = default;
explicit BMRound(const BMRound &other);
- BMRound(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMRound(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent = nullptr);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmshape.cpp b/src/bodymovin/bmshape.cpp
index a81a46e..4e9014d 100644
--- a/src/bodymovin/bmshape.cpp
+++ b/src/bodymovin/bmshape.cpp
@@ -35,7 +35,7 @@ BMBase *BMShape::clone() const
return new BMShape(*this);
}
-BMShape *BMShape::construct(QJsonObject definition, BMBase *parent)
+BMShape *BMShape::construct(QJsonObject definition, const QVersionNumber &version, BMBase *parent)
{
qCDebug(lcLottieQtBodymovinParser) << "BMShape::construct()";
@@ -56,77 +56,77 @@ BMShape *BMShape::construct(QJsonObject definition, BMBase *parent)
case BM_SHAPE_TAG('g', 'r'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse group";
- shape = new BMGroup(definition, parent);
+ shape = new BMGroup(definition, version, parent);
shape->setType(BM_SHAPE_GROUP_IX);
break;
}
case BM_SHAPE_TAG('r', 'c'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse m_rect";
- shape = new BMRect(definition, parent);
+ shape = new BMRect(definition, version, parent);
shape->setType(BM_SHAPE_RECT_IX);
break;
}
case BM_SHAPE_TAG('f', 'l'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse fill";
- shape = new BMFill(definition, parent);
+ shape = new BMFill(definition, version, parent);
shape->setType(BM_SHAPE_FILL_IX);
break;
}
case BM_SHAPE_TAG('g', 'f'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse group fill";
- shape = new BMGFill(definition, parent);
+ shape = new BMGFill(definition, version, parent);
shape->setType(BM_SHAPE_GFILL_IX);
break;
}
case BM_SHAPE_TAG('s', 't'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse stroke";
- shape = new BMStroke(definition, parent);
+ shape = new BMStroke(definition, version, parent);
shape->setType(BM_SHAPE_STROKE_IX);
break;
}
case BM_SHAPE_TAG('t', 'r'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse shape transform";
- shape = new BMShapeTransform(definition, parent);
+ shape = new BMShapeTransform(definition, version, parent);
shape->setType(BM_SHAPE_TRANS_IX);
break;
}
case BM_SHAPE_TAG('e', 'l'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse ellipse";
- shape = new BMEllipse(definition, parent);
+ shape = new BMEllipse(definition, version, parent);
shape->setType(BM_SHAPE_ELLIPSE_IX);
break;
}
case BM_SHAPE_TAG('r', 'd'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse round";
- shape = new BMRound(definition, parent);
+ shape = new BMRound(definition, version, parent);
shape->setType(BM_SHAPE_ROUND_IX);
break;
}
case BM_SHAPE_TAG('s', 'h'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse shape";
- shape = new BMFreeFormShape(definition, parent);
+ shape = new BMFreeFormShape(definition, version, parent);
shape->setType(BM_SHAPE_SHAPE_IX);
break;
}
case BM_SHAPE_TAG('t', 'm'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse trim path";
- shape = new BMTrimPath(definition, parent);
+ shape = new BMTrimPath(definition, version, parent);
shape->setType(BM_SHAPE_TRIM_IX);
break;
}
case BM_SHAPE_TAG('r', 'p'):
{
qCDebug(lcLottieQtBodymovinParser) << "Parse trim path";
- shape = new BMRepeater(definition, parent);
+ shape = new BMRepeater(definition, version, parent);
shape->setType(BM_SHAPE_REPEATER_IX);
break;
}
diff --git a/src/bodymovin/bmshape_p.h b/src/bodymovin/bmshape_p.h
index 698dc59..a41bb18 100644
--- a/src/bodymovin/bmshape_p.h
+++ b/src/bodymovin/bmshape_p.h
@@ -49,7 +49,8 @@ public:
BMBase *clone() const override;
- static BMShape *construct(QJsonObject definition, BMBase *parent = nullptr);
+ static BMShape *construct(QJsonObject definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
virtual const QPainterPath &path() const;
virtual bool acceptsTrim() const;
diff --git a/src/bodymovin/bmshapelayer.cpp b/src/bodymovin/bmshapelayer.cpp
index 71d7e42..a753d2e 100644
--- a/src/bodymovin/bmshapelayer.cpp
+++ b/src/bodymovin/bmshapelayer.cpp
@@ -25,9 +25,10 @@ BMShapeLayer::BMShapeLayer(const BMShapeLayer &other)
m_appliedTrim = other.m_appliedTrim;
}
-BMShapeLayer::BMShapeLayer(const QJsonObject &definition)
+BMShapeLayer::BMShapeLayer(const QJsonObject &definition, const QVersionNumber &version)
{
m_type = BM_LAYER_SHAPE_IX;
+ m_version = version;
BMLayer::parse(definition);
if (m_hidden)
@@ -44,13 +45,13 @@ BMShapeLayer::BMShapeLayer(const QJsonObject &definition)
}
QJsonObject trans = definition.value(QLatin1String("ks")).toObject();
- m_layerTransform = new BMBasicTransform(trans, this);
+ m_layerTransform = new BMBasicTransform(trans, version, this);
QJsonArray items = definition.value(QLatin1String("shapes")).toArray();
QJsonArray::const_iterator itemIt = items.constEnd();
while (itemIt != items.constBegin()) {
itemIt--;
- BMShape *shape = BMShape::construct((*itemIt).toObject(), this);
+ BMShape *shape = BMShape::construct((*itemIt).toObject(), version, this);
if (shape)
appendChild(shape);
}
diff --git a/src/bodymovin/bmshapelayer_p.h b/src/bodymovin/bmshapelayer_p.h
index e905b6b..c23535f 100644
--- a/src/bodymovin/bmshapelayer_p.h
+++ b/src/bodymovin/bmshapelayer_p.h
@@ -31,7 +31,7 @@ class BODYMOVIN_EXPORT BMShapeLayer : public BMLayer
public:
BMShapeLayer() = default;
explicit BMShapeLayer(const BMShapeLayer &other);
- BMShapeLayer(const QJsonObject &definition);
+ BMShapeLayer(const QJsonObject &definition, const QVersionNumber &version);
~BMShapeLayer() override;
BMBase *clone() const override;
diff --git a/src/bodymovin/bmshapetransform.cpp b/src/bodymovin/bmshapetransform.cpp
index 3370a0e..b5cb523 100644
--- a/src/bodymovin/bmshapetransform.cpp
+++ b/src/bodymovin/bmshapetransform.cpp
@@ -19,10 +19,11 @@ BMShapeTransform::BMShapeTransform(const BMShapeTransform &other)
m_shearAngle = other.m_shearAngle;
}
-BMShapeTransform::BMShapeTransform(const QJsonObject &definition, BMBase *parent)
+BMShapeTransform::BMShapeTransform(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent)
{
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMBase *BMShapeTransform::clone() const
@@ -30,19 +31,19 @@ BMBase *BMShapeTransform::clone() const
return new BMShapeTransform(*this);
}
-void BMShapeTransform::construct(const QJsonObject &definition)
+void BMShapeTransform::construct(const QJsonObject &definition, const QVersionNumber &version)
{
- BMBasicTransform::construct(definition);
+ BMBasicTransform::construct(definition, version);
qCDebug(lcLottieQtBodymovinParser) << "BMShapeTransform::construct():" << BMShape::name();
QJsonObject skew = definition.value(QLatin1String("sk")).toObject();
skew = resolveExpression(skew);
- m_skew.construct(skew);
+ m_skew.construct(skew, version);
QJsonObject skewAxis = definition.value(QLatin1String("sa")).toObject();
skewAxis = resolveExpression(skewAxis);
- m_skewAxis.construct(skewAxis);
+ m_skewAxis.construct(skewAxis, version);
}
void BMShapeTransform::updateProperties(int frame)
diff --git a/src/bodymovin/bmshapetransform_p.h b/src/bodymovin/bmshapetransform_p.h
index b0c52d2..9b9d120 100644
--- a/src/bodymovin/bmshapetransform_p.h
+++ b/src/bodymovin/bmshapetransform_p.h
@@ -29,11 +29,11 @@ class BODYMOVIN_EXPORT BMShapeTransform : public BMBasicTransform
{
public:
explicit BMShapeTransform(const BMShapeTransform &other);
- BMShapeTransform(const QJsonObject &definition, BMBase *parent);
+ BMShapeTransform(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/bodymovin/bmspatialproperty_p.h b/src/bodymovin/bmspatialproperty_p.h
index e857720..7d2432b 100644
--- a/src/bodymovin/bmspatialproperty_p.h
+++ b/src/bodymovin/bmspatialproperty_p.h
@@ -25,15 +25,68 @@ QT_BEGIN_NAMESPACE
class BMSpatialProperty : public BMProperty2D<QPointF>
{
public:
- virtual void construct(const QJsonObject &definition) override
+ virtual void construct(const QJsonObject &definition, const QVersionNumber &version) override
{
qCDebug(lcLottieQtBodymovinParser) << "BMSpatialProperty::construct()";
- BMProperty2D<QPointF>::construct(definition);
+ BMProperty2D<QPointF>::construct(definition, version);
}
- virtual EasingSegment<QPointF> parseKeyframe(const QJsonObject keyframe, bool fromExpression) override
+ virtual EasingSegment<QPointF> parseKeyframe(const QJsonObject keyframe,
+ bool fromExpression) override
{
- EasingSegment<QPointF> easing = BMProperty2D<QPointF>::parseKeyframe(keyframe, fromExpression);
+ EasingSegment<QPointF> easing =
+ BMProperty2D<QPointF>::parseKeyframe(keyframe, fromExpression);
+
+ // No need to parse further incomplete keyframes (i.e. last keyframes)
+ if (!easing.complete) {
+ return easing;
+ }
+
+ qreal tix = 0, tiy = 0, tox = 0, toy = 0;
+ if (fromExpression) {
+ // If spatial property definition originates from
+ // an expression (specifically Slider), it contains scalar
+ // property. It must be expanded to both x and y coordinates
+ QJsonArray iArr = keyframe.value(QLatin1String("i")).toArray();
+ QJsonArray oArr = keyframe.value(QLatin1String("o")).toArray();
+
+ if (iArr.count() && oArr.count()) {
+ tix = iArr.at(0).toDouble();
+ tiy = tix;
+ tox = oArr.at(0).toDouble();
+ toy = tox;
+ }
+ } else {
+ QJsonArray tiArr = keyframe.value(QLatin1String("ti")).toArray();
+ QJsonArray toArr = keyframe.value(QLatin1String("to")).toArray();
+
+ if (tiArr.count() && toArr.count()) {
+ tix = tiArr.at(0).toDouble();
+ tiy = tiArr.at(1).toDouble();
+ tox = toArr.at(0).toDouble();
+ toy = toArr.at(1).toDouble();
+ }
+ }
+ QPointF s(easing.startValue);
+ QPointF e(easing.endValue);
+ QPointF c1(tox, toy);
+ QPointF c2(tix, tiy);
+
+ c1 += s;
+ c2 += e;
+
+ m_bezierPath.moveTo(s);
+ m_bezierPath.cubicTo(c1, c2, e);
+
+ return easing;
+ }
+
+ virtual EasingSegment<QPointF> parseKeyframe(const QJsonObject keyframe,
+ const QJsonObject nextKeyframe,
+ bool fromExpression) override
+ {
+ EasingSegment<QPointF> easing =
+ BMProperty2D<QPointF>::parseKeyframe(keyframe, nextKeyframe, fromExpression);
// No need to parse further incomplete keyframes (i.e. last keyframes)
if (!easing.complete) {
diff --git a/src/bodymovin/bmstroke.cpp b/src/bodymovin/bmstroke.cpp
index e596a86..86a5f20 100644
--- a/src/bodymovin/bmstroke.cpp
+++ b/src/bodymovin/bmstroke.cpp
@@ -20,7 +20,7 @@ BMStroke::BMStroke(const BMStroke &other)
m_miterLimit = other.m_miterLimit;
}
-BMStroke::BMStroke(const QJsonObject &definition, BMBase *parent)
+BMStroke::BMStroke(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
setParent(parent);
@@ -63,15 +63,15 @@ BMStroke::BMStroke(const QJsonObject &definition, BMBase *parent)
QJsonObject opacity = definition.value(QLatin1String("o")).toObject();
opacity = resolveExpression(opacity);
- m_opacity.construct(opacity);
+ m_opacity.construct(opacity, version);
QJsonObject width = definition.value(QLatin1String("w")).toObject();
width = resolveExpression(width);
- m_width.construct(width);
+ m_width.construct(width, version);
QJsonObject color = definition.value(QLatin1String("c")).toObject();
color = resolveExpression(color);
- m_color.construct(color);
+ m_color.construct(color, version);
}
BMBase *BMStroke::clone() const
diff --git a/src/bodymovin/bmstroke_p.h b/src/bodymovin/bmstroke_p.h
index 6a811ab..cc3b838 100644
--- a/src/bodymovin/bmstroke_p.h
+++ b/src/bodymovin/bmstroke_p.h
@@ -28,7 +28,8 @@ class BODYMOVIN_EXPORT BMStroke : public BMShape
public:
BMStroke() = default;
explicit BMStroke(const BMStroke &other);
- BMStroke(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMStroke(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
BMBase *clone() const override;
diff --git a/src/bodymovin/bmtrimpath.cpp b/src/bodymovin/bmtrimpath.cpp
index dea1b7b..62a5f7a 100644
--- a/src/bodymovin/bmtrimpath.cpp
+++ b/src/bodymovin/bmtrimpath.cpp
@@ -15,12 +15,12 @@ BMTrimPath::BMTrimPath()
m_appliedTrim = this;
}
-BMTrimPath::BMTrimPath(const QJsonObject &definition, BMBase *parent)
+BMTrimPath::BMTrimPath(const QJsonObject &definition, const QVersionNumber &version, BMBase *parent)
{
m_appliedTrim = this;
setParent(parent);
- construct(definition);
+ construct(definition, version);
}
BMTrimPath::BMTrimPath(const BMTrimPath &other)
@@ -37,7 +37,7 @@ BMBase *BMTrimPath::clone() const
return new BMTrimPath(*this);
}
-void BMTrimPath::construct(const QJsonObject &definition)
+void BMTrimPath::construct(const QJsonObject &definition, const QVersionNumber &version)
{
BMBase::parse(definition);
if (m_hidden)
@@ -47,15 +47,15 @@ void BMTrimPath::construct(const QJsonObject &definition)
QJsonObject start = definition.value(QLatin1String("s")).toObject();
start = resolveExpression(start);
- m_start.construct(start);
+ m_start.construct(start, version);
QJsonObject end = definition.value(QLatin1String("e")).toObject();
end = resolveExpression(end);
- m_end.construct(end);
+ m_end.construct(end, version);
QJsonObject offset = definition.value(QLatin1String("o")).toObject();
offset = resolveExpression(offset);
- m_offset.construct(offset);
+ m_offset.construct(offset, version);
int simultaneous = true;
if (definition.contains(QLatin1String("m"))) {
diff --git a/src/bodymovin/bmtrimpath_p.h b/src/bodymovin/bmtrimpath_p.h
index fdcdad2..ea653c0 100644
--- a/src/bodymovin/bmtrimpath_p.h
+++ b/src/bodymovin/bmtrimpath_p.h
@@ -27,14 +27,15 @@ class BODYMOVIN_EXPORT BMTrimPath : public BMShape
{
public:
BMTrimPath();
- BMTrimPath(const QJsonObject &definition, BMBase *parent = nullptr);
+ BMTrimPath(const QJsonObject &definition, const QVersionNumber &version,
+ BMBase *parent = nullptr);
explicit BMTrimPath(const BMTrimPath &other);
void inherit(const BMTrimPath &other);
BMBase *clone() const override;
- void construct(const QJsonObject &definition);
+ void construct(const QJsonObject &definition, const QVersionNumber &version);
void updateProperties(int frame) override;
void render(LottieRenderer &renderer) const override;
diff --git a/src/imports/lottieanimation.cpp b/src/imports/lottieanimation.cpp
index 1334c76..4d60ed6 100644
--- a/src/imports/lottieanimation.cpp
+++ b/src/imports/lottieanimation.cpp
@@ -315,6 +315,11 @@ int LottieAnimation::currentFrame() const
return m_currentFrame;
}
+QVersionNumber LottieAnimation::version() const
+{
+ return m_version;
+}
+
/*!
\qmlproperty int LottieAnimation::frameRate
@@ -655,6 +660,12 @@ int LottieAnimation::parse(QByteArray jsonSource)
if (Q_UNLIKELY(rootObj.empty()))
return -1;
+ QStringList versionString = rootObj.value(QLatin1String("v")).toString().split(u'.');
+ QList<int> version;
+ foreach (QString v, versionString)
+ version.append(v.toInt());
+ m_version = QVersionNumber(version);
+
int startFrame = rootObj.value(QLatin1String("ip")).toVariant().toInt();
int endFrame = rootObj.value(QLatin1String("op")).toVariant().toInt();
m_animFrameRate = rootObj.value(QLatin1String("fr")).toVariant().toInt();
diff --git a/src/imports/lottieanimation.h b/src/imports/lottieanimation.h
index 88c9dde..cce6d5e 100644
--- a/src/imports/lottieanimation.h
+++ b/src/imports/lottieanimation.h
@@ -74,6 +74,8 @@ public:
int endFrame() const;
int currentFrame() const;
+ QVersionNumber version() const;
+
Q_INVOKABLE void start();
Q_INVOKABLE void play();
@@ -122,6 +124,7 @@ protected:
QMetaObject::Connection m_waitForFrameConn;
Status m_status = Null;
+ QVersionNumber m_version = QVersionNumber();
int m_startFrame = 0;
int m_endFrame = 0;
int m_currentFrame = 0;
diff --git a/src/imports/rasterrenderer/batchrenderer.cpp b/src/imports/rasterrenderer/batchrenderer.cpp
index d83eb70..1d11074 100644
--- a/src/imports/rasterrenderer/batchrenderer.cpp
+++ b/src/imports/rasterrenderer/batchrenderer.cpp
@@ -86,7 +86,7 @@ void BatchRenderer::registerAnimator(LottieAnimation *animator)
entry->currentFrame = animator->startFrame();
entry->animDir = animator->direction();
entry->bmTreeBlueprint = new BMBase;
- parse(entry->bmTreeBlueprint, animator->jsonSource());
+ parse(entry->bmTreeBlueprint, animator->jsonSource(), animator->version());
m_waitCondition.wakeAll();
}
@@ -210,7 +210,8 @@ void BatchRenderer::run()
}
}
-int BatchRenderer::parse(BMBase *rootElement, const QByteArray &jsonSource) const
+int BatchRenderer::parse(BMBase *rootElement, const QByteArray &jsonSource,
+ const QVersionNumber &version) const
{
QJsonDocument doc = QJsonDocument::fromJson(jsonSource);
QJsonObject rootObj = doc.object();
@@ -239,7 +240,7 @@ int BatchRenderer::parse(BMBase *rootElement, const QByteArray &jsonSource) cons
QString refId = jsonLayer.value("refId").toString();
jsonLayer.insert("asset", assets.value(refId));
}
- BMLayer *layer = BMLayer::construct(jsonLayer);
+ BMLayer *layer = BMLayer::construct(jsonLayer, version);
if (layer) {
layer->setParent(rootElement);
// Mask layers must be rendered before the layers they affect to
diff --git a/src/imports/rasterrenderer/batchrenderer.h b/src/imports/rasterrenderer/batchrenderer.h
index 619f84e..7d86edc 100644
--- a/src/imports/rasterrenderer/batchrenderer.h
+++ b/src/imports/rasterrenderer/batchrenderer.h
@@ -13,6 +13,7 @@ QT_BEGIN_NAMESPACE
class BMBase;
class QImage;
+class QVersionNumber;
class LottieAnimation;
class BatchRenderer : public QThread
@@ -55,7 +56,8 @@ public slots:
protected:
void run() override;
- int parse(BMBase *rootElement, const QByteArray &jsonSource) const;
+ int parse(BMBase *rootElement, const QByteArray &jsonSource,
+ const QVersionNumber &version) const;
void prerender(Entry *animEntry);