mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 20:14:37 +00:00
sw_engine: enforce the drawing of small stroke cubic outlines.
At the construction stage, some stroke points can be skipped if the distance between the points is too narrow. Previously, this was assumed to be an error case, but it's clearly intended to remove unnecessary points introduced in a small area of drawing. This sometimes leads to a flickering issue when super small-sized vector images are drawn. Now, it's fixed.
This commit is contained in:
parent
739bb63f92
commit
f93fbc9e59
2 changed files with 7 additions and 33 deletions
|
@ -708,7 +708,7 @@ static void _cubicTo(RleWorker& rw, const SwPoint& ctrl1, const SwPoint& ctrl2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _decomposeOutline(RleWorker& rw)
|
static void _decomposeOutline(RleWorker& rw)
|
||||||
{
|
{
|
||||||
auto outline = rw.outline;
|
auto outline = rw.outline;
|
||||||
auto first = 0; //index of first point in contour
|
auto first = 0; //index of first point in contour
|
||||||
|
@ -721,8 +721,6 @@ static bool _decomposeOutline(RleWorker& rw)
|
||||||
auto types = outline->types.data + first;
|
auto types = outline->types.data + first;
|
||||||
|
|
||||||
/* A contour cannot start with a cubic control point! */
|
/* A contour cannot start with a cubic control point! */
|
||||||
if (types[0] == SW_CURVE_TYPE_CUBIC) goto invalid_outline;
|
|
||||||
|
|
||||||
_moveTo(rw, UPSCALE(outline->pts.data[first]));
|
_moveTo(rw, UPSCALE(outline->pts.data[first]));
|
||||||
|
|
||||||
while (pt < limit) {
|
while (pt < limit) {
|
||||||
|
@ -734,9 +732,6 @@ static bool _decomposeOutline(RleWorker& rw)
|
||||||
_lineTo(rw, UPSCALE(*pt));
|
_lineTo(rw, UPSCALE(*pt));
|
||||||
//types cubic
|
//types cubic
|
||||||
} else {
|
} else {
|
||||||
if (pt + 1 > limit || types[1] != SW_CURVE_TYPE_CUBIC)
|
|
||||||
goto invalid_outline;
|
|
||||||
|
|
||||||
pt += 2;
|
pt += 2;
|
||||||
types += 2;
|
types += 2;
|
||||||
|
|
||||||
|
@ -752,22 +747,15 @@ static bool _decomposeOutline(RleWorker& rw)
|
||||||
close:
|
close:
|
||||||
first = last + 1;
|
first = last + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
invalid_outline:
|
|
||||||
TVGERR("SW_ENGINE", "Invalid Outline!");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _genRle(RleWorker& rw)
|
static int _genRle(RleWorker& rw)
|
||||||
{
|
{
|
||||||
if (setjmp(rw.jmpBuf) == 0) {
|
if (setjmp(rw.jmpBuf) == 0) {
|
||||||
auto ret = _decomposeOutline(rw);
|
_decomposeOutline(rw);
|
||||||
if (!rw.invalid) _recordCell(rw);
|
if (!rw.invalid) _recordCell(rw);
|
||||||
if (ret) return 0; //success
|
return 0;
|
||||||
else return 1; //fail
|
|
||||||
}
|
}
|
||||||
return -1; //lack of cell memory
|
return -1; //lack of cell memory
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,6 @@ static void _borderCubicTo(SwStrokeBorder* border, const SwPoint& ctrl1, const S
|
||||||
tag[2] = SW_STROKE_TAG_POINT;
|
tag[2] = SW_STROKE_TAG_POINT;
|
||||||
|
|
||||||
border->ptsCnt += 3;
|
border->ptsCnt += 3;
|
||||||
|
|
||||||
border->movable = false;
|
border->movable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +192,6 @@ static void _borderLineTo(SwStrokeBorder* border, const SwPoint& to, bool movabl
|
||||||
//move last point
|
//move last point
|
||||||
border->pts[border->ptsCnt - 1] = to;
|
border->pts[border->ptsCnt - 1] = to;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//don't add zero-length line_to
|
//don't add zero-length line_to
|
||||||
if (border->ptsCnt > 0 && (border->pts[border->ptsCnt - 1] - to).small()) return;
|
if (border->ptsCnt > 0 && (border->pts[border->ptsCnt - 1] - to).small()) return;
|
||||||
|
|
||||||
|
@ -430,8 +428,7 @@ static void _lineTo(SwStroke& stroke, const SwPoint& to)
|
||||||
|
|
||||||
static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to)
|
static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl2, const SwPoint& to)
|
||||||
{
|
{
|
||||||
/* if all control points are coincident, this is a no-op;
|
//if all control points are coincident, this is a no-op; avoid creating a spurious corner
|
||||||
avoid creating a spurious corner */
|
|
||||||
if ((stroke.center - ctrl1).small() && (ctrl1 - ctrl2).small() && (ctrl2 - to).small()) {
|
if ((stroke.center - ctrl1).small() && (ctrl1 - ctrl2).small() && (ctrl2 - to).small()) {
|
||||||
stroke.center = to;
|
stroke.center = to;
|
||||||
return;
|
return;
|
||||||
|
@ -497,8 +494,7 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
||||||
auto border = stroke.borders;
|
auto border = stroke.borders;
|
||||||
int32_t side = 0;
|
int32_t side = 0;
|
||||||
|
|
||||||
while (side <= 1)
|
while (side < 2) {
|
||||||
{
|
|
||||||
auto rotate = SIDE_TO_ROTATE(side);
|
auto rotate = SIDE_TO_ROTATE(side);
|
||||||
|
|
||||||
//compute control points
|
//compute control points
|
||||||
|
@ -519,7 +515,6 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
||||||
_end += arc[0];
|
_end += arc[0];
|
||||||
|
|
||||||
if (stroke.handleWideStrokes) {
|
if (stroke.handleWideStrokes) {
|
||||||
|
|
||||||
/* determine whether the border radius is greater than the radius of
|
/* determine whether the border radius is greater than the radius of
|
||||||
curvature of the original arc */
|
curvature of the original arc */
|
||||||
auto _start = border->pts[border->ptsCnt - 1];
|
auto _start = border->pts[border->ptsCnt - 1];
|
||||||
|
@ -554,8 +549,6 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
||||||
++border;
|
++border;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//else fall through
|
|
||||||
}
|
}
|
||||||
_borderCubicTo(border, _ctrl1, _ctrl2, _end);
|
_borderCubicTo(border, _ctrl1, _ctrl2, _end);
|
||||||
++side;
|
++side;
|
||||||
|
@ -651,7 +644,6 @@ static void _addReverseLeft(SwStroke& stroke, bool opened)
|
||||||
if (ttag == SW_STROKE_TAG_BEGIN || ttag == SW_STROKE_TAG_END)
|
if (ttag == SW_STROKE_TAG_BEGIN || ttag == SW_STROKE_TAG_END)
|
||||||
dstTag[0] ^= (SW_STROKE_TAG_BEGIN | SW_STROKE_TAG_END);
|
dstTag[0] ^= (SW_STROKE_TAG_BEGIN | SW_STROKE_TAG_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
--srcPt;
|
--srcPt;
|
||||||
--srcTag;
|
--srcTag;
|
||||||
++dstPt;
|
++dstPt;
|
||||||
|
@ -777,8 +769,7 @@ fail:
|
||||||
static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uint32_t side)
|
static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uint32_t side)
|
||||||
{
|
{
|
||||||
auto border = stroke.borders + side;
|
auto border = stroke.borders + side;
|
||||||
|
if (border->ptsCnt == 0) return;
|
||||||
if (border->ptsCnt == 0) return; //invalid border
|
|
||||||
|
|
||||||
memcpy(outline->pts.data + outline->pts.count, border->pts, border->ptsCnt * sizeof(SwPoint));
|
memcpy(outline->pts.data + outline->pts.count, border->pts, border->ptsCnt * sizeof(SwPoint));
|
||||||
|
|
||||||
|
@ -790,12 +781,8 @@ static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uin
|
||||||
while (cnt > 0) {
|
while (cnt > 0) {
|
||||||
if (*src & SW_STROKE_TAG_POINT) *tags = SW_CURVE_TYPE_POINT;
|
if (*src & SW_STROKE_TAG_POINT) *tags = SW_CURVE_TYPE_POINT;
|
||||||
else if (*src & SW_STROKE_TAG_CUBIC) *tags = SW_CURVE_TYPE_CUBIC;
|
else if (*src & SW_STROKE_TAG_CUBIC) *tags = SW_CURVE_TYPE_CUBIC;
|
||||||
else {
|
else TVGERR("SW_ENGINE", "Invalid stroke tag was given! = %d", *src);
|
||||||
//LOG: What type of stroke outline??
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*src & SW_STROKE_TAG_END) outline->cntrs.push(idx);
|
if (*src & SW_STROKE_TAG_END) outline->cntrs.push(idx);
|
||||||
|
|
||||||
++src;
|
++src;
|
||||||
++tags;
|
++tags;
|
||||||
++idx;
|
++idx;
|
||||||
|
@ -899,7 +886,6 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline)
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close:
|
close:
|
||||||
if (!stroke->firstPt) _endSubPath(*stroke);
|
if (!stroke->firstPt) _endSubPath(*stroke);
|
||||||
first = last + 1;
|
first = last + 1;
|
||||||
|
|
Loading…
Add table
Reference in a new issue