lottie: ++parser stability

fixed a parsing failure that occurred
when a desired single value was presented as part of an array.

issue: https://github.com/thorvg/thorvg/issues/2975
This commit is contained in:
Hermet Park 2024-11-27 16:44:43 +09:00
parent 14d66198d1
commit a233ae09da
2 changed files with 56 additions and 49 deletions

View file

@ -156,7 +156,7 @@ StrokeJoin LottieParser::getStrokeJoin()
} }
void LottieParser::getValue(TextDocument& doc) bool LottieParser::getValue(TextDocument& doc)
{ {
enterObject(); enterObject();
while (auto key = nextObjectKey()) { while (auto key = nextObjectKey()) {
@ -175,10 +175,11 @@ void LottieParser::getValue(TextDocument& doc)
else if (KEY_AS("of")) doc.stroke.render = getBool(); else if (KEY_AS("of")) doc.stroke.render = getBool();
else skip(key); else skip(key);
} }
return false;
} }
void LottieParser::getValue(PathSet& path) bool LottieParser::getValue(PathSet& path)
{ {
Array<Point> outs, ins, pts; Array<Point> outs, ins, pts;
bool closed = false; bool closed = false;
@ -201,8 +202,8 @@ void LottieParser::getValue(PathSet& path)
if (arrayWrapper) nextArrayValue(); if (arrayWrapper) nextArrayValue();
//valid path data? //valid path data?
if (ins.empty() || outs.empty() || pts.empty()) return; if (ins.empty() || outs.empty() || pts.empty()) return false;
if (ins.count != outs.count || outs.count != pts.count) return; if (ins.count != outs.count || outs.count != pts.count) return false;
//convert path //convert path
auto out = outs.begin(); auto out = outs.begin();
@ -248,21 +249,29 @@ void LottieParser::getValue(PathSet& path)
outPts.data = nullptr; outPts.data = nullptr;
outCmds.data = nullptr; outCmds.data = nullptr;
return false;
} }
void LottieParser::getValue(ColorStop& color) bool LottieParser::getValue(ColorStop& color)
{ {
if (peekType() == kArrayType) enterArray(); if (peekType() == kArrayType) {
enterArray();
if (!nextArrayValue()) return true;
}
if (!color.input) color.input = new Array<float>(static_cast<LottieGradient*>(context.parent)->colorStops.count * 6); if (!color.input) color.input = new Array<float>(static_cast<LottieGradient*>(context.parent)->colorStops.count * 6);
else color.input->clear(); else color.input->clear();
while (nextArrayValue()) color.input->push(getFloat()); do color.input->push(getFloat());
while (nextArrayValue());
return true;
} }
void LottieParser::getValue(Array<Point>& pts) bool LottieParser::getValue(Array<Point>& pts)
{ {
enterArray(); enterArray();
while (nextArrayValue()) { while (nextArrayValue()) {
@ -271,10 +280,11 @@ void LottieParser::getValue(Array<Point>& pts)
getValue(pt); getValue(pt);
pts.push(pt); pts.push(pt);
} }
return false;
} }
void LottieParser::getValue(int8_t& val) bool LottieParser::getValue(int8_t& val)
{ {
if (peekType() == kArrayType) { if (peekType() == kArrayType) {
enterArray(); enterArray();
@ -282,12 +292,13 @@ void LottieParser::getValue(int8_t& val)
//discard rest //discard rest
while (nextArrayValue()) getInt(); while (nextArrayValue()) getInt();
} else { } else {
val = (int8_t)getFloat(); val = (int8_t) getFloat();
} }
return false;
} }
void LottieParser::getValue(uint8_t& val) bool LottieParser::getValue(uint8_t& val)
{ {
if (peekType() == kArrayType) { if (peekType() == kArrayType) {
enterArray(); enterArray();
@ -297,10 +308,11 @@ void LottieParser::getValue(uint8_t& val)
} else { } else {
val = (uint8_t)(getFloat() * 2.55f); val = (uint8_t)(getFloat() * 2.55f);
} }
return false;
} }
void LottieParser::getValue(float& val) bool LottieParser::getValue(float& val)
{ {
if (peekType() == kArrayType) { if (peekType() == kArrayType) {
enterArray(); enterArray();
@ -310,40 +322,43 @@ void LottieParser::getValue(float& val)
} else { } else {
val = getFloat(); val = getFloat();
} }
return false;
} }
bool LottieParser::getValue(Point& pt) bool LottieParser::getValue(Point& pt)
{ {
auto type = peekType(); if (peekType() == kNullType) return false;
if (type == kNullType) return false; if (peekType() == kArrayType) {
enterArray();
int i = 0; if (!nextArrayValue()) return false;
auto ptr = (float*)(&pt);
if (type == kArrayType) enterArray();
while (nextArrayValue()) {
auto val = getFloat();
if (i < 2) ptr[i++] = val;
} }
pt.x = getFloat();
pt.y = getFloat();
while (nextArrayValue()) getFloat(); //drop
return true; return true;
} }
void LottieParser::getValue(RGB24& color) bool LottieParser::getValue(RGB24& color)
{ {
int i = 0; if (peekType() == kArrayType) {
enterArray();
if (peekType() == kArrayType) enterArray(); if (!nextArrayValue()) return false;
while (nextArrayValue()) {
auto val = getFloat();
if (i < 3) color.rgb[i++] = REMAP255(val);
} }
color.rgb[0] = REMAP255(getFloat());
color.rgb[1] = REMAP255(getFloat());
color.rgb[2] = REMAP255(getFloat());
while (nextArrayValue()) getFloat(); //drop
//TODO: color filter? //TODO: color filter?
return true;
} }
@ -468,18 +483,10 @@ void LottieParser::parsePropertyInternal(T& prop)
getValue(prop.value); getValue(prop.value);
//multi value property //multi value property
} else { } else {
//TODO: Here might be a single frame.
//Can we figure out the frame number in advance?
enterArray(); enterArray();
while (nextArrayValue()) { while (nextArrayValue()) {
//keyframes value if (peekType() == kObjectType) parseKeyFrame(prop); //keyframes value
if (peekType() == kObjectType) { else if (getValue(prop.value)) break; //multi value property with no keyframes
parseKeyFrame(prop);
//multi value property with no keyframes
} else {
getValue(prop.value);
break;
}
} }
prop.prepare(); prop.prepare();
} }

View file

@ -58,14 +58,14 @@ private:
void getInterpolatorPoint(Point& pt); void getInterpolatorPoint(Point& pt);
void getPathSet(LottiePathSet& path); void getPathSet(LottiePathSet& path);
void getLayerSize(float& val); void getLayerSize(float& val);
void getValue(TextDocument& doc); bool getValue(TextDocument& doc);
void getValue(PathSet& path); bool getValue(PathSet& path);
void getValue(Array<Point>& pts); bool getValue(Array<Point>& pts);
void getValue(ColorStop& color); bool getValue(ColorStop& color);
void getValue(float& val); bool getValue(float& val);
void getValue(uint8_t& val); bool getValue(uint8_t& val);
void getValue(int8_t& val); bool getValue(int8_t& val);
void getValue(RGB24& color); bool getValue(RGB24& color);
bool getValue(Point& pt); bool getValue(Point& pt);
template<typename T> bool parseTangent(const char *key, LottieVectorFrame<T>& value); template<typename T> bool parseTangent(const char *key, LottieVectorFrame<T>& value);