aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-01-29 16:31:14 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-29 21:57:44 +0000
commit38ea40eb750596c75b8ffb5c8f94bcb84b94a7c3 (patch)
tree966c9416f99c784dd84dcc31d91fe3bf790bfd11 /experimental
parenteed48b66eb083f01638d1a2126a2b49f1e2ddc8f (diff)
[skottie] Layer clip support
TBR= Change-Id: Ibf65efc69031f8f6e19f4f28cccab29c357e704d Reviewed-on: https://skia-review.googlesource.com/101540 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'experimental')
-rw-r--r--experimental/skottie/Skottie.cpp12
-rw-r--r--experimental/sksg/SkSGGeometryNode.cpp5
-rw-r--r--experimental/sksg/SkSGGeometryNode.h3
-rw-r--r--experimental/sksg/effects/SkSGClipEffect.cpp50
-rw-r--r--experimental/sksg/effects/SkSGClipEffect.h50
-rw-r--r--experimental/sksg/geometry/SkSGGeometryTransform.cpp12
-rw-r--r--experimental/sksg/geometry/SkSGGeometryTransform.h4
-rw-r--r--experimental/sksg/geometry/SkSGMerge.cpp4
-rw-r--r--experimental/sksg/geometry/SkSGMerge.h1
-rw-r--r--experimental/sksg/geometry/SkSGPath.cpp4
-rw-r--r--experimental/sksg/geometry/SkSGPath.h1
-rw-r--r--experimental/sksg/geometry/SkSGRect.cpp8
-rw-r--r--experimental/sksg/geometry/SkSGRect.h2
-rw-r--r--experimental/sksg/geometry/SkSGTrimEffect.cpp4
-rw-r--r--experimental/sksg/geometry/SkSGTrimEffect.h1
15 files changed, 156 insertions, 5 deletions
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp
index 532cc8d36d..1ac8f7de3d 100644
--- a/experimental/skottie/Skottie.cpp
+++ b/experimental/skottie/Skottie.cpp
@@ -19,6 +19,7 @@
#include "SkPaint.h"
#include "SkParse.h"
#include "SkPoint.h"
+#include "SkSGClipEffect.h"
#include "SkSGColor.h"
#include "SkSGDraw.h"
#include "SkSGGeometryTransform.h"
@@ -944,12 +945,23 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer,
// Layer content.
auto layer = gLayerAttachers[type](jlayer, &local_ctx, &time_bias, &time_scale);
+
+ // Clip layers with explicit dimensions.
+ float w, h;
+ if (Parse(jlayer["w"], &w) && Parse(jlayer["h"], &h)) {
+ layer = sksg::ClipEffect::Make(std::move(layer),
+ sksg::Rect::Make(SkRect::MakeWH(w, h)),
+ true);
+ }
+
// Optional layer mask.
layer = AttachMask(jlayer["masksProperties"], &local_ctx, std::move(layer));
+
// Optional layer transform.
if (auto layerMatrix = layerCtx->AttachLayerMatrix(jlayer)) {
layer = sksg::Transform::Make(std::move(layer), std::move(layerMatrix));
}
+
// Optional layer opacity.
layer = AttachOpacity(jlayer["ks"], &local_ctx, std::move(layer));
diff --git a/experimental/sksg/SkSGGeometryNode.cpp b/experimental/sksg/SkSGGeometryNode.cpp
index 98022ad811..6b78c488b7 100644
--- a/experimental/sksg/SkSGGeometryNode.cpp
+++ b/experimental/sksg/SkSGGeometryNode.cpp
@@ -14,6 +14,11 @@ namespace sksg {
// Geometry nodes don't generate damage on their own, but via their aggregation ancestor Draw nodes.
GeometryNode::GeometryNode() : INHERITED(kBubbleDamage_Trait) {}
+void GeometryNode::clip(SkCanvas* canvas, bool aa) const {
+ SkASSERT(!this->hasInval());
+ this->onClip(canvas, aa);
+}
+
void GeometryNode::draw(SkCanvas* canvas, const SkPaint& paint) const {
SkASSERT(!this->hasInval());
this->onDraw(canvas, paint);
diff --git a/experimental/sksg/SkSGGeometryNode.h b/experimental/sksg/SkSGGeometryNode.h
index b436d27570..7ce3aa9b79 100644
--- a/experimental/sksg/SkSGGeometryNode.h
+++ b/experimental/sksg/SkSGGeometryNode.h
@@ -24,6 +24,7 @@ namespace sksg {
*/
class GeometryNode : public Node {
public:
+ void clip(SkCanvas*, bool antiAlias) const;
void draw(SkCanvas*, const SkPaint&) const;
SkPath asPath() const;
@@ -31,6 +32,8 @@ public:
protected:
GeometryNode();
+ virtual void onClip(SkCanvas*, bool antiAlias) const = 0;
+
virtual void onDraw(SkCanvas*, const SkPaint&) const = 0;
virtual SkPath onAsPath() const = 0;
diff --git a/experimental/sksg/effects/SkSGClipEffect.cpp b/experimental/sksg/effects/SkSGClipEffect.cpp
new file mode 100644
index 0000000000..b2d68fc8cf
--- /dev/null
+++ b/experimental/sksg/effects/SkSGClipEffect.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkSGClipEffect.h"
+
+#include "SkCanvas.h"
+#include "SkPath.h"
+#include "SkSGGeometryNode.h"
+
+namespace sksg {
+
+ClipEffect::ClipEffect(sk_sp<RenderNode> child, sk_sp<GeometryNode> clip, bool aa)
+ : INHERITED(std::move(child))
+ , fClipNode(std::move(clip))
+ , fAntiAlias(aa) {
+ this->observeInval(fClipNode);
+}
+
+ClipEffect::~ClipEffect() {
+ this->unobserveInval(fClipNode);
+}
+
+void ClipEffect::onRender(SkCanvas* canvas) const {
+ if (this->bounds().isEmpty())
+ return;
+
+ SkAutoCanvasRestore acr(canvas, !fNoop);
+ if (!fNoop) {
+ fClipNode->clip(canvas, fAntiAlias);
+ }
+
+ this->INHERITED::onRender(canvas);
+}
+
+SkRect ClipEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
+ SkASSERT(this->hasInval());
+
+ const auto clipBounds = fClipNode->revalidate(ic, ctm);
+ auto childBounds = this->INHERITED::onRevalidate(ic, ctm);
+
+ fNoop = fClipNode->asPath().conservativelyContainsRect(childBounds);
+
+ return childBounds.intersect(clipBounds) ? childBounds : SkRect::MakeEmpty();
+}
+
+} // namespace sksg
diff --git a/experimental/sksg/effects/SkSGClipEffect.h b/experimental/sksg/effects/SkSGClipEffect.h
new file mode 100644
index 0000000000..674edb2b5c
--- /dev/null
+++ b/experimental/sksg/effects/SkSGClipEffect.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSGClipEffect_DEFINED
+#define SkSGClipEffect_DEFINED
+
+#include "SkSGEffectNode.h"
+
+namespace sksg {
+
+class GeometryNode;
+
+/**
+ * Concrete Effect node, applying a clip to its descendants.
+ *
+ */
+class ClipEffect final : public EffectNode {
+public:
+ static sk_sp<ClipEffect> Make(sk_sp<RenderNode> child, sk_sp<GeometryNode> clip,
+ bool aa = false) {
+ return (child && clip)
+ ? sk_sp<ClipEffect>(new ClipEffect(std::move(child), std::move(clip), aa))
+ : nullptr;
+ }
+
+ ~ClipEffect() override;
+
+protected:
+ ClipEffect(sk_sp<RenderNode>, sk_sp<GeometryNode>, bool aa);
+
+ void onRender(SkCanvas*) const override;
+
+ SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
+
+private:
+ const sk_sp<GeometryNode> fClipNode;
+ const bool fAntiAlias;
+
+ bool fNoop = false;
+
+ typedef EffectNode INHERITED;
+};
+
+} // namespace sksg
+
+#endif // SkSGClipEffect_DEFINED
diff --git a/experimental/sksg/geometry/SkSGGeometryTransform.cpp b/experimental/sksg/geometry/SkSGGeometryTransform.cpp
index 91367d48d6..5b366b9620 100644
--- a/experimental/sksg/geometry/SkSGGeometryTransform.cpp
+++ b/experimental/sksg/geometry/SkSGGeometryTransform.cpp
@@ -23,6 +23,14 @@ GeometryTransform::~GeometryTransform() {
this->unobserveInval(fMatrix);
}
+void GeometryTransform::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipPath(fTransformed, SkClipOp::kIntersect, antiAlias);
+}
+
+void GeometryTransform::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
+ canvas->drawPath(fTransformed, paint);
+}
+
SkRect GeometryTransform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
SkASSERT(this->hasInval());
@@ -42,8 +50,4 @@ SkPath GeometryTransform::onAsPath() const {
return fTransformed;
}
-void GeometryTransform::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
- canvas->drawPath(fTransformed, paint);
-}
-
} // namespace sksg
diff --git a/experimental/sksg/geometry/SkSGGeometryTransform.h b/experimental/sksg/geometry/SkSGGeometryTransform.h
index 31a3371408..ea990c6f29 100644
--- a/experimental/sksg/geometry/SkSGGeometryTransform.h
+++ b/experimental/sksg/geometry/SkSGGeometryTransform.h
@@ -37,9 +37,11 @@ public:
const sk_sp<Matrix>& getMatrix() const { return fMatrix; }
protected:
+ void onClip(SkCanvas*, bool antiAlias) const override;
+ void onDraw(SkCanvas*, const SkPaint&) const override;
+
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
SkPath onAsPath() const override;
- void onDraw(SkCanvas*, const SkPaint&) const override;
private:
GeometryTransform(sk_sp<GeometryNode>, sk_sp<Matrix>);
diff --git a/experimental/sksg/geometry/SkSGMerge.cpp b/experimental/sksg/geometry/SkSGMerge.cpp
index 49e780413d..be1ff4123a 100644
--- a/experimental/sksg/geometry/SkSGMerge.cpp
+++ b/experimental/sksg/geometry/SkSGMerge.cpp
@@ -26,6 +26,10 @@ Merge::~Merge() {
}
}
+void Merge::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipPath(fMerged, SkClipOp::kIntersect, antiAlias);
+}
+
void Merge::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
canvas->drawPath(fMerged, paint);
}
diff --git a/experimental/sksg/geometry/SkSGMerge.h b/experimental/sksg/geometry/SkSGMerge.h
index b0cb40de9c..69f824e011 100644
--- a/experimental/sksg/geometry/SkSGMerge.h
+++ b/experimental/sksg/geometry/SkSGMerge.h
@@ -43,6 +43,7 @@ public:
~Merge() override;
protected:
+ void onClip(SkCanvas*, bool antiAlias) const override;
void onDraw(SkCanvas*, const SkPaint&) const override;
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
diff --git a/experimental/sksg/geometry/SkSGPath.cpp b/experimental/sksg/geometry/SkSGPath.cpp
index 2b7dc94952..8d5a25373a 100644
--- a/experimental/sksg/geometry/SkSGPath.cpp
+++ b/experimental/sksg/geometry/SkSGPath.cpp
@@ -14,6 +14,10 @@ namespace sksg {
Path::Path(const SkPath& path) : fPath(path) {}
+void Path::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipPath(fPath, SkClipOp::kIntersect, antiAlias);
+}
+
void Path::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
canvas->drawPath(fPath, paint);
}
diff --git a/experimental/sksg/geometry/SkSGPath.h b/experimental/sksg/geometry/SkSGPath.h
index 18caa10f2a..6dd259394b 100644
--- a/experimental/sksg/geometry/SkSGPath.h
+++ b/experimental/sksg/geometry/SkSGPath.h
@@ -28,6 +28,7 @@ public:
SG_ATTRIBUTE(Path, SkPath, fPath)
protected:
+ void onClip(SkCanvas*, bool antiAlias) const override;
void onDraw(SkCanvas*, const SkPaint&) const override;
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
diff --git a/experimental/sksg/geometry/SkSGRect.cpp b/experimental/sksg/geometry/SkSGRect.cpp
index 532a604af4..16f0a6f1e1 100644
--- a/experimental/sksg/geometry/SkSGRect.cpp
+++ b/experimental/sksg/geometry/SkSGRect.cpp
@@ -15,6 +15,10 @@ namespace sksg {
Rect::Rect(const SkRect& rect) : fRect(rect) {}
+void Rect::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipRect(fRect, SkClipOp::kIntersect, antiAlias);
+}
+
void Rect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
canvas->drawRect(fRect, paint);
}
@@ -33,6 +37,10 @@ SkPath Rect::onAsPath() const {
RRect::RRect(const SkRRect& rr) : fRRect(rr) {}
+void RRect::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipRRect(fRRect, SkClipOp::kIntersect, antiAlias);
+}
+
void RRect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
canvas->drawRRect(fRRect, paint);
}
diff --git a/experimental/sksg/geometry/SkSGRect.h b/experimental/sksg/geometry/SkSGRect.h
index ad27910da9..a99c76ab98 100644
--- a/experimental/sksg/geometry/SkSGRect.h
+++ b/experimental/sksg/geometry/SkSGRect.h
@@ -32,6 +32,7 @@ public:
SG_ATTRIBUTE(B, SkScalar, fRect.fBottom)
protected:
+ void onClip(SkCanvas*, bool antiAlias) const override;
void onDraw(SkCanvas*, const SkPaint&) const override;
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
@@ -54,6 +55,7 @@ public:
SG_ATTRIBUTE(RRect, SkRRect, fRRect)
protected:
+ void onClip(SkCanvas*, bool antiAlias) const override;
void onDraw(SkCanvas*, const SkPaint&) const override;
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
diff --git a/experimental/sksg/geometry/SkSGTrimEffect.cpp b/experimental/sksg/geometry/SkSGTrimEffect.cpp
index afcc7e46b6..0b664fd436 100644
--- a/experimental/sksg/geometry/SkSGTrimEffect.cpp
+++ b/experimental/sksg/geometry/SkSGTrimEffect.cpp
@@ -22,6 +22,10 @@ TrimEffect::~TrimEffect() {
this->unobserveInval(fChild);
}
+void TrimEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipPath(fChild->asPath(), SkClipOp::kIntersect, antiAlias);
+}
+
// TODO
// This is a quick hack to get something on the screen. What we really want here is to apply
// the geometry transformation and cache the result on revalidation. Or an SkTrimPathEffect.
diff --git a/experimental/sksg/geometry/SkSGTrimEffect.h b/experimental/sksg/geometry/SkSGTrimEffect.h
index 77da3ab2d0..860cfafc25 100644
--- a/experimental/sksg/geometry/SkSGTrimEffect.h
+++ b/experimental/sksg/geometry/SkSGTrimEffect.h
@@ -33,6 +33,7 @@ public:
SG_ATTRIBUTE(Offset, SkScalar, fOffset)
protected:
+ void onClip(SkCanvas*, bool antiAlias) const override;
void onDraw(SkCanvas*, const SkPaint&) const override;
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;