Reland path bounds change with correct bounds for convex and hairline path renderers.
R=robertphillips@google.com Review URL: https://codereview.chromium.org/15465005 git-svn-id: http://skia.googlecode.com/svn/trunk@9194 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
4b0757b748
commit
1dd9baa6c8
@ -660,6 +660,24 @@ 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 = origPath.getBounds();
|
||||
adcd.getOriginalMatrix().mapRect(&devBounds);
|
||||
devBounds.outset(SK_Scalar1, SK_Scalar1);
|
||||
|
||||
// Check devBounds
|
||||
#if GR_DEBUG
|
||||
SkRect tolDevBounds = devBounds;
|
||||
tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000);
|
||||
SkRect actualBounds;
|
||||
actualBounds.set(verts[0].fPos, verts[1].fPos);
|
||||
for (int i = 2; i < vCount; ++i) {
|
||||
actualBounds.growToInclude(verts[i].fPos.fX, verts[i].fPos.fY);
|
||||
}
|
||||
GrAssert(tolDevBounds.contains(actualBounds));
|
||||
#endif
|
||||
|
||||
int vOffset = 0;
|
||||
for (int i = 0; i < draws.count(); ++i) {
|
||||
const Draw& draw = draws[i];
|
||||
@ -667,7 +685,8 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
vOffset, // start vertex
|
||||
0, // start index
|
||||
draw.fVertexCnt,
|
||||
draw.fIndexCnt);
|
||||
draw.fIndexCnt,
|
||||
&devBounds);
|
||||
vOffset += draw.fVertexCnt;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
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();
|
||||
|
@ -29,7 +29,6 @@ protected:
|
||||
bool antiAlias) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
GrAAHairLinePathRenderer(const GrContext* context,
|
||||
const GrIndexBuffer* fLinesIndexBuffer,
|
||||
const GrIndexBuffer* fQuadsIndexBuffer);
|
||||
@ -38,7 +37,8 @@ private:
|
||||
GrDrawTarget* target,
|
||||
int* lineCnt,
|
||||
int* quadCnt,
|
||||
GrDrawTarget::AutoReleaseGeometry* arg);
|
||||
GrDrawTarget::AutoReleaseGeometry* arg,
|
||||
SkRect* devBounds );
|
||||
|
||||
const GrIndexBuffer* fLinesIndexBuffer;
|
||||
const GrIndexBuffer* fQuadsIndexBuffer;
|
||||
|
@ -445,7 +445,9 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
SkRect devBounds;
|
||||
GetPathDevBounds(path, drawState->getRenderTarget(), viewM, &devBounds);
|
||||
|
||||
for (int p = 0; p < passCount; ++p) {
|
||||
drawState->setDrawFace(drawFace[p]);
|
||||
if (NULL != passes[p]) {
|
||||
@ -460,10 +462,8 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
|
||||
GrDrawState::AutoDeviceCoordDraw adcd;
|
||||
if (reverse) {
|
||||
GrAssert(NULL != drawState->getRenderTarget());
|
||||
// draw over the whole world.
|
||||
bounds.setLTRB(0, 0,
|
||||
SkIntToScalar(drawState->getRenderTarget()->width()),
|
||||
SkIntToScalar(drawState->getRenderTarget()->height()));
|
||||
// draw over the dev bounds (which will be the whole dst surface for inv fill).
|
||||
bounds = devBounds;
|
||||
SkMatrix vmi;
|
||||
// mapRect through persp matrix may not be correct
|
||||
if (!drawState->getViewMatrix().hasPerspective() &&
|
||||
@ -483,13 +483,12 @@ bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
|
||||
}
|
||||
if (indexCnt) {
|
||||
target->drawIndexed(primType, 0, 0,
|
||||
vertexCnt, indexCnt);
|
||||
vertexCnt, indexCnt, &devBounds);
|
||||
} else {
|
||||
target->drawNonIndexed(primType, 0, vertexCnt);
|
||||
target->drawNonIndexed(primType, 0, vertexCnt, &devBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -12,3 +12,15 @@ SK_DEFINE_INST_COUNT(GrPathRenderer)
|
||||
|
||||
GrPathRenderer::GrPathRenderer() {
|
||||
}
|
||||
|
||||
void GrPathRenderer::GetPathDevBounds(const SkPath& path,
|
||||
int devW, int devH,
|
||||
const SkMatrix& matrix,
|
||||
SkRect* bounds) {
|
||||
if (path.isInverseFillType()) {
|
||||
*bounds = SkRect::MakeWH(SkIntToScalar(devW), SkIntToScalar(devH));
|
||||
return;
|
||||
}
|
||||
*bounds = path.getBounds();
|
||||
matrix.mapRect(bounds);
|
||||
}
|
||||
|
@ -173,6 +173,22 @@ protected:
|
||||
this->drawPath(path, stroke, target, false);
|
||||
}
|
||||
|
||||
// Helper for getting the device bounds of a path. Inverse filled paths will have bounds set
|
||||
// by devSize. Non-inverse path bounds will not necessarily be clipped to devSize.
|
||||
static void GetPathDevBounds(const SkPath& path,
|
||||
int devW,
|
||||
int devH,
|
||||
const SkMatrix& matrix,
|
||||
SkRect* bounds);
|
||||
|
||||
// Helper version that gets the dev width and height from a GrSurface.
|
||||
static void GetPathDevBounds(const SkPath& path,
|
||||
const GrSurface* device,
|
||||
const SkMatrix& matrix,
|
||||
SkRect* bounds) {
|
||||
GetPathDevBounds(path, device->width(), device->height(), matrix, bounds);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
typedef GrRefCnt INHERITED;
|
||||
|
Loading…
Reference in New Issue
Block a user