diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index c0cd8863..c6dcf79a 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -205,6 +205,7 @@ struct SwDashStroke float* pattern = nullptr; uint32_t cnt = 0; bool curOpGap = false; + bool move = true; }; struct SwShape diff --git a/src/renderer/sw_engine/tvgSwShape.cpp b/src/renderer/sw_engine/tvgSwShape.cpp index 159898c7..4f66cdac 100644 --- a/src/renderer/sw_engine/tvgSwShape.cpp +++ b/src/renderer/sw_engine/tvgSwShape.cpp @@ -121,7 +121,10 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans if (len < dash.curLen) { dash.curLen -= len; if (!dash.curOpGap) { - _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + if (dash.move) { + _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + dash.move = false; + } _outlineLineTo(*dash.outline, to, transform); } } else { @@ -131,7 +134,10 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans len -= dash.curLen; _lineSplitAt(cur, dash.curLen, left, right); if (!dash.curOpGap) { - _outlineMoveTo(*dash.outline, &left.pt1, transform); + if (dash.move || dash.pattern[dash.curIdx] - dash.curLen < FLT_EPSILON) { + _outlineMoveTo(*dash.outline, &left.pt1, transform); + dash.move = false; + } _outlineLineTo(*dash.outline, &left.pt2, transform); } } else { @@ -142,11 +148,15 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans dash.curOpGap = !dash.curOpGap; cur = right; dash.ptCur = cur.pt1; + dash.move = true; } //leftovers dash.curLen -= len; if (!dash.curOpGap) { - _outlineMoveTo(*dash.outline, &cur.pt1, transform); + if (dash.move) { + _outlineMoveTo(*dash.outline, &cur.pt1, transform); + dash.move = false; + } _outlineLineTo(*dash.outline, &cur.pt2, transform); } if (dash.curLen < 1 && TO_SWCOORD(len) > 1) { @@ -168,21 +178,22 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct if (len < dash.curLen) { dash.curLen -= len; if (!dash.curOpGap) { - _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + if (dash.move) { + _outlineMoveTo(*dash.outline, &dash.ptCur, transform); + dash.move = false; + } _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform); } } else { - bool begin = true; //starting with move_to while (len > dash.curLen) { Bezier left, right; if (dash.curLen > 0) { len -= dash.curLen; bezSplitAt(cur, dash.curLen, left, right); if (!dash.curOpGap) { - // leftovers from a previous command don't require moveTo - if (begin || dash.pattern[dash.curIdx] - dash.curLen < FLT_EPSILON) { + if (dash.move || dash.pattern[dash.curIdx] - dash.curLen < FLT_EPSILON) { _outlineMoveTo(*dash.outline, &left.start, transform); - begin = false; + dash.move = false; } _outlineCubicTo(*dash.outline, &left.ctrl1, &left.ctrl2, &left.end, transform); } @@ -194,11 +205,15 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct dash.curOpGap = !dash.curOpGap; cur = right; dash.ptCur = right.start; + dash.move = true; } //leftovers dash.curLen -= len; if (!dash.curOpGap) { - _outlineMoveTo(*dash.outline, &cur.start, transform); + if (dash.move) { + _outlineMoveTo(*dash.outline, &cur.start, transform); + dash.move = false; + } _outlineCubicTo(*dash.outline, &cur.ctrl1, &cur.ctrl2, &cur.end, transform); } if (dash.curLen < 1 && TO_SWCOORD(len) > 1) { @@ -212,6 +227,22 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct } +static void _dashClose(SwDashStroke& dash, const Matrix* transform) +{ + _dashLineTo(dash, &dash.ptStart, transform); +} + + +static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts, const Matrix* transform) +{ + dash.curIdx = offIdx % dash.cnt; + dash.curLen = dash.pattern[dash.curIdx] - offset; + dash.curOpGap = offIdx % 2; + dash.ptStart = dash.ptCur = *pts; + dash.move = true; +} + + static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* transform, float length, SwMpool* mpool, unsigned tid) { const PathCommand* cmds = rshape->path.cmds.data; @@ -261,7 +292,6 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans trimmed = true; //just a dasy style. } else { - if (dash.cnt == 0) return nullptr; } @@ -303,15 +333,11 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans while (cmdCnt-- > 0) { switch (*cmds) { case PathCommand::Close: { - _dashLineTo(dash, &dash.ptStart, transform); + _dashClose(dash, transform); break; } case PathCommand::MoveTo: { - //reset the dash - dash.curIdx = offIdx % dash.cnt; - dash.curLen = dash.pattern[dash.curIdx] - offset; - dash.curOpGap = offIdx % 2; - dash.ptStart = dash.ptCur = *pts; + _dashMoveTo(dash, offIdx, offset, pts, transform); ++pts; break; } diff --git a/src/renderer/sw_engine/tvgSwStroke.cpp b/src/renderer/sw_engine/tvgSwStroke.cpp index b1bdccbb..75c5fa56 100644 --- a/src/renderer/sw_engine/tvgSwStroke.cpp +++ b/src/renderer/sw_engine/tvgSwStroke.cpp @@ -689,7 +689,6 @@ static void _endSubPath(SwStroke& stroke) //No specific corner processing is required if the turn is 0 if (turn != 0) { - //when we turn to the right, the inside is 0 int32_t inside = 0;