Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Unified Diff: src/gpu/GrAAConvexPathRenderer.cpp

Issue 23905005: Fix convex path renderer bounds computation (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(&degenerateData, 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(&degenerateData, 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(&degenerateData, pts[1]);
update_degenerate_test(&degenerateData, 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(&degenerateData, pts[1]);
update_degenerate_test(&degenerateData, pts[2]);
update_degenerate_test(&degenerateData, 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;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698