bump picture version since SkPath has changed (conics)

enable conics in SkPath

git-svn-id: http://skia.googlecode.com/svn/trunk@9370 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 95cd9fe..7485c0b 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -369,6 +369,7 @@
                 SkASSERT(moveCnt);
                 break;
             case kQuad_Verb:
+            case kConic_Verb:
                 SkASSERT(moveCnt);
                 nextPt = 2;
                 break;
@@ -558,12 +559,16 @@
                 break;
             }
             case kQuad_Verb:
+            case kConic_Verb:
             case kCubic_Verb:
                 return false; // quadratic, cubic not allowed
             case kMove_Verb:
                 last = *pts++;
                 closedOrMoved = true;
                 break;
+            default:
+                SkASSERT(!"unexpected verb");
+                break;
         }
         *currVerb += 1;
         lastDirection = nextDirection;
@@ -805,15 +810,15 @@
 
 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
     SkDEBUGCODE(this->validate();)
-
+    
     this->injectMoveToIfNeeded();
-
+    
     SkPathRef::Editor ed(&fPathRef);
     SkPoint* pts = ed.growForVerb(kQuad_Verb);
     pts[0].set(x1, y1);
     pts[1].set(x2, y2);
     fSegmentMask |= kQuad_SegmentMask;
-
+    
     GEN_ID_INC;
     DIRTY_AFTER_EDIT;
 }
@@ -824,6 +829,39 @@
     this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
 }
 
+void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                     SkScalar w) {
+    // check for <= 0 or NaN with this test
+    if (!(w > 0)) {
+        this->lineTo(x2, y2);
+    } else if (!SkScalarIsFinite(w)) {
+        this->lineTo(x1, y1);
+        this->lineTo(x2, y2);
+    } else if (SK_Scalar1 == w) {
+        this->quadTo(x1, y1, x2, y2);
+    } else {
+        SkDEBUGCODE(this->validate();)
+        
+        this->injectMoveToIfNeeded();
+        
+        SkPathRef::Editor ed(&fPathRef);
+        SkPoint* pts = ed.growForConic(w);
+        pts[0].set(x1, y1);
+        pts[1].set(x2, y2);
+        fSegmentMask |= kConic_SegmentMask;
+        
+        GEN_ID_INC;
+        DIRTY_AFTER_EDIT;
+    }
+}
+
+void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+                      SkScalar w) {
+    SkPoint pt;
+    this->getLastPt(&pt);
+    this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
+}
+
 void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
                      SkScalar x3, SkScalar y3) {
     SkDEBUGCODE(this->validate();)
@@ -857,6 +895,7 @@
         switch (fPathRef->atVerb(count - 1)) {
             case kLine_Verb:
             case kQuad_Verb:
+            case kConic_Verb:
             case kCubic_Verb:
             case kMove_Verb: {
                 SkPathRef::Editor ed(&fPathRef);
@@ -864,9 +903,12 @@
                 GEN_ID_INC;
                 break;
             }
-            default:
+            case kClose_Verb:
                 // don't add a close if it's the first verb or a repeat
                 break;
+            default:
+                SkASSERT(!"unexpected verb");
+                break;
         }
     }
 
@@ -1430,6 +1472,10 @@
                 proc(matrix, &pts[1], &pts[1], 2);
                 this->quadTo(pts[1], pts[2]);
                 break;
+            case kConic_Verb:
+                proc(matrix, &pts[1], &pts[1], 2);
+                this->conicTo(pts[1], pts[2], iter.conicWeight());
+                break;
             case kCubic_Verb:
                 proc(matrix, &pts[1], &pts[1], 3);
                 this->cubicTo(pts[1], pts[2], pts[3]);
@@ -1445,14 +1491,20 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static const uint8_t gPtsInVerb[] = {
-    1,  // kMove
-    1,  // kLine
-    2,  // kQuad
-    3,  // kCubic
-    0,  // kClose
-    0   // kDone
-};
+static int pts_in_verb(unsigned verb) {
+    static const uint8_t gPtsInVerb[] = {
+        1,  // kMove
+        1,  // kLine
+        2,  // kQuad
+        2,  // kConic
+        3,  // kCubic
+        0,  // kClose
+        0   // kDone
+    };
+
+    SkASSERT(verb < SK_ARRAY_COUNT(gPtsInVerb));
+    return gPtsInVerb[verb];
+}
 
 // ignore the initial moveto, and stop when the 1st contour ends
 void SkPath::pathTo(const SkPath& path) {
@@ -1469,6 +1521,7 @@
     const uint8_t* verbs = path.fPathRef->verbs();
     // skip the initial moveTo
     const SkPoint*  pts = path.fPathRef->points() + 1;
+    const SkScalar* conicWeight = path.fPathRef->conicWeights();
 
     SkASSERT(verbs[~0] == kMove_Verb);
     for (i = 1; i < vcount; i++) {
@@ -1479,13 +1532,16 @@
             case kQuad_Verb:
                 this->quadTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY);
                 break;
+            case kConic_Verb:
+                this->conicTo(pts[0], pts[1], *conicWeight++);
+                break;
             case kCubic_Verb:
                 this->cubicTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
                 break;
             case kClose_Verb:
                 return;
         }
-        pts += gPtsInVerb[verbs[~i]];
+        pts += pts_in_verb(verbs[~i]);
     }
 }
 
@@ -1503,14 +1559,17 @@
 
     const uint8_t*  verbs = path.fPathRef->verbs();
     const SkPoint*  pts = path.fPathRef->points();
+    const SkScalar* conicWeights = path.fPathRef->conicWeights();
 
     SkASSERT(verbs[~0] == kMove_Verb);
     for (i = 1; i < vcount; ++i) {
-        int n = gPtsInVerb[verbs[~i]];
+        unsigned v = verbs[~i];
+        int n = pts_in_verb(v);
         if (n == 0) {
             break;
         }
         pts += n;
+        conicWeights += (SkPath::kConic_Verb == v);
     }
 
     while (--i > 0) {
@@ -1521,6 +1580,9 @@
             case kQuad_Verb:
                 this->quadTo(pts[-1].fX, pts[-1].fY, pts[-2].fX, pts[-2].fY);
                 break;
+            case kConic_Verb:
+                this->conicTo(pts[-1], pts[-2], *--conicWeights);
+                break;
             case kCubic_Verb:
                 this->cubicTo(pts[-1].fX, pts[-1].fY, pts[-2].fX, pts[-2].fY,
                               pts[-3].fX, pts[-3].fY);
@@ -1529,7 +1591,7 @@
                 SkDEBUGFAIL("bad verb");
                 break;
         }
-        pts -= gPtsInVerb[verbs[~i]];
+        pts -= pts_in_verb(verbs[~i]);
     }
 }
 
@@ -1540,6 +1602,7 @@
     // we will iterator through src's verbs backwards
     const uint8_t* verbs = src.fPathRef->verbsMemBegin(); // points at the last verb
     const uint8_t* verbsEnd = src.fPathRef->verbs(); // points just past the first verb
+    const SkScalar* conicWeights = src.fPathRef->conicWeightsEnd();
 
     fIsOval = false;
 
@@ -1547,7 +1610,7 @@
     bool needClose = false;
     while (verbs < verbsEnd) {
         uint8_t v = *(verbs++);
-        int n = gPtsInVerb[v];
+        int n = pts_in_verb(v);
 
         if (needMove) {
             --pts;
@@ -1570,6 +1633,9 @@
             case kQuad_Verb:
                 this->quadTo(pts[1], pts[0]);
                 break;
+            case kConic_Verb:
+                this->conicTo(pts[1], pts[0], *--conicWeights);
+                break;
             case kCubic_Verb:
                 this->cubicTo(pts[2], pts[1], pts[0]);
                 break;
@@ -1644,6 +1710,10 @@
                 case kQuad_Verb:
                     subdivide_quad_to(&tmp, pts);
                     break;
+                case kConic_Verb:
+                    SkASSERT(!"TODO: compute new weight");
+                    tmp.conicTo(pts[1], pts[2], iter.conicWeight());
+                    break;
                 case kCubic_Verb:
                     subdivide_cubic_to(&tmp, pts);
                     break;
@@ -1741,6 +1811,7 @@
 SkPath::Iter::Iter() {
 #ifdef SK_DEBUG
     fPts = NULL;
+    fConicWeights = NULL;
     fMoveTo.fX = fMoveTo.fY = fLastPt.fX = fLastPt.fY = 0;
     fForceClose = fCloseLine = false;
     fSegmentState = kEmptyContour_SegmentState;
@@ -1759,6 +1830,7 @@
     fPts = path.fPathRef->points();
     fVerbs = path.fPathRef->verbs();
     fVerbStop = path.fPathRef->verbsMemBegin();
+    fConicWeights = path.fPathRef->conicWeights() - 1; // begin one behind
     fLastPt.fX = fLastPt.fY = 0;
     fMoveTo.fX = fMoveTo.fY = 0;
     fForceClose = SkToU8(forceClose);
@@ -1870,6 +1942,7 @@
                 fPts++;
                 break;
 
+            case kConic_Verb:
             case kQuad_Verb:
                 if (!IsQuadDegenerate(lastPt, fPts[0], fPts[1])) {
                     if (lastMoveVerb) {
@@ -1882,6 +1955,7 @@
                 // Ignore this line and continue
                 fVerbs--;
                 fPts += 2;
+                fConicWeights += (kConic_Verb == verb);
                 break;
 
             case kCubic_Verb:
@@ -1951,6 +2025,9 @@
             fCloseLine = false;
             srcPts += 1;
             break;
+        case kConic_Verb:
+            fConicWeights += 1;
+            // fall-through
         case kQuad_Verb:
             pts[0] = this->cons_moveTo();
             memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint));
@@ -1983,6 +2060,7 @@
 SkPath::RawIter::RawIter() {
 #ifdef SK_DEBUG
     fPts = NULL;
+    fConicWeights = NULL;
     fMoveTo.fX = fMoveTo.fY = fLastPt.fX = fLastPt.fY = 0;
 #endif
     // need to init enough to make next() harmlessly return kDone_Verb
@@ -1998,6 +2076,7 @@
     fPts = path.fPathRef->points();
     fVerbs = path.fPathRef->verbs();
     fVerbStop = path.fPathRef->verbsMemBegin();
+    fConicWeights = path.fPathRef->conicWeights() - 1; // begin one behind
     fMoveTo.fX = fMoveTo.fY = 0;
     fLastPt.fX = fLastPt.fY = 0;
 }
@@ -2025,6 +2104,9 @@
             fLastPt = srcPts[0];
             srcPts += 1;
             break;
+        case kConic_Verb:
+            fConicWeights += 1;
+            // fall-through
         case kQuad_Verb:
             pts[0] = fLastPt;
             memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint));
@@ -2057,22 +2139,12 @@
 
     if (NULL == storage) {
         const int byteCount = sizeof(int32_t)
-#if NEW_PICTURE_FORMAT
                       + fPathRef->writeSize()
-#else
-                      + 2 * sizeof(int32_t)
-                      + sizeof(SkPoint) * fPathRef->countPoints()
-                      + sizeof(uint8_t) * fPathRef->countVerbs()
-#endif
                       + sizeof(SkRect);
         return SkAlign4(byteCount);
     }
 
     SkWBuffer   buffer(storage);
-#if !NEW_PICTURE_FORMAT
-    buffer.write32(fPathRef->countPoints());
-    buffer.write32(fPathRef->countVerbs());
-#endif
 
     // Call getBounds() to ensure (as a side-effect) that fBounds
     // and fIsFinite are computed.
@@ -2098,24 +2170,16 @@
 
 uint32_t SkPath::readFromMemory(const void* storage) {
     SkRBuffer   buffer(storage);
-#if !NEW_PICTURE_FORMAT
-    int32_t pcount = buffer.readS32();
-    int32_t vcount = buffer.readS32();
-#endif
 
     uint32_t packed = buffer.readS32();
     fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
     fIsOval = (packed >> kIsOval_SerializationShift) & 1;
     fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
     fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
-    fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0x7;
+    fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
     fDirection = (packed >> kDirection_SerializationShift) & 0x3;
 
-#if NEW_PICTURE_FORMAT
     fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer));
-#else
-    fPathRef.reset(SkPathRef::CreateFromBuffer(vcount, pcount, &buffer));
-#endif
 
     buffer.read(&fBounds, sizeof(fBounds));
     fBoundsIsDirty = false;
@@ -2142,7 +2206,7 @@
 }
 
 static void append_params(SkString* str, const char label[], const SkPoint pts[],
-                          int count) {
+                          int count, SkScalar conicWeight = -1) {
     str->append(label);
     str->append("(");
 
@@ -2155,6 +2219,10 @@
             str->append(", ");
         }
     }
+    if (conicWeight >= 0) {
+        str->append(", ");
+        append_scalar(str, conicWeight);
+    }
     str->append(");\n");
 }
 
@@ -2180,6 +2248,9 @@
             case kQuad_Verb:
                 append_params(&builder, "path.quadTo", &pts[1], 2);
                 break;
+            case kConic_Verb:
+                append_params(&builder, "path.conicTo", &pts[1], 2, iter.conicWeight());
+                break;
             case kCubic_Verb:
                 append_params(&builder, "path.cubicTo", &pts[1], 3);
                 break;
@@ -2239,6 +2310,9 @@
             case kQuad_Verb:
                 mask |= kQuad_SegmentMask;
                 break;
+            case kConic_Verb:
+                mask |= kConic_SegmentMask;
+                break;
             case kCubic_Verb:
                 mask |= kCubic_SegmentMask;
             case kMove_Verb:  // these verbs aren't included in the segment mask.
@@ -2379,6 +2453,7 @@
                 break;
             case kLine_Verb: count = 1; break;
             case kQuad_Verb: count = 2; break;
+            case kConic_Verb: count = 2; break;
             case kCubic_Verb: count = 3; break;
             case kClose_Verb:
                 state.close();
@@ -2423,6 +2498,7 @@
     const SkPoint* fCurrPt;
     const uint8_t* fCurrVerb;
     const uint8_t* fStopVerbs;
+    const SkScalar* fCurrConicWeight;
     bool fDone;
     SkDEBUGCODE(int fContourCounter;)
 };
@@ -2432,6 +2508,7 @@
     fDone = false;
     fCurrPt = pathRef.points();
     fCurrVerb = pathRef.verbs();
+    fCurrConicWeight = pathRef.conicWeights();
     fCurrPtCount = 0;
     SkDEBUGCODE(fContourCounter = 0;)
     this->next();
@@ -2459,13 +2536,19 @@
             case SkPath::kLine_Verb:
                 ptCount += 1;
                 break;
+            case SkPath::kConic_Verb:
+                fCurrConicWeight += 1;
+                // fall-through
             case SkPath::kQuad_Verb:
                 ptCount += 2;
                 break;
             case SkPath::kCubic_Verb:
                 ptCount += 3;
                 break;
-            default:    // kClose_Verb, just keep going
+            case SkPath::kClose_Verb:
+                break;
+            default:
+                SkASSERT(!"unexpected verb");
                 break;
         }
     }
@@ -2957,13 +3040,16 @@
             case SkPath::kQuad_Verb:
                 w += winding_quad(pts, x, y);
                 break;
+            case SkPath::kConic_Verb:
+                SkASSERT(0);
+                break;
             case SkPath::kCubic_Verb:
                 w += winding_cubic(pts, x, y);
                 break;
             case SkPath::kDone_Verb:
                 done = true;
                 break;
-        }
+       }
     } while (!done);
 
     switch (this->getFillType()) {