aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/strokes.cpp10
-rw-r--r--src/core/SkCanvas.cpp2
-rw-r--r--src/core/SkStroke.cpp12
-rw-r--r--tests/EmptyPathTest.cpp19
4 files changed, 40 insertions, 3 deletions
diff --git a/gm/strokes.cpp b/gm/strokes.cpp
index 57517a0616..e74d35f800 100644
--- a/gm/strokes.cpp
+++ b/gm/strokes.cpp
@@ -84,12 +84,16 @@ private:
*/
class ZeroLenStrokesGM : public skiagm::GM {
SkPath fMoveHfPath, fMoveZfPath, fDashedfPath, fRefPath[4];
+ SkPath fCubicPath, fQuadPath, fLinePath;
protected:
void onOnceBeforeDraw() override {
SkAssertResult(SkParsePath::FromSVGString("M0,0h0M10,0h0M20,0h0", &fMoveHfPath));
SkAssertResult(SkParsePath::FromSVGString("M0,0zM10,0zM20,0z", &fMoveZfPath));
SkAssertResult(SkParsePath::FromSVGString("M0,0h25", &fDashedfPath));
+ SkAssertResult(SkParsePath::FromSVGString("M 0 0 C 0 0 0 0 0 0", &fCubicPath));
+ SkAssertResult(SkParsePath::FromSVGString("M 0 0 Q 0 0 0 0", &fQuadPath));
+ SkAssertResult(SkParsePath::FromSVGString("M 0 0 L 0 0", &fLinePath));
for (int i = 0; i < 3; ++i) {
fRefPath[0].addCircle(i * 10.f, 0, 5);
@@ -140,6 +144,12 @@ protected:
canvas->translate(0, 30);
fillPaint.setAlpha(127);
canvas->drawPath(fRefPath[1 + i * 2], fillPaint);
+ canvas->translate(0, 30);
+ canvas->drawPath(fCubicPath, strokePaint);
+ canvas->translate(0, 30);
+ canvas->drawPath(fQuadPath, strokePaint);
+ canvas->translate(0, 30);
+ canvas->drawPath(fLinePath, strokePaint);
canvas->restore();
}
}
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7043ec3bc3..3a289566cb 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2124,8 +2124,8 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
if (r.width() <= 0 && r.height() <= 0) {
if (path.isInverseFillType()) {
this->internalDrawPaint(paint);
+ return;
}
- return;
}
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 1689f9730b..522a000712 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -619,6 +619,10 @@ void SkPathStroker::conicTo(const SkPoint& pt1, const SkPoint& pt2, SkScalar wei
SkPoint reduction;
ReductionType reductionType = CheckConicLinear(conic, &reduction);
if (kPoint_ReductionType == reductionType) {
+ /* If the stroke consists of a moveTo followed by a degenerate curve, treat it
+ as if it were followed by a zero-length line. Lines without length
+ can have square and round end caps. */
+ this->lineTo(pt2);
return;
}
if (kLine_ReductionType == reductionType) {
@@ -653,6 +657,10 @@ void SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
SkPoint reduction;
ReductionType reductionType = CheckQuadLinear(quad, &reduction);
if (kPoint_ReductionType == reductionType) {
+ /* If the stroke consists of a moveTo followed by a degenerate curve, treat it
+ as if it were followed by a zero-length line. Lines without length
+ can have square and round end caps. */
+ this->lineTo(pt2);
return;
}
if (kLine_ReductionType == reductionType) {
@@ -1168,6 +1176,10 @@ void SkPathStroker::cubicTo(const SkPoint& pt1, const SkPoint& pt2,
const SkPoint* tangentPt;
ReductionType reductionType = CheckCubicLinear(cubic, reduction, &tangentPt);
if (kPoint_ReductionType == reductionType) {
+ /* If the stroke consists of a moveTo followed by a degenerate curve, treat it
+ as if it were followed by a zero-length line. Lines without length
+ can have square and round end caps. */
+ this->lineTo(pt3);
return;
}
if (kLine_ReductionType == reductionType) {
diff --git a/tests/EmptyPathTest.cpp b/tests/EmptyPathTest.cpp
index c4f011a0dc..060ef8d237 100644
--- a/tests/EmptyPathTest.cpp
+++ b/tests/EmptyPathTest.cpp
@@ -54,7 +54,13 @@ static void drawAndTest(skiatest::Reporter* reporter, const SkPath& path,
}
}
-static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool shouldDraw) {
+enum DrawCaps {
+ kDontDrawCaps,
+ kDrawCaps
+};
+
+static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool shouldDraw,
+ DrawCaps drawCaps) {
static const SkPaint::Cap gCaps[] = {
SkPaint::kButt_Cap,
SkPaint::kRound_Cap,
@@ -73,6 +79,11 @@ static void iter_paint(skiatest::Reporter* reporter, const SkPath& path, bool sh
for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
for (size_t join = 0; join < SK_ARRAY_COUNT(gJoins); ++join) {
for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
+ if (drawCaps && SkPaint::kButt_Cap != gCaps[cap]
+ && SkPaint::kFill_Style != gStyles[style]) {
+ continue;
+ }
+
SkPaint paint;
paint.setStrokeWidth(SkIntToScalar(10));
@@ -127,10 +138,14 @@ static void test_emptydrawing(skiatest::Reporter* reporter) {
if (doClose) {
path.close();
}
+ /* zero length segments and close following moves draw round and square caps */
+ bool allowCaps = make_L == gMakeProc[i] || make_Q == gMakeProc[i]
+ || make_C == gMakeProc[i] || make_MZM == gMakeProc[i];
+ allowCaps |= SkToBool(doClose);
for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
path.setFillType(gFills[fill]);
bool shouldDraw = path.isInverseFillType();
- iter_paint(reporter, path, shouldDraw);
+ iter_paint(reporter, path, shouldDraw, allowCaps ? kDrawCaps : kDontDrawCaps);
}
}
}