From f93fbc9e59e6ca64ddd7dd423fa8b221086d48a1 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 27 Jul 2023 00:23:34 +0900 Subject: [PATCH] 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. --- src/lib/sw_engine/tvgSwRle.cpp | 18 +++--------------- src/lib/sw_engine/tvgSwStroke.cpp | 22 ++++------------------ 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index a3982622..9b6ef4c6 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -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 } diff --git a/src/lib/sw_engine/tvgSwStroke.cpp b/src/lib/sw_engine/tvgSwStroke.cpp index 0367b2fb..38626cb4 100644 --- a/src/lib/sw_engine/tvgSwStroke.cpp +++ b/src/lib/sw_engine/tvgSwStroke.cpp @@ -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;