lottie: Fixed a font/glyph parsing error.

Previously, the Lottie parser expected a specific parsing order:
font followed by glyph, for optimal data processing.

However, since this order is not guaranteed,
we have revised the parsing logic to accommodate any order.
This commit is contained in:
Hermet Park 2024-01-29 14:36:58 +09:00 committed by Hermet Park
parent e7a1e6e43c
commit 5d02b3ac42
3 changed files with 32 additions and 18 deletions

View file

@ -241,6 +241,8 @@ struct LottieGlyph
Array<LottieObject*> children; //glyph shapes. Array<LottieObject*> children; //glyph shapes.
float width; float width;
char* code; char* code;
char* family = nullptr;
char* style = nullptr;
uint16_t size; uint16_t size;
uint8_t len; uint8_t len;

View file

@ -956,26 +956,19 @@ void LottieParser::parseAssets()
} }
void LottieParser::parseChars() void LottieParser::parseChars(Array<LottieGlyph*>& glyphes)
{ {
if (comp->fonts.count == 0) {
TVGERR("LOTTIE", "No font data?");
return;
}
enterArray(); enterArray();
while (nextArrayValue()) { while (nextArrayValue()) {
enterObject(); enterObject();
//a new glyph //a new glyph
auto glyph = new LottieGlyph; auto glyph = new LottieGlyph;
char* style = nullptr;
char* family = nullptr;
while (auto key = nextObjectKey()) { while (auto key = nextObjectKey()) {
if (!strcmp("ch", key)) glyph->code = getStringCopy(); if (!strcmp("ch", key)) glyph->code = getStringCopy();
else if (!strcmp("size", key)) glyph->size = static_cast<uint16_t>(getFloat()); else if (!strcmp("size", key)) glyph->size = static_cast<uint16_t>(getFloat());
else if (!strcmp("style", key)) style = const_cast<char*>(getString()); else if (!strcmp("style", key)) glyph->style = getStringCopy();
else if (!strcmp("w", key)) glyph->width = getFloat(); else if (!strcmp("w", key)) glyph->width = getFloat();
else if (!strcmp("fFamily", key)) family = const_cast<char*>(getString()); else if (!strcmp("fFamily", key)) glyph->family = getStringCopy();
else if (!strcmp("data", key)) else if (!strcmp("data", key))
{ //glyph shapes { //glyph shapes
enterObject(); enterObject();
@ -984,13 +977,8 @@ void LottieParser::parseChars()
} }
} else skip(key); } else skip(key);
} }
//aggregate the font characters
for (uint32_t i = 0; i < comp->fonts.count; ++i) {
auto& font = comp->fonts[i];
if (!strcmp(font->family, family) && !strcmp(font->style, style)) font->chars.push(glyph);
else TVGERR("LOTTIE", "No font data?");
}
glyph->prepare(); glyph->prepare();
glyphes.push(glyph);
} }
} }
@ -1240,6 +1228,24 @@ LottieLayer* LottieParser::parseLayers()
} }
void LottieParser::postProcess(Array<LottieGlyph*>& glyphes)
{
//aggregate font characters
for (uint32_t g = 0; g < glyphes.count; ++g) {
auto glyph = glyphes[g];
for (uint32_t i = 0; i < comp->fonts.count; ++i) {
auto& font = comp->fonts[i];
if (!strcmp(font->family, glyph->family) && !strcmp(font->style, glyph->style)) {
font->chars.push(glyph);
free(glyph->family);
free(glyph->style);
break;
}
}
}
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
@ -1255,6 +1261,8 @@ bool LottieParser::parse()
comp = new LottieComposition; comp = new LottieComposition;
if (!comp) return false; if (!comp) return false;
Array<LottieGlyph*> glyphes;
//assign parsing context //assign parsing context
LottieParser::Context context; LottieParser::Context context;
this->context = &context; this->context = &context;
@ -1270,7 +1278,7 @@ bool LottieParser::parse()
else if (!strcmp(key, "assets")) parseAssets(); else if (!strcmp(key, "assets")) parseAssets();
else if (!strcmp(key, "layers")) comp->root = parseLayers(); else if (!strcmp(key, "layers")) comp->root = parseLayers();
else if (!strcmp(key, "fonts")) parseFonts(); else if (!strcmp(key, "fonts")) parseFonts();
else if (!strcmp(key, "chars")) parseChars(); else if (!strcmp(key, "chars")) parseChars(glyphes);
else skip(key); else skip(key);
} }
@ -1278,5 +1286,8 @@ bool LottieParser::parse()
comp->root->inFrame = comp->startFrame; comp->root->inFrame = comp->startFrame;
comp->root->outFrame = comp->endFrame; comp->root->outFrame = comp->endFrame;
postProcess(glyphes);
return true; return true;
} }

View file

@ -99,7 +99,8 @@ private:
void parseTextRange(LottieText* text); void parseTextRange(LottieText* text);
void parseAssets(); void parseAssets();
void parseFonts(); void parseFonts();
void parseChars(); void parseChars(Array<LottieGlyph*>& glyphes);
void postProcess(Array<LottieGlyph*>& glyphes);
//Current parsing context //Current parsing context
struct Context { struct Context {