Implement all SkCanvas overrides that SkPictureRecord does.

Primarily this is for isDrawingToLayer().  drawData() and onNewSurface() are
for completeness.

BUG=409138
R=robertphillips@google.com, mtklein@google.com, reed@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/545613002
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 67402dd..3845a5c 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -108,6 +108,7 @@
 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint));
 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
                                 r.xmode.get(), r.indices, r.indexCount, r.paint));
+DRAW(DrawData, drawData(r.data, r.length));
 #undef DRAW
 
 
@@ -212,6 +213,7 @@
     void trackBounds(const BeginCommentGroup&) { this->pushControl(); }
     void trackBounds(const AddComment&)        { this->pushControl(); }
     void trackBounds(const EndCommentGroup&)   { this->pushControl(); }
+    void trackBounds(const DrawData&)          { this->pushControl(); }
 
     // For all other ops, we can calculate and store the bounds directly now.
     template <typename T> void trackBounds(const T& op) {
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index df3e1d8..86578a5 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -11,7 +11,9 @@
 
 // SkCanvas will fail in mysterious ways if it doesn't know the real width and height.
 SkRecorder::SkRecorder(SkRecord* record, int width, int height)
-    : SkCanvas(width, height), fRecord(record) {}
+    : SkCanvas(width, height)
+    , fRecord(record)
+    , fSaveLayerCount(0) {}
 
 void SkRecorder::forgetRecord() {
     fRecord = NULL;
@@ -229,17 +231,25 @@
 }
 
 void SkRecorder::willSave() {
+    fSaveIsSaveLayer.push(false);
     APPEND(Save);
 }
 
 SkCanvas::SaveLayerStrategy SkRecorder::willSaveLayer(const SkRect* bounds,
                                                       const SkPaint* paint,
                                                       SkCanvas::SaveFlags flags) {
+    fSaveLayerCount++;
+    fSaveIsSaveLayer.push(true);
     APPEND(SaveLayer, this->copy(bounds), this->copy(paint), flags);
     return SkCanvas::kNoLayer_SaveLayerStrategy;
 }
 
 void SkRecorder::didRestore() {
+    SkBool8 saveLayer;
+    fSaveIsSaveLayer.pop(&saveLayer);
+    if (saveLayer) {
+        fSaveLayerCount--;
+    }
     APPEND(Restore, this->devBounds(), this->getTotalMatrix());
 }
 
@@ -295,3 +305,11 @@
 void SkRecorder::endCommentGroup() {
     APPEND(EndCommentGroup);
 }
+
+bool SkRecorder::isDrawingToLayer() const {
+    return fSaveLayerCount > 0;
+}
+
+void SkRecorder::drawData(const void* data, size_t length) {
+    APPEND(DrawData, copy((const char*)data), length);
+}
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 683d29b..db57eb0 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -11,6 +11,7 @@
 #include "SkCanvas.h"
 #include "SkRecord.h"
 #include "SkRecords.h"
+#include "SkTDArray.h"
 
 // SkRecorder provides an SkCanvas interface for recording into an SkRecord.
 
@@ -64,6 +65,7 @@
 
     void willSave() SK_OVERRIDE;
     SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SkCanvas::SaveFlags) SK_OVERRIDE;
+    void willRestore() SK_OVERRIDE {}
     void didRestore() SK_OVERRIDE;
 
     void didConcat(const SkMatrix&) SK_OVERRIDE;
@@ -110,6 +112,10 @@
     void beginCommentGroup(const char*) SK_OVERRIDE;
     void addComment(const char*, const char*) SK_OVERRIDE;
     void endCommentGroup() SK_OVERRIDE;
+    void drawData(const void*, size_t) SK_OVERRIDE;
+
+    bool isDrawingToLayer() const SK_OVERRIDE;
+    SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE { return NULL; }
 
 private:
     template <typename T>
@@ -125,6 +131,9 @@
     }
 
     SkRecord* fRecord;
+
+    int fSaveLayerCount;
+    SkTDArray<SkBool8> fSaveIsSaveLayer;
 };
 
 #endif//SkRecorder_DEFINED
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index bd65fc5..c1c5596 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -58,7 +58,8 @@
     M(DrawRRect)                                                    \
     M(DrawRect)                                                     \
     M(DrawSprite)                                                   \
-    M(DrawTextBlob)                                                     \
+    M(DrawTextBlob)                                                 \
+    M(DrawData)                                                     \
     M(DrawVertices)
 
 // Defines SkRecords::Type, an enum of all record types.
@@ -270,6 +271,8 @@
                         SkPath, path,
                         Optional<SkMatrix>, matrix);
 
+RECORD2(DrawData, PODArray<char>, data, size_t, length);
+
 // This guy is so ugly we just write it manually.
 struct DrawVertices {
     static const Type kType = DrawVertices_Type;
diff --git a/tests/RecorderTest.cpp b/tests/RecorderTest.cpp
index 21a897c..aced54f 100644
--- a/tests/RecorderTest.cpp
+++ b/tests/RecorderTest.cpp
@@ -68,6 +68,20 @@
     REPORTER_ASSERT(r, 1 == tally.count<SkRecords::EndCommentGroup>());
 }
 
+// DrawData is similar to comment groups.  It doesn't affect drawing, but
+// it's a pass-through we provide to the client.  Again, a simple reg. test.
+DEF_TEST(Recorder_DrawData, r) {
+    SkRecord record;
+    SkRecorder recorder(&record, 100, 100);
+
+    const char* data = "This sure is some data, eh?";
+    recorder.drawData(data, strlen(data));
+
+    Tally tally;
+    tally.apply(record);
+    REPORTER_ASSERT(r, 1 == tally.count<SkRecords::DrawData>());
+}
+
 // Regression test for leaking refs held by optional arguments.
 DEF_TEST(Recorder_RefLeaking, r) {
     // We use SaveLayer to test:
@@ -109,3 +123,30 @@
     // the recorder destructor should have released us (back to unique)
     REPORTER_ASSERT(r, pic->unique());
 }
+
+DEF_TEST(Recorder_IsDrawingToLayer, r) {
+    SkRecord record;
+    SkRecorder recorder(&record, 100, 100);
+
+    // We'll save, saveLayer, save, and saveLayer, then restore them all,
+    // checking that isDrawingToLayer() is correct at each step.
+
+    REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
+    recorder.save();
+        REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
+        recorder.saveLayer(NULL, NULL);
+            REPORTER_ASSERT(r, recorder.isDrawingToLayer());
+            recorder.save();
+                REPORTER_ASSERT(r, recorder.isDrawingToLayer());
+                recorder.saveLayer(NULL, NULL);
+                    REPORTER_ASSERT(r, recorder.isDrawingToLayer());
+                recorder.restore();
+                REPORTER_ASSERT(r, recorder.isDrawingToLayer());
+            recorder.restore();
+            REPORTER_ASSERT(r, recorder.isDrawingToLayer());
+        recorder.restore();
+        REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
+    recorder.restore();
+    REPORTER_ASSERT(r, !recorder.isDrawingToLayer());
+}
+