From 38ea40eb750596c75b8ffb5c8f94bcb84b94a7c3 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Mon, 29 Jan 2018 16:31:14 -0500 Subject: [skottie] Layer clip support TBR= Change-Id: Ibf65efc69031f8f6e19f4f28cccab29c357e704d Reviewed-on: https://skia-review.googlesource.com/101540 Reviewed-by: Florin Malita Commit-Queue: Florin Malita --- experimental/skottie/Skottie.cpp | 12 ++++++ experimental/sksg/SkSGGeometryNode.cpp | 5 +++ experimental/sksg/SkSGGeometryNode.h | 3 ++ experimental/sksg/effects/SkSGClipEffect.cpp | 50 ++++++++++++++++++++++ experimental/sksg/effects/SkSGClipEffect.h | 50 ++++++++++++++++++++++ .../sksg/geometry/SkSGGeometryTransform.cpp | 12 ++++-- experimental/sksg/geometry/SkSGGeometryTransform.h | 4 +- experimental/sksg/geometry/SkSGMerge.cpp | 4 ++ experimental/sksg/geometry/SkSGMerge.h | 1 + experimental/sksg/geometry/SkSGPath.cpp | 4 ++ experimental/sksg/geometry/SkSGPath.h | 1 + experimental/sksg/geometry/SkSGRect.cpp | 8 ++++ experimental/sksg/geometry/SkSGRect.h | 2 + experimental/sksg/geometry/SkSGTrimEffect.cpp | 4 ++ experimental/sksg/geometry/SkSGTrimEffect.h | 1 + 15 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 experimental/sksg/effects/SkSGClipEffect.cpp create mode 100644 experimental/sksg/effects/SkSGClipEffect.h (limited to 'experimental') 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 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 child, sk_sp 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 Make(sk_sp child, sk_sp clip, + bool aa = false) { + return (child && clip) + ? sk_sp(new ClipEffect(std::move(child), std::move(clip), aa)) + : nullptr; + } + + ~ClipEffect() override; + +protected: + ClipEffect(sk_sp, sk_sp, bool aa); + + void onRender(SkCanvas*) const override; + + SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + +private: + const sk_sp 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& 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, sk_sp); 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; -- cgit v1.2.3