diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 68fa43df..935f3b5b 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -236,15 +236,16 @@ void LottieTrimpath::segment(float frameNo, float& start, float& end, Tween& twe end = 0.0f; return; } - if (tvg::equal(diff, 1.0f) || tvg::equal(diff, 2.0f)) { + + //Even if the start and end values do not cause trimming, an offset > 0 can still affect dashing starting point + auto o = fmodf(this->offset(frameNo, tween, exps), 360.0f) / 360.0f; //0 ~ 1 + if (tvg::zero(o) && diff >= 1.0f) { start = 0.0f; end = 1.0f; return; } if (start > end) std::swap(start, end); - - auto o = fmodf(this->offset(frameNo, tween, exps), 360.0f) / 360.0f; //0 ~ 1 start += o; end += o; } diff --git a/src/renderer/tvgShape.h b/src/renderer/tvgShape.h index 3ed2aca7..0a504abb 100644 --- a/src/renderer/tvgShape.h +++ b/src/renderer/tvgShape.h @@ -211,10 +211,8 @@ struct Shape::Impl : Paint::Impl void strokeTrim(float begin, float end, bool simultaneous) { - if (fabsf(end - begin) >= 1.0f) { - begin = 0.0f; - end = 1.0f; - } + //Even if there is no trimming effect, begin can still affect dashing starting point + if (fabsf(end - begin) >= 1.0f) end = begin + 1.0f; if (!rs.stroke) { if (begin == 0.0f && end == 1.0f) return; diff --git a/src/renderer/tvgTrimPath.cpp b/src/renderer/tvgTrimPath.cpp index 120a67a7..4cf46083 100644 --- a/src/renderer/tvgTrimPath.cpp +++ b/src/renderer/tvgTrimPath.cpp @@ -162,7 +162,7 @@ static void _add(const PathCommand* cmds, const Point* pts, const Point& moveTo, } -static void _trimPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, TVG_UNUSED uint32_t inPtsCnt, float trimStart, float trimEnd, RenderPath& out) +static void _trimPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, TVG_UNUSED uint32_t inPtsCnt, float trimStart, float trimEnd, RenderPath& out, bool connect = false) { auto cmds = const_cast(inCmds); auto pts = const_cast(inPts); @@ -203,7 +203,7 @@ static void _trimPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point ++cmds; }; - bool start = true; + auto start = !connect; for (uint32_t i = 0; i < inCmdsCnt; ++i) { auto dLen = _length(); @@ -234,15 +234,18 @@ static void _trimPath(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point } -static void _trim(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, float begin, float end, RenderPath& out) +static void _trim(const PathCommand* inCmds, uint32_t inCmdsCnt, const Point* inPts, uint32_t inPtsCnt, float begin, float end, bool connect, RenderPath& out) { auto totalLength = _pathLength(inCmds, inCmdsCnt, inPts, inPtsCnt); auto trimStart = begin * totalLength; auto trimEnd = end * totalLength; - if (trimStart > trimEnd) { + if (fabsf(begin - end) < EPSILON) { _trimPath(inCmds, inCmdsCnt, inPts, inPtsCnt, trimStart, totalLength, out); - _trimPath(inCmds, inCmdsCnt, inPts, inPtsCnt, 0.0f, trimEnd, out); + _trimPath(inCmds, inCmdsCnt, inPts, inPtsCnt, 0.0f, trimStart, out, connect); + } else if (begin > end) { + _trimPath(inCmds, inCmdsCnt, inPts, inPtsCnt, trimStart, totalLength, out); + _trimPath(inCmds, inCmdsCnt, inPts, inPtsCnt, 0.0f, trimEnd, out, connect); } else { _trimPath(inCmds, inCmdsCnt, inPts, inPtsCnt, trimStart, trimEnd, out); } @@ -280,11 +283,11 @@ bool TrimPath::valid() const bool TrimPath::trim(const RenderPath& in, RenderPath& out) const { + if (in.pts.count < 2 || tvg::zero(begin - end)) return false; + float begin = this->begin, end = this->end; _get(begin, end); - if (in.pts.count < 2 || tvg::zero(begin - end)) return false; - out.cmds.reserve(in.cmds.count * 2); out.pts.reserve(in.pts.count * 2); @@ -298,7 +301,7 @@ bool TrimPath::trim(const RenderPath& in, RenderPath& out) const while (i < in.cmds.count) { switch (in.cmds[i]) { case PathCommand::MoveTo: { - if (startCmds != cmds) _trim(startCmds, cmds - startCmds, startPts, pts - startPts, begin, end, out); + if (startCmds != cmds) _trim(startCmds, cmds - startCmds, startPts, pts - startPts, begin, end, *(cmds - 1) == PathCommand::Close, out); startPts = pts; startCmds = cmds; ++pts; @@ -317,7 +320,7 @@ bool TrimPath::trim(const RenderPath& in, RenderPath& out) const } case PathCommand::Close: { ++cmds; - if (startCmds != cmds) _trim(startCmds, cmds - startCmds, startPts, pts - startPts, begin, end, out); + if (startCmds != cmds) _trim(startCmds, cmds - startCmds, startPts, pts - startPts, begin, end, *(cmds - 1) == PathCommand::Close, out); startPts = pts; startCmds = cmds; break; @@ -325,9 +328,9 @@ bool TrimPath::trim(const RenderPath& in, RenderPath& out) const } i++; } - if (startCmds != cmds) _trim(startCmds, cmds - startCmds, startPts, pts - startPts, begin, end, out); + if (startCmds != cmds) _trim(startCmds, cmds - startCmds, startPts, pts - startPts, begin, end, *(cmds - 1) == PathCommand::Close, out); } else { - _trim(in.cmds.data, in.cmds.count, in.pts.data, in.pts.count, begin, end, out); + _trim(in.cmds.data, in.cmds.count, in.pts.data, in.pts.count, begin, end, false, out); } return out.pts.count >= 2;