aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/sksg/effects
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-01-04 21:11:55 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-05 03:29:04 +0000
commit18eafd922d911606dfe991efad8ec5eaafbc2704 (patch)
treeba4bfefd307c84a0045986b3d08d930f0d9380e5 /experimental/sksg/effects
parent98992ae3b7e06aa8de48d91b5b12dd3a5e8ea54f (diff)
[skotty, sksg] Add layer transform inheritance support
Split the matrix component of sksg::Transform into its own, free-floating, chainable node. Update the composite transform animator to target matrix nodes instead of transform nodes. Update the layer transform attachment logic to follow "parent" references, and build matrix inheritance chains on the fly. TBR= Change-Id: I017e5e462274c2cc210730e057b3ea2e7de5c0cb Reviewed-on: https://skia-review.googlesource.com/90803 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'experimental/sksg/effects')
-rw-r--r--experimental/sksg/effects/SkSGTransform.cpp51
-rw-r--r--experimental/sksg/effects/SkSGTransform.h50
2 files changed, 89 insertions, 12 deletions
diff --git a/experimental/sksg/effects/SkSGTransform.cpp b/experimental/sksg/effects/SkSGTransform.cpp
index dc31623db2..1ea1e619a8 100644
--- a/experimental/sksg/effects/SkSGTransform.cpp
+++ b/experimental/sksg/effects/SkSGTransform.cpp
@@ -11,21 +11,60 @@
namespace sksg {
-Transform::Transform(sk_sp<RenderNode> child, const SkMatrix& matrix)
+Matrix::Matrix(const SkMatrix& m, sk_sp<Matrix> parent)
+ : fParent(std::move(parent))
+ , fLocalMatrix(m) {
+ if (fParent) {
+ fParent->addInvalReceiver(this);
+ }
+}
+
+Matrix::~Matrix() {
+ if (fParent) {
+ fParent->removeInvalReceiver(this);
+ }
+}
+
+Node::RevalidationResult Matrix::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
+ fTotalMatrix = fLocalMatrix;
+
+ if (fParent) {
+ fParent->revalidate(ic, ctm);
+ fTotalMatrix.postConcat(fParent->getTotalMatrix());
+ }
+
+ // A free-floating matrix contributes no damage.
+ return { SkRect::MakeEmpty(), Damage::kBlockSelf };
+}
+
+Transform::Transform(sk_sp<RenderNode> child, sk_sp<Matrix> matrix)
: INHERITED(std::move(child))
- , fMatrix(matrix) {}
+ , fMatrix(std::move(matrix)) {
+ fMatrix->addInvalReceiver(this);
+}
+
+Transform::~Transform() {
+ fMatrix->removeInvalReceiver(this);
+}
void Transform::onRender(SkCanvas* canvas) const {
- SkAutoCanvasRestore acr(canvas, !fMatrix.isIdentity());
- canvas->concat(fMatrix);
+ const auto& m = fMatrix->getTotalMatrix();
+ SkAutoCanvasRestore acr(canvas, !m.isIdentity());
+ canvas->concat(m);
this->INHERITED::onRender(canvas);
}
Node::RevalidationResult Transform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
SkASSERT(this->hasInval());
- auto result = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, fMatrix));
- fMatrix.mapRect(&result.fBounds);
+ // We don't care about matrix reval results, but we do care whether it was invalidated.
+ const auto localDamage = fMatrix->hasInval() ? Damage::kForceSelf : Damage::kDefault;
+ fMatrix->revalidate(ic, ctm);
+
+ const auto& m = fMatrix->getTotalMatrix();
+ auto result = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
+ m.mapRect(&result.fBounds);
+ result.fDamage = localDamage;
return result;
}
diff --git a/experimental/sksg/effects/SkSGTransform.h b/experimental/sksg/effects/SkSGTransform.h
index 8a97a679ed..0d11739f30 100644
--- a/experimental/sksg/effects/SkSGTransform.h
+++ b/experimental/sksg/effects/SkSGTransform.h
@@ -15,25 +15,63 @@
namespace sksg {
/**
- * Concrete Effect node, wrapping an SkMatrix.
+ * Concrete node, wrapping an SkMatrix, with an optional parent Matrix (to allow chaining):
+ *
+ * M' = parent x M
+ */
+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)));
+ }
+
+ ~Matrix() override;
+
+ SG_ATTRIBUTE(Matrix, SkMatrix, fLocalMatrix)
+
+ const SkMatrix& getTotalMatrix() const { return fTotalMatrix; }
+
+protected:
+ explicit Matrix(const SkMatrix&, sk_sp<Matrix>);
+
+ RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override;
+
+private:
+ sk_sp<Matrix> fParent;
+ SkMatrix fLocalMatrix,
+ fTotalMatrix; // cached during revalidation
+
+ typedef Node INHERITED;
+};
+
+/**
+ * Concrete Effect node, binding a Matrix to a RenderNode.
*/
class Transform : public EffectNode {
public:
- static sk_sp<Transform> Make(sk_sp<RenderNode> child, const SkMatrix& matrix) {
- return sk_sp<Transform>(new Transform(std::move(child), matrix));
+ static sk_sp<Transform> Make(sk_sp<RenderNode> child, sk_sp<Matrix> matrix) {
+ return child && matrix
+ ? sk_sp<Transform>(new Transform(std::move(child), std::move(matrix)))
+ : nullptr;
}
- SG_ATTRIBUTE(Matrix, SkMatrix, fMatrix)
+ static sk_sp<Transform> Make(sk_sp<RenderNode> child, const SkMatrix& m) {
+ return Make(std::move(child), Matrix::Make(m));
+ }
+
+ ~Transform() override;
+
+ const sk_sp<Matrix>& getMatrix() const { return fMatrix; }
protected:
- Transform(sk_sp<RenderNode>, const SkMatrix&);
+ Transform(sk_sp<RenderNode>, sk_sp<Matrix>);
void onRender(SkCanvas*) const override;
RevalidationResult onRevalidate(InvalidationController*, const SkMatrix&) override;
private:
- SkMatrix fMatrix;
+ sk_sp<Matrix> fMatrix;
typedef EffectNode INHERITED;
};