Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: src/gpu/GrAAHairLinePathRenderer.cpp

Issue 15465005: Reland path bounds change with correct bounds for convex and hairline path renderers. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: tighter tolerances Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/gpu/GrAAHairLinePathRenderer.h ('k') | src/gpu/GrDefaultPathRenderer.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/gpu/GrAAHairLinePathRenderer.h ('k') | src/gpu/GrDefaultPathRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698