mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
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:
parent
b453bd4f40
commit
e811a513f2
5 changed files with 78 additions and 83 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue