Index: src/gpu/GrAAConvexPathRenderer.cpp |
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp |
index 59529c5f8bbcc486b4f2228cf94f23b242e67248..e50e6b406eb0d276c6ad0cdb89ff0d899326bea7 100644 |
--- a/src/gpu/GrAAConvexPathRenderer.cpp |
+++ b/src/gpu/GrAAConvexPathRenderer.cpp |
@@ -218,33 +218,44 @@ static inline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath:: |
return true; |
} |
-static inline void add_line_to_segment(const SkPoint& pt, SegmentArray* segments) { |
+static inline void add_line_to_segment(const SkPoint& pt, |
+ SegmentArray* segments, |
+ SkRect* devBounds) { |
segments->push_back(); |
segments->back().fType = Segment::kLine; |
segments->back().fPts[0] = pt; |
+ devBounds->growToInclude(pt.fX, pt.fY); |
} |
-static inline void add_quad_segment(const SkPoint pts[3], SegmentArray* segments) { |
+static inline bool contains_inclusive(const SkRect& rect, const SkPoint& p) { |
+ return p.fX >= rect.fLeft && p.fX <= rect.fRight && p.fY >= rect.fTop && p.fY <= rect.fBottom; |
+} |
+static inline void add_quad_segment(const SkPoint pts[3], |
+ SegmentArray* segments, |
+ SkRect* devBounds) { |
if (pts[0].distanceToSqd(pts[1]) < kCloseSqd || pts[1].distanceToSqd(pts[2]) < kCloseSqd) { |
if (pts[0] != pts[2]) { |
- add_line_to_segment(pts[2], segments); |
+ add_line_to_segment(pts[2], segments, devBounds); |
} |
} else { |
segments->push_back(); |
segments->back().fType = Segment::kQuad; |
segments->back().fPts[0] = pts[1]; |
segments->back().fPts[1] = pts[2]; |
+ SkASSERT(contains_inclusive(*devBounds, pts[0])); |
+ devBounds->growToInclude(pts + 1, 2); |
} |
} |
static inline void add_cubic_segments(const SkPoint pts[4], |
SkPath::Direction dir, |
- SegmentArray* segments) { |
+ SegmentArray* segments, |
+ SkRect* devBounds) { |
SkSTArray<15, SkPoint, true> quads; |
GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads); |
int count = quads.count(); |
for (int q = 0; q < count; q += 3) { |
- add_quad_segment(&quads[q], segments); |
+ add_quad_segment(&quads[q], segments, devBounds); |
} |
} |
@@ -253,7 +264,8 @@ static bool get_segments(const SkPath& path, |
SegmentArray* segments, |
SkPoint* fanPt, |
int* vCount, |
- int* iCount) { |
+ int* iCount, |
+ SkRect* devBounds) { |
SkPath::Iter iter(path, true); |
// This renderer over-emphasizes very thin path regions. We use the distance |
// to the path from the sample to compute coverage. Every pixel intersected |
@@ -276,25 +288,26 @@ static bool get_segments(const SkPath& path, |
case SkPath::kMove_Verb: |
m.mapPoints(pts, 1); |
update_degenerate_test(°enerateData, pts[0]); |
+ devBounds->set(pts->fX, pts->fY, pts->fX, pts->fY); |
break; |
case SkPath::kLine_Verb: { |
m.mapPoints(&pts[1], 1); |
update_degenerate_test(°enerateData, pts[1]); |
- add_line_to_segment(pts[1], segments); |
+ add_line_to_segment(pts[1], segments, devBounds); |
break; |
} |
case SkPath::kQuad_Verb: |
m.mapPoints(pts, 3); |
update_degenerate_test(°enerateData, pts[1]); |
update_degenerate_test(°enerateData, pts[2]); |
- add_quad_segment(pts, segments); |
+ add_quad_segment(pts, segments, devBounds); |
break; |
case SkPath::kCubic_Verb: { |
m.mapPoints(pts, 4); |
update_degenerate_test(°enerateData, pts[1]); |
update_degenerate_test(°enerateData, pts[2]); |
update_degenerate_test(°enerateData, pts[3]); |
- add_cubic_segments(pts, dir, segments); |
+ add_cubic_segments(pts, dir, segments, devBounds); |
break; |
}; |
case SkPath::kDone_Verb: |
@@ -645,10 +658,16 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, |
SkSTArray<kPreallocSegmentCnt, Segment, true> segments; |
SkPoint fanPt; |
- if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount)) { |
+ // We can't simply use the path bounds because we may degenerate cubics to quads which produces |
+ // new control points outside the original convex hull. |
+ SkRect devBounds; |
+ if (!get_segments(*path, viewMatrix, &segments, &fanPt, &vCount, &iCount, &devBounds)) { |
return false; |
} |
+ // Our computed verts should all be within one pixel of the segment control points. |
+ devBounds.outset(SK_Scalar1, SK_Scalar1); |
+ |
drawState->setVertexAttribs<gPathAttribs>(SK_ARRAY_COUNT(gPathAttribs)); |
static const int kEdgeAttrIndex = 1; |
@@ -666,12 +685,6 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath, |
SkSTArray<kPreallocDrawCnt, Draw, true> draws; |
create_vertices(segments, fanPt, &draws, verts, idxs); |
- // This is valid because all the computed verts are within 1 pixel of the path control points. |
- SkRect devBounds; |
- devBounds = path->getBounds(); |
- viewMatrix.mapRect(&devBounds); |
- devBounds.outset(SK_Scalar1, SK_Scalar1); |
- |
// Check devBounds |
#ifdef SK_DEBUG |
SkRect tolDevBounds = devBounds; |