Added the framework for having canvas/recorder/picture record depth_set's.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2127233002

Committed: https://skia.googlesource.com/skia/+/6d3fb898d5f73a82e36f11c712a633c3921ed518
Committed: https://skia.googlesource.com/skia/+/1185d90c785f743364cc9113d7007a59af07470c
Review-Url: https://codereview.chromium.org/2127233002
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 97aa3c7..35a8d1c 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -451,6 +451,13 @@
     */
     void resetMatrix();
 
+    /** Add the specified translation to the current draw depth of the canvas.
+        @param z    The distance to translate in Z.
+                    Negative into screen, positive out of screen.
+                    Without translation, the draw depth defaults to 0.
+    */
+    void translateZ(SkScalar z);
+
     /**
      *  Modify the current clip with the specified rectangle.
      *  @param rect The rect to combine with the current clip
@@ -1260,6 +1267,10 @@
     void temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds);
 
 protected:
+    /** Returns the current (cumulative) draw depth of the canvas.
+      */
+    SkScalar getZ() const;
+
     /** After calling saveLayer(), there can be any number of devices that make
         up the top-most drawing area. LayerIter can be used to iterate through
         those devices. Note that the iterator is only valid until the next API
@@ -1325,6 +1336,7 @@
     virtual void didRestore() {}
     virtual void didConcat(const SkMatrix&) {}
     virtual void didSetMatrix(const SkMatrix&) {}
+    virtual void didTranslateZ(SkScalar) {}
 
     virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
     virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
diff --git a/include/private/SkRecords.h b/include/private/SkRecords.h
index 9ec2d21..35adca2 100644
--- a/include/private/SkRecords.h
+++ b/include/private/SkRecords.h
@@ -47,6 +47,7 @@
     M(Save)                                                         \
     M(SaveLayer)                                                    \
     M(SetMatrix)                                                    \
+    M(TranslateZ)                                                   \
     M(Concat)                                                       \
     M(ClipPath)                                                     \
     M(ClipRRect)                                                    \
@@ -218,6 +219,8 @@
 RECORD(Concat, 0,
         TypedMatrix matrix);
 
+RECORD(TranslateZ, 0, SkScalar z);
+
 struct RegionOpAndAA {
     RegionOpAndAA() {}
     RegionOpAndAA(SkRegion::Op op, bool aa) : op(op), aa(aa) {}
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index f893a62..0bd3851 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -294,17 +294,22 @@
     SkMatrix        fMatrix;
     int             fDeferredSaveCount;
 
+    // This is the current cumulative depth (aggregate of all done translateZ calls)
+    SkScalar        fCurDrawDepth;
+
     MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
         fFilter     = nullptr;
         fLayer      = nullptr;
         fTopLayer   = nullptr;
         fMatrix.reset();
         fDeferredSaveCount = 0;
+        fCurDrawDepth      = 0;
 
         // don't bother initializing fNext
         inc_rec();
     }
-    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
+    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix),
+                               fCurDrawDepth(prev.fCurDrawDepth) {
         fFilter = SkSafeRef(prev.fFilter);
         fLayer = nullptr;
         fTopLayer = prev.fTopLayer;
@@ -1539,6 +1544,16 @@
     this->setMatrix(SkMatrix::I());
 }
 
+void SkCanvas::translateZ(SkScalar z) {
+    this->checkForDeferredSave();
+    this->fMCRec->fCurDrawDepth += z;
+    this->didTranslateZ(z);
+}
+
+SkScalar SkCanvas::getZ() const {
+    return this->fMCRec->fCurDrawDepth;
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 3546fb2..125d4e9 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -81,7 +81,9 @@
     DRAW_DRAWABLE_MATRIX,
     DRAW_TEXT_RSXFORM,
 
-    LAST_DRAWTYPE_ENUM = DRAW_DRAWABLE_MATRIX,
+    TRANSLATE_Z,
+
+    LAST_DRAWTYPE_ENUM = TRANSLATE_Z
 };
 
 // In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 6b89304..60c4fe8 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -129,8 +129,8 @@
             reader->skip(size - 4);
         } break;
         case CLIP_PATH: {
-            const SkPath& path = fPictureData->getPath(reader);
-            uint32_t packed = reader->readInt();
+            const SkPath& path = fPictureData->getPath(reader); 
+            uint32_t packed = reader->readInt(); 
             SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed);
             bool doAA = ClipParams_unpackDoAA(packed);
             size_t offsetToRestore = reader->readInt();
@@ -616,6 +616,10 @@
             SkScalar dy = reader->readScalar();
             canvas->translate(dx, dy);
         } break;
+        case TRANSLATE_Z: {
+            SkScalar dz = reader->readScalar();
+            canvas->translateZ(dz);
+        }
         default:
             SkASSERTF(false, "Unknown draw type: %d", op);
     }
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 17ed1aa..f2a0fd8 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -218,6 +218,16 @@
     this->INHERITED::didSetMatrix(matrix);
 }
 
+void SkPictureRecord::didTranslateZ(SkScalar z) {
+    this->validate(fWriter.bytesWritten(), 0);
+    // op + scalar
+    size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
+    size_t initialOffset = this->addDraw(TRANSLATE_Z, &size);
+    this->addScalar(z);
+    this->validate(initialOffset, size);
+    this->INHERITED::didTranslateZ(z);
+}
+
 static bool regionOpExpands(SkRegion::Op op) {
     switch (op) {
         case SkRegion::kUnion_Op:
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index bdb6609..276dd3e 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -159,6 +159,8 @@
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
 
+    void didTranslateZ(SkScalar) override;
+
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
 
     void onDrawText(const void* text, size_t, SkScalar x, SkScalar y, const SkPaint&) override;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index eb02729..02d07d5 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -86,6 +86,8 @@
 DRAW(ClipRect, clipRect(r.rect, r.opAA.op, r.opAA.aa));
 DRAW(ClipRegion, clipRegion(r.region, r.op));
 
+DRAW(TranslateZ, SkCanvas::translateZ(r.z));
+
 DRAW(DrawBitmap, drawBitmap(r.bitmap.shallowCopy(), r.left, r.top, r.paint));
 DRAW(DrawBitmapNine, drawBitmapNine(r.bitmap.shallowCopy(), r.center, r.dst, r.paint));
 DRAW(DrawBitmapRect,
@@ -287,6 +289,8 @@
     void trackBounds(const ClipPath&)          { this->pushControl(); }
     void trackBounds(const ClipRegion&)        { this->pushControl(); }
 
+    void trackBounds(const TranslateZ&)              { this->pushControl(); }
+
     // For all other ops, we can calculate and store the bounds directly now.
     template <typename T> void trackBounds(const T& op) {
         fBounds[fCurrentOp] = this->bounds(op);
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 19cb663..c7869bb 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -369,6 +369,10 @@
     APPEND(SetMatrix, matrix);
 }
 
+void SkRecorder::didTranslateZ(SkScalar z)  {
+    APPEND(TranslateZ, z);
+}
+
 void SkRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
     INHERITED(onClipRect, rect, op, edgeStyle);
     SkRecords::RegionOpAndAA opAA(op, kSoft_ClipEdgeStyle == edgeStyle);
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 3cf0be9..66a0067 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -60,6 +60,7 @@
 
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
+    void didTranslateZ(SkScalar) override;
 
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
     void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 82e065f..1e5f9e1 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -779,6 +779,45 @@
     canvas.restore();
 }
 
+#define SHADOW_TEST_CANVAS_CONST 10
+
+class SkShadowTestCanvas : public SkPaintFilterCanvas {
+public:
+
+    SkShadowTestCanvas(int x, int y, skiatest::Reporter* reporter)
+        : INHERITED(x,y)
+        , fReporter(reporter) {}
+
+    bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const {
+        REPORTER_ASSERT(this->fReporter, this->getZ() == SHADOW_TEST_CANVAS_CONST);
+
+        return true;
+    }
+
+    void testUpdateDepth(skiatest::Reporter *reporter) {
+        // set some depths (with picture enabled), then check them as they get set
+
+        REPORTER_ASSERT(reporter, this->getZ() == 0);
+        this->translateZ(-10);
+        REPORTER_ASSERT(reporter, this->getZ() == -10);
+
+        this->save();
+        this->translateZ(20);
+        REPORTER_ASSERT(reporter, this->getZ() == 10);
+
+        this->restore();
+        REPORTER_ASSERT(reporter, this->getZ() == -10);
+
+        this->translateZ(13.14f);
+        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(this->getZ(), 3.14f));
+    }
+
+private:
+    skiatest::Reporter* fReporter;
+
+    typedef SkPaintFilterCanvas INHERITED;
+};
+
 namespace {
 
 class MockFilterCanvas : public SkPaintFilterCanvas {
@@ -812,6 +851,20 @@
     REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix());
     REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2));
     REPORTER_ASSERT(reporter, clip1 == clip2);
+
+    SkShadowTestCanvas* tCanvas = new SkShadowTestCanvas(100,100, reporter);
+    tCanvas->testUpdateDepth(reporter);
+    delete(tCanvas);
+
+    SkPictureRecorder recorder;
+    SkShadowTestCanvas *tSCanvas = new SkShadowTestCanvas(100, 100, reporter);
+    SkCanvas *tPCanvas = recorder.beginRecording(SkRect::MakeIWH(100, 100));
+
+    tPCanvas->translateZ(SHADOW_TEST_CANVAS_CONST);
+    sk_sp<SkPicture> pic = recorder.finishRecordingAsPicture();
+    tSCanvas->drawPicture(pic);
+
+    delete(tSCanvas);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/tools/debugger/SkDebugCanvas.cpp b/tools/debugger/SkDebugCanvas.cpp
index b80eeea..ae934a1 100644
--- a/tools/debugger/SkDebugCanvas.cpp
+++ b/tools/debugger/SkDebugCanvas.cpp
@@ -690,6 +690,11 @@
     this->INHERITED::didSetMatrix(matrix);
 }
 
+void SkDebugCanvas::didTranslateZ(SkScalar z) {
+    this->addDrawCommand(new SkTranslateZCommand(z));
+    this->INHERITED::didTranslateZ(z);
+}
+
 void SkDebugCanvas::toggleCommand(int index, bool toggle) {
     SkASSERT(index < fCommandVector.count());
     fCommandVector[index]->setVisible(toggle);
diff --git a/tools/debugger/SkDebugCanvas.h b/tools/debugger/SkDebugCanvas.h
index e8d9113..4264f55 100644
--- a/tools/debugger/SkDebugCanvas.h
+++ b/tools/debugger/SkDebugCanvas.h
@@ -194,6 +194,8 @@
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
 
+    void didTranslateZ(SkScalar) override;
+
     void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
     void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index ecd6a70..8f42cb7 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -28,6 +28,7 @@
 #define SKDEBUGCANVAS_ATTRIBUTE_COMMAND           "command"
 #define SKDEBUGCANVAS_ATTRIBUTE_VISIBLE           "visible"
 #define SKDEBUGCANVAS_ATTRIBUTE_MATRIX            "matrix"
+#define SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS    "drawDepthTranslation"
 #define SKDEBUGCANVAS_ATTRIBUTE_COORDS            "coords"
 #define SKDEBUGCANVAS_ATTRIBUTE_BOUNDS            "bounds"
 #define SKDEBUGCANVAS_ATTRIBUTE_PAINT             "paint"
@@ -211,6 +212,7 @@
         case kSave_OpType: return "Save";
         case kSaveLayer_OpType: return "SaveLayer";
         case kSetMatrix_OpType: return "SetMatrix";
+        case kTranslateZ_OpType: return "TranslateZ";
         default:
             SkDebugf("OpType error 0x%08x\n", type);
             SkASSERT(0);
@@ -268,6 +270,8 @@
         INSTALL_FACTORY(Save);
         INSTALL_FACTORY(SaveLayer);
         INSTALL_FACTORY(SetMatrix);
+
+        INSTALL_FACTORY(TranslateZ);
     }
     SkString name = SkString(command[SKDEBUGCANVAS_ATTRIBUTE_COMMAND].asCString());
     FROM_JSON* factory = factories.find(name);
@@ -470,6 +474,11 @@
     return result;
 }
 
+Json::Value SkDrawCommand::MakeJsonScalar(SkScalar z) {
+    Json::Value result(z);
+    return result;
+}
+
 Json::Value SkDrawCommand::MakeJsonPath(const SkPath& path) {
     Json::Value result(Json::objectValue);
     switch (path.getFillType()) {
@@ -1482,6 +1491,11 @@
     result->set9(values);
 }
 
+static void extract_json_scalar(Json::Value& scalar, SkScalar* result) {
+    SkScalar value = scalar.asFloat();
+    *result = value;
+}
+
 static void extract_json_path(Json::Value& path, SkPath* result) {
     const char* fillType = path[SKDEBUGCANVAS_ATTRIBUTE_FILLTYPE].asCString();
     if (!strcmp(fillType, SKDEBUGCANVAS_FILLTYPE_WINDING)) {
@@ -3295,3 +3309,26 @@
     extract_json_matrix(command[SKDEBUGCANVAS_ATTRIBUTE_MATRIX], &matrix);
     return new SkSetMatrixCommand(matrix);
 }
+
+SkTranslateZCommand::SkTranslateZCommand(SkScalar z)
+    : INHERITED(kTranslateZ_OpType) {
+    fZTranslate = z;
+    fInfo.push(SkObjectParser::ScalarToString(fZTranslate, "drawDepthTranslation"));
+}
+
+void SkTranslateZCommand::execute(SkCanvas* canvas) const {
+    canvas->translateZ(fZTranslate);
+}
+
+Json::Value SkTranslateZCommand::toJSON(UrlDataManager& urlDataManager) const {
+    Json::Value result = INHERITED::toJSON(urlDataManager);
+    result[SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS] = MakeJsonScalar(fZTranslate);
+    return result;
+}
+
+SkTranslateZCommand* SkTranslateZCommand::fromJSON(Json::Value& command,
+                                       UrlDataManager& urlDataManager) {
+    SkScalar z;
+    extract_json_scalar(command[SKDEBUGCANVAS_ATTRIBUTE_DRAWDEPTHTRANS], &z);
+    return new SkTranslateZCommand(z);
+}
diff --git a/tools/debugger/SkDrawCommand.h b/tools/debugger/SkDrawCommand.h
index dc639ec..a7e6c73 100644
--- a/tools/debugger/SkDrawCommand.h
+++ b/tools/debugger/SkDrawCommand.h
@@ -56,8 +56,9 @@
         kSave_OpType,
         kSaveLayer_OpType,
         kSetMatrix_OpType,
+        kTranslateZ_OpType,
 
-        kLast_OpType = kSetMatrix_OpType
+        kLast_OpType = kTranslateZ_OpType
     };
 
     static const int kOpTypeCount = kLast_OpType + 1;
@@ -125,6 +126,7 @@
     static Json::Value MakeJsonRect(const SkRect& rect);
     static Json::Value MakeJsonIRect(const SkIRect&);
     static Json::Value MakeJsonMatrix(const SkMatrix&);
+    static Json::Value MakeJsonScalar(SkScalar);
     static Json::Value MakeJsonPath(const SkPath& path);
     static Json::Value MakeJsonRegion(const SkRegion& region);
     static Json::Value MakeJsonPaint(const SkPaint& paint, UrlDataManager& urlDataManager);
@@ -731,4 +733,16 @@
     typedef SkDrawCommand INHERITED;
 };
 
+class SkTranslateZCommand : public SkDrawCommand {
+public:
+    SkTranslateZCommand(SkScalar);
+    void execute(SkCanvas* canvas) const override;
+    Json::Value toJSON(UrlDataManager& urlDataManager) const override;
+    static SkTranslateZCommand* fromJSON(Json::Value& command, UrlDataManager& urlDataManager);
+
+private:
+    SkScalar fZTranslate;
+
+    typedef SkDrawCommand INHERITED;
+};
 #endif