1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "GrAAConvexTessellator.h" 9 #include "SkCanvas.h" 10 #include "SkPath.h" 11 #include "SkPoint.h" 12 #include "SkString.h" 13 #include "GrPathUtils.h" 14 15 // Next steps: 16 // add an interactive sample app slide 17 // add debug check that all points are suitably far apart 18 // test more degenerate cases 19 20 // The tolerance for fusing vertices and eliminating colinear lines (It is in device space). 21 static const SkScalar kClose = (SK_Scalar1 / 16); 22 static const SkScalar kCloseSqd = kClose * kClose; 23 24 // tesselation tolerance values, in device space pixels 25 static const SkScalar kQuadTolerance = 0.2f; 26 static const SkScalar kCubicTolerance = 0.2f; 27 static const SkScalar kConicTolerance = 0.25f; 28 29 // dot product below which we use a round cap between curve segments 30 static const SkScalar kRoundCapThreshold = 0.8f; 31 32 // dot product above which we consider two adjacent curves to be part of the "same" curve 33 static const SkScalar kCurveConnectionThreshold = 0.8f; 34 35 static bool intersect(const SkPoint& p0, const SkPoint& n0, 36 const SkPoint& p1, const SkPoint& n1, 37 SkScalar* t) { 38 const SkPoint v = p1 - p0; 39 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX; 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; 46 } 47 48 // This is a special case version of intersect where we have the vector 49 // perpendicular to the second line rather than the vector parallel to it. 50 static SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0, 51 const SkPoint& p1, const SkPoint& perp) { 52 const SkPoint v = p1 - p0; 53 SkScalar perpDot = n0.dot(perp); 54 return v.dot(perp) / perpDot; 55 } 56 57 static bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) { 58 SkScalar distSq = SkPointPriv::DistanceToSqd(p0, p1); 59 return distSq < kCloseSqd; 60 } 61 62 static bool points_are_colinear_and_b_is_middle(const SkPoint& a, const SkPoint& b, 63 const SkPoint& c) { 64 // 'area' is twice the area of the triangle with corners a, b, and c. 65 SkScalar area = a.fX * (b.fY - c.fY) + b.fX * (c.fY - a.fY) + c.fX * (a.fY - b.fY); 66 if (SkScalarAbs(area) >= 2 * kCloseSqd) { 67 return false; 68 } 69 return (a - b).dot(b - c) >= 0; 70 } 71 72 int GrAAConvexTessellator::addPt(const SkPoint& pt, 73 SkScalar depth, 74 SkScalar coverage, 75 bool movable, 76 CurveState curve) { 77 SkASSERT(pt.isFinite()); 78 this->validate(); 79 80 int index = fPts.count(); 81 *fPts.push() = pt; 82 *fCoverages.push() = coverage; 83 *fMovable.push() = movable; 84 *fCurveState.push() = curve; 85 86 this->validate(); 87 return index; 88 } 89 90 void GrAAConvexTessellator::popLastPt() { 91 this->validate(); 92 93 fPts.pop(); 94 fCoverages.pop(); 95 fMovable.pop(); 96 fCurveState.pop(); 97 98 this->validate(); 99 } 100 101 void GrAAConvexTessellator::popFirstPtShuffle() { 102 this->validate(); 103 104 fPts.removeShuffle(0); 105 fCoverages.removeShuffle(0); 106 fMovable.removeShuffle(0); 107 fCurveState.removeShuffle(0); 108 109 this->validate(); 110 } 111 112 void GrAAConvexTessellator::updatePt(int index, 113 const SkPoint& pt, 114 SkScalar depth, 115 SkScalar coverage) { 116 this->validate(); 117 SkASSERT(fMovable[index]); 118 119 fPts[index] = pt; 120 fCoverages[index] = coverage; 121 } 122 123 void GrAAConvexTessellator::addTri(int i0, int i1, int i2) { 124 if (i0 == i1 || i1 == i2 || i2 == i0) { 125 return; 126 } 127 128 *fIndices.push() = i0; 129 *fIndices.push() = i1; 130 *fIndices.push() = i2; 131 } 132 133 void GrAAConvexTessellator::rewind() { 134 fPts.rewind(); 135 fCoverages.rewind(); 136 fMovable.rewind(); 137 fIndices.rewind(); 138 fNorms.rewind(); 139 fCurveState.rewind(); 140 fInitialRing.rewind(); 141 fCandidateVerts.rewind(); 142 #if GR_AA_CONVEX_TESSELLATOR_VIZ 143 fRings.rewind(); // TODO: leak in this case! 144 #else 145 fRings[0].rewind(); 146 fRings[1].rewind(); 147 #endif 148 } 149 150 void GrAAConvexTessellator::computeNormals() { 151 auto normalToVector = [this](SkVector v) { 152 SkVector n = SkPointPriv::MakeOrthog(v, fSide); 153 SkAssertResult(n.normalize()); 154 SkASSERT(SkScalarNearlyEqual(1.0f, n.length())); 155 return n; 156 }; 157 158 // Check the cross product of the final trio 159 fNorms.append(fPts.count()); 160 fNorms[0] = fPts[1] - fPts[0]; 161 fNorms.top() = fPts[0] - fPts.top(); 162 SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top()); 163 fSide = (cross > 0.0f) ? SkPointPriv::kRight_Side : SkPointPriv::kLeft_Side; 164 fNorms[0] = normalToVector(fNorms[0]); 165 for (int cur = 1; cur < fNorms.count() - 1; ++cur) { 166 fNorms[cur] = normalToVector(fPts[cur + 1] - fPts[cur]); 167 } 168 fNorms.top() = normalToVector(fNorms.top()); 169 } 170 171 void GrAAConvexTessellator::computeBisectors() { 172 fBisectors.setCount(fNorms.count()); 173 174 int prev = fBisectors.count() - 1; 175 for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) { 176 fBisectors[cur] = fNorms[cur] + fNorms[prev]; 177 if (!fBisectors[cur].normalize()) { 178 fBisectors[cur] = SkPointPriv::MakeOrthog(fNorms[cur], (SkPointPriv::Side)-fSide) + 179 SkPointPriv::MakeOrthog(fNorms[prev], fSide); 180 SkAssertResult(fBisectors[cur].normalize()); 181 } else { 182 fBisectors[cur].negate(); // make the bisector face in 183 } 184 if (fCurveState[prev] == kIndeterminate_CurveState) { 185 if (fCurveState[cur] == kSharp_CurveState) { 186 fCurveState[prev] = kSharp_CurveState; 187 } else { 188 if (SkScalarAbs(fNorms[cur].dot(fNorms[prev])) > kCurveConnectionThreshold) { 189 fCurveState[prev] = kCurve_CurveState; 190 fCurveState[cur] = kCurve_CurveState; 191 } else { 192 fCurveState[prev] = kSharp_CurveState; 193 fCurveState[cur] = kSharp_CurveState; 194 } 195 } 196 } 197 198 SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length())); 199 } 200 } 201 202 // Create as many rings as we need to (up to a predefined limit) to reach the specified target 203 // depth. If we are in fill mode, the final ring will automatically be fanned. 204 bool GrAAConvexTessellator::createInsetRings(Ring& previousRing, SkScalar initialDepth, 205 SkScalar initialCoverage, SkScalar targetDepth, 206 SkScalar targetCoverage, Ring** finalRing) { 207 static const int kMaxNumRings = 8; 208 209 if (previousRing.numPts() < 3) { 210 return false; 211 } 212 Ring* currentRing = &previousRing; 213 int i; 214 for (i = 0; i < kMaxNumRings; ++i) { 215 Ring* nextRing = this->getNextRing(currentRing); 216 SkASSERT(nextRing != currentRing); 217 218 bool done = this->createInsetRing(*currentRing, nextRing, initialDepth, initialCoverage, 219 targetDepth, targetCoverage, i == 0); 220 currentRing = nextRing; 221 if (done) { 222 break; 223 } 224 currentRing->init(*this); 225 } 226 227 if (kMaxNumRings == i) { 228 // Bail if we've exceeded the amount of time we want to throw at this. 229 this->terminate(*currentRing); 230 return false; 231 } 232 bool done = currentRing->numPts() >= 3; 233 if (done) { 234 currentRing->init(*this); 235 } 236 *finalRing = currentRing; 237 return done; 238 } 239 240 // The general idea here is to, conceptually, start with the original polygon and slide 241 // the vertices along the bisectors until the first intersection. At that 242 // point two of the edges collapse and the process repeats on the new polygon. 243 // The polygon state is captured in the Ring class while the GrAAConvexTessellator 244 // controls the iteration. The CandidateVerts holds the formative points for the 245 // next ring. 246 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { 247 if (!this->extractFromPath(m, path)) { 248 return false; 249 } 250 251 SkScalar coverage = 1.0f; 252 SkScalar scaleFactor = 0.0f; 253 254 if (SkStrokeRec::kStrokeAndFill_Style == fStyle) { 255 SkASSERT(m.isSimilarity()); 256 scaleFactor = m.getMaxScale(); // x and y scale are the same 257 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; 258 Ring outerStrokeAndAARing; 259 this->createOuterRing(fInitialRing, 260 effectiveStrokeWidth / 2 + kAntialiasingRadius, 0.0, 261 &outerStrokeAndAARing); 262 263 // discard all the triangles added between the originating ring and the new outer ring 264 fIndices.rewind(); 265 266 outerStrokeAndAARing.init(*this); 267 268 outerStrokeAndAARing.makeOriginalRing(); 269 270 // Add the outer stroke ring's normals to the originating ring's normals 271 // so it can also act as an originating ring 272 fNorms.setCount(fNorms.count() + outerStrokeAndAARing.numPts()); 273 for (int i = 0; i < outerStrokeAndAARing.numPts(); ++i) { 274 SkASSERT(outerStrokeAndAARing.index(i) < fNorms.count()); 275 fNorms[outerStrokeAndAARing.index(i)] = outerStrokeAndAARing.norm(i); 276 } 277 278 // the bisectors are only needed for the computation of the outer ring 279 fBisectors.rewind(); 280 281 Ring* insetAARing; 282 this->createInsetRings(outerStrokeAndAARing, 283 0.0f, 0.0f, 2*kAntialiasingRadius, 1.0f, 284 &insetAARing); 285 286 SkDEBUGCODE(this->validate();) 287 return true; 288 } 289 290 if (SkStrokeRec::kStroke_Style == fStyle) { 291 SkASSERT(fStrokeWidth >= 0.0f); 292 SkASSERT(m.isSimilarity()); 293 scaleFactor = m.getMaxScale(); // x and y scale are the same 294 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; 295 Ring outerStrokeRing; 296 this->createOuterRing(fInitialRing, effectiveStrokeWidth / 2 - kAntialiasingRadius, 297 coverage, &outerStrokeRing); 298 outerStrokeRing.init(*this); 299 Ring outerAARing; 300 this->createOuterRing(outerStrokeRing, kAntialiasingRadius * 2, 0.0f, &outerAARing); 301 } else { 302 Ring outerAARing; 303 this->createOuterRing(fInitialRing, kAntialiasingRadius, 0.0f, &outerAARing); 304 } 305 306 // the bisectors are only needed for the computation of the outer ring 307 fBisectors.rewind(); 308 if (SkStrokeRec::kStroke_Style == fStyle && fInitialRing.numPts() > 2) { 309 SkASSERT(fStrokeWidth >= 0.0f); 310 SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth; 311 Ring* insetStrokeRing; 312 SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius; 313 if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, coverage, 314 &insetStrokeRing)) { 315 Ring* insetAARing; 316 this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, strokeDepth + 317 kAntialiasingRadius * 2, 0.0f, &insetAARing); 318 } 319 } else { 320 Ring* insetAARing; 321 this->createInsetRings(fInitialRing, 0.0f, 0.5f, kAntialiasingRadius, 1.0f, &insetAARing); 322 } 323 324 SkDEBUGCODE(this->validate();) 325 return true; 326 } 327 328 SkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const { 329 SkASSERT(edgeIdx < fNorms.count()); 330 331 SkPoint v = p - fPts[edgeIdx]; 332 SkScalar depth = -fNorms[edgeIdx].dot(v); 333 return depth; 334 } 335 336 // Find a point that is 'desiredDepth' away from the 'edgeIdx'-th edge and lies 337 // along the 'bisector' from the 'startIdx'-th point. 338 bool GrAAConvexTessellator::computePtAlongBisector(int startIdx, 339 const SkVector& bisector, 340 int edgeIdx, 341 SkScalar desiredDepth, 342 SkPoint* result) const { 343 const SkPoint& norm = fNorms[edgeIdx]; 344 345 // First find the point where the edge and the bisector intersect 346 SkPoint newP; 347 348 SkScalar t = perp_intersect(fPts[startIdx], bisector, fPts[edgeIdx], norm); 349 if (SkScalarNearlyEqual(t, 0.0f)) { 350 // the start point was one of the original ring points 351 SkASSERT(startIdx < fPts.count()); 352 newP = fPts[startIdx]; 353 } else if (t < 0.0f) { 354 newP = bisector; 355 newP.scale(t); 356 newP += fPts[startIdx]; 357 } else { 358 return false; 359 } 360 361 // Then offset along the bisector from that point the correct distance 362 SkScalar dot = bisector.dot(norm); 363 t = -desiredDepth / dot; 364 *result = bisector; 365 result->scale(t); 366 *result += newP; 367 368 return true; 369 } 370 371 bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& path) { 372 SkASSERT(SkPath::kConvex_Convexity == path.getConvexity()); 373 374 SkRect bounds = path.getBounds(); 375 m.mapRect(&bounds); 376 if (!bounds.isFinite()) { 377 // We could do something smarter here like clip the path based on the bounds of the dst. 378 // We'd have to be careful about strokes to ensure we don't draw something wrong. 379 return false; 380 } 381 382 // Outer ring: 3*numPts 383 // Middle ring: numPts 384 // Presumptive inner ring: numPts 385 this->reservePts(5*path.countPoints()); 386 // Outer ring: 12*numPts 387 // Middle ring: 0 388 // Presumptive inner ring: 6*numPts + 6 389 fIndices.setReserve(18*path.countPoints() + 6); 390 391 // TODO: is there a faster way to extract the points from the path? Perhaps 392 // get all the points via a new entry point, transform them all in bulk 393 // and then walk them to find duplicates? 394 SkPath::Iter iter(path, true); 395 SkPoint pts[4]; 396 SkPath::Verb verb; 397 while ((verb = iter.next(pts, true, true)) != SkPath::kDone_Verb) { 398 switch (verb) { 399 case SkPath::kLine_Verb: 400 this->lineTo(m, pts[1], kSharp_CurveState); 401 break; 402 case SkPath::kQuad_Verb: 403 this->quadTo(m, pts); 404 break; 405 case SkPath::kCubic_Verb: 406 this->cubicTo(m, pts); 407 break; 408 case SkPath::kConic_Verb: 409 this->conicTo(m, pts, iter.conicWeight()); 410 break; 411 case SkPath::kMove_Verb: 412 case SkPath::kClose_Verb: 413 case SkPath::kDone_Verb: 414 break; 415 } 416 } 417 418 if (this->numPts() < 2) { 419 return false; 420 } 421 422 // check if last point is a duplicate of the first point. If so, remove it. 423 if (duplicate_pt(fPts[this->numPts()-1], fPts[0])) { 424 this->popLastPt(); 425 } 426 427 // Remove any lingering colinear points where the path wraps around 428 bool noRemovalsToDo = false; 429 while (!noRemovalsToDo && this->numPts() >= 3) { 430 if (points_are_colinear_and_b_is_middle(fPts[fPts.count() - 2], fPts.top(), fPts[0])) { 431 this->popLastPt(); 432 } else if (points_are_colinear_and_b_is_middle(fPts.top(), fPts[0], fPts[1])) { 433 this->popFirstPtShuffle(); 434 } else { 435 noRemovalsToDo = true; 436 } 437 } 438 439 // Compute the normals and bisectors. 440 SkASSERT(fNorms.empty()); 441 if (this->numPts() >= 3) { 442 this->computeNormals(); 443 this->computeBisectors(); 444 } else if (this->numPts() == 2) { 445 // We've got two points, so we're degenerate. 446 if (fStyle == SkStrokeRec::kFill_Style) { 447 // it's a fill, so we don't need to worry about degenerate paths 448 return false; 449 } 450 // For stroking, we still need to process the degenerate path, so fix it up 451 fSide = SkPointPriv::kLeft_Side; 452 453 fNorms.append(2); 454 fNorms[0] = SkPointPriv::MakeOrthog(fPts[1] - fPts[0], fSide); 455 fNorms[0].normalize(); 456 fNorms[1] = -fNorms[0]; 457 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[0].length())); 458 // we won't actually use the bisectors, so just push zeroes 459 fBisectors.push_back(SkPoint::Make(0.0, 0.0)); 460 fBisectors.push_back(SkPoint::Make(0.0, 0.0)); 461 } else { 462 return false; 463 } 464 465 fCandidateVerts.setReserve(this->numPts()); 466 fInitialRing.setReserve(this->numPts()); 467 for (int i = 0; i < this->numPts(); ++i) { 468 fInitialRing.addIdx(i, i); 469 } 470 fInitialRing.init(fNorms, fBisectors); 471 472 this->validate(); 473 return true; 474 } 475 476 GrAAConvexTessellator::Ring* GrAAConvexTessellator::getNextRing(Ring* lastRing) { 477 #if GR_AA_CONVEX_TESSELLATOR_VIZ 478 Ring* ring = *fRings.push() = new Ring; 479 ring->setReserve(fInitialRing.numPts()); 480 ring->rewind(); 481 return ring; 482 #else 483 // Flip flop back and forth between fRings[0] & fRings[1] 484 int nextRing = (lastRing == &fRings[0]) ? 1 : 0; 485 fRings[nextRing].setReserve(fInitialRing.numPts()); 486 fRings[nextRing].rewind(); 487 return &fRings[nextRing]; 488 #endif 489 } 490 491 void GrAAConvexTessellator::fanRing(const Ring& ring) { 492 // fan out from point 0 493 int startIdx = ring.index(0); 494 for (int cur = ring.numPts() - 2; cur >= 0; --cur) { 495 this->addTri(startIdx, ring.index(cur), ring.index(cur + 1)); 496 } 497 } 498 499 void GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar outset, 500 SkScalar coverage, Ring* nextRing) { 501 const int numPts = previousRing.numPts(); 502 if (numPts == 0) { 503 return; 504 } 505 506 int prev = numPts - 1; 507 int lastPerpIdx = -1, firstPerpIdx = -1; 508 509 const SkScalar outsetSq = outset * outset; 510 SkScalar miterLimitSq = outset * fMiterLimit; 511 miterLimitSq = miterLimitSq * miterLimitSq; 512 for (int cur = 0; cur < numPts; ++cur) { 513 int originalIdx = previousRing.index(cur); 514 // For each vertex of the original polygon we add at least two points to the 515 // outset polygon - one extending perpendicular to each impinging edge. Connecting these 516 // two points yields a bevel join. We need one additional point for a mitered join, and 517 // a round join requires one or more points depending upon curvature. 518 519 // The perpendicular point for the last edge 520 SkPoint normal1 = previousRing.norm(prev); 521 SkPoint perp1 = normal1; 522 perp1.scale(outset); 523 perp1 += this->point(originalIdx); 524 525 // The perpendicular point for the next edge. 526 SkPoint normal2 = previousRing.norm(cur); 527 SkPoint perp2 = normal2; 528 perp2.scale(outset); 529 perp2 += fPts[originalIdx]; 530 531 CurveState curve = fCurveState[originalIdx]; 532 533 // We know it isn't a duplicate of the prior point (since it and this 534 // one are just perpendicular offsets from the non-merged polygon points) 535 int perp1Idx = this->addPt(perp1, -outset, coverage, false, curve); 536 nextRing->addIdx(perp1Idx, originalIdx); 537 538 int perp2Idx; 539 // For very shallow angles all the corner points could fuse. 540 if (duplicate_pt(perp2, this->point(perp1Idx))) { 541 perp2Idx = perp1Idx; 542 } else { 543 perp2Idx = this->addPt(perp2, -outset, coverage, false, curve); 544 } 545 546 if (perp2Idx != perp1Idx) { 547 if (curve == kCurve_CurveState) { 548 // bevel or round depending upon curvature 549 SkScalar dotProd = normal1.dot(normal2); 550 if (dotProd < kRoundCapThreshold) { 551 // Currently we "round" by creating a single extra point, which produces 552 // good results for common cases. For thick strokes with high curvature, we will 553 // need to add more points; for the time being we simply fall back to software 554 // rendering for thick strokes. 555 SkPoint miter = previousRing.bisector(cur); 556 miter.setLength(-outset); 557 miter += fPts[originalIdx]; 558 559 // For very shallow angles all the corner points could fuse 560 if (!duplicate_pt(miter, this->point(perp1Idx))) { 561 int miterIdx; 562 miterIdx = this->addPt(miter, -outset, coverage, false, kSharp_CurveState); 563 nextRing->addIdx(miterIdx, originalIdx); 564 // The two triangles for the corner 565 this->addTri(originalIdx, perp1Idx, miterIdx); 566 this->addTri(originalIdx, miterIdx, perp2Idx); 567 } 568 } else { 569 this->addTri(originalIdx, perp1Idx, perp2Idx); 570 } 571 } else { 572 switch (fJoin) { 573 case SkPaint::Join::kMiter_Join: { 574 // The bisector outset point 575 SkPoint miter = previousRing.bisector(cur); 576 SkScalar dotProd = normal1.dot(normal2); 577 // The max is because this could go slightly negative if precision causes 578 // us to become slightly concave. 579 SkScalar sinHalfAngleSq = SkTMax(SkScalarHalf(SK_Scalar1 + dotProd), 0.f); 580 SkScalar lengthSq = sk_ieee_float_divide(outsetSq, sinHalfAngleSq); 581 if (lengthSq > miterLimitSq) { 582 // just bevel it 583 this->addTri(originalIdx, perp1Idx, perp2Idx); 584 break; 585 } 586 miter.setLength(-SkScalarSqrt(lengthSq)); 587 miter += fPts[originalIdx]; 588 589 // For very shallow angles all the corner points could fuse 590 if (!duplicate_pt(miter, this->point(perp1Idx))) { 591 int miterIdx; 592 miterIdx = this->addPt(miter, -outset, coverage, false, 593 kSharp_CurveState); 594 nextRing->addIdx(miterIdx, originalIdx); 595 // The two triangles for the corner 596 this->addTri(originalIdx, perp1Idx, miterIdx); 597 this->addTri(originalIdx, miterIdx, perp2Idx); 598 } else { 599 // ignore the miter point as it's so close to perp1/perp2 and simply 600 // bevel. 601 this->addTri(originalIdx, perp1Idx, perp2Idx); 602 } 603 break; 604 } 605 case SkPaint::Join::kBevel_Join: 606 this->addTri(originalIdx, perp1Idx, perp2Idx); 607 break; 608 default: 609 // kRound_Join is unsupported for now. GrAALinearizingConvexPathRenderer is 610 // only willing to draw mitered or beveled, so we should never get here. 611 SkASSERT(false); 612 } 613 } 614 615 nextRing->addIdx(perp2Idx, originalIdx); 616 } 617 618 if (0 == cur) { 619 // Store the index of the first perpendicular point to finish up 620 firstPerpIdx = perp1Idx; 621 SkASSERT(-1 == lastPerpIdx); 622 } else { 623 // The triangles for the previous edge 624 int prevIdx = previousRing.index(prev); 625 this->addTri(prevIdx, perp1Idx, originalIdx); 626 this->addTri(prevIdx, lastPerpIdx, perp1Idx); 627 } 628 629 // Track the last perpendicular outset point so we can construct the 630 // trailing edge triangles. 631 lastPerpIdx = perp2Idx; 632 prev = cur; 633 } 634 635 // pick up the final edge rect 636 int lastIdx = previousRing.index(numPts - 1); 637 this->addTri(lastIdx, firstPerpIdx, previousRing.index(0)); 638 this->addTri(lastIdx, lastPerpIdx, firstPerpIdx); 639 640 this->validate(); 641 } 642 643 // Something went wrong in the creation of the next ring. If we're filling the shape, just go ahead 644 // and fan it. 645 void GrAAConvexTessellator::terminate(const Ring& ring) { 646 if (fStyle != SkStrokeRec::kStroke_Style && ring.numPts() > 0) { 647 this->fanRing(ring); 648 } 649 } 650 651 static SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar initialCoverage, 652 SkScalar targetDepth, SkScalar targetCoverage) { 653 if (SkScalarNearlyEqual(initialDepth, targetDepth)) { 654 return targetCoverage; 655 } 656 SkScalar result = (depth - initialDepth) / (targetDepth - initialDepth) * 657 (targetCoverage - initialCoverage) + initialCoverage; 658 return SkScalarClampMax(result, 1.0f); 659 } 660 661 // return true when processing is complete 662 bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing, 663 SkScalar initialDepth, SkScalar initialCoverage, 664 SkScalar targetDepth, SkScalar targetCoverage, 665 bool forceNew) { 666 bool done = false; 667 668 fCandidateVerts.rewind(); 669 670 // Loop through all the points in the ring and find the intersection with the smallest depth 671 SkScalar minDist = SK_ScalarMax, minT = 0.0f; 672 int minEdgeIdx = -1; 673 674 for (int cur = 0; cur < lastRing.numPts(); ++cur) { 675 int next = (cur + 1) % lastRing.numPts(); 676 677 SkScalar t; 678 bool result = intersect(this->point(lastRing.index(cur)), lastRing.bisector(cur), 679 this->point(lastRing.index(next)), lastRing.bisector(next), 680 &t); 681 // The bisectors may be parallel (!result) or the previous ring may have become slightly 682 // concave due to accumulated error (t <= 0). 683 if (!result || t <= 0) { 684 continue; 685 } 686 SkScalar dist = -t * lastRing.norm(cur).dot(lastRing.bisector(cur)); 687 688 if (minDist > dist) { 689 minDist = dist; 690 minT = t; 691 minEdgeIdx = cur; 692 } 693 } 694 695 if (minEdgeIdx == -1) { 696 return false; 697 } 698 SkPoint newPt = lastRing.bisector(minEdgeIdx); 699 newPt.scale(minT); 700 newPt += this->point(lastRing.index(minEdgeIdx)); 701 702 SkScalar depth = this->computeDepthFromEdge(lastRing.origEdgeID(minEdgeIdx), newPt); 703 if (depth >= targetDepth) { 704 // None of the bisectors intersect before reaching the desired depth. 705 // Just step them all to the desired depth 706 depth = targetDepth; 707 done = true; 708 } 709 710 // 'dst' stores where each point in the last ring maps to/transforms into 711 // in the next ring. 712 SkTDArray<int> dst; 713 dst.setCount(lastRing.numPts()); 714 715 // Create the first point (who compares with no one) 716 if (!this->computePtAlongBisector(lastRing.index(0), 717 lastRing.bisector(0), 718 lastRing.origEdgeID(0), 719 depth, &newPt)) { 720 this->terminate(lastRing); 721 return true; 722 } 723 dst[0] = fCandidateVerts.addNewPt(newPt, 724 lastRing.index(0), lastRing.origEdgeID(0), 725 !this->movable(lastRing.index(0))); 726 727 // Handle the middle points (who only compare with the prior point) 728 for (int cur = 1; cur < lastRing.numPts()-1; ++cur) { 729 if (!this->computePtAlongBisector(lastRing.index(cur), 730 lastRing.bisector(cur), 731 lastRing.origEdgeID(cur), 732 depth, &newPt)) { 733 this->terminate(lastRing); 734 return true; 735 } 736 if (!duplicate_pt(newPt, fCandidateVerts.lastPoint())) { 737 dst[cur] = fCandidateVerts.addNewPt(newPt, 738 lastRing.index(cur), lastRing.origEdgeID(cur), 739 !this->movable(lastRing.index(cur))); 740 } else { 741 dst[cur] = fCandidateVerts.fuseWithPrior(lastRing.origEdgeID(cur)); 742 } 743 } 744 745 // Check on the last point (handling the wrap around) 746 int cur = lastRing.numPts()-1; 747 if (!this->computePtAlongBisector(lastRing.index(cur), 748 lastRing.bisector(cur), 749 lastRing.origEdgeID(cur), 750 depth, &newPt)) { 751 this->terminate(lastRing); 752 return true; 753 } 754 bool dupPrev = duplicate_pt(newPt, fCandidateVerts.lastPoint()); 755 bool dupNext = duplicate_pt(newPt, fCandidateVerts.firstPoint()); 756 757 if (!dupPrev && !dupNext) { 758 dst[cur] = fCandidateVerts.addNewPt(newPt, 759 lastRing.index(cur), lastRing.origEdgeID(cur), 760 !this->movable(lastRing.index(cur))); 761 } else if (dupPrev && !dupNext) { 762 dst[cur] = fCandidateVerts.fuseWithPrior(lastRing.origEdgeID(cur)); 763 } else if (!dupPrev && dupNext) { 764 dst[cur] = fCandidateVerts.fuseWithNext(); 765 } else { 766 bool dupPrevVsNext = duplicate_pt(fCandidateVerts.firstPoint(), fCandidateVerts.lastPoint()); 767 768 if (!dupPrevVsNext) { 769 dst[cur] = fCandidateVerts.fuseWithPrior(lastRing.origEdgeID(cur)); 770 } else { 771 const int fused = fCandidateVerts.fuseWithBoth(); 772 dst[cur] = fused; 773 const int targetIdx = dst[cur - 1]; 774 for (int i = cur - 1; i >= 0 && dst[i] == targetIdx; i--) { 775 dst[i] = fused; 776 } 777 } 778 } 779 780 // Fold the new ring's points into the global pool 781 for (int i = 0; i < fCandidateVerts.numPts(); ++i) { 782 int newIdx; 783 if (fCandidateVerts.needsToBeNew(i) || forceNew) { 784 // if the originating index is still valid then this point wasn't 785 // fused (and is thus movable) 786 SkScalar coverage = compute_coverage(depth, initialDepth, initialCoverage, 787 targetDepth, targetCoverage); 788 newIdx = this->addPt(fCandidateVerts.point(i), depth, coverage, 789 fCandidateVerts.originatingIdx(i) != -1, kSharp_CurveState); 790 } else { 791 SkASSERT(fCandidateVerts.originatingIdx(i) != -1); 792 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.point(i), depth, 793 targetCoverage); 794 newIdx = fCandidateVerts.originatingIdx(i); 795 } 796 797 nextRing->addIdx(newIdx, fCandidateVerts.origEdge(i)); 798 } 799 800 // 'dst' currently has indices into the ring. Remap these to be indices 801 // into the global pool since the triangulation operates in that space. 802 for (int i = 0; i < dst.count(); ++i) { 803 dst[i] = nextRing->index(dst[i]); 804 } 805 806 for (int i = 0; i < lastRing.numPts(); ++i) { 807 int next = (i + 1) % lastRing.numPts(); 808 809 this->addTri(lastRing.index(i), lastRing.index(next), dst[next]); 810 this->addTri(lastRing.index(i), dst[next], dst[i]); 811 } 812 813 if (done && fStyle != SkStrokeRec::kStroke_Style) { 814 // fill or stroke-and-fill 815 this->fanRing(*nextRing); 816 } 817 818 if (nextRing->numPts() < 3) { 819 done = true; 820 } 821 return done; 822 } 823 824 void GrAAConvexTessellator::validate() const { 825 SkASSERT(fPts.count() == fMovable.count()); 826 SkASSERT(fPts.count() == fCoverages.count()); 827 SkASSERT(fPts.count() == fCurveState.count()); 828 SkASSERT(0 == (fIndices.count() % 3)); 829 SkASSERT(!fBisectors.count() || fBisectors.count() == fNorms.count()); 830 } 831 832 ////////////////////////////////////////////////////////////////////////////// 833 void GrAAConvexTessellator::Ring::init(const GrAAConvexTessellator& tess) { 834 this->computeNormals(tess); 835 this->computeBisectors(tess); 836 } 837 838 void GrAAConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms, 839 const SkTDArray<SkVector>& bisectors) { 840 for (int i = 0; i < fPts.count(); ++i) { 841 fPts[i].fNorm = norms[i]; 842 fPts[i].fBisector = bisectors[i]; 843 } 844 } 845 846 // Compute the outward facing normal at each vertex. 847 void GrAAConvexTessellator::Ring::computeNormals(const GrAAConvexTessellator& tess) { 848 for (int cur = 0; cur < fPts.count(); ++cur) { 849 int next = (cur + 1) % fPts.count(); 850 851 fPts[cur].fNorm = tess.point(fPts[next].fIndex) - tess.point(fPts[cur].fIndex); 852 SkPoint::Normalize(&fPts[cur].fNorm); 853 fPts[cur].fNorm = SkPointPriv::MakeOrthog(fPts[cur].fNorm, tess.side()); 854 } 855 } 856 857 void GrAAConvexTessellator::Ring::computeBisectors(const GrAAConvexTessellator& tess) { 858 int prev = fPts.count() - 1; 859 for (int cur = 0; cur < fPts.count(); prev = cur, ++cur) { 860 fPts[cur].fBisector = fPts[cur].fNorm + fPts[prev].fNorm; 861 if (!fPts[cur].fBisector.normalize()) { 862 fPts[cur].fBisector = 863 SkPointPriv::MakeOrthog(fPts[cur].fNorm, (SkPointPriv::Side)-tess.side()) + 864 SkPointPriv::MakeOrthog(fPts[prev].fNorm, tess.side()); 865 SkAssertResult(fPts[cur].fBisector.normalize()); 866 } else { 867 fPts[cur].fBisector.negate(); // make the bisector face in 868 } 869 } 870 } 871 872 ////////////////////////////////////////////////////////////////////////////// 873 #ifdef SK_DEBUG 874 // Is this ring convex? 875 bool GrAAConvexTessellator::Ring::isConvex(const GrAAConvexTessellator& tess) const { 876 if (fPts.count() < 3) { 877 return true; 878 } 879 880 SkPoint prev = tess.point(fPts[0].fIndex) - tess.point(fPts.top().fIndex); 881 SkPoint cur = tess.point(fPts[1].fIndex) - tess.point(fPts[0].fIndex); 882 SkScalar minDot = prev.fX * cur.fY - prev.fY * cur.fX; 883 SkScalar maxDot = minDot; 884 885 prev = cur; 886 for (int i = 1; i < fPts.count(); ++i) { 887 int next = (i + 1) % fPts.count(); 888 889 cur = tess.point(fPts[next].fIndex) - tess.point(fPts[i].fIndex); 890 SkScalar dot = prev.fX * cur.fY - prev.fY * cur.fX; 891 892 minDot = SkMinScalar(minDot, dot); 893 maxDot = SkMaxScalar(maxDot, dot); 894 895 prev = cur; 896 } 897 898 if (SkScalarNearlyEqual(maxDot, 0.0f, 0.005f)) { 899 maxDot = 0; 900 } 901 if (SkScalarNearlyEqual(minDot, 0.0f, 0.005f)) { 902 minDot = 0; 903 } 904 return (maxDot >= 0.0f) == (minDot >= 0.0f); 905 } 906 907 #endif 908 909 void GrAAConvexTessellator::lineTo(const SkPoint& p, CurveState curve) { 910 if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) { 911 return; 912 } 913 914 if (this->numPts() >= 2 && 915 points_are_colinear_and_b_is_middle(fPts[fPts.count() - 2], fPts.top(), p)) { 916 // The old last point is on the line from the second to last to the new point 917 this->popLastPt(); 918 // double-check that the new last point is not a duplicate of the new point. In an ideal 919 // world this wouldn't be necessary (since it's only possible for non-convex paths), but 920 // floating point precision issues mean it can actually happen on paths that were 921 // determined to be convex. 922 if (duplicate_pt(p, this->lastPoint())) { 923 return; 924 } 925 } 926 SkScalar initialRingCoverage = (SkStrokeRec::kFill_Style == fStyle) ? 0.5f : 1.0f; 927 this->addPt(p, 0.0f, initialRingCoverage, false, curve); 928 } 929 930 void GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, CurveState curve) { 931 m.mapPoints(&p, 1); 932 this->lineTo(p, curve); 933 } 934 935 void GrAAConvexTessellator::quadTo(const SkPoint pts[3]) { 936 int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); 937 fPointBuffer.setCount(maxCount); 938 SkPoint* target = fPointBuffer.begin(); 939 int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], 940 kQuadTolerance, &target, maxCount); 941 fPointBuffer.setCount(count); 942 for (int i = 0; i < count - 1; i++) { 943 this->lineTo(fPointBuffer[i], kCurve_CurveState); 944 } 945 this->lineTo(fPointBuffer[count - 1], kIndeterminate_CurveState); 946 } 947 948 void GrAAConvexTessellator::quadTo(const SkMatrix& m, SkPoint pts[3]) { 949 m.mapPoints(pts, 3); 950 this->quadTo(pts); 951 } 952 953 void GrAAConvexTessellator::cubicTo(const SkMatrix& m, SkPoint pts[4]) { 954 m.mapPoints(pts, 4); 955 int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); 956 fPointBuffer.setCount(maxCount); 957 SkPoint* target = fPointBuffer.begin(); 958 int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], 959 kCubicTolerance, &target, maxCount); 960 fPointBuffer.setCount(count); 961 for (int i = 0; i < count - 1; i++) { 962 this->lineTo(fPointBuffer[i], kCurve_CurveState); 963 } 964 this->lineTo(fPointBuffer[count - 1], kIndeterminate_CurveState); 965 } 966 967 // include down here to avoid compilation errors caused by "-" overload in SkGeometry.h 968 #include "SkGeometry.h" 969 970 void GrAAConvexTessellator::conicTo(const SkMatrix& m, SkPoint pts[3], SkScalar w) { 971 m.mapPoints(pts, 3); 972 SkAutoConicToQuads quadder; 973 const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance); 974 SkPoint lastPoint = *(quads++); 975 int count = quadder.countQuads(); 976 for (int i = 0; i < count; ++i) { 977 SkPoint quadPts[3]; 978 quadPts[0] = lastPoint; 979 quadPts[1] = quads[0]; 980 quadPts[2] = i == count - 1 ? pts[2] : quads[1]; 981 this->quadTo(quadPts); 982 lastPoint = quadPts[2]; 983 quads += 2; 984 } 985 } 986 987 ////////////////////////////////////////////////////////////////////////////// 988 #if GR_AA_CONVEX_TESSELLATOR_VIZ 989 static const SkScalar kPointRadius = 0.02f; 990 static const SkScalar kArrowStrokeWidth = 0.0f; 991 static const SkScalar kArrowLength = 0.2f; 992 static const SkScalar kEdgeTextSize = 0.1f; 993 static const SkScalar kPointTextSize = 0.02f; 994 995 static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) { 996 SkPaint paint; 997 SkASSERT(paramValue <= 1.0f); 998 int gs = int(255*paramValue); 999 paint.setARGB(255, gs, gs, gs); 1000 1001 canvas->drawCircle(p.fX, p.fY, kPointRadius, paint); 1002 1003 if (stroke) { 1004 SkPaint stroke; 1005 stroke.setColor(SK_ColorYELLOW); 1006 stroke.setStyle(SkPaint::kStroke_Style); 1007 stroke.setStrokeWidth(kPointRadius/3.0f); 1008 canvas->drawCircle(p.fX, p.fY, kPointRadius, stroke); 1009 } 1010 } 1011 1012 static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, SkColor color) { 1013 SkPaint p; 1014 p.setColor(color); 1015 1016 canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, p); 1017 } 1018 1019 static void draw_arrow(SkCanvas*canvas, const SkPoint& p, const SkPoint &n, 1020 SkScalar len, SkColor color) { 1021 SkPaint paint; 1022 paint.setColor(color); 1023 paint.setStrokeWidth(kArrowStrokeWidth); 1024 paint.setStyle(SkPaint::kStroke_Style); 1025 1026 canvas->drawLine(p.fX, p.fY, 1027 p.fX + len * n.fX, p.fY + len * n.fY, 1028 paint); 1029 } 1030 1031 void GrAAConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const { 1032 SkPaint paint; 1033 paint.setTextSize(kEdgeTextSize); 1034 1035 for (int cur = 0; cur < fPts.count(); ++cur) { 1036 int next = (cur + 1) % fPts.count(); 1037 1038 draw_line(canvas, 1039 tess.point(fPts[cur].fIndex), 1040 tess.point(fPts[next].fIndex), 1041 SK_ColorGREEN); 1042 1043 SkPoint mid = tess.point(fPts[cur].fIndex) + tess.point(fPts[next].fIndex); 1044 mid.scale(0.5f); 1045 1046 if (fPts.count()) { 1047 draw_arrow(canvas, mid, fPts[cur].fNorm, kArrowLength, SK_ColorRED); 1048 mid.fX += (kArrowLength/2) * fPts[cur].fNorm.fX; 1049 mid.fY += (kArrowLength/2) * fPts[cur].fNorm.fY; 1050 } 1051 1052 SkString num; 1053 num.printf("%d", this->origEdgeID(cur)); 1054 canvas->drawString(num, mid.fX, mid.fY, paint); 1055 1056 if (fPts.count()) { 1057 draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector, 1058 kArrowLength, SK_ColorBLUE); 1059 } 1060 } 1061 } 1062 1063 void GrAAConvexTessellator::draw(SkCanvas* canvas) const { 1064 for (int i = 0; i < fIndices.count(); i += 3) { 1065 SkASSERT(fIndices[i] < this->numPts()) ; 1066 SkASSERT(fIndices[i+1] < this->numPts()) ; 1067 SkASSERT(fIndices[i+2] < this->numPts()) ; 1068 1069 draw_line(canvas, 1070 this->point(this->fIndices[i]), this->point(this->fIndices[i+1]), 1071 SK_ColorBLACK); 1072 draw_line(canvas, 1073 this->point(this->fIndices[i+1]), this->point(this->fIndices[i+2]), 1074 SK_ColorBLACK); 1075 draw_line(canvas, 1076 this->point(this->fIndices[i+2]), this->point(this->fIndices[i]), 1077 SK_ColorBLACK); 1078 } 1079 1080 fInitialRing.draw(canvas, *this); 1081 for (int i = 0; i < fRings.count(); ++i) { 1082 fRings[i]->draw(canvas, *this); 1083 } 1084 1085 for (int i = 0; i < this->numPts(); ++i) { 1086 draw_point(canvas, 1087 this->point(i), 0.5f + (this->depth(i)/(2 * kAntialiasingRadius)), 1088 !this->movable(i)); 1089 1090 SkPaint paint; 1091 paint.setTextSize(kPointTextSize); 1092 if (this->depth(i) <= -kAntialiasingRadius) { 1093 paint.setColor(SK_ColorWHITE); 1094 } 1095 1096 SkString num; 1097 num.printf("%d", i); 1098 canvas->drawString(num, 1099 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f), 1100 paint); 1101 } 1102 } 1103 1104 #endif 1105