184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips/*
284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips * Copyright 2015 Google Inc.
384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips *
484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips * Use of this source code is governed by a BSD-style license that can be
584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips * found in the LICENSE file.
684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips */
784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#include "GrAAConvexTessellator.h"
984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#include "SkCanvas.h"
1084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#include "SkPath.h"
1184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#include "SkPoint.h"
1284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#include "SkString.h"
131a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "GrPathUtils.h"
1484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
1584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// Next steps:
1684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips//  add an interactive sample app slide
1784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips//  add debug check that all points are suitably far apart
1884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips//  test more degenerate cases
1984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
2084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// The tolerance for fusing vertices and eliminating colinear lines (It is in device space).
2184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic const SkScalar kClose = (SK_Scalar1 / 16);
228be952ad8c9deefe19cff36f9ad217563400f817Mike Reedstatic const SkScalar kCloseSqd = kClose * kClose;
2384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
24bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// tesselation tolerance values, in device space pixels
25bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kQuadTolerance = 0.2f;
26bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kCubicTolerance = 0.2f;
27bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kConicTolerance = 0.5f;
28bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
29bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// dot product below which we use a round cap between curve segments
30bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitastatic const SkScalar kRoundCapThreshold = 0.8f;
31bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
32fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas// dot product above which we consider two adjacent curves to be part of the "same" curve
33fc6cb7366493665dce96c5d66e67e94924b21cb6ethannicholasstatic const SkScalar kCurveConnectionThreshold = 0.8f;
34fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas
358c170971f182d47bc9af71fc88a607740d03dfd5robertphillipsstatic bool intersect(const SkPoint& p0, const SkPoint& n0,
368c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                      const SkPoint& p1, const SkPoint& n1,
378c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                      SkScalar* t) {
3884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    const SkPoint v = p1 - p0;
3984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX;
408c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (SkScalarNearlyZero(perpDot)) {
418c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        return false;
428c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    }
438c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    *t = (v.fX * n1.fY - v.fY * n1.fX) / perpDot;
448c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkASSERT(SkScalarIsFinite(*t));
458c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    return true;
4684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
4784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
489d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary// This is a special case version of intersect where we have the vector
4984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// perpendicular to the second line rather than the vector parallel to it.
5084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0,
5184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                               const SkPoint& p1, const SkPoint& perp) {
5284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    const SkPoint v = p1 - p0;
5384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar perpDot = n0.dot(perp);
5484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return v.dot(perp) / perpDot;
5584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
5684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
5784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) {
5884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar distSq = p0.distanceToSqd(p1);
5984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return distSq < kCloseSqd;
6084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
6184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
6284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic SkScalar abs_dist_from_line(const SkPoint& p0, const SkVector& v, const SkPoint& test) {
6384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint testV = test - p0;
6484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar dist = testV.fX * v.fY - testV.fY * v.fX;
6584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return SkScalarAbs(dist);
6684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
6784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
6884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsint GrAAConvexTessellator::addPt(const SkPoint& pt,
6984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                 SkScalar depth,
70bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                 SkScalar coverage,
711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                                 bool movable,
72fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                                 CurveState curve) {
7384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
7484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
7584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int index = fPts.count();
7684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *fPts.push() = pt;
77bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    *fCoverages.push() = coverage;
7884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *fMovable.push() = movable;
79fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas    *fCurveState.push() = curve;
8084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
8184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
8284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return index;
8384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
8484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
8584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::popLastPt() {
8684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
8784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
8884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fPts.pop();
89bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    fCoverages.pop();
9084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fMovable.pop();
911d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    fCurveState.pop();
9284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
9384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
9484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
9584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
9684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::popFirstPtShuffle() {
9784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
9884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
9984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fPts.removeShuffle(0);
100bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    fCoverages.removeShuffle(0);
10184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fMovable.removeShuffle(0);
1021d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    fCurveState.removeShuffle(0);
10384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
10484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
10584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
10684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
10784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::updatePt(int index,
10884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                     const SkPoint& pt,
109bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                     SkScalar depth,
110bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                     SkScalar coverage) {
11184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
11284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(fMovable[index]);
11384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
11484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fPts[index] = pt;
115bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    fCoverages[index] = coverage;
11684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
11784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
11884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::addTri(int i0, int i1, int i2) {
11984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (i0 == i1 || i1 == i2 || i2 == i0) {
12084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        return;
12184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
12284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
12384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *fIndices.push() = i0;
12484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *fIndices.push() = i1;
12584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *fIndices.push() = i2;
12684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
12784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
12884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::rewind() {
12984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fPts.rewind();
130bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    fCoverages.rewind();
13184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fMovable.rewind();
13284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fIndices.rewind();
13384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fNorms.rewind();
1341d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    fCurveState.rewind();
13584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fInitialRing.rewind();
13684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fCandidateVerts.rewind();
13784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#if GR_AA_CONVEX_TESSELLATOR_VIZ
13884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fRings.rewind();        // TODO: leak in this case!
13984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#else
14084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fRings[0].rewind();
14184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fRings[1].rewind();
14284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#endif
14384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
14484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
14584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::computeBisectors() {
14684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fBisectors.setCount(fNorms.count());
14784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
14884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int prev = fBisectors.count() - 1;
14984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) {
15084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fBisectors[cur] = fNorms[cur] + fNorms[prev];
151364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips        if (!fBisectors[cur].normalize()) {
152364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            SkASSERT(SkPoint::kLeft_Side == fSide || SkPoint::kRight_Side == fSide);
153364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            fBisectors[cur].setOrthog(fNorms[cur], (SkPoint::Side)-fSide);
154364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            SkVector other;
155364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            other.setOrthog(fNorms[prev], fSide);
156364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            fBisectors[cur] += other;
1579d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary            SkAssertResult(fBisectors[cur].normalize());
158364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips        } else {
159364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            fBisectors[cur].negate();      // make the bisector face in
160364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips        }
161fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas        if (fCurveState[prev] == kIndeterminate_CurveState) {
162fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas            if (fCurveState[cur] == kSharp_CurveState) {
163fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                fCurveState[prev] = kSharp_CurveState;
164fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas            } else {
165fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                if (SkScalarAbs(fNorms[cur].dot(fNorms[prev])) > kCurveConnectionThreshold) {
166fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                    fCurveState[prev] = kCurve_CurveState;
167fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                    fCurveState[cur]  = kCurve_CurveState;
168fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                } else {
169fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                    fCurveState[prev] = kSharp_CurveState;
170fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                    fCurveState[cur]  = kSharp_CurveState;
171fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                }
172fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas            }
173fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas        }
17484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
17584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length()));
17684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
17784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
17884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
179bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// Create as many rings as we need to (up to a predefined limit) to reach the specified target
180bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// depth. If we are in fill mode, the final ring will automatically be fanned.
181bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitabool GrAAConvexTessellator::createInsetRings(Ring& previousRing, SkScalar initialDepth,
1829d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                                             SkScalar initialCoverage, SkScalar targetDepth,
183bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                             SkScalar targetCoverage, Ring** finalRing) {
184bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    static const int kMaxNumRings = 8;
185bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
186bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (previousRing.numPts() < 3) {
187bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
188bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
189bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    Ring* currentRing = &previousRing;
190bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    int i;
191bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    for (i = 0; i < kMaxNumRings; ++i) {
192bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        Ring* nextRing = this->getNextRing(currentRing);
193bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkASSERT(nextRing != currentRing);
194bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
1959d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        bool done = this->createInsetRing(*currentRing, nextRing, initialDepth, initialCoverage,
196bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                          targetDepth, targetCoverage, i == 0);
197bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        currentRing = nextRing;
198bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (done) {
199bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            break;
200bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
201bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        currentRing->init(*this);
202bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
203bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
204bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (kMaxNumRings == i) {
205bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // Bail if we've exceeded the amount of time we want to throw at this.
206bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->terminate(*currentRing);
207bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
208bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
209bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    bool done = currentRing->numPts() >= 3;
210bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (done) {
211bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        currentRing->init(*this);
212bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
213bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    *finalRing = currentRing;
214bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    return done;
215bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita}
216bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
21784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// The general idea here is to, conceptually, start with the original polygon and slide
21884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// the vertices along the bisectors until the first intersection. At that
21984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// point two of the edges collapse and the process repeats on the new polygon.
22084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// The polygon state is captured in the Ring class while the GrAAConvexTessellator
22184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// controls the iteration. The CandidateVerts holds the formative points for the
22284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// next ring.
22384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsbool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) {
22484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (!this->extractFromPath(m, path)) {
22584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        return false;
22684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
22784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
228bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    SkScalar coverage = 1.0f;
229fea7763140ba74b78f2c30028452e250140b6f21ethannicholas    SkScalar scaleFactor = 0.0f;
2308c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2318c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (SkStrokeRec::kStrokeAndFill_Style == fStyle) {
2328c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkASSERT(m.isSimilarity());
2338c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        scaleFactor = m.getMaxScale(); // x and y scale are the same
2348c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
2358c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        Ring outerStrokeAndAARing;
2368c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        this->createOuterRing(fInitialRing,
2378c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                              effectiveStrokeWidth / 2 + kAntialiasingRadius, 0.0,
2388c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                              &outerStrokeAndAARing);
2398c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2408c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        // discard all the triangles added between the originating ring and the new outer ring
2418c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        fIndices.rewind();
2428c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2438c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        outerStrokeAndAARing.init(*this);
2448c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2458c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        outerStrokeAndAARing.makeOriginalRing();
2468c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2478c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        // Add the outer stroke ring's normals to the originating ring's normals
2488c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        // so it can also act as an originating ring
2498c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        fNorms.setCount(fNorms.count() + outerStrokeAndAARing.numPts());
2508c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        for (int i = 0; i < outerStrokeAndAARing.numPts(); ++i) {
2518c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            SkASSERT(outerStrokeAndAARing.index(i) < fNorms.count());
2528c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            fNorms[outerStrokeAndAARing.index(i)] = outerStrokeAndAARing.norm(i);
2538c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
2548c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2558c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        // the bisectors are only needed for the computation of the outer ring
2568c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        fBisectors.rewind();
2578c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2588c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        Ring* insetAARing;
2598c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        this->createInsetRings(outerStrokeAndAARing,
2608c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                               0.0f, 0.0f, 2*kAntialiasingRadius, 1.0f,
2618c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                               &insetAARing);
2628c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2638c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkDEBUGCODE(this->validate();)
2648c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        return true;
2658c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    }
2668c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
2678c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (SkStrokeRec::kStroke_Style == fStyle) {
2688c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkASSERT(fStrokeWidth >= 0.0f);
2699d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        SkASSERT(m.isSimilarity());
270fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        scaleFactor = m.getMaxScale(); // x and y scale are the same
271fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
272bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        Ring outerStrokeRing;
2739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        this->createOuterRing(fInitialRing, effectiveStrokeWidth / 2 - kAntialiasingRadius,
274fea7763140ba74b78f2c30028452e250140b6f21ethannicholas                              coverage, &outerStrokeRing);
275bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        outerStrokeRing.init(*this);
276bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        Ring outerAARing;
277bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->createOuterRing(outerStrokeRing, kAntialiasingRadius * 2, 0.0f, &outerAARing);
278bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    } else {
279bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        Ring outerAARing;
280bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->createOuterRing(fInitialRing, kAntialiasingRadius, 0.0f, &outerAARing);
281bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
28284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
28384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // the bisectors are only needed for the computation of the outer ring
28484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fBisectors.rewind();
2858c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (SkStrokeRec::kStroke_Style == fStyle && fInitialRing.numPts() > 2) {
2868c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkASSERT(fStrokeWidth >= 0.0f);
287fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        SkScalar effectiveStrokeWidth = scaleFactor * fStrokeWidth;
288bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        Ring* insetStrokeRing;
289fea7763140ba74b78f2c30028452e250140b6f21ethannicholas        SkScalar strokeDepth = effectiveStrokeWidth / 2 - kAntialiasingRadius;
2909d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        if (this->createInsetRings(fInitialRing, 0.0f, coverage, strokeDepth, coverage,
2918c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                   &insetStrokeRing)) {
292bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            Ring* insetAARing;
2939d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary            this->createInsetRings(*insetStrokeRing, strokeDepth, coverage, strokeDepth +
2948c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                   kAntialiasingRadius * 2, 0.0f, &insetAARing);
29584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
296bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    } else {
297bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        Ring* insetAARing;
298bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->createInsetRings(fInitialRing, 0.0f, 0.5f, kAntialiasingRadius, 1.0f, &insetAARing);
29984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
30084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
301bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    SkDEBUGCODE(this->validate();)
30284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return true;
30384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
30484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
30584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsSkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const {
30684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(edgeIdx < fNorms.count());
30784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
30884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint v = p - fPts[edgeIdx];
30984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar depth = -fNorms[edgeIdx].dot(v);
31084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return depth;
31184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
31284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
31384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// Find a point that is 'desiredDepth' away from the 'edgeIdx'-th edge and lies
31484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// along the 'bisector' from the 'startIdx'-th point.
31584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsbool GrAAConvexTessellator::computePtAlongBisector(int startIdx,
31684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                                   const SkVector& bisector,
31784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                                   int edgeIdx,
31884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                                   SkScalar desiredDepth,
31984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                                   SkPoint* result) const {
32084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    const SkPoint& norm = fNorms[edgeIdx];
32184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
32284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // First find the point where the edge and the bisector intersect
32384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint newP;
324bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
32584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar t = perp_intersect(fPts[startIdx], bisector, fPts[edgeIdx], norm);
32684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (SkScalarNearlyEqual(t, 0.0f)) {
32784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        // the start point was one of the original ring points
328bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkASSERT(startIdx < fPts.count());
32984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        newP = fPts[startIdx];
330bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    } else if (t < 0.0f) {
33184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        newP = bisector;
33284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        newP.scale(t);
33384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        newP += fPts[startIdx];
33484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    } else {
33584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        return false;
33684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
33784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
33884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Then offset along the bisector from that point the correct distance
339bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    SkScalar dot = bisector.dot(norm);
340bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    t = -desiredDepth / dot;
34184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *result = bisector;
34284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    result->scale(t);
34384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    *result += newP;
34484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
34584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return true;
34684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
34784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
34884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsbool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& path) {
34984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(SkPath::kConvex_Convexity == path.getConvexity());
35084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
35184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Outer ring: 3*numPts
35284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Middle ring: numPts
35384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Presumptive inner ring: numPts
35484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->reservePts(5*path.countPoints());
35584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Outer ring: 12*numPts
35684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Middle ring: 0
35784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Presumptive inner ring: 6*numPts + 6
35884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fIndices.setReserve(18*path.countPoints() + 6);
35984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
36084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fNorms.setReserve(path.countPoints());
36184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
36284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // TODO: is there a faster way to extract the points from the path? Perhaps
36384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // get all the points via a new entry point, transform them all in bulk
36484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // and then walk them to find duplicates?
36584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPath::Iter iter(path, true);
36684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint pts[4];
36784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPath::Verb verb;
36897042bfd9f4a1ff825a92ac13965b80fd712d4f2Brian Salomon    while ((verb = iter.next(pts, true, true)) != SkPath::kDone_Verb) {
36984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        switch (verb) {
37084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            case SkPath::kLine_Verb:
371fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                this->lineTo(m, pts[1], kSharp_CurveState);
37284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                break;
37384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            case SkPath::kQuad_Verb:
3741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                this->quadTo(m, pts);
3751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                break;
37684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            case SkPath::kCubic_Verb:
3771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                this->cubicTo(m, pts);
3781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                break;
3791a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            case SkPath::kConic_Verb:
3801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas                this->conicTo(m, pts, iter.conicWeight());
38184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                break;
38284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            case SkPath::kMove_Verb:
38384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            case SkPath::kClose_Verb:
38484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            case SkPath::kDone_Verb:
38584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                break;
38684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
38784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
38884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
389bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (this->numPts() < 2) {
39084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        return false;
39184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
39284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
39384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // check if last point is a duplicate of the first point. If so, remove it.
39484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (duplicate_pt(fPts[this->numPts()-1], fPts[0])) {
39584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        this->popLastPt();
39684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fNorms.pop();
39784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
39884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
39984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(fPts.count() == fNorms.count()+1);
400bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (this->numPts() >= 3) {
401bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (abs_dist_from_line(fPts.top(), fNorms.top(), fPts[0]) < kClose) {
402bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            // The last point is on the line from the second to last to the first point.
403bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            this->popLastPt();
404bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            fNorms.pop();
405bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
40684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
407bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        *fNorms.push() = fPts[0] - fPts.top();
408bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top());
409bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkASSERT(len > 0.0f);
410bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkASSERT(fPts.count() == fNorms.count());
41184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
41284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
413bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (this->numPts() >= 3 && abs_dist_from_line(fPts[0], fNorms.top(), fPts[1]) < kClose) {
41484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        // The first point is on the line from the last to the second.
41584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        this->popFirstPtShuffle();
41684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fNorms.removeShuffle(0);
41784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fNorms[0] = fPts[1] - fPts[0];
41884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms[0]);
41984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkASSERT(len > 0.0f);
42084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[0].length()));
42184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
42284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
423bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (this->numPts() >= 3) {
424bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // Check the cross product of the final trio
425bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top());
426bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (cross > 0.0f) {
427bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            fSide = SkPoint::kRight_Side;
428bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        } else {
429bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            fSide = SkPoint::kLeft_Side;
430bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
4312436f191e6602953b32a51cf50f2d7a4e2af90fdethannicholas
432bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // Make all the normals face outwards rather than along the edge
433bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        for (int cur = 0; cur < fNorms.count(); ++cur) {
434bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            fNorms[cur].setOrthog(fNorms[cur], fSide);
435bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
436bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
437bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
438bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->computeBisectors();
439bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    } else if (this->numPts() == 2) {
4409d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        // We've got two points, so we're degenerate.
4418c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (fStyle == SkStrokeRec::kFill_Style) {
442bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            // it's a fill, so we don't need to worry about degenerate paths
443bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            return false;
444bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
445bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // For stroking, we still need to process the degenerate path, so fix it up
44684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fSide = SkPoint::kLeft_Side;
44784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
448bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // Make all the normals face outwards rather than along the edge
449bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        for (int cur = 0; cur < fNorms.count(); ++cur) {
450bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            fNorms[cur].setOrthog(fNorms[cur], fSide);
451bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
452bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
45384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
454bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        fNorms.push(SkPoint::Make(-fNorms[0].fX, -fNorms[0].fY));
455bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // we won't actually use the bisectors, so just push zeroes
456bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        fBisectors.push(SkPoint::Make(0.0, 0.0));
457bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        fBisectors.push(SkPoint::Make(0.0, 0.0));
458bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    } else {
459bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
460bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
4619730f4a663534009d216c2f6d834bd534dd44a3dreed
46284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fCandidateVerts.setReserve(this->numPts());
46384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fInitialRing.setReserve(this->numPts());
46484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < this->numPts(); ++i) {
46584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fInitialRing.addIdx(i, i);
46684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
46784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fInitialRing.init(fNorms, fBisectors);
46884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
46984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
47084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return true;
47184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
47284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
47384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsGrAAConvexTessellator::Ring* GrAAConvexTessellator::getNextRing(Ring* lastRing) {
47484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#if GR_AA_CONVEX_TESSELLATOR_VIZ
475385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    Ring* ring = *fRings.push() = new Ring;
47684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    ring->setReserve(fInitialRing.numPts());
47784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    ring->rewind();
47884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return ring;
47984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#else
48084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Flip flop back and forth between fRings[0] & fRings[1]
48184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int nextRing = (lastRing == &fRings[0]) ? 1 : 0;
48284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fRings[nextRing].setReserve(fInitialRing.numPts());
48384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fRings[nextRing].rewind();
48484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return &fRings[nextRing];
48584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#endif
48684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
48784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
48884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::fanRing(const Ring& ring) {
48984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // fan out from point 0
490bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    int startIdx = ring.index(0);
491bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    for (int cur = ring.numPts() - 2; cur >= 0; --cur) {
492bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->addTri(startIdx, ring.index(cur), ring.index(cur + 1));
49384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
49484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
49584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
4969d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryvoid GrAAConvexTessellator::createOuterRing(const Ring& previousRing, SkScalar outset,
497bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                            SkScalar coverage, Ring* nextRing) {
498bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    const int numPts = previousRing.numPts();
499bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (numPts == 0) {
500bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return;
501bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
5021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
5039730f4a663534009d216c2f6d834bd534dd44a3dreed    int prev = numPts - 1;
504bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    int lastPerpIdx = -1, firstPerpIdx = -1;
5059730f4a663534009d216c2f6d834bd534dd44a3dreed
5068be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    const SkScalar outsetSq = outset * outset;
5078be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    SkScalar miterLimitSq = outset * fMiterLimit;
5088be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    miterLimitSq = miterLimitSq * miterLimitSq;
509bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    for (int cur = 0; cur < numPts; ++cur) {
510bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        int originalIdx = previousRing.index(cur);
5119d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        // For each vertex of the original polygon we add at least two points to the
512bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // outset polygon - one extending perpendicular to each impinging edge. Connecting these
5139d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        // two points yields a bevel join. We need one additional point for a mitered join, and
514bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // a round join requires one or more points depending upon curvature.
515bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
516bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // The perpendicular point for the last edge
517bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkPoint normal1 = previousRing.norm(prev);
518bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkPoint perp1 = normal1;
519bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        perp1.scale(outset);
520bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        perp1 += this->point(originalIdx);
521bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
522bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // The perpendicular point for the next edge.
523bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkPoint normal2 = previousRing.norm(cur);
524bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkPoint perp2 = normal2;
525bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        perp2.scale(outset);
526bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        perp2 += fPts[originalIdx];
527bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
528fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas        CurveState curve = fCurveState[originalIdx];
529bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
530bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // We know it isn't a duplicate of the prior point (since it and this
531bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // one are just perpendicular offsets from the non-merged polygon points)
532fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas        int perp1Idx = this->addPt(perp1, -outset, coverage, false, curve);
533bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        nextRing->addIdx(perp1Idx, originalIdx);
534bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
535bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        int perp2Idx;
536bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // For very shallow angles all the corner points could fuse.
537bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (duplicate_pt(perp2, this->point(perp1Idx))) {
538bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            perp2Idx = perp1Idx;
539bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        } else {
540fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas            perp2Idx = this->addPt(perp2, -outset, coverage, false, curve);
54184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
5421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
543bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (perp2Idx != perp1Idx) {
544fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas            if (curve == kCurve_CurveState) {
545bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                // bevel or round depending upon curvature
546bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                SkScalar dotProd = normal1.dot(normal2);
547bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                if (dotProd < kRoundCapThreshold) {
548bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    // Currently we "round" by creating a single extra point, which produces
549bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    // good results for common cases. For thick strokes with high curvature, we will
550bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    // need to add more points; for the time being we simply fall back to software
551bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    // rendering for thick strokes.
552bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    SkPoint miter = previousRing.bisector(cur);
553bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    miter.setLength(-outset);
554bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    miter += fPts[originalIdx];
555bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
556bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    // For very shallow angles all the corner points could fuse
557bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    if (!duplicate_pt(miter, this->point(perp1Idx))) {
558bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        int miterIdx;
559fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                        miterIdx = this->addPt(miter, -outset, coverage, false, kSharp_CurveState);
560bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        nextRing->addIdx(miterIdx, originalIdx);
561bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        // The two triangles for the corner
562bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        this->addTri(originalIdx, perp1Idx, miterIdx);
563bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        this->addTri(originalIdx, miterIdx, perp2Idx);
564bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    }
565bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                } else {
566bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    this->addTri(originalIdx, perp1Idx, perp2Idx);
567bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                }
5689730f4a663534009d216c2f6d834bd534dd44a3dreed            } else {
569bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                switch (fJoin) {
570bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    case SkPaint::Join::kMiter_Join: {
571bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        // The bisector outset point
572bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        SkPoint miter = previousRing.bisector(cur);
573bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        SkScalar dotProd = normal1.dot(normal2);
574bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        SkScalar sinHalfAngleSq = SkScalarHalf(SK_Scalar1 + dotProd);
575bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        SkScalar lengthSq = outsetSq / sinHalfAngleSq;
576bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        if (lengthSq > miterLimitSq) {
577bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            // just bevel it
578bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            this->addTri(originalIdx, perp1Idx, perp2Idx);
579bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            break;
580bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        }
581bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        miter.setLength(-SkScalarSqrt(lengthSq));
582bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        miter += fPts[originalIdx];
583bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
584bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        // For very shallow angles all the corner points could fuse
585bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        if (!duplicate_pt(miter, this->point(perp1Idx))) {
586bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            int miterIdx;
587fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                            miterIdx = this->addPt(miter, -outset, coverage, false,
588fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                                                   kSharp_CurveState);
589bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            nextRing->addIdx(miterIdx, originalIdx);
590bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            // The two triangles for the corner
591bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            this->addTri(originalIdx, perp1Idx, miterIdx);
592bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                            this->addTri(originalIdx, miterIdx, perp2Idx);
593bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        }
594bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        break;
595bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    }
596bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    case SkPaint::Join::kBevel_Join:
597bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        this->addTri(originalIdx, perp1Idx, perp2Idx);
598bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        break;
599bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                    default:
6009d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                        // kRound_Join is unsupported for now. GrAALinearizingConvexPathRenderer is
601bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        // only willing to draw mitered or beveled, so we should never get here.
602bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                        SkASSERT(false);
603bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                }
6049730f4a663534009d216c2f6d834bd534dd44a3dreed            }
6051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
606bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            nextRing->addIdx(perp2Idx, originalIdx);
607bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        }
6082436f191e6602953b32a51cf50f2d7a4e2af90fdethannicholas
609bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (0 == cur) {
610bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            // Store the index of the first perpendicular point to finish up
611bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            firstPerpIdx = perp1Idx;
612bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            SkASSERT(-1 == lastPerpIdx);
613bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        } else {
614bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            // The triangles for the previous edge
615bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            int prevIdx = previousRing.index(prev);
616bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            this->addTri(prevIdx, perp1Idx, originalIdx);
617bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            this->addTri(prevIdx, lastPerpIdx, perp1Idx);
6189730f4a663534009d216c2f6d834bd534dd44a3dreed        }
619bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
620bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // Track the last perpendicular outset point so we can construct the
621bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        // trailing edge triangles.
622bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        lastPerpIdx = perp2Idx;
623bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        prev = cur;
62484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
62584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
62684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // pick up the final edge rect
627bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    int lastIdx = previousRing.index(numPts - 1);
628bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    this->addTri(lastIdx, firstPerpIdx, previousRing.index(0));
629bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    this->addTri(lastIdx, lastPerpIdx, firstPerpIdx);
63084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
63184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->validate();
63284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
63384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
634bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// Something went wrong in the creation of the next ring. If we're filling the shape, just go ahead
635bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita// and fan it.
63684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::terminate(const Ring& ring) {
6378c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (fStyle != SkStrokeRec::kStroke_Style) {
638bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        this->fanRing(ring);
63984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
640bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita}
64184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
6429d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanarystatic SkScalar compute_coverage(SkScalar depth, SkScalar initialDepth, SkScalar initialCoverage,
643bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                SkScalar targetDepth, SkScalar targetCoverage) {
644bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (SkScalarNearlyEqual(initialDepth, targetDepth)) {
645bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return targetCoverage;
646bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
6479d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    SkScalar result = (depth - initialDepth) / (targetDepth - initialDepth) *
648bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            (targetCoverage - initialCoverage) + initialCoverage;
649bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    return SkScalarClampMax(result, 1.0f);
65084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
65184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
65284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// return true when processing is complete
6539d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanarybool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing,
6549d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                                            SkScalar initialDepth, SkScalar initialCoverage,
6559d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                                            SkScalar targetDepth, SkScalar targetCoverage,
656bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                            bool forceNew) {
65784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    bool done = false;
65884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
65984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fCandidateVerts.rewind();
66084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
66184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Loop through all the points in the ring and find the intersection with the smallest depth
66284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar minDist = SK_ScalarMax, minT = 0.0f;
66384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int minEdgeIdx = -1;
66484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
66584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int cur = 0; cur < lastRing.numPts(); ++cur) {
66684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        int next = (cur + 1) % lastRing.numPts();
6678c170971f182d47bc9af71fc88a607740d03dfd5robertphillips
6688c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        SkScalar t;
6698c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        bool result = intersect(this->point(lastRing.index(cur)),  lastRing.bisector(cur),
6708c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                this->point(lastRing.index(next)), lastRing.bisector(next),
6718c170971f182d47bc9af71fc88a607740d03dfd5robertphillips                                &t);
6728c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        if (!result) {
6738c170971f182d47bc9af71fc88a607740d03dfd5robertphillips            continue;
6748c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        }
67584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkScalar dist = -t * lastRing.norm(cur).dot(lastRing.bisector(cur));
67684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
67784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        if (minDist > dist) {
67884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            minDist = dist;
67984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            minT = t;
68084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            minEdgeIdx = cur;
68184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
68284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
68384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
684bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (minEdgeIdx == -1) {
685bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return false;
686bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
68784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint newPt = lastRing.bisector(minEdgeIdx);
68884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    newPt.scale(minT);
68984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    newPt += this->point(lastRing.index(minEdgeIdx));
69084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
69184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar depth = this->computeDepthFromEdge(lastRing.origEdgeID(minEdgeIdx), newPt);
692bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (depth >= targetDepth) {
69384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        // None of the bisectors intersect before reaching the desired depth.
69484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        // Just step them all to the desired depth
695bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        depth = targetDepth;
69684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        done = true;
69784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
69884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
69984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // 'dst' stores where each point in the last ring maps to/transforms into
70084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // in the next ring.
70184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkTDArray<int> dst;
70284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    dst.setCount(lastRing.numPts());
70384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
70484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Create the first point (who compares with no one)
70584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (!this->computePtAlongBisector(lastRing.index(0),
70684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                      lastRing.bisector(0),
70784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                      lastRing.origEdgeID(0),
70884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                      depth, &newPt)) {
70984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        this->terminate(lastRing);
71084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        return true;
71184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
71284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    dst[0] = fCandidateVerts.addNewPt(newPt,
71384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                      lastRing.index(0), lastRing.origEdgeID(0),
71484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                      !this->movable(lastRing.index(0)));
71584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
71684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Handle the middle points (who only compare with the prior point)
71784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int cur = 1; cur < lastRing.numPts()-1; ++cur) {
71884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        if (!this->computePtAlongBisector(lastRing.index(cur),
71984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                          lastRing.bisector(cur),
72084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                          lastRing.origEdgeID(cur),
72184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                          depth, &newPt)) {
72284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            this->terminate(lastRing);
72384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            return true;
72484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
72584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        if (!duplicate_pt(newPt, fCandidateVerts.lastPoint())) {
72684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            dst[cur] = fCandidateVerts.addNewPt(newPt,
72784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                                lastRing.index(cur), lastRing.origEdgeID(cur),
72884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                                !this->movable(lastRing.index(cur)));
72984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        } else {
73084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            dst[cur] = fCandidateVerts.fuseWithPrior(lastRing.origEdgeID(cur));
73184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
73284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
73384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
73484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Check on the last point (handling the wrap around)
73584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int cur = lastRing.numPts()-1;
73684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if  (!this->computePtAlongBisector(lastRing.index(cur),
73784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                       lastRing.bisector(cur),
73884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                       lastRing.origEdgeID(cur),
73984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                       depth, &newPt)) {
74084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        this->terminate(lastRing);
74184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        return true;
74284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
74384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    bool dupPrev = duplicate_pt(newPt, fCandidateVerts.lastPoint());
74484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    bool dupNext = duplicate_pt(newPt, fCandidateVerts.firstPoint());
74584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
74684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (!dupPrev && !dupNext) {
74784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        dst[cur] = fCandidateVerts.addNewPt(newPt,
74884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                            lastRing.index(cur), lastRing.origEdgeID(cur),
74984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                            !this->movable(lastRing.index(cur)));
75084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    } else if (dupPrev && !dupNext) {
75184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        dst[cur] = fCandidateVerts.fuseWithPrior(lastRing.origEdgeID(cur));
75284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    } else if (!dupPrev && dupNext) {
75384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        dst[cur] = fCandidateVerts.fuseWithNext();
75484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    } else {
75584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        bool dupPrevVsNext = duplicate_pt(fCandidateVerts.firstPoint(), fCandidateVerts.lastPoint());
75684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
75784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        if (!dupPrevVsNext) {
75884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            dst[cur] = fCandidateVerts.fuseWithPrior(lastRing.origEdgeID(cur));
75984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        } else {
7600dacc6708d5db4fbe755d7b1d0716b51fe703058ethannicholas            const int fused = fCandidateVerts.fuseWithBoth();
7610dacc6708d5db4fbe755d7b1d0716b51fe703058ethannicholas            dst[cur] = fused;
7620dacc6708d5db4fbe755d7b1d0716b51fe703058ethannicholas            const int targetIdx = dst[cur - 1];
7630dacc6708d5db4fbe755d7b1d0716b51fe703058ethannicholas            for (int i = cur - 1; i >= 0 && dst[i] == targetIdx; i--) {
7640dacc6708d5db4fbe755d7b1d0716b51fe703058ethannicholas                dst[i] = fused;
7650dacc6708d5db4fbe755d7b1d0716b51fe703058ethannicholas            }
76684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
76784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
76884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
76984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // Fold the new ring's points into the global pool
77084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < fCandidateVerts.numPts(); ++i) {
77184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        int newIdx;
772bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (fCandidateVerts.needsToBeNew(i) || forceNew) {
7739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary            // if the originating index is still valid then this point wasn't
77484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            // fused (and is thus movable)
7759d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary            SkScalar coverage = compute_coverage(depth, initialDepth, initialCoverage,
776bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                                                 targetDepth, targetCoverage);
777bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            newIdx = this->addPt(fCandidateVerts.point(i), depth, coverage,
778fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas                                 fCandidateVerts.originatingIdx(i) != -1, kSharp_CurveState);
77984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        } else {
78084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            SkASSERT(fCandidateVerts.originatingIdx(i) != -1);
781bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita            this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.point(i), depth,
782bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita                           targetCoverage);
78384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            newIdx = fCandidateVerts.originatingIdx(i);
78484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
78584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
78684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        nextRing->addIdx(newIdx, fCandidateVerts.origEdge(i));
78784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
78884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
78984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // 'dst' currently has indices into the ring. Remap these to be indices
79084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    // into the global pool since the triangulation operates in that space.
79184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < dst.count(); ++i) {
79284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        dst[i] = nextRing->index(dst[i]);
79384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
79484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
79544c3128bd892d32f797810d93ef1ed392e0b902drobertphillips    for (int i = 0; i < lastRing.numPts(); ++i) {
79644c3128bd892d32f797810d93ef1ed392e0b902drobertphillips        int next = (i + 1) % lastRing.numPts();
79784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
79844c3128bd892d32f797810d93ef1ed392e0b902drobertphillips        this->addTri(lastRing.index(i), lastRing.index(next), dst[next]);
79944c3128bd892d32f797810d93ef1ed392e0b902drobertphillips        this->addTri(lastRing.index(i), dst[next], dst[i]);
80084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
80184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
8028c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    if (done && fStyle != SkStrokeRec::kStroke_Style) {
8038c170971f182d47bc9af71fc88a607740d03dfd5robertphillips        // fill or stroke-and-fill
80484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        this->fanRing(*nextRing);
80584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
80684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
80784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (nextRing->numPts() < 3) {
80884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        done = true;
80984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
81084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    return done;
81184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
81284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
81384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::validate() const {
81484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(fPts.count() == fMovable.count());
8151d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    SkASSERT(fPts.count() == fCoverages.count());
8161d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    SkASSERT(fPts.count() == fCurveState.count());
81784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(0 == (fIndices.count() % 3));
8181d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    SkASSERT(!fBisectors.count() || fBisectors.count() == fNorms.count());
81984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
82084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
82184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips//////////////////////////////////////////////////////////////////////////////
82284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::Ring::init(const GrAAConvexTessellator& tess) {
82384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    this->computeNormals(tess);
824364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips    this->computeBisectors(tess);
82584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
82684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
82784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms,
82884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                                       const SkTDArray<SkVector>& bisectors) {
82984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < fPts.count(); ++i) {
83084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fPts[i].fNorm = norms[i];
83184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fPts[i].fBisector = bisectors[i];
83284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
83384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
83484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
83584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// Compute the outward facing normal at each vertex.
83684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::Ring::computeNormals(const GrAAConvexTessellator& tess) {
83784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int cur = 0; cur < fPts.count(); ++cur) {
83884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        int next = (cur + 1) % fPts.count();
83984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
84084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fPts[cur].fNorm = tess.point(fPts[next].fIndex) - tess.point(fPts[cur].fIndex);
841bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        SkPoint::Normalize(&fPts[cur].fNorm);
84284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fPts[cur].fNorm.setOrthog(fPts[cur].fNorm, tess.side());
84384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
84484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
84584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
846364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillipsvoid GrAAConvexTessellator::Ring::computeBisectors(const GrAAConvexTessellator& tess) {
84784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int prev = fPts.count() - 1;
84884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int cur = 0; cur < fPts.count(); prev = cur, ++cur) {
84984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fPts[cur].fBisector = fPts[cur].fNorm + fPts[prev].fNorm;
850364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips        if (!fPts[cur].fBisector.normalize()) {
851364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            SkASSERT(SkPoint::kLeft_Side == tess.side() || SkPoint::kRight_Side == tess.side());
852364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            fPts[cur].fBisector.setOrthog(fPts[cur].fNorm, (SkPoint::Side)-tess.side());
853364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            SkVector other;
854364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            other.setOrthog(fPts[prev].fNorm, tess.side());
855364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            fPts[cur].fBisector += other;
856364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            SkAssertResult(fPts[cur].fBisector.normalize());
857364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips        } else {
858364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips            fPts[cur].fBisector.negate();      // make the bisector face in
859364ad00446923d1cbc963c7358cd9b01efc53d3erobertphillips        }
860bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    }
86184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
86284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
86384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips//////////////////////////////////////////////////////////////////////////////
86484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#ifdef SK_DEBUG
86584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips// Is this ring convex?
86684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsbool GrAAConvexTessellator::Ring::isConvex(const GrAAConvexTessellator& tess) const {
86784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (fPts.count() < 3) {
868bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        return true;
86984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
87084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
87184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint prev = tess.point(fPts[0].fIndex) - tess.point(fPts.top().fIndex);
87284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPoint cur  = tess.point(fPts[1].fIndex) - tess.point(fPts[0].fIndex);
87384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar minDot = prev.fX * cur.fY - prev.fY * cur.fX;
87484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkScalar maxDot = minDot;
87584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
87684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    prev = cur;
87784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 1; i < fPts.count(); ++i) {
87884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        int next = (i + 1) % fPts.count();
87984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
88084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        cur  = tess.point(fPts[next].fIndex) - tess.point(fPts[i].fIndex);
88184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkScalar dot = prev.fX * cur.fY - prev.fY * cur.fX;
88284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
88384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        minDot = SkMinScalar(minDot, dot);
88484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        maxDot = SkMaxScalar(maxDot, dot);
88584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
88684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        prev = cur;
88784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
88884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
889bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (SkScalarNearlyEqual(maxDot, 0.0f, 0.005f)) {
890bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        maxDot = 0;
89184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
892bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    if (SkScalarNearlyEqual(minDot, 0.0f, 0.005f)) {
893bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        minDot = 0;
89484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
895bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    return (maxDot >= 0.0f) == (minDot >= 0.0f);
89684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
89784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
89884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#endif
89984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
9001d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillipsvoid GrAAConvexTessellator::lineTo(const SkPoint& p, CurveState curve) {
9011a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) {
9021a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        return;
9031a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
9041a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
9051a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1);
9061d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    if (this->numPts() >= 2 && abs_dist_from_line(fPts.top(), fNorms.top(), p) < kClose) {
9071a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        // The old last point is on the line from the second to last to the new point
9081a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        this->popLastPt();
9091a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        fNorms.pop();
9101bcbc8f8c0747691496d779055675bc47ca65c86ethannicholas        // double-check that the new last point is not a duplicate of the new point. In an ideal
9111bcbc8f8c0747691496d779055675bc47ca65c86ethannicholas        // world this wouldn't be necessary (since it's only possible for non-convex paths), but
9121d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips        // floating point precision issues mean it can actually happen on paths that were
9131d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips        // determined to be convex.
9141bcbc8f8c0747691496d779055675bc47ca65c86ethannicholas        if (duplicate_pt(p, this->lastPoint())) {
9151bcbc8f8c0747691496d779055675bc47ca65c86ethannicholas            return;
9161bcbc8f8c0747691496d779055675bc47ca65c86ethannicholas        }
9171a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
9188c170971f182d47bc9af71fc88a607740d03dfd5robertphillips    SkScalar initialRingCoverage = (SkStrokeRec::kFill_Style == fStyle) ? 0.5f : 1.0f;
919fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas    this->addPt(p, 0.0f, initialRingCoverage, false, curve);
9201a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    if (this->numPts() > 1) {
9211a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        *fNorms.push() = fPts.top() - fPts[fPts.count()-2];
9221a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top());
9231a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(len > 0.0f);
9241a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length()));
9251a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
9261a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
9271a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
928fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholasvoid GrAAConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, CurveState curve) {
929bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    m.mapPoints(&p, 1);
930fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas    this->lineTo(p, curve);
931bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita}
932bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
9331d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillipsvoid GrAAConvexTessellator::quadTo(const SkPoint pts[3]) {
9341a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
9351a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    fPointBuffer.setReserve(maxCount);
9361a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkPoint* target = fPointBuffer.begin();
9379d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
9381d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips                                                     kQuadTolerance, &target, maxCount);
9391a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    fPointBuffer.setCount(count);
940fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas    for (int i = 0; i < count - 1; i++) {
9411d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips        this->lineTo(fPointBuffer[i], kCurve_CurveState);
9421a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
9431d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    this->lineTo(fPointBuffer[count - 1], kIndeterminate_CurveState);
9441a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
9451a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
946bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitavoid GrAAConvexTessellator::quadTo(const SkMatrix& m, SkPoint pts[3]) {
9471d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    m.mapPoints(pts, 3);
9481d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    this->quadTo(pts);
949bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita}
950bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita
9511a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholasvoid GrAAConvexTessellator::cubicTo(const SkMatrix& m, SkPoint pts[4]) {
952bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    m.mapPoints(pts, 4);
9531a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance);
9541a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    fPointBuffer.setReserve(maxCount);
9551a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkPoint* target = fPointBuffer.begin();
9569d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
9571a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas            kCubicTolerance, &target, maxCount);
9581a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    fPointBuffer.setCount(count);
959fab4a9b9882bfd1c2d8c3fd5eeaf691caeba0f31ethannicholas    for (int i = 0; i < count - 1; i++) {
9601d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips        this->lineTo(fPointBuffer[i], kCurve_CurveState);
9611a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
9621d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips    this->lineTo(fPointBuffer[count - 1], kIndeterminate_CurveState);
9631a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
9641a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
9651a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas// include down here to avoid compilation errors caused by "-" overload in SkGeometry.h
9661a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas#include "SkGeometry.h"
9671a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
968bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalitavoid GrAAConvexTessellator::conicTo(const SkMatrix& m, SkPoint pts[3], SkScalar w) {
969bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita    m.mapPoints(pts, 3);
9701a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkAutoConicToQuads quadder;
9711a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance);
9721a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    SkPoint lastPoint = *(quads++);
9731a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    int count = quadder.countQuads();
9741a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    for (int i = 0; i < count; ++i) {
9751a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        SkPoint quadPts[3];
9761a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        quadPts[0] = lastPoint;
9771a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        quadPts[1] = quads[0];
9781a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        quadPts[2] = i == count - 1 ? pts[2] : quads[1];
9791d08998e4fb81755978f3d1c11744a6c77ddab2eRobert Phillips        this->quadTo(quadPts);
9801a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        lastPoint = quadPts[2];
9811a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas        quads += 2;
9821a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas    }
9831a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas}
9841a1b3ac0d4feecb0fefa8a07c7abf3471c96f545ethannicholas
98584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips//////////////////////////////////////////////////////////////////////////////
98684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#if GR_AA_CONVEX_TESSELLATOR_VIZ
98784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic const SkScalar kPointRadius = 0.02f;
98884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic const SkScalar kArrowStrokeWidth = 0.0f;
98984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic const SkScalar kArrowLength = 0.2f;
99084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic const SkScalar kEdgeTextSize = 0.1f;
99184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic const SkScalar kPointTextSize = 0.02f;
99284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
99384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) {
99484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPaint paint;
99584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkASSERT(paramValue <= 1.0f);
99684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    int gs = int(255*paramValue);
99784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    paint.setARGB(255, gs, gs, gs);
99884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
99984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    canvas->drawCircle(p.fX, p.fY, kPointRadius, paint);
100084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
100184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    if (stroke) {
100284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkPaint stroke;
100384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        stroke.setColor(SK_ColorYELLOW);
100484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        stroke.setStyle(SkPaint::kStroke_Style);
100584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        stroke.setStrokeWidth(kPointRadius/3.0f);
10069d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        canvas->drawCircle(p.fX, p.fY, kPointRadius, stroke);
100784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
100884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
100984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
101084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, SkColor color) {
101184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPaint p;
101284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    p.setColor(color);
101384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
101484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, p);
101584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
101684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
101784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsstatic void draw_arrow(SkCanvas*canvas, const SkPoint& p, const SkPoint &n,
101884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                       SkScalar len, SkColor color) {
101984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPaint paint;
102084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    paint.setColor(color);
102184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    paint.setStrokeWidth(kArrowStrokeWidth);
102284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    paint.setStyle(SkPaint::kStroke_Style);
102384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
102484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    canvas->drawLine(p.fX, p.fY,
102584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                     p.fX + len * n.fX, p.fY + len * n.fY,
102684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                     paint);
102784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
102884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
102984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const {
103084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    SkPaint paint;
103184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    paint.setTextSize(kEdgeTextSize);
103284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
103384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int cur = 0; cur < fPts.count(); ++cur) {
103484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        int next = (cur + 1) % fPts.count();
103584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
103684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        draw_line(canvas,
103784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  tess.point(fPts[cur].fIndex),
103884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  tess.point(fPts[next].fIndex),
103984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  SK_ColorGREEN);
104084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
104184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkPoint mid = tess.point(fPts[cur].fIndex) + tess.point(fPts[next].fIndex);
104284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        mid.scale(0.5f);
104384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
104484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        if (fPts.count()) {
104584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            draw_arrow(canvas, mid, fPts[cur].fNorm, kArrowLength, SK_ColorRED);
104684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            mid.fX += (kArrowLength/2) * fPts[cur].fNorm.fX;
104784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            mid.fY += (kArrowLength/2) * fPts[cur].fNorm.fY;
104884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
104984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
105084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkString num;
105184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        num.printf("%d", this->origEdgeID(cur));
105284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        canvas->drawText(num.c_str(), num.size(), mid.fX, mid.fY, paint);
105384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
105484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        if (fPts.count()) {
105584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector,
105684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                       kArrowLength, SK_ColorBLUE);
105784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
10589d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    }
105984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
106084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
106184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillipsvoid GrAAConvexTessellator::draw(SkCanvas* canvas) const {
106284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < fIndices.count(); i += 3) {
106384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkASSERT(fIndices[i] < this->numPts()) ;
106484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkASSERT(fIndices[i+1] < this->numPts()) ;
106584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkASSERT(fIndices[i+2] < this->numPts()) ;
106684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
106784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        draw_line(canvas,
106884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  this->point(this->fIndices[i]), this->point(this->fIndices[i+1]),
106984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  SK_ColorBLACK);
107084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        draw_line(canvas,
107184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  this->point(this->fIndices[i+1]), this->point(this->fIndices[i+2]),
107284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  SK_ColorBLACK);
107384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        draw_line(canvas,
107484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  this->point(this->fIndices[i+2]), this->point(this->fIndices[i]),
107584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                  SK_ColorBLACK);
107684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
107784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
107884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    fInitialRing.draw(canvas, *this);
107984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < fRings.count(); ++i) {
108084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        fRings[i]->draw(canvas, *this);
108184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
108284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
108384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    for (int i = 0; i < this->numPts(); ++i) {
108484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        draw_point(canvas,
10859d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                   this->point(i), 0.5f + (this->depth(i)/(2 * kAntialiasingRadius)),
108684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                   !this->movable(i));
108784b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
108884b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkPaint paint;
108984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        paint.setTextSize(kPointTextSize);
109084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        paint.setTextAlign(SkPaint::kCenter_Align);
1091bd5d7e75c1ef08816bfd8eed52150cd716e15d5bfmalita        if (this->depth(i) <= -kAntialiasingRadius) {
109284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips            paint.setColor(SK_ColorWHITE);
109384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        }
109484b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
109584b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        SkString num;
109684b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips        num.printf("%d", i);
10979d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        canvas->drawText(num.c_str(), num.size(),
10989d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                         this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f),
109984b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips                         paint);
110084b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips    }
110184b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips}
110284b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips
110384b008873b5bdf35eba9185038fb3b5580a8b9a8robertphillips#endif
1104