From a9cd630dfd46f8bff38b81526b2909431d794d6c Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 1 Apr 2025 19:32:05 +0900 Subject: [PATCH] lottie: code refactoring - aligned the property types with the class types. - removed tempaltes, since property types are deterministic. --- src/loaders/lottie/tvgLottieExpressions.cpp | 40 ++-- src/loaders/lottie/tvgLottieLoader.cpp | 4 +- src/loaders/lottie/tvgLottieModel.cpp | 24 +-- src/loaders/lottie/tvgLottieModel.h | 20 +- src/loaders/lottie/tvgLottieParser.cpp | 197 ++++++++++---------- src/loaders/lottie/tvgLottieParser.h | 6 +- src/loaders/lottie/tvgLottieProperty.h | 42 +++-- 7 files changed, 167 insertions(+), 166 deletions(-) diff --git a/src/loaders/lottie/tvgLottieExpressions.cpp b/src/loaders/lottie/tvgLottieExpressions.cpp index 04b67d5e..9870f69d 100644 --- a/src/loaders/lottie/tvgLottieExpressions.cpp +++ b/src/loaders/lottie/tvgLottieExpressions.cpp @@ -139,22 +139,22 @@ static jerry_value_t _toComp(const jerry_call_info_t* info, const jerry_value_t static jerry_value_t _value(float frameNo, LottieProperty* property) { switch (property->type) { - case LottieProperty::Type::Point: { - return _point2d((*static_cast(property))(frameNo)); - } case LottieProperty::Type::Float: { return jerry_number((*static_cast(property))(frameNo)); } - case LottieProperty::Type::Opacity: { - return jerry_number((*static_cast(property))(frameNo)); + case LottieProperty::Type::Scalar: { + return _point2d((*static_cast(property))(frameNo)); + } + case LottieProperty::Type::Vector: { + return _point2d((*static_cast(property))(frameNo)); } case LottieProperty::Type::PathSet: { auto value = jerry_object(); jerry_object_set_native_ptr(value, nullptr, property); return value; } - case LottieProperty::Type::Position: { - return _point2d((*static_cast(property))(frameNo)); + case LottieProperty::Type::Opacity: { + return jerry_number((*static_cast(property))(frameNo)); } default: { TVGERR("LOTTIE", "Non supported type for value? = %d", (int) property->type); @@ -668,21 +668,21 @@ static jerry_value_t _velocityAtTime(const jerry_call_info_t* info, const jerry_ //compute the velocity switch (exp->property->type) { - case LottieProperty::Type::Point: { - auto prv = (*static_cast(exp->property))(pframe); - auto cur = (*static_cast(exp->property))(cframe); - return _velocity(prv, cur, elapsed); - } - case LottieProperty::Type::Position: { - auto prv = (*static_cast(exp->property))(pframe); - auto cur = (*static_cast(exp->property))(cframe); - return _velocity(prv, cur, elapsed); - } case LottieProperty::Type::Float: { auto prv = (*static_cast(exp->property))(pframe); auto cur = (*static_cast(exp->property))(cframe); return jerry_number((cur - prv) / elapsed); } + case LottieProperty::Type::Scalar: { + auto prv = (*static_cast(exp->property))(pframe); + auto cur = (*static_cast(exp->property))(cframe); + return _velocity(prv, cur, elapsed); + } + case LottieProperty::Type::Vector: { + auto prv = (*static_cast(exp->property))(pframe); + auto cur = (*static_cast(exp->property))(cframe); + return _velocity(prv, cur, elapsed); + } default: TVGLOG("LOTTIE", "Non supported type for velocityAtTime?"); } return jerry_undefined(); @@ -700,12 +700,12 @@ static jerry_value_t _speedAtTime(const jerry_call_info_t* info, const jerry_val //compute the velocity switch (exp->property->type) { - case LottieProperty::Type::Point: { + case LottieProperty::Type::Scalar: { prv = (*static_cast(exp->property))(pframe); cur = (*static_cast(exp->property))(cframe); break; } - case LottieProperty::Type::Position: { + case LottieProperty::Type::Vector: { prv = (*static_cast(exp->property))(pframe); cur = (*static_cast(exp->property))(cframe); break; @@ -891,7 +891,7 @@ static jerry_value_t _key(const jerry_call_info_t* info, const jerry_value_t arg //direct access, key[0], key[1] if (exp->property->type == LottieProperty::Type::Float) { jerry_object_set_index(obj, 0, value); - } else if (exp->property->type == LottieProperty::Type::Point || exp->property->type == LottieProperty::Type::Position) { + } else if (exp->property->type == LottieProperty::Type::Scalar || exp->property->type == LottieProperty::Type::Vector) { jerry_object_set_index(obj, 0, jerry_object_get_index(value, 0)); jerry_object_set_index(obj, 1, jerry_object_get_index(value, 1)); } diff --git a/src/loaders/lottie/tvgLottieLoader.cpp b/src/loaders/lottie/tvgLottieLoader.cpp index 1138cef7..f56f61d8 100644 --- a/src/loaders/lottie/tvgLottieLoader.cpp +++ b/src/loaders/lottie/tvgLottieLoader.cpp @@ -319,9 +319,7 @@ bool LottieLoader::override(const char* slots, bool byDefault) return rebuild; //reset slots } else if (overridden) { - ARRAY_FOREACH(p, comp->slots) { - (*p)->reset(); - } + ARRAY_FOREACH(p, comp->slots) (*p)->reset(); overridden = false; rebuild = true; } diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 7212ff9e..b1a817a5 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -182,19 +182,24 @@ void LottieSlot::assign(LottieObject* target, bool byDefault) ARRAY_FOREACH(pair, pairs) { //backup the original properties before overwriting switch (type) { - case LottieProperty::Type::Position: { - if (copy) pair->prop = new LottieVector(static_cast(pair->obj)->position); - pair->obj->override(&static_cast(target)->position, shallow, !copy); + case LottieProperty::Type::Float: { + if (copy) pair->prop = new LottieFloat(static_cast(pair->obj)->rotation); + pair->obj->override(&static_cast(target)->rotation, shallow, !copy); break; } - case LottieProperty::Type::Point: { + case LottieProperty::Type::Scalar: { if (copy) pair->prop = new LottieScalar(static_cast(pair->obj)->scale); pair->obj->override(&static_cast(target)->scale, shallow, !copy); break; } - case LottieProperty::Type::Float: { - if (copy) pair->prop = new LottieFloat(static_cast(pair->obj)->rotation); - pair->obj->override(&static_cast(target)->rotation, shallow, !copy); + case LottieProperty::Type::Vector: { + if (copy) pair->prop = new LottieVector(static_cast(pair->obj)->position); + pair->obj->override(&static_cast(target)->position, shallow, !copy); + break; + } + case LottieProperty::Type::Color: { + if (copy) pair->prop = new LottieColor(static_cast(pair->obj)->color); + pair->obj->override(&static_cast(target)->color, shallow, !copy); break; } case LottieProperty::Type::Opacity: { @@ -205,11 +210,6 @@ void LottieSlot::assign(LottieObject* target, bool byDefault) pair->obj->override(&static_cast(target)->opacity, shallow, !copy); break; } - case LottieProperty::Type::Color: { - if (copy) pair->prop = new LottieColor(static_cast(pair->obj)->color); - pair->obj->override(&static_cast(target)->color, shallow, !copy); - break; - } case LottieProperty::Type::ColorStop: { if (copy) pair->prop = new LottieColorStop(static_cast(pair->obj)->colorStops); pair->obj->override(&static_cast(target)->colorStops, shallow, !copy); diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 92708f96..d925916d 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -591,21 +591,21 @@ struct LottieTransform : LottieObject void override(LottieProperty* prop, bool shallow, bool release) override { switch (prop->type) { - case LottieProperty::Type::Position: { - if (release) position.release(); - position.copy(*static_cast(prop), shallow); - break; - } case LottieProperty::Type::Float: { if (release) rotation.release(); rotation.copy(*static_cast(prop), shallow); break; } - case LottieProperty::Type::Point: { + case LottieProperty::Type::Scalar: { if (release) scale.release(); scale.copy(*static_cast(prop), shallow); break; } + case LottieProperty::Type::Vector: { + if (release) position.release(); + position.copy(*static_cast(prop), shallow); + break; + } case LottieProperty::Type::Opacity: { if (release) opacity.release(); opacity.copy(*static_cast(prop), shallow); @@ -676,12 +676,12 @@ struct LottieSolidFill : LottieSolid void override(LottieProperty* prop, bool shallow, bool release) override { - if (prop->type == LottieProperty::Type::Opacity) { - if (release) opacity.release(); - opacity.copy(*static_cast(prop), shallow); - } else if (prop->type == LottieProperty::Type::Color) { + if (prop->type == LottieProperty::Type::Color) { if (release) color.release(); color.copy(*static_cast(prop), shallow); + } else if (prop->type == LottieProperty::Type::Opacity) { + if (release) opacity.release(); + opacity.copy(*static_cast(prop), shallow); } } diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 4c61331e..7d4fbbb5 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -341,11 +341,11 @@ void LottieParser::getInterpolatorPoint(Point& pt) } -template +template void LottieParser::parseSlotProperty(T& prop) { while (auto key = nextObjectKey()) { - if (KEY_AS("p")) parseProperty(prop); + if (KEY_AS("p")) parseProperty(prop); else skip(); } } @@ -462,8 +462,7 @@ void LottieParser::parsePropertyInternal(T& prop) } -template -void LottieParser::registerSlot(LottieObject* obj, const char* sid) +void LottieParser::registerSlot(LottieObject* obj, const char* sid, LottieProperty::Type type) { //append object if the slot already exists. ARRAY_FOREACH(p, comp->slots) { @@ -475,18 +474,17 @@ void LottieParser::registerSlot(LottieObject* obj, const char* sid) } -template +template void LottieParser::parseProperty(T& prop, LottieObject* obj) { enterObject(); while (auto key = nextObjectKey()) { if (KEY_AS("k")) parsePropertyInternal(prop); - else if (obj && KEY_AS("sid")) registerSlot(obj, getString()); + else if (obj && KEY_AS("sid")) registerSlot(obj, getString(), prop.type); else if (KEY_AS("x") && expressions) prop.exp = getExpression(getStringCopy(), comp, context.layer, context.parent, &prop); else if (KEY_AS("ix")) prop.ix = getInt(); else skip(); } - prop.type = type; } @@ -522,9 +520,9 @@ LottieRect* LottieParser::parseRect() while (auto key = nextObjectKey()) { if (parseCommon(rect, key)) continue; - else if (KEY_AS("s")) parseProperty(rect->size); - else if (KEY_AS("p")) parseProperty(rect->position); - else if (KEY_AS("r")) parseProperty(rect->radius); + else if (KEY_AS("s")) parseProperty(rect->size); + else if (KEY_AS("p")) parseProperty(rect->position); + else if (KEY_AS("r")) parseProperty(rect->radius); else if (parseDirection(rect, key)) continue; else skip(); } @@ -540,8 +538,8 @@ LottieEllipse* LottieParser::parseEllipse() while (auto key = nextObjectKey()) { if (parseCommon(ellipse, key)) continue; - else if (KEY_AS("p")) parseProperty(ellipse->position); - else if (KEY_AS("s")) parseProperty(ellipse->size); + else if (KEY_AS("p")) parseProperty(ellipse->position); + else if (KEY_AS("s")) parseProperty(ellipse->size); else if (parseDirection(ellipse, key)) continue; else skip(); } @@ -569,24 +567,23 @@ LottieTransform* LottieParser::parseTransform(bool ddd) if (KEY_AS("k")) parsePropertyInternal(transform->position); else if (KEY_AS("s") && getBool()) transform->coords = new LottieTransform::SeparateCoord; //check separateCoord to figure out whether "x(expression)" / "x(coord)" - else if (transform->coords && KEY_AS("x")) parseProperty(transform->coords->x); - else if (transform->coords && KEY_AS("y")) parseProperty(transform->coords->y); + else if (transform->coords && KEY_AS("x")) parseProperty(transform->coords->x); + else if (transform->coords && KEY_AS("y")) parseProperty(transform->coords->y); else if (KEY_AS("x") && expressions) transform->position.exp = getExpression(getStringCopy(), comp, context.layer, context.parent, &transform->position); - else if (KEY_AS("sid")) registerSlot(transform, getString()); + else if (KEY_AS("sid")) registerSlot(transform, getString(), LottieProperty::Type::Vector); else if (KEY_AS("ix")) transform->position.ix = getInt(); else skip(); } - transform->position.type = LottieProperty::Type::Position; } - else if (KEY_AS("a")) parseProperty(transform->anchor); - else if (KEY_AS("s")) parseProperty(transform->scale, transform); - else if (KEY_AS("r")) parseProperty(transform->rotation, transform); - else if (KEY_AS("o")) parseProperty(transform->opacity, transform); - else if (transform->rotationEx && KEY_AS("rx")) parseProperty(transform->rotationEx->x); - else if (transform->rotationEx && KEY_AS("ry")) parseProperty(transform->rotationEx->y); - else if (transform->rotationEx && KEY_AS("rz")) parseProperty(transform->rotation); - else if (KEY_AS("sk")) parseProperty(transform->skewAngle); - else if (KEY_AS("sa")) parseProperty(transform->skewAxis); + else if (KEY_AS("a")) parseProperty(transform->anchor); + else if (KEY_AS("s")) parseProperty(transform->scale, transform); + else if (KEY_AS("r")) parseProperty(transform->rotation, transform); + else if (KEY_AS("o")) parseProperty(transform->opacity, transform); + else if (transform->rotationEx && KEY_AS("rx")) parseProperty(transform->rotationEx->x); + else if (transform->rotationEx && KEY_AS("ry")) parseProperty(transform->rotationEx->y); + else if (transform->rotationEx && KEY_AS("rz")) parseProperty(transform->rotation); + else if (KEY_AS("sk")) parseProperty(transform->skewAngle); + else if (KEY_AS("sa")) parseProperty(transform->skewAxis); else skip(); } return transform; @@ -601,8 +598,8 @@ LottieSolidFill* LottieParser::parseSolidFill() while (auto key = nextObjectKey()) { if (parseCommon(fill, key)) continue; - else if (KEY_AS("c")) parseProperty(fill->color, fill); - else if (KEY_AS("o")) parseProperty(fill->opacity, fill); + else if (KEY_AS("c")) parseProperty(fill->color, fill); + else if (KEY_AS("o")) parseProperty(fill->opacity, fill); else if (KEY_AS("fillEnabled")) fill->hidden |= !getBool(); else if (KEY_AS("r")) fill->rule = (getInt() == 1) ? FillRule::NonZero : FillRule::EvenOdd; else skip(); @@ -620,8 +617,8 @@ void LottieParser::parseStrokeDash(LottieStroke* stroke) while (auto key = nextObjectKey()) { if (KEY_AS("n")) style = getString(); else if (KEY_AS("v")) { - if (style && !strcmp("o", style)) parseProperty(stroke->dashOffset()); - else parseProperty(stroke->dashValue()); + if (style && !strcmp("o", style)) parseProperty(stroke->dashOffset()); + else parseProperty(stroke->dashValue()); } else skip(); } } @@ -636,9 +633,9 @@ LottieSolidStroke* LottieParser::parseSolidStroke() while (auto key = nextObjectKey()) { if (parseCommon(stroke, key)) continue; - else if (KEY_AS("c")) parseProperty(stroke->color, stroke); - else if (KEY_AS("o")) parseProperty(stroke->opacity, stroke); - else if (KEY_AS("w")) parseProperty(stroke->width, stroke); + else if (KEY_AS("c")) parseProperty(stroke->color, stroke); + else if (KEY_AS("o")) parseProperty(stroke->opacity, stroke); + else if (KEY_AS("w")) parseProperty(stroke->width, stroke); else if (KEY_AS("lc")) stroke->cap = (StrokeCap) getInt(); else if (KEY_AS("lj")) stroke->join = (StrokeJoin) getInt(); else if (KEY_AS("ml")) stroke->miterLimit = getFloat(); @@ -691,13 +688,13 @@ LottiePolyStar* LottieParser::parsePolyStar() while (auto key = nextObjectKey()) { if (parseCommon(star, key)) continue; - else if (KEY_AS("p")) parseProperty(star->position); - else if (KEY_AS("pt")) parseProperty(star->ptsCnt); - else if (KEY_AS("ir")) parseProperty(star->innerRadius); - else if (KEY_AS("is")) parseProperty(star->innerRoundness); - else if (KEY_AS("or")) parseProperty(star->outerRadius); - else if (KEY_AS("os")) parseProperty(star->outerRoundness); - else if (KEY_AS("r")) parseProperty(star->rotation); + else if (KEY_AS("p")) parseProperty(star->position); + else if (KEY_AS("pt")) parseProperty(star->ptsCnt); + else if (KEY_AS("ir")) parseProperty(star->innerRadius); + else if (KEY_AS("is")) parseProperty(star->innerRoundness); + else if (KEY_AS("or")) parseProperty(star->outerRadius); + else if (KEY_AS("os")) parseProperty(star->outerRoundness); + else if (KEY_AS("r")) parseProperty(star->rotation); else if (KEY_AS("sy")) star->type = (LottiePolyStar::Type) getInt(); else if (parseDirection(star, key)) continue; else skip(); @@ -714,7 +711,7 @@ LottieRoundedCorner* LottieParser::parseRoundedCorner() while (auto key = nextObjectKey()) { if (parseCommon(corner, key)) continue; - else if (KEY_AS("r")) parseProperty(corner->radius); + else if (KEY_AS("r")) parseProperty(corner->radius); else skip(); } return corner; @@ -726,8 +723,8 @@ void LottieParser::parseColorStop(LottieGradient* gradient) enterObject(); while (auto key = nextObjectKey()) { if (KEY_AS("p")) gradient->colorStops.count = getInt(); - else if (KEY_AS("k")) parseProperty(gradient->colorStops, gradient); - else if (KEY_AS("sid")) registerSlot(gradient, getString()); + else if (KEY_AS("k")) parseProperty(gradient->colorStops, gradient); + else if (KEY_AS("sid")) registerSlot(gradient, getString(), LottieProperty::Type::ColorStop); else skip(); } } @@ -736,12 +733,12 @@ void LottieParser::parseColorStop(LottieGradient* gradient) void LottieParser::parseGradient(LottieGradient* gradient, const char* key) { if (KEY_AS("t")) gradient->id = getInt(); - else if (KEY_AS("o")) parseProperty(gradient->opacity, gradient); + else if (KEY_AS("o")) parseProperty(gradient->opacity, gradient); else if (KEY_AS("g")) parseColorStop(gradient); - else if (KEY_AS("s")) parseProperty(gradient->start, gradient); - else if (KEY_AS("e")) parseProperty(gradient->end, gradient); - else if (KEY_AS("h")) parseProperty(gradient->height, gradient); - else if (KEY_AS("a")) parseProperty(gradient->angle, gradient); + else if (KEY_AS("s")) parseProperty(gradient->start, gradient); + else if (KEY_AS("e")) parseProperty(gradient->end, gradient); + else if (KEY_AS("h")) parseProperty(gradient->height, gradient); + else if (KEY_AS("a")) parseProperty(gradient->angle, gradient); else skip(); } @@ -775,7 +772,7 @@ LottieGradientStroke* LottieParser::parseGradientStroke() else if (KEY_AS("lc")) stroke->cap = (StrokeCap) getInt(); else if (KEY_AS("lj")) stroke->join = (StrokeJoin) getInt(); else if (KEY_AS("ml")) stroke->miterLimit = getFloat(); - else if (KEY_AS("w")) parseProperty(stroke->width); + else if (KEY_AS("w")) parseProperty(stroke->width); else if (KEY_AS("d")) parseStrokeDash(stroke); else parseGradient(stroke, key); } @@ -793,9 +790,9 @@ LottieTrimpath* LottieParser::parseTrimpath() while (auto key = nextObjectKey()) { if (parseCommon(trim, key)) continue; - else if (KEY_AS("s")) parseProperty(trim->start); - else if (KEY_AS("e")) parseProperty(trim->end); - else if (KEY_AS("o")) parseProperty(trim->offset); + else if (KEY_AS("s")) parseProperty(trim->start); + else if (KEY_AS("e")) parseProperty(trim->end); + else if (KEY_AS("o")) parseProperty(trim->offset); else if (KEY_AS("m")) trim->type = static_cast(getInt()); else skip(); } @@ -811,19 +808,19 @@ LottieRepeater* LottieParser::parseRepeater() while (auto key = nextObjectKey()) { if (parseCommon(repeater, key)) continue; - else if (KEY_AS("c")) parseProperty(repeater->copies); - else if (KEY_AS("o")) parseProperty(repeater->offset); + else if (KEY_AS("c")) parseProperty(repeater->copies); + else if (KEY_AS("o")) parseProperty(repeater->offset); else if (KEY_AS("m")) repeater->inorder = getInt() == 2; else if (KEY_AS("tr")) { enterObject(); while (auto key = nextObjectKey()) { - if (KEY_AS("a")) parseProperty(repeater->anchor); - else if (KEY_AS("p")) parseProperty(repeater->position); - else if (KEY_AS("r")) parseProperty(repeater->rotation); - else if (KEY_AS("s")) parseProperty(repeater->scale); - else if (KEY_AS("so")) parseProperty(repeater->startOpacity); - else if (KEY_AS("eo")) parseProperty(repeater->endOpacity); + if (KEY_AS("a")) parseProperty(repeater->anchor); + else if (KEY_AS("p")) parseProperty(repeater->position); + else if (KEY_AS("r")) parseProperty(repeater->rotation); + else if (KEY_AS("s")) parseProperty(repeater->scale); + else if (KEY_AS("so")) parseProperty(repeater->startOpacity); + else if (KEY_AS("eo")) parseProperty(repeater->endOpacity); else skip(); } } @@ -841,9 +838,9 @@ LottieOffsetPath* LottieParser::parseOffsetPath() while (auto key = nextObjectKey()) { if (parseCommon(offsetPath, key)) continue; - else if (KEY_AS("a")) parseProperty(offsetPath->offset); + else if (KEY_AS("a")) parseProperty(offsetPath->offset); else if (KEY_AS("lj")) offsetPath->join = (StrokeJoin) getInt(); - else if (KEY_AS("ml")) parseProperty(offsetPath->miterLimit); + else if (KEY_AS("ml")) parseProperty(offsetPath->miterLimit); else skip(); } return offsetPath; @@ -953,7 +950,7 @@ LottieObject* LottieParser::parseAsset() if (data) { obj = new LottieImage; parseImage(static_cast(obj), data, subPath, embedded, width, height); - if (sid) registerSlot(obj, sid); + if (sid) registerSlot(obj, sid, LottieProperty::Type::Image); } if (obj) obj->id = id; return obj; @@ -1087,7 +1084,7 @@ LottieObject* LottieParser::parseGroup() void LottieParser::parseTimeRemap(LottieLayer* layer) { - parseProperty(layer->timeRemap); + parseProperty(layer->timeRemap); } @@ -1116,7 +1113,7 @@ void LottieParser::parseTextAlignmentOption(LottieText* text) enterObject(); while (auto key = nextObjectKey()) { if (KEY_AS("g")) text->alignOption.grouping = (LottieText::AlignOption::Group) getInt(); - else if (KEY_AS("a")) parseProperty(text->alignOption.anchor); + else if (KEY_AS("a")) parseProperty(text->alignOption.anchor); else skip(); } } @@ -1136,35 +1133,35 @@ void LottieParser::parseTextRange(LottieText* text) while (auto key = nextObjectKey()) { if (KEY_AS("t")) selector->expressible = (bool) getInt(); else if (KEY_AS("xe")) { - parseProperty(selector->maxEase); + parseProperty(selector->maxEase); selector->interpolator = tvg::malloc(sizeof(LottieInterpolator)); } - else if (KEY_AS("ne")) parseProperty(selector->minEase); - else if (KEY_AS("a")) parseProperty(selector->maxAmount); + else if (KEY_AS("ne")) parseProperty(selector->minEase); + else if (KEY_AS("a")) parseProperty(selector->maxAmount); else if (KEY_AS("b")) selector->based = (LottieTextRange::Based) getInt(); else if (KEY_AS("rn")) selector->random = getInt() ? rand() : 0; else if (KEY_AS("sh")) selector->shape = (LottieTextRange::Shape) getInt(); - else if (KEY_AS("o")) parseProperty(selector->offset); + else if (KEY_AS("o")) parseProperty(selector->offset); else if (KEY_AS("r")) selector->rangeUnit = (LottieTextRange::Unit) getInt(); - else if (KEY_AS("sm")) parseProperty(selector->smoothness); - else if (KEY_AS("s")) parseProperty(selector->start); - else if (KEY_AS("e")) parseProperty(selector->end); + else if (KEY_AS("sm")) parseProperty(selector->smoothness); + else if (KEY_AS("s")) parseProperty(selector->start); + else if (KEY_AS("e")) parseProperty(selector->end); else skip(); } } else if (KEY_AS("a")) { // text style enterObject(); while (auto key = nextObjectKey()) { - if (KEY_AS("t")) parseProperty(selector->style.letterSpacing); - else if (KEY_AS("ls")) parseProperty(selector->style.lineSpacing); - else if (KEY_AS("fc")) parseProperty(selector->style.fillColor); - else if (KEY_AS("fo")) parseProperty(selector->style.fillOpacity); - else if (KEY_AS("sw")) parseProperty(selector->style.strokeWidth); - else if (KEY_AS("sc")) parseProperty(selector->style.strokeColor); - else if (KEY_AS("so")) parseProperty(selector->style.strokeOpacity); - else if (KEY_AS("o")) parseProperty(selector->style.opacity); - else if (KEY_AS("p")) parseProperty(selector->style.position); - else if (KEY_AS("s")) parseProperty(selector->style.scale); - else if (KEY_AS("r")) parseProperty(selector->style.rotation); + if (KEY_AS("t")) parseProperty(selector->style.letterSpacing); + else if (KEY_AS("ls")) parseProperty(selector->style.lineSpacing); + else if (KEY_AS("fc")) parseProperty(selector->style.fillColor); + else if (KEY_AS("fo")) parseProperty(selector->style.fillOpacity); + else if (KEY_AS("sw")) parseProperty(selector->style.strokeWidth); + else if (KEY_AS("sc")) parseProperty(selector->style.strokeColor); + else if (KEY_AS("so")) parseProperty(selector->style.strokeOpacity); + else if (KEY_AS("o")) parseProperty(selector->style.opacity); + else if (KEY_AS("p")) parseProperty(selector->style.position); + else if (KEY_AS("s")) parseProperty(selector->style.scale); + else if (KEY_AS("r")) parseProperty(selector->style.rotation); else skip(); } } else skip(); @@ -1183,7 +1180,7 @@ void LottieParser::parseTextFollowPath(LottieText* text) if (!text->followPath) text->followPath = new LottieTextFollowPath; do { if (KEY_AS("m")) text->followPath->maskIdx = getInt(); - else if (KEY_AS("f")) parseProperty(text->followPath->firstMargin); + else if (KEY_AS("f")) parseProperty(text->followPath->firstMargin); else skip(); } while ((key = nextObjectKey())); } @@ -1196,7 +1193,7 @@ void LottieParser::parseText(Array& parent) auto text = new LottieText; while (auto key = nextObjectKey()) { - if (KEY_AS("d")) parseProperty(text->doc, text); + if (KEY_AS("d")) parseProperty(text->doc, text); else if (KEY_AS("a")) parseTextRange(text); else if (KEY_AS("m")) parseTextAlignmentOption(text); else if (KEY_AS("p")) parseTextFollowPath(text); @@ -1226,8 +1223,8 @@ LottieMask* LottieParser::parseMask() if (KEY_AS("inv")) mask->inverse = getBool(); else if (KEY_AS("mode")) mask->method = getMaskMethod(mask->inverse); else if (KEY_AS("pt")) getPathSet(mask->pathset); - else if (KEY_AS("o")) parseProperty(mask->opacity); - else if (KEY_AS("x")) parseProperty(mask->expand); + else if (KEY_AS("o")) parseProperty(mask->opacity); + else if (KEY_AS("x")) parseProperty(mask->expand); else skip(); } return mask; @@ -1512,29 +1509,29 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault) context = {slot->context.layer, slot->context.parent}; switch (slot->type) { - case LottieProperty::Type::Position: { - obj = new LottieTransform; - parseSlotProperty(static_cast(obj)->position); - break; - } - case LottieProperty::Type::Point: { - obj = new LottieTransform; - parseSlotProperty(static_cast(obj)->scale); - break; - } case LottieProperty::Type::Float: { obj = new LottieTransform; - parseSlotProperty(static_cast(obj)->rotation); + parseSlotProperty(static_cast(obj)->rotation); + break; + } + case LottieProperty::Type::Scalar: { + obj = new LottieTransform; + parseSlotProperty(static_cast(obj)->scale); + break; + } + case LottieProperty::Type::Vector: { + obj = new LottieTransform; + parseSlotProperty(static_cast(obj)->position); break; } case LottieProperty::Type::Opacity: { obj = new LottieSolid; - parseSlotProperty(static_cast(obj)->opacity); + parseSlotProperty(static_cast(obj)->opacity); break; } case LottieProperty::Type::Color: { obj = new LottieSolid; - parseSlotProperty(static_cast(obj)->color); + parseSlotProperty(static_cast(obj)->color); break; } case LottieProperty::Type::ColorStop: { @@ -1547,7 +1544,7 @@ bool LottieParser::apply(LottieSlot* slot, bool byDefault) } case LottieProperty::Type::TextDoc: { obj = new LottieText; - parseSlotProperty(static_cast(obj)->doc); + parseSlotProperty(static_cast(obj)->doc); break; } case LottieProperty::Type::Image: { diff --git a/src/loaders/lottie/tvgLottieParser.h b/src/loaders/lottie/tvgLottieParser.h index 01b8b780..2f430f3a 100644 --- a/src/loaders/lottie/tvgLottieParser.h +++ b/src/loaders/lottie/tvgLottieParser.h @@ -40,7 +40,7 @@ public: bool apply(LottieSlot* slot, bool byDefault); const char* sid(bool first = false); void captureSlots(const char* key); - template void registerSlot(LottieObject* obj, const char* sid); + void registerSlot(LottieObject* obj, const char* sid, LottieProperty::Type type); LottieComposition* comp = nullptr; const char* dirName = nullptr; //base resource directory @@ -72,8 +72,8 @@ private: template bool parseTangent(const char *key, LottieScalarFrame& value); template void parseKeyFrame(T& prop); template void parsePropertyInternal(T& prop); - template void parseProperty(T& prop, LottieObject* obj = nullptr); - template void parseSlotProperty(T& prop); + template void parseProperty(T& prop, LottieObject* obj = nullptr); + template void parseSlotProperty(T& prop); LottieObject* parseObject(); LottieObject* parseAsset(); diff --git a/src/loaders/lottie/tvgLottieProperty.h b/src/loaders/lottie/tvgLottieProperty.h index a58bdf00..4b7ebee3 100644 --- a/src/loaders/lottie/tvgLottieProperty.h +++ b/src/loaders/lottie/tvgLottieProperty.h @@ -186,13 +186,13 @@ struct LottieExpression //Property would have an either keyframes or single value. struct LottieProperty { - enum class Type : uint8_t { Point = 0, Float, Opacity, Color, PathSet, ColorStop, Position, TextDoc, Image, Invalid }; + enum class Type : uint8_t { Invalid = 0, Float, Integer, Scalar, Vector, PathSet, Color, Opacity, ColorStop, TextDoc, Image}; LottieExpression* exp = nullptr; Type type; uint8_t ix; //property index - //TODO: Apply common bodies? + LottieProperty(Type type = Type::Invalid) : type(type) {} virtual ~LottieProperty() {} virtual uint32_t frameCnt() = 0; virtual uint32_t nearest(float frameNo) = 0; @@ -316,15 +316,16 @@ float _loop(T* frames, float frameNo, LottieExpression* exp) } -template +template struct LottieGenericProperty : LottieProperty { //Property has an either keyframes or single value. Array* frames = nullptr; Value value; - LottieGenericProperty(Value v) : value(v) {} - LottieGenericProperty() {} + LottieGenericProperty(Value v) : LottieProperty(PType), value(v) {} + + LottieGenericProperty() : LottieProperty(PType) {} LottieGenericProperty(const LottieGenericProperty& rhs) { @@ -402,7 +403,7 @@ struct LottieGenericProperty : LottieProperty return tvg::lerp(operator()(frameNo, exps), operator()(tween.frameNo, exps), tween.progress); } - void copy(LottieGenericProperty& rhs, bool shallow = true) + void copy(LottieGenericProperty& rhs, bool shallow = true) { if (LottieProperty::copy(&rhs, shallow)) return; @@ -414,7 +415,10 @@ struct LottieGenericProperty : LottieProperty frames = new Array; *frames = *rhs.frames; } - } else value = rhs.value; + } else { + frames = nullptr; + value = rhs.value; + } } float angle(float frameNo) @@ -453,6 +457,8 @@ struct LottiePathSet : LottieProperty Array>* frames = nullptr; PathSet value; + LottiePathSet() : LottieProperty(LottieProperty::Type::PathSet) {} + ~LottiePathSet() { release(); @@ -638,7 +644,7 @@ struct LottieColorStop : LottieProperty uint16_t count = 0; //colorstop count bool populated = false; - LottieColorStop() {} + LottieColorStop() : LottieProperty(LottieProperty::Type::ColorStop) {} LottieColorStop(const LottieColorStop& rhs) { @@ -801,6 +807,7 @@ struct LottieColorStop : LottieProperty *frames = *rhs.frames; } } else { + frames = nullptr; value = rhs.value; rhs.value = ColorStop(); } @@ -817,7 +824,7 @@ struct LottieTextDoc : LottieProperty Array>* frames = nullptr; TextDocument value; - LottieTextDoc() {} + LottieTextDoc() : LottieProperty(LottieProperty::Type::TextDoc) {} LottieTextDoc(const LottieTextDoc& rhs) { @@ -923,6 +930,7 @@ struct LottieTextDoc : LottieProperty *frames = *rhs.frames; } } else { + frames = nullptr; value = rhs.value; rhs.value.text = nullptr; rhs.value.name = nullptr; @@ -944,7 +952,7 @@ struct LottieBitmap : LottieProperty float width = 0.0f; float height = 0.0f; - LottieBitmap() {} + LottieBitmap() : LottieProperty(LottieProperty::Type::Image) {} LottieBitmap(const LottieBitmap& rhs) { @@ -976,7 +984,6 @@ struct LottieBitmap : LottieProperty if (shallow) { b64Data = rhs.b64Data; mimeType = rhs.mimeType; - rhs.b64Data = nullptr; rhs.mimeType = nullptr; } else { @@ -985,19 +992,18 @@ struct LottieBitmap : LottieProperty b64Data = duplicate(rhs.b64Data); if (rhs.mimeType) mimeType = duplicate(rhs.mimeType); } - size = rhs.size; width = rhs.width; height = rhs.height; } }; +using LottieFloat = LottieGenericProperty, float, LottieProperty::Type::Float>; +using LottieInteger = LottieGenericProperty, int8_t, LottieProperty::Type::Integer>; +using LottieScalar = LottieGenericProperty, Point, LottieProperty::Type::Scalar>; +using LottieVector = LottieGenericProperty, Point, LottieProperty::Type::Vector, 0>; +using LottieColor = LottieGenericProperty, RGB24, LottieProperty::Type::Color>; +using LottieOpacity = LottieGenericProperty, uint8_t, LottieProperty::Type::Opacity>; -using LottieScalar = LottieGenericProperty, Point>; -using LottieFloat = LottieGenericProperty, float>; -using LottieOpacity = LottieGenericProperty, uint8_t>; -using LottieColor = LottieGenericProperty, RGB24>; -using LottieInteger = LottieGenericProperty, int8_t>; -using LottieVector = LottieGenericProperty, Point, 0>; #endif //_TVG_LOTTIE_PROPERTY_H_