Index: src/gpu/GrAAHairLinePathRenderer.cpp |
=================================================================== |
--- src/gpu/GrAAHairLinePathRenderer.cpp (revision 11234) |
+++ src/gpu/GrAAHairLinePathRenderer.cpp (working copy) |
@@ -28,8 +28,16 @@ |
static const int kVertsPerQuad = 5; |
static const int kIdxsPerQuad = 9; |
+// lines are rendered as: |
+// *______________* |
+// |\ -_______ /| |
+// | \ \ / | |
+// | *--------* | |
+// | / ______/ \ | |
+// */_-__________\* |
+// For: 6 vertices and 18 indices (for 6 triangles) |
static const int kVertsPerLineSeg = 6; |
-static const int kIdxsPerLineSeg = 12; |
+static const int kIdxsPerLineSeg = 18; |
static const int kNumQuadsInIdxBuffer = 256; |
static const size_t kQuadIdxSBufize = kIdxsPerQuad * |
@@ -90,32 +98,41 @@ |
data = SkNEW_ARRAY(uint16_t, kNumLineSegsInIdxBuffer * kIdxsPerLineSeg); |
} |
for (int i = 0; i < kNumLineSegsInIdxBuffer; ++i) { |
- // Each line segment is rendered as two quads, with alpha = 1 along the |
- // spine of the segment, and alpha = 0 along the outer edges, represented |
- // horizontally (i.e., the line equation is t*(p1-p0) + p0) |
+ // Each line segment is rendered as two quads and two triangles. |
+ // p0 and p1 have alpha = 1 while all other points have alpha = 0. |
+ // The four external points are offset 1 pixel perpendicular to the |
+ // line and half a pixel parallel to the line. |
// |
// p4 p5 |
- // p0 p1 |
+ // p0 p1 |
// p2 p3 |
// |
- // Each is drawn as four triangles specified by these 12 indices: |
+ // Each is drawn as six triangles specified by these 18 indices: |
int baseIdx = i * kIdxsPerLineSeg; |
uint16_t baseVert = (uint16_t)(i * kVertsPerLineSeg); |
- data[0 + baseIdx] = baseVert + 0; // p0 |
- data[1 + baseIdx] = baseVert + 1; // p1 |
- data[2 + baseIdx] = baseVert + 2; // p2 |
+ data[0 + baseIdx] = baseVert + 0; |
+ data[1 + baseIdx] = baseVert + 1; |
+ data[2 + baseIdx] = baseVert + 3; |
- data[3 + baseIdx] = baseVert + 2; // p2 |
- data[4 + baseIdx] = baseVert + 1; // p1 |
- data[5 + baseIdx] = baseVert + 3; // p3 |
+ data[3 + baseIdx] = baseVert + 0; |
+ data[4 + baseIdx] = baseVert + 3; |
+ data[5 + baseIdx] = baseVert + 2; |
- data[6 + baseIdx] = baseVert + 0; // p0 |
- data[7 + baseIdx] = baseVert + 5; // p5 |
- data[8 + baseIdx] = baseVert + 1; // p1 |
+ data[6 + baseIdx] = baseVert + 0; |
+ data[7 + baseIdx] = baseVert + 4; |
+ data[8 + baseIdx] = baseVert + 5; |
- data[9 + baseIdx] = baseVert + 0; // p0 |
- data[10+ baseIdx] = baseVert + 4; // p4 |
- data[11+ baseIdx] = baseVert + 5; // p5 |
+ data[9 + baseIdx] = baseVert + 0; |
+ data[10+ baseIdx] = baseVert + 5; |
+ data[11+ baseIdx] = baseVert + 1; |
+ |
+ data[12 + baseIdx] = baseVert + 0; |
+ data[13 + baseIdx] = baseVert + 2; |
+ data[14 + baseIdx] = baseVert + 4; |
+ |
+ data[15 + baseIdx] = baseVert + 1; |
+ data[16 + baseIdx] = baseVert + 5; |
+ data[17 + baseIdx] = baseVert + 3; |
} |
if (tempData) { |
bool ret = lIdxBuffer->updateData(data, kLineSegIdxSBufize); |
@@ -649,31 +666,33 @@ |
} |
void add_line(const SkPoint p[2], |
- int rtHeight, |
const SkMatrix* toSrc, |
GrColor coverage, |
LineVertex** vert) { |
const SkPoint& a = p[0]; |
const SkPoint& b = p[1]; |
- SkVector orthVec = b; |
- orthVec -= a; |
+ SkVector ortho, vec = b; |
+ vec -= a; |
- if (orthVec.setLength(SK_Scalar1)) { |
- orthVec.setOrthog(orthVec); |
+ if (vec.setLength(SK_ScalarHalf)) { |
+ // Create a vector orthogonal to 'vec' and of unit length |
+ ortho.fX = 2.0f * vec.fY; |
+ ortho.fY = -2.0f * vec.fX; |
- for (int i = 0; i < kVertsPerLineSeg; ++i) { |
- (*vert)[i].fPos = (i & 0x1) ? b : a; |
- if (i & 0x2) { |
- (*vert)[i].fPos += orthVec; |
- (*vert)[i].fCoverage = 0; |
- } else if (i & 0x4) { |
- (*vert)[i].fPos -= orthVec; |
- (*vert)[i].fCoverage = 0; |
- } else { |
- (*vert)[i].fCoverage = coverage; |
- } |
- } |
+ (*vert)[0].fPos = a; |
+ (*vert)[0].fCoverage = coverage; |
+ (*vert)[1].fPos = b; |
+ (*vert)[1].fCoverage = coverage; |
+ (*vert)[2].fPos = a - vec + ortho; |
+ (*vert)[2].fCoverage = 0; |
+ (*vert)[3].fPos = b + vec + ortho; |
+ (*vert)[3].fCoverage = 0; |
+ (*vert)[4].fPos = a - vec - ortho; |
+ (*vert)[4].fCoverage = 0; |
+ (*vert)[5].fPos = b + vec - ortho; |
+ (*vert)[5].fCoverage = 0; |
+ |
if (NULL != toSrc) { |
toSrc->mapPointsWithStride(&(*vert)->fPos, |
sizeof(LineVertex), |
@@ -709,15 +728,13 @@ |
}; |
-bool GrAAHairLinePathRenderer::createLineGeom( |
- const SkPath& path, |
- GrDrawTarget* target, |
- const PtArray& lines, |
- int lineCnt, |
- GrDrawTarget::AutoReleaseGeometry* arg, |
- SkRect* devBounds) { |
+bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path, |
+ GrDrawTarget* target, |
+ const PtArray& lines, |
+ int lineCnt, |
+ GrDrawTarget::AutoReleaseGeometry* arg, |
+ SkRect* devBounds) { |
GrDrawState* drawState = target->drawState(); |
- int rtHeight = drawState->getRenderTarget()->height(); |
const SkMatrix& viewM = drawState->getViewMatrix(); |
@@ -725,8 +742,8 @@ |
int vertCnt = kVertsPerLineSeg * lineCnt; |
- target->drawState()->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(gHairlineLineAttribs)); |
- SkASSERT(sizeof(LineVertex) == target->getDrawState().getVertexSize()); |
+ drawState->setVertexAttribs<gHairlineLineAttribs>(SK_ARRAY_COUNT(gHairlineLineAttribs)); |
+ SkASSERT(sizeof(LineVertex) == drawState->getVertexSize()); |
if (!arg->set(target, vertCnt, 0)) { |
return false; |
@@ -744,7 +761,7 @@ |
} |
devBounds->set(lines.begin(), lines.count()); |
for (int i = 0; i < lineCnt; ++i) { |
- add_line(&lines[2*i], rtHeight, toSrc, drawState->getCoverage(), &verts); |
+ add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts); |
} |
// All the verts computed by add_line are within unit distance of the end points. Add a little |
// extra to account for vector normalization precision. |
@@ -910,7 +927,7 @@ |
GrDrawTarget::AutoStateRestore asr; |
- // createGeom transforms the geometry to device space when the matrix does not have |
+ // createLineGeom transforms the geometry to device space when the matrix does not have |
// perspective. |
if (target->getDrawState().getViewMatrix().hasPerspective()) { |
asr.set(target, GrDrawTarget::kPreserve_ASRInit); |
@@ -933,8 +950,8 @@ |
kVertsPerLineSeg*lines, // startV |
0, // startI |
kVertsPerLineSeg*n, // vCount |
- kIdxsPerLineSeg*n, |
- &devBounds); // iCount |
+ kIdxsPerLineSeg*n, // iCount |
+ &devBounds); |
lines += n; |
} |
} |