diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index e1549415..efa3e44e 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -897,7 +897,7 @@ static void _updateTrimpath(TVG_UNUSED LottieGroup* parent, LottieObject** child end = (length * end) + pbegin; } - P(ctx->propagator)->strokeTrim(begin, end); + P(ctx->propagator)->strokeTrim(begin, end, false); //TODO: individual or simultaenous mode } diff --git a/src/renderer/sw_engine/tvgSwShape.cpp b/src/renderer/sw_engine/tvgSwShape.cpp index c5436fde..9de61888 100644 --- a/src/renderer/sw_engine/tvgSwShape.cpp +++ b/src/renderer/sw_engine/tvgSwShape.cpp @@ -105,6 +105,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans if (mathZero(len)) { _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + //draw the current line fully } else if (len < dash.curLen) { dash.curLen -= len; if (!dash.curOpGap) { @@ -114,6 +115,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans } _outlineLineTo(*dash.outline, to, transform); } + //draw the current line partially } else { while (len - dash.curLen > 0.0001f) { Line left, right; @@ -162,6 +164,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct Bezier cur = {dash.ptCur, *ctrl1, *ctrl2, *to}; auto len = bezLength(cur); + //draw the current line fully if (mathZero(len)) { _outlineMoveTo(*dash.outline, &dash.ptCur, transform); } else if (len < dash.curLen) { @@ -173,6 +176,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct } _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform); } + //draw the current line partially } else { while ((len - dash.curLen) > 0.0001f) { Bezier left, right; @@ -222,7 +226,15 @@ static void _dashClose(SwDashStroke& dash, const Matrix* transform) } -static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts, const Matrix* transform) +static void _dashMoveTo(SwDashStroke& dash, const Point* pts) +{ + dash.ptCur = *pts; + dash.ptStart = *pts; + dash.move = true; +} + + +static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts) { dash.curIdx = offIdx % dash.cnt; dash.curLen = dash.pattern[dash.curIdx] - offset; @@ -257,7 +269,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans //default if (end > begin) { - if (begin > 0) dash.cnt += 4; + if (begin > 0.0f) dash.cnt += 4; else dash.cnt += 2; //looping } else dash.cnt += 3; @@ -275,7 +287,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans dash.pattern[0] = 0; //zero dash to start with a space. dash.pattern[1] = begin; dash.pattern[2] = end - begin; - dash.pattern[3] = length - (end - begin); + dash.pattern[3] = length - end; } trimmed = true; @@ -304,14 +316,22 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans dash.outline = mpoolReqDashOutline(mpool, tid); - while (cmdCnt-- > 0) { + //must begin with moveTo + if (cmds[0] == PathCommand::MoveTo) { + _dashMoveTo(dash, offIdx, offset, pts); + cmds++; + pts++; + } + + while (--cmdCnt > 0) { switch (*cmds) { case PathCommand::Close: { _dashClose(dash, transform); break; } case PathCommand::MoveTo: { - _dashMoveTo(dash, offIdx, offset, pts, transform); + if (rshape->stroke->trim.individual) _dashMoveTo(dash, pts); + else _dashMoveTo(dash, offIdx, offset, pts); ++pts; break; } @@ -349,13 +369,19 @@ static float _outlineLength(const RenderShape* rshape) const Point* close = nullptr; auto length = 0.0f; + auto slength = 0.0f; + auto simutaneous = !rshape->stroke->trim.individual; //Compute the whole length while (cmdCnt-- > 0) { switch (*cmds) { case PathCommand::Close: { length += mathLength(pts - 1, close); - ++pts; + //retrieve the max length of the shape if the simultaneous mode. + if (simutaneous && slength < length) { + slength = length; + length = 0.0f; + } break; } case PathCommand::MoveTo: { @@ -376,7 +402,8 @@ static float _outlineLength(const RenderShape* rshape) } ++cmds; } - return length; + if (simutaneous && slength > length) return slength; + else return length; } diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index 9bc785e7..0caccd16 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -161,6 +161,7 @@ struct RenderStroke struct { float begin = 0.0f; float end = 1.0f; + bool individual = false; } trim; ~RenderStroke() diff --git a/src/renderer/tvgShape.h b/src/renderer/tvgShape.h index f45ed7a3..6d34511b 100644 --- a/src/renderer/tvgShape.h +++ b/src/renderer/tvgShape.h @@ -203,7 +203,7 @@ struct Shape::Impl return true; } - bool strokeTrim(float begin, float end) + bool strokeTrim(float begin, float end, bool individual) { if (!rs.stroke) { if (begin == 0.0f && end == 1.0f) return true; @@ -214,6 +214,7 @@ struct Shape::Impl rs.stroke->trim.begin = begin; rs.stroke->trim.end = end; + rs.stroke->trim.individual = individual; flag |= RenderUpdateFlag::Stroke; return true;