ccpr: Clamp the number of linear stroke segments
Clamps the number of linear segments before indexing into arrays with
it (oops). Also adds some minor fixups surrounding NaNs.
Bug: skia:8360
Change-Id: Id520ac49df2ebce71bda9fcaa0f164ddb6ddf2d2
Reviewed-on: https://skia-review.googlesource.com/154771
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index a24cd67..7b63f04 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -205,7 +205,7 @@
return &fCopyAtlasStack.current();
}
-static void transform_path_pts(const SkMatrix& m, const SkPath& path,
+static bool transform_path_pts(const SkMatrix& m, const SkPath& path,
const SkAutoSTArray<32, SkPoint>& outDevPts, SkRect* devBounds,
SkRect* devBounds45) {
const SkPoint* pts = SkPathPriv::PointData(path);
@@ -246,6 +246,11 @@
devPt.store(&outDevPts[i]);
}
+ if (!(Sk4f(0) == topLeft*0).allTrue() || !(Sk4f(0) == bottomRight*0).allTrue()) {
+ // The bounds are infinite or NaN.
+ return false;
+ }
+
SkPoint topLeftPts[2], bottomRightPts[2];
topLeft.store(topLeftPts);
bottomRight.store(bottomRightPts);
@@ -253,6 +258,7 @@
bottomRightPts[0].y());
devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(), bottomRightPts[1].x(),
bottomRightPts[1].y());
+ return true;
}
const GrCCAtlas* GrCCPerFlushResources::renderShapeInAtlas(
@@ -267,7 +273,11 @@
SkDEBUGCODE(--fEndPathInstance);
return nullptr;
}
- transform_path_pts(m, path, fLocalDevPtsBuffer, devBounds, devBounds45);
+ if (!transform_path_pts(m, path, fLocalDevPtsBuffer, devBounds, devBounds45)) {
+ // The transformed path had infinite or NaN bounds.
+ SkDEBUGCODE(--fEndPathInstance);
+ return nullptr;
+ }
const SkStrokeRec& stroke = shape.style().strokeRec();
if (!stroke.isFillStyle()) {
diff --git a/src/gpu/ccpr/GrCCStrokeGeometry.cpp b/src/gpu/ccpr/GrCCStrokeGeometry.cpp
index 3fcafec..ec626b0 100644
--- a/src/gpu/ccpr/GrCCStrokeGeometry.cpp
+++ b/src/gpu/ccpr/GrCCStrokeGeometry.cpp
@@ -156,6 +156,7 @@
// Decide how many flat line segments to chop the curve into.
int numSegments = wangs_formula_quadratic(p0, p1, p2);
+ numSegments = SkTMin(numSegments, 1 << kMaxNumLinearSegmentsLog2);
if (numSegments <= 1) {
this->rotateTo(leftJoinVerb, normals[0]);
this->lineTo(Verb::kInternalRoundJoin, P[2]);
@@ -283,6 +284,7 @@
// Decide how many flat line segments to chop the curve into.
int numSegments = wangs_formula_cubic(p0, p1, p2, p3);
+ numSegments = SkTMin(numSegments, 1 << kMaxNumLinearSegmentsLog2);
if (numSegments <= 1) {
this->rotateTo(leftJoinVerb, normals[0]);
this->lineTo(leftJoinVerb, P[3]);
diff --git a/src/gpu/ccpr/GrCCStroker.cpp b/src/gpu/ccpr/GrCCStroker.cpp
index ab3906c..919e0f7 100644
--- a/src/gpu/ccpr/GrCCStroker.cpp
+++ b/src/gpu/ccpr/GrCCStroker.cpp
@@ -476,7 +476,7 @@
// For miter and round joins, we place an additional triangle cap on top of the bevel. This
// triangle is literal for miters and is conic control points for round joins.
- SkASSERT(miterCapHeightOverWidth >= 0);
+ SkASSERT(miterCapHeightOverWidth >= 0 || SkScalarIsNaN(miterCapHeightOverWidth));
Sk2f base = n1 - n0;
Sk2f baseNorm = Sk2f(base[1], -base[0]);
Sk2f c = (n0 + n1) * .5f + baseNorm * miterCapHeightOverWidth;