lottie: corrected an omission in overriding the default slot

issue: https://github.com/thorvg/thorvg/issues/2953
This commit is contained in:
Hermet Park 2024-11-18 16:23:23 +09:00
parent fcf080cc4e
commit 88098f547f
7 changed files with 108 additions and 85 deletions

View file

@ -44,7 +44,7 @@ void LottieLoader::run(unsigned tid)
comp = parser.comp; comp = parser.comp;
} }
if (parser.slots) { if (parser.slots) {
override(parser.slots, false); override(parser.slots, true);
parser.slots = nullptr; parser.slots = nullptr;
} }
builder->build(comp); builder->build(comp);
@ -290,7 +290,7 @@ Paint* LottieLoader::paint()
} }
bool LottieLoader::override(const char* slots, bool copy) bool LottieLoader::override(const char* slots, bool byDefault)
{ {
if (!ready() || comp->slots.count == 0) return false; if (!ready() || comp->slots.count == 0) return false;
@ -299,7 +299,7 @@ bool LottieLoader::override(const char* slots, bool copy)
//override slots //override slots
if (slots) { if (slots) {
//Copy the input data because the JSON parser will encode the data immediately. //Copy the input data because the JSON parser will encode the data immediately.
auto temp = copy ? strdup(slots) : slots; auto temp = byDefault ? slots : strdup(slots);
//parsing slot json //parsing slot json
LottieParser parser(temp, dirName); LottieParser parser(temp, dirName);
@ -309,7 +309,7 @@ bool LottieLoader::override(const char* slots, bool copy)
while (auto sid = parser.sid(idx == 0)) { while (auto sid = parser.sid(idx == 0)) {
for (auto s = comp->slots.begin(); s < comp->slots.end(); ++s) { for (auto s = comp->slots.begin(); s < comp->slots.end(); ++s) {
if (strcmp((*s)->sid, sid)) continue; if (strcmp((*s)->sid, sid)) continue;
if (!parser.apply(*s)) success = false; if (!parser.apply(*s, byDefault)) success = false;
break; break;
} }
++idx; ++idx;

View file

@ -57,7 +57,7 @@ public:
bool resize(Paint* paint, float w, float h) override; bool resize(Paint* paint, float w, float h) override;
bool read() override; bool read() override;
Paint* paint() override; Paint* paint() override;
bool override(const char* slot, bool copy = true); bool override(const char* slot, bool byDefault = false);
//Frame Controls //Frame Controls
bool frame(float no) override; bool frame(float no) override;

View file

@ -78,56 +78,43 @@ void LottieSlot::reset()
} }
void LottieSlot::assign(LottieObject* target) void LottieSlot::assign(LottieObject* target, bool byDefault)
{ {
auto copy = !overridden && !byDefault;
//apply slot object to all targets //apply slot object to all targets
for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) {
//backup the original properties before overwriting //backup the original properties before overwriting
switch (type) { switch (type) {
case LottieProperty::Type::Opacity: { case LottieProperty::Type::Opacity: {
if (!overridden) { if (copy) pair->prop = new LottieOpacity(static_cast<LottieSolid*>(pair->obj)->opacity);
pair->prop = new LottieOpacity; pair->obj->override(&static_cast<LottieSolid*>(target)->opacity, byDefault);
*static_cast<LottieOpacity*>(pair->prop) = static_cast<LottieSolid*>(pair->obj)->opacity;
}
pair->obj->override(&static_cast<LottieSolid*>(target)->opacity);
break; break;
} }
case LottieProperty::Type::Color: { case LottieProperty::Type::Color: {
if (!overridden) { if (copy) pair->prop = new LottieColor(static_cast<LottieSolid*>(pair->obj)->color);
pair->prop = new LottieColor; pair->obj->override(&static_cast<LottieSolid*>(target)->color, byDefault);
*static_cast<LottieColor*>(pair->prop) = static_cast<LottieSolid*>(pair->obj)->color;
}
pair->obj->override(&static_cast<LottieSolid*>(target)->color);
break; break;
} }
case LottieProperty::Type::ColorStop: { case LottieProperty::Type::ColorStop: {
if (!overridden) { if (copy) pair->prop = new LottieColorStop(static_cast<LottieGradient*>(pair->obj)->colorStops);
pair->prop = new LottieColorStop; pair->obj->override(&static_cast<LottieGradient*>(target)->colorStops, byDefault);
*static_cast<LottieColorStop*>(pair->prop) = static_cast<LottieGradient*>(pair->obj)->colorStops;
}
pair->obj->override(&static_cast<LottieGradient*>(target)->colorStops);
break; break;
} }
case LottieProperty::Type::TextDoc: { case LottieProperty::Type::TextDoc: {
if (!overridden) { if (copy) pair->prop = new LottieTextDoc(static_cast<LottieText*>(pair->obj)->doc);
pair->prop = new LottieTextDoc; pair->obj->override(&static_cast<LottieText*>(target)->doc, byDefault);
*static_cast<LottieTextDoc*>(pair->prop) = static_cast<LottieText*>(pair->obj)->doc;
}
pair->obj->override(&static_cast<LottieText*>(target)->doc);
break; break;
} }
case LottieProperty::Type::Image: { case LottieProperty::Type::Image: {
if (!overridden) { if (copy) pair->prop = new LottieBitmap(static_cast<LottieImage*>(pair->obj)->data);
pair->prop = new LottieBitmap; pair->obj->override(&static_cast<LottieImage*>(target)->data, byDefault);
*static_cast<LottieBitmap*>(pair->prop) = static_cast<LottieImage*>(pair->obj)->data;
}
pair->obj->override(&static_cast<LottieImage*>(target)->data);
break; break;
} }
default: break; default: break;
} }
} }
overridden = true; if (!byDefault) overridden = true;
} }

View file

@ -142,7 +142,7 @@ struct LottieObject
{ {
} }
virtual void override(LottieProperty* prop) virtual void override(LottieProperty* prop, bool byDefault = false)
{ {
TVGERR("LOTTIE", "Unsupported slot type"); TVGERR("LOTTIE", "Unsupported slot type");
} }
@ -262,10 +262,11 @@ struct LottieText : LottieObject, LottieRenderPooler<tvg::Shape>
LottieObject::type = LottieObject::Text; LottieObject::type = LottieObject::Text;
} }
void override(LottieProperty* prop) override void override(LottieProperty* prop, bool byDefault = false) override
{ {
this->doc = *static_cast<LottieTextDoc*>(prop); if (byDefault) doc.release();
this->prepare(); doc = *static_cast<LottieTextDoc*>(prop);
prepare();
} }
LottieProperty* property(uint16_t ix) override LottieProperty* property(uint16_t ix) override
@ -533,10 +534,11 @@ struct LottieSolidStroke : LottieSolid, LottieStroke
return LottieSolid::property(ix); return LottieSolid::property(ix);
} }
void override(LottieProperty* prop) override void override(LottieProperty* prop, bool byDefault) override
{ {
this->color = *static_cast<LottieColor*>(prop); if (byDefault) color.release();
this->prepare(); color = *static_cast<LottieColor*>(prop);
prepare();
} }
}; };
@ -548,11 +550,16 @@ struct LottieSolidFill : LottieSolid
LottieObject::type = LottieObject::SolidFill; LottieObject::type = LottieObject::SolidFill;
} }
void override(LottieProperty* prop) override void override(LottieProperty* prop, bool byDefault) override
{ {
if (prop->type == LottieProperty::Type::Opacity) this->opacity = *static_cast<LottieOpacity*>(prop); if (prop->type == LottieProperty::Type::Opacity) {
else if (prop->type == LottieProperty::Type::Color) this->color = *static_cast<LottieColor*>(prop); if (byDefault) opacity.release();
this->prepare(); opacity = *static_cast<LottieOpacity*>(prop);
} else if (prop->type == LottieProperty::Type::Color) {
if (byDefault) color.release();
color = *static_cast<LottieColor*>(prop);
}
prepare();
} }
FillRule rule = FillRule::Winding; FillRule rule = FillRule::Winding;
@ -610,10 +617,11 @@ struct LottieGradientFill : LottieGradient
LottieGradient::prepare(); LottieGradient::prepare();
} }
void override(LottieProperty* prop) override void override(LottieProperty* prop, bool byDefault) override
{ {
this->colorStops = *static_cast<LottieColorStop*>(prop); if (byDefault) colorStops.release();
this->prepare(); colorStops = *static_cast<LottieColorStop*>(prop);
prepare();
} }
FillRule rule = FillRule::Winding; FillRule rule = FillRule::Winding;
@ -639,10 +647,11 @@ struct LottieGradientStroke : LottieGradient, LottieStroke
return LottieGradient::property(ix); return LottieGradient::property(ix);
} }
void override(LottieProperty* prop) override void override(LottieProperty* prop, bool byDefault = false) override
{ {
this->colorStops = *static_cast<LottieColorStop*>(prop); if (byDefault) colorStops.release();
this->prepare(); colorStops = *static_cast<LottieColorStop*>(prop);
prepare();
} }
}; };
@ -651,10 +660,11 @@ struct LottieImage : LottieObject, LottieRenderPooler<tvg::Picture>
{ {
LottieBitmap data; LottieBitmap data;
void override(LottieProperty* prop) override void override(LottieProperty* prop, bool byDefault = false) override
{ {
this->data = *static_cast<LottieBitmap*>(prop); if (byDefault) data.release();
this->prepare(); data = *static_cast<LottieBitmap*>(prop);
prepare();
} }
void prepare(); void prepare();
@ -825,7 +835,7 @@ struct LottieSlot
LottieProperty* prop; LottieProperty* prop;
}; };
void assign(LottieObject* target); void assign(LottieObject* target, bool byDefault);
void reset(); void reset();
LottieSlot(char* sid, LottieObject* obj, LottieProperty::Type type) : sid(sid), type(type) LottieSlot(char* sid, LottieObject* obj, LottieProperty::Type type) : sid(sid), type(type)

View file

@ -1441,7 +1441,7 @@ const char* LottieParser::sid(bool first)
} }
bool LottieParser::apply(LottieSlot* slot) bool LottieParser::apply(LottieSlot* slot, bool byDefault)
{ {
enterObject(); enterObject();
@ -1486,7 +1486,7 @@ bool LottieParser::apply(LottieSlot* slot)
if (!obj || Invalid()) return false; if (!obj || Invalid()) return false;
slot->assign(obj); slot->assign(obj, byDefault);
delete(obj); delete(obj);

View file

@ -36,7 +36,7 @@ public:
} }
bool parse(); bool parse();
bool apply(LottieSlot* slot); bool apply(LottieSlot* slot, bool byDefault);
const char* sid(bool first = false); const char* sid(bool first = false);
void captureSlots(const char* key); void captureSlots(const char* key);
template<LottieProperty::Type type = LottieProperty::Type::Invalid> void registerSlot(LottieObject* obj, char* sid); template<LottieProperty::Type type = LottieProperty::Type::Invalid> void registerSlot(LottieObject* obj, char* sid);

View file

@ -261,6 +261,11 @@ struct LottieGenericProperty : LottieProperty
LottieGenericProperty(T v) : value(v) {} LottieGenericProperty(T v) : value(v) {}
LottieGenericProperty() {} LottieGenericProperty() {}
LottieGenericProperty(const LottieGenericProperty<T>& rhs)
{
*this = rhs;
}
~LottieGenericProperty() ~LottieGenericProperty()
{ {
release(); release();
@ -329,13 +334,13 @@ struct LottieGenericProperty : LottieProperty
return operator()(frameNo); return operator()(frameNo);
} }
LottieGenericProperty<T>& operator=(const LottieGenericProperty<T>& other) LottieGenericProperty<T>& operator=(const LottieGenericProperty<T>& rhs)
{ {
//shallow copy, used for slot overriding //shallow copy, used for slot overriding
if (other.frames) { if (rhs.frames) {
frames = other.frames; frames = rhs.frames;
const_cast<LottieGenericProperty<T>&>(other).frames = nullptr; const_cast<LottieGenericProperty<T>&>(rhs).frames = nullptr;
} else value = other.value; } else value = rhs.value;
return *this; return *this;
} }
@ -504,6 +509,13 @@ struct LottieColorStop : LottieProperty
uint16_t count = 0; //colorstop count uint16_t count = 0; //colorstop count
bool populated = false; bool populated = false;
LottieColorStop() {}
LottieColorStop(const LottieColorStop& rhs)
{
*this = rhs;
}
~LottieColorStop() ~LottieColorStop()
{ {
release(); release();
@ -610,18 +622,18 @@ struct LottieColorStop : LottieProperty
return fill->colorStops(result.data, count); return fill->colorStops(result.data, count);
} }
LottieColorStop& operator=(const LottieColorStop& other) LottieColorStop& operator=(const LottieColorStop& rhs)
{ {
//shallow copy, used for slot overriding //shallow copy, used for slot overriding
if (other.frames) { if (rhs.frames) {
frames = other.frames; frames = rhs.frames;
const_cast<LottieColorStop&>(other).frames = nullptr; const_cast<LottieColorStop&>(rhs).frames = nullptr;
} else { } else {
value = other.value; value = rhs.value;
const_cast<LottieColorStop&>(other).value = {nullptr, nullptr}; const_cast<LottieColorStop&>(rhs).value = {nullptr, nullptr};
} }
populated = other.populated; populated = rhs.populated;
count = other.count; count = rhs.count;
return *this; return *this;
} }
@ -737,6 +749,13 @@ struct LottieTextDoc : LottieProperty
Array<LottieScalarFrame<TextDocument>>* frames = nullptr; Array<LottieScalarFrame<TextDocument>>* frames = nullptr;
TextDocument value; TextDocument value;
LottieTextDoc() {}
LottieTextDoc(const LottieTextDoc& rhs)
{
*this = rhs;
}
~LottieTextDoc() ~LottieTextDoc()
{ {
release(); release();
@ -810,16 +829,16 @@ struct LottieTextDoc : LottieProperty
return frame->value; return frame->value;
} }
LottieTextDoc& operator=(const LottieTextDoc& other) LottieTextDoc& operator=(const LottieTextDoc& rhs)
{ {
//shallow copy, used for slot overriding //shallow copy, used for slot overriding
if (other.frames) { if (rhs.frames) {
frames = other.frames; frames = rhs.frames;
const_cast<LottieTextDoc&>(other).frames = nullptr; const_cast<LottieTextDoc&>(rhs).frames = nullptr;
} else { } else {
value = other.value; value = rhs.value;
const_cast<LottieTextDoc&>(other).value.text = nullptr; const_cast<LottieTextDoc&>(rhs).value.text = nullptr;
const_cast<LottieTextDoc&>(other).value.name = nullptr; const_cast<LottieTextDoc&>(rhs).value.name = nullptr;
} }
return *this; return *this;
} }
@ -839,6 +858,13 @@ struct LottieBitmap : LottieProperty
float width = 0.0f; float width = 0.0f;
float height = 0.0f; float height = 0.0f;
LottieBitmap() {}
LottieBitmap(const LottieBitmap& rhs)
{
*this = rhs;
}
~LottieBitmap() ~LottieBitmap()
{ {
release(); release();
@ -857,18 +883,18 @@ struct LottieBitmap : LottieProperty
uint32_t nearest(float time) override { return 0; } uint32_t nearest(float time) override { return 0; }
float frameNo(int32_t key) override { return 0; } float frameNo(int32_t key) override { return 0; }
LottieBitmap& operator=(const LottieBitmap& other) LottieBitmap& operator=(const LottieBitmap& rhs)
{ {
//shallow copy, used for slot overriding //shallow copy, used for slot overriding
if (other.mimeType) b64Data = other.b64Data; if (rhs.mimeType) b64Data = rhs.b64Data;
else path = other.path; else path = rhs.path;
mimeType = other.mimeType; mimeType = rhs.mimeType;
size = other.size; size = rhs.size;
width = other.width; width = rhs.width;
height = other.height; height = rhs.height;
const_cast<LottieBitmap&>(other).b64Data = nullptr; const_cast<LottieBitmap&>(rhs).b64Data = nullptr;
const_cast<LottieBitmap&>(other).mimeType = nullptr; const_cast<LottieBitmap&>(rhs).mimeType = nullptr;
return *this; return *this;
} }
}; };