Dedup SkPaths by gen-ID when going to .skp

We're all set up to serialize and deserialze paths by an integer ID,
but we're just not deduping any paths (every path gets a new ID).

This turns on deduping.  This should mean the number of paths in a
deserialized SkPicture are the same as when it was recorded.

No diffs:
https://gold.skia.org/search2?issue=1409373011&unt=true&query=source_type%3Dgm&master=false

BUG=skia:4527

Review URL: https://codereview.chromium.org/1409373011
diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp
index 9ed98cf..4391be4 100644
--- a/src/core/SkPictureData.cpp
+++ b/src/core/SkPictureData.cpp
@@ -46,7 +46,13 @@
 
     fBitmaps = record.fBitmaps;
     fPaints  = record.fPaints;
-    fPaths   = record.fPaths;
+
+    fPaths.reset(record.fPaths.count());
+    record.fPaths.foreach([this](const SkPath& path, int n) {
+        // These indices are logically 1-based, but we need to serialize them
+        // 0-based to keep the deserializing SkPictureData::getPath() working.
+        fPaths[n-1] = path;
+    });
 
     this->initForPlayback();
 
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 28561c7..2b56b74 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -587,7 +587,7 @@
         size += sizeof(*src);   // + rect
     }
     size += sizeof(dst);        // + rect
-    
+
     size_t initialOffset = this->addDraw(DRAW_IMAGE_RECT, &size);
     SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_RECT, size)
              == fWriter.bytesWritten());
@@ -603,7 +603,7 @@
                                       const SkPaint* paint) {
     // id + paint_index + image_index + center + dst
     size_t size = 3 * kUInt32Size + sizeof(SkIRect) + sizeof(SkRect);
-    
+
     size_t initialOffset = this->addDraw(DRAW_IMAGE_NINE, &size);
     SkASSERT(initialOffset+get_paint_offset(DRAW_IMAGE_NINE, size) == fWriter.bytesWritten());
     this->addPaintPtr(paint);
@@ -863,7 +863,7 @@
         flags |= DRAW_ATLAS_HAS_CULL;
         size += sizeof(SkRect);
     }
-    
+
     size_t initialOffset = this->addDraw(DRAW_ATLAS, &size);
     SkASSERT(initialOffset+get_paint_offset(DRAW_ATLAS, size) == fWriter.bytesWritten());
     this->addPaintPtr(paint);
@@ -987,8 +987,12 @@
 }
 
 int SkPictureRecord::addPathToHeap(const SkPath& path) {
-    fPaths.push_back(path);
-    return fPaths.count();
+    if (int* n = fPaths.find(path)) {
+        return *n;
+    }
+    int n = fPaths.count() + 1;  // 0 is reserved for null / error.
+    fPaths.set(path, n);
+    return n;
 }
 
 void SkPictureRecord::addPath(const SkPath& path) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index c305f10..7e21fab 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -14,6 +14,7 @@
 #include "SkPictureData.h"
 #include "SkTArray.h"
 #include "SkTDArray.h"
+#include "SkTHash.h"
 #include "SkWriter32.h"
 
 // These macros help with packing and unpacking a single byte value and
@@ -226,7 +227,11 @@
 
     SkTArray<SkBitmap> fBitmaps;
     SkTArray<SkPaint>  fPaints;
-    SkTArray<SkPath>   fPaths;
+
+    struct PathHash {
+        uint32_t operator()(const SkPath& p) { return p.getGenerationID(); }
+    };
+    SkTHashMap<SkPath, int, PathHash> fPaths;
 
     SkWriter32 fWriter;