change path serialization version to 4

New format should be much simpler:
- only store public data (e.g. points, verbs, filltype)
- deserialize just uses public APIs

Refactor reading code to manage different (older) versions, to make
it clear (hopefully) what we can delete when we can abandon version
3 support.

Bug: skia:
Change-Id: I30465f891cba3f044ae1cb2c13c04f04fdc9da78
Reviewed-on: https://skia-review.googlesource.com/109160
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 95fa37f..279615d 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -16,6 +16,7 @@
 #include "SkPathRef.h"
 #include "SkPointPriv.h"
 #include "SkRRect.h"
+#include "SkSafeMath.h"
 
 static float poly_eval(float A, float B, float C, float t) {
     return (A * t + B) * t + C;
@@ -2073,150 +2074,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-/*
-    Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]]
-*/
-
-size_t SkPath::writeToMemoryAsRRect(int32_t packedHeader, void* storage) const {
-    SkRect oval;
-    SkRRect rrect;
-    bool isCCW;
-    unsigned start;
-    if (fPathRef->isOval(&oval, &isCCW, &start)) {
-        rrect.setOval(oval);
-        // Convert to rrect start indices.
-        start *= 2;
-    } else if (!fPathRef->isRRect(&rrect, &isCCW, &start)) {
-        return false;
-    }
-    if (!storage) {
-        // packed header, rrect, start index.
-        return sizeof(int32_t) + SkRRect::kSizeInMemory + sizeof(int32_t);
-    }
-
-    SkWBuffer buffer(storage);
-    // Rewrite header's first direction based on rrect direction.
-    uint8_t firstDir = isCCW ? SkPathPriv::kCCW_FirstDirection : SkPathPriv::kCW_FirstDirection;
-    packedHeader &= ~(0x3 << kDirection_SerializationShift);
-    packedHeader |= firstDir << kDirection_SerializationShift;
-    packedHeader |= SerializationType::kRRect << kType_SerializationShift;
-    buffer.write32(packedHeader);
-    rrect.writeToBuffer(&buffer);
-    buffer.write32(SkToS32(start));
-    buffer.padToAlign4();
-    return buffer.pos();
-}
-
-size_t SkPath::writeToMemory(void* storage) const {
-    SkDEBUGCODE(this->validate();)
-
-    int32_t packed = (fConvexity << kConvexity_SerializationShift) |
-                     (fFillType << kFillType_SerializationShift) |
-                     (fFirstDirection << kDirection_SerializationShift) |
-                     (fIsVolatile << kIsVolatile_SerializationShift) |
-                     kCurrent_Version;
-    if (size_t bytes = this->writeToMemoryAsRRect(packed, storage)) {
-        return bytes;
-    }
-
-    SkWBuffer   buffer(storage);
-
-    static_assert(0 == SerializationType::kGeneral, "packed has zero in type bits");
-    if (nullptr == storage) {
-        // packed header, pathref, start index
-        const int byteCount = sizeof(int32_t) * 2 + fPathRef->writeSize();
-        return SkAlign4(byteCount);
-    }
-    buffer.write32(packed);
-    buffer.write32(fLastMoveToIndex);
-
-    fPathRef->writeToBuffer(&buffer);
-
-    buffer.padToAlign4();
-    return buffer.pos();
-}
-
-sk_sp<SkData> SkPath::serialize() const {
-    size_t size = this->writeToMemory(nullptr);
-    sk_sp<SkData> data = SkData::MakeUninitialized(size);
-    this->writeToMemory(data->writable_data());
-    return data;
-}
-
-size_t SkPath::readFromMemory(const void* storage, size_t length) {
-    SkRBuffer buffer(storage, length);
-
-    int32_t packed;
-    if (!buffer.readS32(&packed)) {
-        return 0;
-    }
-
-    unsigned version = packed & 0xFF;
-    uint8_t dir = (packed >> kDirection_SerializationShift) & 0x3;
-    FillType fillType = static_cast<FillType>((packed >> kFillType_SerializationShift) & 0x3);
-    if (version >= kPathPrivTypeEnumVersion) {
-        SerializationType type =
-                static_cast<SerializationType>((packed >> kType_SerializationShift) & 0xF);
-        switch (type) {
-            case SerializationType::kRRect: {
-                Direction rrectDir;
-                SkRRect rrect;
-                int32_t start;
-                switch (dir) {
-                    case SkPathPriv::kCW_FirstDirection:
-                        rrectDir = kCW_Direction;
-                        break;
-                    case SkPathPriv::kCCW_FirstDirection:
-                        rrectDir = kCCW_Direction;
-                        break;
-                    default:
-                        return 0;
-                }
-                if (!rrect.readFromBuffer(&buffer)) {
-                    return 0;
-                }
-                if (!buffer.readS32(&start) || start != SkTPin(start, 0, 7)) {
-                    return 0;
-                }
-                this->reset();
-                this->addRRect(rrect, rrectDir, SkToUInt(start));
-                this->setFillType(fillType);
-                buffer.skipToAlign4();
-                return buffer.pos();
-            }
-            case SerializationType::kGeneral:
-                // Fall through to general path deserialization
-                break;
-            default:
-                return 0;
-        }
-    }
-    if (version >= kPathPrivLastMoveToIndex_Version && !buffer.readS32(&fLastMoveToIndex)) {
-        return 0;
-    }
-
-    // These are written into the serialized data but we no longer use them in the deserialized
-    // path. If convexity is corrupted it may cause the GPU backend to make incorrect
-    // rendering choices, possibly crashing. We set them to unknown so that they'll be recomputed if
-    // requested.
-    fConvexity = kUnknown_Convexity;
-    fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
-
-    fFillType = fillType;
-    fIsVolatile = (packed >> kIsVolatile_SerializationShift) & 0x1;
-    SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
-    if (!pathRef) {
-        return 0;
-    }
-
-    fPathRef.reset(pathRef);
-    SkDEBUGCODE(this->validate();)
-    buffer.skipToAlign4();
-    return buffer.pos();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 #include "SkString.h"
 #include "SkStringUtils.h"
 #include "SkStream.h"