blob: 25ec1c8901b9c13b0b4d94f3172c28074099e0d3 [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "modules/skottie/src/effects/Effects.h"
#include "include/private/SkNx.h"
#include "modules/skottie/src/Adapter.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGColorFilter.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "src/utils/SkJSON.h"
namespace skottie::internal {
namespace {
class CCTonerAdapter final : public DiscardableAdapterBase<CCTonerAdapter,
sksg::GradientColorFilter> {
public:
CCTonerAdapter(const skjson::ArrayValue& jprops,
sk_sp<sksg::RenderNode> layer,
const AnimationBuilder& abuilder,
std::vector<sk_sp<sksg::Color>> colorNodes)
: INHERITED(sksg::GradientColorFilter::Make(std::move(layer), colorNodes))
, fColorNodes(std::move(colorNodes))
{
enum : size_t {
kTone_Index = 0,
kHiColor_Index = 1,
kBrightColor_Index = 2,
kMidColor_Index = 3,
kDarkColor_Index = 4,
kShadowColor_Index = 5,
kBlendAmount_Index = 6,
};
EffectBinder(jprops, abuilder, this)
.bind( kTone_Index, fTone)
.bind( kHiColor_Index, fHighlights)
.bind(kBrightColor_Index, fBrights)
.bind( kMidColor_Index, fMidtones)
.bind( kDarkColor_Index, fDarktones)
.bind(kShadowColor_Index, fShadows);
}
private:
static SkColor lerpColor(SkColor c0, SkColor c1, float t) {
const auto c0_4f = SkNx_cast<float>(Sk4b::Load(&c0)),
c1_4f = SkNx_cast<float>(Sk4b::Load(&c1)),
c_4f = c0_4f + (c1_4f - c0_4f) * t;
SkColor c;
SkNx_cast<uint8_t>(Sk4f_round(c_4f)).store(&c);
return c;
}
void onSync() override {
switch (SkScalarRoundToInt(fTone)) {
// duotone
case 1: fColorNodes.at(0)->setColor(fShadows);
fColorNodes.at(1)->setColor(lerpColor(fShadows, fHighlights, 0.25));
fColorNodes.at(2)->setColor(lerpColor(fShadows, fHighlights, 0.5));
fColorNodes.at(3)->setColor(lerpColor(fShadows, fHighlights, 0.75));
fColorNodes.at(4)->setColor(fHighlights);
break;
// tritone
case 2: fColorNodes.at(0)->setColor(fShadows);
fColorNodes.at(1)->setColor(lerpColor(fShadows, fMidtones, 0.5));
fColorNodes.at(2)->setColor(fMidtones);
fColorNodes.at(3)->setColor(lerpColor(fMidtones, fHighlights, 0.5));
fColorNodes.at(4)->setColor(fHighlights);
break;
// pentone
case 3: fColorNodes.at(0)->setColor(fShadows);
fColorNodes.at(1)->setColor(fDarktones);
fColorNodes.at(2)->setColor(fMidtones);
fColorNodes.at(3)->setColor(fBrights);
fColorNodes.at(4)->setColor(fHighlights);
break;
// solid
default: fColorNodes.at(0)->setColor(fMidtones);
fColorNodes.at(1)->setColor(fMidtones);
fColorNodes.at(2)->setColor(fMidtones);
fColorNodes.at(3)->setColor(fMidtones);
fColorNodes.at(4)->setColor(fMidtones);
break;
}
this->node()->setWeight((100-fBlend)/100);
}
const std::vector<sk_sp<sksg::Color>> fColorNodes;
ScalarValue fTone = 0;
VectorValue fHighlights,
fBrights,
fMidtones,
fDarktones,
fShadows;
ScalarValue fBlend = 0;
using INHERITED = DiscardableAdapterBase<CCTonerAdapter, sksg::GradientColorFilter>;
};
} // namespace
sk_sp<sksg::RenderNode> EffectBuilder::attachCCTonerEffect(const skjson::ArrayValue& jprops,
sk_sp<sksg::RenderNode> layer) const {
std::vector<sk_sp<sksg::Color>> colorNodes = {
sksg::Color::Make(SK_ColorRED),
sksg::Color::Make(SK_ColorRED),
sksg::Color::Make(SK_ColorRED),
sksg::Color::Make(SK_ColorRED),
sksg::Color::Make(SK_ColorRED)
};
return fBuilder->attachDiscardableAdapter<CCTonerAdapter>(jprops,
std::move(layer),
*fBuilder,
std::move(colorNodes));
}
} // namespace skottie::internal