mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 06:34:01 +00:00
lottie/builder: ++size optimization
Replaced std::queue with inlist for optimizing binary size (-1.3kb).
This commit is contained in:
parent
e89eb09a33
commit
023d961118
1 changed files with 104 additions and 100 deletions
|
@ -20,11 +20,10 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgPaint.h"
|
||||
#include "tvgShape.h"
|
||||
#include "tvgInlist.h"
|
||||
#include "tvgLottieModel.h"
|
||||
#include "tvgLottieBuilder.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
|
@ -51,6 +50,8 @@ struct RenderRepeater
|
|||
|
||||
struct RenderContext
|
||||
{
|
||||
INLIST_ITEM(RenderContext);
|
||||
|
||||
Shape* propagator = nullptr;
|
||||
Shape* merging = nullptr; //merging shapes if possible (if shapes have same properties)
|
||||
LottieObject** begin = nullptr; //iteration entry point
|
||||
|
@ -83,7 +84,7 @@ struct RenderContext
|
|||
};
|
||||
|
||||
|
||||
static void _updateChildren(LottieGroup* parent, float frameNo, queue<RenderContext>& contexts);
|
||||
static void _updateChildren(LottieGroup* parent, float frameNo, Inlist<RenderContext>& contexts);
|
||||
static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo);
|
||||
static bool _buildComposition(LottieComposition* comp, LottieGroup* parent);
|
||||
|
||||
|
@ -177,30 +178,30 @@ static void _updateTransform(LottieLayer* layer, float frameNo)
|
|||
}
|
||||
|
||||
|
||||
static void _updateTransform(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateTransform(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto transform = static_cast<LottieTransform*>(*child);
|
||||
if (!transform) return;
|
||||
|
||||
ctx.merging = nullptr;
|
||||
ctx->merging = nullptr;
|
||||
|
||||
Matrix matrix;
|
||||
uint8_t opacity;
|
||||
if (!_updateTransform(transform, frameNo, false, matrix, opacity)) return;
|
||||
|
||||
auto pmatrix = PP(ctx.propagator)->transform();
|
||||
ctx.propagator->transform(pmatrix ? mathMultiply(pmatrix, &matrix) : matrix);
|
||||
ctx.propagator->opacity(MULTIPLY(opacity, PP(ctx.propagator)->opacity));
|
||||
auto pmatrix = PP(ctx->propagator)->transform();
|
||||
ctx->propagator->transform(pmatrix ? mathMultiply(pmatrix, &matrix) : matrix);
|
||||
ctx->propagator->opacity(MULTIPLY(opacity, PP(ctx->propagator)->opacity));
|
||||
|
||||
//FIXME: preserve the stroke width. too workaround, need a better design.
|
||||
if (P(ctx.propagator)->rs.strokeWidth() > 0.0f) {
|
||||
if (P(ctx->propagator)->rs.strokeWidth() > 0.0f) {
|
||||
auto denominator = sqrtf(matrix.e11 * matrix.e11 + matrix.e12 * matrix.e12);
|
||||
if (denominator > 1.0f) ctx.propagator->strokeWidth(ctx.propagator->strokeWidth() / denominator);
|
||||
if (denominator > 1.0f) ctx->propagator->strokeWidth(ctx->propagator->strokeWidth() / denominator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _updateGroup(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& pcontexts, RenderContext& ctx)
|
||||
static void _updateGroup(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& pcontexts, RenderContext* ctx)
|
||||
{
|
||||
auto group = static_cast<LottieGroup*>(*child);
|
||||
|
||||
|
@ -209,122 +210,124 @@ static void _updateGroup(LottieGroup* parent, LottieObject** child, float frameN
|
|||
//Prepare render data
|
||||
group->scene = parent->scene;
|
||||
|
||||
queue<RenderContext> contexts;
|
||||
contexts.push(ctx);
|
||||
Inlist<RenderContext> contexts;
|
||||
contexts.back(new RenderContext(*ctx));
|
||||
|
||||
_updateChildren(group, frameNo, contexts);
|
||||
|
||||
contexts.free();
|
||||
}
|
||||
|
||||
|
||||
static void _updateStroke(LottieStroke* stroke, float frameNo, RenderContext& ctx)
|
||||
static void _updateStroke(LottieStroke* stroke, float frameNo, RenderContext* ctx)
|
||||
{
|
||||
ctx.propagator->strokeWidth(stroke->width(frameNo));
|
||||
ctx.propagator->strokeCap(stroke->cap);
|
||||
ctx.propagator->strokeJoin(stroke->join);
|
||||
ctx.propagator->strokeMiterlimit(stroke->miterLimit);
|
||||
ctx->propagator->strokeWidth(stroke->width(frameNo));
|
||||
ctx->propagator->strokeCap(stroke->cap);
|
||||
ctx->propagator->strokeJoin(stroke->join);
|
||||
ctx->propagator->strokeMiterlimit(stroke->miterLimit);
|
||||
|
||||
if (stroke->dashattr) {
|
||||
float dashes[2];
|
||||
dashes[0] = stroke->dashSize(frameNo);
|
||||
dashes[1] = dashes[0] + stroke->dashGap(frameNo);
|
||||
ctx.propagator->strokeDash(dashes, 2, stroke->dashOffset(frameNo));
|
||||
ctx->propagator->strokeDash(dashes, 2, stroke->dashOffset(frameNo));
|
||||
} else {
|
||||
ctx.propagator->strokeDash(nullptr, 0);
|
||||
ctx->propagator->strokeDash(nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool _fragmentedStroking(LottieObject** child, queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static bool _fragmentedStroking(LottieObject** child, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (!ctx.reqFragment) return false;
|
||||
if (ctx.stroking) return true;
|
||||
if (!ctx->reqFragment) return false;
|
||||
if (ctx->stroking) return true;
|
||||
|
||||
contexts.push(ctx);
|
||||
auto& fragment = contexts.back();
|
||||
fragment.propagator->strokeWidth(0.0f);
|
||||
fragment.begin = child - 1;
|
||||
ctx.stroking = true;
|
||||
contexts.back(new RenderContext(*ctx));
|
||||
auto fragment = contexts.tail;
|
||||
fragment->propagator->strokeWidth(0.0f);
|
||||
fragment->begin = child - 1;
|
||||
ctx->stroking = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void _updateSolidStroke(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateSolidStroke(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (_fragmentedStroking(child, contexts, ctx)) return;
|
||||
|
||||
auto stroke = static_cast<LottieSolidStroke*>(*child);
|
||||
|
||||
ctx.merging = nullptr;
|
||||
ctx->merging = nullptr;
|
||||
auto color = stroke->color(frameNo);
|
||||
ctx.propagator->strokeFill(color.rgb[0], color.rgb[1], color.rgb[2], stroke->opacity(frameNo));
|
||||
ctx->propagator->strokeFill(color.rgb[0], color.rgb[1], color.rgb[2], stroke->opacity(frameNo));
|
||||
_updateStroke(static_cast<LottieStroke*>(stroke), frameNo, ctx);
|
||||
}
|
||||
|
||||
|
||||
static void _updateGradientStroke(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateGradientStroke(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (_fragmentedStroking(child, contexts, ctx)) return;
|
||||
|
||||
auto stroke = static_cast<LottieGradientStroke*>(*child);
|
||||
|
||||
ctx.merging = nullptr;
|
||||
ctx.propagator->strokeFill(unique_ptr<Fill>(stroke->fill(frameNo)));
|
||||
ctx->merging = nullptr;
|
||||
ctx->propagator->strokeFill(unique_ptr<Fill>(stroke->fill(frameNo)));
|
||||
_updateStroke(static_cast<LottieStroke*>(stroke), frameNo, ctx);
|
||||
}
|
||||
|
||||
|
||||
static void _updateSolidFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateSolidFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (ctx.stroking) return;
|
||||
if (ctx->stroking) return;
|
||||
|
||||
auto fill = static_cast<LottieSolidFill*>(*child);
|
||||
|
||||
ctx.merging = nullptr;
|
||||
ctx->merging = nullptr;
|
||||
|
||||
auto color = fill->color(frameNo);
|
||||
ctx.propagator->fill(color.rgb[0], color.rgb[1], color.rgb[2], fill->opacity(frameNo));
|
||||
ctx.propagator->fill(fill->rule);
|
||||
ctx->propagator->fill(color.rgb[0], color.rgb[1], color.rgb[2], fill->opacity(frameNo));
|
||||
ctx->propagator->fill(fill->rule);
|
||||
|
||||
if (ctx.propagator->strokeWidth() > 0) ctx.propagator->order(true);
|
||||
if (ctx->propagator->strokeWidth() > 0) ctx->propagator->order(true);
|
||||
}
|
||||
|
||||
|
||||
static Shape* _updateGradientFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static Shape* _updateGradientFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (ctx.stroking) return nullptr;
|
||||
if (ctx->stroking) return nullptr;
|
||||
|
||||
auto fill = static_cast<LottieGradientFill*>(*child);
|
||||
|
||||
ctx.merging = nullptr;
|
||||
ctx->merging = nullptr;
|
||||
|
||||
//TODO: reuse the fill instance?
|
||||
ctx.propagator->fill(unique_ptr<Fill>(fill->fill(frameNo)));
|
||||
ctx.propagator->fill(fill->rule);
|
||||
ctx.propagator->opacity(MULTIPLY(fill->opacity(frameNo), PP(ctx.propagator)->opacity));
|
||||
ctx->propagator->fill(unique_ptr<Fill>(fill->fill(frameNo)));
|
||||
ctx->propagator->fill(fill->rule);
|
||||
ctx->propagator->opacity(MULTIPLY(fill->opacity(frameNo), PP(ctx->propagator)->opacity));
|
||||
|
||||
if (ctx.propagator->strokeWidth() > 0) ctx.propagator->order(true);
|
||||
if (ctx->propagator->strokeWidth() > 0) ctx->propagator->order(true);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static Shape* _draw(LottieGroup* parent, RenderContext& ctx)
|
||||
static Shape* _draw(LottieGroup* parent, RenderContext* ctx)
|
||||
{
|
||||
if (ctx.allowMerging && ctx.merging) return ctx.merging;
|
||||
if (ctx->allowMerging && ctx->merging) return ctx->merging;
|
||||
|
||||
auto shape = cast<Shape>(ctx.propagator->duplicate());
|
||||
ctx.merging = shape.get();
|
||||
auto shape = cast<Shape>(ctx->propagator->duplicate());
|
||||
ctx->merging = shape.get();
|
||||
parent->scene->push(std::move(shape));
|
||||
|
||||
return ctx.merging;
|
||||
return ctx->merging;
|
||||
}
|
||||
|
||||
|
||||
//OPTIMIZE: path?
|
||||
static void _repeat(LottieGroup* parent, unique_ptr<Shape> path, RenderContext& ctx)
|
||||
static void _repeat(LottieGroup* parent, unique_ptr<Shape> path, RenderContext* ctx)
|
||||
{
|
||||
auto repeater = ctx.repeater;
|
||||
auto repeater = ctx->repeater;
|
||||
|
||||
Array<Shape*> shapes;
|
||||
shapes.reserve(repeater->cnt);
|
||||
|
@ -332,7 +335,7 @@ static void _repeat(LottieGroup* parent, unique_ptr<Shape> path, RenderContext&
|
|||
for (int i = 0; i < repeater->cnt; ++i) {
|
||||
auto multiplier = repeater->offset + static_cast<float>(i);
|
||||
|
||||
auto shape = static_cast<Shape*>(ctx.propagator->duplicate());
|
||||
auto shape = static_cast<Shape*>(ctx->propagator->duplicate());
|
||||
P(shape)->rs.path = P(path.get())->rs.path;
|
||||
|
||||
auto opacity = repeater->interpOpacity ? mathLerp<uint8_t>(repeater->startOpacity, repeater->endOpacity, static_cast<float>(i + 1) / repeater->cnt) : repeater->startOpacity;
|
||||
|
@ -348,7 +351,7 @@ static void _repeat(LottieGroup* parent, unique_ptr<Shape> path, RenderContext&
|
|||
auto pm = PP(shape)->transform();
|
||||
shape->transform(pm ? mathMultiply(&m, pm) : m);
|
||||
|
||||
if (ctx.roundness > 1.0f && P(shape)->rs.stroke) {
|
||||
if (ctx->roundness > 1.0f && P(shape)->rs.stroke) {
|
||||
TVGERR("LOTTIE", "FIXME: Path roundesss should be applied properly!");
|
||||
P(shape)->rs.stroke->join = StrokeJoin::Round;
|
||||
}
|
||||
|
@ -369,21 +372,21 @@ static void _repeat(LottieGroup* parent, unique_ptr<Shape> path, RenderContext&
|
|||
}
|
||||
|
||||
|
||||
static void _updateRect(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateRect(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto rect= static_cast<LottieRect*>(*child);
|
||||
|
||||
auto position = rect->position(frameNo);
|
||||
auto size = rect->size(frameNo);
|
||||
auto roundness = rect->radius(frameNo);
|
||||
if (ctx.roundness > roundness) roundness = ctx.roundness;
|
||||
if (ctx->roundness > roundness) roundness = ctx->roundness;
|
||||
|
||||
if (roundness > 0.0f) {
|
||||
if (roundness > size.x * 0.5f) roundness = size.x * 0.5f;
|
||||
if (roundness > size.y * 0.5f) roundness = size.y * 0.5f;
|
||||
}
|
||||
|
||||
if (ctx.repeater) {
|
||||
if (ctx->repeater) {
|
||||
auto path = Shape::gen();
|
||||
path->appendRect(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y, roundness, roundness);
|
||||
_repeat(parent, std::move(path), ctx);
|
||||
|
@ -394,14 +397,14 @@ static void _updateRect(LottieGroup* parent, LottieObject** child, float frameNo
|
|||
}
|
||||
|
||||
|
||||
static void _updateEllipse(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateEllipse(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto ellipse= static_cast<LottieEllipse*>(*child);
|
||||
|
||||
auto position = ellipse->position(frameNo);
|
||||
auto size = ellipse->size(frameNo);
|
||||
|
||||
if (ctx.repeater) {
|
||||
if (ctx->repeater) {
|
||||
auto path = Shape::gen();
|
||||
path->appendCircle(position.x, position.y, size.x * 0.5f, size.y * 0.5f);
|
||||
_repeat(parent, std::move(path), ctx);
|
||||
|
@ -412,11 +415,11 @@ static void _updateEllipse(LottieGroup* parent, LottieObject** child, float fram
|
|||
}
|
||||
|
||||
|
||||
static void _updatePath(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updatePath(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto path= static_cast<LottiePath*>(*child);
|
||||
|
||||
if (ctx.repeater) {
|
||||
if (ctx->repeater) {
|
||||
auto p = Shape::gen();
|
||||
path->pathset(frameNo, P(p)->rs.path.cmds, P(p)->rs.path.pts);
|
||||
_repeat(parent, std::move(p), ctx);
|
||||
|
@ -427,7 +430,7 @@ static void _updatePath(LottieGroup* parent, LottieObject** child, float frameNo
|
|||
P(merging)->update(RenderUpdateFlag::Path);
|
||||
}
|
||||
|
||||
if (ctx.roundness > 1.0f && P(merging)->rs.stroke) {
|
||||
if (ctx->roundness > 1.0f && P(merging)->rs.stroke) {
|
||||
TVGERR("LOTTIE", "FIXME: Path roundesss should be applied properly!");
|
||||
P(merging)->rs.stroke->join = StrokeJoin::Round;
|
||||
}
|
||||
|
@ -613,7 +616,7 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* tr
|
|||
}
|
||||
|
||||
|
||||
static void _updatePolystar(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updatePolystar(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto star= static_cast<LottiePolyStar*>(*child);
|
||||
|
||||
|
@ -626,7 +629,7 @@ static void _updatePolystar(LottieGroup* parent, LottieObject** child, float fra
|
|||
|
||||
auto identity = mathIdentity((const Matrix*)&matrix);
|
||||
|
||||
if (ctx.repeater) {
|
||||
if (ctx->repeater) {
|
||||
auto p = Shape::gen();
|
||||
if (star->type == LottiePolyStar::Star) _updateStar(parent, star, identity ? nullptr : &matrix, frameNo, p.get());
|
||||
else _updatePolygon(parent, star, identity ? nullptr : &matrix, frameNo, p.get());
|
||||
|
@ -640,7 +643,7 @@ static void _updatePolystar(LottieGroup* parent, LottieObject** child, float fra
|
|||
}
|
||||
|
||||
|
||||
static void _updateImage(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateImage(LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto image = static_cast<LottieImage*>(*child);
|
||||
auto picture = image->picture;
|
||||
|
@ -669,74 +672,74 @@ static void _updateImage(LottieGroup* parent, LottieObject** child, float frameN
|
|||
PP(picture)->ref();
|
||||
}
|
||||
|
||||
if (ctx.propagator) {
|
||||
if (auto matrix = PP(ctx.propagator)->transform()) {
|
||||
if (ctx->propagator) {
|
||||
if (auto matrix = PP(ctx->propagator)->transform()) {
|
||||
picture->transform(*matrix);
|
||||
}
|
||||
picture->opacity(PP(ctx.propagator)->opacity);
|
||||
picture->opacity(PP(ctx->propagator)->opacity);
|
||||
}
|
||||
parent->scene->push(cast<Picture>(picture));
|
||||
}
|
||||
|
||||
|
||||
static void _updateRoundedCorner(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateRoundedCorner(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto roundedCorner= static_cast<LottieRoundedCorner*>(*child);
|
||||
|
||||
auto roundness = roundedCorner->radius(frameNo);
|
||||
if (ctx.roundness < roundness) ctx.roundness = roundness;
|
||||
if (ctx->roundness < roundness) ctx->roundness = roundness;
|
||||
}
|
||||
|
||||
|
||||
static void _updateRepeater(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateRepeater(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto repeater= static_cast<LottieRepeater*>(*child);
|
||||
|
||||
if (!ctx.repeater) ctx.repeater = new RenderRepeater();
|
||||
ctx.repeater->cnt = static_cast<int>(repeater->copies(frameNo));
|
||||
ctx.repeater->offset = repeater->offset(frameNo);
|
||||
ctx.repeater->position = repeater->position(frameNo);
|
||||
ctx.repeater->anchor = repeater->anchor(frameNo);
|
||||
ctx.repeater->scale = repeater->scale(frameNo);
|
||||
ctx.repeater->rotation = repeater->rotation(frameNo);
|
||||
ctx.repeater->startOpacity = repeater->startOpacity(frameNo);
|
||||
ctx.repeater->endOpacity = repeater->endOpacity(frameNo);
|
||||
ctx.repeater->inorder = repeater->inorder;
|
||||
ctx.repeater->interpOpacity = (ctx.repeater->startOpacity == ctx.repeater->endOpacity) ? false : true;
|
||||
if (!ctx->repeater) ctx->repeater = new RenderRepeater();
|
||||
ctx->repeater->cnt = static_cast<int>(repeater->copies(frameNo));
|
||||
ctx->repeater->offset = repeater->offset(frameNo);
|
||||
ctx->repeater->position = repeater->position(frameNo);
|
||||
ctx->repeater->anchor = repeater->anchor(frameNo);
|
||||
ctx->repeater->scale = repeater->scale(frameNo);
|
||||
ctx->repeater->rotation = repeater->rotation(frameNo);
|
||||
ctx->repeater->startOpacity = repeater->startOpacity(frameNo);
|
||||
ctx->repeater->endOpacity = repeater->endOpacity(frameNo);
|
||||
ctx->repeater->inorder = repeater->inorder;
|
||||
ctx->repeater->interpOpacity = (ctx->repeater->startOpacity == ctx->repeater->endOpacity) ? false : true;
|
||||
|
||||
ctx.merging = nullptr;
|
||||
ctx->merging = nullptr;
|
||||
}
|
||||
|
||||
|
||||
static void _updateTrimpath(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED queue<RenderContext>& contexts, RenderContext& ctx)
|
||||
static void _updateTrimpath(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
auto trimpath= static_cast<LottieTrimpath*>(*child);
|
||||
|
||||
float begin, end;
|
||||
trimpath->segment(frameNo, begin, end);
|
||||
|
||||
if (P(ctx.propagator)->rs.stroke) {
|
||||
auto pbegin = P(ctx.propagator)->rs.stroke->trim.begin;
|
||||
auto pend = P(ctx.propagator)->rs.stroke->trim.end;
|
||||
if (P(ctx->propagator)->rs.stroke) {
|
||||
auto pbegin = P(ctx->propagator)->rs.stroke->trim.begin;
|
||||
auto pend = P(ctx->propagator)->rs.stroke->trim.end;
|
||||
auto length = fabsf(pend - pbegin);
|
||||
begin = (length * begin) + pbegin;
|
||||
end = (length * end) + pbegin;
|
||||
}
|
||||
|
||||
P(ctx.propagator)->strokeTrim(begin, end);
|
||||
P(ctx->propagator)->strokeTrim(begin, end);
|
||||
|
||||
if (trimpath->type == LottieTrimpath::Individual) ctx.allowMerging = false;
|
||||
if (trimpath->type == LottieTrimpath::Individual) ctx->allowMerging = false;
|
||||
}
|
||||
|
||||
|
||||
static void _updateChildren(LottieGroup* parent, float frameNo, queue<RenderContext>& contexts)
|
||||
static void _updateChildren(LottieGroup* parent, float frameNo, Inlist<RenderContext>& contexts)
|
||||
{
|
||||
contexts.front().begin = parent->children.end() - 1;
|
||||
contexts.head->begin = parent->children.end() - 1;
|
||||
|
||||
while (contexts.size() > 0) {
|
||||
auto& ctx = contexts.front();
|
||||
ctx.reqFragment = parent->reqFragment;
|
||||
for (auto child = ctx.begin; child >= parent->children.data; --child) {
|
||||
while (!contexts.empty()) {
|
||||
auto ctx = contexts.front();
|
||||
ctx->reqFragment = parent->reqFragment;
|
||||
for (auto child = ctx->begin; child >= parent->children.data; --child) {
|
||||
switch ((*child)->type) {
|
||||
case LottieObject::Group: {
|
||||
_updateGroup(parent, child, frameNo, contexts, ctx);
|
||||
|
@ -797,7 +800,7 @@ static void _updateChildren(LottieGroup* parent, float frameNo, queue<RenderCont
|
|||
default: break;
|
||||
}
|
||||
}
|
||||
contexts.pop();
|
||||
delete(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,9 +939,10 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo)
|
|||
}
|
||||
default: {
|
||||
if (!layer->children.empty()) {
|
||||
queue<RenderContext> contexts;
|
||||
contexts.emplace();
|
||||
Inlist<RenderContext> contexts;
|
||||
contexts.back(new RenderContext);
|
||||
_updateChildren(layer, frameNo, contexts);
|
||||
contexts.free();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue