mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
sw_engine/stroke: enhanced the quality of the dash line corners.
Previously, the engine didn't properly cover the dash line corner styles because it considered a new line to start at the corner. This update modifies the logic to recognize curved lines as a single line, including the corners. There may still be some quality issues, but it's an improvement over the previous version. @Issue: https://github.com/thorvg/thorvg/issues/121
This commit is contained in:
parent
12260198d1
commit
3d06d5552f
3 changed files with 43 additions and 17 deletions
|
@ -205,6 +205,7 @@ struct SwDashStroke
|
|||
float* pattern = nullptr;
|
||||
uint32_t cnt = 0;
|
||||
bool curOpGap = false;
|
||||
bool move = true;
|
||||
};
|
||||
|
||||
struct SwShape
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue