Fix bug in path clipping (chopping)

When trying to chop a quadratic along the right edge of a clip,
the computed t value was so close to 1.0 that our chopper method
returns false (we would have needed doubles to detect this).

To handle this, pin the X values to the right edge, so that we at least
maintain the contract that we are clipped.

Bug: 1070835
Change-Id: Ifdc59f97c7f5c32b321647f6739b37b33ce801c9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/285576
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2020-04-26 17:20:22 -04:00 committed by Skia Commit-Bot
parent b6130e919d
commit 1ae3e75a0b
2 changed files with 45 additions and 1 deletions

View File

@ -618,3 +618,45 @@ DEF_SIMPLE_GM(bug7792, canvas, 800, 800) {
path.close();
canvas->drawPath(path, p);
}
#include "include/core/SkSurface.h"
DEF_SIMPLE_GM(path_stroke_clip_crbug1070835, canvas, 25, 50) {
SkCanvas* orig = canvas;
auto surf = SkSurface::MakeRasterN32Premul(25, 25);
canvas = surf->getCanvas();
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(2);
canvas->scale(4.16666651f/2, 4.16666651f/2);
SkPath path;
SkPoint pts[] = {
{11, 12},
{11, 18.0751324f},
{6.07513189f, 23},
{-4.80825292E-7f, 23},
{-6.07513332f, 23},
{-11, 18.0751324f},
{-11, 11.999999f},
{-10.999999f, 5.92486763f},
{-6.07513189f, 1},
{1.31173692E-7f, 1},
{6.07513141f, 1},
{10.9999981f, 5.92486572f},
{11, 11.9999971f},
};
path.moveTo(pts[0]).cubicTo(pts[1], pts[2], pts[3])
.cubicTo(pts[4], pts[5], pts[6])
.cubicTo(pts[7], pts[8], pts[9])
.cubicTo(pts[10],pts[11],pts[12]);
canvas->drawPath(path, p);
surf->draw(orig, 0, 0, nullptr);
}

View File

@ -209,7 +209,9 @@ void SkEdgeClipper::clipMonoQuad(const SkPoint srcPts[3], const SkRect& clip) {
} else {
// if chopMonoQuadAtY failed, then we may have hit inexact numerics
// so we just clamp against the right
this->appendVLine(clip.fRight, pts[0].fY, pts[2].fY, reverse);
pts[1].fX = std::min(pts[1].fX, clip.fRight);
pts[2].fX = std::min(pts[2].fX, clip.fRight);
this->appendQuad(pts, reverse);
}
} else { // wholly inside the clip
this->appendQuad(pts, reverse);