OLD | NEW |
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 18 matching lines...) Expand all Loading... |
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 static SkScalar intersect(const SkPoint& p0, const SkPoint& n0, | 32 static SkScalar intersect(const SkPoint& p0, const SkPoint& n0, |
33 const SkPoint& p1, const SkPoint& n1) { | 33 const SkPoint& p1, const SkPoint& n1) { |
34 const SkPoint v = p1 - p0; | 34 const SkPoint v = p1 - p0; |
35 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX; | 35 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX; |
36 return (v.fX * n1.fY - v.fY * n1.fX) / perpDot; | 36 return (v.fX * n1.fY - v.fY * n1.fX) / perpDot; |
37 } | 37 } |
38 | 38 |
39 // This is a special case version of intersect where we have the vector | 39 // This is a special case version of intersect where we have the vector |
40 // perpendicular to the second line rather than the vector parallel to it. | 40 // perpendicular to the second line rather than the vector parallel to it. |
41 static SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0, | 41 static SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0, |
42 const SkPoint& p1, const SkPoint& perp) { | 42 const SkPoint& p1, const SkPoint& perp) { |
43 const SkPoint v = p1 - p0; | 43 const SkPoint v = p1 - p0; |
44 SkScalar perpDot = n0.dot(perp); | 44 SkScalar perpDot = n0.dot(perp); |
45 return v.dot(perp) / perpDot; | 45 return v.dot(perp) / perpDot; |
46 } | 46 } |
47 | 47 |
48 static bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) { | 48 static bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) { |
49 SkScalar distSq = p0.distanceToSqd(p1); | 49 SkScalar distSq = p0.distanceToSqd(p1); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 | 135 |
136 int prev = fBisectors.count() - 1; | 136 int prev = fBisectors.count() - 1; |
137 for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) { | 137 for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) { |
138 fBisectors[cur] = fNorms[cur] + fNorms[prev]; | 138 fBisectors[cur] = fNorms[cur] + fNorms[prev]; |
139 if (!fBisectors[cur].normalize()) { | 139 if (!fBisectors[cur].normalize()) { |
140 SkASSERT(SkPoint::kLeft_Side == fSide || SkPoint::kRight_Side == fSi
de); | 140 SkASSERT(SkPoint::kLeft_Side == fSide || SkPoint::kRight_Side == fSi
de); |
141 fBisectors[cur].setOrthog(fNorms[cur], (SkPoint::Side)-fSide); | 141 fBisectors[cur].setOrthog(fNorms[cur], (SkPoint::Side)-fSide); |
142 SkVector other; | 142 SkVector other; |
143 other.setOrthog(fNorms[prev], fSide); | 143 other.setOrthog(fNorms[prev], fSide); |
144 fBisectors[cur] += other; | 144 fBisectors[cur] += other; |
145 SkAssertResult(fBisectors[cur].normalize()); | 145 SkAssertResult(fBisectors[cur].normalize()); |
146 } else { | 146 } else { |
147 fBisectors[cur].negate(); // make the bisector face in | 147 fBisectors[cur].negate(); // make the bisector face in |
148 } | 148 } |
149 | 149 |
150 SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length())); | 150 SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length())); |
151 } | 151 } |
152 } | 152 } |
153 | 153 |
154 // Create as many rings as we need to (up to a predefined limit) to reach the sp
ecified target | 154 // Create as many rings as we need to (up to a predefined limit) to reach the sp
ecified target |
155 // depth. If we are in fill mode, the final ring will automatically be fanned. | 155 // depth. If we are in fill mode, the final ring will automatically be fanned. |
156 bool GrAAConvexTessellator::createInsetRings(Ring& previousRing, SkScalar initia
lDepth, | 156 bool GrAAConvexTessellator::createInsetRings(Ring& previousRing, SkScalar initia
lDepth, |
157 SkScalar initialCoverage, SkScalar
targetDepth, | 157 SkScalar initialCoverage, SkScalar
targetDepth, |
158 SkScalar targetCoverage, Ring** fin
alRing) { | 158 SkScalar targetCoverage, Ring** fin
alRing) { |
159 static const int kMaxNumRings = 8; | 159 static const int kMaxNumRings = 8; |
160 | 160 |
161 if (previousRing.numPts() < 3) { | 161 if (previousRing.numPts() < 3) { |
162 return false; | 162 return false; |
163 } | 163 } |
164 Ring* currentRing = &previousRing; | 164 Ring* currentRing = &previousRing; |
165 int i; | 165 int i; |
166 for (i = 0; i < kMaxNumRings; ++i) { | 166 for (i = 0; i < kMaxNumRings; ++i) { |
167 Ring* nextRing = this->getNextRing(currentRing); | 167 Ring* nextRing = this->getNextRing(currentRing); |
168 SkASSERT(nextRing != currentRing); | 168 SkASSERT(nextRing != currentRing); |
169 | 169 |
170 bool done = this->createInsetRing(*currentRing, nextRing, initialDepth,
initialCoverage, | 170 bool done = this->createInsetRing(*currentRing, nextRing, initialDepth,
initialCoverage, |
171 targetDepth, targetCoverage, i == 0); | 171 targetDepth, targetCoverage, i == 0); |
172 currentRing = nextRing; | 172 currentRing = nextRing; |
173 if (done) { | 173 if (done) { |
174 break; | 174 break; |
175 } | 175 } |
176 currentRing->init(*this); | 176 currentRing->init(*this); |
177 } | 177 } |
178 | 178 |
179 if (kMaxNumRings == i) { | 179 if (kMaxNumRings == i) { |
180 // Bail if we've exceeded the amount of time we want to throw at this. | 180 // Bail if we've exceeded the amount of time we want to throw at this. |
(...skipping 15 matching lines...) Expand all Loading... |
196 // controls the iteration. The CandidateVerts holds the formative points for the | 196 // controls the iteration. The CandidateVerts holds the formative points for the |
197 // next ring. | 197 // next ring. |
198 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { | 198 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { |
199 if (!this->extractFromPath(m, path)) { | 199 if (!this->extractFromPath(m, path)) { |
200 return false; | 200 return false; |
201 } | 201 } |
202 | 202 |
203 SkScalar coverage = 1.0f; | 203 SkScalar coverage = 1.0f; |
204 SkScalar scaleFactor = 0.0f; | 204 SkScalar scaleFactor = 0.0f; |
205 if (fStrokeWidth >= 0.0f) { | 205 if (fStrokeWidth >= 0.0f) { |
206 SkASSERT(m.isSimilarity()); | 206 SkASSERT(m.isSimilarity()); |
207 scaleFactor = m.getMaxScale(); // x and y scale are the same | 207 scaleFactor = m.getMaxScale(); // x and y scale are the same |
208 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; | 208 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; |
209 Ring outerStrokeRing; | 209 Ring outerStrokeRing; |
210 this->createOuterRing(fInitialRing, effectiveStrokeWidth / 2 - kAntialia
singRadius, | 210 this->createOuterRing(fInitialRing, effectiveStrokeWidth / 2 - kAntialia
singRadius, |
211 coverage, &outerStrokeRing); | 211 coverage, &outerStrokeRing); |
212 outerStrokeRing.init(*this); | 212 outerStrokeRing.init(*this); |
213 Ring outerAARing; | 213 Ring outerAARing; |
214 this->createOuterRing(outerStrokeRing, kAntialiasingRadius * 2, 0.0f, &o
uterAARing); | 214 this->createOuterRing(outerStrokeRing, kAntialiasingRadius * 2, 0.0f, &o
uterAARing); |
215 } else { | 215 } else { |
216 Ring outerAARing; | 216 Ring outerAARing; |
217 this->createOuterRing(fInitialRing, kAntialiasingRadius, 0.0f, &outerAAR
ing); | 217 this->createOuterRing(fInitialRing, kAntialiasingRadius, 0.0f, &outerAAR
ing); |
218 } | 218 } |
219 | 219 |
220 // the bisectors are only needed for the computation of the outer ring | 220 // the bisectors are only needed for the computation of the outer ring |
221 fBisectors.rewind(); | 221 fBisectors.rewind(); |
222 if (fStrokeWidth >= 0.0f && fInitialRing.numPts() > 2) { | 222 if (fStrokeWidth >= 0.0f && fInitialRing.numPts() > 2) { |
223 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; | 223 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; |
224 Ring* insetStrokeRing; | 224 Ring* insetStrokeRing; |
225 SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius; | 225 SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius; |
226 if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, co
verage, | 226 if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, co
verage, |
227 &insetStrokeRing)) { | 227 &insetStrokeRing)) { |
228 Ring* insetAARing; | 228 Ring* insetAARing; |
229 this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, stro
keDepth + | 229 this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, stro
keDepth + |
230 kAntialiasingRadius * 2, 0.0f, &insetAARing); | 230 kAntialiasingRadius * 2, 0.0f, &insetAARing); |
231 } | 231 } |
232 } else { | 232 } else { |
233 Ring* insetAARing; | 233 Ring* insetAARing; |
234 this->createInsetRings(fInitialRing, 0.0f, 0.5f, kAntialiasingRadius, 1.
0f, &insetAARing); | 234 this->createInsetRings(fInitialRing, 0.0f, 0.5f, kAntialiasingRadius, 1.
0f, &insetAARing); |
235 } | 235 } |
236 | 236 |
237 SkDEBUGCODE(this->validate();) | 237 SkDEBUGCODE(this->validate();) |
238 return true; | 238 return true; |
239 } | 239 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 } | 366 } |
367 | 367 |
368 // Make all the normals face outwards rather than along the edge | 368 // Make all the normals face outwards rather than along the edge |
369 for (int cur = 0; cur < fNorms.count(); ++cur) { | 369 for (int cur = 0; cur < fNorms.count(); ++cur) { |
370 fNorms[cur].setOrthog(fNorms[cur], fSide); | 370 fNorms[cur].setOrthog(fNorms[cur], fSide); |
371 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length())); | 371 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length())); |
372 } | 372 } |
373 | 373 |
374 this->computeBisectors(); | 374 this->computeBisectors(); |
375 } else if (this->numPts() == 2) { | 375 } else if (this->numPts() == 2) { |
376 // We've got two points, so we're degenerate. | 376 // We've got two points, so we're degenerate. |
377 if (fStrokeWidth < 0.0f) { | 377 if (fStrokeWidth < 0.0f) { |
378 // it's a fill, so we don't need to worry about degenerate paths | 378 // it's a fill, so we don't need to worry about degenerate paths |
379 return false; | 379 return false; |
380 } | 380 } |
381 // For stroking, we still need to process the degenerate path, so fix it
up | 381 // For stroking, we still need to process the degenerate path, so fix it
up |
382 fSide = SkPoint::kLeft_Side; | 382 fSide = SkPoint::kLeft_Side; |
383 | 383 |
384 // Make all the normals face outwards rather than along the edge | 384 // Make all the normals face outwards rather than along the edge |
385 for (int cur = 0; cur < fNorms.count(); ++cur) { | 385 for (int cur = 0; cur < fNorms.count(); ++cur) { |
386 fNorms[cur].setOrthog(fNorms[cur], fSide); | 386 fNorms[cur].setOrthog(fNorms[cur], fSide); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 } | 422 } |
423 | 423 |
424 void GrAAConvexTessellator::fanRing(const Ring& ring) { | 424 void GrAAConvexTessellator::fanRing(const Ring& ring) { |
425 // fan out from point 0 | 425 // fan out from point 0 |
426 int startIdx = ring.index(0); | 426 int startIdx = ring.index(0); |
427 for (int cur = ring.numPts() - 2; cur >= 0; --cur) { | 427 for (int cur = ring.numPts() - 2; cur >= 0; --cur) { |
428 this->addTri(startIdx, ring.index(cur), ring.index(cur + 1)); | 428 this->addTri(startIdx, ring.index(cur), ring.index(cur + 1)); |
429 } | 429 } |
430 } | 430 } |
431 | 431 |
432 void GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar o
utset, | 432 void GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar o
utset, |
433 SkScalar coverage, Ring* nextRing) { | 433 SkScalar coverage, Ring* nextRing) { |
434 const int numPts = previousRing.numPts(); | 434 const int numPts = previousRing.numPts(); |
435 if (numPts == 0) { | 435 if (numPts == 0) { |
436 return; | 436 return; |
437 } | 437 } |
438 | 438 |
439 int prev = numPts - 1; | 439 int prev = numPts - 1; |
440 int lastPerpIdx = -1, firstPerpIdx = -1; | 440 int lastPerpIdx = -1, firstPerpIdx = -1; |
441 | 441 |
442 const SkScalar outsetSq = SkScalarMul(outset, outset); | 442 const SkScalar outsetSq = SkScalarMul(outset, outset); |
443 SkScalar miterLimitSq = SkScalarMul(outset, fMiterLimit); | 443 SkScalar miterLimitSq = SkScalarMul(outset, fMiterLimit); |
444 miterLimitSq = SkScalarMul(miterLimitSq, miterLimitSq); | 444 miterLimitSq = SkScalarMul(miterLimitSq, miterLimitSq); |
445 for (int cur = 0; cur < numPts; ++cur) { | 445 for (int cur = 0; cur < numPts; ++cur) { |
446 int originalIdx = previousRing.index(cur); | 446 int originalIdx = previousRing.index(cur); |
447 // For each vertex of the original polygon we add at least two points to
the | 447 // For each vertex of the original polygon we add at least two points to
the |
448 // outset polygon - one extending perpendicular to each impinging edge.
Connecting these | 448 // outset polygon - one extending perpendicular to each impinging edge.
Connecting these |
449 // two points yields a bevel join. We need one additional point for a mi
tered join, and | 449 // two points yields a bevel join. We need one additional point for a mi
tered join, and |
450 // a round join requires one or more points depending upon curvature. | 450 // a round join requires one or more points depending upon curvature. |
451 | 451 |
452 // The perpendicular point for the last edge | 452 // The perpendicular point for the last edge |
453 SkPoint normal1 = previousRing.norm(prev); | 453 SkPoint normal1 = previousRing.norm(prev); |
454 SkPoint perp1 = normal1; | 454 SkPoint perp1 = normal1; |
455 perp1.scale(outset); | 455 perp1.scale(outset); |
456 perp1 += this->point(originalIdx); | 456 perp1 += this->point(originalIdx); |
457 | 457 |
458 // The perpendicular point for the next edge. | 458 // The perpendicular point for the next edge. |
459 SkPoint normal2 = previousRing.norm(cur); | 459 SkPoint normal2 = previousRing.norm(cur); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 // The two triangles for the corner | 525 // The two triangles for the corner |
526 this->addTri(originalIdx, perp1Idx, miterIdx); | 526 this->addTri(originalIdx, perp1Idx, miterIdx); |
527 this->addTri(originalIdx, miterIdx, perp2Idx); | 527 this->addTri(originalIdx, miterIdx, perp2Idx); |
528 } | 528 } |
529 break; | 529 break; |
530 } | 530 } |
531 case SkPaint::Join::kBevel_Join: | 531 case SkPaint::Join::kBevel_Join: |
532 this->addTri(originalIdx, perp1Idx, perp2Idx); | 532 this->addTri(originalIdx, perp1Idx, perp2Idx); |
533 break; | 533 break; |
534 default: | 534 default: |
535 // kRound_Join is unsupported for now. GrAALinearizingCo
nvexPathRenderer is | 535 // kRound_Join is unsupported for now. GrAALinearizingCo
nvexPathRenderer is |
536 // only willing to draw mitered or beveled, so we should
never get here. | 536 // only willing to draw mitered or beveled, so we should
never get here. |
537 SkASSERT(false); | 537 SkASSERT(false); |
538 } | 538 } |
539 } | 539 } |
540 | 540 |
541 nextRing->addIdx(perp2Idx, originalIdx); | 541 nextRing->addIdx(perp2Idx, originalIdx); |
542 } | 542 } |
543 | 543 |
544 if (0 == cur) { | 544 if (0 == cur) { |
545 // Store the index of the first perpendicular point to finish up | 545 // Store the index of the first perpendicular point to finish up |
(...skipping 21 matching lines...) Expand all Loading... |
567 } | 567 } |
568 | 568 |
569 // Something went wrong in the creation of the next ring. If we're filling the s
hape, just go ahead | 569 // Something went wrong in the creation of the next ring. If we're filling the s
hape, just go ahead |
570 // and fan it. | 570 // and fan it. |
571 void GrAAConvexTessellator::terminate(const Ring& ring) { | 571 void GrAAConvexTessellator::terminate(const Ring& ring) { |
572 if (fStrokeWidth < 0.0f) { | 572 if (fStrokeWidth < 0.0f) { |
573 this->fanRing(ring); | 573 this->fanRing(ring); |
574 } | 574 } |
575 } | 575 } |
576 | 576 |
577 static SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar
initialCoverage, | 577 static SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar
initialCoverage, |
578 SkScalar targetDepth, SkScalar targetCoverage) { | 578 SkScalar targetDepth, SkScalar targetCoverage) { |
579 if (SkScalarNearlyEqual(initialDepth, targetDepth)) { | 579 if (SkScalarNearlyEqual(initialDepth, targetDepth)) { |
580 return targetCoverage; | 580 return targetCoverage; |
581 } | 581 } |
582 SkScalar result = (depth - initialDepth) / (targetDepth - initialDepth) * | 582 SkScalar result = (depth - initialDepth) / (targetDepth - initialDepth) * |
583 (targetCoverage - initialCoverage) + initialCoverage; | 583 (targetCoverage - initialCoverage) + initialCoverage; |
584 return SkScalarClampMax(result, 1.0f); | 584 return SkScalarClampMax(result, 1.0f); |
585 } | 585 } |
586 | 586 |
587 // return true when processing is complete | 587 // return true when processing is complete |
588 bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing
, | 588 bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing
, |
589 SkScalar initialDepth, SkScalar init
ialCoverage, | 589 SkScalar initialDepth, SkScalar init
ialCoverage, |
590 SkScalar targetDepth, SkScalar targe
tCoverage, | 590 SkScalar targetDepth, SkScalar targe
tCoverage, |
591 bool forceNew) { | 591 bool forceNew) { |
592 bool done = false; | 592 bool done = false; |
593 | 593 |
594 fCandidateVerts.rewind(); | 594 fCandidateVerts.rewind(); |
595 | 595 |
596 // Loop through all the points in the ring and find the intersection with th
e smallest depth | 596 // Loop through all the points in the ring and find the intersection with th
e smallest depth |
597 SkScalar minDist = SK_ScalarMax, minT = 0.0f; | 597 SkScalar minDist = SK_ScalarMax, minT = 0.0f; |
598 int minEdgeIdx = -1; | 598 int minEdgeIdx = -1; |
599 | 599 |
600 for (int cur = 0; cur < lastRing.numPts(); ++cur) { | 600 for (int cur = 0; cur < lastRing.numPts(); ++cur) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 for (int i = cur - 1; i >= 0 && dst[i] == targetIdx; i--) { | 692 for (int i = cur - 1; i >= 0 && dst[i] == targetIdx; i--) { |
693 dst[i] = fused; | 693 dst[i] = fused; |
694 } | 694 } |
695 } | 695 } |
696 } | 696 } |
697 | 697 |
698 // Fold the new ring's points into the global pool | 698 // Fold the new ring's points into the global pool |
699 for (int i = 0; i < fCandidateVerts.numPts(); ++i) { | 699 for (int i = 0; i < fCandidateVerts.numPts(); ++i) { |
700 int newIdx; | 700 int newIdx; |
701 if (fCandidateVerts.needsToBeNew(i) || forceNew) { | 701 if (fCandidateVerts.needsToBeNew(i) || forceNew) { |
702 // if the originating index is still valid then this point wasn't | 702 // if the originating index is still valid then this point wasn't |
703 // fused (and is thus movable) | 703 // fused (and is thus movable) |
704 SkScalar coverage = compute_coverage(depth, initialDepth, initialCov
erage, | 704 SkScalar coverage = compute_coverage(depth, initialDepth, initialCov
erage, |
705 targetDepth, targetCoverage); | 705 targetDepth, targetCoverage); |
706 newIdx = this->addPt(fCandidateVerts.point(i), depth, coverage, | 706 newIdx = this->addPt(fCandidateVerts.point(i), depth, coverage, |
707 fCandidateVerts.originatingIdx(i) != -1, false)
; | 707 fCandidateVerts.originatingIdx(i) != -1, false)
; |
708 } else { | 708 } else { |
709 SkASSERT(fCandidateVerts.originatingIdx(i) != -1); | 709 SkASSERT(fCandidateVerts.originatingIdx(i) != -1); |
710 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.po
int(i), depth, | 710 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.po
int(i), depth, |
711 targetCoverage); | 711 targetCoverage); |
712 newIdx = fCandidateVerts.originatingIdx(i); | 712 newIdx = fCandidateVerts.originatingIdx(i); |
713 } | 713 } |
714 | 714 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 } | 822 } |
823 | 823 |
824 #endif | 824 #endif |
825 | 825 |
826 void GrAAConvexTessellator::lineTo(SkPoint p, bool isCurve) { | 826 void GrAAConvexTessellator::lineTo(SkPoint p, bool isCurve) { |
827 if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) { | 827 if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) { |
828 return; | 828 return; |
829 } | 829 } |
830 | 830 |
831 SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1); | 831 SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1); |
832 if (this->numPts() >= 2 && | 832 if (this->numPts() >= 2 && |
833 abs_dist_from_line(fPts.top(), fNorms.top(), p) < kClose) { | 833 abs_dist_from_line(fPts.top(), fNorms.top(), p) < kClose) { |
834 // The old last point is on the line from the second to last to the new
point | 834 // The old last point is on the line from the second to last to the new
point |
835 this->popLastPt(); | 835 this->popLastPt(); |
836 fNorms.pop(); | 836 fNorms.pop(); |
837 fIsCurve.pop(); | 837 fIsCurve.pop(); |
838 // double-check that the new last point is not a duplicate of the new po
int. In an ideal | 838 // double-check that the new last point is not a duplicate of the new po
int. In an ideal |
839 // world this wouldn't be necessary (since it's only possible for non-co
nvex paths), but | 839 // world this wouldn't be necessary (since it's only possible for non-co
nvex paths), but |
840 // floating point precision issues mean it can actually happen on paths
that were determined | 840 // floating point precision issues mean it can actually happen on paths
that were determined |
841 // to be convex. | 841 // to be convex. |
842 if (duplicate_pt(p, this->lastPoint())) { | 842 if (duplicate_pt(p, this->lastPoint())) { |
(...skipping 12 matching lines...) Expand all Loading... |
855 | 855 |
856 void GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, bool isCurve) { | 856 void GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, bool isCurve) { |
857 m.mapPoints(&p, 1); | 857 m.mapPoints(&p, 1); |
858 this->lineTo(p, isCurve); | 858 this->lineTo(p, isCurve); |
859 } | 859 } |
860 | 860 |
861 void GrAAConvexTessellator::quadTo(SkPoint pts[3]) { | 861 void GrAAConvexTessellator::quadTo(SkPoint pts[3]) { |
862 int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); | 862 int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); |
863 fPointBuffer.setReserve(maxCount); | 863 fPointBuffer.setReserve(maxCount); |
864 SkPoint* target = fPointBuffer.begin(); | 864 SkPoint* target = fPointBuffer.begin(); |
865 int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], | 865 int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], |
866 kQuadTolerance, &target, maxCount); | 866 kQuadTolerance, &target, maxCount); |
867 fPointBuffer.setCount(count); | 867 fPointBuffer.setCount(count); |
868 for (int i = 0; i < count; i++) { | 868 for (int i = 0; i < count; i++) { |
869 lineTo(fPointBuffer[i], true); | 869 lineTo(fPointBuffer[i], true); |
870 } | 870 } |
871 } | 871 } |
872 | 872 |
873 void GrAAConvexTessellator::quadTo(const SkMatrix& m, SkPoint pts[3]) { | 873 void GrAAConvexTessellator::quadTo(const SkMatrix& m, SkPoint pts[3]) { |
874 SkPoint transformed[3]; | 874 SkPoint transformed[3]; |
875 transformed[0] = pts[0]; | 875 transformed[0] = pts[0]; |
876 transformed[1] = pts[1]; | 876 transformed[1] = pts[1]; |
877 transformed[2] = pts[2]; | 877 transformed[2] = pts[2]; |
878 m.mapPoints(transformed, 3); | 878 m.mapPoints(transformed, 3); |
879 quadTo(transformed); | 879 quadTo(transformed); |
880 } | 880 } |
881 | 881 |
882 void GrAAConvexTessellator::cubicTo(const SkMatrix& m, SkPoint pts[4]) { | 882 void GrAAConvexTessellator::cubicTo(const SkMatrix& m, SkPoint pts[4]) { |
883 m.mapPoints(pts, 4); | 883 m.mapPoints(pts, 4); |
884 int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); | 884 int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); |
885 fPointBuffer.setReserve(maxCount); | 885 fPointBuffer.setReserve(maxCount); |
886 SkPoint* target = fPointBuffer.begin(); | 886 SkPoint* target = fPointBuffer.begin(); |
887 int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
| 887 int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], |
888 kCubicTolerance, &target, maxCount); | 888 kCubicTolerance, &target, maxCount); |
889 fPointBuffer.setCount(count); | 889 fPointBuffer.setCount(count); |
890 for (int i = 0; i < count; i++) { | 890 for (int i = 0; i < count; i++) { |
891 lineTo(fPointBuffer[i], true); | 891 lineTo(fPointBuffer[i], true); |
892 } | 892 } |
893 } | 893 } |
894 | 894 |
895 // include down here to avoid compilation errors caused by "-" overload in SkGeo
metry.h | 895 // include down here to avoid compilation errors caused by "-" overload in SkGeo
metry.h |
896 #include "SkGeometry.h" | 896 #include "SkGeometry.h" |
897 | 897 |
(...skipping 28 matching lines...) Expand all Loading... |
926 int gs = int(255*paramValue); | 926 int gs = int(255*paramValue); |
927 paint.setARGB(255, gs, gs, gs); | 927 paint.setARGB(255, gs, gs, gs); |
928 | 928 |
929 canvas->drawCircle(p.fX, p.fY, kPointRadius, paint); | 929 canvas->drawCircle(p.fX, p.fY, kPointRadius, paint); |
930 | 930 |
931 if (stroke) { | 931 if (stroke) { |
932 SkPaint stroke; | 932 SkPaint stroke; |
933 stroke.setColor(SK_ColorYELLOW); | 933 stroke.setColor(SK_ColorYELLOW); |
934 stroke.setStyle(SkPaint::kStroke_Style); | 934 stroke.setStyle(SkPaint::kStroke_Style); |
935 stroke.setStrokeWidth(kPointRadius/3.0f); | 935 stroke.setStrokeWidth(kPointRadius/3.0f); |
936 canvas->drawCircle(p.fX, p.fY, kPointRadius, stroke); | 936 canvas->drawCircle(p.fX, p.fY, kPointRadius, stroke); |
937 } | 937 } |
938 } | 938 } |
939 | 939 |
940 static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, Sk
Color color) { | 940 static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, Sk
Color color) { |
941 SkPaint p; | 941 SkPaint p; |
942 p.setColor(color); | 942 p.setColor(color); |
943 | 943 |
944 canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, p); | 944 canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, p); |
945 } | 945 } |
946 | 946 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 } | 978 } |
979 | 979 |
980 SkString num; | 980 SkString num; |
981 num.printf("%d", this->origEdgeID(cur)); | 981 num.printf("%d", this->origEdgeID(cur)); |
982 canvas->drawText(num.c_str(), num.size(), mid.fX, mid.fY, paint); | 982 canvas->drawText(num.c_str(), num.size(), mid.fX, mid.fY, paint); |
983 | 983 |
984 if (fPts.count()) { | 984 if (fPts.count()) { |
985 draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector
, | 985 draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector
, |
986 kArrowLength, SK_ColorBLUE); | 986 kArrowLength, SK_ColorBLUE); |
987 } | 987 } |
988 } | 988 } |
989 } | 989 } |
990 | 990 |
991 void GrAAConvexTessellator::draw(SkCanvas* canvas) const { | 991 void GrAAConvexTessellator::draw(SkCanvas* canvas) const { |
992 for (int i = 0; i < fIndices.count(); i += 3) { | 992 for (int i = 0; i < fIndices.count(); i += 3) { |
993 SkASSERT(fIndices[i] < this->numPts()) ; | 993 SkASSERT(fIndices[i] < this->numPts()) ; |
994 SkASSERT(fIndices[i+1] < this->numPts()) ; | 994 SkASSERT(fIndices[i+1] < this->numPts()) ; |
995 SkASSERT(fIndices[i+2] < this->numPts()) ; | 995 SkASSERT(fIndices[i+2] < this->numPts()) ; |
996 | 996 |
997 draw_line(canvas, | 997 draw_line(canvas, |
998 this->point(this->fIndices[i]), this->point(this->fIndices[i+1
]), | 998 this->point(this->fIndices[i]), this->point(this->fIndices[i+1
]), |
999 SK_ColorBLACK); | 999 SK_ColorBLACK); |
1000 draw_line(canvas, | 1000 draw_line(canvas, |
1001 this->point(this->fIndices[i+1]), this->point(this->fIndices[i
+2]), | 1001 this->point(this->fIndices[i+1]), this->point(this->fIndices[i
+2]), |
1002 SK_ColorBLACK); | 1002 SK_ColorBLACK); |
1003 draw_line(canvas, | 1003 draw_line(canvas, |
1004 this->point(this->fIndices[i+2]), this->point(this->fIndices[i
]), | 1004 this->point(this->fIndices[i+2]), this->point(this->fIndices[i
]), |
1005 SK_ColorBLACK); | 1005 SK_ColorBLACK); |
1006 } | 1006 } |
1007 | 1007 |
1008 fInitialRing.draw(canvas, *this); | 1008 fInitialRing.draw(canvas, *this); |
1009 for (int i = 0; i < fRings.count(); ++i) { | 1009 for (int i = 0; i < fRings.count(); ++i) { |
1010 fRings[i]->draw(canvas, *this); | 1010 fRings[i]->draw(canvas, *this); |
1011 } | 1011 } |
1012 | 1012 |
1013 for (int i = 0; i < this->numPts(); ++i) { | 1013 for (int i = 0; i < this->numPts(); ++i) { |
1014 draw_point(canvas, | 1014 draw_point(canvas, |
1015 this->point(i), 0.5f + (this->depth(i)/(2 * kAntialiasingRadi
us)), | 1015 this->point(i), 0.5f + (this->depth(i)/(2 * kAntialiasingRadi
us)), |
1016 !this->movable(i)); | 1016 !this->movable(i)); |
1017 | 1017 |
1018 SkPaint paint; | 1018 SkPaint paint; |
1019 paint.setTextSize(kPointTextSize); | 1019 paint.setTextSize(kPointTextSize); |
1020 paint.setTextAlign(SkPaint::kCenter_Align); | 1020 paint.setTextAlign(SkPaint::kCenter_Align); |
1021 if (this->depth(i) <= -kAntialiasingRadius) { | 1021 if (this->depth(i) <= -kAntialiasingRadius) { |
1022 paint.setColor(SK_ColorWHITE); | 1022 paint.setColor(SK_ColorWHITE); |
1023 } | 1023 } |
1024 | 1024 |
1025 SkString num; | 1025 SkString num; |
1026 num.printf("%d", i); | 1026 num.printf("%d", i); |
1027 canvas->drawText(num.c_str(), num.size(), | 1027 canvas->drawText(num.c_str(), num.size(), |
1028 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f
), | 1028 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f
), |
1029 paint); | 1029 paint); |
1030 } | 1030 } |
1031 } | 1031 } |
1032 | 1032 |
1033 #endif | 1033 #endif |
1034 | |
OLD | NEW |