lottie: revise the effect parsing logic

Unify the common parts of the parsing logic
by applying a strategy pattern,
allowing the behavior to vary based on the effect type.

This helps to reduce the size and improved the parsing safety.
This commit is contained in:
Hermet Park 2025-01-25 02:33:20 +09:00
parent 8f7103e109
commit 09ebf10432
3 changed files with 74 additions and 129 deletions

View file

@ -1261,7 +1261,7 @@ void LottieParser::parseMasks(LottieLayer* layer)
}
void LottieParser::parseTint(LottieFxTint* effect)
void LottieParser::parseEffect(LottieEffect* effect, void(LottieParser::*func)(LottieEffect*, int))
{
int idx = 0;
enterArray();
@ -1269,144 +1269,88 @@ void LottieParser::parseTint(LottieFxTint* effect)
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("v")) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) {
if (idx == 0) parsePropertyInternal(effect->black);
else if (idx == 1) parsePropertyInternal(effect->white);
else if (idx == 2) parsePropertyInternal(effect->intensity);
if (peekType() == kObjectType) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) (this->*func)(effect, idx);
else skip(key);
} else skip(key);
}
++idx;
} else skip(key);
}
++idx;
} else skip();
} else skip();
}
}
}
void LottieParser::parseTritone(LottieFxTritone* effect)
void LottieParser::parseTint(LottieEffect* effect, int idx)
{
int idx = 0;
enterArray();
while (nextArrayValue()) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("v")) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) {
if (idx == 0) parsePropertyInternal(effect->bright);
else if (idx == 1) parsePropertyInternal(effect->midtone);
else if (idx == 2) parsePropertyInternal(effect->dark);
else skip(key);
} else skip(key);
}
++idx;
} else skip(key);
}
}
auto tint = static_cast<LottieFxTint*>(effect);
if (idx == 0) parsePropertyInternal(tint->black);
else if (idx == 1) parsePropertyInternal(tint->white);
else if (idx == 2) parsePropertyInternal(tint->intensity);
else skip();
}
void LottieParser::parseFill(LottieFxFill* effect)
void LottieParser::parseTritone(LottieEffect* effect, int idx)
{
int idx = 0;
enterArray();
while (nextArrayValue()) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("v")) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) {
if (idx == 2) parsePropertyInternal(effect->color);
else if (idx == 6) parsePropertyInternal(effect->opacity);
else skip(key);
} else skip(key);
}
++idx;
} else skip(key);
}
}
auto tritone = static_cast<LottieFxTritone*>(effect);
if (idx == 0) parsePropertyInternal(tritone->bright);
else if (idx == 1) parsePropertyInternal(tritone->midtone);
else if (idx == 2) parsePropertyInternal(tritone->dark);
else skip();
}
void LottieParser::parseGaussianBlur(LottieFxGaussianBlur* effect)
void LottieParser::parseFill(LottieEffect* effect, int idx)
{
int idx = 0;
enterArray();
while (nextArrayValue()) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("v")) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) {
if (idx == 0) parsePropertyInternal(effect->blurness);
else if (idx == 1) parsePropertyInternal(effect->direction);
else if (idx == 2) parsePropertyInternal(effect->wrap);
else skip(key);
++idx;
} else skip(key);
}
} else skip(key);
}
}
auto fill = static_cast<LottieFxFill*>(effect);
if (idx == 2) parsePropertyInternal(fill->color);
else if (idx == 6) parsePropertyInternal(fill->opacity);
else skip();
}
void LottieParser::parseDropShadow(LottieFxDropShadow* effect)
void LottieParser::parseGaussianBlur(LottieEffect* effect, int idx)
{
int idx = 0;
enterArray();
while (nextArrayValue()) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("v")) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) {
if (idx == 0) parsePropertyInternal(effect->color);
else if (idx == 1) parsePropertyInternal(effect->opacity);
else if (idx == 2) parsePropertyInternal(effect->angle);
else if (idx == 3) parsePropertyInternal(effect->distance);
else if (idx == 4) parsePropertyInternal(effect->blurness);
else skip(key);
++idx;
} else skip(key);
}
} else skip(key);
}
}
auto blur = static_cast<LottieFxGaussianBlur*>(effect);
if (idx == 0) parsePropertyInternal(blur->blurness);
else if (idx == 1) parsePropertyInternal(blur->direction);
else if (idx == 2) parsePropertyInternal(blur->wrap);
else skip();
}
void LottieParser::parseStroke(LottieFxStroke* effect)
void LottieParser::parseDropShadow(LottieEffect* effect, int idx)
{
int idx = 0;
enterArray();
while (nextArrayValue()) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("v")) {
enterObject();
while (auto key = nextObjectKey()) {
if (KEY_AS("k")) {
if (idx == 0) parsePropertyInternal(effect->mask);
else if (idx == 1) parsePropertyInternal(effect->allMask);
else if (idx == 3) parsePropertyInternal(effect->color);
else if (idx == 4) parsePropertyInternal(effect->size);
else if (idx == 6) parsePropertyInternal(effect->opacity);
else if (idx == 7) parsePropertyInternal(effect->begin);
else if (idx == 8) parsePropertyInternal(effect->end);
else skip(key);
++idx;
} else skip(key);
}
} else skip(key);
}
}
auto shadow = static_cast<LottieFxDropShadow*>(effect);
if (idx == 0) parsePropertyInternal(shadow->color);
else if (idx == 1) parsePropertyInternal(shadow->opacity);
else if (idx == 2) parsePropertyInternal(shadow->angle);
else if (idx == 3) parsePropertyInternal(shadow->distance);
else if (idx == 4) parsePropertyInternal(shadow->blurness);
else skip();
}
void LottieParser::parseStroke(LottieEffect* effect, int idx)
{
auto stroke = static_cast<LottieFxStroke*>(effect);
if (idx == 0) parsePropertyInternal(stroke->mask);
else if (idx == 1) parsePropertyInternal(stroke->allMask);
else if (idx == 3) parsePropertyInternal(stroke->color);
else if (idx == 4) parsePropertyInternal(stroke->size);
else if (idx == 6) parsePropertyInternal(stroke->opacity);
else if (idx == 7) parsePropertyInternal(stroke->begin);
else if (idx == 8) parsePropertyInternal(stroke->end);
else skip();
}
@ -1414,27 +1358,27 @@ void LottieParser::parseEffect(LottieEffect* effect)
{
switch (effect->type) {
case LottieEffect::Tint: {
parseTint(static_cast<LottieFxTint*>(effect));
parseEffect(effect, &LottieParser::parseTint);
break;
}
case LottieEffect::Fill: {
parseFill(static_cast<LottieFxFill*>(effect));
parseEffect(effect, &LottieParser::parseFill);
break;
}
case LottieEffect::Stroke: {
parseStroke(static_cast<LottieFxStroke*>(effect));
parseEffect(effect, &LottieParser::parseStroke);
break;
}
case LottieEffect::Tritone: {
parseTritone(static_cast<LottieFxTritone*>(effect));
parseEffect(effect, &LottieParser::parseTritone);
break;
}
case LottieEffect::DropShadow: {
parseDropShadow(static_cast<LottieFxDropShadow*>(effect));
parseEffect(effect, &LottieParser::parseDropShadow);
break;
}
case LottieEffect::GaussianBlur: {
parseGaussianBlur(static_cast<LottieFxGaussianBlur*>(effect));
parseEffect(effect, &LottieParser::parseGaussianBlur);
break;
}
default: break;

View file

@ -98,12 +98,13 @@ private:
LottieFont* parseFont();
LottieMarker* parseMarker();
void parseStroke(LottieFxStroke* effect);
void parseTritone(LottieFxTritone* effect);
void parseTint(LottieFxTint* effect);
void parseFill(LottieFxFill* effect);
void parseGaussianBlur(LottieFxGaussianBlur* effect);
void parseDropShadow(LottieFxDropShadow* effect);
void parseEffect(LottieEffect* effect, void(LottieParser::*func)(LottieEffect*, int));
void parseStroke(LottieEffect* effect, int idx);
void parseTritone(LottieEffect* effect, int idx);
void parseTint(LottieEffect* effect, int idx);
void parseFill(LottieEffect* effect, int idx);
void parseGaussianBlur(LottieEffect* effect, int idx);
void parseDropShadow(LottieEffect* effect, int idx);
bool parseDirection(LottieShape* shape, const char* key);
bool parseCommon(LottieObject* obj, const char* key);

View file

@ -192,7 +192,7 @@ struct LookaheadParserHandler
void getNull();
bool parseNext();
const char* nextObjectKey();
void skip(const char* key);
void skip(const char* key = nullptr);
void skipOut(int depth);
int peekType();
char* getPos();