break out of cubic stroker loop on degenerate case
The looper can generate more than one quad, but if any one is degenerate, give up, but not before generating the state for the line join to produce the correct end. Before, the early return allowed the inside path to contain multiple movetos that caused reversePath to assert. R=reed@google.com Review URL: https://codereview.chromium.org/948043002
This commit is contained in:
parent
f056bd1e01
commit
6df8e3495a
@ -26,7 +26,28 @@ protected:
|
||||
}
|
||||
|
||||
virtual SkISize onISize() {
|
||||
return SkISize::Make(640, 480);
|
||||
return SkISize::Make(860, 700);
|
||||
}
|
||||
|
||||
void flower(SkCanvas* canvas, const SkPath& path, SkScalar intervals[2], SkPaint::Join join) {
|
||||
SkPathEffect* pe = SkDashPathEffect::Create(intervals, 2, 0);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setStrokeJoin(join);
|
||||
paint.setStrokeWidth(42);
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setStrokeWidth(21);
|
||||
paint.setPathEffect(pe)->unref();
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
paint.setPathEffect(NULL);
|
||||
paint.setStrokeWidth(0);
|
||||
canvas->drawPath(path, paint);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
@ -42,26 +63,16 @@ protected:
|
||||
"C 283,231 344,195 338,98";
|
||||
|
||||
SkParsePath::FromSVGString(d, &path);
|
||||
|
||||
SkScalar intervals[] = { 5, 10 };
|
||||
SkPathEffect* pe = SkDashPathEffect::Create(intervals, 2, 0);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
|
||||
paint.setStrokeWidth(42);
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
paint.setStrokeWidth(21);
|
||||
paint.setPathEffect(pe)->unref();
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
paint.setPathEffect(NULL);
|
||||
paint.setStrokeWidth(0);
|
||||
canvas->drawPath(path, paint);
|
||||
canvas->translate(-35.f, -55.f);
|
||||
for (int x = 0; x < 2; ++x) {
|
||||
for (int y = 0; y < 2; ++y) {
|
||||
canvas->save();
|
||||
canvas->translate(x * 430.f, y * 355.f);
|
||||
SkScalar intervals[] = { 5 + (x ? 0 : 0.0001f + 0.0001f), 10 };
|
||||
flower(canvas, path, intervals, y ? SkPaint::kDefault_Join : SkPaint::kRound_Join);
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -905,9 +905,10 @@ void SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
|
||||
// compute the perpendicular point and its tangent.
|
||||
void SkPathStroker::setRayPts(const SkPoint& tPt, SkVector* dxy, SkPoint* onPt,
|
||||
SkPoint* tangent) const {
|
||||
SkPoint oldDxy = *dxy;
|
||||
if (!dxy->setLength(fRadius)) { // consider moving double logic into SkPoint::setLength
|
||||
double xx = dxy->fX;
|
||||
double yy = dxy->fY;
|
||||
double xx = oldDxy.fX;
|
||||
double yy = oldDxy.fY;
|
||||
double dscale = fRadius / sqrt(xx * xx + yy * yy);
|
||||
dxy->fX = SkDoubleToScalar(xx * dscale);
|
||||
dxy->fY = SkDoubleToScalar(yy * dscale);
|
||||
@ -1412,14 +1413,16 @@ void SkPathStroker::cubicTo(const SkPoint& pt1, const SkPoint& pt2,
|
||||
SkQuadConstruct quadPts;
|
||||
this->init(kOuter_StrokeType, &quadPts, lastT, nextT);
|
||||
if (!this->cubicStroke(cubic, &quadPts)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
this->init(kInner_StrokeType, &quadPts, lastT, nextT);
|
||||
if (!this->cubicStroke(cubic, &quadPts)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
lastT = nextT;
|
||||
}
|
||||
// emit the join even if one stroke succeeded but the last one failed
|
||||
// this avoids reversing an inner stroke with a partial path followed by another moveto
|
||||
this->setCubicEndNormal(cubic, normalAB, unitAB, &normalCD, &unitCD);
|
||||
#else
|
||||
bool degenerateAB = SkPath::IsLineDegenerate(fPrevPt, pt1);
|
||||
|
Loading…
Reference in New Issue
Block a user