diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index cb1bc2cd..d2ef838d 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -77,6 +77,10 @@ static renderer::Layer *createLayerItem(model::Layer *layerData, { switch (layerData->mLayerType) { case model::Layer::Type::Precomp: { + model::Composition *comp = layerData->extra()->mCompRef; + if (comp && comp->mRootLayer->includes(layerData)) { + return nullptr; + } return allocator->make(layerData, allocator); } case model::Layer::Type::Solid: { @@ -1159,6 +1163,11 @@ void renderer::Polystar::updatePath(VPath &path, int frameNo) path.reset(); VMatrix m; + if (!(points > 0)) { + vWarning << "The number of path points is below zero or NaN at all"; + return; + } + if (mData->mPolyType == model::Polystar::PolyType::Star) { path.addPolystar(points, innerRadius, outerRadius, innerRoundness, outerRoundness, 0.0, 0.0, 0.0, mData->direction()); diff --git a/src/lottie/lottiemodel.cpp b/src/lottie/lottiemodel.cpp index 1bca99d2..1945b68a 100644 --- a/src/lottie/lottiemodel.cpp +++ b/src/lottie/lottiemodel.cpp @@ -23,12 +23,27 @@ #include "lottiemodel.h" #include #include +#include #include #include "vimageloader.h" #include "vline.h" using namespace rlottie::internal; +bool model::Group::includes(model::Group *pointer) { + if (this == pointer) { + return true; + } + for (Object *child : mChildren) { + if ((child->type() == Type::Group || child->type() == Type::Layer) + && this != child + && static_cast(child)->includes(pointer)) { + return true; + } + } + return false; +} + /* * We process the iterator objects in the children list * by iterating from back to front. when we find a repeater object @@ -79,6 +94,8 @@ class LottieRepeaterProcesser { void visit(model::Object *obj) { + if (!mVisited.insert(obj).second) return; + switch (obj->type()) { case model::Object::Type::Group: case model::Object::Type::Layer: { @@ -89,6 +106,9 @@ class LottieRepeaterProcesser { break; } } + +private: + std::set mVisited; }; class LottieUpdateStatVisitor { @@ -127,6 +147,8 @@ class LottieUpdateStatVisitor { } void visit(model::Object *obj) { + if (!mVisited.insert(obj).second) return; + switch (obj->type()) { case model::Object::Type::Layer: { visitLayer(static_cast(obj)); @@ -144,6 +166,9 @@ class LottieUpdateStatVisitor { break; } } + +private: + std::set mVisited; }; void model::Composition::processRepeaterObjects() diff --git a/src/lottie/lottiemodel.h b/src/lottie/lottiemodel.h index 3e043085..b1161400 100644 --- a/src/lottie/lottiemodel.h +++ b/src/lottie/lottiemodel.h @@ -157,8 +157,8 @@ struct PathData { template struct Value { - T start_; - T end_; + T start_{}; + T end_{}; T at(float t) const { return lerp(start_, end_, t); } float angle(float) const { return 0; } void cache() {} @@ -168,10 +168,10 @@ struct Position; template struct Value { - T start_; - T end_; - T inTangent_; - T outTangent_; + T start_{}; + T end_{}; + T inTangent_{}; + T outTangent_{}; float length_{0}; bool hasTangent_{false}; @@ -340,6 +340,7 @@ class Property { value().toPath(path); } else { const auto &vec = animation().frames_; + if (vec.empty()) return; if (vec.front().start_ >= frameNo) return vec.front().value_.start_.toPath(path); if (vec.back().end_ <= frameNo) @@ -659,6 +660,7 @@ class Group : public Object { public: Group() : Object(Object::Type::Group) {} explicit Group(Object::Type type) : Object(type) {} + bool includes(Group *); public: std::vector mChildren; @@ -1053,8 +1055,8 @@ class Trim : public Object { private: Segment noloop(float start, float end) const { - assert(start >= 0); - assert(end >= 0); + if (!(start >= 0)) start = 0; + if (!(end >= 0)) end = 0; Segment s; s.start = std::min(start, end); s.end = std::max(start, end); @@ -1062,8 +1064,8 @@ class Trim : public Object { } Segment loop(float start, float end) const { - assert(start >= 0); - assert(end >= 0); + if (!(start >= 0)) start = 0; + if (!(end >= 0)) end = 0; Segment s; s.start = std::max(start, end); s.end = std::min(start, end); diff --git a/src/vector/freetype/v_ft_stroker.cpp b/src/vector/freetype/v_ft_stroker.cpp index 3160f84f..e53f51da 100644 --- a/src/vector/freetype/v_ft_stroker.cpp +++ b/src/vector/freetype/v_ft_stroker.cpp @@ -18,6 +18,7 @@ #include "v_ft_stroker.h" #include +#include #include #include #include "v_ft_math.h" @@ -626,6 +627,8 @@ static SW_FT_Error ft_stroke_border_get_counts(SW_FT_StrokeBorder border, static void ft_stroke_border_export(SW_FT_StrokeBorder border, SW_FT_Outline* outline) { + if ((unsigned long)outline->n_points + border->num_points > SHRT_MAX) return; + /* copy point locations */ memcpy(outline->points + outline->n_points, border->points, border->num_points * sizeof(SW_FT_Vector)); diff --git a/src/vector/vbezier.cpp b/src/vector/vbezier.cpp index 15889299..ea8745f9 100644 --- a/src/vector/vbezier.cpp +++ b/src/vector/vbezier.cpp @@ -52,7 +52,13 @@ float VBezier::length() const if ((len - chord) > 0.01) { VBezier left, right; split(&left, &right); - return left.length() + right.length(); + + float sum = 0; + if (*this != left) + sum += left.length(); + if (*this != right) + sum += right.length(); + return sum; } return len; diff --git a/src/vector/vbezier.h b/src/vector/vbezier.h index 18b7c596..df18c4f9 100644 --- a/src/vector/vbezier.h +++ b/src/vector/vbezier.h @@ -23,11 +23,14 @@ #ifndef VBEZIER_H #define VBEZIER_H +#include #include V_BEGIN_NAMESPACE class VBezier { + friend bool operator == (const VBezier &l, const VBezier &r); + public: VBezier() = default; VPointF pointAt(float t) const; @@ -134,6 +137,16 @@ inline void VBezier::split(VBezier *firstHalf, VBezier *secondHalf) const firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2) * 0.5f; } +inline bool operator == (const VBezier &l, const VBezier &r) +{ + return std::tie(l.x1, l.y1, l.x2, l.y2, l.x3, l.y3, l.x4, l.y4) + == std::tie(r.x1, r.y1, r.x2, r.y2, r.x3, r.y3, r.x4, r.y4); +} +inline bool operator != (const VBezier &l, const VBezier &r) +{ + return !(l == r); +} + V_END_NAMESPACE #endif // VBEZIER_H diff --git a/src/vector/vraster.cpp b/src/vector/vraster.cpp index fdf66fb0..007b56e4 100644 --- a/src/vector/vraster.cpp +++ b/src/vector/vraster.cpp @@ -373,6 +373,7 @@ struct VRleTask { { if (mPath.points().size() > SHRT_MAX || mPath.points().size() + mPath.segments() > SHRT_MAX) { + mRle.notify(); return; }