mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
lottie: Fixed the issue with gradient filling.
Previously, multiple gradients within a single group couldn't be accounted for during rendering. This fix addresses the scenario by fragmenting the rendering context.
This commit is contained in:
parent
5b89479963
commit
3c98cb5828
2 changed files with 20 additions and 16 deletions
|
@ -59,7 +59,7 @@ struct RenderContext
|
|||
LottieObject** begin = nullptr; //iteration entry point
|
||||
RenderRepeater* repeater = nullptr;
|
||||
float roundness = 0.0f;
|
||||
bool stroking = false; //context has been separated by the stroking
|
||||
bool fragmenting = false; //render context has been fragmented by filling
|
||||
bool reqFragment = false; //requirment to fragment the render context
|
||||
bool allowMerging = true; //individual trimpath doesn't allow merging shapes
|
||||
|
||||
|
@ -239,16 +239,18 @@ static void _updateStroke(LottieStroke* stroke, float frameNo, RenderContext* ct
|
|||
}
|
||||
|
||||
|
||||
static bool _fragmentedStroking(LottieObject** child, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
static bool _fragmented(LottieObject** child, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (!ctx->reqFragment) return false;
|
||||
if (ctx->stroking) return true;
|
||||
if (ctx->fragmenting) return true;
|
||||
|
||||
contexts.back(new RenderContext(*ctx));
|
||||
auto fragment = contexts.tail;
|
||||
fragment->propagator->stroke(0.0f);
|
||||
fragment->begin = child - 1;
|
||||
ctx->stroking = true;
|
||||
ctx->fragmenting = true;
|
||||
|
||||
TVGERR("LOTTIE", "Rendering is fragmented.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -256,7 +258,7 @@ static bool _fragmentedStroking(LottieObject** child, Inlist<RenderContext>& con
|
|||
|
||||
static void _updateSolidStroke(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (_fragmentedStroking(child, contexts, ctx)) return;
|
||||
if (_fragmented(child, contexts, ctx)) return;
|
||||
|
||||
auto stroke = static_cast<LottieSolidStroke*>(*child);
|
||||
|
||||
|
@ -269,7 +271,7 @@ static void _updateSolidStroke(TVG_UNUSED LottieGroup* parent, LottieObject** ch
|
|||
|
||||
static void _updateGradientStroke(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (_fragmentedStroking(child, contexts, ctx)) return;
|
||||
if (_fragmented(child, contexts, ctx)) return;
|
||||
|
||||
auto stroke = static_cast<LottieGradientStroke*>(*child);
|
||||
|
||||
|
@ -281,12 +283,11 @@ static void _updateGradientStroke(TVG_UNUSED LottieGroup* parent, LottieObject**
|
|||
|
||||
static void _updateSolidFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (ctx->stroking) return;
|
||||
if (_fragmented(child, contexts, ctx)) return;
|
||||
|
||||
auto fill = static_cast<LottieSolidFill*>(*child);
|
||||
|
||||
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);
|
||||
|
@ -297,12 +298,11 @@ static void _updateSolidFill(TVG_UNUSED LottieGroup* parent, LottieObject** chil
|
|||
|
||||
static Shape* _updateGradientFill(TVG_UNUSED LottieGroup* parent, LottieObject** child, float frameNo, TVG_UNUSED Inlist<RenderContext>& contexts, RenderContext* ctx)
|
||||
{
|
||||
if (ctx->stroking) return nullptr;
|
||||
if (_fragmented(child, contexts, ctx)) return nullptr;
|
||||
|
||||
auto fill = static_cast<LottieGradientFill*>(*child);
|
||||
|
||||
ctx->merging = nullptr;
|
||||
|
||||
//TODO: reuse the fill instance?
|
||||
ctx->propagator->fill(unique_ptr<Fill>(fill->fill(frameNo)));
|
||||
ctx->propagator->fill(fill->rule);
|
||||
|
@ -883,7 +883,7 @@ static void _updateChildren(LottieGroup* parent, float frameNo, Inlist<RenderCon
|
|||
|
||||
static void _updatePrecomp(LottieLayer* precomp, float frameNo)
|
||||
{
|
||||
if (precomp->children.count == 0) return;
|
||||
if (precomp->children.empty()) return;
|
||||
|
||||
frameNo = precomp->remap(frameNo);
|
||||
|
||||
|
@ -1000,9 +1000,7 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo)
|
|||
|
||||
switch (layer->type) {
|
||||
case LottieLayer::Precomp: {
|
||||
if (!layer->children.empty()) {
|
||||
_updatePrecomp(layer, frameNo);
|
||||
}
|
||||
_updatePrecomp(layer, frameNo);
|
||||
break;
|
||||
}
|
||||
case LottieLayer::Solid: {
|
||||
|
|
|
@ -139,6 +139,7 @@ void LottieGroup::prepare(LottieObject::Type type)
|
|||
if (children.count == 0) return;
|
||||
|
||||
size_t strokeCnt = 0;
|
||||
size_t fillCnt = 0;
|
||||
|
||||
for (auto c = children.end() - 1; c >= children.data; --c) {
|
||||
if (reqFragment && !statical) break;
|
||||
|
@ -148,10 +149,15 @@ void LottieGroup::prepare(LottieObject::Type type)
|
|||
Multiple stroking or grouping with a stroking would occur this.
|
||||
This fragment resolves the overlapped stroke outlines. */
|
||||
if (reqFragment) continue;
|
||||
if (child->type == LottieObject::SolidStroke || child->type == LottieObject::GradientStroke) {
|
||||
if (child->type == LottieObject::Group) {
|
||||
if (strokeCnt > 0 || fillCnt > 0) reqFragment = true;
|
||||
} else if (child->type == LottieObject::SolidStroke || child->type == LottieObject::GradientStroke) {
|
||||
if (strokeCnt > 0) reqFragment = true;
|
||||
else ++strokeCnt;
|
||||
} else if (child->type == LottieObject::Group && strokeCnt > 0) reqFragment = true;
|
||||
} else if (child->type == LottieObject::SolidFill || child->type == LottieObject::GradientFill) {
|
||||
if (fillCnt > 0) reqFragment = true;
|
||||
else ++fillCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue