Fix convex path renderer bounds computation
R=jvanverth@google.com
Author: bsalomon@google.com
Review URL: https://chromiumcodereview.appspot.com/23905005
git-svn-id: http://skia.googlecode.com/svn/trunk/src@11069 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/GrAAConvexPathRenderer.cpp b/gpu/GrAAConvexPathRenderer.cpp
index 59529c5..e50e6b4 100644
--- a/gpu/GrAAConvexPathRenderer.cpp
+++ b/gpu/GrAAConvexPathRenderer.cpp
@@ -218,33 +218,44 @@
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 @@
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 @@
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 @@
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 @@
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;