diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index c5cb5305..cea0be12 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -361,9 +361,9 @@ static void _updateSolidFill(TVG_UNUSED LottieGroup* parent, LottieObject** chil } -static Shape* _updateGradientFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist& contexts, RenderContext* ctx, LottieExpressions* exps) +static void _updateGradientFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist& contexts, RenderContext* ctx, LottieExpressions* exps) { - if (_fragmented(child, contexts, ctx)) return nullptr; + if (_fragmented(child, contexts, ctx)) return; auto fill = static_cast(*child); @@ -374,8 +374,6 @@ static Shape* _updateGradientFill(TVG_UNUSED LottieGroup* parent, LottieObject** ctx->propagator->opacity(MULTIPLY(fill->opacity(frameNo), PP(ctx->propagator)->opacity)); if (ctx->propagator->strokeWidth() > 0) ctx->propagator->order(true); - - return nullptr; } @@ -975,7 +973,6 @@ static void _updateImage(LottieGroup* parent, LottieObject** child, float frameN static void _updateRoundedCorner(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist& contexts, RenderContext* ctx, LottieExpressions* exps) { auto roundedCorner= static_cast(*child); - auto roundness = roundedCorner->radius(frameNo, exps); if (ctx->roundness < roundness) ctx->roundness = roundness; } @@ -1028,6 +1025,7 @@ static void _updateChildren(LottieGroup* parent, float frameNo, InlistreqFragment = parent->reqFragment; for (auto child = ctx->begin; child >= parent->children.data; --child) { + //Here switch-case statements are more performant than virtual methods. switch ((*child)->type) { case LottieObject::Group: { _updateGroup(parent, child, frameNo, contexts, ctx, exps); diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 6336d647..7fab8ffb 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -35,6 +35,79 @@ /* External Class Implementation */ /************************************************************************/ +void LottieSlot::reset() +{ + if (!overriden) return; + + for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { + switch (type) { + case LottieProperty::Type::ColorStop: { + static_cast(pair->obj)->colorStops.release(); + static_cast(pair->obj)->colorStops = *static_cast(pair->prop); + static_cast(pair->prop)->frames = nullptr; + break; + } + case LottieProperty::Type::Color: { + static_cast(pair->obj)->color.release(); + static_cast(pair->obj)->color = *static_cast(pair->prop); + static_cast(pair->prop)->frames = nullptr; + break; + } + case LottieProperty::Type::TextDoc: { + static_cast(pair->obj)->doc.release(); + static_cast(pair->obj)->doc = *static_cast(pair->prop); + static_cast(pair->prop)->frames = nullptr; + break; + } + default: break; + } + delete(pair->prop); + pair->prop = nullptr; + } + overriden = false; +} + + +void LottieSlot::assign(LottieObject* target) +{ + //apply slot object to all targets + for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { + //backup the original properties before overwriting + switch (type) { + case LottieProperty::Type::ColorStop: { + if (!overriden) { + pair->prop = new LottieColorStop; + *static_cast(pair->prop) = static_cast(pair->obj)->colorStops; + } + + pair->obj->override(&static_cast(target)->colorStops); + break; + } + case LottieProperty::Type::Color: { + if (!overriden) { + pair->prop = new LottieColor; + *static_cast(pair->prop) = static_cast(pair->obj)->color; + } + + pair->obj->override(&static_cast(target)->color); + break; + } + case LottieProperty::Type::TextDoc: { + if (!overriden) { + pair->prop = new LottieTextDoc; + *static_cast(pair->prop) = static_cast(pair->obj)->doc; + } + + pair->obj->override(&static_cast(target)->doc); + break; + } + default: break; + } + } + overriden = true; +} + + LottieImage::~LottieImage() { free(b64Data); @@ -89,6 +162,90 @@ void LottieTrimpath::segment(float frameNo, float& start, float& end, LottieExpr } +uint32_t LottieGradient::populate(ColorStop& color) +{ + colorStops.populated = true; + if (!color.input) return 0; + + uint32_t alphaCnt = (color.input->count - (colorStops.count * 4)) / 2; + Array output(colorStops.count + alphaCnt); + uint32_t cidx = 0; //color count + uint32_t clast = colorStops.count * 4; + if (clast > color.input->count) clast = color.input->count; + uint32_t aidx = clast; //alpha count + Fill::ColorStop cs; + + //merge color stops. + for (uint32_t i = 0; i < color.input->count; ++i) { + if (cidx == clast || aidx == color.input->count) break; + if ((*color.input)[cidx] == (*color.input)[aidx]) { + cs.offset = (*color.input)[cidx]; + cs.r = lroundf((*color.input)[cidx + 1] * 255.0f); + cs.g = lroundf((*color.input)[cidx + 2] * 255.0f); + cs.b = lroundf((*color.input)[cidx + 3] * 255.0f); + cs.a = lroundf((*color.input)[aidx + 1] * 255.0f); + cidx += 4; + aidx += 2; + } else if ((*color.input)[cidx] < (*color.input)[aidx]) { + cs.offset = (*color.input)[cidx]; + cs.r = lroundf((*color.input)[cidx + 1] * 255.0f); + cs.g = lroundf((*color.input)[cidx + 2] * 255.0f); + cs.b = lroundf((*color.input)[cidx + 3] * 255.0f); + //generate alpha value + if (output.count > 0) { + auto p = ((*color.input)[cidx] - output.last().offset) / ((*color.input)[aidx] - output.last().offset); + cs.a = mathLerp(output.last().a, lroundf((*color.input)[aidx + 1] * 255.0f), p); + } else cs.a = 255; + cidx += 4; + } else { + cs.offset = (*color.input)[aidx]; + cs.a = lroundf((*color.input)[aidx + 1] * 255.0f); + //generate color value + if (output.count > 0) { + auto p = ((*color.input)[aidx] - output.last().offset) / ((*color.input)[cidx] - output.last().offset); + cs.r = mathLerp(output.last().r, lroundf((*color.input)[cidx + 1] * 255.0f), p); + cs.g = mathLerp(output.last().g, lroundf((*color.input)[cidx + 2] * 255.0f), p); + cs.b = mathLerp(output.last().b, lroundf((*color.input)[cidx + 3] * 255.0f), p); + } else cs.r = cs.g = cs.b = 255; + aidx += 2; + } + output.push(cs); + } + + //color remains + while (cidx + 3 < clast) { + cs.offset = (*color.input)[cidx]; + cs.r = lroundf((*color.input)[cidx + 1] * 255.0f); + cs.g = lroundf((*color.input)[cidx + 2] * 255.0f); + cs.b = lroundf((*color.input)[cidx + 3] * 255.0f); + cs.a = (output.count > 0) ? output.last().a : 255; + output.push(cs); + cidx += 4; + } + + //alpha remains + while (aidx < color.input->count) { + cs.offset = (*color.input)[aidx]; + cs.a = lroundf((*color.input)[aidx + 1] * 255.0f); + if (output.count > 0) { + cs.r = output.last().r; + cs.g = output.last().g; + cs.b = output.last().b; + } else cs.r = cs.g = cs.b = 255; + output.push(cs); + aidx += 2; + } + + color.data = output.data; + output.data = nullptr; + + color.input->reset(); + delete(color.input); + + return output.count; +} + + Fill* LottieGradient::fill(float frameNo, LottieExpressions* exps) { Fill* fill = nullptr; diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 80d39534..eef6025d 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -387,89 +387,6 @@ struct LottieSolidFill : LottieSolid struct LottieGradient : LottieObject { - uint32_t populate(ColorStop& color) - { - colorStops.populated = true; - if (!color.input) return 0; - - uint32_t alphaCnt = (color.input->count - (colorStops.count * 4)) / 2; - Array output(colorStops.count + alphaCnt); - uint32_t cidx = 0; //color count - uint32_t clast = colorStops.count * 4; - if (clast > color.input->count) clast = color.input->count; - uint32_t aidx = clast; //alpha count - Fill::ColorStop cs; - - //merge color stops. - for (uint32_t i = 0; i < color.input->count; ++i) { - if (cidx == clast || aidx == color.input->count) break; - if ((*color.input)[cidx] == (*color.input)[aidx]) { - cs.offset = (*color.input)[cidx]; - cs.r = lroundf((*color.input)[cidx + 1] * 255.0f); - cs.g = lroundf((*color.input)[cidx + 2] * 255.0f); - cs.b = lroundf((*color.input)[cidx + 3] * 255.0f); - cs.a = lroundf((*color.input)[aidx + 1] * 255.0f); - cidx += 4; - aidx += 2; - } else if ((*color.input)[cidx] < (*color.input)[aidx]) { - cs.offset = (*color.input)[cidx]; - cs.r = lroundf((*color.input)[cidx + 1] * 255.0f); - cs.g = lroundf((*color.input)[cidx + 2] * 255.0f); - cs.b = lroundf((*color.input)[cidx + 3] * 255.0f); - //generate alpha value - if (output.count > 0) { - auto p = ((*color.input)[cidx] - output.last().offset) / ((*color.input)[aidx] - output.last().offset); - cs.a = mathLerp(output.last().a, lroundf((*color.input)[aidx + 1] * 255.0f), p); - } else cs.a = 255; - cidx += 4; - } else { - cs.offset = (*color.input)[aidx]; - cs.a = lroundf((*color.input)[aidx + 1] * 255.0f); - //generate color value - if (output.count > 0) { - auto p = ((*color.input)[aidx] - output.last().offset) / ((*color.input)[cidx] - output.last().offset); - cs.r = mathLerp(output.last().r, lroundf((*color.input)[cidx + 1] * 255.0f), p); - cs.g = mathLerp(output.last().g, lroundf((*color.input)[cidx + 2] * 255.0f), p); - cs.b = mathLerp(output.last().b, lroundf((*color.input)[cidx + 3] * 255.0f), p); - } else cs.r = cs.g = cs.b = 255; - aidx += 2; - } - output.push(cs); - } - - //color remains - while (cidx + 3 < clast) { - cs.offset = (*color.input)[cidx]; - cs.r = lroundf((*color.input)[cidx + 1] * 255.0f); - cs.g = lroundf((*color.input)[cidx + 2] * 255.0f); - cs.b = lroundf((*color.input)[cidx + 3] * 255.0f); - cs.a = (output.count > 0) ? output.last().a : 255; - output.push(cs); - cidx += 4; - } - - //alpha remains - while (aidx < color.input->count) { - cs.offset = (*color.input)[aidx]; - cs.a = lroundf((*color.input)[aidx + 1] * 255.0f); - if (output.count > 0) { - cs.r = output.last().r; - cs.g = output.last().g; - cs.b = output.last().b; - } else cs.r = cs.g = cs.b = 255; - output.push(cs); - aidx += 2; - } - - color.data = output.data; - output.data = nullptr; - - color.input->reset(); - delete(color.input); - - return output.count; - } - bool prepare() { if (!colorStops.populated) { @@ -485,6 +402,7 @@ struct LottieGradient : LottieObject return false; } + uint32_t populate(ColorStop& color); Fill* fill(float frameNo, LottieExpressions* exps); LottiePoint start = Point{0.0f, 0.0f}; @@ -666,76 +584,8 @@ struct LottieSlot LottieProperty* prop; }; - void assign(LottieObject* target) - { - //apply slot object to all targets - for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { - //backup the original properties before overwriting - switch (type) { - case LottieProperty::Type::ColorStop: { - if (!overriden) { - pair->prop = new LottieColorStop; - *static_cast(pair->prop) = static_cast(pair->obj)->colorStops; - } - - pair->obj->override(&static_cast(target)->colorStops); - break; - } - case LottieProperty::Type::Color: { - if (!overriden) { - pair->prop = new LottieColor; - *static_cast(pair->prop) = static_cast(pair->obj)->color; - } - - pair->obj->override(&static_cast(target)->color); - break; - } - case LottieProperty::Type::TextDoc: { - if (!overriden) { - pair->prop = new LottieTextDoc; - *static_cast(pair->prop) = static_cast(pair->obj)->doc; - } - - pair->obj->override(&static_cast(target)->doc); - break; - } - default: break; - } - } - overriden = true; - } - - void reset() - { - if (!overriden) return; - - for (auto pair = pairs.begin(); pair < pairs.end(); ++pair) { - switch (type) { - case LottieProperty::Type::ColorStop: { - static_cast(pair->obj)->colorStops.release(); - static_cast(pair->obj)->colorStops = *static_cast(pair->prop); - static_cast(pair->prop)->frames = nullptr; - break; - } - case LottieProperty::Type::Color: { - static_cast(pair->obj)->color.release(); - static_cast(pair->obj)->color = *static_cast(pair->prop); - static_cast(pair->prop)->frames = nullptr; - break; - } - case LottieProperty::Type::TextDoc: { - static_cast(pair->obj)->doc.release(); - static_cast(pair->obj)->doc = *static_cast(pair->prop); - static_cast(pair->prop)->frames = nullptr; - break; - } - default: break; - } - delete(pair->prop); - pair->prop = nullptr; - } - overriden = false; - } + void assign(LottieObject* target); + void reset(); LottieSlot(char* sid, LottieObject* obj, LottieProperty::Type type) : sid(sid), type(type) {