Use a smaller tolerance when chopping conics to quads
In most places we were using 0.25 (maximum distance between the actual and approximated curves). In these few places, we were using 0.5, which is enough to produce visible errors. Added a GM that demonstrated the problem as reported - many of the arcs with radius ~8 were previously closer to round-rects than circles. Bug: chromium:888453 Change-Id: I7d22e27773f56174861526dd0223f52a93bf48eb Reviewed-on: https://skia-review.googlesource.com/c/172060 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
343063f338
commit
e3deee1319
@ -233,3 +233,23 @@ DEF_SIMPLE_GM(onebadarc, canvas, 100, 100) {
|
||||
SkRect kRect = { 60, 0, 100, 40};
|
||||
canvas->drawArc(kRect, 45, 90, true, p0);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM(crbug_888453, canvas, 480, 150) {
|
||||
// Two GPU path renderers were using a too-large tolerance when chopping connics to quads.
|
||||
// This manifested as not-very-round circular arcs at certain radii. All the arcs being drawn
|
||||
// here should look like circles.
|
||||
SkPaint fill;
|
||||
fill.setAntiAlias(true);
|
||||
SkPaint hairline = fill;
|
||||
hairline.setStyle(SkPaint::kStroke_Style);
|
||||
SkPaint stroke = hairline;
|
||||
stroke.setStrokeWidth(2.0f);
|
||||
int x = 4;
|
||||
int y0 = 25, y1 = 75, y2 = 125;
|
||||
for (int r = 2; r <= 20; ++r) {
|
||||
canvas->drawArc(SkRect::MakeXYWH(x - r, y0 - r, 2 * r, 2 * r), 0, 360, false, fill);
|
||||
canvas->drawArc(SkRect::MakeXYWH(x - r, y1 - r, 2 * r, 2 * r), 0, 360, false, hairline);
|
||||
canvas->drawArc(SkRect::MakeXYWH(x - r, y2 - r, 2 * r, 2 * r), 0, 360, false, stroke);
|
||||
x += 2 * r + 4;
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ static bool get_segments(const SkPath& path,
|
||||
m.mapPoints(pts, 3);
|
||||
SkScalar weight = iter.conicWeight();
|
||||
SkAutoConicToQuads converter;
|
||||
const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.5f);
|
||||
const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.25f);
|
||||
for (int i = 0; i < converter.countQuads(); ++i) {
|
||||
update_degenerate_test(°enerateData, quadPts[2*i + 1]);
|
||||
update_degenerate_test(°enerateData, quadPts[2*i + 2]);
|
||||
|
@ -24,7 +24,7 @@ static const SkScalar kCloseSqd = kClose * kClose;
|
||||
// tesselation tolerance values, in device space pixels
|
||||
static const SkScalar kQuadTolerance = 0.2f;
|
||||
static const SkScalar kCubicTolerance = 0.2f;
|
||||
static const SkScalar kConicTolerance = 0.5f;
|
||||
static const SkScalar kConicTolerance = 0.25f;
|
||||
|
||||
// dot product below which we use a round cap between curve segments
|
||||
static const SkScalar kRoundCapThreshold = 0.8f;
|
||||
|
@ -318,7 +318,7 @@ static int gather_lines_and_quads(const SkPath& path,
|
||||
if (convertConicsToQuads) {
|
||||
SkScalar weight = iter.conicWeight();
|
||||
SkAutoConicToQuads converter;
|
||||
const SkPoint* quadPts = converter.computeQuads(pathPts, weight, 0.5f);
|
||||
const SkPoint* quadPts = converter.computeQuads(pathPts, weight, 0.25f);
|
||||
for (int i = 0; i < converter.countQuads(); ++i) {
|
||||
addSrcChoppedQuad(quadPts + 2 * i, !verbsInContour && 0 == i);
|
||||
}
|
||||
|
@ -725,7 +725,7 @@ void SkBaseShadowTessellator::stitchConcaveRings(const SkTDArray<SkPoint>& umbra
|
||||
static const SkScalar kQuadTolerance = 0.2f;
|
||||
static const SkScalar kCubicTolerance = 0.2f;
|
||||
#endif
|
||||
static const SkScalar kConicTolerance = 0.5f;
|
||||
static const SkScalar kConicTolerance = 0.25f;
|
||||
|
||||
// clamps the point to the nearest 16th of a pixel
|
||||
static void sanitize_point(const SkPoint& in, SkPoint* out) {
|
||||
|
Loading…
Reference in New Issue
Block a user