This commit is contained in:
Jinny You 2025-05-26 23:16:36 +09:00 committed by GitHub
commit c875f49864
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 392 additions and 88 deletions

View file

@ -177,7 +177,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample1.json"))) return false;
const char* slotJson = R"({"gradient_fill":{"p":{"p":2,"k":{"k":[0,0.1,0.1,0.2,1,1,0.1,0.2,0,0,1,1]}}}})";
if (!tvgexam::verify(slot1->override(slotJson))) return false;
auto slotId = slot1->genSlot(slotJson);
if (!tvgexam::verify(slot1->applySlot(slotId))) return false;
sizing(picture, 1);
@ -191,7 +192,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample2.json"))) return false;
const char* slotJson = R"({"ball_color":{"p":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0,0.176,0.867]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":22,"s":[0.867,0,0.533]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":37,"s":[0.867,0,0.533]},{"t":51,"s":[0,0.867,0.255]}]}}})";
if (!tvgexam::verify(slot2->override(slotJson))) return false;
auto slotId = slot2->genSlot(slotJson);
if (!tvgexam::verify(slot2->applySlot(slotId))) return false;
sizing(picture, 2);
@ -205,7 +207,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample3.json"))) return false;
const char* slotJson = R"({"path_img":{"p":{"id":"image_0","w":200,"h":300,"u":"images/","p":"logo.png","e":0}}})";
if (!tvgexam::verify(slot3->override(slotJson))) return false;
auto slotId = slot3->genSlot(slotJson);
if (!tvgexam::verify(slot3->applySlot(slotId))) return false;
sizing(picture, 3);
@ -219,7 +222,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample4.json"))) return false;
const char* slotJson = R"({"bg_color":{"p":{"a":0,"k":[1,0.8196,0.2275]}},"check_color":{"p":{"a":0,"k":[0.0078,0.0078,0.0078]}}})";
if (!tvgexam::verify(slot4->override(slotJson))) return false;
auto slotId = slot4->genSlot(slotJson);
if (!tvgexam::verify(slot4->applySlot(slotId))) return false;
sizing(picture, 4);
@ -244,7 +248,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample6.json"))) return false;
const char* slotJson = R"({"position_id":{"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"s":[100,100],"t":0},{"s":[200,300],"t":100}]}}})";
if (!tvgexam::verify(slot6->override(slotJson))) return false;
auto slotId = slot6->genSlot(slotJson);
if (!tvgexam::verify(slot6->applySlot(slotId))) return false;
sizing(picture, 6);
@ -258,7 +263,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample7.json"))) return false;
const char* slotJson = R"({"scale_id":{"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"s":[0,0],"t":0},{"s":[100,100],"t":100}]}}})";
if (!tvgexam::verify(slot7->override(slotJson))) return false;
auto slotId = slot7->genSlot(slotJson);
if (!tvgexam::verify(slot7->applySlot(slotId))) return false;
sizing(picture, 7);
@ -272,7 +278,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample8.json"))) return false;
const char* slotJson = R"({"rotation_id":{"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"s":[0],"t":0},{"s":[180],"t":100}]}}})";
if (!tvgexam::verify(slot8->override(slotJson))) return false;
auto slotId = slot8->genSlot(slotJson);
if (!tvgexam::verify(slot8->applySlot(slotId))) return false;
sizing(picture, 8);
@ -286,7 +293,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample9.json"))) return false;
const char* slotJson = R"({"opacity_id":{"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"s":[0],"t":0},{"s":[100],"t":100}]}}})";
if (!tvgexam::verify(slot9->override(slotJson))) return false;
auto slotId = slot9->genSlot(slotJson);
if (!tvgexam::verify(slot9->applySlot(slotId))) return false;
sizing(picture, 9);
@ -300,7 +308,8 @@ struct UserExample : tvgexam::Example
if (!tvgexam::verify(picture->load(EXAMPLE_DIR"/lottie/extensions/slotsample10.json"))) return false;
const char* slotJson = R"({"rect_rotation":{"p":{"x":"var $bm_rt = time * 360;"}},"rect_scale":{"p":{"x":"var $bm_rt = [];$bm_rt[0] = value[0] + Math.cos(2 * Math.PI * time) * 100;$bm_rt[1] = value[1];"}},"rect_position":{"p":{"x":"var $bm_rt = [];$bm_rt[0] = value[0] + Math.cos(2 * Math.PI * time) * 100;$bm_rt[1] = value[1];"}}})";
if (!tvgexam::verify(slot10->override(slotJson))) return false;
auto slotId = slot10->genSlot(slotJson);
if (!tvgexam::verify(slot10->applySlot(slotId))) return false;
sizing(picture, 10);
@ -321,6 +330,19 @@ struct UserExample : tvgexam::Example
return true;
}
~UserExample()
{
slot1->delSlot(0);
slot2->delSlot(0);
slot3->delSlot(0);
slot4->delSlot(0);
slot6->delSlot(0);
slot7->delSlot(0);
slot8->delSlot(0);
slot9->delSlot(0);
slot10->delSlot(0);
}
};

View file

@ -2524,19 +2524,47 @@ TVG_API Tvg_Animation* tvg_lottie_animation_new(void);
/*!
* @brief Override the lottie properties through the slot data.
* @brief Generates a new slot from the given slot data.
*
* @param[in] animation The Tvg_Animation object to override the property with the slot.
* @param[in] slot The Lottie slot data in json, or @c nullptr to reset.
* @param[in] animation The Tvg_Animation pointer to the Lottie animation object.
* @param[in] slot The Lottie slot data in JSON format.
*
* @return The generated slot ID when successful, 0 otherwise.
*
* @since 1.0
*/
TVG_API uint32_t tvg_lottie_animation_gen_slot(Tvg_Animation* animation, const char* slot);
/*!
* @brief Applies a previously generated slot to the animation.
*
* @param[in] animation The Tvg_Animation pointer to the Lottie animation object.
* @param[in] id The ID of the slot to apply, or 0 to reset all slots.
*
* @return Tvg_Result enumeration.
* @retval TVG_RESULT_INSUFFICIENT_CONDITION In case the animation is not loaded.
* @retval TVG_RESULT_INVALID_ARGUMENT When the given @p slot is invalid
* @retval TVG_RESULT_INSUFFICIENT_CONDITION In case the animation is not loaded or the slot ID is invalid.
* @retval TVG_RESULT_NOT_SUPPORTED The Lottie Animation is not supported.
*
* @since 1.0
*/
TVG_API Tvg_Result tvg_lottie_animation_override(Tvg_Animation* animation, const char* slot);
TVG_API Tvg_Result tvg_lottie_animation_apply_slot(Tvg_Animation* animation, uint32_t id);
/*!
* @brief Deletes a previously generated slot.
*
* @param[in] animation The Tvg_Animation pointer to the Lottie animation object.
* @param[in] id The ID of the slot to delete, or 0 to delete all slots.
*
* @return Tvg_Result enumeration.
* @retval TVG_RESULT_INSUFFICIENT_CONDITION In case the animation is not loaded or the slot ID is invalid.
* @retval TVG_RESULT_NOT_SUPPORTED The Lottie Animation is not supported.
*
* @since 1.0
*/
TVG_API Tvg_Result tvg_lottie_animation_del_slot(Tvg_Animation* animation, uint32_t id);
/*!

View file

@ -944,11 +944,31 @@ TVG_API Tvg_Animation* tvg_lottie_animation_new()
}
TVG_API Tvg_Result tvg_lottie_animation_override(Tvg_Animation* animation, const char* slot)
TVG_API uint32_t tvg_lottie_animation_gen_slot(Tvg_Animation* animation, const char* slot)
{
#ifdef THORVG_LOTTIE_LOADER_SUPPORT
if (!animation) return 0;
return reinterpret_cast<LottieAnimation*>(animation)->genSlot(slot);
#endif
return 0;
}
TVG_API Tvg_Result tvg_lottie_animation_apply_slot(Tvg_Animation* animation, uint32_t id)
{
#ifdef THORVG_LOTTIE_LOADER_SUPPORT
if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
return (Tvg_Result) reinterpret_cast<LottieAnimation*>(animation)->override(slot);
return (Tvg_Result) reinterpret_cast<LottieAnimation*>(animation)->applySlot(id);
#endif
return TVG_RESULT_NOT_SUPPORTED;
}
TVG_API Tvg_Result tvg_lottie_animation_del_slot(Tvg_Animation* animation, uint32_t id)
{
#ifdef THORVG_LOTTIE_LOADER_SUPPORT
if (!animation) return TVG_RESULT_INVALID_ARGUMENT;
return (Tvg_Result) reinterpret_cast<LottieAnimation*>(animation)->delSlot(id);
#endif
return TVG_RESULT_NOT_SUPPORTED;
}

View file

@ -22,17 +22,6 @@ class TVG_API LottieAnimation final : public Animation
public:
~LottieAnimation() override;
/**
* @brief Override Lottie properties using slot data.
*
* @param[in] slot The Lottie slot data in JSON format to override, or @c nullptr to reset.
*
* @retval Result::InsufficientCondition In case the animation is not loaded.
*
* @since 1.0
*/
Result override(const char* slot) noexcept;
/**
* @brief Specifies a segment by marker.
*
@ -110,6 +99,39 @@ public:
*/
Result assign(const char* layer, uint32_t ix, const char* var, float val);
/**
* @brief Generates a new slot from the given slot data.
*
* @param[in] slot The Lottie slot data in JSON format.
*
* @retval The generated slot ID when successful, 0 otherwise.
*
* @since 1.0
*/
uint32_t genSlot(const char* slot) noexcept;
/**
* @brief Applies a previously generated slot to the animation.
*
* @param[in] slotId The ID of the slot to apply, or 0 to reset all slots.
*
* @retval Result::InsufficientCondition In case the animation is not loaded or the slot ID is invalid.
*
* @since 1.0
*/
Result applySlot(uint32_t slotId) noexcept;
/**
* @brief Deletes a previously generated slot.
*
* @param[in] slotId The ID of the slot to delete, or 0 to delete all slots.
*
* @retval Result::InsufficientCondition In case the animation is not loaded or the slot ID is invalid.
*
* @since 1.0
*/
Result delSlot(uint32_t slotId) noexcept;
/**
* @brief Creates a new LottieAnimation object.
*

View file

@ -30,12 +30,32 @@ LottieAnimation::LottieAnimation() = default;
LottieAnimation::~LottieAnimation() = default;
Result LottieAnimation::override(const char* slot) noexcept
uint32_t LottieAnimation::genSlot(const char* slot) noexcept
{
auto loader = PICTURE(pImpl->picture)->loader;
if (!loader) return 0;
return static_cast<LottieLoader*>(loader)->genSlot(slot);
}
Result LottieAnimation::applySlot(uint32_t slotId) noexcept
{
auto loader = PICTURE(pImpl->picture)->loader;
if (!loader) return Result::InsufficientCondition;
if (static_cast<LottieLoader*>(loader)->override(slot)) return Result::Success;
if (static_cast<LottieLoader*>(loader)->applySlot(slotId)) return Result::Success;
return Result::InvalidArguments;
}
Result LottieAnimation::delSlot(uint32_t slotId) noexcept
{
auto loader = PICTURE(pImpl->picture)->loader;
if (!loader) return Result::InsufficientCondition;
if (static_cast<LottieLoader*>(loader)->delSlot(slotId)) return Result::Success;
return Result::InvalidArguments;
}

View file

@ -25,6 +25,7 @@
#include "tvgLottieModel.h"
#include "tvgLottieParser.h"
#include "tvgLottieBuilder.h"
#include "tvgCompressor.h"
/************************************************************************/
/* Internal Class Implementation */
@ -44,7 +45,9 @@ void LottieLoader::run(unsigned tid)
comp = parser.comp;
}
if (parser.slots) {
override(parser.slots, true);
auto slotId = genSlot(parser.slots);
applySlot(slotId, true);
delSlot(slotId, true);
parser.slots = nullptr;
}
builder->build(comp);
@ -288,45 +291,133 @@ Paint* LottieLoader::paint()
}
bool LottieLoader::override(const char* slots, bool byDefault)
bool LottieLoader::applySlot(uint32_t slotId, bool byDefault)
{
if (!ready() || comp->slots.count == 0) return false;
if (!ready() || comp->slots.count == 0 || comp->slotDatas.empty()) return false;
//override slots
if (slots) {
//Copy the input data because the JSON parser will encode the data immediately.
auto temp = byDefault ? slots : duplicate(slots);
//parsing slot json
LottieParser parser(temp, dirName, builder->expressions());
parser.comp = comp;
auto idx = 0;
auto succeed = false;
while (auto sid = parser.sid(idx == 0)) {
auto applied = false;
ARRAY_FOREACH(p, comp->slots) {
if (strcmp((*p)->sid, sid)) continue;
if (parser.apply(*p, byDefault)) succeed = applied = true;
break;
}
if (!applied) parser.skip();
++idx;
if (slotId == 0) {
ARRAY_FOREACH(p, comp->slots) {
(*p)->reset();
}
tvg::free((char*)temp);
rebuild = succeed;
overridden |= succeed;
return rebuild;
//reset slots
} else if (overridden) {
ARRAY_FOREACH(p, comp->slots) (*p)->reset();
overridden = false;
rebuild = true;
return true;
}
LottieSlotData* slotData = nullptr;
INLIST_FOREACH(comp->slotDatas, p) {
if (p->id == slotId) {
slotData = p;
break;
}
}
if (!slotData) return false;
ARRAY_FOREACH(p, slotData->datas) {
ARRAY_FOREACH(q, comp->slots) {
if (strcmp((*q)->sid, p->sid)) continue;
(*q)->apply(p->prop, byDefault);
break;
}
}
overridden = true;
rebuild = true;
return true;
}
bool LottieLoader::delSlot(uint32_t slotId, bool byDefault)
{
if (!ready() || comp->slots.count == 0 || comp->slotDatas.empty()) return false;
if (slotId == 0) {
if (!byDefault) {
ARRAY_FOREACH(p, comp->slots) {
(*p)->reset();
}
rebuild = true;
}
comp->slotDatas.free();
overridden = false;
return true;
}
LottieSlotData* slotData = nullptr;
INLIST_FOREACH(comp->slotDatas, p) {
if (p->id == slotId) {
slotData = p;
break;
}
}
if (!slotData) return false;
ARRAY_FOREACH(p, slotData->datas) {
ARRAY_FOREACH(q, comp->slots) {
if (strcmp((*q)->sid, p->sid)) continue;
if (!byDefault && (*q)->overridden) {
(*q)->reset();
rebuild = true;
}
break;
}
}
comp->slotDatas.remove(slotData);
delete(slotData);
return true;
}
uint32_t LottieLoader::genSlot(const char* slots)
{
if (!slots || !ready() || comp->slots.count == 0) return 0;
auto slotId = djb2Encode(slots);
INLIST_FOREACH(comp->slotDatas, p) {
if (p->id == slotId) return slotId;
}
auto temp = duplicate(slots);
//parsing slot json
LottieParser parser(temp, dirName, builder->expressions());
parser.comp = comp;
auto idx = 0;
bool generated = false;
LottieSlotData* slotData = new LottieSlotData(slotId);
while (auto sid = parser.sid(idx == 0)) {
ARRAY_FOREACH(p, comp->slots) {
if (strcmp((*p)->sid, sid)) continue;
auto prop = parser.slotData(*p);
if (prop) {
slotData->datas.push({duplicate(sid), prop});
generated = true;
}
break;
}
++idx;
}
tvg::free((char*)temp);
if (generated) comp->slotDatas.back(slotData);
else {
delete(slotData);
return 0;
}
return slotData->id;
}
float LottieLoader::shorten(float frameNo)
{
//This ensures that the target frame number is reached.

View file

@ -56,7 +56,11 @@ public:
bool resize(Paint* paint, float w, float h) override;
bool read() override;
Paint* paint() override;
bool override(const char* slot, bool byDefault = false);
//Slot APIs
uint32_t genSlot(const char* slot);
bool applySlot(uint32_t slotId, bool byDefault = false);
bool delSlot(uint32_t slotId, bool byDefault = false);
//Frame Controls
bool frame(float no) override;

View file

@ -203,7 +203,62 @@ void LottieSlot::reset()
}
void LottieSlot::assign(LottieObject* target, bool byDefault)
LottieProperty* LottieSlot::data(LottieObject* target)
{
LottieProperty* prop = nullptr;
//apply slot object to all targets
ARRAY_FOREACH(pair, pairs) {
//backup the original properties before overwriting
switch (type) {
case LottieProperty::Type::Vector: {
prop = new LottieVector;
static_cast<LottieVector*>(prop)->copy(static_cast<LottieTransform*>(target)->position, false);
break;
}
case LottieProperty::Type::Scalar: {
prop = new LottieScalar;
static_cast<LottieScalar*>(prop)->copy(static_cast<LottieTransform*>(target)->scale, false);
break;
}
case LottieProperty::Type::Float: {
prop = new LottieFloat;
static_cast<LottieFloat*>(prop)->copy(static_cast<LottieTransform*>(target)->rotation, false);
break;
}
case LottieProperty::Type::Opacity: {
prop = new LottieOpacity;
static_cast<LottieOpacity*>(prop)->copy(static_cast<LottieSolid*>(target)->opacity, false);
break;
}
case LottieProperty::Type::Color: {
prop = new LottieColor;
static_cast<LottieColor*>(prop)->copy(static_cast<LottieSolid*>(target)->color, false);
break;
}
case LottieProperty::Type::ColorStop: {
prop = new LottieColorStop;
static_cast<LottieColorStop*>(prop)->copy(static_cast<LottieGradient*>(target)->colorStops, false);
break;
}
case LottieProperty::Type::TextDoc: {
prop = new LottieTextDoc;
static_cast<LottieTextDoc*>(prop)->copy(static_cast<LottieText*>(target)->doc, false);
break;
}
case LottieProperty::Type::Image: {
prop = new LottieBitmap;
static_cast<LottieBitmap*>(prop)->copy(static_cast<LottieImage*>(target)->data, false);
break;
}
default: break;
}
}
return prop;
}
void LottieSlot::apply(LottieProperty* prop, bool byDefault)
{
auto copy = !overridden && !byDefault;
auto shallow = pairs.count == 1 ? true : false;
@ -214,22 +269,22 @@ void LottieSlot::assign(LottieObject* target, bool byDefault)
switch (type) {
case LottieProperty::Type::Float: {
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(prop, shallow, !copy);
break;
}
case LottieProperty::Type::Scalar: {
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(prop, shallow, !copy);
break;
}
case LottieProperty::Type::Vector: {
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(prop, shallow, !copy);
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, shallow, !copy);
pair->obj->override(prop, shallow, !copy);
break;
}
case LottieProperty::Type::Opacity: {
@ -237,27 +292,28 @@ void LottieSlot::assign(LottieObject* target, bool byDefault)
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);
}
pair->obj->override(&static_cast<LottieSolid*>(target)->opacity, shallow, !copy);
pair->obj->override(prop, shallow, !copy);
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, shallow, !copy);
pair->obj->override(prop, shallow, !copy);
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, shallow, !copy);
pair->obj->override(prop, shallow, !copy);
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, shallow, !copy);
pair->obj->override(prop, shallow, !copy);
break;
}
default: break;
}
}
if (!byDefault) overridden = true;
}
@ -733,4 +789,5 @@ LottieComposition::~LottieComposition()
ARRAY_FOREACH(p, fonts) delete(*p);
ARRAY_FOREACH(p, slots) delete(*p);
ARRAY_FOREACH(p, markers) delete(*p);
slotDatas.free();
}

View file

@ -26,6 +26,7 @@
#include "tvgCommon.h"
#include "tvgStr.h"
#include "tvgCompressor.h"
#include "tvgInlist.h"
#include "tvgRender.h"
#include "tvgLottieProperty.h"
#include "tvgLottieRenderPooler.h"
@ -1050,6 +1051,30 @@ struct LottieLayer : LottieGroup
};
struct LottieSlotData
{
INLIST_ITEM(LottieSlotData);
struct SlotData {
char* sid;
LottieProperty* prop;
};
LottieSlotData(uint32_t id) : id(id) {}
~LottieSlotData()
{
ARRAY_FOREACH(p, datas) {
delete(p->prop);
tvg::free(p->sid);
}
}
uint32_t id;
Array<SlotData> datas;
};
struct LottieSlot
{
struct Pair {
@ -1057,7 +1082,8 @@ struct LottieSlot
LottieProperty* prop;
};
void assign(LottieObject* target, bool byDefault);
LottieProperty* data(LottieObject* target);
void apply(LottieProperty* prop, bool byDefault = false);
void reset();
LottieSlot(LottieLayer* layer, LottieObject* parent, char* sid, LottieObject* obj, LottieProperty::Type type) : context{layer, parent}, sid(sid), type(type)
@ -1137,6 +1163,7 @@ struct LottieComposition
Array<LottieFont*> fonts;
Array<LottieSlot*> slots;
Array<LottieMarker*> markers;
Inlist<LottieSlotData> slotDatas;
bool expressions = false;
bool initiated = false;
};

View file

@ -1540,7 +1540,7 @@ const char* LottieParser::sid(bool first)
}
bool LottieParser::apply(LottieSlot* slot, bool byDefault)
LottieProperty* LottieParser::slotData(LottieSlot* slot)
{
enterObject();
@ -1599,14 +1599,13 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault)
if (!obj || Invalid()) {
delete(obj);
return false;
return nullptr;
}
slot->assign(obj, byDefault);
auto prop = slot->data(obj);
delete(obj);
return true;
return prop;
}

View file

@ -37,8 +37,8 @@ public:
}
bool parse();
bool apply(LottieSlot* slot, bool byDefault);
const char* sid(bool first = false);
LottieProperty* slotData(LottieSlot* slot);
void captureSlots(const char* key);
void registerSlot(LottieObject* obj, const char* sid, LottieProperty::Type type);

View file

@ -46,26 +46,33 @@ TEST_CASE("Lottie Slot", "[tvgLottie]")
const char* slotJson = R"({"gradient_fill":{"p":{"p":2,"k":{"a":0,"k":[0,0.1,0.1,0.2,1,1,0.1,0.2,0.1,1]}}}})";
//Slot override before loaded
REQUIRE(animation->override(slotJson) == Result::InsufficientCondition);
//Slot generation before loaded
REQUIRE(animation->genSlot(slotJson) == 0);
//Animation load
REQUIRE(picture->load(TEST_DIR"/lottieslot.json") == Result::Success);
//Slot generation
auto slotId = animation->genSlot(slotJson);
REQUIRE(slotId > 0);
//Slot revert before overriding
REQUIRE(animation->override(nullptr) == Result::Success);
REQUIRE(animation->applySlot(0) == Result::Success);
//Slot override
REQUIRE(animation->override(slotJson) == Result::Success);
REQUIRE(animation->applySlot(slotId) == Result::Success);
//Slot revert
REQUIRE(animation->override(nullptr) == Result::Success);
REQUIRE(animation->applySlot(0) == Result::Success);
//Slot override after reverting
REQUIRE(animation->override(slotJson) == Result::Success);
REQUIRE(animation->applySlot(slotId) == Result::Success);
//Slot override with invalid JSON
REQUIRE(animation->override("") == Result::InvalidArguments);
//Slot generation with invalid JSON
REQUIRE(animation->genSlot("") == 0);
//Slot deletion
REQUIRE(animation->delSlot(slotId) == Result::Success);
REQUIRE(Initializer::term() == Result::Success);
}
@ -84,14 +91,21 @@ TEST_CASE("Lottie Slot 2", "[tvgLottie]")
//Animation load
REQUIRE(picture->load(TEST_DIR"/lottieslotkeyframe.json") == Result::Success);
//Slot generation
auto slotId = animation->genSlot(slotJson);
REQUIRE(slotId > 0);
//Slot override
REQUIRE(animation->override(slotJson) == Result::Success);
REQUIRE(animation->applySlot(slotId) == Result::Success);
//Slot revert
REQUIRE(animation->override(nullptr) == Result::Success);
REQUIRE(animation->applySlot(0) == Result::Success);
//Slot override after reverting
REQUIRE(animation->override(slotJson) == Result::Success);
REQUIRE(animation->applySlot(slotId) == Result::Success);
//Slot deletion
REQUIRE(animation->delSlot(slotId) == Result::Success);
REQUIRE(Initializer::term() == Result::Success);
}