lottie: ++slot overriding

- fixed the ommiting the duplicate keyframe data overriding
- code refactoring

issue: https://github.com/thorvg/thorvg/issues/2988
This commit is contained in:
Hermet Park 2024-11-25 21:44:48 +09:00 committed by Hermet Park
parent b453bd4f40
commit e811a513f2
5 changed files with 78 additions and 83 deletions

View file

@ -39,36 +39,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<LottieGradient*>(pair->obj)->colorStops.release();
static_cast<LottieGradient*>(pair->obj)->colorStops = *static_cast<LottieColorStop*>(pair->prop);
static_cast<LottieColorStop*>(pair->prop)->frames = nullptr;
break;
}
case LottieProperty::Type::Color: {
static_cast<LottieSolid*>(pair->obj)->color.release();
static_cast<LottieSolid*>(pair->obj)->color = *static_cast<LottieColor*>(pair->prop);
static_cast<LottieColor*>(pair->prop)->frames = nullptr;
break;
}
case LottieProperty::Type::TextDoc: {
static_cast<LottieText*>(pair->obj)->doc.release();
static_cast<LottieText*>(pair->obj)->doc = *static_cast<LottieTextDoc*>(pair->prop);
static_cast<LottieTextDoc*>(pair->prop)->frames = nullptr;
break;
}
case LottieProperty::Type::Image: {
static_cast<LottieImage*>(pair->obj)->data.release();
static_cast<LottieImage*>(pair->obj)->data = *static_cast<LottieBitmap*>(pair->prop);
static_cast<LottieBitmap*>(pair->prop)->b64Data = nullptr;
static_cast<LottieBitmap*>(pair->prop)->mimeType = nullptr;
static_cast<LottieImage*>(pair->obj)->prepare();
break;
}
default: break;
}
pair->obj->override(pair->prop, shallow, true);
delete(pair->prop);
pair->prop = nullptr;
}
@ -79,6 +53,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) {
@ -86,27 +61,27 @@ void LottieSlot::assign(LottieObject* target, bool byDefault)
switch (type) {
case LottieProperty::Type::Opacity: {
if (copy) pair->prop = new LottieOpacity(static_cast<LottieSolid*>(pair->obj)->opacity);
pair->obj->override(&static_cast<LottieSolid*>(target)->opacity, byDefault);
pair->obj->override(&static_cast<LottieSolid*>(target)->opacity, shallow, byDefault);
break;
}
case LottieProperty::Type::Color: {
if (copy) pair->prop = new LottieColor(static_cast<LottieSolid*>(pair->obj)->color);
pair->obj->override(&static_cast<LottieSolid*>(target)->color, byDefault);
pair->obj->override(&static_cast<LottieSolid*>(target)->color, shallow, byDefault);
break;
}
case LottieProperty::Type::ColorStop: {
if (copy) pair->prop = new LottieColorStop(static_cast<LottieGradient*>(pair->obj)->colorStops);
pair->obj->override(&static_cast<LottieGradient*>(target)->colorStops, byDefault);
pair->obj->override(&static_cast<LottieGradient*>(target)->colorStops, shallow, byDefault);
break;
}
case LottieProperty::Type::TextDoc: {
if (copy) pair->prop = new LottieTextDoc(static_cast<LottieText*>(pair->obj)->doc);
pair->obj->override(&static_cast<LottieText*>(target)->doc, byDefault);
pair->obj->override(&static_cast<LottieText*>(target)->doc, shallow, byDefault);
break;
}
case LottieProperty::Type::Image: {
if (copy) pair->prop = new LottieBitmap(static_cast<LottieImage*>(pair->obj)->data);
pair->obj->override(&static_cast<LottieImage*>(target)->data, byDefault);
pair->obj->override(&static_cast<LottieImage*>(target)->data, shallow, byDefault);
break;
}
default: break;

View file

@ -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<tvg::Shape>
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<LottieTextDoc*>(prop);
doc.copy(*static_cast<LottieTextDoc*>(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<LottieColor*>(prop);
color.copy(*static_cast<LottieColor*>(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<LottieOpacity*>(prop);
opacity.copy(*static_cast<LottieOpacity*>(prop), shallow);
} else if (prop->type == LottieProperty::Type::Color) {
if (byDefault) color.release();
color = *static_cast<LottieColor*>(prop);
color.copy(*static_cast<LottieColor*>(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<LottieColorStop*>(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<LottieColorStop*>(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<LottieColorStop*>(prop);
LottieGradient::override(prop, shallow, byDefault);
prepare();
}
};
@ -682,10 +686,10 @@ struct LottieImage : LottieObject, LottieRenderPooler<tvg::Picture>
{
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<LottieBitmap*>(prop);
data.copy(*static_cast<LottieBitmap*>(prop), shallow);
update();
}

View file

@ -487,7 +487,7 @@ void LottieParser::parsePropertyInternal(T& prop)
template<LottieProperty::Type type>
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<type>(obj, getStringCopy());
else if (obj && KEY_AS("sid")) registerSlot<type>(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<LottieProperty::Type::ColorStop>(gradient->colorStops, gradient);
else if (KEY_AS("sid")) registerSlot<LottieProperty::Type::ColorStop>(gradient, getStringCopy());
else if (KEY_AS("sid")) registerSlot<LottieProperty::Type::ColorStop>(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) {

View file

@ -39,7 +39,7 @@ public:
bool apply(LottieSlot* slot, bool byDefault);
const char* sid(bool first = false);
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, const char* sid);
LottieComposition* comp = nullptr;
const char* dirName = nullptr; //base resource directory

View file

@ -263,7 +263,8 @@ struct LottieGenericProperty : LottieProperty
LottieGenericProperty(const LottieGenericProperty<T>& rhs)
{
*this = rhs;
copy(rhs);
type = rhs.type;
}
~LottieGenericProperty()
@ -334,14 +335,17 @@ struct LottieGenericProperty : LottieProperty
return operator()(frameNo);
}
LottieGenericProperty<T>& operator=(const LottieGenericProperty<T>& rhs)
void copy(const LottieGenericProperty<T>& rhs, bool shallow = true)
{
//shallow copy, used for slot overriding
if (rhs.frames) {
frames = rhs.frames;
const_cast<LottieGenericProperty<T>&>(rhs).frames = nullptr;
if (shallow) {
frames = rhs.frames;
const_cast<LottieGenericProperty<T>&>(rhs).frames = nullptr;
} else {
frames = new Array<LottieScalarFrame<T>>;
*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()
@ -620,20 +625,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<LottieColorStop&>(rhs).frames = nullptr;
if (shallow) {
frames = rhs.frames;
const_cast<LottieColorStop&>(rhs).frames = nullptr;
} else {
frames = new Array<LottieScalarFrame<ColorStop>>;
*frames = *rhs.frames;
}
} else {
value = rhs.value;
const_cast<LottieColorStop&>(rhs).value = ColorStop();
}
populated = rhs.populated;
count = rhs.count;
return *this;
}
void prepare() {}
@ -751,7 +758,8 @@ struct LottieTextDoc : LottieProperty
LottieTextDoc(const LottieTextDoc& rhs)
{
*this = rhs;
copy(rhs);
type = rhs.type;
}
~LottieTextDoc()
@ -827,18 +835,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<LottieTextDoc&>(rhs).frames = nullptr;
if (shallow) {
frames = rhs.frames;
const_cast<LottieTextDoc&>(rhs).frames = nullptr;
} else {
frames = new Array<LottieScalarFrame<TextDocument>>;
*frames = *rhs.frames;
}
} else {
value = rhs.value;
const_cast<LottieTextDoc&>(rhs).value.text = nullptr;
const_cast<LottieTextDoc&>(rhs).value.name = nullptr;
}
return *this;
}
void prepare() {}
@ -860,7 +871,8 @@ struct LottieBitmap : LottieProperty
LottieBitmap(const LottieBitmap& rhs)
{
*this = rhs;
copy(rhs);
type = rhs.type;
}
~LottieBitmap()
@ -881,19 +893,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<LottieBitmap&>(rhs).b64Data = nullptr;
const_cast<LottieBitmap&>(rhs).mimeType = nullptr;
return *this;
}
};