sw_engine: ++stability

cut the Bezier curve based on the number of points
and transform it into a straight line when it's very small.

issue: https://github.com/thorvg/thorvg/issues/2759
This commit is contained in:
Hermet Park 2024-10-03 16:26:16 +09:00 committed by Hermet Park
parent d3af7a5cb0
commit b868503033
2 changed files with 17 additions and 27 deletions

View file

@ -690,31 +690,27 @@ static void _decomposeOutline(RleWorker& rw)
auto start = UPSCALE(outline->pts[first]); auto start = UPSCALE(outline->pts[first]);
auto pt = outline->pts.data + first; auto pt = outline->pts.data + first;
auto types = outline->types.data + first; auto types = outline->types.data + first;
++types;
_moveTo(rw, UPSCALE(outline->pts[first])); _moveTo(rw, UPSCALE(outline->pts[first]));
while (pt < limit) { while (pt < limit) {
++pt;
++types;
//emit a single line_to //emit a single line_to
if (types[0] == SW_CURVE_TYPE_POINT) { if (types[0] == SW_CURVE_TYPE_POINT) {
++pt;
++types;
_lineTo(rw, UPSCALE(*pt)); _lineTo(rw, UPSCALE(*pt));
//types cubic //types cubic
} else { } else {
pt += 2; pt += 3;
types += 2; types += 3;
if (pt <= limit) _cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), UPSCALE(pt[0]));
if (pt <= limit) { else if (pt - 1 == limit) _cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), start);
_cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), UPSCALE(pt[0])); else goto close;
continue;
}
_cubicTo(rw, UPSCALE(pt[-2]), UPSCALE(pt[-1]), start);
goto close;
} }
} }
_lineTo(rw, start);
close: close:
_lineTo(rw, start);
first = last + 1; first = last + 1;
} }
} }

View file

@ -845,31 +845,25 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline)
//A contour cannot start with a cubic control point //A contour cannot start with a cubic control point
if (type == SW_CURVE_TYPE_CUBIC) return false; if (type == SW_CURVE_TYPE_CUBIC) return false;
++types;
auto closed = outline.closed.data ? outline.closed.data[i]: false; auto closed = outline.closed.data ? outline.closed.data[i]: false;
_beginSubPath(*stroke, start, closed); _beginSubPath(*stroke, start, closed);
while (pt < limit) { while (pt < limit) {
++pt;
++types;
//emit a single line_to //emit a single line_to
if (types[0] == SW_CURVE_TYPE_POINT) { if (types[0] == SW_CURVE_TYPE_POINT) {
++pt;
++types;
_lineTo(*stroke, *pt); _lineTo(*stroke, *pt);
//types cubic //types cubic
} else { } else {
if (pt + 1 > limit || types[1] != SW_CURVE_TYPE_CUBIC) return false; pt += 3;
types += 3;
pt += 2; if (pt <= limit) _cubicTo(*stroke, pt[-2], pt[-1], pt[0]);
types += 2; else if (pt - 1 == limit) _cubicTo(*stroke, pt[-2], pt[-1], start);
else goto close;
if (pt <= limit) {
_cubicTo(*stroke, pt[-2], pt[-1], pt[0]);
continue;
}
_cubicTo(*stroke, pt[-2], pt[-1], start);
goto close;
} }
} }
close: close: