diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index c5eff903..0991bbb6 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -926,7 +926,7 @@ struct LottieSlot void assign(LottieObject* target, bool byDefault); void reset(); - LottieSlot(char* sid, LottieObject* obj, LottieProperty::Type type) : sid(sid), type(type) + LottieSlot(LottieLayer* layer, LottieObject* parent, char* sid, LottieObject* obj, LottieProperty::Type type) : context{layer, parent}, sid(sid), type(type) { pairs.push({obj}); } @@ -940,9 +940,15 @@ struct LottieSlot } } + struct { + LottieLayer* layer; + LottieObject* parent; + } context; + char* sid; Array pairs; LottieProperty::Type type; + bool overridden = false; }; diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 7b4f84bc..c81b4afd 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -507,7 +507,7 @@ void LottieParser::registerSlot(LottieObject* obj, const char* sid) (*slot)->pairs.push({obj}); return; } - comp->slots.push(new LottieSlot(strdup(sid), obj, type)); + comp->slots.push(new LottieSlot(context.layer, context.parent, strdup(sid), obj, type)); } @@ -1538,41 +1538,36 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault) //OPTIMIZE: we can create the property directly, without object LottieObject* obj = nullptr; //slot object + context = {slot->context.layer, slot->context.parent}; switch (slot->type) { case LottieProperty::Type::Position: { obj = new LottieTransform; - context.parent = obj; parseSlotProperty(static_cast(obj)->position); break; } case LottieProperty::Type::Point: { obj = new LottieTransform; - context.parent = obj; parseSlotProperty(static_cast(obj)->scale); break; } case LottieProperty::Type::Float: { obj = new LottieTransform; - context.parent = obj; parseSlotProperty(static_cast(obj)->rotation); break; } case LottieProperty::Type::Opacity: { obj = new LottieSolid; - context.parent = obj; parseSlotProperty(static_cast(obj)->opacity); break; } case LottieProperty::Type::Color: { obj = new LottieSolid; - context.parent = obj; parseSlotProperty(static_cast(obj)->color); break; } case LottieProperty::Type::ColorStop: { obj = new LottieGradient; - context.parent = obj; while (auto key = nextObjectKey()) { if (KEY_AS("p")) parseColorStop(static_cast(obj)); else skip(key); @@ -1581,7 +1576,6 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault) } case LottieProperty::Type::TextDoc: { obj = new LottieText; - context.parent = obj; parseSlotProperty(static_cast(obj)->doc); break; } @@ -1590,7 +1584,6 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault) if (KEY_AS("p")) obj = parseAsset(); else skip(key); } - context.parent = obj; break; } default: break; diff --git a/src/loaders/lottie/tvgLottieProperty.h b/src/loaders/lottie/tvgLottieProperty.h index 0947c762..07abff4f 100644 --- a/src/loaders/lottie/tvgLottieProperty.h +++ b/src/loaders/lottie/tvgLottieProperty.h @@ -34,6 +34,7 @@ struct LottieFont; struct LottieLayer; struct LottieObject; +struct LottieProperty; template @@ -109,23 +110,6 @@ struct LottieVectorFrame }; -//Property would have an either keyframes or single value. -struct LottieProperty -{ - enum class Type : uint8_t { Point = 0, Float, Opacity, Color, PathSet, ColorStop, Position, TextDoc, Image, Invalid }; - - LottieExpression* exp = nullptr; - Type type; - uint8_t ix; //property index - - //TODO: Apply common bodies? - virtual ~LottieProperty() {} - virtual uint32_t frameCnt() = 0; - virtual uint32_t nearest(float time) = 0; - virtual float frameNo(int32_t key) = 0; -}; - - struct LottieExpression { enum LoopMode : uint8_t { None = 0, InCycle = 1, InPingPong, InOffset, InContinue, OutCycle, OutPingPong, OutOffset, OutContinue }; @@ -143,6 +127,18 @@ struct LottieExpression LoopMode mode = None; } loop; + LottieExpression() {} + + LottieExpression(const LottieExpression* rhs) + { + code = strdup(rhs->code); + comp = rhs->comp; + layer = rhs->layer; + object = rhs->object; + property = rhs->property; + disabled = rhs->disabled; + } + ~LottieExpression() { free(code); @@ -150,6 +146,36 @@ struct LottieExpression }; +//Property would have an either keyframes or single value. +struct LottieProperty +{ + enum class Type : uint8_t { Point = 0, Float, Opacity, Color, PathSet, ColorStop, Position, TextDoc, Image, Invalid }; + + LottieExpression* exp = nullptr; + Type type; + uint8_t ix; //property index + + //TODO: Apply common bodies? + virtual ~LottieProperty() {} + virtual uint32_t frameCnt() = 0; + virtual uint32_t nearest(float time) = 0; + virtual float frameNo(int32_t key) = 0; + + bool copy(LottieProperty* rhs, bool shallow) + { + if (!rhs->exp) return false; + if (shallow) { + exp = rhs->exp; + rhs->exp = nullptr; + } else { + exp = new LottieExpression(rhs->exp); + } + exp->property = this; + return true; + } +}; + + static void _copy(PathSet* pathset, Array& outPts, Matrix* transform) { Array inPts; @@ -263,7 +289,7 @@ struct LottieGenericProperty : LottieProperty LottieGenericProperty(const LottieGenericProperty& rhs) { - copy(rhs); + copy(const_cast&>(rhs)); type = rhs.type; ix = rhs.ix; } @@ -336,12 +362,15 @@ struct LottieGenericProperty : LottieProperty return operator()(frameNo); } - void copy(const LottieGenericProperty& rhs, bool shallow = true) + void copy(LottieGenericProperty& rhs, bool shallow = true) { + if (LottieProperty::copy(&rhs, shallow)) return; + if (rhs.frames) { if (shallow) { frames = rhs.frames; const_cast&>(rhs).frames = nullptr; + rhs.frames = nullptr; } else { frames = new Array>; *frames = *rhs.frames; @@ -518,7 +547,7 @@ struct LottieColorStop : LottieProperty LottieColorStop(const LottieColorStop& rhs) { - copy(rhs); + copy(const_cast(rhs)); type = rhs.type; ix = rhs.ix; } @@ -629,19 +658,21 @@ struct LottieColorStop : LottieProperty return fill->colorStops(result.data, count); } - void copy(const LottieColorStop& rhs, bool shallow = true) + void copy(LottieColorStop& rhs, bool shallow = true) { + if (LottieProperty::copy(&rhs, shallow)) return; + if (rhs.frames) { if (shallow) { frames = rhs.frames; - const_cast(rhs).frames = nullptr; + rhs.frames = nullptr; } else { frames = new Array>; *frames = *rhs.frames; } } else { value = rhs.value; - const_cast(rhs).value = ColorStop(); + rhs.value = ColorStop(); } populated = rhs.populated; count = rhs.count; @@ -775,7 +806,7 @@ struct LottieTextDoc : LottieProperty LottieTextDoc(const LottieTextDoc& rhs) { - copy(rhs); + copy(const_cast(rhs)); type = rhs.type; ix = rhs.ix; } @@ -853,20 +884,22 @@ struct LottieTextDoc : LottieProperty return frame->value; } - void copy(const LottieTextDoc& rhs, bool shallow = true) + void copy(LottieTextDoc& rhs, bool shallow = true) { + if (LottieProperty::copy(&rhs, shallow)) return; + if (rhs.frames) { if (shallow) { frames = rhs.frames; - const_cast(rhs).frames = nullptr; + rhs.frames = nullptr; } else { frames = new Array>; *frames = *rhs.frames; } } else { value = rhs.value; - const_cast(rhs).value.text = nullptr; - const_cast(rhs).value.name = nullptr; + rhs.value.text = nullptr; + rhs.value.name = nullptr; } } @@ -889,7 +922,7 @@ struct LottieBitmap : LottieProperty LottieBitmap(const LottieBitmap& rhs) { - copy(rhs); + copy(const_cast(rhs)); type = rhs.type; ix = rhs.ix; } @@ -912,8 +945,10 @@ struct LottieBitmap : LottieProperty uint32_t nearest(float time) override { return 0; } float frameNo(int32_t key) override { return 0; } - void copy(const LottieBitmap& rhs, bool shallow = true) + void copy(LottieBitmap& rhs, bool shallow = true) { + if (LottieProperty::copy(&rhs, shallow)) return; + if (shallow) { b64Data = rhs.b64Data; mimeType = rhs.mimeType; @@ -927,8 +962,8 @@ struct LottieBitmap : LottieProperty width = rhs.width; height = rhs.height; - const_cast(rhs).b64Data = nullptr; - const_cast(rhs).mimeType = nullptr; + rhs.b64Data = nullptr; + rhs.mimeType = nullptr; } };