diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 58290d27..22c1b269 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -41,36 +41,10 @@ void LottieSlot::reset() { if (!overridden) return; + auto shallow = pairs.count == 1 ? true : false; + for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { - switch (type) { - case LottieProperty::Type::ColorStop: { - static_cast(pair->obj)->colorStops.release(); - static_cast(pair->obj)->colorStops = *static_cast(pair->prop); - static_cast(pair->prop)->frames = nullptr; - break; - } - case LottieProperty::Type::Color: { - static_cast(pair->obj)->color.release(); - static_cast(pair->obj)->color = *static_cast(pair->prop); - static_cast(pair->prop)->frames = nullptr; - break; - } - case LottieProperty::Type::TextDoc: { - static_cast(pair->obj)->doc.release(); - static_cast(pair->obj)->doc = *static_cast(pair->prop); - static_cast(pair->prop)->frames = nullptr; - break; - } - case LottieProperty::Type::Image: { - static_cast(pair->obj)->data.release(); - static_cast(pair->obj)->data = *static_cast(pair->prop); - static_cast(pair->prop)->b64Data = nullptr; - static_cast(pair->prop)->mimeType = nullptr; - static_cast(pair->obj)->prepare(); - break; - } - default: break; - } + pair->obj->override(pair->prop, shallow, true); delete(pair->prop); pair->prop = nullptr; } @@ -81,6 +55,7 @@ void LottieSlot::reset() void LottieSlot::assign(LottieObject* target, bool byDefault) { auto copy = !overridden && !byDefault; + auto shallow = pairs.count == 1 ? true : false; //apply slot object to all targets for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { @@ -88,27 +63,27 @@ void LottieSlot::assign(LottieObject* target, bool byDefault) switch (type) { case LottieProperty::Type::Opacity: { if (copy) pair->prop = new LottieOpacity(static_cast(pair->obj)->opacity); - pair->obj->override(&static_cast(target)->opacity, byDefault); + pair->obj->override(&static_cast(target)->opacity, shallow, byDefault); break; } case LottieProperty::Type::Color: { if (copy) pair->prop = new LottieColor(static_cast(pair->obj)->color); - pair->obj->override(&static_cast(target)->color, byDefault); + pair->obj->override(&static_cast(target)->color, shallow, byDefault); break; } case LottieProperty::Type::ColorStop: { if (copy) pair->prop = new LottieColorStop(static_cast(pair->obj)->colorStops); - pair->obj->override(&static_cast(target)->colorStops, byDefault); + pair->obj->override(&static_cast(target)->colorStops, shallow, byDefault); break; } case LottieProperty::Type::TextDoc: { if (copy) pair->prop = new LottieTextDoc(static_cast(pair->obj)->doc); - pair->obj->override(&static_cast(target)->doc, byDefault); + pair->obj->override(&static_cast(target)->doc, shallow, byDefault); break; } case LottieProperty::Type::Image: { if (copy) pair->prop = new LottieBitmap(static_cast(pair->obj)->data); - pair->obj->override(&static_cast(target)->data, byDefault); + pair->obj->override(&static_cast(target)->data, shallow, byDefault); break; } default: break; diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 6c0314e3..97b3e1d5 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -158,7 +158,7 @@ struct LottieObject { } - virtual void override(LottieProperty* prop, bool byDefault = false) + virtual void override(LottieProperty* prop, bool shallow, bool byDefault) { TVGERR("LOTTIE", "Unsupported slot type"); } @@ -284,10 +284,10 @@ struct LottieText : LottieObject, LottieRenderPooler LottieObject::type = LottieObject::Text; } - void override(LottieProperty* prop, bool byDefault = false) override + void override(LottieProperty* prop, bool shallow, bool byDefault = false) override { if (byDefault) doc.release(); - doc = *static_cast(prop); + doc.copy(*static_cast(prop), shallow); prepare(); } @@ -556,10 +556,10 @@ struct LottieSolidStroke : LottieSolid, LottieStroke return LottieSolid::property(ix); } - void override(LottieProperty* prop, bool byDefault) override + void override(LottieProperty* prop, bool shallow, bool byDefault) override { if (byDefault) color.release(); - color = *static_cast(prop); + color.copy(*static_cast(prop), shallow); prepare(); } }; @@ -572,14 +572,14 @@ struct LottieSolidFill : LottieSolid LottieObject::type = LottieObject::SolidFill; } - void override(LottieProperty* prop, bool byDefault) override + void override(LottieProperty* prop, bool shallow, bool byDefault) override { if (prop->type == LottieProperty::Type::Opacity) { if (byDefault) opacity.release(); - opacity = *static_cast(prop); + opacity.copy(*static_cast(prop), shallow); } else if (prop->type == LottieProperty::Type::Color) { if (byDefault) color.release(); - color = *static_cast(prop); + color.copy(*static_cast(prop), shallow); } prepare(); } @@ -618,6 +618,12 @@ struct LottieGradient : LottieObject return nullptr; } + void override(LottieProperty* prop, bool shallow, bool byDefault = false) override + { + if (byDefault) colorStops.release(); + colorStops.copy(*static_cast(prop), shallow); + } + uint32_t populate(ColorStop& color, size_t count); Fill* fill(float frameNo, LottieExpressions* exps); @@ -639,10 +645,9 @@ struct LottieGradientFill : LottieGradient LottieGradient::prepare(); } - void override(LottieProperty* prop, bool byDefault) override + void override(LottieProperty* prop, bool shallow, bool byDefault) override { - if (byDefault) colorStops.release(); - colorStops = *static_cast(prop); + LottieGradient::override(prop, shallow, byDefault); prepare(); } @@ -669,10 +674,9 @@ struct LottieGradientStroke : LottieGradient, LottieStroke return LottieGradient::property(ix); } - void override(LottieProperty* prop, bool byDefault = false) override + void override(LottieProperty* prop, bool shallow, bool byDefault = false) override { - if (byDefault) colorStops.release(); - colorStops = *static_cast(prop); + LottieGradient::override(prop, shallow, byDefault); prepare(); } }; @@ -682,10 +686,10 @@ struct LottieImage : LottieObject, LottieRenderPooler { LottieBitmap data; - void override(LottieProperty* prop, bool byDefault = false) override + void override(LottieProperty* prop, bool shallow, bool byDefault = false) override { if (byDefault) data.release(); - data = *static_cast(prop); + data.copy(*static_cast(prop), shallow); update(); } diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 52c53ed4..6e5d2f99 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -487,7 +487,7 @@ void LottieParser::parsePropertyInternal(T& prop) template -void LottieParser::registerSlot(LottieObject* obj, char* sid) +void LottieParser::registerSlot(LottieObject* obj, const char* sid) { //append object if the slot already exists. for (auto slot = comp->slots.begin(); slot < comp->slots.end(); ++slot) { @@ -495,7 +495,7 @@ void LottieParser::registerSlot(LottieObject* obj, char* sid) (*slot)->pairs.push({obj}); return; } - comp->slots.push(new LottieSlot(sid, obj, type)); + comp->slots.push(new LottieSlot(strdup(sid), obj, type)); } @@ -505,7 +505,7 @@ void LottieParser::parseProperty(T& prop, LottieObject* obj) enterObject(); while (auto key = nextObjectKey()) { if (KEY_AS("k")) parsePropertyInternal(prop); - else if (obj && KEY_AS("sid")) registerSlot(obj, getStringCopy()); + else if (obj && KEY_AS("sid")) registerSlot(obj, getString()); else if (KEY_AS("x")) prop.exp = _expression(getStringCopy(), comp, context.layer, context.parent, &prop); else if (KEY_AS("ix")) prop.ix = getInt(); else skip(key); @@ -760,7 +760,7 @@ void LottieParser::parseColorStop(LottieGradient* gradient) while (auto key = nextObjectKey()) { if (KEY_AS("p")) gradient->colorStops.count = getInt(); else if (KEY_AS("k")) parseProperty(gradient->colorStops, gradient); - else if (KEY_AS("sid")) registerSlot(gradient, getStringCopy()); + else if (KEY_AS("sid")) registerSlot(gradient, getString()); else skip(key); } } @@ -964,7 +964,7 @@ LottieObject* LottieParser::parseAsset() unsigned long id = 0; //Used for Image Asset - char* sid = nullptr; + const char* sid = nullptr; const char* data = nullptr; const char* subPath = nullptr; float width = 0.0f; @@ -986,7 +986,7 @@ LottieObject* LottieParser::parseAsset() else if (KEY_AS("w")) width = getFloat(); else if (KEY_AS("h")) height = getFloat(); else if (KEY_AS("e")) embedded = getInt(); - else if (KEY_AS("sid")) sid = getStringCopy(); + else if (KEY_AS("sid")) sid = getString(); else skip(key); } if (data) { diff --git a/src/loaders/lottie/tvgLottieParser.h b/src/loaders/lottie/tvgLottieParser.h index ff6a12fb..576181e7 100644 --- a/src/loaders/lottie/tvgLottieParser.h +++ b/src/loaders/lottie/tvgLottieParser.h @@ -39,7 +39,7 @@ public: bool apply(LottieSlot* slot, bool byDefault); const char* sid(bool first = false); void captureSlots(const char* key); - template void registerSlot(LottieObject* obj, char* sid); + template void registerSlot(LottieObject* obj, const char* sid); LottieComposition* comp = nullptr; const char* dirName = nullptr; //base resource directory diff --git a/src/loaders/lottie/tvgLottieProperty.h b/src/loaders/lottie/tvgLottieProperty.h index c8f37dbf..b8a33f83 100644 --- a/src/loaders/lottie/tvgLottieProperty.h +++ b/src/loaders/lottie/tvgLottieProperty.h @@ -263,7 +263,8 @@ struct LottieGenericProperty : LottieProperty LottieGenericProperty(const LottieGenericProperty& rhs) { - *this = rhs; + copy(rhs); + type = rhs.type; } ~LottieGenericProperty() @@ -334,14 +335,17 @@ struct LottieGenericProperty : LottieProperty return operator()(frameNo); } - LottieGenericProperty& operator=(const LottieGenericProperty& rhs) + void copy(const LottieGenericProperty& rhs, bool shallow = true) { - //shallow copy, used for slot overriding if (rhs.frames) { - frames = rhs.frames; - const_cast&>(rhs).frames = nullptr; + if (shallow) { + frames = rhs.frames; + const_cast&>(rhs).frames = nullptr; + } else { + frames = new Array>; + *frames = *rhs.frames; + } } else value = rhs.value; - return *this; } float angle(float frameNo) { return 0; } @@ -513,7 +517,8 @@ struct LottieColorStop : LottieProperty LottieColorStop(const LottieColorStop& rhs) { - *this = rhs; + copy(rhs); + type = rhs.type; } ~LottieColorStop() @@ -622,20 +627,22 @@ struct LottieColorStop : LottieProperty return fill->colorStops(result.data, count); } - LottieColorStop& operator=(const LottieColorStop& rhs) + void copy(const LottieColorStop& rhs, bool shallow = true) { - //shallow copy, used for slot overriding if (rhs.frames) { - frames = rhs.frames; - const_cast(rhs).frames = nullptr; + if (shallow) { + frames = rhs.frames; + const_cast(rhs).frames = nullptr; + } else { + frames = new Array>; + *frames = *rhs.frames; + } } else { value = rhs.value; const_cast(rhs).value = ColorStop(); } populated = rhs.populated; count = rhs.count; - - return *this; } void prepare() {} @@ -753,7 +760,8 @@ struct LottieTextDoc : LottieProperty LottieTextDoc(const LottieTextDoc& rhs) { - *this = rhs; + copy(rhs); + type = rhs.type; } ~LottieTextDoc() @@ -829,18 +837,21 @@ struct LottieTextDoc : LottieProperty return frame->value; } - LottieTextDoc& operator=(const LottieTextDoc& rhs) + void copy(const LottieTextDoc& rhs, bool shallow = true) { - //shallow copy, used for slot overriding if (rhs.frames) { - frames = rhs.frames; - const_cast(rhs).frames = nullptr; + if (shallow) { + frames = rhs.frames; + const_cast(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; } - return *this; } void prepare() {} @@ -862,7 +873,8 @@ struct LottieBitmap : LottieProperty LottieBitmap(const LottieBitmap& rhs) { - *this = rhs; + copy(rhs); + type = rhs.type; } ~LottieBitmap() @@ -883,19 +895,23 @@ struct LottieBitmap : LottieProperty uint32_t nearest(float time) override { return 0; } float frameNo(int32_t key) override { return 0; } - LottieBitmap& operator=(const LottieBitmap& rhs) + void copy(const LottieBitmap& rhs, bool shallow = true) { - //shallow copy, used for slot overriding - if (rhs.mimeType) b64Data = rhs.b64Data; - else path = rhs.path; - mimeType = rhs.mimeType; + if (shallow) { + b64Data = rhs.b64Data; + mimeType = rhs.mimeType; + } else { + //TODO: optimize here by avoiding data copy + TVGLOG("LOTTIE", "Shallow copy of the image data!"); + b64Data = strdup(rhs.b64Data); + mimeType = strdup(rhs.mimeType); + } size = rhs.size; width = rhs.width; height = rhs.height; const_cast(rhs).b64Data = nullptr; const_cast(rhs).mimeType = nullptr; - return *this; } };