convert pathops to use SkSTArray where possible.
authorcaryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 17 Jun 2013 14:10:36 +0000 (14:10 +0000)
committercaryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 17 Jun 2013 14:10:36 +0000 (14:10 +0000)
Replace SkTDArray with SkTArray and use SkSTArray when
the probable array size is known.

In a couple of places (spans, chases) the arrays are
constructed using insert() so SkTArrays can't be used for
now.

Also, add an optimization to cubic subdivide if either end
is zero or one.

BUG=

Review URL: https://codereview.chromium.org/16951017

git-svn-id: http://skia.googlecode.com/svn/trunk@9635 2bbb7eff-a529-9590-31e7-b0007b416f81

24 files changed:
src/pathops/SkAddIntersections.cpp
src/pathops/SkAddIntersections.h
src/pathops/SkDCubicIntersection.cpp
src/pathops/SkDCubicToQuads.cpp
src/pathops/SkDQuadIntersection.cpp
src/pathops/SkOpAngle.h
src/pathops/SkOpContour.cpp
src/pathops/SkOpContour.h
src/pathops/SkOpEdgeBuilder.cpp
src/pathops/SkOpEdgeBuilder.h
src/pathops/SkOpSegment.cpp
src/pathops/SkOpSegment.h
src/pathops/SkPathOpsCommon.cpp
src/pathops/SkPathOpsCommon.h
src/pathops/SkPathOpsCubic.cpp
src/pathops/SkPathOpsCubic.h
src/pathops/SkPathOpsOp.cpp
src/pathops/SkPathOpsSimplify.cpp
src/pathops/SkReduceOrder.cpp
src/pathops/SkReduceOrder.h
tests/PathOpsCubicIntersectionTest.cpp
tests/PathOpsCubicToQuadsTest.cpp
tests/PathOpsTestCommon.cpp
tests/PathOpsTestCommon.h

index 1884d4e..0d65446 100644 (file)
@@ -413,7 +413,7 @@ void AddSelfIntersectTs(SkOpContour* test) {
 
 // resolve any coincident pairs found while intersecting, and
 // see if coincidence is formed by clipping non-concident segments
-void CoincidenceCheck(SkTDArray<SkOpContour*>* contourList, int total) {
+void CoincidenceCheck(SkTArray<SkOpContour*, true>* contourList, int total) {
     int contourCount = (*contourList).count();
     for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
         SkOpContour* contour = (*contourList)[cIndex];
index b5727a4..94ea436 100644 (file)
@@ -9,10 +9,10 @@
 
 #include "SkIntersectionHelper.h"
 #include "SkIntersections.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 
 bool AddIntersectTs(SkOpContour* test, SkOpContour* next);
 void AddSelfIntersectTs(SkOpContour* test);
-void CoincidenceCheck(SkTDArray<SkOpContour*>* contourList, int total);
+void CoincidenceCheck(SkTArray<SkOpContour*, true>* contourList, int total);
 
 #endif
index 5106bbb..511879c 100644 (file)
@@ -12,7 +12,6 @@
 #include "SkPathOpsQuad.h"
 #include "SkPathOpsRect.h"
 #include "SkReduceOrder.h"
-#include "SkTDArray.h"
 #include "SkTSort.h"
 
 #if ONE_OFF_DEBUG
@@ -23,6 +22,8 @@ static const double tLimits2[2][2] = {{-0.865211397, -0.865215212}, {-0.86520769
 #define DEBUG_QUAD_PART 0
 #define SWAP_TOP_DEBUG 0
 
+static const int kCubicToQuadSubdivisionDepth = 8; // slots reserved for cubic to quads subdivision
+
 static int quadPart(const SkDCubic& cubic, double tStart, double tEnd, SkReduceOrder* reducer) {
     SkDCubic part = cubic.subDivide(tStart, tEnd);
     SkDQuad quad = part.toQuad();
@@ -74,10 +75,10 @@ static void intersect(const SkDCubic& cubic1, double t1s, double t1e, const SkDC
     i.upDepth();
     SkDCubic c1 = cubic1.subDivide(t1s, t1e);
     SkDCubic c2 = cubic2.subDivide(t2s, t2e);
-    SkTDArray<double> ts1;
+    SkSTArray<kCubicToQuadSubdivisionDepth, double, true> ts1;
     // OPTIMIZE: if c1 == c2, call once (happens when detecting self-intersection)
     c1.toQuadraticTs(c1.calcPrecision() * precisionScale, &ts1);
-    SkTDArray<double> ts2;
+    SkSTArray<kCubicToQuadSubdivisionDepth, double, true> ts2;
     c2.toQuadraticTs(c2.calcPrecision() * precisionScale, &ts2);
     double t1Start = t1s;
     int ts1Count = ts1.count();
@@ -264,10 +265,12 @@ static void intersectEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cub
     int t1Index = start ? 0 : 3;
     // don't bother if the two cubics are connnected
 #if 1
-    SkTDArray<double> tVals;  // OPTIMIZE: replace with hard-sized array
+    static const int kPointsInCubic = 4; // FIXME: move to DCubic, replace '4' with this
+    static const int kMaxLineCubicIntersections = 3;
+    SkSTArray<(kMaxLineCubicIntersections - 1) * kMaxLineCubicIntersections, double, true> tVals;
     line[0] = cubic1[t1Index];
     // this variant looks for intersections with the end point and lines parallel to other points
-    for (int index = 0; index < 4; ++index) {
+    for (int index = 0; index < kPointsInCubic; ++index) {
         if (index == t1Index) {
             continue;
         }
@@ -296,7 +299,7 @@ static void intersectEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cub
                     i.insert(start ? 0 : 1, foundT, line[0]);
                 }
             } else {
-                *tVals.append() = foundT;
+                tVals.push_back(foundT);
             }
         }
     }
index b950535..571f1d9 100644 (file)
@@ -49,7 +49,7 @@ http://www.caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
 #include "SkPathOpsLine.h"
 #include "SkPathOpsQuad.h"
 #include "SkReduceOrder.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 #include "SkTSort.h"
 
 #define USE_CUBIC_END_POINTS 1
@@ -88,26 +88,26 @@ SkDQuad SkDCubic::toQuad() const {
     return quad;
 }
 
-static bool add_simple_ts(const SkDCubic& cubic, double precision, SkTDArray<double>* ts) {
+static bool add_simple_ts(const SkDCubic& cubic, double precision, SkTArray<double, true>* ts) {
     double tDiv = calc_t_div(cubic, precision, 0);
     if (tDiv >= 1) {
         return true;
     }
     if (tDiv >= 0.5) {
-        *ts->append() = 0.5;
+        ts->push_back(0.5);
         return true;
     }
     return false;
 }
 
 static void addTs(const SkDCubic& cubic, double precision, double start, double end,
-        SkTDArray<double>* ts) {
+        SkTArray<double, true>* ts) {
     double tDiv = calc_t_div(cubic, precision, 0);
     double parts = ceil(1.0 / tDiv);
     for (double index = 0; index < parts; ++index) {
         double newT = start + (index / parts) * (end - start);
         if (newT > 0 && newT < 1) {
-            *ts->append() = newT;
+            ts->push_back(newT);
         }
     }
 }
@@ -116,7 +116,7 @@ static void addTs(const SkDCubic& cubic, double precision, double start, double
 // FIXME: when called from recursive intersect 2, this could take the original cubic
 // and do a more precise job when calling chop at and sub divide by computing the fractional ts.
 // it would still take the prechopped cubic for reduce order and find cubic inflections
-void SkDCubic::toQuadraticTs(double precision, SkTDArray<double>* ts) const {
+void SkDCubic::toQuadraticTs(double precision, SkTArray<double, true>* ts) const {
     SkReduceOrder reducer;
     int order = reducer.reduce(*this, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
     if (order < 3) {
index b6a1761..8b222f7 100644 (file)
@@ -9,7 +9,7 @@
 #include "SkIntersections.h"
 #include "SkPathOpsLine.h"
 #include "SkQuarticRoot.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 #include "SkTSort.h"
 
 /* given the implicit form 0 = Ax^2 + Bxy + Cy^2 + Dx + Ey + F
@@ -150,9 +150,9 @@ static bool is_linear_inner(const SkDQuad& q1, double t1s, double t1e, const SkD
     SkDQuad hull = q1.subDivide(t1s, t1e);
     SkDLine line = {{hull[2], hull[0]}};
     const SkDLine* testLines[] = { &line, (const SkDLine*) &hull[0], (const SkDLine*) &hull[1] };
-    size_t testCount = SK_ARRAY_COUNT(testLines);
-    SkTDArray<double> tsFound;
-    for (size_t index = 0; index < testCount; ++index) {
+    const size_t kTestCount = SK_ARRAY_COUNT(testLines);
+    SkSTArray<kTestCount * 2, double, true> tsFound;
+    for (size_t index = 0; index < kTestCount; ++index) {
         SkIntersections rootTs;
         int roots = rootTs.intersect(q2, *testLines[index]);
         for (int idx2 = 0; idx2 < roots; ++idx2) {
@@ -165,7 +165,7 @@ static bool is_linear_inner(const SkDQuad& q1, double t1s, double t1e, const SkD
             if (approximately_negative(t - t2s) || approximately_positive(t - t2e)) {
                 continue;
             }
-            *tsFound.append() = rootTs[0][idx2];
+            tsFound.push_back(rootTs[0][idx2]);
         }
     }
     int tCount = tsFound.count();
index 2800ff0..e7e5e1f 100644 (file)
@@ -17,6 +17,8 @@ class SkOpSegment;
 // given angles of {dx dy ddx ddy dddx dddy} sort them
 class SkOpAngle {
 public:
+    enum { kStackBasedCount = 8 }; // FIXME: determine what this should be
+
     bool operator<(const SkOpAngle& rh) const;
 
     bool calcSlop(double x, double y, double rx, double ry, bool* result) const;
index 6266c65..f3861a1 100644 (file)
@@ -11,7 +11,7 @@
 
 void SkOpContour::addCoincident(int index, SkOpContour* other, int otherIndex,
         const SkIntersections& ts, bool swap) {
-    SkCoincidence& coincidence = *fCoincidences.append();
+    SkCoincidence& coincidence = fCoincidences.push_back();
     coincidence.fContours[0] = this;  // FIXME: no need to store
     coincidence.fContours[1] = other;
     coincidence.fSegments[0] = index;
@@ -152,9 +152,9 @@ void SkOpContour::calcCoincidentWinding() {
 
 void SkOpContour::sortSegments() {
     int segmentCount = fSegments.count();
-    fSortedSegments.setReserve(segmentCount);
+    fSortedSegments.push_back_n(segmentCount);
     for (int test = 0; test < segmentCount; ++test) {
-        *fSortedSegments.append() = &fSegments[test];
+        fSortedSegments[test] = &fSegments[test];
     }
     SkTQSort<SkOpSegment>(fSortedSegments.begin(), fSortedSegments.end() - 1);
     fFirstSorted = 0;
@@ -229,7 +229,7 @@ int SkOpContour::debugShowWindingValues(int totalSegments, int ofInterest) {
     return sum;
 }
 
-static void SkOpContour::debugShowWindingValues(const SkTDArray<SkOpContour*>& contourList) {
+static void SkOpContour::debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList) {
 //     int ofInterest = 1 << 1 | 1 << 5 | 1 << 9 | 1 << 13;
 //    int ofInterest = 1 << 4 | 1 << 8 | 1 << 12 | 1 << 16;
     int ofInterest = 1 << 5 | 1 << 8;
index c57fbac..84f0eb1 100644 (file)
@@ -46,7 +46,7 @@ public:
             SkASSERT(fCrosses[index] != crosser);
         }
 #endif
-        *fCrosses.append() = crosser;
+        fCrosses.push_back(crosser);
     }
 
     void addCubic(const SkPoint pts[4]) {
@@ -214,17 +214,17 @@ public:
 
 #if DEBUG_SHOW_WINDING
     int debugShowWindingValues(int totalSegments, int ofInterest);
-    static void debugShowWindingValues(const SkTDArray<SkOpContour*>& contourList);
+    static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList);
 #endif
 
 private:
     void setBounds();
 
     SkTArray<SkOpSegment> fSegments;
-    SkTDArray<SkOpSegment*> fSortedSegments;
+    SkTArray<SkOpSegment*, true> fSortedSegments;
     int fFirstSorted;
-    SkTDArray<SkCoincidence> fCoincidences;
-    SkTDArray<const SkOpContour*> fCrosses;
+    SkTArray<SkCoincidence, true> fCoincidences;
+    SkTArray<const SkOpContour*, true> fCrosses;
     SkPathOpsBounds fBounds;
     bool fContainsIntercepts;  // FIXME: is this used by anybody?
     bool fContainsCubics;
index 5803afa..d7f5275 100644 (file)
@@ -22,7 +22,7 @@ void SkOpEdgeBuilder::init() {
 
 void SkOpEdgeBuilder::addOperand(const SkPath& path) {
     SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
-    fPathVerbs.pop();
+    fPathVerbs.pop_back();
     fPath = &path;
     fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
             : kWinding_PathOpsMask;
@@ -72,11 +72,11 @@ int SkOpEdgeBuilder::preFetch() {
     SkPath::Verb verb;
     do {
         verb = iter.next(pts);
-        *fPathVerbs.append() = verb;
+        fPathVerbs.push_back(verb);
         if (verb == SkPath::kMove_Verb) {
-            *fPathPts.append() = pts[0];
+            fPathPts.push_back(pts[0]);
         } else if (verb >= SkPath::kLine_Verb && verb <= SkPath::kCubic_Verb) {
-            fPathPts.append(SkPathOpsVerbToPoints(verb), &pts[1]);
+            fPathPts.push_back_n(SkPathOpsVerbToPoints(verb), &pts[1]);
         }
     } while (verb != SkPath::kDone_Verb);
     return fPathVerbs.count() - 1;
@@ -84,10 +84,10 @@ int SkOpEdgeBuilder::preFetch() {
 
 bool SkOpEdgeBuilder::close() {
     if (fFinalCurveStart && fFinalCurveEnd && *fFinalCurveStart != *fFinalCurveEnd) {
-        *fReducePts.append() = *fFinalCurveStart;
-        *fReducePts.append() = *fFinalCurveEnd;
+        fReducePts.push_back(*fFinalCurveStart);
+        fReducePts.push_back(*fFinalCurveEnd);
         const SkPoint* lineStart = fReducePts.end() - 2;
-        *fExtra.append() = fCurrentContour->addLine(lineStart);
+        fExtra.push_back(fCurrentContour->addLine(lineStart));
     }
     complete();
     return true;
@@ -119,7 +119,7 @@ bool SkOpEdgeBuilder::walk() {
                     fCurrentContour = fContours.push_back_n(1);
                     fCurrentContour->setOperand(fOperand);
                     fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_PathOpsMask);
-                    *fExtra.append() = -1;  // start new contour
+                    fExtra.push_back(-1);  // start new contour
                 }
                 fFinalCurveEnd = pointsPtr++;
                 continue;
@@ -139,7 +139,7 @@ bool SkOpEdgeBuilder::walk() {
                 }
                 if (reducedVerb == SkPath::kLine_Verb) {
                     const SkPoint* lineStart = fReducePts.end() - 2;
-                   *fExtra.append() = fCurrentContour->addLine(lineStart);
+                    fExtra.push_back(fCurrentContour->addLine(lineStart));
                     break;
                 }
                 fCurrentContour->addQuad(quadStart);
@@ -152,12 +152,12 @@ bool SkOpEdgeBuilder::walk() {
                 }
                 if (reducedVerb == SkPath::kLine_Verb) {
                     const SkPoint* lineStart = fReducePts.end() - 2;
-                    *fExtra.append() = fCurrentContour->addLine(lineStart);
+                    fExtra.push_back(fCurrentContour->addLine(lineStart));
                     break;
                 }
                 if (reducedVerb == SkPath::kQuad_Verb) {
                     const SkPoint* quadStart = fReducePts.end() - 3;
-                    *fExtra.append() = fCurrentContour->addQuad(quadStart);
+                    fExtra.push_back(fCurrentContour->addQuad(quadStart));
                     break;
                 }
                 fCurrentContour->addCubic(cubicStart);
index b827a2a..2a2bf03 100644 (file)
@@ -10,7 +10,6 @@
 #include "SkOpContour.h"
 #include "SkPathWriter.h"
 #include "SkTArray.h"
-#include "SkTDArray.h"
 
 class SkOpEdgeBuilder {
 public:
@@ -49,12 +48,12 @@ private:
     bool walk();
 
     const SkPath* fPath;
-    SkTDArray<SkPoint> fPathPts;
-    SkTDArray<uint8_t> fPathVerbs;
+    SkTArray<SkPoint, true> fPathPts;
+    SkTArray<uint8_t, true> fPathVerbs;
     SkOpContour* fCurrentContour;
     SkTArray<SkOpContour>& fContours;
-    SkTDArray<SkPoint> fReducePts;  // segments created on the fly
-    SkTDArray<int> fExtra;  // -1 marks new contour, > 0 offsets into contour
+    SkTArray<SkPoint, true> fReducePts;  // segments created on the fly
+    SkTArray<int, true> fExtra;  // -1 marks new contour, > 0 offsets into contour
     SkPathOpsMask fXorMask[2];
     const SkPoint* fFinalCurveStart;
     const SkPoint* fFinalCurveEnd;
index a9e20fd..08f4f7e 100644 (file)
@@ -32,6 +32,8 @@ static const bool gActiveEdge[kXOR_PathOp + 1][2][2][2][2] = {
 #undef F
 #undef T
 
+enum { kOutsideTrackedTCount = 16 }; // FIXME: determine what this should be
+
 // OPTIMIZATION: does the following also work, and is it any faster?
 // return outerWinding * innerWinding > 0
 //      || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0)))
@@ -44,7 +46,7 @@ bool SkOpSegment::UseInnerWinding(int outerWinding, int innerWinding) {
     return result;
 }
 
-bool SkOpSegment::activeAngle(int index, int* done, SkTDArray<SkOpAngle>* angles) {
+bool SkOpSegment::activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles) {
     if (activeAngleInner(index, done, angles)) {
         return true;
     }
@@ -63,14 +65,14 @@ bool SkOpSegment::activeAngle(int index, int* done, SkTDArray<SkOpAngle>* angles
     return false;
 }
 
-bool SkOpSegment::activeAngleOther(int index, int* done, SkTDArray<SkOpAngle>* angles) {
+bool SkOpSegment::activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angles) {
     SkOpSpan* span = &fTs[index];
     SkOpSegment* other = span->fOther;
     int oIndex = span->fOtherIndex;
     return other->activeAngleInner(oIndex, done, angles);
 }
 
-bool SkOpSegment::activeAngleInner(int index, int* done, SkTDArray<SkOpAngle>* angles) {
+bool SkOpSegment::activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angles) {
     int next = nextExactSpan(index, 1);
     if (next > 0) {
         SkOpSpan& upSpan = fTs[index];
@@ -204,11 +206,11 @@ bool SkOpSegment::activeWinding(int index, int endIndex, int* maxWinding, int* s
     return result;
 }
 
-void SkOpSegment::addAngle(SkTDArray<SkOpAngle>* anglesPtr, int start, int end) const {
+void SkOpSegment::addAngle(SkTArray<SkOpAngle, true>* anglesPtr, int start, int end) const {
     SkASSERT(start != end);
-    SkOpAngle* angle = anglesPtr->append();
+    SkOpAngle& angle = anglesPtr->push_back();
 #if DEBUG_ANGLE
-    SkTDArray<SkOpAngle>& angles = *anglesPtr;
+    SkTArray<SkOpAngle, true>& angles = *anglesPtr;
     if (angles.count() > 1) {
         const SkOpSegment* aSeg = angles[0].segment();
         int aStart = angles[0].start();
@@ -224,7 +226,7 @@ void SkOpSegment::addAngle(SkTDArray<SkOpAngle>* anglesPtr, int start, int end)
         }
     }
 #endif
-    angle->set(this, start, end);
+    angle.set(this, start, end);
 }
 
 void SkOpSegment::addCancelOutsides(double tStart, double oStart, SkOpSegment* other, double oEnd) {
@@ -299,7 +301,7 @@ void SkOpSegment::addCancelOutsides(double tStart, double oStart, SkOpSegment* o
     }
 }
 
-void SkOpSegment::addCoinOutsides(const SkTDArray<double>& outsideTs, SkOpSegment* other,
+void SkOpSegment::addCoinOutsides(const SkTArray<double, true>& outsideTs, SkOpSegment* other,
                                   double oEnd) {
     // walk this to outsideTs[0]
     // walk other to outsideTs[1]
@@ -566,8 +568,8 @@ void SkOpSegment::addTCancel(double startT, double endT, SkOpSegment* other,
     double tRatio = (oEndT - oStartT) / (endT - startT);
     SkOpSpan* test = &fTs[index];
     SkOpSpan* oTest = &other->fTs[oIndex];
-    SkTDArray<double> outsideTs;
-    SkTDArray<double> oOutsideTs;
+    SkSTArray<kOutsideTrackedTCount, double, true> outsideTs;
+    SkSTArray<kOutsideTrackedTCount, double, true> oOutsideTs;
     do {
         bool decrement = test->fWindValue && oTest->fWindValue;
         bool track = test->fWindValue || oTest->fWindValue;
@@ -658,7 +660,7 @@ int SkOpSegment::addUnsortableT(SkOpSegment* other, bool start, const SkPoint& p
 }
 
 int SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool opp, int index,
-        SkTDArray<double>* outsideTs) {
+        SkTArray<double, true>* outsideTs) {
     int oWindValue = oTest.fWindValue;
     int oOppValue = oTest.fOppValue;
     if (opp) {
@@ -681,7 +683,7 @@ int SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool opp, int index,
 // intermediate T values (using this as the master, other as the follower)
 // and walk other conditionally -- hoping that it catches up in the end
 int SkOpSegment::bumpCoincidentOther(const SkOpSpan& test, double oEndT, int& oIndex,
-        SkTDArray<double>* oOutsideTs) {
+        SkTArray<double, true>* oOutsideTs) {
     SkOpSpan* const oTest = &fTs[oIndex];
     SkOpSpan* oEnd = oTest;
     const double startT = test.fT;
@@ -719,8 +721,8 @@ void SkOpSegment::addTCoincident(double startT, double endT, SkOpSegment* other,
     }
     SkOpSpan* test = &fTs[index];
     SkOpSpan* oTest = &other->fTs[oIndex];
-    SkTDArray<double> outsideTs;
-    SkTDArray<double> oOutsideTs;
+    SkSTArray<kOutsideTrackedTCount, double, true> outsideTs;
+    SkSTArray<kOutsideTrackedTCount, double, true> oOutsideTs;
     do {
         // if either span has an opposite value and the operands don't match, resolve first
  //       SkASSERT(!test->fDone || !oTest->fDone);
@@ -775,7 +777,7 @@ void SkOpSegment::addTPair(double t, SkOpSegment* other, double otherT, bool bor
     other->matchWindingValue(otherInsertedAt, otherT, borrowWind);
 }
 
-void SkOpSegment::addTwoAngles(int start, int end, SkTDArray<SkOpAngle>* angles) const {
+void SkOpSegment::addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const {
     // add edge leading into junction
     int min = SkMin32(end, start);
     if (fTs[min].fWindValue > 0 || fTs[min].fOppValue != 0) {
@@ -817,7 +819,7 @@ bool SkOpSegment::betweenTs(int lesser, double testT, int greater) const {
     return approximately_between(fTs[lesser].fT, testT, fTs[greater].fT);
 }
 
-void SkOpSegment::buildAngles(int index, SkTDArray<SkOpAngle>* angles, bool includeOpp) const {
+void SkOpSegment::buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeOpp) const {
     double referenceT = fTs[index].fT;
     int lesser = index;
     while (--lesser >= 0 && (includeOpp || fTs[lesser].fOther->fOperand == fOperand)
@@ -830,7 +832,7 @@ void SkOpSegment::buildAngles(int index, SkTDArray<SkOpAngle>* angles, bool incl
             && precisely_negative(fTs[index].fT - referenceT));
 }
 
-void SkOpSegment::buildAnglesInner(int index, SkTDArray<SkOpAngle>* angles) const {
+void SkOpSegment::buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const {
     const SkOpSpan* span = &fTs[index];
     SkOpSegment* other = span->fOther;
 // if there is only one live crossing, and no coincidence, continue
@@ -850,12 +852,12 @@ void SkOpSegment::buildAnglesInner(int index, SkTDArray<SkOpAngle>* angles) cons
 }
 
 int SkOpSegment::computeSum(int startIndex, int endIndex, bool binary) {
-    SkTDArray<SkOpAngle> angles;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
     addTwoAngles(startIndex, endIndex, &angles);
     buildAngles(endIndex, &angles, false);
     // OPTIMIZATION: check all angles to see if any have computed wind sum
     // before sorting (early exit if none)
-    SkTDArray<SkOpAngle*> sorted;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
     // FIXME?: Not sure if this sort must be ordered or if the relaxed ordering is OK ...
     bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_SortAngleKind);
 #if DEBUG_SORT
@@ -1137,12 +1139,12 @@ SkOpSegment* SkOpSegment::findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart
         return other;
     }
     // more than one viable candidate -- measure angles to find best
-    SkTDArray<SkOpAngle> angles;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
     SkASSERT(startIndex - endIndex != 0);
     SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
     addTwoAngles(startIndex, end, &angles);
     buildAngles(end, &angles, true);
-    SkTDArray<SkOpAngle*> sorted;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
     bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_SortAngleKind);
     int angleCount = angles.count();
     int firstIndex = findStartingEdge(sorted, startIndex, end);
@@ -1259,12 +1261,12 @@ SkOpSegment* SkOpSegment::findNextWinding(SkTDArray<SkOpSpan*>* chase, int* next
         return other;
     }
     // more than one viable candidate -- measure angles to find best
-    SkTDArray<SkOpAngle> angles;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
     SkASSERT(startIndex - endIndex != 0);
     SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
     addTwoAngles(startIndex, end, &angles);
     buildAngles(end, &angles, true);
-    SkTDArray<SkOpAngle*> sorted;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
     bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_SortAngleKind);
     int angleCount = angles.count();
     int firstIndex = findStartingEdge(sorted, startIndex, end);
@@ -1388,12 +1390,12 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
         SkASSERT(step < 0 ? *nextEnd >= 0 : *nextEnd < other->fTs.count());
         return other;
     }
-    SkTDArray<SkOpAngle> angles;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
     SkASSERT(startIndex - endIndex != 0);
     SkASSERT((startIndex - endIndex < 0) ^ (step < 0));
     addTwoAngles(startIndex, end, &angles);
     buildAngles(end, &angles, false);
-    SkTDArray<SkOpAngle*> sorted;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
     bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMustBeOrdered_SortAngleKind);
     if (!sortable) {
         *unsortable = true;
@@ -1449,7 +1451,7 @@ SkOpSegment* SkOpSegment::findNextXor(int* nextStart, int* nextEnd, bool* unsort
     return nextSegment;
 }
 
-int SkOpSegment::findStartingEdge(const SkTDArray<SkOpAngle*>& sorted, int start, int end) {
+int SkOpSegment::findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end) {
     int angleCount = sorted.count();
     int firstIndex = -1;
     for (int angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
@@ -1631,11 +1633,11 @@ SkOpSegment* SkOpSegment::findTop(int* tIndexPtr, int* endIndexPtr, bool* unsort
     }
     // if the topmost T is not on end, or is three-way or more, find left
     // look for left-ness from tLeft to firstT (matching y of other)
-    SkTDArray<SkOpAngle> angles;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
     SkASSERT(firstT - end != 0);
     addTwoAngles(end, firstT, &angles);
     buildAngles(firstT, &angles, true);
-    SkTDArray<SkOpAngle*> sorted;
+    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
     bool sortable = SortAngles(angles, &sorted, SkOpSegment::kMayBeUnordered_SortAngleKind);
     int first = SK_MaxS32;
     SkScalar top = SK_ScalarMax;
@@ -2343,15 +2345,17 @@ void SkOpSegment::setUpWindings(int index, int endIndex, int* sumMiWinding, int*
 // exclusion in find top and others. This could be optimized to only mark
 // adjacent spans that unsortable. However, this makes it difficult to later
 // determine starting points for edge detection in find top and the like.
-bool SkOpSegment::SortAngles(const SkTDArray<SkOpAngle>& angles, SkTDArray<SkOpAngle*>* angleList,
+bool SkOpSegment::SortAngles(const SkTArray<SkOpAngle, true>& angles,
+                             SkTArray<SkOpAngle*, true>* angleList,
                              SortAngleKind orderKind) {
     bool sortable = true;
     int angleCount = angles.count();
     int angleIndex;
-    angleList->setReserve(angleCount);
+// FIXME: caller needs to use SkTArray constructor with reserve count
+//    angleList->setReserve(angleCount);
     for (angleIndex = 0; angleIndex < angleCount; ++angleIndex) {
         const SkOpAngle& angle = angles[angleIndex];
-        *angleList->append() = const_cast<SkOpAngle*>(&angle);
+        angleList->push_back(const_cast<SkOpAngle*>(&angle));
 #if DEBUG_ANGLE
         (*(angleList->end() - 1))->setID(angleIndex);
 #endif
@@ -2470,11 +2474,11 @@ bool SkOpSegment::isTiny(int index) const {
     return fTs[index].fTiny;
 }
 
-void SkOpSegment::TrackOutside(SkTDArray<double>* outsideTs, double end, double start) {
+void SkOpSegment::TrackOutside(SkTArray<double, true>* outsideTs, double end, double start) {
     int outCount = outsideTs->count();
     if (outCount == 0 || !approximately_negative(end - (*outsideTs)[outCount - 2])) {
-        *outsideTs->append() = end;
-        *outsideTs->append() = start;
+        outsideTs->push_back(end);
+        outsideTs->push_back(start);
     }
 }
 
@@ -2763,8 +2767,9 @@ void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int
 #endif
 
 #if DEBUG_SORT || DEBUG_SWAP_TOP
-void SkOpSegment::debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first,
-        const int contourWinding, const int oppContourWinding) const {
+void SkOpSegment::debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles,
+                                int first, const int contourWinding,
+                                const int oppContourWinding) const {
     if (--gDebugSortCount < 0) {
         return;
     }
@@ -2872,7 +2877,8 @@ void SkOpSegment::debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& an
     } while (index != first);
 }
 
-void SkOpSegment::debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first) {
+void SkOpSegment::debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles,
+                                int first) {
     const SkOpAngle* firstAngle = angles[first];
     const SkOpSegment* segment = firstAngle->segment();
     int winding = segment->updateWinding(firstAngle);
@@ -2888,8 +2894,7 @@ int SkOpSegment::debugShowWindingValues(int slotCount, int ofInterest) const {
         return 0;
     }
     int sum = 0;
-    SkTDArray<char> slots;
-    slots.setCount(slotCount * 2);
+    SkTArray<char, true> slots(slotCount * 2);
     memset(slots.begin(), ' ', slotCount * 2);
     for (int i = 0; i < fTs.count(); ++i) {
    //     if (!(1 << fTs[i].fOther->fID & ofInterest)) {
index b26bad1..94efcb5 100644 (file)
@@ -11,6 +11,7 @@
 #include "SkOpSpan.h"
 #include "SkPathOpsBounds.h"
 #include "SkPathOpsCurve.h"
+#include "SkTArray.h"
 #include "SkTDArray.h"
 
 class SkPathWriter;
@@ -230,7 +231,7 @@ public:
         return xyAtT(span).fY;
     }
 
-    bool activeAngle(int index, int* done, SkTDArray<SkOpAngle>* angles);
+    bool activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles);
     SkPoint activeLeftTop(bool onlySortable, int* firstT) const;
     bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
     bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
@@ -294,7 +295,8 @@ public:
         kMustBeOrdered_SortAngleKind, // required for winding calc
         kMayBeUnordered_SortAngleKind // ok for find top
     };
-    static bool SortAngles(const SkTDArray<SkOpAngle>& angles, SkTDArray<SkOpAngle*>* angleList,
+    static bool SortAngles(const SkTArray<SkOpAngle, true>& angles,
+                           SkTArray<SkOpAngle*, true>* angleList,
                            SortAngleKind );
     bool subDivide(int start, int end, SkPoint edge[4]) const;
     bool subDivide(int start, int end, SkDCubic* result) const;
@@ -315,9 +317,9 @@ public:
     void debugShowActiveSpans() const;
 #endif
 #if DEBUG_SORT || DEBUG_SWAP_TOP
-    void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first,
+    void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first,
             const int contourWinding, const int oppContourWinding) const;
-    void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int first);
+    void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles, int first);
 #endif
 #if DEBUG_CONCIDENT
     void debugShowTs() const;
@@ -327,25 +329,25 @@ public:
 #endif
 
 private:
-    bool activeAngleOther(int index, int* done, SkTDArray<SkOpAngle>* angles);
-    bool activeAngleInner(int index, int* done, SkTDArray<SkOpAngle>* angles);
-    void addAngle(SkTDArray<SkOpAngle>* angles, int start, int end) const;
+    bool activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angles);
+    bool activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angles);
+    void addAngle(SkTArray<SkOpAngle, true>* angles, int start, int end) const;
     void addCancelOutsides(double tStart, double oStart, SkOpSegment* other, double oEnd);
-    void addCoinOutsides(const SkTDArray<double>& outsideTs, SkOpSegment* other, double oEnd);
-    void addTwoAngles(int start, int end, SkTDArray<SkOpAngle>* angles) const;
+    void addCoinOutsides(const SkTArray<double, true>& outsideTs, SkOpSegment* other, double oEnd);
+    void addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) const;
     int advanceCoincidentOther(const SkOpSpan* test, double oEndT, int oIndex);
     int advanceCoincidentThis(const SkOpSpan* oTest, bool opp, int index);
-    void buildAngles(int index, SkTDArray<SkOpAngle>* angles, bool includeOpp) const;
-    void buildAnglesInner(int index, SkTDArray<SkOpAngle>* angles) const;
+    void buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeOpp) const;
+    void buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const;
     int bumpCoincidentThis(const SkOpSpan& oTest, bool opp, int index,
-                           SkTDArray<double>* outsideTs);
+                           SkTArray<double, true>* outsideTs);
     int bumpCoincidentOther(const SkOpSpan& test, double oEndT, int& oIndex,
-                            SkTDArray<double>* oOutsideTs);
+                            SkTArray<double, true>* oOutsideTs);
     bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
     bool clockwise(int tStart, int tEnd) const;
     void decrementSpan(SkOpSpan* span);
     bool equalPoints(int greaterTIndex, int lesserTIndex);
-    int findStartingEdge(const SkTDArray<SkOpAngle*>& sorted, int start, int end);
+    int findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, int end);
     void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
     void matchWindingValue(int tIndex, double t, bool borrowWind);
     SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
@@ -365,7 +367,7 @@ private:
     SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last);
     bool serpentine(int tStart, int tEnd) const;
     void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
-    static void TrackOutside(SkTDArray<double>* outsideTs, double end, double start);
+    static void TrackOutside(SkTArray<double, true>* outsideTs, double end, double start);
     int updateOppWinding(int index, int endIndex) const;
     int updateOppWinding(const SkOpAngle* angle) const;
     int updateWinding(int index, int endIndex) const;
@@ -393,6 +395,7 @@ private:
 
     const SkPoint* fPts;
     SkPathOpsBounds fBounds;
+    // FIXME: can't convert to SkTArray because it uses insert
     SkTDArray<SkOpSpan> fTs;  // two or more (always includes t=0 t=1)
     // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
     int fDoneSpans;  // quick check that segment is finished
index 9215cbc..0fa5ce0 100644 (file)
@@ -9,7 +9,7 @@
 #include "SkPathWriter.h"
 #include "SkTSort.h"
 
-static int contourRangeCheckY(const SkTDArray<SkOpContour*>& contourList, SkOpSegment** currentPtr,
+static int contourRangeCheckY(const SkTArray<SkOpContour*, true>& contourList, SkOpSegment** currentPtr,
                               int* indexPtr, int* endIndexPtr, double* bestHit, SkScalar* bestDx,
                               bool* tryAgain, double* midPtr, bool opp) {
     const int index = *indexPtr;
@@ -97,7 +97,7 @@ abortContours:
     return result;
 }
 
-SkOpSegment* FindUndone(SkTDArray<SkOpContour*>& contourList, int* start, int* end) {
+SkOpSegment* FindUndone(SkTArray<SkOpContour*, true>& contourList, int* start, int* end) {
     int contourCount = contourList.count();
     SkOpSegment* result;
     for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
@@ -117,7 +117,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
         const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex);
         SkOpSegment* segment = backPtr.fOther;
         tIndex = backPtr.fOtherIndex;
-        SkTDArray<SkOpAngle> angles;
+        SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
         int done = 0;
         if (segment->activeAngle(tIndex, &done, &angles)) {
             SkOpAngle* last = angles.end() - 1;
@@ -133,7 +133,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
         if (done == angles.count()) {
             continue;
         }
-        SkTDArray<SkOpAngle*> sorted;
+        SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
         bool sortable = SkOpSegment::SortAngles(angles, &sorted,
                 SkOpSegment::kMayBeUnordered_SortAngleKind);
         int angleCount = sorted.count();
@@ -208,7 +208,7 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex)
 }
 
 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
-void DebugShowActiveSpans(SkTDArray<SkOpContour*>& contourList) {
+void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) {
     int index;
     for (index = 0; index < contourList.count(); ++ index) {
         contourList[index]->debugShowActiveSpans();
@@ -216,7 +216,7 @@ void DebugShowActiveSpans(SkTDArray<SkOpContour*>& contourList) {
 }
 #endif
 
-static SkOpSegment* findSortableTop(const SkTDArray<SkOpContour*>& contourList,
+static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourList,
                                     int* index, int* endIndex, SkPoint* topLeft, bool* unsortable,
                                     bool* done, bool onlySortable) {
     SkOpSegment* result;
@@ -253,7 +253,7 @@ static SkOpSegment* findSortableTop(const SkTDArray<SkOpContour*>& contourList,
     return result;
 }
 
-static int rightAngleWinding(const SkTDArray<SkOpContour*>& contourList,
+static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList,
                              SkOpSegment** current, int* index, int* endIndex, double* tHit,
                              SkScalar* hitDx, bool* tryAgain, bool opp) {
     double test = 0.9;
@@ -270,7 +270,7 @@ static int rightAngleWinding(const SkTDArray<SkOpContour*>& contourList,
     return contourWinding;
 }
 
-static void skipVertical(const SkTDArray<SkOpContour*>& contourList,
+static void skipVertical(const SkTArray<SkOpContour*, true>& contourList,
         SkOpSegment** current, int* index, int* endIndex) {
     if (!(*current)->isVertical(*index, *endIndex)) {
         return;
@@ -288,7 +288,7 @@ static void skipVertical(const SkTDArray<SkOpContour*>& contourList,
     }
 }
 
-SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour*>& contourList, bool* firstContour,
+SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, bool* firstContour,
                              int* indexPtr, int* endIndexPtr, SkPoint* topLeft, bool* unsortable,
                              bool* done,  bool binary) {
     SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, topLeft, unsortable,
@@ -344,7 +344,7 @@ SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour*>& contourList, bool* f
     return current;
 }
 
-void FixOtherTIndex(SkTDArray<SkOpContour*>* contourList) {
+void FixOtherTIndex(SkTArray<SkOpContour*, true>* contourList) {
     int contourCount = (*contourList).count();
     for (int cTest = 0; cTest < contourCount; ++cTest) {
         SkOpContour* contour = (*contourList)[cTest];
@@ -352,7 +352,7 @@ void FixOtherTIndex(SkTDArray<SkOpContour*>* contourList) {
     }
 }
 
-void SortSegments(SkTDArray<SkOpContour*>* contourList) {
+void SortSegments(SkTArray<SkOpContour*, true>* contourList) {
     int contourCount = (*contourList).count();
     for (int cTest = 0; cTest < contourCount; ++cTest) {
         SkOpContour* contour = (*contourList)[cTest];
@@ -360,7 +360,7 @@ void SortSegments(SkTDArray<SkOpContour*>* contourList) {
     }
 }
 
-void MakeContourList(SkTArray<SkOpContour>& contours, SkTDArray<SkOpContour*>& list,
+void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, true>& list,
                      bool evenOdd, bool oppEvenOdd) {
     int count = contours.count();
     if (count == 0) {
@@ -369,7 +369,7 @@ void MakeContourList(SkTArray<SkOpContour>& contours, SkTDArray<SkOpContour*>& l
     for (int index = 0; index < count; ++index) {
         SkOpContour& contour = contours[index];
         contour.setOppXor(contour.operand() ? evenOdd : oppEvenOdd);
-        *list.append() = &contour;
+        list.push_back(&contour);
     }
     SkTQSort<SkOpContour>(list.begin(), list.end() - 1);
 }
@@ -403,7 +403,7 @@ void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
     builder.finish();
     int count = contours.count();
     int outer;
-    SkTDArray<int> runs;  // indices of partial contours
+    SkTArray<int, true> runs(count);  // indices of partial contours
     for (outer = 0; outer < count; ++outer) {
         const SkOpContour& eContour = contours[outer];
         const SkPoint& eStart = eContour.start();
@@ -422,23 +422,23 @@ void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
             eContour.toPath(simple);
             continue;
         }
-        *runs.append() = outer;
+        runs.push_back(outer);
     }
     count = runs.count();
     if (count == 0) {
         return;
     }
-    SkTDArray<int> sLink, eLink;
-    sLink.setCount(count);
-    eLink.setCount(count);
+    SkTArray<int, true> sLink, eLink;
+    sLink.push_back_n(count);
+    eLink.push_back_n(count);
     int rIndex, iIndex;
     for (rIndex = 0; rIndex < count; ++rIndex) {
         sLink[rIndex] = eLink[rIndex] = SK_MaxS32;
     }
-    SkTDArray<double> distances;
     const int ends = count * 2;  // all starts and ends
     const int entries = (ends - 1) * count;  // folded triangle : n * (n - 1) / 2
-    distances.setCount(entries);
+    SkTArray<double, true> distances;
+    distances.push_back_n(entries);
     for (rIndex = 0; rIndex < ends - 1; ++rIndex) {
         outer = runs[rIndex >> 1];
         const SkOpContour& oContour = contours[outer];
@@ -455,8 +455,8 @@ void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
             distances[row + iIndex] = dist;  // oStart distance from iStart
         }
     }
-    SkTDArray<int> sortedDist;
-    sortedDist.setCount(entries);
+    SkTArray<int, true> sortedDist;
+    sortedDist.push_back_n(entries);
     for (rIndex = 0; rIndex < entries; ++rIndex) {
         sortedDist[rIndex] = rIndex;
     }
index 8bbe232..569edb7 100644 (file)
@@ -8,22 +8,24 @@
 #define SkPathOpsCommon_DEFINED
 
 #include "SkOpContour.h"
+#include "SkTDArray.h"
 
 class SkPathWriter;
 
 void Assemble(const SkPathWriter& path, SkPathWriter* simple);
+// FIXME: find chase uses insert, so it can't be converted to SkTArray yet
 SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex);
-SkOpSegment* FindSortableTop(const SkTDArray<SkOpContour*>& contourList, bool* firstContour,
+SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList, bool* firstContour,
                              int* index, int* endIndex, SkPoint* topLeft, bool* unsortable,
                              bool* done, bool binary);
-SkOpSegment* FindUndone(SkTDArray<SkOpContour*>& contourList, int* start, int* end);
-void FixOtherTIndex(SkTDArray<SkOpContour*>* contourList);
-void MakeContourList(SkTArray<SkOpContour>& contours, SkTDArray<SkOpContour*>& list,
+SkOpSegment* FindUndone(SkTArray<SkOpContour*, true>& contourList, int* start, int* end);
+void FixOtherTIndex(SkTArray<SkOpContour*, true>* contourList);
+void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, true>& list,
                      bool evenOdd, bool oppEvenOdd);
-void SortSegments(SkTDArray<SkOpContour*>* contourList);
+void SortSegments(SkTArray<SkOpContour*, true>* contourList);
 
 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
-void DebugShowActiveSpans(SkTDArray<SkOpContour*>& contourList);
+void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList);
 #endif
 
 #endif
index 5d77e5a..60dca44 100644 (file)
@@ -383,8 +383,13 @@ static double interp_cubic_coords(const double* src, double t) {
 }
 
 SkDCubic SkDCubic::subDivide(double t1, double t2) const {
-    if (t1 == 0 && t2 == 1) {
-        return *this;
+    if (t1 == 0 || t2 == 1) {
+        if (t1 == 0 && t2 == 1) {
+            return *this;
+        }
+        SkDCubicPair pair = chopAt(t1 == 0 ? t2 : t1);
+        SkDCubic dst = t1 == 0 ? pair.first() : pair.second();
+        return dst;
     }
     SkDCubic dst;
     double ax = dst[0].fX = interp_cubic_coords(&fPts[0].fX, t1);
index 7be6142..f07af80 100644 (file)
@@ -10,7 +10,7 @@
 
 #include "SkPath.h"
 #include "SkPathOpsPoint.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 
 struct SkDCubicPair {
     const SkDCubic& first() const { return (const SkDCubic&) pts[0]; }
@@ -74,7 +74,7 @@ struct SkDCubic {
     }
 
     SkDPoint top(double startT, double endT) const;
-    void toQuadraticTs(double precision, SkTDArray<double>* ts) const;
+    void toQuadraticTs(double precision, SkTArray<double, true>* ts) const;
     SkDQuad toQuad() const;
     SkDPoint xyAtT(double t) const;
 };
index f030765..7e1c772 100644 (file)
@@ -20,7 +20,7 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int
         const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex);
         SkOpSegment* segment = backPtr.fOther;
         nextStart = backPtr.fOtherIndex;
-        SkTDArray<SkOpAngle> angles;
+        SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
         int done = 0;
         if (segment->activeAngle(nextStart, &done, &angles)) {
             SkOpAngle* last = angles.end() - 1;
@@ -36,7 +36,7 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int
         if (done == angles.count()) {
             continue;
         }
-        SkTDArray<SkOpAngle*> sorted;
+        SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
         bool sortable = SkOpSegment::SortAngles(angles, &sorted,
                 SkOpSegment::kMayBeUnordered_SortAngleKind);
         int angleCount = sorted.count();
@@ -126,7 +126,7 @@ static bool windingIsActive(int winding, int oppWinding, int spanWinding, int op
 }
 */
 
-static bool bridgeOp(SkTDArray<SkOpContour*>& contourList, const SkPathOp op,
+static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp op,
         const int xorMask, const int xorOpMask, SkPathWriter* simple) {
     bool firstContour = true;
     bool unsortable = false;
@@ -263,7 +263,7 @@ bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
     result->reset();
     result->setFillType(fillType);
     const int xorOpMask = builder.xorMask();
-    SkTDArray<SkOpContour*> contourList;
+    SkTArray<SkOpContour*, true> contourList;
     MakeContourList(contours, contourList, xorMask == kEvenOdd_PathOpsMask,
             xorOpMask == kEvenOdd_PathOpsMask);
     SkOpContour** currentPtr = contourList.begin();
index 9a319e0..f89c4af 100644 (file)
@@ -9,7 +9,7 @@
 #include "SkPathOpsCommon.h"
 #include "SkPathWriter.h"
 
-static bool bridgeWinding(SkTDArray<SkOpContour*>& contourList, SkPathWriter* simple) {
+static bool bridgeWinding(SkTArray<SkOpContour*, true>& contourList, SkPathWriter* simple) {
     bool firstContour = true;
     bool unsortable = false;
     bool topUnsortable = false;
@@ -94,7 +94,7 @@ static bool bridgeWinding(SkTDArray<SkOpContour*>& contourList, SkPathWriter* si
 }
 
 // returns true if all edges were processed
-static bool bridgeXor(SkTDArray<SkOpContour*>& contourList, SkPathWriter* simple) {
+static bool bridgeXor(SkTArray<SkOpContour*, true>& contourList, SkPathWriter* simple) {
     SkOpSegment* current;
     int start, end;
     bool unsortable = false;
@@ -161,7 +161,7 @@ bool Simplify(const SkPath& path, SkPath* result) {
     if (!builder.finish()) {
         return false;
     }
-    SkTDArray<SkOpContour*> contourList;
+    SkTArray<SkOpContour*, true> contourList;
     MakeContourList(contours, contourList, false, false);
     SkOpContour** currentPtr = contourList.begin();
     result->setFillType(fillType);
index 6d2339c..ab85f3d 100644 (file)
@@ -425,31 +425,31 @@ int SkReduceOrder::reduce(const SkDCubic& cubic, Quadratics allowQuadratics,
     return 4;
 }
 
-SkPath::Verb SkReduceOrder::Quad(const SkPoint a[3], SkTDArray<SkPoint>* reducePts) {
+SkPath::Verb SkReduceOrder::Quad(const SkPoint a[3], SkTArray<SkPoint, true>* reducePts) {
     SkDQuad quad;
     quad.set(a);
     SkReduceOrder reducer;
     int order = reducer.reduce(quad, kFill_Style);
     if (order == 2) {  // quad became line
         for (int index = 0; index < order; ++index) {
-            SkPoint* pt = reducePts->append();
-            pt->fX = SkDoubleToScalar(reducer.fLine[index].fX);
-            pt->fY = SkDoubleToScalar(reducer.fLine[index].fY);
+            SkPoint& pt = reducePts->push_back();
+            pt.fX = SkDoubleToScalar(reducer.fLine[index].fX);
+            pt.fY = SkDoubleToScalar(reducer.fLine[index].fY);
         }
     }
     return SkPathOpsPointsToVerb(order - 1);
 }
 
-SkPath::Verb SkReduceOrder::Cubic(const SkPoint a[4], SkTDArray<SkPoint>* reducePts) {
+SkPath::Verb SkReduceOrder::Cubic(const SkPoint a[4], SkTArray<SkPoint, true>* reducePts) {
     SkDCubic cubic;
     cubic.set(a);
     SkReduceOrder reducer;
     int order = reducer.reduce(cubic, kAllow_Quadratics, kFill_Style);
     if (order == 2 || order == 3) {  // cubic became line or quad
         for (int index = 0; index < order; ++index) {
-            SkPoint* pt = reducePts->append();
-            pt->fX = SkDoubleToScalar(reducer.fQuad[index].fX);
-            pt->fY = SkDoubleToScalar(reducer.fQuad[index].fY);
+            SkPoint& pt = reducePts->push_back();
+            pt.fX = SkDoubleToScalar(reducer.fQuad[index].fX);
+            pt.fY = SkDoubleToScalar(reducer.fQuad[index].fY);
         }
     }
     return SkPathOpsPointsToVerb(order - 1);
index 62b4af9..82f8ffb 100644 (file)
@@ -11,7 +11,7 @@
 #include "SkPathOpsCubic.h"
 #include "SkPathOpsLine.h"
 #include "SkPathOpsQuad.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 
 union SkReduceOrder {
     enum Quadratics {
@@ -27,8 +27,8 @@ union SkReduceOrder {
     int reduce(const SkDLine& line);
     int reduce(const SkDQuad& quad, Style);
 
-    static SkPath::Verb Cubic(const SkPoint pts[4], SkTDArray<SkPoint>* reducePts);
-    static SkPath::Verb Quad(const SkPoint pts[3], SkTDArray<SkPoint>* reducePts);
+    static SkPath::Verb Cubic(const SkPoint pts[4], SkTArray<SkPoint, true>* reducePts);
+    static SkPath::Verb Quad(const SkPoint pts[3], SkTArray<SkPoint, true>* reducePts);
 
     SkDLine fLine;
     SkDQuad fQuad;
index b0d6bd8..7f5f4cd 100644 (file)
@@ -244,7 +244,7 @@ static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const S
         cubic2[0].fX, cubic2[0].fY, cubic2[1].fX, cubic2[1].fY,
         cubic2[2].fX, cubic2[2].fY, cubic2[3].fX, cubic2[3].fY);
 #endif
-    SkTDArray<SkDQuad> quads1;
+    SkTArray<SkDQuad, true> quads1;
     CubicToQuads(cubic1, cubic1.calcPrecision(), quads1);
 #if ONE_OFF_DEBUG
     SkDebugf("computed quadratics set 1\n");
@@ -254,7 +254,7 @@ static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const S
                  q[1].fX, q[1].fY,  q[2].fX, q[2].fY);
     }
 #endif
-    SkTDArray<SkDQuad> quads2;
+    SkTArray<SkDQuad, true> quads2;
     CubicToQuads(cubic2, cubic2.calcPrecision(), quads2);
 #if ONE_OFF_DEBUG
     SkDebugf("computed quadratics set 2\n");
index f738e07..774fbae 100644 (file)
@@ -18,7 +18,7 @@ static void test(skiatest::Reporter* reporter, const SkDCubic* cubics, const cha
     for (size_t index = firstTest; index < testCount; ++index) {
         const SkDCubic& cubic = cubics[index];
         double precision = cubic.calcPrecision();
-        SkTDArray<SkDQuad> quads;
+        SkTArray<SkDQuad, true> quads;
         CubicToQuads(cubic, precision, quads);
         if (quads.count() != 1 && quads.count() != 2) {
             SkDebugf("%s [%d] cubic to quadratics failed count=%d\n", name, static_cast<int>(index),
@@ -34,7 +34,7 @@ static void test(skiatest::Reporter* reporter, const SkDQuad* quadTests, const c
         const SkDQuad& quad = quadTests[index];
         SkDCubic cubic = quad.toCubic();
         double precision = cubic.calcPrecision();
-        SkTDArray<SkDQuad> quads;
+        SkTArray<SkDQuad, true> quads;
         CubicToQuads(cubic, precision, quads);
         if (quads.count() != 1 && quads.count() != 2) {
             SkDebugf("%s [%d] cubic to quadratics failed count=%d\n", name, static_cast<int>(index),
@@ -50,7 +50,7 @@ static void testC(skiatest::Reporter* reporter, const SkDCubic* cubics, const ch
     for (size_t index = firstTest; index < testCount; ++index) {
         const SkDCubic& cubic = cubics[index];
         double precision = cubic.calcPrecision();
-        SkTDArray<SkDQuad> quads;
+        SkTArray<SkDQuad, true> quads;
         CubicToQuads(cubic, precision, quads);
         if (!AlmostEqualUlps(cubic[0].fX, quads[0][0].fX)
                 || !AlmostEqualUlps(cubic[0].fY, quads[0][0].fY)) {
@@ -72,7 +72,7 @@ static void testC(skiatest::Reporter* reporter, const SkDCubic(* cubics)[2], con
         for (int idx2 = 0; idx2 < 2; ++idx2) {
             const SkDCubic& cubic = cubics[index][idx2];
             double precision = cubic.calcPrecision();
-            SkTDArray<SkDQuad> quads;
+            SkTArray<SkDQuad, true> quads;
             CubicToQuads(cubic, precision, quads);
             if (!AlmostEqualUlps(cubic[0].fX, quads[0][0].fX)
                     || !AlmostEqualUlps(cubic[0].fY, quads[0][0].fY)) {
@@ -176,7 +176,7 @@ static void oneOff(skiatest::Reporter* reporter, size_t x) {
     SkScalar skinflect[2];
     int skin = SkFindCubicInflections(skcubic, skinflect);
     if (false) SkDebugf("%s %d %1.9g\n", __FUNCTION__, skin, skinflect[0]);
-    SkTDArray<SkDQuad> quads;
+    SkTArray<SkDQuad, true> quads;
     double precision = cubic.calcPrecision();
     CubicToQuads(cubic, precision, quads);
     if (false) SkDebugf("%s quads=%d\n", __FUNCTION__, quads.count());
index aab7d6e..4356b42 100644 (file)
@@ -7,12 +7,12 @@
 #include "PathOpsTestCommon.h"
 #include "SkPathOpsCubic.h"
 
-void CubicToQuads(const SkDCubic& cubic, double precision, SkTDArray<SkDQuad>& quads) {
-    SkTDArray<double> ts;
+void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads) {
+    SkTArray<double, true> ts;
     cubic.toQuadraticTs(precision, &ts);
     if (ts.count() <= 0) {
         SkDQuad quad = cubic.toQuad();
-        *quads.append() = quad;
+        quads.push_back(quad);
         return;
     }
     double tStart = 0;
@@ -20,7 +20,7 @@ void CubicToQuads(const SkDCubic& cubic, double precision, SkTDArray<SkDQuad>& q
         const double tEnd = i1 < ts.count() ? ts[i1] : 1;
         SkDCubic part = cubic.subDivide(tStart, tEnd);
         SkDQuad quad = part.toQuad();
-        *quads.append() = quad;
+        quads.push_back(quad);
         tStart = tEnd;
     }
 }
index e4ab829..5072ad6 100644 (file)
@@ -8,8 +8,8 @@
 #define PathOpsTestCommon_DEFINED
 
 #include "SkPathOpsQuad.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 
-void CubicToQuads(const SkDCubic& cubic, double precision, SkTDArray<SkDQuad>& quads);
+void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads);
 
 #endif