Move fLastMoveToIndex from SkPath to SkPathRef
authorrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 10 Feb 2014 13:51:32 +0000 (13:51 +0000)
committerrobertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 10 Feb 2014 13:51:32 +0000 (13:51 +0000)
https://codereview.chromium.org/146913002/

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

include/core/SkPath.h
include/core/SkPathRef.h
src/core/SkPath.cpp
src/core/SkPathRef.cpp

index dd7a672cdd4456862fa3d2715177c18a20c35668..2d63bb23531a26a7c6fa0dbdc70df0ccf02ec52a 100644 (file)
@@ -962,7 +962,6 @@ private:
 
     SkAutoTUnref<SkPathRef> fPathRef;
 
-    int                 fLastMoveToIndex;
     uint8_t             fFillType;
     mutable uint8_t     fConvexity;
     mutable uint8_t     fDirection;
@@ -998,7 +997,10 @@ private:
     //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
     // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
     //
-    inline void injectMoveToIfNeeded();
+    void injectMoveToIfNeeded() {
+        SkPathRef::Editor ed(&fPathRef);
+        ed.injectMoveToIfNeeded();
+    }
 
     inline bool hasOnlyMoveTos() const;
 
index 8802714243090edc3fa207a58ffebce8bc356a4d..3c663f7f7d98bc147036aa55c307d38b8687afb6 100644 (file)
@@ -104,6 +104,13 @@ public:
 
         void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); }
 
+        // In some cases we need to inject a leading moveTo before we add points
+        // for lineTo, quadTo, conicTo, cubicTo
+        // 
+        // SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
+        // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
+        void injectMoveToIfNeeded() { fPathRef->injectMoveToIfNeeded(); }
+
     private:
         SkPathRef* fPathRef;
     };
@@ -254,6 +261,9 @@ public:
     uint32_t genID() const;
 
 private:
+    // flag to require a moveTo if we begin with something else, like lineTo etc.
+    static const int kINITIAL_LASTMOVETOINDEX_VALUE = ~0;
+
     enum SerializationOffsets {
         kIsFinite_SerializationShift = 25,  // requires 1 bit
         kIsOval_SerializationShift = 24,    // requires 1 bit
@@ -261,6 +271,7 @@ private:
     };
 
     SkPathRef() {
+        fLastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE;
         fBoundsIsDirty = true;    // this also invalidates fIsFinite
         fPointCnt = 0;
         fVerbCnt = 0;
@@ -348,6 +359,8 @@ private:
         SkDEBUGCODE(this->validate();)
     }
 
+    void injectMoveToIfNeeded();
+
     /**
      * Increases the verb count by numVbs and point count by the required amount.
      * The new points are uninitialized. All the new verbs are set to the specified
@@ -433,6 +446,7 @@ private:
     };
 
     mutable SkRect      fBounds;
+    int                 fLastMoveToIndex;
     uint8_t             fSegmentMask;
     mutable uint8_t     fBoundsIsDirty;
     mutable SkBool8     fIsFinite;    // only meaningful if bounds are valid
index 04c807b64415492aa4b3ee617391a22c2800ea78..d3f493d46f8fa0afaa876663bd1646a63b45a4f5 100644 (file)
@@ -122,9 +122,6 @@ private:
 
 ////////////////////////////////////////////////////////////////////////////
 
-// flag to require a moveTo if we begin with something else, like lineTo etc.
-#define INITIAL_LASTMOVETOINDEX_VALUE   ~0
-
 SkPath::SkPath()
     : fPathRef(SkPathRef::CreateEmpty())
 #ifdef SK_BUILD_FOR_ANDROID
@@ -136,7 +133,6 @@ SkPath::SkPath()
 
 void SkPath::resetFields() {
     //fPathRef is assumed to have been emptied by the caller.
-    fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
     fFillType = kWinding_FillType;
     fConvexity = kUnknown_Convexity;
     fDirection = kUnknown_Direction;
@@ -174,7 +170,6 @@ SkPath& SkPath::operator=(const SkPath& that) {
 
 void SkPath::copyFields(const SkPath& that) {
     //fPathRef is assumed to have been set by the caller.
-    fLastMoveToIndex = that.fLastMoveToIndex;
     fFillType        = that.fFillType;
     fConvexity       = that.fConvexity;
     fDirection       = that.fDirection;
@@ -192,7 +187,6 @@ void SkPath::swap(SkPath& that) {
 
     if (this != &that) {
         fPathRef.swap(&that.fPathRef);
-        SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
         SkTSwap<uint8_t>(fFillType, that.fFillType);
         SkTSwap<uint8_t>(fConvexity, that.fConvexity);
         SkTSwap<uint8_t>(fDirection, that.fDirection);
@@ -667,9 +661,6 @@ void SkPath::moveTo(SkScalar x, SkScalar y) {
 
     SkPathRef::Editor ed(&fPathRef);
 
-    // remember our index
-    fLastMoveToIndex = fPathRef->countPoints();
-
     ed.growForVerb(kMove_Verb)->set(x, y);
 }
 
@@ -679,26 +670,11 @@ void SkPath::rMoveTo(SkScalar x, SkScalar y) {
     this->moveTo(pt.fX + x, pt.fY + y);
 }
 
-void SkPath::injectMoveToIfNeeded() {
-    if (fLastMoveToIndex < 0) {
-        SkScalar x, y;
-        if (fPathRef->countVerbs() == 0) {
-            x = y = 0;
-        } else {
-            const SkPoint& pt = fPathRef->atPoint(~fLastMoveToIndex);
-            x = pt.fX;
-            y = pt.fY;
-        }
-        this->moveTo(x, y);
-    }
-}
-
 void SkPath::lineTo(SkScalar x, SkScalar y) {
     SkDEBUGCODE(this->validate();)
 
-    this->injectMoveToIfNeeded();
-
     SkPathRef::Editor ed(&fPathRef);
+    ed.injectMoveToIfNeeded();
     ed.growForVerb(kLine_Verb)->set(x, y);
 
     DIRTY_AFTER_EDIT;
@@ -714,9 +690,8 @@ void SkPath::rLineTo(SkScalar x, SkScalar y) {
 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
     SkDEBUGCODE(this->validate();)
 
-    this->injectMoveToIfNeeded();
-
     SkPathRef::Editor ed(&fPathRef);
+    ed.injectMoveToIfNeeded();
     SkPoint* pts = ed.growForVerb(kQuad_Verb);
     pts[0].set(x1, y1);
     pts[1].set(x2, y2);
@@ -744,9 +719,8 @@ void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
     } else {
         SkDEBUGCODE(this->validate();)
 
-        this->injectMoveToIfNeeded();
-
         SkPathRef::Editor ed(&fPathRef);
+        ed.injectMoveToIfNeeded();
         SkPoint* pts = ed.growForVerb(kConic_Verb, w);
         pts[0].set(x1, y1);
         pts[1].set(x2, y2);
@@ -767,9 +741,8 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                      SkScalar x3, SkScalar y3) {
     SkDEBUGCODE(this->validate();)
 
-    this->injectMoveToIfNeeded();
-
     SkPathRef::Editor ed(&fPathRef);
+    ed.injectMoveToIfNeeded();
     SkPoint* pts = ed.growForVerb(kCubic_Verb);
     pts[0].set(x1, y1);
     pts[1].set(x2, y2);
@@ -810,15 +783,6 @@ void SkPath::close() {
                 break;
         }
     }
-
-    // signal that we need a moveTo to follow us (unless we're done)
-#if 0
-    if (fLastMoveToIndex >= 0) {
-        fLastMoveToIndex = ~fLastMoveToIndex;
-    }
-#else
-    fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
-#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -860,8 +824,6 @@ void SkPath::addPoly(const SkPoint pts[], int count, bool close) {
         return;
     }
 
-    fLastMoveToIndex = fPathRef->countPoints();
-
     // +close makes room for the extra kClose_Verb
     SkPathRef::Editor ed(&fPathRef, count+close, count);
 
@@ -1358,8 +1320,6 @@ void SkPath::addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle
     SkDEBUGCODE(this->validate();)
     SkASSERT(count & 1);
 
-    fLastMoveToIndex = fPathRef->countPoints();
-
     SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count);
 
     ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY);
index 161eb804199ba2f7e96d03d4a926819bdaaf99f1..1272cf25942ff1080e8a71e21bd8eb86f8d501b6 100644 (file)
@@ -154,6 +154,7 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
 void SkPathRef::Rewind(SkAutoTUnref<SkPathRef>* pathRef) {
     if ((*pathRef)->unique()) {
         SkDEBUGCODE((*pathRef)->validate();)
+        (*pathRef)->fLastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE;
         (*pathRef)->fBoundsIsDirty = true;  // this also invalidates fIsFinite
         (*pathRef)->fVerbCnt = 0;
         (*pathRef)->fPointCnt = 0;
@@ -276,6 +277,20 @@ void SkPathRef::copy(const SkPathRef& ref,
     SkDEBUGCODE(this->validate();)
 }
 
+void SkPathRef::injectMoveToIfNeeded() {
+    if (fLastMoveToIndex < 0) {
+        SkScalar x, y;
+        if (this->countVerbs() == 0) {
+            x = y = 0;
+        } else {
+            const SkPoint& pt = this->atPoint(~fLastMoveToIndex);
+            x = pt.fX;
+            y = pt.fY;
+        }
+        this->growForVerb(SkPath::kMove_Verb, 0)->set(x, y);
+    }
+}
+
 SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
                                         int numVbs,
                                         SkScalar** weights) {
@@ -284,11 +299,16 @@ SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
     // future this will appear to have been a fluke...
     static const unsigned int kMIN_COUNT_FOR_MEMSET_TO_BE_FAST = 16;
 
+    if (numVbs <= 0) {
+        return NULL;
+    }
+
     SkDEBUGCODE(this->validate();)
     int pCnt;
     bool dirtyAfterEdit = true;
     switch (verb) {
         case SkPath::kMove_Verb:
+            fLastMoveToIndex = fPointCnt + numVbs - 1;
             pCnt = numVbs;
             dirtyAfterEdit = false;
             break;
@@ -310,6 +330,8 @@ SkPoint* SkPathRef::growForRepeatedVerb(int /*SkPath::Verb*/ verb,
             break;
         case SkPath::kClose_Verb:
             SkDEBUGFAIL("growForRepeatedVerb called for kClose_Verb");
+            // signal that we need a moveTo to follow us (unless we're done)
+            fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
             pCnt = 0;
             dirtyAfterEdit = false;
             break;
@@ -361,6 +383,8 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
     bool dirtyAfterEdit = true;
     switch (verb) {
         case SkPath::kMove_Verb:
+            // remember our index
+            fLastMoveToIndex = fPointCnt;
             pCnt = 1;
             dirtyAfterEdit = false;
             break;
@@ -381,6 +405,8 @@ SkPoint* SkPathRef::growForVerb(int /* SkPath::Verb*/ verb, SkScalar weight) {
             pCnt = 3;
             break;
         case SkPath::kClose_Verb:
+            // signal that we need a moveTo to follow us (unless we're done)
+            fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
             pCnt = 0;
             dirtyAfterEdit = false;
             break;
@@ -460,23 +486,34 @@ void SkPathRef::validate() const {
 
 #ifdef SK_DEBUG_PATH
     uint32_t mask = 0;
+    int lastMoveToIndex = kINITIAL_LASTMOVETOINDEX_VALUE;
+    int pointCnt = 0;
     for (int i = 0; i < fVerbCnt; ++i) {
         switch (fVerbs[~i]) {
             case SkPath::kMove_Verb:
+                lastMoveToIndex = pointCnt;
+                ++pointCnt;
                 break;
             case SkPath::kLine_Verb:
                 mask |= SkPath::kLine_SegmentMask;
+                ++pointCnt;
                 break;
             case SkPath::kQuad_Verb:
                 mask |= SkPath::kQuad_SegmentMask;
+                pointCnt += 2;
                 break;
             case SkPath::kConic_Verb:
                 mask |= SkPath::kConic_SegmentMask;
+                pointCnt += 2;
                 break;
             case SkPath::kCubic_Verb:
                 mask |= SkPath::kCubic_SegmentMask;
+                pointCnt += 3;
                 break;
             case SkPath::kClose_Verb:
+                if (lastMoveToIndex >= 0) {
+                    lastMoveToIndex = ~lastMoveToIndex;
+                }
                 break;
             case SkPath::kDone_Verb:
                 SkDEBUGFAIL("Done verb shouldn't be recorded.");
@@ -487,6 +524,8 @@ void SkPathRef::validate() const {
         }
     }
     SkASSERT(mask == fSegmentMask);
+    SkASSERT(lastMoveToIndex == fLastMoveToIndex);
+    SkASSERT(pointCnt == fPointCnt);
 #endif // SK_DEBUG_PATH
 }
 #endif