add pipecanvas

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2201323003

Review-Url: https://codereview.chromium.org/2201323003
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index b6b9cde..4c930c2 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -34,6 +34,9 @@
 #include "SkWindow.h"
 #include "sk_tool_utils.h"
 
+#include "SkReadBuffer.h"
+#include "SkStream.h"
+
 #if SK_SUPPORT_GPU
 #   include "gl/GrGLInterface.h"
 #   include "gl/GrGLUtil.h"
@@ -540,6 +543,26 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+class SampleTFSerializer : public SkTypefaceSerializer {
+public:
+    sk_sp<SkData> serialize(SkTypeface* tf) override {
+        tf->ref();
+        return SkData::MakeWithCopy(&tf, sizeof(tf));
+    }
+};
+
+class SampleTFDeserializer : public SkTypefaceDeserializer {
+public:
+    sk_sp<SkTypeface> deserialize(const void* data, size_t size) override {
+        SkASSERT(sizeof(SkTypeface*) == size);
+        SkTypeface* tf;
+        memcpy(&tf, data, size);
+        return sk_sp<SkTypeface>(tf);   // this was ref'd in SampleTFSerializer
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
 enum TilingMode {
     kNo_Tiling,
     kAbs_128x128_Tiling,
@@ -696,11 +719,14 @@
 #endif
 
 #include "SkTaskGroup.h"
+#include "SkForceLinking.h"
 
 SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager)
     : INHERITED(hwnd)
     , fDevManager(nullptr) {
 
+    SkForceLinking(false);
+
     SkCommandLineFlags::Parse(argc, argv);
 
     fCurrIndex = -1;
@@ -851,6 +877,11 @@
     fSaveToPdf = false;
     fSaveToSKP = false;
 
+    if (true) {
+        fPipeSerializer.setTypefaceSerializer(new SampleTFSerializer);
+        fPipeDeserializer.setTypefaceDeserializer(new SampleTFDeserializer);
+    }
+
     int sinkID = this->getSinkID();
     fAppMenu = new SkOSMenu;
     fAppMenu->setTitle("Global Settings");
@@ -1304,7 +1335,10 @@
     } else if (fSaveToSKP) {
         canvas = fRecorder.beginRecording(9999, 9999, nullptr, 0);
     } else if (fUsePicture) {
-        canvas = fRecorder.beginRecording(9999, 9999, nullptr, 0);
+        fPipeStream.reset(new SkDynamicMemoryWStream);
+        canvas = fPipeSerializer.beginWrite(SkRect::MakeWH(this->width(), this->height()),
+                                            fPipeStream.get());
+//        canvas = fRecorder.beginRecording(9999, 9999, nullptr, 0);
     } else {
         canvas = this->INHERITED::beforeChildren(canvas);
     }
@@ -1366,17 +1400,15 @@
     }
 
     if (fUsePicture) {
-        sk_sp<SkPicture> picture(fRecorder.finishRecordingAsPicture());
-
-        // serialize/deserialize?
-        if (false) {
-            SkDynamicMemoryWStream wstream;
-            picture->serialize(&wstream);
-
-            SkAutoTDelete<SkStream> rstream(wstream.detachAsStream());
-            picture = SkPicture::MakeFromStream(rstream);
+        if (true) {
+            fPipeSerializer.endWrite();
+            sk_sp<SkData> data(fPipeStream->detachAsData());
+            fPipeDeserializer.playback(data->data(), data->size(), orig);
+            fPipeStream.reset();
+        } else {
+            sk_sp<SkPicture> picture(fRecorder.finishRecordingAsPicture());
+            orig->drawPicture(picture.get());
         }
-        orig->drawPicture(picture.get());
     }
 
     // Do this after presentGL and other finishing, rather than in afterChild