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

Side by Side Diff: src/gpu/batches/GrAAConvexTessellator.cpp

Issue 2301353004: Make AALinearizingConvexPathRenderer able to handle stroke and fill (Closed)
Patch Set: Fix bug Created 4 years, 3 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
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrAAConvexTessellator.h" 8 #include "GrAAConvexTessellator.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkPath.h" 10 #include "SkPath.h"
(...skipping 14 matching lines...) Expand all
25 static const SkScalar kQuadTolerance = 0.2f; 25 static const SkScalar kQuadTolerance = 0.2f;
26 static const SkScalar kCubicTolerance = 0.2f; 26 static const SkScalar kCubicTolerance = 0.2f;
27 static const SkScalar kConicTolerance = 0.5f; 27 static const SkScalar kConicTolerance = 0.5f;
28 28
29 // dot product below which we use a round cap between curve segments 29 // dot product below which we use a round cap between curve segments
30 static const SkScalar kRoundCapThreshold = 0.8f; 30 static const SkScalar kRoundCapThreshold = 0.8f;
31 31
32 // dot product above which we consider two adjacent curves to be part of the "sa me" curve 32 // dot product above which we consider two adjacent curves to be part of the "sa me" curve
33 static const SkScalar kCurveConnectionThreshold = 0.8f; 33 static const SkScalar kCurveConnectionThreshold = 0.8f;
34 34
35 static SkScalar intersect(const SkPoint& p0, const SkPoint& n0, 35 static bool intersect(const SkPoint& p0, const SkPoint& n0,
36 const SkPoint& p1, const SkPoint& n1) { 36 const SkPoint& p1, const SkPoint& n1,
37 SkScalar* t) {
37 const SkPoint v = p1 - p0; 38 const SkPoint v = p1 - p0;
38 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX; 39 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX;
39 return (v.fX * n1.fY - v.fY * n1.fX) / perpDot; 40 if (SkScalarNearlyZero(perpDot)) {
41 return false;
42 }
43 *t = (v.fX * n1.fY - v.fY * n1.fX) / perpDot;
44 SkASSERT(SkScalarIsFinite(*t));
45 return true;
40 } 46 }
41 47
42 // This is a special case version of intersect where we have the vector 48 // This is a special case version of intersect where we have the vector
43 // perpendicular to the second line rather than the vector parallel to it. 49 // perpendicular to the second line rather than the vector parallel to it.
44 static SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0, 50 static SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0,
45 const SkPoint& p1, const SkPoint& perp) { 51 const SkPoint& p1, const SkPoint& perp) {
46 const SkPoint v = p1 - p0; 52 const SkPoint v = p1 - p0;
47 SkScalar perpDot = n0.dot(perp); 53 SkScalar perpDot = n0.dot(perp);
48 return v.dot(perp) / perpDot; 54 return v.dot(perp) / perpDot;
49 } 55 }
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 // The polygon state is captured in the Ring class while the GrAAConvexTessellat or 217 // The polygon state is captured in the Ring class while the GrAAConvexTessellat or
212 // controls the iteration. The CandidateVerts holds the formative points for the 218 // controls the iteration. The CandidateVerts holds the formative points for the
213 // next ring. 219 // next ring.
214 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { 220 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) {
215 if (!this->extractFromPath(m, path)) { 221 if (!this->extractFromPath(m, path)) {
216 return false; 222 return false;
217 } 223 }
218 224
219 SkScalar coverage = 1.0f; 225 SkScalar coverage = 1.0f;
220 SkScalar scaleFactor = 0.0f; 226 SkScalar scaleFactor = 0.0f;
221 if (fStrokeWidth >= 0.0f) { 227
228 if (SkStrokeRec::kStrokeAndFill_Style == fStyle) {
222 SkASSERT(m.isSimilarity()); 229 SkASSERT(m.isSimilarity());
223 scaleFactor = m.getMaxScale(); // x and y scale are the same 230 scaleFactor = m.getMaxScale(); // x and y scale are the same
224 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; 231 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
232 Ring outerStrokeAndAARing;
233 this->createOuterRing(fInitialRing,
234 effectiveStrokeWidth / 2 + kAntialiasingRadius, 0. 0,
235 &outerStrokeAndAARing);
236
237 // discard all the triangles added between the originating ring and the new outer ring
238 fIndices.rewind();
239
240 outerStrokeAndAARing.init(*this);
241
242 outerStrokeAndAARing.makeOriginalRing();
243
244 // Add the outer stroke ring's normals to the originating ring's normals
245 // so it can also act as an originating ring
246 fNorms.setCount(fNorms.count() + outerStrokeAndAARing.numPts());
247 for (int i = 0; i < outerStrokeAndAARing.numPts(); ++i) {
248 SkASSERT(outerStrokeAndAARing.index(i) < fNorms.count());
249 fNorms[outerStrokeAndAARing.index(i)] = outerStrokeAndAARing.norm(i) ;
250 }
251
252 // the bisectors are only needed for the computation of the outer ring
253 fBisectors.rewind();
254
255 Ring* insetAARing;
256 this->createInsetRings(outerStrokeAndAARing,
257 0.0f, 0.0f, 2*kAntialiasingRadius, 1.0f,
258 &insetAARing);
259
260 SkDEBUGCODE(this->validate();)
261 return true;
262 }
263
264 if (SkStrokeRec::kStroke_Style == fStyle) {
265 SkASSERT(fStrokeWidth >= 0.0f);
266 SkASSERT(m.isSimilarity());
267 scaleFactor = m.getMaxScale(); // x and y scale are the same
268 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
225 Ring outerStrokeRing; 269 Ring outerStrokeRing;
226 this->createOuterRing(fInitialRing, effectiveStrokeWidth / 2 - kAntialia singRadius, 270 this->createOuterRing(fInitialRing, effectiveStrokeWidth / 2 - kAntialia singRadius,
227 coverage, &outerStrokeRing); 271 coverage, &outerStrokeRing);
228 outerStrokeRing.init(*this); 272 outerStrokeRing.init(*this);
229 Ring outerAARing; 273 Ring outerAARing;
230 this->createOuterRing(outerStrokeRing, kAntialiasingRadius * 2, 0.0f, &o uterAARing); 274 this->createOuterRing(outerStrokeRing, kAntialiasingRadius * 2, 0.0f, &o uterAARing);
231 } else { 275 } else {
232 Ring outerAARing; 276 Ring outerAARing;
233 this->createOuterRing(fInitialRing, kAntialiasingRadius, 0.0f, &outerAAR ing); 277 this->createOuterRing(fInitialRing, kAntialiasingRadius, 0.0f, &outerAAR ing);
234 } 278 }
235 279
236 // the bisectors are only needed for the computation of the outer ring 280 // the bisectors are only needed for the computation of the outer ring
237 fBisectors.rewind(); 281 fBisectors.rewind();
238 if (fStrokeWidth >= 0.0f && fInitialRing.numPts() > 2) { 282 if (SkStrokeRec::kStroke_Style == fStyle && fInitialRing.numPts() > 2) {
283 SkASSERT(fStrokeWidth >= 0.0f);
239 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; 284 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
240 Ring* insetStrokeRing; 285 Ring* insetStrokeRing;
241 SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius; 286 SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius;
242 if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, co verage, 287 if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, co verage,
243 &insetStrokeRing)) { 288 &insetStrokeRing)) {
244 Ring* insetAARing; 289 Ring* insetAARing;
245 this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, stro keDepth + 290 this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, stro keDepth +
246 kAntialiasingRadius * 2, 0.0f, &insetAARing); 291 kAntialiasingRadius * 2, 0.0f, &insetAARing);
247 } 292 }
248 } else { 293 } else {
249 Ring* insetAARing; 294 Ring* insetAARing;
250 this->createInsetRings(fInitialRing, 0.0f, 0.5f, kAntialiasingRadius, 1. 0f, &insetAARing); 295 this->createInsetRings(fInitialRing, 0.0f, 0.5f, kAntialiasingRadius, 1. 0f, &insetAARing);
251 } 296 }
252 297
253 SkDEBUGCODE(this->validate();) 298 SkDEBUGCODE(this->validate();)
254 return true; 299 return true;
255 } 300 }
256 301
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 428
384 // Make all the normals face outwards rather than along the edge 429 // Make all the normals face outwards rather than along the edge
385 for (int cur = 0; cur < fNorms.count(); ++cur) { 430 for (int cur = 0; cur < fNorms.count(); ++cur) {
386 fNorms[cur].setOrthog(fNorms[cur], fSide); 431 fNorms[cur].setOrthog(fNorms[cur], fSide);
387 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length())); 432 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
388 } 433 }
389 434
390 this->computeBisectors(); 435 this->computeBisectors();
391 } else if (this->numPts() == 2) { 436 } else if (this->numPts() == 2) {
392 // We've got two points, so we're degenerate. 437 // We've got two points, so we're degenerate.
393 if (fStrokeWidth < 0.0f) { 438 if (fStyle == SkStrokeRec::kFill_Style) {
394 // it's a fill, so we don't need to worry about degenerate paths 439 // it's a fill, so we don't need to worry about degenerate paths
395 return false; 440 return false;
396 } 441 }
397 // For stroking, we still need to process the degenerate path, so fix it up 442 // For stroking, we still need to process the degenerate path, so fix it up
398 fSide = SkPoint::kLeft_Side; 443 fSide = SkPoint::kLeft_Side;
399 444
400 // Make all the normals face outwards rather than along the edge 445 // Make all the normals face outwards rather than along the edge
401 for (int cur = 0; cur < fNorms.count(); ++cur) { 446 for (int cur = 0; cur < fNorms.count(); ++cur) {
402 fNorms[cur].setOrthog(fNorms[cur], fSide); 447 fNorms[cur].setOrthog(fNorms[cur], fSide);
403 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length())); 448 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 int lastIdx = previousRing.index(numPts - 1); 624 int lastIdx = previousRing.index(numPts - 1);
580 this->addTri(lastIdx, firstPerpIdx, previousRing.index(0)); 625 this->addTri(lastIdx, firstPerpIdx, previousRing.index(0));
581 this->addTri(lastIdx, lastPerpIdx, firstPerpIdx); 626 this->addTri(lastIdx, lastPerpIdx, firstPerpIdx);
582 627
583 this->validate(); 628 this->validate();
584 } 629 }
585 630
586 // Something went wrong in the creation of the next ring. If we're filling the s hape, just go ahead 631 // Something went wrong in the creation of the next ring. If we're filling the s hape, just go ahead
587 // and fan it. 632 // and fan it.
588 void GrAAConvexTessellator::terminate(const Ring& ring) { 633 void GrAAConvexTessellator::terminate(const Ring& ring) {
589 if (fStrokeWidth < 0.0f) { 634 if (fStyle != SkStrokeRec::kStroke_Style) {
590 this->fanRing(ring); 635 this->fanRing(ring);
591 } 636 }
592 } 637 }
593 638
594 static SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar initialCoverage, 639 static SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar initialCoverage,
595 SkScalar targetDepth, SkScalar targetCoverage) { 640 SkScalar targetDepth, SkScalar targetCoverage) {
596 if (SkScalarNearlyEqual(initialDepth, targetDepth)) { 641 if (SkScalarNearlyEqual(initialDepth, targetDepth)) {
597 return targetCoverage; 642 return targetCoverage;
598 } 643 }
599 SkScalar result = (depth - initialDepth) / (targetDepth - initialDepth) * 644 SkScalar result = (depth - initialDepth) / (targetDepth - initialDepth) *
600 (targetCoverage - initialCoverage) + initialCoverage; 645 (targetCoverage - initialCoverage) + initialCoverage;
601 return SkScalarClampMax(result, 1.0f); 646 return SkScalarClampMax(result, 1.0f);
602 } 647 }
603 648
604 // return true when processing is complete 649 // return true when processing is complete
605 bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing , 650 bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing ,
606 SkScalar initialDepth, SkScalar init ialCoverage, 651 SkScalar initialDepth, SkScalar init ialCoverage,
607 SkScalar targetDepth, SkScalar targe tCoverage, 652 SkScalar targetDepth, SkScalar targe tCoverage,
608 bool forceNew) { 653 bool forceNew) {
609 bool done = false; 654 bool done = false;
610 655
611 fCandidateVerts.rewind(); 656 fCandidateVerts.rewind();
612 657
613 // Loop through all the points in the ring and find the intersection with th e smallest depth 658 // Loop through all the points in the ring and find the intersection with th e smallest depth
614 SkScalar minDist = SK_ScalarMax, minT = 0.0f; 659 SkScalar minDist = SK_ScalarMax, minT = 0.0f;
615 int minEdgeIdx = -1; 660 int minEdgeIdx = -1;
616 661
617 for (int cur = 0; cur < lastRing.numPts(); ++cur) { 662 for (int cur = 0; cur < lastRing.numPts(); ++cur) {
618 int next = (cur + 1) % lastRing.numPts(); 663 int next = (cur + 1) % lastRing.numPts();
619 SkScalar t = intersect(this->point(lastRing.index(cur)), lastRing.bisec tor(cur), 664
620 this->point(lastRing.index(next)), lastRing.bisec tor(next)); 665 SkScalar t;
666 bool result = intersect(this->point(lastRing.index(cur)), lastRing.bise ctor(cur),
667 this->point(lastRing.index(next)), lastRing.bise ctor(next),
668 &t);
669 if (!result) {
670 continue;
671 }
621 SkScalar dist = -t * lastRing.norm(cur).dot(lastRing.bisector(cur)); 672 SkScalar dist = -t * lastRing.norm(cur).dot(lastRing.bisector(cur));
622 673
623 if (minDist > dist) { 674 if (minDist > dist) {
624 minDist = dist; 675 minDist = dist;
625 minT = t; 676 minT = t;
626 minEdgeIdx = cur; 677 minEdgeIdx = cur;
627 } 678 }
628 } 679 }
629 680
630 if (minEdgeIdx == -1) { 681 if (minEdgeIdx == -1) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 dst[i] = nextRing->index(dst[i]); 789 dst[i] = nextRing->index(dst[i]);
739 } 790 }
740 791
741 for (int i = 0; i < lastRing.numPts(); ++i) { 792 for (int i = 0; i < lastRing.numPts(); ++i) {
742 int next = (i + 1) % lastRing.numPts(); 793 int next = (i + 1) % lastRing.numPts();
743 794
744 this->addTri(lastRing.index(i), lastRing.index(next), dst[next]); 795 this->addTri(lastRing.index(i), lastRing.index(next), dst[next]);
745 this->addTri(lastRing.index(i), dst[next], dst[i]); 796 this->addTri(lastRing.index(i), dst[next], dst[i]);
746 } 797 }
747 798
748 if (done && fStrokeWidth < 0.0f) { 799 if (done && fStyle != SkStrokeRec::kStroke_Style) {
749 // fill 800 // fill or stroke-and-fill
750 this->fanRing(*nextRing); 801 this->fanRing(*nextRing);
751 } 802 }
752 803
753 if (nextRing->numPts() < 3) { 804 if (nextRing->numPts() < 3) {
754 done = true; 805 done = true;
755 } 806 }
756 return done; 807 return done;
757 } 808 }
758 809
759 void GrAAConvexTessellator::validate() const { 810 void GrAAConvexTessellator::validate() const {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 fNorms.pop(); 904 fNorms.pop();
854 fCurveState.pop(); 905 fCurveState.pop();
855 // double-check that the new last point is not a duplicate of the new po int. In an ideal 906 // double-check that the new last point is not a duplicate of the new po int. In an ideal
856 // world this wouldn't be necessary (since it's only possible for non-co nvex paths), but 907 // world this wouldn't be necessary (since it's only possible for non-co nvex paths), but
857 // floating point precision issues mean it can actually happen on paths that were determined 908 // floating point precision issues mean it can actually happen on paths that were determined
858 // to be convex. 909 // to be convex.
859 if (duplicate_pt(p, this->lastPoint())) { 910 if (duplicate_pt(p, this->lastPoint())) {
860 return; 911 return;
861 } 912 }
862 } 913 }
863 SkScalar initialRingCoverage = fStrokeWidth < 0.0f ? 0.5f : 1.0f; 914 SkScalar initialRingCoverage = (SkStrokeRec::kFill_Style == fStyle) ? 0.5f : 1.0f;
864 this->addPt(p, 0.0f, initialRingCoverage, false, curve); 915 this->addPt(p, 0.0f, initialRingCoverage, false, curve);
865 if (this->numPts() > 1) { 916 if (this->numPts() > 1) {
866 *fNorms.push() = fPts.top() - fPts[fPts.count()-2]; 917 *fNorms.push() = fPts.top() - fPts[fPts.count()-2];
867 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top()); 918 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top());
868 SkASSERT(len > 0.0f); 919 SkASSERT(len > 0.0f);
869 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length())); 920 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length()));
870 } 921 }
871 } 922 }
872 923
873 void GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, CurveState curv e) { 924 void GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, CurveState curv e) {
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 1094
1044 SkString num; 1095 SkString num;
1045 num.printf("%d", i); 1096 num.printf("%d", i);
1046 canvas->drawText(num.c_str(), num.size(), 1097 canvas->drawText(num.c_str(), num.size(),
1047 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ), 1098 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ),
1048 paint); 1099 paint);
1049 } 1100 }
1050 } 1101 }
1051 1102
1052 #endif 1103 #endif
OLDNEW
« no previous file with comments | « src/gpu/batches/GrAAConvexTessellator.h ('k') | src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698