Skip to content

Commit

Permalink
[skottie] Initial Fill layer effect support
Browse files Browse the repository at this point in the history
Overwrite the layer content color with a color filter.

TBR=
Change-Id: I39f920225affb2641cc11ab1f0c1456d89b47cb7
Reviewed-on: https://skia-review.googlesource.com/145730
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
  • Loading branch information
fmalita authored and Skia Commit-Bot committed Aug 7, 2018
1 parent ae64e49 commit 36216fb
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 8 deletions.
64 changes: 56 additions & 8 deletions modules/skottie/src/Skottie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "SkPoint.h"
#include "SkSGClipEffect.h"
#include "SkSGColor.h"
#include "SkSGColorFilter.h"
#include "SkSGDraw.h"
#include "SkSGGeometryTransform.h"
#include "SkSGGradient.h"
Expand Down Expand Up @@ -258,9 +259,10 @@ sk_sp<sksg::GeometryNode> AttachPolystarGeometry(const skjson::ObjectValue& jsta
return std::move(path_node);
}

sk_sp<sksg::Color> AttachColor(const skjson::ObjectValue& jcolor, AttachContext* ctx) {
sk_sp<sksg::Color> AttachColor(const skjson::ObjectValue& jcolor, AttachContext* ctx,
const char prop_name[]) {
auto color_node = sksg::Color::Make(SK_ColorBLACK);
BindProperty<VectorValue>(jcolor["c"], &ctx->fAnimators,
BindProperty<VectorValue>(jcolor[prop_name], &ctx->fAnimators,
[color_node](const VectorValue& c) {
color_node->setColor(ValueTraits<VectorValue>::As<SkColor>(c));
});
Expand Down Expand Up @@ -357,15 +359,15 @@ sk_sp<sksg::PaintNode> AttachStroke(const skjson::ObjectValue& jstroke, AttachCo
}

sk_sp<sksg::PaintNode> AttachColorFill(const skjson::ObjectValue& jfill, AttachContext* ctx) {
return AttachPaint(jfill, ctx, AttachColor(jfill, ctx));
return AttachPaint(jfill, ctx, AttachColor(jfill, ctx, "c"));
}

sk_sp<sksg::PaintNode> AttachGradientFill(const skjson::ObjectValue& jfill, AttachContext* ctx) {
return AttachPaint(jfill, ctx, AttachGradient(jfill, ctx));
}

sk_sp<sksg::PaintNode> AttachColorStroke(const skjson::ObjectValue& jstroke, AttachContext* ctx) {
return AttachStroke(jstroke, ctx, AttachPaint(jstroke, ctx, AttachColor(jstroke, ctx)));
return AttachStroke(jstroke, ctx, AttachPaint(jstroke, ctx, AttachColor(jstroke, ctx, "c")));
}

sk_sp<sksg::PaintNode> AttachGradientStroke(const skjson::ObjectValue& jstroke,
Expand Down Expand Up @@ -1106,14 +1108,55 @@ sk_sp<sksg::RenderNode> AttachMask(const skjson::ArrayValue* jmask,
return sksg::MaskEffect::Make(std::move(childNode), std::move(mask_group));
}


sk_sp<sksg::RenderNode> AttachFillLayerEffect(const skjson::ArrayValue* jeffect_props,
AttachContext* ctx,
sk_sp<sksg::RenderNode> layer) {
if (!jeffect_props) return layer;

sk_sp<sksg::Color> color_node;

for (const skjson::ObjectValue* jprop : *jeffect_props) {
if (!jprop) continue;

switch (const auto ty = ParseDefault<int>((*jprop)["ty"], -1)) {
case 2: // color
color_node = AttachColor(*jprop, ctx, "v");
break;
default:
LOG("?? Ignoring unsupported fill effect poperty type: %d\n", ty);
break;
}
}

return color_node
? sksg::ColorModeFilter::Make(std::move(layer), std::move(color_node), SkBlendMode::kSrcIn)
: nullptr;
}

sk_sp<sksg::RenderNode> AttachLayerEffects(const skjson::ArrayValue& jeffects,
AttachContext* ctx,
sk_sp<sksg::RenderNode> layer) {
for (const skjson::ObjectValue* jeffect : jeffects) {
if (!jeffect) continue;

switch (const auto ty = ParseDefault<int>((*jeffect)["ty"], -1)) {
case 21: // Fill
layer = AttachFillLayerEffect((*jeffect)["ef"], ctx, std::move(layer));
break;
default:
LOG("?? Unsupported layer effect type: %d\n", ty);
break;
}
}

return layer;
}

sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer,
AttachLayerContext* layerCtx) {
if (!jlayer) return nullptr;

if (!(*jlayer)["ef"].is<skjson::NullValue>()) {
LOG("?? Unsupported layer effect.\n");
}

using LayerAttacher = sk_sp<sksg::RenderNode> (*)(const skjson::ObjectValue&, AttachContext*);
static constexpr LayerAttacher gLayerAttachers[] = {
AttachCompLayer, // 'ty': 0
Expand Down Expand Up @@ -1157,6 +1200,11 @@ sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer,
layer = AttachOpacity(*jtransform, &local_ctx, std::move(layer));
}

// Optional layer effects.
if (const skjson::ArrayValue* jeffects = (*jlayer)["ef"]) {
layer = AttachLayerEffects(*jeffects, &local_ctx, std::move(layer));
}

class LayerController final : public sksg::GroupAnimator {
public:
LayerController(sksg::AnimatorList&& layer_animators,
Expand Down
68 changes: 68 additions & 0 deletions modules/sksg/include/SkSGColorFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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 SkSGColorFilter_DEFINED
#define SkSGColorFilter_DEFINED

#include "SkSGEffectNode.h"

#include "SkBlendMode.h"

class SkColorFilter;

namespace sksg {

class Color;

/**
* Base class for nodes which apply a color filter when rendering their descendants.
*
*/
class ColorFilter : public EffectNode {
protected:
explicit ColorFilter(sk_sp<RenderNode>);

void onRender(SkCanvas*) const final;

sk_sp<SkColorFilter> fColorFilter;

private:
typedef EffectNode INHERITED;
};

/**
* Concrete SkModeColorFilter Effect node.
*
*/
class ColorModeFilter final : public ColorFilter {
public:
~ColorModeFilter() override;

static sk_sp<ColorModeFilter> Make(sk_sp<RenderNode> child, sk_sp<Color> color,
SkBlendMode mode) {
return (child && color)
? sk_sp<ColorModeFilter>(new ColorModeFilter(std::move(child), std::move(color), mode))
: nullptr;
}

SG_ATTRIBUTE(Mode , SkBlendMode, fMode )

protected:
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;

private:
ColorModeFilter(sk_sp<RenderNode>, sk_sp<Color>, SkBlendMode);

sk_sp<Color> fColor;
SkBlendMode fMode;

typedef ColorFilter INHERITED;
};

} // namespace sksg

#endif // SkSGColorFilter_DEFINED
1 change: 1 addition & 0 deletions modules/sksg/sksg.gni
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ _src = get_path_info("src", "abspath")
skia_sksg_sources = [
"$_src/SkSGClipEffect.cpp",
"$_src/SkSGColor.cpp",
"$_src/SkSGColorFilter.cpp",
"$_src/SkSGDraw.cpp",
"$_src/SkSGEffectNode.cpp",
"$_src/SkSGGeometryNode.cpp",
Expand Down
54 changes: 54 additions & 0 deletions modules/sksg/src/SkSGColorFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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 "SkSGColorFilter.h"

#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkSGColor.h"

namespace sksg {

ColorFilter::ColorFilter(sk_sp<RenderNode> child)
: INHERITED(std::move(child)) {}

void ColorFilter::onRender(SkCanvas* canvas) const {
if (this->bounds().isEmpty())
return;

SkAutoCanvasRestore acr(canvas, false);

if (fColorFilter) {
SkPaint p;
p.setColorFilter(fColorFilter);
canvas->saveLayer(this->bounds(), &p);
}

this->INHERITED::onRender(canvas);
}

ColorModeFilter::ColorModeFilter(sk_sp<RenderNode> child, sk_sp<Color> color, SkBlendMode mode)
: INHERITED(std::move(child))
, fColor(std::move(color))
, fMode(mode) {
this->observeInval(fColor);
}

ColorModeFilter::~ColorModeFilter() {
this->unobserveInval(fColor);
}

SkRect ColorModeFilter::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
SkASSERT(this->hasInval());

fColor->revalidate(ic, ctm);
fColorFilter = SkColorFilter::MakeModeFilter(fColor->getColor(), fMode);

return this->INHERITED::onRevalidate(ic, ctm);
}

} // namespace sksg

0 comments on commit 36216fb

Please sign in to comment.