diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index fd0db10a..ca707e9f 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -488,6 +488,13 @@ void LottieBuilder::updatePath(LottieGroup* parent, LottieObject** child, float } +static void _close(Array& pts, const Point& p, bool round) +{ + if (round && tvg::zero(pts.last() - pts[pts.count - 2])) pts[pts.count - 2] = p; + pts.last() = p; +} + + void LottieBuilder::updateStar(LottiePolyStar* star, float frameNo, Matrix* transform, Shape* merging, RenderContext* ctx, Tween& tween, LottieExpressions* exps) { static constexpr auto POLYSTAR_MAGIC_NUMBER = 0.47829f / 0.28f; @@ -595,6 +602,8 @@ void LottieBuilder::updateStar(LottiePolyStar* star, float frameNo, Matrix* tran angle += dTheta * direction; longSegment = !longSegment; } + //ensure proper shape closure - important for modifiers that behave differently for degenerate (linear) vs curved cubics + _close(SHAPE(shape)->rs.path.pts, in, hasRoundness); shape->close(); if (ctx->modifier) ctx->modifier->modifyPolystar(SHAPE(shape)->rs.path, SHAPE(merging)->rs.path, outerRoundness, hasRoundness); @@ -663,6 +672,8 @@ void LottieBuilder::updatePolygon(LottieGroup* parent, LottiePolyStar* star, flo } angle += anglePerPoint * direction; } + //ensure proper shape closure - important for modifiers that behave differently for degenerate (linear) vs curved cubics + _close(SHAPE(shape)->rs.path.pts, in, hasRoundness); shape->close(); if (ctx->modifier) ctx->modifier->modifyPolystar(SHAPE(shape)->rs.path, SHAPE(merging)->rs.path, 0.0f, false); diff --git a/src/loaders/lottie/tvgLottieModifier.cpp b/src/loaders/lottie/tvgLottieModifier.cpp index ed14d062..de72fc98 100644 --- a/src/loaders/lottie/tvgLottieModifier.cpp +++ b/src/loaders/lottie/tvgLottieModifier.cpp @@ -52,16 +52,9 @@ static void _roundCorner(Array& cmds, Array& pts, Point& pre } -static bool _zero(Point& p1, Point& p2) -{ - constexpr float epsilon = 1e-3f; - return fabsf(p1.x / p2.x - 1.0f) < epsilon && fabsf(p1.y / p2.y - 1.0f) < epsilon; -} - - static bool _intersect(Line& line1, Line& line2, Point& intersection, bool& inside) { - if (_zero(line1.pt2, line2.pt1)) { + if (tvg::zero(line1.pt2 - line2.pt1)) { intersection = line1.pt2; inside = true; return true; @@ -168,7 +161,7 @@ void LottieOffsetModifier::line(RenderPath& out, PathCommand* inCmds, uint32_t i Line nextLine = state.firstLine; if (inCmds[curCmd + 1] == PathCommand::LineTo) nextLine = _offset(inPts[curPt + degenerated], inPts[curPt + 1 + degenerated], offset); else if (inCmds[curCmd + 1] == PathCommand::CubicTo) nextLine = _offset(inPts[curPt + 1 + degenerated], inPts[curPt + 2 + degenerated], offset); - else if (inCmds[curCmd + 1] == PathCommand::Close && !_zero(inPts[curPt + degenerated], inPts[state.movetoInIndex + degenerated])) + else if (inCmds[curCmd + 1] == PathCommand::Close && !tvg::zero(inPts[curPt + degenerated] - inPts[state.movetoInIndex + degenerated])) nextLine = _offset(inPts[curPt + degenerated], inPts[state.movetoInIndex + degenerated], offset); corner(out, state.line, nextLine, state.movetoOutIndex, inCmds[curCmd + 1] == PathCommand::Close); @@ -386,7 +379,7 @@ bool LottieOffsetModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, P iPt += 3; } else { - if (!_zero(inPts[iPt - 1], inPts[state.movetoInIndex])) { + if (!tvg::zero(inPts[iPt - 1] - inPts[state.movetoInIndex])) { out.cmds.push(PathCommand::LineTo); corner(out, state.line, state.firstLine, state.movetoOutIndex, true); }