Index: src/gpu/GrAAHairLinePathRenderer.cpp |
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp |
index da54ed643c1d99a990791cd19848a78e45a82747..8e3ec5b02e9e433b966f4fc00dc10b8112f244c6 100644 |
--- a/src/gpu/GrAAHairLinePathRenderer.cpp |
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp |
@@ -360,7 +360,8 @@ void intersect_lines(const SkPoint& ptA, const SkVector& normA, |
} |
void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, |
- const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { |
+ const SkMatrix* toSrc, Vertex verts[kVertsPerQuad], |
+ SkRect* devBounds) { |
GrAssert(!toDevice == !toSrc); |
// original quad is specified by tri a,b,c |
SkPoint a = qpts[0]; |
@@ -427,7 +428,10 @@ void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, |
c1.fPos = c; |
c1.fPos -= cbN; |
+ // This point may not be within 1 pixel of a control point. We update the bounding box to |
+ // include it. |
intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); |
+ devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); |
if (toSrc) { |
toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad); |
@@ -439,15 +443,16 @@ void add_quads(const SkPoint p[3], |
int subdiv, |
const SkMatrix* toDevice, |
const SkMatrix* toSrc, |
- Vertex** vert) { |
+ Vertex** vert, |
+ SkRect* devBounds) { |
GrAssert(subdiv >= 0); |
if (subdiv) { |
SkPoint newP[5]; |
SkChopQuadAtHalf(p, newP); |
- add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); |
- add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); |
+ add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); |
+ add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); |
} else { |
- bloat_quad(p, toDevice, toSrc, *vert); |
+ bloat_quad(p, toDevice, toSrc, *vert, devBounds); |
*vert += kVertsPerQuad; |
} |
} |
@@ -704,7 +709,8 @@ bool GrAAHairLinePathRenderer::createGeom( |
GrDrawTarget* target, |
int* lineCnt, |
int* quadCnt, |
- GrDrawTarget::AutoReleaseGeometry* arg) { |
+ GrDrawTarget::AutoReleaseGeometry* arg, |
+ SkRect* devBounds) { |
GrDrawState* drawState = target->drawState(); |
int rtHeight = drawState->getRenderTarget()->height(); |
@@ -714,6 +720,13 @@ bool GrAAHairLinePathRenderer::createGeom( |
SkMatrix viewM = drawState->getViewMatrix(); |
+ // All the vertices that we compute are within 1 of path control points with the exception of |
+ // one of the bounding vertices for each quad. The add_quads() function will update the bounds |
+ // for each quad added. |
+ *devBounds = path.getBounds(); |
+ viewM.mapRect(devBounds); |
+ devBounds->outset(SK_Scalar1, SK_Scalar1); |
+ |
PREALLOC_PTARRAY(128) lines; |
PREALLOC_PTARRAY(128) quads; |
IntArray qSubdivs; |
@@ -750,7 +763,7 @@ bool GrAAHairLinePathRenderer::createGeom( |
int unsubdivQuadCnt = quads.count() / 3; |
for (int i = 0; i < unsubdivQuadCnt; ++i) { |
GrAssert(qSubdivs[i] >= 0); |
- add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); |
+ add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); |
} |
return true; |
@@ -781,11 +794,14 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, |
int lineCnt; |
int quadCnt; |
GrDrawTarget::AutoReleaseGeometry arg; |
+ SkRect devBounds; |
+ |
if (!this->createGeom(path, |
target, |
&lineCnt, |
&quadCnt, |
- &arg)) { |
+ &arg, |
+ &devBounds)) { |
return false; |
} |
@@ -816,6 +832,33 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, |
GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); |
GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); |
+ // Check devBounds |
+#if GR_DEBUG |
robertphillips
2013/05/20 13:50:42
I have needed an SkRect::contains with a tolerance
|
+ SkRect tolDevBounds = devBounds; |
+ tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); |
+ SkRect actualBounds; |
+ Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices()); |
+ int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt; |
+ bool first = true; |
+ for (int i = 0; i < vCount; ++i) { |
+ SkPoint pos = verts[i].fPos; |
+ // This is a hack to workaround the fact that we move some degenerate segments offscreen. |
+ if (SK_ScalarMax == pos.fX) { |
+ continue; |
+ } |
+ drawState->getViewMatrix().mapPoints(&pos, 1); |
+ if (first) { |
+ actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); |
+ first = false; |
+ } else { |
+ actualBounds.growToInclude(pos.fX, pos.fY); |
+ } |
+ } |
+ if (!first) { |
+ GrAssert(tolDevBounds.contains(actualBounds)); |
+ } |
+#endif |
+ |
target->setIndexSourceToBuffer(fLinesIndexBuffer); |
int lines = 0; |
int nBufLines = fLinesIndexBuffer->maxQuads(); |
@@ -826,7 +869,8 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, |
kVertsPerLineSeg*lines, // startV |
0, // startI |
kVertsPerLineSeg*n, // vCount |
- kIdxsPerLineSeg*n); // iCount |
+ kIdxsPerLineSeg*n, |
+ &devBounds); // iCount |
lines += n; |
} |
@@ -839,7 +883,8 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, |
4 * lineCnt + kVertsPerQuad*quads, // startV |
0, // startI |
kVertsPerQuad*n, // vCount |
- kIdxsPerQuad*n); // iCount |
+ kIdxsPerQuad*n, // iCount |
+ &devBounds); |
quads += n; |
} |
target->resetIndexSource(); |