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

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

Issue 1158803002: Added GrAAFlatteningConvexPathRenderer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebased Created 5 years, 6 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
« no previous file with comments | « src/gpu/GrAAConvexTessellator.h ('k') | src/gpu/GrAALinearizingConvexPathRenderer.h » ('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 * 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"
11 #include "SkPoint.h" 11 #include "SkPoint.h"
12 #include "SkString.h" 12 #include "SkString.h"
13 #include "GrPathUtils.h"
13 14
14 // Next steps: 15 // Next steps:
15 // use in AAConvexPathRenderer 16 // use in AAConvexPathRenderer
16 // add an interactive sample app slide 17 // add an interactive sample app slide
17 // add debug check that all points are suitably far apart 18 // add debug check that all points are suitably far apart
18 // test more degenerate cases 19 // test more degenerate cases
19 20
20 // The tolerance for fusing vertices and eliminating colinear lines (It is in de vice space). 21 // The tolerance for fusing vertices and eliminating colinear lines (It is in de vice space).
21 static const SkScalar kClose = (SK_Scalar1 / 16); 22 static const SkScalar kClose = (SK_Scalar1 / 16);
22 static const SkScalar kCloseSqd = SkScalarMul(kClose, kClose); 23 static const SkScalar kCloseSqd = SkScalarMul(kClose, kClose);
(...skipping 21 matching lines...) Expand all
44 } 45 }
45 46
46 static SkScalar abs_dist_from_line(const SkPoint& p0, const SkVector& v, const S kPoint& test) { 47 static SkScalar abs_dist_from_line(const SkPoint& p0, const SkVector& v, const S kPoint& test) {
47 SkPoint testV = test - p0; 48 SkPoint testV = test - p0;
48 SkScalar dist = testV.fX * v.fY - testV.fY * v.fX; 49 SkScalar dist = testV.fX * v.fY - testV.fY * v.fX;
49 return SkScalarAbs(dist); 50 return SkScalarAbs(dist);
50 } 51 }
51 52
52 int GrAAConvexTessellator::addPt(const SkPoint& pt, 53 int GrAAConvexTessellator::addPt(const SkPoint& pt,
53 SkScalar depth, 54 SkScalar depth,
54 bool movable) { 55 bool movable,
56 bool isCurve) {
55 this->validate(); 57 this->validate();
56 58
57 int index = fPts.count(); 59 int index = fPts.count();
58 *fPts.push() = pt; 60 *fPts.push() = pt;
59 *fDepths.push() = depth; 61 *fDepths.push() = depth;
60 *fMovable.push() = movable; 62 *fMovable.push() = movable;
63 *fIsCurve.push() = isCurve;
61 64
62 this->validate(); 65 this->validate();
63 return index; 66 return index;
64 } 67 }
65 68
66 void GrAAConvexTessellator::popLastPt() { 69 void GrAAConvexTessellator::popLastPt() {
67 this->validate(); 70 this->validate();
68 71
69 fPts.pop(); 72 fPts.pop();
70 fDepths.pop(); 73 fDepths.pop();
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 SkASSERT(t > 0.0f); 232 SkASSERT(t > 0.0f);
230 *result = bisector; 233 *result = bisector;
231 result->scale(t); 234 result->scale(t);
232 *result += newP; 235 *result += newP;
233 236
234 237
235 return true; 238 return true;
236 } 239 }
237 240
238 bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat h) { 241 bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat h) {
239 SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks());
240 SkASSERT(SkPath::kConvex_Convexity == path.getConvexity()); 242 SkASSERT(SkPath::kConvex_Convexity == path.getConvexity());
241 243
242 // Outer ring: 3*numPts 244 // Outer ring: 3*numPts
243 // Middle ring: numPts 245 // Middle ring: numPts
244 // Presumptive inner ring: numPts 246 // Presumptive inner ring: numPts
245 this->reservePts(5*path.countPoints()); 247 this->reservePts(5*path.countPoints());
246 // Outer ring: 12*numPts 248 // Outer ring: 12*numPts
247 // Middle ring: 0 249 // Middle ring: 0
248 // Presumptive inner ring: 6*numPts + 6 250 // Presumptive inner ring: 6*numPts + 6
249 fIndices.setReserve(18*path.countPoints() + 6); 251 fIndices.setReserve(18*path.countPoints() + 6);
250 252
251 fNorms.setReserve(path.countPoints()); 253 fNorms.setReserve(path.countPoints());
252 254
253 SkScalar minCross = SK_ScalarMax, maxCross = -SK_ScalarMax; 255 SkDEBUGCODE(fMinCross = SK_ScalarMax;)
256 SkDEBUGCODE(fMaxCross = -SK_ScalarMax;)
254 257
255 // TODO: is there a faster way to extract the points from the path? Perhaps 258 // TODO: is there a faster way to extract the points from the path? Perhaps
256 // get all the points via a new entry point, transform them all in bulk 259 // get all the points via a new entry point, transform them all in bulk
257 // and then walk them to find duplicates? 260 // and then walk them to find duplicates?
258 SkPath::Iter iter(path, true); 261 SkPath::Iter iter(path, true);
259 SkPoint pts[4]; 262 SkPoint pts[4];
260 SkPath::Verb verb; 263 SkPath::Verb verb;
261 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 264 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
262 switch (verb) { 265 switch (verb) {
263 case SkPath::kLine_Verb: 266 case SkPath::kLine_Verb:
264 m.mapPoints(&pts[1], 1); 267 this->lineTo(m, pts[1], false);
265 if (this->numPts() > 0 && duplicate_pt(pts[1], this->lastPoint() )) {
266 continue;
267 }
268
269 SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1);
270 if (this->numPts() >= 2 &&
271 abs_dist_from_line(fPts.top(), fNorms.top(), pts[1]) < kClos e) {
272 // The old last point is on the line from the second to last to the new point
273 this->popLastPt();
274 fNorms.pop();
275 }
276
277 this->addPt(pts[1], 0.0f, false);
278 if (this->numPts() > 1) {
279 *fNorms.push() = fPts.top() - fPts[fPts.count()-2];
280 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top() );
281 SkASSERT(len > 0.0f);
282 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length()));
283 }
284
285 if (this->numPts() >= 3) {
286 int cur = this->numPts()-1;
287 SkScalar cross = SkPoint::CrossProduct(fNorms[cur-1], fNorms [cur-2]);
288 maxCross = SkTMax(maxCross, cross);
289 minCross = SkTMin(minCross, cross);
290 }
291 break; 268 break;
292 case SkPath::kQuad_Verb: 269 case SkPath::kQuad_Verb:
270 this->quadTo(m, pts);
271 break;
272 case SkPath::kCubic_Verb:
273 this->cubicTo(m, pts);
274 break;
293 case SkPath::kConic_Verb: 275 case SkPath::kConic_Verb:
294 case SkPath::kCubic_Verb: 276 this->conicTo(m, pts, iter.conicWeight());
295 SkASSERT(false);
296 break; 277 break;
297 case SkPath::kMove_Verb: 278 case SkPath::kMove_Verb:
298 case SkPath::kClose_Verb: 279 case SkPath::kClose_Verb:
299 case SkPath::kDone_Verb: 280 case SkPath::kDone_Verb:
300 break; 281 break;
301 } 282 }
302 } 283 }
303 284
304 if (this->numPts() < 3) { 285 if (this->numPts() < 3) {
305 return false; 286 return false;
(...skipping 29 matching lines...) Expand all
335 fNorms[0] = fPts[1] - fPts[0]; 316 fNorms[0] = fPts[1] - fPts[0];
336 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms[0]); 317 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms[0]);
337 SkASSERT(len > 0.0f); 318 SkASSERT(len > 0.0f);
338 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[0].length())); 319 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[0].length()));
339 } 320 }
340 321
341 if (this->numPts() < 3) { 322 if (this->numPts() < 3) {
342 return false; 323 return false;
343 } 324 }
344 325
345 // Check the cross produce of the final trio 326 // Check the cross product of the final trio
346 SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top()); 327 SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top());
347 maxCross = SkTMax(maxCross, cross); 328 SkDEBUGCODE(fMaxCross = SkTMax(fMaxCross, cross));
348 minCross = SkTMin(minCross, cross); 329 SkDEBUGCODE(fMinCross = SkTMin(fMinCross, cross));
349 330 SkASSERT((fMaxCross >= 0.0f) == (fMinCross >= 0.0f));
350 if (maxCross > 0.0f) { 331 if (cross > 0.0f) {
351 SkASSERT(minCross >= 0.0f);
352 fSide = SkPoint::kRight_Side; 332 fSide = SkPoint::kRight_Side;
353 } else { 333 } else {
354 SkASSERT(minCross <= 0.0f);
355 fSide = SkPoint::kLeft_Side; 334 fSide = SkPoint::kLeft_Side;
356 } 335 }
357 336
358 // Make all the normals face outwards rather than along the edge 337 // Make all the normals face outwards rather than along the edge
359 for (int cur = 0; cur < fNorms.count(); ++cur) { 338 for (int cur = 0; cur < fNorms.count(); ++cur) {
360 fNorms[cur].setOrthog(fNorms[cur], fSide); 339 fNorms[cur].setOrthog(fNorms[cur], fSide);
361 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length())); 340 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
362 } 341 }
363 342
364 this->computeBisectors(); 343 this->computeBisectors();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 376 }
398 377
399 void GrAAConvexTessellator::createOuterRing() { 378 void GrAAConvexTessellator::createOuterRing() {
400 // For now, we're only generating one outer ring (at the start). This 379 // For now, we're only generating one outer ring (at the start). This
401 // could be relaxed for stroking use cases. 380 // could be relaxed for stroking use cases.
402 SkASSERT(0 == fIndices.count()); 381 SkASSERT(0 == fIndices.count());
403 SkASSERT(fPts.count() == fNorms.count()); 382 SkASSERT(fPts.count() == fNorms.count());
404 383
405 const int numPts = fPts.count(); 384 const int numPts = fPts.count();
406 385
407 // For each vertex of the original polygon we add three points to the
408 // outset polygon - one extending perpendicular to each impinging edge
409 // and one along the bisector. Two triangles are added for each corner
410 // and two are added along each edge.
411 int prev = numPts - 1; 386 int prev = numPts - 1;
412 int lastPerpIdx = -1, firstPerpIdx = -1, newIdx0, newIdx1, newIdx2; 387 int lastPerpIdx = -1, firstPerpIdx = -1, newIdx0, newIdx1, newIdx2;
413 for (int cur = 0; cur < numPts; ++cur) { 388 for (int cur = 0; cur < numPts; ++cur) {
414 // The perpendicular point for the last edge 389 if (fIsCurve[cur]) {
415 SkPoint temp = fNorms[prev]; 390 // Inside a curve, we assume that the curvature is shallow enough (d ue to tesselation)
416 temp.scale(fTargetDepth); 391 // that we only need one corner point. Mathematically, the distance the corner point
417 temp += fPts[cur]; 392 // gets shifted out should depend on the angle between the two line segments (as in
393 // mitering), but again due to tesselation we assume that this angle is small and
394 // therefore the correction factor is negligible and we do not bothe r with it.
418 395
419 // We know it isn't a duplicate of the prior point (since it and this 396 // The bisector outset point
420 // one are just perpendicular offsets from the non-merged polygon points ) 397 SkPoint temp = fBisectors[cur];
421 newIdx0 = this->addPt(temp, -fTargetDepth, false); 398 temp.scale(-fTargetDepth); // the bisectors point in
399 temp += fPts[cur];
422 400
423 // The bisector outset point 401 // double-check our "sufficiently flat" assumption; we want the bise ctor point to be
424 temp = fBisectors[cur]; 402 // close to the normal point.
425 temp.scale(-fTargetDepth); // the bisectors point in 403 #define kFlatnessTolerance 1.0f
426 temp += fPts[cur]; 404 SkDEBUGCODE(SkPoint prevNormal = fNorms[prev];)
405 SkDEBUGCODE(prevNormal.scale(fTargetDepth);)
406 SkDEBUGCODE(prevNormal += fPts[cur];)
407 SkASSERT((temp - prevNormal).length() < kFlatnessTolerance);
427 408
428 // For very shallow angles all the corner points could fuse 409 newIdx1 = this->addPt(temp, -fTargetDepth, false, true);
429 if (duplicate_pt(temp, this->point(newIdx0))) { 410
430 newIdx1 = newIdx0; 411 if (0 == cur) {
431 } else { 412 // Store the index of the first perpendicular point to finish up
432 newIdx1 = this->addPt(temp, -fTargetDepth, false); 413 firstPerpIdx = newIdx1;
414 SkASSERT(-1 == lastPerpIdx);
415 } else {
416 // The triangles for the previous edge
417 this->addTri(prev, newIdx1, cur);
418 this->addTri(prev, lastPerpIdx, newIdx1);
419 }
420
421 prev = cur;
422 // Track the last perpendicular outset point so we can construct the
423 // trailing edge triangles.
424 lastPerpIdx = newIdx1;
433 } 425 }
426 else {
427 // For each vertex of the original polygon we add three points to th e
428 // outset polygon - one extending perpendicular to each impinging ed ge
429 // and one along the bisector. Two triangles are added for each corn er
430 // and two are added along each edge.
434 431
435 // The perpendicular point for the next edge. 432 // The perpendicular point for the last edge
436 temp = fNorms[cur]; 433 SkPoint temp = fNorms[prev];
437 temp.scale(fTargetDepth); 434 temp.scale(fTargetDepth);
438 temp += fPts[cur]; 435 temp += fPts[cur];
439 436
440 // For very shallow angles all the corner points could fuse. 437 // We know it isn't a duplicate of the prior point (since it and thi s
441 if (duplicate_pt(temp, this->point(newIdx1))) { 438 // one are just perpendicular offsets from the non-merged polygon po ints)
442 newIdx2 = newIdx1; 439 newIdx0 = this->addPt(temp, -fTargetDepth, false, false);
443 } else { 440
444 newIdx2 = this->addPt(temp, -fTargetDepth, false); 441 // The bisector outset point
442 temp = fBisectors[cur];
443 temp.scale(-fTargetDepth); // the bisectors point in
444 temp += fPts[cur];
445
446 // For very shallow angles all the corner points could fuse
447 if (duplicate_pt(temp, this->point(newIdx0))) {
448 newIdx1 = newIdx0;
449 } else {
450 newIdx1 = this->addPt(temp, -fTargetDepth, false, false);
451 }
452
453 // The perpendicular point for the next edge.
454 temp = fNorms[cur];
455 temp.scale(fTargetDepth);
456 temp += fPts[cur];
457
458 // For very shallow angles all the corner points could fuse.
459 if (duplicate_pt(temp, this->point(newIdx1))) {
460 newIdx2 = newIdx1;
461 } else {
462 newIdx2 = this->addPt(temp, -fTargetDepth, false, false);
463 }
464
465 if (0 == cur) {
466 // Store the index of the first perpendicular point to finish up
467 firstPerpIdx = newIdx0;
468 SkASSERT(-1 == lastPerpIdx);
469 } else {
470 // The triangles for the previous edge
471 this->addTri(prev, newIdx0, cur);
472 this->addTri(prev, lastPerpIdx, newIdx0);
473 }
474
475 // The two triangles for the corner
476 this->addTri(cur, newIdx0, newIdx1);
477 this->addTri(cur, newIdx1, newIdx2);
478
479 prev = cur;
480 // Track the last perpendicular outset point so we can construct the
481 // trailing edge triangles.
482 lastPerpIdx = newIdx2;
445 } 483 }
446
447 if (0 == cur) {
448 // Store the index of the first perpendicular point to finish up
449 firstPerpIdx = newIdx0;
450 SkASSERT(-1 == lastPerpIdx);
451 } else {
452 // The triangles for the previous edge
453 this->addTri(prev, newIdx0, cur);
454 this->addTri(prev, lastPerpIdx, newIdx0);
455 }
456
457 // The two triangles for the corner
458 this->addTri(cur, newIdx0, newIdx1);
459 this->addTri(cur, newIdx1, newIdx2);
460
461 prev = cur;
462 // Track the last perpendicular outset point so we can construct the
463 // trailing edge triangles.
464 lastPerpIdx = newIdx2;
465 } 484 }
466 485
467 // pick up the final edge rect 486 // pick up the final edge rect
468 this->addTri(numPts-1, firstPerpIdx, 0); 487 this->addTri(numPts - 1, firstPerpIdx, 0);
469 this->addTri(numPts-1, lastPerpIdx, firstPerpIdx); 488 this->addTri(numPts - 1, lastPerpIdx, firstPerpIdx);
470 489
471 this->validate(); 490 this->validate();
472 } 491 }
473 492
474 // Something went wrong in the creation of the next ring. Mark the last good 493 // Something went wrong in the creation of the next ring. Mark the last good
475 // ring as being at the desired depth and fan it. 494 // ring as being at the desired depth and fan it.
476 void GrAAConvexTessellator::terminate(const Ring& ring) { 495 void GrAAConvexTessellator::terminate(const Ring& ring) {
477 for (int i = 0; i < ring.numPts(); ++i) { 496 for (int i = 0; i < ring.numPts(); ++i) {
478 fDepths[ring.index(i)] = fTargetDepth; 497 fDepths[ring.index(i)] = fTargetDepth;
479 } 498 }
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 } 604 }
586 } 605 }
587 606
588 // Fold the new ring's points into the global pool 607 // Fold the new ring's points into the global pool
589 for (int i = 0; i < fCandidateVerts.numPts(); ++i) { 608 for (int i = 0; i < fCandidateVerts.numPts(); ++i) {
590 int newIdx; 609 int newIdx;
591 if (fCandidateVerts.needsToBeNew(i)) { 610 if (fCandidateVerts.needsToBeNew(i)) {
592 // if the originating index is still valid then this point wasn't 611 // if the originating index is still valid then this point wasn't
593 // fused (and is thus movable) 612 // fused (and is thus movable)
594 newIdx = this->addPt(fCandidateVerts.point(i), depth, 613 newIdx = this->addPt(fCandidateVerts.point(i), depth,
595 fCandidateVerts.originatingIdx(i) != -1); 614 fCandidateVerts.originatingIdx(i) != -1, false) ;
596 } else { 615 } else {
597 SkASSERT(fCandidateVerts.originatingIdx(i) != -1); 616 SkASSERT(fCandidateVerts.originatingIdx(i) != -1);
598 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.po int(i), depth); 617 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.po int(i), depth);
599 newIdx = fCandidateVerts.originatingIdx(i); 618 newIdx = fCandidateVerts.originatingIdx(i);
600 } 619 }
601 620
602 nextRing->addIdx(newIdx, fCandidateVerts.origEdge(i)); 621 nextRing->addIdx(newIdx, fCandidateVerts.origEdge(i));
603 } 622 }
604 623
605 // 'dst' currently has indices into the ring. Remap these to be indices 624 // 'dst' currently has indices into the ring. Remap these to be indices
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 // Verify that the incrementally computed depths are close to the actual depths. 780 // Verify that the incrementally computed depths are close to the actual depths.
762 void GrAAConvexTessellator::checkAllDepths() const { 781 void GrAAConvexTessellator::checkAllDepths() const {
763 for (int cur = 0; cur < this->numPts(); ++cur) { 782 for (int cur = 0; cur < this->numPts(); ++cur) {
764 SkScalar realDepth = this->computeRealDepth(this->point(cur)); 783 SkScalar realDepth = this->computeRealDepth(this->point(cur));
765 SkScalar computedDepth = this->depth(cur); 784 SkScalar computedDepth = this->depth(cur);
766 SkASSERT(SkScalarNearlyEqual(realDepth, computedDepth, 0.01f)); 785 SkASSERT(SkScalarNearlyEqual(realDepth, computedDepth, 0.01f));
767 } 786 }
768 } 787 }
769 #endif 788 #endif
770 789
790 #define kQuadTolerance 0.2f
791 #define kCubicTolerance 0.2f
792 #define kConicTolerance 0.5f
793
794 void GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, bool isCurve) {
795 m.mapPoints(&p, 1);
796 if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) {
797 return;
798 }
799
800 SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1);
801 if (this->numPts() >= 2 &&
802 abs_dist_from_line(fPts.top(), fNorms.top(), p) < kClose) {
803 // The old last point is on the line from the second to last to the new point
804 this->popLastPt();
805 fNorms.pop();
806 fIsCurve.pop();
807 }
808 this->addPt(p, 0.0f, false, isCurve);
809 if (this->numPts() > 1) {
810 *fNorms.push() = fPts.top() - fPts[fPts.count()-2];
811 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top());
812 SkASSERT(len > 0.0f);
813 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length()));
814 }
815 SkDEBUGCODE(
816 if (this->numPts() >= 3) {
817 int cur = this->numPts()-1;
818 SkScalar cross = SkPoint::CrossProduct(fNorms[cur-1], fNorms[cur-2]) ;
819 fMaxCross = SkTMax(fMaxCross, cross);
820 fMinCross = SkTMin(fMinCross, cross);
821 }
822 )
823 }
824
825 void GrAAConvexTessellator::quadTo(const SkMatrix& m, SkPoint pts[3]) {
826 int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
827 fPointBuffer.setReserve(maxCount);
828 SkPoint* target = fPointBuffer.begin();
829 int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
830 kQuadTolerance, &target, maxCount);
831 fPointBuffer.setCount(count);
832 for (int i = 0; i < count; i++) {
833 lineTo(m, fPointBuffer[i], true);
834 }
835 }
836
837 void GrAAConvexTessellator::cubicTo(const SkMatrix& m, SkPoint pts[4]) {
838 int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance);
839 fPointBuffer.setReserve(maxCount);
840 SkPoint* target = fPointBuffer.begin();
841 int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
842 kCubicTolerance, &target, maxCount);
843 fPointBuffer.setCount(count);
844 for (int i = 0; i < count; i++) {
845 lineTo(m, fPointBuffer[i], true);
846 }
847 }
848
849 // include down here to avoid compilation errors caused by "-" overload in SkGeo metry.h
850 #include "SkGeometry.h"
851
852 void GrAAConvexTessellator::conicTo(const SkMatrix& m, SkPoint* pts, SkScalar w) {
853 SkAutoConicToQuads quadder;
854 const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance);
855 SkPoint lastPoint = *(quads++);
856 int count = quadder.countQuads();
857 for (int i = 0; i < count; ++i) {
858 SkPoint quadPts[3];
859 quadPts[0] = lastPoint;
860 quadPts[1] = quads[0];
861 quadPts[2] = i == count - 1 ? pts[2] : quads[1];
862 quadTo(m, quadPts);
863 lastPoint = quadPts[2];
864 quads += 2;
865 }
866 }
867
771 ////////////////////////////////////////////////////////////////////////////// 868 //////////////////////////////////////////////////////////////////////////////
772 #if GR_AA_CONVEX_TESSELLATOR_VIZ 869 #if GR_AA_CONVEX_TESSELLATOR_VIZ
773 static const SkScalar kPointRadius = 0.02f; 870 static const SkScalar kPointRadius = 0.02f;
774 static const SkScalar kArrowStrokeWidth = 0.0f; 871 static const SkScalar kArrowStrokeWidth = 0.0f;
775 static const SkScalar kArrowLength = 0.2f; 872 static const SkScalar kArrowLength = 0.2f;
776 static const SkScalar kEdgeTextSize = 0.1f; 873 static const SkScalar kEdgeTextSize = 0.1f;
777 static const SkScalar kPointTextSize = 0.02f; 874 static const SkScalar kPointTextSize = 0.02f;
778 875
779 static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) { 876 static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) {
780 SkPaint paint; 877 SkPaint paint;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 SkString num; 978 SkString num;
882 num.printf("%d", i); 979 num.printf("%d", i);
883 canvas->drawText(num.c_str(), num.size(), 980 canvas->drawText(num.c_str(), num.size(),
884 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ), 981 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ),
885 paint); 982 paint);
886 } 983 }
887 } 984 }
888 985
889 #endif 986 #endif
890 987
OLDNEW
« no previous file with comments | « src/gpu/GrAAConvexTessellator.h ('k') | src/gpu/GrAALinearizingConvexPathRenderer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698