[sksg] Trim down sksg::Matrix size

Matrix nodes are most often not composed outside of the DAG.  Split into
a basic Matrix class and a (private) ComposedMatrix subclass.

TBR=
Bug: skia:8340
Change-Id: I3c182e10ae5fa20d0639c1031523dba3956b75bb
Reviewed-on: https://skia-review.googlesource.com/153883
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/sksg/include/SkSGTransform.h b/modules/sksg/include/SkSGTransform.h
index c878773..790373b 100644
--- a/modules/sksg/include/SkSGTransform.h
+++ b/modules/sksg/include/SkSGTransform.h
@@ -21,25 +21,19 @@
  */
 class Matrix : public Node {
 public:
-    static sk_sp<Matrix> Make(const SkMatrix& m, sk_sp<Matrix> parent = nullptr) {
-        return sk_sp<Matrix>(new Matrix(m, std::move(parent)));
-    }
+    static sk_sp<Matrix> Make(const SkMatrix& m, sk_sp<Matrix> parent = nullptr);
 
-    ~Matrix() override;
+    SG_ATTRIBUTE(Matrix, SkMatrix, fMatrix)
 
-    SG_ATTRIBUTE(Matrix, SkMatrix, fLocalMatrix)
-
-    const SkMatrix& getTotalMatrix() const { return fTotalMatrix; }
+    virtual const SkMatrix& getTotalMatrix() const;
 
 protected:
-    Matrix(const SkMatrix&, sk_sp<Matrix>);
+    explicit Matrix(const SkMatrix&);
 
     SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
 
 private:
-    sk_sp<Matrix> fParent;
-    SkMatrix      fLocalMatrix,
-                  fTotalMatrix; // cached during revalidation
+    SkMatrix fMatrix;
 
     typedef Node INHERITED;
 };
diff --git a/modules/sksg/src/SkSGTransform.cpp b/modules/sksg/src/SkSGTransform.cpp
index 41b6a35..76b180a 100644
--- a/modules/sksg/src/SkSGTransform.cpp
+++ b/modules/sksg/src/SkSGTransform.cpp
@@ -10,30 +10,57 @@
 #include "SkCanvas.h"
 
 namespace sksg {
-// Matrix nodes don't generate damage on their own, but via aggregation ancestor Transform nodes.
-Matrix::Matrix(const SkMatrix& m, sk_sp<Matrix> parent)
-    : INHERITED(kBubbleDamage_Trait)
-    , fParent(std::move(parent))
-    , fLocalMatrix(m) {
-    if (fParent) {
+namespace {
+
+class ComposedMatrix final : public Matrix {
+public:
+    ComposedMatrix(const SkMatrix& m, sk_sp<Matrix> parent)
+        : INHERITED(m)
+        , fParent(std::move(parent)) {
+        SkASSERT(fParent);
         this->observeInval(fParent);
     }
-}
 
-Matrix::~Matrix() {
-    if (fParent) {
+    ~ComposedMatrix() override {
         this->unobserveInval(fParent);
     }
-}
 
-SkRect Matrix::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
-    fTotalMatrix = fLocalMatrix;
-
-    if (fParent) {
-        fParent->revalidate(ic, ctm);
-        fTotalMatrix.postConcat(fParent->getTotalMatrix());
+    const SkMatrix& getTotalMatrix() const override {
+        SkASSERT(!this->hasInval());
+        return fTotalMatrix;
     }
 
+protected:
+    SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
+        fParent->revalidate(ic, ctm);
+        fTotalMatrix = SkMatrix::Concat(fParent->getTotalMatrix(), this->getMatrix());
+        return SkRect::MakeEmpty();
+    }
+
+private:
+    const sk_sp<Matrix> fParent;
+    SkMatrix            fTotalMatrix; // cached during revalidation.
+
+    using INHERITED = Matrix;
+};
+
+} // namespace
+
+sk_sp<Matrix> Matrix::Make(const SkMatrix& m, sk_sp<Matrix> parent) {
+    return sk_sp<Matrix>(parent ? new ComposedMatrix(m, std::move(parent))
+                                : new Matrix(m));
+}
+
+// Matrix nodes don't generate damage on their own, but via aggregation ancestor Transform nodes.
+Matrix::Matrix(const SkMatrix& m)
+    : INHERITED(kBubbleDamage_Trait)
+    , fMatrix(m) {}
+
+const SkMatrix& Matrix::getTotalMatrix() const {
+    return fMatrix;
+}
+
+SkRect Matrix::onRevalidate(InvalidationController*, const SkMatrix&) {
     return SkRect::MakeEmpty();
 }