fix circle dash

Thin conic dashes are treated as lines both if the
curvature is detected as zero, and if the midpoint
is close enough to the control point.

To fix:
Halve the midpoint to control point magic number.
Use quad max curvature as a placeholder for conic
max curvature.

R=reed@google.com,fmalita@chromium.org
Bug:843966
Change-Id: Ide43bef8767c03670ffd19fdc38c191d6e2332f3
Reviewed-on: https://skia-review.googlesource.com/c/129243
Commit-Queue: Cary Clark <caryclark@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Cary Clark <caryclark@skia.org>
This commit is contained in:
Cary Clark 2018-12-04 14:52:40 -05:00 committed by Skia Commit-Bot
parent 7d1eb33aec
commit dbf2aec28a
2 changed files with 48 additions and 8 deletions

View File

@ -225,3 +225,39 @@ protected:
};
DEF_GM(return new DashCircle2GM;)
DEF_SIMPLE_GM(maddash, canvas, 1600, 1600) {
canvas->drawRect({0, 0, 1600, 1600}, SkPaint());
SkPaint p;
p.setColor(SK_ColorRED);
p.setAntiAlias(true);
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(380);
SkScalar intvls[] = { 2.5, 10 /* 1200 */ };
p.setPathEffect(SkDashPathEffect::Make(intvls, 2, 0));
canvas->drawCircle(400, 400, 200, p);
SkPath path;
path.moveTo(800, 400);
path.quadTo(1000, 400, 1000, 600);
path.quadTo(1000, 800, 800, 800);
path.quadTo(600, 800, 600, 600);
path.quadTo(600, 400, 800, 400);
path.close();
canvas->translate(350, 150);
p.setStrokeWidth(320);
canvas->drawPath(path, p);
path.reset();
path.moveTo(800, 400);
path.cubicTo(900, 400, 1000, 500, 1000, 600);
path.cubicTo(1000, 700, 900, 800, 800, 800);
path.cubicTo(700, 800, 600, 700, 600, 600);
path.cubicTo(600, 500, 700, 400, 800, 400);
path.close();
canvas->translate(-550, 500);
p.setStrokeWidth(300);
canvas->drawPath(path, p);
}

View File

@ -591,7 +591,12 @@ static bool quad_in_line(const SkPoint quad[3]) {
SkASSERT(outer2 >= 1 && outer2 <= 2);
SkASSERT(outer1 < outer2);
int mid = outer1 ^ outer2 ^ 3;
SkScalar lineSlop = ptMax * ptMax * 0.00001f; // this multiplier is pulled out of the air
#ifdef SK_USE_LEGACY_CONIC_CURVATURE_SLOP
const float kCurvatureSlop = 0.00001f;
#else
const float kCurvatureSlop = 0.000005f; // this multiplier is pulled out of the air
#endif
SkScalar lineSlop = ptMax * ptMax * kCurvatureSlop;
return pt_to_line(quad[mid], quad[outer1], quad[outer2]) <= lineSlop;
}
@ -651,20 +656,19 @@ SkPathStroker::ReductionType SkPathStroker::CheckConicLinear(const SkConic& coni
if (!conic_in_line(conic)) {
return kQuad_ReductionType;
}
#if 0 // once findMaxCurvature is implemented, this will be a better solution
SkScalar t;
if (!conic.findMaxCurvature(&t) || 0 == t) {
return kLine_ReductionType;
}
#else // but for now, use extrema instead
#ifdef SK_USE_LEGACY_CONIC_CURVATURE_SLOP
SkScalar xT = 0, yT = 0;
(void) conic.findXExtrema(&xT);
(void) conic.findYExtrema(&yT);
SkScalar t = SkTMax(xT, yT);
#else
// SkFindConicMaxCurvature would be a better solution, once we know how to
// implement it. Quad curvature is a reasonable substitute
SkScalar t = SkFindQuadMaxCurvature(conic.fPts);
#endif
if (0 == t) {
return kLine_ReductionType;
}
#endif
conic.evalAt(t, reduction, nullptr);
return kDegenerate_ReductionType;
}