mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +00:00
lottie: optimize the internal data
encode the object name with the hash value to save memory and enable fast data comparison.
This commit is contained in:
parent
2cc522d9e9
commit
33883f302d
5 changed files with 44 additions and 48 deletions
|
@ -1264,7 +1264,7 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo, L
|
|||
static void _buildReference(LottieComposition* comp, LottieLayer* layer)
|
||||
{
|
||||
for (auto asset = comp->assets.begin(); asset < comp->assets.end(); ++asset) {
|
||||
if (strcmp(layer->refId, (*asset)->name)) continue;
|
||||
if (layer->rid != (*asset)->id) continue;
|
||||
if (layer->type == LottieLayer::Precomp) {
|
||||
auto assetLayer = static_cast<LottieLayer*>(*asset);
|
||||
if (_buildComposition(comp, assetLayer)) {
|
||||
|
@ -1333,7 +1333,7 @@ static bool _buildComposition(LottieComposition* comp, LottieGroup* parent)
|
|||
auto child = static_cast<LottieLayer*>(*c);
|
||||
|
||||
//attach the precomp layer.
|
||||
if (child->refId) _buildReference(comp, child);
|
||||
if (child->rid) _buildReference(comp, child);
|
||||
|
||||
if (child->matte.type != CompositeMethod::None) {
|
||||
//no index of the matte layer is provided: the layer above is used as the matte source
|
||||
|
@ -1353,7 +1353,7 @@ static bool _buildComposition(LottieComposition* comp, LottieGroup* parent)
|
|||
//parenting
|
||||
_bulidHierarchy(parent, child->matte.target);
|
||||
//precomp referencing
|
||||
if (child->matte.target->refId) _buildReference(comp, child->matte.target);
|
||||
if (child->matte.target->rid) _buildReference(comp, child->matte.target);
|
||||
}
|
||||
_bulidHierarchy(parent, child);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
|
||||
#include "tvgMath.h"
|
||||
#include "tvgCompressor.h"
|
||||
#include "tvgLottieModel.h"
|
||||
#include "tvgLottieExpressions.h"
|
||||
|
||||
|
@ -76,6 +77,15 @@ static char* _name(jerry_value_t args)
|
|||
}
|
||||
|
||||
|
||||
static unsigned long _idByName(jerry_value_t args)
|
||||
{
|
||||
auto name = _name(args);
|
||||
auto id = djb2Encode(name);
|
||||
free(name);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
static jerry_value_t _toComp(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
TVGERR("LOTTIE", "toComp is not supported in expressions!");
|
||||
|
@ -537,11 +547,9 @@ static jerry_value_t _fromCompToSurface(const jerry_call_info_t* info, const jer
|
|||
|
||||
static jerry_value_t _content(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
auto name = _name(args[0]);
|
||||
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
|
||||
auto group = static_cast<LottieGroup*>(data->obj);
|
||||
auto target = group->content((char*)name);
|
||||
free(name);
|
||||
auto target = group->content(_idByName(args[0]));
|
||||
if (!target) return jerry_undefined();
|
||||
|
||||
//find the a path property(sh) in the group layer?
|
||||
|
@ -598,13 +606,11 @@ static jerry_value_t _layer(const jerry_call_info_t* info, const jerry_value_t a
|
|||
//layer index
|
||||
if (jerry_value_is_number(args[0])) {
|
||||
auto idx = (uint16_t)jerry_value_as_int32(args[0]);
|
||||
layer = comp->layer(idx);
|
||||
layer = comp->layerByIdx(idx);
|
||||
jerry_value_free(idx);
|
||||
//layer name
|
||||
} else {
|
||||
auto name = _name(args[0]);
|
||||
layer = comp->layer((char*)name);
|
||||
free(name);
|
||||
layer = comp->layerById(_idByName(args[0]));
|
||||
}
|
||||
|
||||
if (!layer) return jerry_undefined();
|
||||
|
@ -998,17 +1004,7 @@ static void _buildProperty(float frameNo, jerry_value_t context, LottieExpressio
|
|||
static jerry_value_t _comp(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||
{
|
||||
auto comp = static_cast<LottieComposition*>(jerry_object_get_native_ptr(info->function, nullptr));
|
||||
LottieLayer* layer;
|
||||
|
||||
auto arg0 = jerry_value_to_string(args[0]);
|
||||
auto len = jerry_string_length(arg0);
|
||||
auto name = (jerry_char_t*)alloca(len * sizeof(jerry_char_t) + 1);
|
||||
jerry_string_to_buffer(arg0, JERRY_ENCODING_UTF8, name, len);
|
||||
name[len] = '\0';
|
||||
|
||||
jerry_value_free(arg0);
|
||||
|
||||
layer = comp->asset((char*)name);
|
||||
auto layer = comp->asset(_idByName(args[0]));
|
||||
|
||||
if (!layer) return jerry_undefined();
|
||||
|
||||
|
|
|
@ -344,11 +344,8 @@ void LottieGroup::prepare(LottieObject::Type type)
|
|||
|
||||
LottieLayer::~LottieLayer()
|
||||
{
|
||||
if (refId) {
|
||||
//No need to free assets children because the Composition owns them.
|
||||
children.clear();
|
||||
free(refId);
|
||||
}
|
||||
//No need to free assets children because the Composition owns them.
|
||||
if (rid) children.clear();
|
||||
|
||||
for (auto m = masks.begin(); m < masks.end(); ++m) {
|
||||
delete(*m);
|
||||
|
@ -356,6 +353,7 @@ LottieLayer::~LottieLayer()
|
|||
|
||||
matte.target = nullptr;
|
||||
delete(transform);
|
||||
free(name);
|
||||
}
|
||||
|
||||
void LottieLayer::prepare()
|
||||
|
|
|
@ -110,7 +110,6 @@ struct LottieObject
|
|||
|
||||
virtual ~LottieObject()
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
|
||||
virtual void override(LottieProperty* prop)
|
||||
|
@ -120,7 +119,7 @@ struct LottieObject
|
|||
|
||||
virtual bool mergeable() { return false; }
|
||||
|
||||
char* name = nullptr;
|
||||
unsigned long id = 0;
|
||||
Type type;
|
||||
bool hidden = false; //remove?
|
||||
};
|
||||
|
@ -500,16 +499,16 @@ struct LottieGroup : LottieObject
|
|||
void prepare(LottieObject::Type type = LottieObject::Group);
|
||||
bool mergeable() override { return allowMerge; }
|
||||
|
||||
LottieObject* content(const char* id)
|
||||
LottieObject* content(unsigned long id)
|
||||
{
|
||||
if (name && !strcmp(name, id)) return this;
|
||||
if (this->id == id) return this;
|
||||
|
||||
//source has children, find recursively.
|
||||
for (auto c = children.begin(); c < children.end(); ++c) {
|
||||
auto child = *c;
|
||||
if (child->type == LottieObject::Type::Group || child->type == LottieObject::Type::Layer) {
|
||||
if (auto ret = static_cast<LottieGroup*>(child)->content(id)) return ret;
|
||||
} else if (child->name && !strcmp(child->name, id)) return child;
|
||||
} else if (child->id == id) return child;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -547,6 +546,7 @@ struct LottieLayer : LottieGroup
|
|||
LottieLayer* target = nullptr;
|
||||
} matte;
|
||||
|
||||
char* name = nullptr;
|
||||
BlendMethod blendMethod = BlendMethod::Normal;
|
||||
LottieLayer* parent = nullptr;
|
||||
LottieFloat timeRemap = 0.0f;
|
||||
|
@ -560,12 +560,11 @@ struct LottieLayer : LottieGroup
|
|||
float inFrame = 0.0f;
|
||||
float outFrame = 0.0f;
|
||||
float startFrame = 0.0f;
|
||||
char* refId = nullptr; //pre-composition reference.
|
||||
unsigned long rid = 0; //pre-composition reference id.
|
||||
int16_t mid = -1; //id of the matte layer.
|
||||
int16_t pidx = -1; //index of the parent layer.
|
||||
int16_t idx = -1; //index of the current layer.
|
||||
|
||||
//cached data
|
||||
struct {
|
||||
float frameNo = -1.0f;
|
||||
Matrix matrix;
|
||||
|
@ -635,16 +634,16 @@ struct LottieComposition
|
|||
return endFrame - startFrame;
|
||||
}
|
||||
|
||||
LottieLayer* layer(const char* name)
|
||||
LottieLayer* layerById(unsigned long id)
|
||||
{
|
||||
for (auto child = root->children.begin(); child < root->children.end(); ++child) {
|
||||
auto layer = static_cast<LottieLayer*>(*child);
|
||||
if (layer->name && !strcmp(layer->name, name)) return layer;
|
||||
if (layer->id == id) return layer;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LottieLayer* layer(int16_t idx)
|
||||
LottieLayer* layerByIdx(int16_t idx)
|
||||
{
|
||||
for (auto child = root->children.begin(); child < root->children.end(); ++child) {
|
||||
auto layer = static_cast<LottieLayer*>(*child);
|
||||
|
@ -653,11 +652,11 @@ struct LottieComposition
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LottieLayer* asset(const char* name)
|
||||
LottieLayer* asset(unsigned long id)
|
||||
{
|
||||
for (auto asset = assets.begin(); asset < assets.end(); ++asset) {
|
||||
auto layer = static_cast<LottieLayer*>(*asset);
|
||||
if (layer->name && !strcmp(layer->name, name)) return layer;
|
||||
if (layer->id == id) return layer;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -51,11 +51,11 @@ static LottieExpression* _expression(char* code, LottieComposition* comp, Lottie
|
|||
}
|
||||
|
||||
|
||||
static char* _int2str(int num)
|
||||
static unsigned long _int2str(int num)
|
||||
{
|
||||
char str[20];
|
||||
snprintf(str, 20, "%d", num);
|
||||
return strdup(str);
|
||||
return djb2Encode(str);
|
||||
}
|
||||
|
||||
|
||||
|
@ -515,7 +515,7 @@ void LottieParser::parseProperty(T& prop, LottieObject* obj)
|
|||
bool LottieParser::parseCommon(LottieObject* obj, const char* key)
|
||||
{
|
||||
if (KEY_AS("nm")) {
|
||||
obj->name = getStringCopy();
|
||||
obj->id = djb2Encode(getString());
|
||||
return true;
|
||||
} else if (KEY_AS("hd")) {
|
||||
obj->hidden = getBool();
|
||||
|
@ -921,7 +921,7 @@ LottieObject* LottieParser::parseAsset()
|
|||
enterObject();
|
||||
|
||||
LottieObject* obj = nullptr;
|
||||
char *id = nullptr;
|
||||
unsigned long id = 0;
|
||||
|
||||
//Used for Image Asset
|
||||
const char* data = nullptr;
|
||||
|
@ -932,7 +932,7 @@ LottieObject* LottieParser::parseAsset()
|
|||
if (KEY_AS("id"))
|
||||
{
|
||||
if (peekType() == kStringType) {
|
||||
id = getStringCopy();
|
||||
id = djb2Encode(getString());
|
||||
} else {
|
||||
id = _int2str(getInt());
|
||||
}
|
||||
|
@ -944,8 +944,7 @@ LottieObject* LottieParser::parseAsset()
|
|||
else skip(key);
|
||||
}
|
||||
if (data) obj = parseImage(data, subPath, embedded);
|
||||
if (obj) obj->name = id;
|
||||
else free(id);
|
||||
if (obj) obj->id = id;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -1192,10 +1191,14 @@ LottieLayer* LottieParser::parseLayer()
|
|||
enterObject();
|
||||
|
||||
while (auto key = nextObjectKey()) {
|
||||
if (KEY_AS("ddd")) ddd = getInt(); //3d layer
|
||||
if (KEY_AS("nm"))
|
||||
{
|
||||
layer->name = getStringCopy();
|
||||
layer->id = djb2Encode(layer->name);
|
||||
}
|
||||
else if (KEY_AS("ddd")) ddd = getInt(); //3d layer
|
||||
else if (KEY_AS("ind")) layer->idx = getInt();
|
||||
else if (KEY_AS("ty")) layer->type = (LottieLayer::Type) getInt();
|
||||
else if (KEY_AS("nm")) layer->name = getStringCopy();
|
||||
else if (KEY_AS("sr")) layer->timeStretch = getFloat();
|
||||
else if (KEY_AS("ks"))
|
||||
{
|
||||
|
@ -1217,7 +1220,7 @@ LottieLayer* LottieParser::parseLayer()
|
|||
else if (KEY_AS("tp")) layer->mid = getInt();
|
||||
else if (KEY_AS("masksProperties")) parseMasks(layer);
|
||||
else if (KEY_AS("hd")) layer->hidden = getBool();
|
||||
else if (KEY_AS("refId")) layer->refId = getStringCopy();
|
||||
else if (KEY_AS("refId")) layer->rid = djb2Encode(getString());
|
||||
else if (KEY_AS("td")) layer->matteSrc = getInt(); //used for matte layer
|
||||
else if (KEY_AS("t")) parseText(layer->children);
|
||||
else if (KEY_AS("ef"))
|
||||
|
|
Loading…
Add table
Reference in a new issue