[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>
This commit is contained in:
parent
eed48b66eb
commit
38ea40eb75
1
BUILD.gn
1
BUILD.gn
@ -1400,6 +1400,7 @@ if (skia_enable_tools) {
|
||||
"experimental/sksg/SkSGPaintNode.cpp",
|
||||
"experimental/sksg/SkSGRenderNode.cpp",
|
||||
"experimental/sksg/SkSGScene.cpp",
|
||||
"experimental/sksg/effects/SkSGClipEffect.cpp",
|
||||
"experimental/sksg/effects/SkSGMaskEffect.cpp",
|
||||
"experimental/sksg/effects/SkSGOpacityEffect.cpp",
|
||||
"experimental/sksg/effects/SkSGTransform.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));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
50
experimental/sksg/effects/SkSGClipEffect.cpp
Normal file
50
experimental/sksg/effects/SkSGClipEffect.cpp
Normal file
@ -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
|
50
experimental/sksg/effects/SkSGClipEffect.h
Normal file
50
experimental/sksg/effects/SkSGClipEffect.h
Normal file
@ -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
|
@ -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
|
||||
|
@ -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>);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user