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@11069 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
25f72ed034
commit
106655efdf
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user