1 /*
2 * Copyright 2021 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "modules/skottie/src/effects/Effects.h"
9
10 #include "include/private/SkNx.h"
11 #include "modules/skottie/src/Adapter.h"
12 #include "modules/skottie/src/SkottieValue.h"
13 #include "modules/sksg/include/SkSGColorFilter.h"
14 #include "modules/sksg/include/SkSGPaint.h"
15 #include "src/utils/SkJSON.h"
16
17 namespace skottie::internal {
18
19 namespace {
20
21 class CCTonerAdapter final : public DiscardableAdapterBase<CCTonerAdapter,
22 sksg::GradientColorFilter> {
23 public:
CCTonerAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder & abuilder,std::vector<sk_sp<sksg::Color>> colorNodes)24 CCTonerAdapter(const skjson::ArrayValue& jprops,
25 sk_sp<sksg::RenderNode> layer,
26 const AnimationBuilder& abuilder,
27 std::vector<sk_sp<sksg::Color>> colorNodes)
28 : INHERITED(sksg::GradientColorFilter::Make(std::move(layer), colorNodes))
29 , fColorNodes(std::move(colorNodes))
30 {
31 enum : size_t {
32 kTone_Index = 0,
33 kHiColor_Index = 1,
34 kBrightColor_Index = 2,
35 kMidColor_Index = 3,
36 kDarkColor_Index = 4,
37 kShadowColor_Index = 5,
38 kBlendAmount_Index = 6,
39 };
40
41
42 EffectBinder(jprops, abuilder, this)
43 .bind( kTone_Index, fTone)
44 .bind( kHiColor_Index, fHighlights)
45 .bind(kBrightColor_Index, fBrights)
46 .bind( kMidColor_Index, fMidtones)
47 .bind( kDarkColor_Index, fDarktones)
48 .bind(kShadowColor_Index, fShadows);
49
50 }
51 private:
lerpColor(SkColor c0,SkColor c1,float t)52 static SkColor lerpColor(SkColor c0, SkColor c1, float t) {
53 const auto c0_4f = SkNx_cast<float>(Sk4b::Load(&c0)),
54 c1_4f = SkNx_cast<float>(Sk4b::Load(&c1)),
55 c_4f = c0_4f + (c1_4f - c0_4f) * t;
56
57 SkColor c;
58 SkNx_cast<uint8_t>(Sk4f_round(c_4f)).store(&c);
59 return c;
60 }
61
onSync()62 void onSync() override {
63 switch (SkScalarRoundToInt(fTone)) {
64 // duotone
65 case 1: fColorNodes.at(0)->setColor(fShadows);
66 fColorNodes.at(1)->setColor(lerpColor(fShadows, fHighlights, 0.25));
67 fColorNodes.at(2)->setColor(lerpColor(fShadows, fHighlights, 0.5));
68 fColorNodes.at(3)->setColor(lerpColor(fShadows, fHighlights, 0.75));
69 fColorNodes.at(4)->setColor(fHighlights);
70 break;
71 // tritone
72 case 2: fColorNodes.at(0)->setColor(fShadows);
73 fColorNodes.at(1)->setColor(lerpColor(fShadows, fMidtones, 0.5));
74 fColorNodes.at(2)->setColor(fMidtones);
75 fColorNodes.at(3)->setColor(lerpColor(fMidtones, fHighlights, 0.5));
76 fColorNodes.at(4)->setColor(fHighlights);
77 break;
78 // pentone
79 case 3: fColorNodes.at(0)->setColor(fShadows);
80 fColorNodes.at(1)->setColor(fDarktones);
81 fColorNodes.at(2)->setColor(fMidtones);
82 fColorNodes.at(3)->setColor(fBrights);
83 fColorNodes.at(4)->setColor(fHighlights);
84 break;
85 // solid
86 default: fColorNodes.at(0)->setColor(fMidtones);
87 fColorNodes.at(1)->setColor(fMidtones);
88 fColorNodes.at(2)->setColor(fMidtones);
89 fColorNodes.at(3)->setColor(fMidtones);
90 fColorNodes.at(4)->setColor(fMidtones);
91 break;
92 }
93
94 this->node()->setWeight((100-fBlend)/100);
95 }
96
97
98 const std::vector<sk_sp<sksg::Color>> fColorNodes;
99
100 ScalarValue fTone = 0;
101 VectorValue fHighlights,
102 fBrights,
103 fMidtones,
104 fDarktones,
105 fShadows;
106 ScalarValue fBlend = 0;
107
108 using INHERITED = DiscardableAdapterBase<CCTonerAdapter, sksg::GradientColorFilter>;
109 };
110
111 } // namespace
112
attachCCTonerEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const113 sk_sp<sksg::RenderNode> EffectBuilder::attachCCTonerEffect(const skjson::ArrayValue& jprops,
114 sk_sp<sksg::RenderNode> layer) const {
115 std::vector<sk_sp<sksg::Color>> colorNodes = {
116 sksg::Color::Make(SK_ColorRED),
117 sksg::Color::Make(SK_ColorRED),
118 sksg::Color::Make(SK_ColorRED),
119 sksg::Color::Make(SK_ColorRED),
120 sksg::Color::Make(SK_ColorRED)
121 };
122 return fBuilder->attachDiscardableAdapter<CCTonerAdapter>(jprops,
123 std::move(layer),
124 *fBuilder,
125 std::move(colorNodes));
126 }
127
128 } // namespace skottie::internal
129