[skotty] Initial opacity support

TBR=

Change-Id: I62581d3a7a83af5ccf373f0f4edf66a2d7f06f07
Reviewed-on: https://skia-review.googlesource.com/92223
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Florin Malita 2018-01-08 16:42:59 -05:00 committed by Skia Commit-Bot
parent 185ffe916e
commit c0034179a1
5 changed files with 121 additions and 3 deletions

View File

@ -1384,6 +1384,7 @@ if (skia_enable_tools) {
"experimental/sksg/SkSGNode.cpp",
"experimental/sksg/SkSGPaintNode.cpp",
"experimental/sksg/SkSGRenderNode.cpp",
"experimental/sksg/effects/SkSGOpacityEffect.cpp",
"experimental/sksg/effects/SkSGTransform.cpp",
"experimental/sksg/geometry/SkSGMerge.cpp",
"experimental/sksg/geometry/SkSGPath.cpp",

View File

@ -24,6 +24,7 @@
#include "SkSGImage.h"
#include "SkSGInvalidationController.h"
#include "SkSGMerge.h"
#include "SkSGOpacityEffect.h"
#include "SkSGPath.h"
#include "SkSGRect.h"
#include "SkSGTransform.h"
@ -140,6 +141,31 @@ sk_sp<sksg::Matrix> AttachMatrix(const Json::Value& t, AttachContext* ctx,
return matrix;
}
sk_sp<sksg::RenderNode> AttachOpacity(const Json::Value& jtransform, AttachContext* ctx,
sk_sp<sksg::RenderNode> childNode) {
if (!jtransform.isObject() || !childNode)
return childNode;
// This is more peeky than other attachers, because we want to avoid redundant opacity
// nodes for the extremely common case of static opaciy == 100.
const auto& opacity = jtransform["o"];
if (opacity.isObject() &&
!ParseBool(opacity["a"], true) &&
ParseScalar(opacity["k"], -1) == 100) {
// Ignoring static full opacity.
return childNode;
}
auto opacityNode = sksg::OpacityEffect::Make(childNode);
AttachProperty<ScalarValue, SkScalar>(opacity, ctx, opacityNode,
[](const sk_sp<sksg::OpacityEffect>& node, const SkScalar& o) {
// BM opacity is [0..100]
node->setOpacity(o * 0.01f);
});
return opacityNode;
}
sk_sp<sksg::RenderNode> AttachShape(const Json::Value&, AttachContext* ctx);
sk_sp<sksg::RenderNode> AttachComposition(const Json::Value&, AttachContext* ctx);
@ -512,6 +538,7 @@ sk_sp<sksg::RenderNode> AttachShape(const Json::Value& shapeArray, AttachContext
xformed_group = sksg::Transform::Make(std::move(xformed_group),
std::move(matrix));
}
xformed_group = AttachOpacity(s, ctx, std::move(xformed_group));
} break;
}
}
@ -694,10 +721,11 @@ sk_sp<sksg::RenderNode> AttachLayer(const Json::Value& jlayer,
auto layer = gLayerAttachers[type](jlayer, layerCtx->fCtx);
auto layerMatrix = layerCtx->AttachLayerMatrix(jlayer);
auto transformed = layerMatrix
? sksg::Transform::Make(std::move(layer), std::move(layerMatrix))
: layer;
return layerMatrix
? sksg::Transform::Make(std::move(layer), std::move(layerMatrix))
: layer;
return AttachOpacity(jlayer["ks"], layerCtx->fCtx, std::move(transformed));
}
sk_sp<sksg::RenderNode> AttachComposition(const Json::Value& comp, AttachContext* ctx) {

View File

@ -44,6 +44,11 @@ protected:
explicit Node(uint32_t invalTraits);
~Node() override;
const SkRect& bounds() const {
SkASSERT(!this->hasInval());
return fBounds;
}
// Tag this node for invalidation and optional damage.
void invalidate(bool damage = true);
bool hasInval() const { return fFlags & kInvalidated_Flag; }

View File

@ -0,0 +1,42 @@
/*
* 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 "SkSGOpacityEffect.h"
#include "SkCanvas.h"
#include <math.h>
namespace sksg {
OpacityEffect::OpacityEffect(sk_sp<RenderNode> child, float opacity)
: INHERITED(std::move(child))
, fOpacity(opacity) {}
void OpacityEffect::onRender(SkCanvas* canvas) const {
// opacity <= 0 disables rendering
if (fOpacity <= 0)
return;
// TODO: we could avoid savelayer if there is no more than one drawing primitive
// in the sub-DAG.
SkAutoCanvasRestore acr(canvas, false);
if (fOpacity < 1) {
canvas->saveLayerAlpha(&this->bounds(), roundf(fOpacity * 255));
}
this->INHERITED::onRender(canvas);
}
SkRect OpacityEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
SkASSERT(this->hasInval());
// opacity <= 0 disables rendering AND revalidation for the sub-DAG
return fOpacity > 0 ? this->INHERITED::onRevalidate(ic, ctm) : SkRect::MakeEmpty();
}
} // namespace sksg

View File

@ -0,0 +1,42 @@
/*
* 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 SkSGOpacityEffect_DEFINED
#define SkSGOpacityEffect_DEFINED
#include "SkSGEffectNode.h"
namespace sksg {
/**
* Concrete Effect node, applying opacity to its descendants.
*
*/
class OpacityEffect final : public EffectNode {
public:
static sk_sp<OpacityEffect> Make(sk_sp<RenderNode> child, float opacity = 1) {
return child ? sk_sp<OpacityEffect>(new OpacityEffect(std::move(child), opacity)) : nullptr;
}
SG_ATTRIBUTE(Opacity, float, fOpacity)
protected:
OpacityEffect(sk_sp<RenderNode>, float);
void onRender(SkCanvas*) const override;
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
private:
float fOpacity;
typedef EffectNode INHERITED;
};
} // namespace sksg
#endif // SkSGOpacityEffect_DEFINED