mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +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 first = 0; //index of first point in contour
|
||||
|
@ -721,8 +721,6 @@ static bool _decomposeOutline(RleWorker& rw)
|
|||
auto types = outline->types.data + first;
|
||||
|
||||
/* 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]));
|
||||
|
||||
while (pt < limit) {
|
||||
|
@ -734,9 +732,6 @@ static bool _decomposeOutline(RleWorker& rw)
|
|||
_lineTo(rw, UPSCALE(*pt));
|
||||
//types cubic
|
||||
} else {
|
||||
if (pt + 1 > limit || types[1] != SW_CURVE_TYPE_CUBIC)
|
||||
goto invalid_outline;
|
||||
|
||||
pt += 2;
|
||||
types += 2;
|
||||
|
||||
|
@ -752,22 +747,15 @@ static bool _decomposeOutline(RleWorker& rw)
|
|||
close:
|
||||
first = last + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
invalid_outline:
|
||||
TVGERR("SW_ENGINE", "Invalid Outline!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int _genRle(RleWorker& rw)
|
||||
{
|
||||
if (setjmp(rw.jmpBuf) == 0) {
|
||||
auto ret = _decomposeOutline(rw);
|
||||
_decomposeOutline(rw);
|
||||
if (!rw.invalid) _recordCell(rw);
|
||||
if (ret) return 0; //success
|
||||
else return 1; //fail
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
|
||||
border->ptsCnt += 3;
|
||||
|
||||
border->movable = false;
|
||||
}
|
||||
|
||||
|
@ -193,7 +192,6 @@ static void _borderLineTo(SwStrokeBorder* border, const SwPoint& to, bool movabl
|
|||
//move last point
|
||||
border->pts[border->ptsCnt - 1] = to;
|
||||
} else {
|
||||
|
||||
//don't add zero-length line_to
|
||||
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)
|
||||
{
|
||||
/* if all control points are coincident, this is a no-op;
|
||||
avoid creating a spurious corner */
|
||||
//if all control points are coincident, this is a no-op; avoid creating a spurious corner
|
||||
if ((stroke.center - ctrl1).small() && (ctrl1 - ctrl2).small() && (ctrl2 - to).small()) {
|
||||
stroke.center = to;
|
||||
return;
|
||||
|
@ -497,8 +494,7 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
|||
auto border = stroke.borders;
|
||||
int32_t side = 0;
|
||||
|
||||
while (side <= 1)
|
||||
{
|
||||
while (side < 2) {
|
||||
auto rotate = SIDE_TO_ROTATE(side);
|
||||
|
||||
//compute control points
|
||||
|
@ -519,7 +515,6 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
|||
_end += arc[0];
|
||||
|
||||
if (stroke.handleWideStrokes) {
|
||||
|
||||
/* determine whether the border radius is greater than the radius of
|
||||
curvature of the original arc */
|
||||
auto _start = border->pts[border->ptsCnt - 1];
|
||||
|
@ -554,8 +549,6 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
|
|||
++border;
|
||||
continue;
|
||||
}
|
||||
|
||||
//else fall through
|
||||
}
|
||||
_borderCubicTo(border, _ctrl1, _ctrl2, _end);
|
||||
++side;
|
||||
|
@ -651,7 +644,6 @@ static void _addReverseLeft(SwStroke& stroke, bool opened)
|
|||
if (ttag == SW_STROKE_TAG_BEGIN || ttag == SW_STROKE_TAG_END)
|
||||
dstTag[0] ^= (SW_STROKE_TAG_BEGIN | SW_STROKE_TAG_END);
|
||||
}
|
||||
|
||||
--srcPt;
|
||||
--srcTag;
|
||||
++dstPt;
|
||||
|
@ -777,8 +769,7 @@ fail:
|
|||
static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uint32_t side)
|
||||
{
|
||||
auto border = stroke.borders + side;
|
||||
|
||||
if (border->ptsCnt == 0) return; //invalid border
|
||||
if (border->ptsCnt == 0) return;
|
||||
|
||||
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) {
|
||||
if (*src & SW_STROKE_TAG_POINT) *tags = SW_CURVE_TYPE_POINT;
|
||||
else if (*src & SW_STROKE_TAG_CUBIC) *tags = SW_CURVE_TYPE_CUBIC;
|
||||
else {
|
||||
//LOG: What type of stroke outline??
|
||||
}
|
||||
|
||||
else TVGERR("SW_ENGINE", "Invalid stroke tag was given! = %d", *src);
|
||||
if (*src & SW_STROKE_TAG_END) outline->cntrs.push(idx);
|
||||
|
||||
++src;
|
||||
++tags;
|
||||
++idx;
|
||||
|
@ -899,7 +886,6 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline)
|
|||
goto close;
|
||||
}
|
||||
}
|
||||
|
||||
close:
|
||||
if (!stroke->firstPt) _endSubPath(*stroke);
|
||||
first = last + 1;
|
||||
|
|
Loading…
Add table
Reference in a new issue