/* * Copyright 2021 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 { public: CCTonerAdapter(const skjson::ArrayValue& jprops, sk_sp layer, const AnimationBuilder& abuilder, std::vector> 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(Sk4b::Load(&c0)), c1_4f = SkNx_cast(Sk4b::Load(&c1)), c_4f = c0_4f + (c1_4f - c0_4f) * t; SkColor c; SkNx_cast(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> fColorNodes; ScalarValue fTone = 0; VectorValue fHighlights, fBrights, fMidtones, fDarktones, fShadows; ScalarValue fBlend = 0; using INHERITED = DiscardableAdapterBase; }; } // namespace sk_sp EffectBuilder::attachCCTonerEffect(const skjson::ArrayValue& jprops, sk_sp layer) const { std::vector> 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(jprops, std::move(layer), *fBuilder, std::move(colorNodes)); } } // namespace skottie::internal