merge per request
R=awhalley@google.com
TBR=reed@google.com
BUG=638223
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2284303004
NOTREECHECKS=true
NOTRY=true
NOPRESUBMIT=true
Review-Url: https://codereview.chromium.org/2284303004
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index 7dd5359..03a63b2 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -1170,10 +1170,24 @@
int SkConic::chopIntoQuadsPOW2(SkPoint pts[], int pow2) const {
SkASSERT(pow2 >= 0);
+ *pts = fPts[0];
+ SkDEBUGCODE(SkPoint* endPts);
+ if (pow2 == kMaxConicToQuadPOW2) { // If an extreme weight generates many quads ...
+ SkConic dst[2];
+ this->chop(dst);
+ // check to see if the first chop generates a pair of lines
+ if (dst[0].fPts[1] == dst[0].fPts[2] && dst[1].fPts[0] == dst[1].fPts[1]) {
+ pts[1] = pts[2] = pts[3] = dst[0].fPts[1]; // set ctrl == end to make lines
+ pts[4] = dst[1].fPts[2];
+ pow2 = 1;
+ SkDEBUGCODE(endPts = &pts[5]);
+ goto commonFinitePtCheck;
+ }
+ }
+ SkDEBUGCODE(endPts = ) subdivide(*this, pts + 1, pow2);
+commonFinitePtCheck:
const int quadCount = 1 << pow2;
const int ptCount = 2 * quadCount + 1;
- *pts = fPts[0];
- SkDEBUGCODE(SkPoint* endPts =) subdivide(*this, pts + 1, pow2);
SkASSERT(endPts - pts == ptCount);
if (!SkPointsAreFinite(pts, ptCount)) {
// if we generated a non-finite, pin ourselves to the middle of the hull,
diff --git a/src/core/SkGeometry.h b/src/core/SkGeometry.h
index 15f1e55..74c9d89 100644
--- a/src/core/SkGeometry.h
+++ b/src/core/SkGeometry.h
@@ -235,7 +235,7 @@
* Chop this conic into N quads, stored continguously in pts[], where
* N = 1 << pow2. The amount of storage needed is (1 + 2 * N)
*/
- int chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
+ int SK_WARN_UNUSED_RESULT chopIntoQuadsPOW2(SkPoint pts[], int pow2) const;
bool findXExtrema(SkScalar* t) const;
bool findYExtrema(SkScalar* t) const;
@@ -384,7 +384,7 @@
int pow2 = conic.computeQuadPOW2(tol);
fQuadCount = 1 << pow2;
SkPoint* pts = fStorage.reset(1 + 2 * fQuadCount);
- conic.chopIntoQuadsPOW2(pts, pow2);
+ fQuadCount = conic.chopIntoQuadsPOW2(pts, pow2);
return pts;
}
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index 8f98e6a..ddbc77c 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -110,6 +110,20 @@
canvas->drawPath(path, paint);
}
+// this is a unit test instead of a GM because it doesn't draw anything
+static void test_fuzz_crbug_638223() {
+ auto surface(SkSurface::MakeRasterN32Premul(250, 250));
+ SkCanvas* canvas = surface->getCanvas();
+ SkPath path;
+ path.moveTo(SkBits2Float(0x47452a00), SkBits2Float(0x43211d01)); // 50474, 161.113f
+ path.conicTo(SkBits2Float(0x401c0000), SkBits2Float(0x40680000),
+ SkBits2Float(0x02c25a81), SkBits2Float(0x981a1fa0),
+ SkBits2Float(0x6bf9abea)); // 2.4375f, 3.625f, 2.85577e-37f, -1.992e-24f, 6.03669e+26f
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ canvas->drawPath(path, paint);
+}
+
/**
* In debug mode, this path was causing an assertion to fail in
* SkPathStroker::preJoinTo() and, in Release, the use of an unitialized value.
@@ -4348,4 +4362,5 @@
test_skbug_3469(reporter);
test_skbug_3239(reporter);
test_bounds_crbug_513799(reporter);
+ test_fuzz_crbug_638223();
}