lottie/slot: refactor override mechanism to property level

Previously, overriding properties were accessed through their parent objects,
which wasn't a best solution.

This change moves the target/source access to the property level directly, making the logic more flexible and simple.

issue: https://github.com/thorvg/thorvg/issues/3099
This commit is contained in:
Jinny You 2025-07-22 01:32:49 +09:00
parent 16604a873a
commit e7057ef118
3 changed files with 42 additions and 32 deletions

View file

@ -203,7 +203,7 @@ void LottieSlot::reset()
} }
void LottieSlot::assign(LottieObject* target, bool byDefault) void LottieSlot::assign(LottieProperty* target, bool byDefault)
{ {
auto copy = !overridden && !byDefault; auto copy = !overridden && !byDefault;
auto shallow = pairs.count == 1 ? true : false; auto shallow = pairs.count == 1 ? true : false;
@ -214,22 +214,22 @@ void LottieSlot::assign(LottieObject* target, bool byDefault)
switch (type) { switch (type) {
case LottieProperty::Type::Float: { case LottieProperty::Type::Float: {
if (copy) pair->prop = new LottieFloat(static_cast<LottieTransform*>(pair->obj)->rotation); if (copy) pair->prop = new LottieFloat(static_cast<LottieTransform*>(pair->obj)->rotation);
pair->obj->override(&static_cast<LottieTransform*>(target)->rotation, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::Scalar: { case LottieProperty::Type::Scalar: {
if (copy) pair->prop = new LottieScalar(static_cast<LottieTransform*>(pair->obj)->scale); if (copy) pair->prop = new LottieScalar(static_cast<LottieTransform*>(pair->obj)->scale);
pair->obj->override(&static_cast<LottieTransform*>(target)->scale, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::Vector: { case LottieProperty::Type::Vector: {
if (copy) pair->prop = new LottieVector(static_cast<LottieTransform*>(pair->obj)->position); if (copy) pair->prop = new LottieVector(static_cast<LottieTransform*>(pair->obj)->position);
pair->obj->override(&static_cast<LottieTransform*>(target)->position, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::Color: { case LottieProperty::Type::Color: {
if (copy) pair->prop = new LottieColor(static_cast<LottieSolid*>(pair->obj)->color); if (copy) pair->prop = new LottieColor(static_cast<LottieSolid*>(pair->obj)->color);
pair->obj->override(&static_cast<LottieSolid*>(target)->color, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::Opacity: { case LottieProperty::Type::Opacity: {
@ -237,22 +237,22 @@ void LottieSlot::assign(LottieObject* target, bool byDefault)
if (pair->obj->type == LottieObject::Type::Transform) pair->prop = new LottieOpacity(static_cast<LottieTransform*>(pair->obj)->opacity); if (pair->obj->type == LottieObject::Type::Transform) pair->prop = new LottieOpacity(static_cast<LottieTransform*>(pair->obj)->opacity);
else pair->prop = new LottieOpacity(static_cast<LottieSolid*>(pair->obj)->opacity); else pair->prop = new LottieOpacity(static_cast<LottieSolid*>(pair->obj)->opacity);
} }
pair->obj->override(&static_cast<LottieSolid*>(target)->opacity, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::ColorStop: { case LottieProperty::Type::ColorStop: {
if (copy) pair->prop = new LottieColorStop(static_cast<LottieGradient*>(pair->obj)->colorStops); if (copy) pair->prop = new LottieColorStop(static_cast<LottieGradient*>(pair->obj)->colorStops);
pair->obj->override(&static_cast<LottieGradient*>(target)->colorStops, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::TextDoc: { case LottieProperty::Type::TextDoc: {
if (copy) pair->prop = new LottieTextDoc(static_cast<LottieText*>(pair->obj)->doc); if (copy) pair->prop = new LottieTextDoc(static_cast<LottieText*>(pair->obj)->doc);
pair->obj->override(&static_cast<LottieText*>(target)->doc, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
case LottieProperty::Type::Image: { case LottieProperty::Type::Image: {
if (copy) pair->prop = new LottieBitmap(static_cast<LottieImage*>(pair->obj)->data); if (copy) pair->prop = new LottieBitmap(static_cast<LottieImage*>(pair->obj)->data);
pair->obj->override(&static_cast<LottieImage*>(target)->data, shallow, !copy); pair->obj->override(target, shallow, !copy);
break; break;
} }
default: break; default: break;

View file

@ -1058,7 +1058,7 @@ struct LottieSlot
LottieProperty* prop; LottieProperty* prop;
}; };
void assign(LottieObject* target, bool byDefault); void assign(LottieProperty* target, bool byDefault);
void reset(); void reset();
LottieSlot(LottieLayer* layer, LottieObject* parent, char* sid, LottieObject* obj, LottieProperty::Type type) : context{layer, parent}, sid(sid), type(type) LottieSlot(LottieLayer* layer, LottieObject* parent, char* sid, LottieObject* obj, LottieProperty::Type type) : context{layer, parent}, sid(sid), type(type)

View file

@ -1543,68 +1543,78 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault)
{ {
enterObject(); enterObject();
//OPTIMIZE: we can create the property directly, without object LottieProperty* prop = nullptr;
LottieObject* obj = nullptr; //slot object
context = {slot->context.layer, slot->context.parent}; context = {slot->context.layer, slot->context.parent};
switch (slot->type) { switch (slot->type) {
case LottieProperty::Type::Float: { case LottieProperty::Type::Float: {
obj = new LottieTransform; prop = new LottieFloat;
parseSlotProperty(static_cast<LottieTransform*>(obj)->rotation); parseSlotProperty(*static_cast<LottieFloat*>(prop));
break; break;
} }
case LottieProperty::Type::Scalar: { case LottieProperty::Type::Scalar: {
obj = new LottieTransform; prop = new LottieScalar;
parseSlotProperty(static_cast<LottieTransform*>(obj)->scale); parseSlotProperty(*static_cast<LottieScalar*>(prop));
break; break;
} }
case LottieProperty::Type::Vector: { case LottieProperty::Type::Vector: {
obj = new LottieTransform; prop = new LottieVector;
parseSlotProperty(static_cast<LottieTransform*>(obj)->position); parseSlotProperty(*static_cast<LottieVector*>(prop));
break; break;
} }
case LottieProperty::Type::Opacity: { case LottieProperty::Type::Opacity: {
obj = new LottieSolid; prop = new LottieOpacity;
parseSlotProperty(static_cast<LottieSolid*>(obj)->opacity); parseSlotProperty(*static_cast<LottieOpacity*>(prop));
break; break;
} }
case LottieProperty::Type::Color: { case LottieProperty::Type::Color: {
obj = new LottieSolid; prop = new LottieColor;
parseSlotProperty(static_cast<LottieSolid*>(obj)->color); parseSlotProperty(*static_cast<LottieColor*>(prop));
break; break;
} }
case LottieProperty::Type::ColorStop: { case LottieProperty::Type::ColorStop: {
obj = new LottieGradient; auto obj = new LottieGradient;
while (auto key = nextObjectKey()) { while (auto key = nextObjectKey()) {
if (KEY_AS("p")) parseColorStop(static_cast<LottieGradient*>(obj)); if (KEY_AS("p")) parseColorStop(obj);
else skip(); else skip();
} }
if (!obj) {
delete(obj);
return false;
}
prop = new LottieColorStop(obj->colorStops);
delete(obj);
break; break;
} }
case LottieProperty::Type::TextDoc: { case LottieProperty::Type::TextDoc: {
obj = new LottieText; prop = new LottieTextDoc;
parseSlotProperty(static_cast<LottieText*>(obj)->doc); parseSlotProperty(*static_cast<LottieTextDoc*>(prop));
break; break;
} }
case LottieProperty::Type::Image: { case LottieProperty::Type::Image: {
auto obj = new LottieObject;
while (auto key = nextObjectKey()) { while (auto key = nextObjectKey()) {
if (KEY_AS("p")) obj = parseAsset(); if (KEY_AS("p")) obj = parseAsset();
else skip(); else skip();
} }
if (!obj) {
delete(obj);
return false;
}
prop = new LottieBitmap(static_cast<LottieImage*>(obj)->data);
delete(obj);
break; break;
} }
default: break; default: break;
} }
if (!obj || Invalid()) { if (!prop || Invalid()) {
delete(obj); delete(prop);
return false; return false;
} }
slot->assign(obj, byDefault); slot->assign(prop, byDefault);
delete(prop);
delete(obj);
return true; return true;
} }