Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "GrAAHairLinePathRenderer.h" | 9 #include "GrAAHairLinePathRenderer.h" |
| 10 | 10 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 wInv = SkScalarInvert(wInv); | 353 wInv = SkScalarInvert(wInv); |
| 354 | 354 |
| 355 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); | 355 result->fX = SkScalarMul(normA.fY, lineBW) - SkScalarMul(lineAW, normB.fY); |
| 356 result->fX = SkScalarMul(result->fX, wInv); | 356 result->fX = SkScalarMul(result->fX, wInv); |
| 357 | 357 |
| 358 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); | 358 result->fY = SkScalarMul(lineAW, normB.fX) - SkScalarMul(normA.fX, lineBW); |
| 359 result->fY = SkScalarMul(result->fY, wInv); | 359 result->fY = SkScalarMul(result->fY, wInv); |
| 360 } | 360 } |
| 361 | 361 |
| 362 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, | 362 void bloat_quad(const SkPoint qpts[3], const SkMatrix* toDevice, |
| 363 const SkMatrix* toSrc, Vertex verts[kVertsPerQuad]) { | 363 const SkMatrix* toSrc, Vertex verts[kVertsPerQuad], |
| 364 SkRect* devBounds) { | |
| 364 GrAssert(!toDevice == !toSrc); | 365 GrAssert(!toDevice == !toSrc); |
| 365 // original quad is specified by tri a,b,c | 366 // original quad is specified by tri a,b,c |
| 366 SkPoint a = qpts[0]; | 367 SkPoint a = qpts[0]; |
| 367 SkPoint b = qpts[1]; | 368 SkPoint b = qpts[1]; |
| 368 SkPoint c = qpts[2]; | 369 SkPoint c = qpts[2]; |
| 369 | 370 |
| 370 // this should be in the src space, not dev coords, when we have perspective | 371 // this should be in the src space, not dev coords, when we have perspective |
| 371 GrPathUtils::QuadUVMatrix DevToUV(qpts); | 372 GrPathUtils::QuadUVMatrix DevToUV(qpts); |
| 372 | 373 |
| 373 if (toDevice) { | 374 if (toDevice) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 a0.fPos = a; | 421 a0.fPos = a; |
| 421 a0.fPos += abN; | 422 a0.fPos += abN; |
| 422 a1.fPos = a; | 423 a1.fPos = a; |
| 423 a1.fPos -= abN; | 424 a1.fPos -= abN; |
| 424 | 425 |
| 425 c0.fPos = c; | 426 c0.fPos = c; |
| 426 c0.fPos += cbN; | 427 c0.fPos += cbN; |
| 427 c1.fPos = c; | 428 c1.fPos = c; |
| 428 c1.fPos -= cbN; | 429 c1.fPos -= cbN; |
| 429 | 430 |
| 431 // This point may not be within 1 pixel of a control point. We update the bo unding box to | |
| 432 // include it. | |
| 430 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); | 433 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); |
| 434 devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); | |
| 431 | 435 |
| 432 if (toSrc) { | 436 if (toSrc) { |
| 433 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad ); | 437 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad ); |
| 434 } | 438 } |
| 435 DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); | 439 DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); |
| 436 } | 440 } |
| 437 | 441 |
| 438 void add_quads(const SkPoint p[3], | 442 void add_quads(const SkPoint p[3], |
| 439 int subdiv, | 443 int subdiv, |
| 440 const SkMatrix* toDevice, | 444 const SkMatrix* toDevice, |
| 441 const SkMatrix* toSrc, | 445 const SkMatrix* toSrc, |
| 442 Vertex** vert) { | 446 Vertex** vert, |
| 447 SkRect* devBounds) { | |
| 443 GrAssert(subdiv >= 0); | 448 GrAssert(subdiv >= 0); |
| 444 if (subdiv) { | 449 if (subdiv) { |
| 445 SkPoint newP[5]; | 450 SkPoint newP[5]; |
| 446 SkChopQuadAtHalf(p, newP); | 451 SkChopQuadAtHalf(p, newP); |
| 447 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert); | 452 add_quads(newP + 0, subdiv-1, toDevice, toSrc, vert, devBounds); |
| 448 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert); | 453 add_quads(newP + 2, subdiv-1, toDevice, toSrc, vert, devBounds); |
| 449 } else { | 454 } else { |
| 450 bloat_quad(p, toDevice, toSrc, *vert); | 455 bloat_quad(p, toDevice, toSrc, *vert, devBounds); |
| 451 *vert += kVertsPerQuad; | 456 *vert += kVertsPerQuad; |
| 452 } | 457 } |
| 453 } | 458 } |
| 454 | 459 |
| 455 void add_line(const SkPoint p[2], | 460 void add_line(const SkPoint p[2], |
| 456 int rtHeight, | 461 int rtHeight, |
| 457 const SkMatrix* toSrc, | 462 const SkMatrix* toSrc, |
| 458 Vertex** vert) { | 463 Vertex** vert) { |
| 459 const SkPoint& a = p[0]; | 464 const SkPoint& a = p[0]; |
| 460 const SkPoint& b = p[1]; | 465 const SkPoint& b = p[1]; |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 697 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g} | 702 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g} |
| 698 }; | 703 }; |
| 699 | 704 |
| 700 }; | 705 }; |
| 701 | 706 |
| 702 bool GrAAHairLinePathRenderer::createGeom( | 707 bool GrAAHairLinePathRenderer::createGeom( |
| 703 const SkPath& path, | 708 const SkPath& path, |
| 704 GrDrawTarget* target, | 709 GrDrawTarget* target, |
| 705 int* lineCnt, | 710 int* lineCnt, |
| 706 int* quadCnt, | 711 int* quadCnt, |
| 707 GrDrawTarget::AutoReleaseGeometry* arg) { | 712 GrDrawTarget::AutoReleaseGeometry* arg, |
| 713 SkRect* devBounds) { | |
| 708 GrDrawState* drawState = target->drawState(); | 714 GrDrawState* drawState = target->drawState(); |
| 709 int rtHeight = drawState->getRenderTarget()->height(); | 715 int rtHeight = drawState->getRenderTarget()->height(); |
| 710 | 716 |
| 711 GrIRect devClipBounds; | 717 GrIRect devClipBounds; |
| 712 target->getClip()->getConservativeBounds(drawState->getRenderTarget(), | 718 target->getClip()->getConservativeBounds(drawState->getRenderTarget(), |
| 713 &devClipBounds); | 719 &devClipBounds); |
| 714 | 720 |
| 715 SkMatrix viewM = drawState->getViewMatrix(); | 721 SkMatrix viewM = drawState->getViewMatrix(); |
| 716 | 722 |
| 723 // All the vertices that we compute are within 1 of path control points with the exception of | |
| 724 // one of the bounding vertices for each quad. The add_quads() function will update the bounds | |
| 725 // for each quad added. | |
| 726 *devBounds = path.getBounds(); | |
| 727 viewM.mapRect(devBounds); | |
| 728 devBounds->outset(SK_Scalar1, SK_Scalar1); | |
| 729 | |
| 717 PREALLOC_PTARRAY(128) lines; | 730 PREALLOC_PTARRAY(128) lines; |
| 718 PREALLOC_PTARRAY(128) quads; | 731 PREALLOC_PTARRAY(128) quads; |
| 719 IntArray qSubdivs; | 732 IntArray qSubdivs; |
| 720 *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, | 733 *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, |
| 721 &lines, &quads, &qSubdivs); | 734 &lines, &quads, &qSubdivs); |
| 722 | 735 |
| 723 *lineCnt = lines.count() / 2; | 736 *lineCnt = lines.count() / 2; |
| 724 int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; | 737 int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt; |
| 725 | 738 |
| 726 target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHair lineAttribs)); | 739 target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHair lineAttribs)); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 743 } | 756 } |
| 744 } | 757 } |
| 745 | 758 |
| 746 for (int i = 0; i < *lineCnt; ++i) { | 759 for (int i = 0; i < *lineCnt; ++i) { |
| 747 add_line(&lines[2*i], rtHeight, toSrc, &verts); | 760 add_line(&lines[2*i], rtHeight, toSrc, &verts); |
| 748 } | 761 } |
| 749 | 762 |
| 750 int unsubdivQuadCnt = quads.count() / 3; | 763 int unsubdivQuadCnt = quads.count() / 3; |
| 751 for (int i = 0; i < unsubdivQuadCnt; ++i) { | 764 for (int i = 0; i < unsubdivQuadCnt; ++i) { |
| 752 GrAssert(qSubdivs[i] >= 0); | 765 GrAssert(qSubdivs[i] >= 0); |
| 753 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts); | 766 add_quads(&quads[3*i], qSubdivs[i], toDevice, toSrc, &verts, devBounds); |
| 754 } | 767 } |
| 755 | 768 |
| 756 return true; | 769 return true; |
| 757 } | 770 } |
| 758 | 771 |
| 759 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, | 772 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, |
| 760 const SkStrokeRec& stroke, | 773 const SkStrokeRec& stroke, |
| 761 const GrDrawTarget* target, | 774 const GrDrawTarget* target, |
| 762 bool antiAlias) const { | 775 bool antiAlias) const { |
| 763 if (!stroke.isHairlineStyle() || !antiAlias) { | 776 if (!stroke.isHairlineStyle() || !antiAlias) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 774 } | 787 } |
| 775 | 788 |
| 776 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, | 789 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, |
| 777 const SkStrokeRec&, | 790 const SkStrokeRec&, |
| 778 GrDrawTarget* target, | 791 GrDrawTarget* target, |
| 779 bool antiAlias) { | 792 bool antiAlias) { |
| 780 | 793 |
| 781 int lineCnt; | 794 int lineCnt; |
| 782 int quadCnt; | 795 int quadCnt; |
| 783 GrDrawTarget::AutoReleaseGeometry arg; | 796 GrDrawTarget::AutoReleaseGeometry arg; |
| 797 SkRect devBounds; | |
| 798 | |
| 784 if (!this->createGeom(path, | 799 if (!this->createGeom(path, |
| 785 target, | 800 target, |
| 786 &lineCnt, | 801 &lineCnt, |
| 787 &quadCnt, | 802 &quadCnt, |
| 788 &arg)) { | 803 &arg, |
| 804 &devBounds)) { | |
| 789 return false; | 805 return false; |
| 790 } | 806 } |
| 791 | 807 |
| 792 GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); | 808 GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); |
| 793 GrDrawState* drawState = target->drawState(); | 809 GrDrawState* drawState = target->drawState(); |
| 794 | 810 |
| 795 GrDrawState::AutoDeviceCoordDraw adcd; | 811 GrDrawState::AutoDeviceCoordDraw adcd; |
| 796 // createGeom transforms the geometry to device space when the matrix does n ot have | 812 // createGeom transforms the geometry to device space when the matrix does n ot have |
| 797 // perspective. | 813 // perspective. |
| 798 if (!drawState->getViewMatrix().hasPerspective()) { | 814 if (!drawState->getViewMatrix().hasPerspective()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 809 // the edge effects share this stage with glyph rendering | 825 // the edge effects share this stage with glyph rendering |
| 810 // (kGlyphMaskStage in GrTextContext) && SW path rendering | 826 // (kGlyphMaskStage in GrTextContext) && SW path rendering |
| 811 // (kPathMaskStage in GrSWMaskHelper) | 827 // (kPathMaskStage in GrSWMaskHelper) |
| 812 kEdgeEffectStage = GrPaint::kTotalStages, | 828 kEdgeEffectStage = GrPaint::kTotalStages, |
| 813 }; | 829 }; |
| 814 static const int kEdgeAttrIndex = 1; | 830 static const int kEdgeAttrIndex = 1; |
| 815 | 831 |
| 816 GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); | 832 GrEffectRef* hairLineEffect = HairLineEdgeEffect::Create(); |
| 817 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); | 833 GrEffectRef* hairQuadEffect = HairQuadEdgeEffect::Create(); |
| 818 | 834 |
| 835 // Check devBounds | |
| 836 #if GR_DEBUG | |
|
robertphillips
2013/05/20 13:50:42
I have needed an SkRect::contains with a tolerance
| |
| 837 SkRect tolDevBounds = devBounds; | |
| 838 tolDevBounds.outset(SK_Scalar1 / 10000, SK_Scalar1 / 10000); | |
| 839 SkRect actualBounds; | |
| 840 Vertex* verts = reinterpret_cast<Vertex*>(arg.vertices()); | |
| 841 int vCount = kVertsPerLineSeg * lineCnt + kVertsPerQuad * quadCnt; | |
| 842 bool first = true; | |
| 843 for (int i = 0; i < vCount; ++i) { | |
| 844 SkPoint pos = verts[i].fPos; | |
| 845 // This is a hack to workaround the fact that we move some degenerate se gments offscreen. | |
| 846 if (SK_ScalarMax == pos.fX) { | |
| 847 continue; | |
| 848 } | |
| 849 drawState->getViewMatrix().mapPoints(&pos, 1); | |
| 850 if (first) { | |
| 851 actualBounds.set(pos.fX, pos.fY, pos.fX, pos.fY); | |
| 852 first = false; | |
| 853 } else { | |
| 854 actualBounds.growToInclude(pos.fX, pos.fY); | |
| 855 } | |
| 856 } | |
| 857 if (!first) { | |
| 858 GrAssert(tolDevBounds.contains(actualBounds)); | |
| 859 } | |
| 860 #endif | |
| 861 | |
| 819 target->setIndexSourceToBuffer(fLinesIndexBuffer); | 862 target->setIndexSourceToBuffer(fLinesIndexBuffer); |
| 820 int lines = 0; | 863 int lines = 0; |
| 821 int nBufLines = fLinesIndexBuffer->maxQuads(); | 864 int nBufLines = fLinesIndexBuffer->maxQuads(); |
| 822 drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unre f(); | 865 drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unre f(); |
| 823 while (lines < lineCnt) { | 866 while (lines < lineCnt) { |
| 824 int n = GrMin(lineCnt - lines, nBufLines); | 867 int n = GrMin(lineCnt - lines, nBufLines); |
| 825 target->drawIndexed(kTriangles_GrPrimitiveType, | 868 target->drawIndexed(kTriangles_GrPrimitiveType, |
| 826 kVertsPerLineSeg*lines, // startV | 869 kVertsPerLineSeg*lines, // startV |
| 827 0, // startI | 870 0, // startI |
| 828 kVertsPerLineSeg*n, // vCount | 871 kVertsPerLineSeg*n, // vCount |
| 829 kIdxsPerLineSeg*n); // iCount | 872 kIdxsPerLineSeg*n, |
| 873 &devBounds); // iCount | |
| 830 lines += n; | 874 lines += n; |
| 831 } | 875 } |
| 832 | 876 |
| 833 target->setIndexSourceToBuffer(fQuadsIndexBuffer); | 877 target->setIndexSourceToBuffer(fQuadsIndexBuffer); |
| 834 int quads = 0; | 878 int quads = 0; |
| 835 drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unre f(); | 879 drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unre f(); |
| 836 while (quads < quadCnt) { | 880 while (quads < quadCnt) { |
| 837 int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); | 881 int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer); |
| 838 target->drawIndexed(kTriangles_GrPrimitiveType, | 882 target->drawIndexed(kTriangles_GrPrimitiveType, |
| 839 4 * lineCnt + kVertsPerQuad*quads, // startV | 883 4 * lineCnt + kVertsPerQuad*quads, // startV |
| 840 0, // startI | 884 0, // startI |
| 841 kVertsPerQuad*n, // vCount | 885 kVertsPerQuad*n, // vCount |
| 842 kIdxsPerQuad*n); // iCount | 886 kIdxsPerQuad*n, // iCount |
| 887 &devBounds); | |
| 843 quads += n; | 888 quads += n; |
| 844 } | 889 } |
| 845 target->resetIndexSource(); | 890 target->resetIndexSource(); |
| 846 | 891 |
| 847 return true; | 892 return true; |
| 848 } | 893 } |
| OLD | NEW |