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>
This commit is contained in:
Chris Dalton 2018-09-14 14:14:49 -06:00 committed by Skia Commit-Bot
parent 7f8c5249d5
commit ce038dce94
4 changed files with 16 additions and 4 deletions

View File

@ -274,7 +274,7 @@ SkScalar SkFindQuadMaxCurvature(const SkPoint src[3]) {
return 1;
}
SkScalar t = numer / denom;
SkASSERT(0 <= t && t < 1);
SkASSERT((0 <= t && t < 1) || SkScalarIsNaN(t));
return t;
}

View File

@ -205,7 +205,7 @@ GrCCAtlas* GrCCPerFlushResources::copyPathToCachedAtlas(const GrCCPathCacheEntry
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 @@ static void transform_path_pts(const SkMatrix& m, const SkPath& path,
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 @@ static void transform_path_pts(const SkMatrix& m, const SkPath& path,
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 @@ const GrCCAtlas* GrCCPerFlushResources::renderShapeInAtlas(
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()) {

View File

@ -156,6 +156,7 @@ void GrCCStrokeGeometry::quadraticTo(Verb leftJoinVerb, const SkPoint P[3], floa
// 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 @@ void GrCCStrokeGeometry::cubicTo(Verb leftJoinVerb, const SkPoint P[4], float ma
// 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]);

View File

@ -476,7 +476,7 @@ public:
// 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;