1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2019 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFloatingPoint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTPin.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/Adapter.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottiePriv.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/SkottieValue.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skottie/src/effects/Effects.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGColorFilter.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "modules/sksg/include/SkSGRenderNode.h"
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
22*c8dee2aaSAndroid Build Coastguard Worker #include <array>
23*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
24*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
25*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
26*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker namespace skjson {
29*c8dee2aaSAndroid Build Coastguard Worker class ArrayValue;
30*c8dee2aaSAndroid Build Coastguard Worker }
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker namespace skottie {
33*c8dee2aaSAndroid Build Coastguard Worker namespace internal {
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker namespace {
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker struct ClipInfo {
38*c8dee2aaSAndroid Build Coastguard Worker ScalarValue fClipBlack = 1, // 1: clip, 2/3: don't clip
39*c8dee2aaSAndroid Build Coastguard Worker fClipWhite = 1; // ^
40*c8dee2aaSAndroid Build Coastguard Worker };
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker struct ChannelMapper {
43*c8dee2aaSAndroid Build Coastguard Worker ScalarValue fInBlack = 0,
44*c8dee2aaSAndroid Build Coastguard Worker fInWhite = 1,
45*c8dee2aaSAndroid Build Coastguard Worker fOutBlack = 0,
46*c8dee2aaSAndroid Build Coastguard Worker fOutWhite = 1,
47*c8dee2aaSAndroid Build Coastguard Worker fGamma = 1;
48*c8dee2aaSAndroid Build Coastguard Worker
build_lutskottie::internal::__anon92cc00470111::ChannelMapper49*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* build_lut(std::array<uint8_t, 256>& lut_storage,
50*c8dee2aaSAndroid Build Coastguard Worker const ClipInfo& clip_info) const {
51*c8dee2aaSAndroid Build Coastguard Worker auto in_0 = fInBlack,
52*c8dee2aaSAndroid Build Coastguard Worker in_1 = fInWhite,
53*c8dee2aaSAndroid Build Coastguard Worker out_0 = fOutBlack,
54*c8dee2aaSAndroid Build Coastguard Worker out_1 = fOutWhite,
55*c8dee2aaSAndroid Build Coastguard Worker g = sk_ieee_float_divide(1, std::max(fGamma, 0.0f));
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker float clip[] = {0, 1};
58*c8dee2aaSAndroid Build Coastguard Worker const auto kLottieDoClip = 1;
59*c8dee2aaSAndroid Build Coastguard Worker if (SkScalarTruncToInt(clip_info.fClipBlack) == kLottieDoClip) {
60*c8dee2aaSAndroid Build Coastguard Worker const auto idx = fOutBlack <= fOutWhite ? 0 : 1;
61*c8dee2aaSAndroid Build Coastguard Worker clip[idx] = SkTPin(out_0, 0.0f, 1.0f);
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker if (SkScalarTruncToInt(clip_info.fClipWhite) == kLottieDoClip) {
64*c8dee2aaSAndroid Build Coastguard Worker const auto idx = fOutBlack <= fOutWhite ? 1 : 0;
65*c8dee2aaSAndroid Build Coastguard Worker clip[idx] = SkTPin(out_1, 0.0f, 1.0f);
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(clip[0] <= clip[1]);
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker if (SkScalarNearlyEqual(in_0, out_0) &&
70*c8dee2aaSAndroid Build Coastguard Worker SkScalarNearlyEqual(in_1, out_1) &&
71*c8dee2aaSAndroid Build Coastguard Worker SkScalarNearlyEqual(g, 1)) {
72*c8dee2aaSAndroid Build Coastguard Worker // no-op
73*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker
76*c8dee2aaSAndroid Build Coastguard Worker auto dIn = in_1 - in_0,
77*c8dee2aaSAndroid Build Coastguard Worker dOut = out_1 - out_0;
78*c8dee2aaSAndroid Build Coastguard Worker
79*c8dee2aaSAndroid Build Coastguard Worker if (SkScalarNearlyZero(dIn)) {
80*c8dee2aaSAndroid Build Coastguard Worker // Degenerate dIn == 0 makes the arithmetic below explode.
81*c8dee2aaSAndroid Build Coastguard Worker //
82*c8dee2aaSAndroid Build Coastguard Worker // We could specialize the builder to deal with that case, or we could just
83*c8dee2aaSAndroid Build Coastguard Worker // nudge by epsilon to make it all work. The latter approach is simpler
84*c8dee2aaSAndroid Build Coastguard Worker // and doesn't have any noticeable downsides.
85*c8dee2aaSAndroid Build Coastguard Worker //
86*c8dee2aaSAndroid Build Coastguard Worker // Also nudge in_0 towards 0.5, in case it was sqashed against an extremity.
87*c8dee2aaSAndroid Build Coastguard Worker // This allows for some abrupt transition when the output interval is not
88*c8dee2aaSAndroid Build Coastguard Worker // collapsed, and produces results closer to AE.
89*c8dee2aaSAndroid Build Coastguard Worker static constexpr auto kEpsilon = 2 * SK_ScalarNearlyZero;
90*c8dee2aaSAndroid Build Coastguard Worker dIn += std::copysign(kEpsilon, dIn);
91*c8dee2aaSAndroid Build Coastguard Worker in_0 += std::copysign(kEpsilon, .5f - in_0);
92*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!SkScalarNearlyZero(dIn));
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker auto t = -in_0 / dIn,
96*c8dee2aaSAndroid Build Coastguard Worker dT = 1 / 255.0f / dIn;
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < 256; ++i) {
99*c8dee2aaSAndroid Build Coastguard Worker const auto out = out_0 + dOut * std::pow(std::max(t, 0.0f), g);
100*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!SkIsNaN(out));
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker lut_storage[i] = static_cast<uint8_t>(std::round(SkTPin(out, clip[0], clip[1]) * 255));
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker t += dT;
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker return lut_storage.data();
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker };
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker // ADBE Easy Levels2 color correction effect.
112*c8dee2aaSAndroid Build Coastguard Worker //
113*c8dee2aaSAndroid Build Coastguard Worker // Maps the selected channel(s) from [inBlack...inWhite] to [outBlack, outWhite],
114*c8dee2aaSAndroid Build Coastguard Worker // based on a gamma exponent.
115*c8dee2aaSAndroid Build Coastguard Worker //
116*c8dee2aaSAndroid Build Coastguard Worker // For [i0..i1] -> [o0..o1]:
117*c8dee2aaSAndroid Build Coastguard Worker //
118*c8dee2aaSAndroid Build Coastguard Worker // c' = o0 + (o1 - o0) * ((c - i0) / (i1 - i0)) ^ G
119*c8dee2aaSAndroid Build Coastguard Worker //
120*c8dee2aaSAndroid Build Coastguard Worker // The output is optionally clipped to the output range.
121*c8dee2aaSAndroid Build Coastguard Worker //
122*c8dee2aaSAndroid Build Coastguard Worker // In/out intervals are clampped to [0..1]. Inversion is allowed.
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker class EasyLevelsEffectAdapter final : public DiscardableAdapterBase<EasyLevelsEffectAdapter,
125*c8dee2aaSAndroid Build Coastguard Worker sksg::ExternalColorFilter> {
126*c8dee2aaSAndroid Build Coastguard Worker public:
EasyLevelsEffectAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder * abuilder)127*c8dee2aaSAndroid Build Coastguard Worker EasyLevelsEffectAdapter(const skjson::ArrayValue& jprops,
128*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> layer,
129*c8dee2aaSAndroid Build Coastguard Worker const AnimationBuilder* abuilder)
130*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(sksg::ExternalColorFilter::Make(std::move(layer))) {
131*c8dee2aaSAndroid Build Coastguard Worker enum : size_t {
132*c8dee2aaSAndroid Build Coastguard Worker kChannel_Index = 0,
133*c8dee2aaSAndroid Build Coastguard Worker // kHist_Index = 1,
134*c8dee2aaSAndroid Build Coastguard Worker kInBlack_Index = 2,
135*c8dee2aaSAndroid Build Coastguard Worker kInWhite_Index = 3,
136*c8dee2aaSAndroid Build Coastguard Worker kGamma_Index = 4,
137*c8dee2aaSAndroid Build Coastguard Worker kOutBlack_Index = 5,
138*c8dee2aaSAndroid Build Coastguard Worker kOutWhite_Index = 6,
139*c8dee2aaSAndroid Build Coastguard Worker kClipToOutBlack_Index = 7,
140*c8dee2aaSAndroid Build Coastguard Worker kClipToOutWhite_Index = 8,
141*c8dee2aaSAndroid Build Coastguard Worker };
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker EffectBinder(jprops, *abuilder, this)
144*c8dee2aaSAndroid Build Coastguard Worker .bind( kChannel_Index, fChannel )
145*c8dee2aaSAndroid Build Coastguard Worker .bind( kInBlack_Index, fMapper.fInBlack )
146*c8dee2aaSAndroid Build Coastguard Worker .bind( kInWhite_Index, fMapper.fInWhite )
147*c8dee2aaSAndroid Build Coastguard Worker .bind( kGamma_Index, fMapper.fGamma )
148*c8dee2aaSAndroid Build Coastguard Worker .bind( kOutBlack_Index, fMapper.fOutBlack)
149*c8dee2aaSAndroid Build Coastguard Worker .bind( kOutWhite_Index, fMapper.fOutWhite)
150*c8dee2aaSAndroid Build Coastguard Worker .bind(kClipToOutBlack_Index, fClip.fClipBlack )
151*c8dee2aaSAndroid Build Coastguard Worker .bind(kClipToOutWhite_Index, fClip.fClipWhite );
152*c8dee2aaSAndroid Build Coastguard Worker }
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Worker private:
onSync()155*c8dee2aaSAndroid Build Coastguard Worker void onSync() override {
156*c8dee2aaSAndroid Build Coastguard Worker enum LottieChannel {
157*c8dee2aaSAndroid Build Coastguard Worker kRGB_Channel = 1,
158*c8dee2aaSAndroid Build Coastguard Worker kR_Channel = 2,
159*c8dee2aaSAndroid Build Coastguard Worker kG_Channel = 3,
160*c8dee2aaSAndroid Build Coastguard Worker kB_Channel = 4,
161*c8dee2aaSAndroid Build Coastguard Worker kA_Channel = 5,
162*c8dee2aaSAndroid Build Coastguard Worker };
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker const auto channel = SkScalarTruncToInt(fChannel);
165*c8dee2aaSAndroid Build Coastguard Worker std::array<uint8_t, 256> lut;
166*c8dee2aaSAndroid Build Coastguard Worker if (channel < kRGB_Channel || channel > kA_Channel || !fMapper.build_lut(lut, fClip)) {
167*c8dee2aaSAndroid Build Coastguard Worker this->node()->setColorFilter(nullptr);
168*c8dee2aaSAndroid Build Coastguard Worker return;
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker this->node()->setColorFilter(SkColorFilters::TableARGB(
172*c8dee2aaSAndroid Build Coastguard Worker channel == kA_Channel ? lut.data() : nullptr,
173*c8dee2aaSAndroid Build Coastguard Worker channel == kR_Channel || channel == kRGB_Channel ? lut.data() : nullptr,
174*c8dee2aaSAndroid Build Coastguard Worker channel == kG_Channel || channel == kRGB_Channel ? lut.data() : nullptr,
175*c8dee2aaSAndroid Build Coastguard Worker channel == kB_Channel || channel == kRGB_Channel ? lut.data() : nullptr
176*c8dee2aaSAndroid Build Coastguard Worker ));
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker ChannelMapper fMapper;
180*c8dee2aaSAndroid Build Coastguard Worker ClipInfo fClip;
181*c8dee2aaSAndroid Build Coastguard Worker ScalarValue fChannel = 1; // 1: RGB, 2: R, 3: G, 4: B, 5: A
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = DiscardableAdapterBase<EasyLevelsEffectAdapter, sksg::ExternalColorFilter>;
184*c8dee2aaSAndroid Build Coastguard Worker };
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker // ADBE Pro Levels2 color correction effect.
187*c8dee2aaSAndroid Build Coastguard Worker //
188*c8dee2aaSAndroid Build Coastguard Worker // Similar to ADBE Easy Levels2, but offers separate controls for each channel.
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker class ProLevelsEffectAdapter final : public DiscardableAdapterBase<ProLevelsEffectAdapter,
191*c8dee2aaSAndroid Build Coastguard Worker sksg::ExternalColorFilter> {
192*c8dee2aaSAndroid Build Coastguard Worker public:
ProLevelsEffectAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder * abuilder)193*c8dee2aaSAndroid Build Coastguard Worker ProLevelsEffectAdapter(const skjson::ArrayValue& jprops,
194*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> layer,
195*c8dee2aaSAndroid Build Coastguard Worker const AnimationBuilder* abuilder)
196*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(sksg::ExternalColorFilter::Make(std::move(layer))) {
197*c8dee2aaSAndroid Build Coastguard Worker enum : size_t {
198*c8dee2aaSAndroid Build Coastguard Worker // kHistChan_Index = 0,
199*c8dee2aaSAndroid Build Coastguard Worker // kHist_Index = 1,
200*c8dee2aaSAndroid Build Coastguard Worker // kRGBBegin_Index = 2,
201*c8dee2aaSAndroid Build Coastguard Worker kRGBInBlack_Index = 3,
202*c8dee2aaSAndroid Build Coastguard Worker kRGBInWhite_Index = 4,
203*c8dee2aaSAndroid Build Coastguard Worker kRGBGamma_Index = 5,
204*c8dee2aaSAndroid Build Coastguard Worker kRGBOutBlack_Index = 6,
205*c8dee2aaSAndroid Build Coastguard Worker kRGBOutWhite_Index = 7,
206*c8dee2aaSAndroid Build Coastguard Worker // kRGBEnd_Index = 8,
207*c8dee2aaSAndroid Build Coastguard Worker // kRBegin_Index = 9,
208*c8dee2aaSAndroid Build Coastguard Worker kRInBlack_Index = 10,
209*c8dee2aaSAndroid Build Coastguard Worker kRInWhite_Index = 11,
210*c8dee2aaSAndroid Build Coastguard Worker kRGamma_Index = 12,
211*c8dee2aaSAndroid Build Coastguard Worker kROutBlack_Index = 13,
212*c8dee2aaSAndroid Build Coastguard Worker kROutWhite_Index = 14,
213*c8dee2aaSAndroid Build Coastguard Worker // kREnd_Index = 15,
214*c8dee2aaSAndroid Build Coastguard Worker // kGBegin_Index = 16,
215*c8dee2aaSAndroid Build Coastguard Worker kGInBlack_Index = 17,
216*c8dee2aaSAndroid Build Coastguard Worker kGInWhite_Index = 18,
217*c8dee2aaSAndroid Build Coastguard Worker kGGamma_Index = 19,
218*c8dee2aaSAndroid Build Coastguard Worker kGOutBlack_Index = 20,
219*c8dee2aaSAndroid Build Coastguard Worker kGOutWhite_Index = 21,
220*c8dee2aaSAndroid Build Coastguard Worker // kGEnd_Index = 22,
221*c8dee2aaSAndroid Build Coastguard Worker // kBBegin_Index = 23,
222*c8dee2aaSAndroid Build Coastguard Worker kBInBlack_Index = 24,
223*c8dee2aaSAndroid Build Coastguard Worker kBInWhite_Index = 25,
224*c8dee2aaSAndroid Build Coastguard Worker kBGamma_Index = 26,
225*c8dee2aaSAndroid Build Coastguard Worker kBOutBlack_Index = 27,
226*c8dee2aaSAndroid Build Coastguard Worker kBOutWhite_Index = 28,
227*c8dee2aaSAndroid Build Coastguard Worker // kBEnd_Index = 29,
228*c8dee2aaSAndroid Build Coastguard Worker // kABegin_Index = 30,
229*c8dee2aaSAndroid Build Coastguard Worker kAInBlack_Index = 31,
230*c8dee2aaSAndroid Build Coastguard Worker kAInWhite_Index = 32,
231*c8dee2aaSAndroid Build Coastguard Worker kAGamma_Index = 33,
232*c8dee2aaSAndroid Build Coastguard Worker kAOutBlack_Index = 34,
233*c8dee2aaSAndroid Build Coastguard Worker kAOutWhite_Index = 35,
234*c8dee2aaSAndroid Build Coastguard Worker // kAEnd_Index = 36,
235*c8dee2aaSAndroid Build Coastguard Worker kClipToOutBlack_Index = 37,
236*c8dee2aaSAndroid Build Coastguard Worker kClipToOutWhite_Index = 38,
237*c8dee2aaSAndroid Build Coastguard Worker };
238*c8dee2aaSAndroid Build Coastguard Worker
239*c8dee2aaSAndroid Build Coastguard Worker EffectBinder(jprops, *abuilder, this)
240*c8dee2aaSAndroid Build Coastguard Worker .bind( kRGBInBlack_Index, fRGBMapper.fInBlack )
241*c8dee2aaSAndroid Build Coastguard Worker .bind( kRGBInWhite_Index, fRGBMapper.fInWhite )
242*c8dee2aaSAndroid Build Coastguard Worker .bind( kRGBGamma_Index, fRGBMapper.fGamma )
243*c8dee2aaSAndroid Build Coastguard Worker .bind(kRGBOutBlack_Index, fRGBMapper.fOutBlack)
244*c8dee2aaSAndroid Build Coastguard Worker .bind(kRGBOutWhite_Index, fRGBMapper.fOutWhite)
245*c8dee2aaSAndroid Build Coastguard Worker
246*c8dee2aaSAndroid Build Coastguard Worker .bind( kRInBlack_Index, fRMapper.fInBlack )
247*c8dee2aaSAndroid Build Coastguard Worker .bind( kRInWhite_Index, fRMapper.fInWhite )
248*c8dee2aaSAndroid Build Coastguard Worker .bind( kRGamma_Index, fRMapper.fGamma )
249*c8dee2aaSAndroid Build Coastguard Worker .bind(kROutBlack_Index, fRMapper.fOutBlack)
250*c8dee2aaSAndroid Build Coastguard Worker .bind(kROutWhite_Index, fRMapper.fOutWhite)
251*c8dee2aaSAndroid Build Coastguard Worker
252*c8dee2aaSAndroid Build Coastguard Worker .bind( kGInBlack_Index, fGMapper.fInBlack )
253*c8dee2aaSAndroid Build Coastguard Worker .bind( kGInWhite_Index, fGMapper.fInWhite )
254*c8dee2aaSAndroid Build Coastguard Worker .bind( kGGamma_Index, fGMapper.fGamma )
255*c8dee2aaSAndroid Build Coastguard Worker .bind(kGOutBlack_Index, fGMapper.fOutBlack)
256*c8dee2aaSAndroid Build Coastguard Worker .bind(kGOutWhite_Index, fGMapper.fOutWhite)
257*c8dee2aaSAndroid Build Coastguard Worker
258*c8dee2aaSAndroid Build Coastguard Worker .bind( kBInBlack_Index, fBMapper.fInBlack )
259*c8dee2aaSAndroid Build Coastguard Worker .bind( kBInWhite_Index, fBMapper.fInWhite )
260*c8dee2aaSAndroid Build Coastguard Worker .bind( kBGamma_Index, fBMapper.fGamma )
261*c8dee2aaSAndroid Build Coastguard Worker .bind(kBOutBlack_Index, fBMapper.fOutBlack)
262*c8dee2aaSAndroid Build Coastguard Worker .bind(kBOutWhite_Index, fBMapper.fOutWhite)
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker .bind( kAInBlack_Index, fAMapper.fInBlack )
265*c8dee2aaSAndroid Build Coastguard Worker .bind( kAInWhite_Index, fAMapper.fInWhite )
266*c8dee2aaSAndroid Build Coastguard Worker .bind( kAGamma_Index, fAMapper.fGamma )
267*c8dee2aaSAndroid Build Coastguard Worker .bind(kAOutBlack_Index, fAMapper.fOutBlack)
268*c8dee2aaSAndroid Build Coastguard Worker .bind(kAOutWhite_Index, fAMapper.fOutWhite);
269*c8dee2aaSAndroid Build Coastguard Worker }
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard Worker private:
onSync()272*c8dee2aaSAndroid Build Coastguard Worker void onSync() override {
273*c8dee2aaSAndroid Build Coastguard Worker std::array<uint8_t, 256> a_lut_storage,
274*c8dee2aaSAndroid Build Coastguard Worker r_lut_storage,
275*c8dee2aaSAndroid Build Coastguard Worker g_lut_storage,
276*c8dee2aaSAndroid Build Coastguard Worker b_lut_storage;
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker auto cf = SkColorFilters::TableARGB(fAMapper.build_lut(a_lut_storage, fClip),
279*c8dee2aaSAndroid Build Coastguard Worker fRMapper.build_lut(r_lut_storage, fClip),
280*c8dee2aaSAndroid Build Coastguard Worker fGMapper.build_lut(g_lut_storage, fClip),
281*c8dee2aaSAndroid Build Coastguard Worker fBMapper.build_lut(b_lut_storage, fClip));
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker // The RGB mapper composes outside individual channel mappers.
284*c8dee2aaSAndroid Build Coastguard Worker if (const auto* rgb_lut = fRGBMapper.build_lut(a_lut_storage, fClip)) {
285*c8dee2aaSAndroid Build Coastguard Worker cf = SkColorFilters::Compose(SkColorFilters::TableARGB(nullptr,
286*c8dee2aaSAndroid Build Coastguard Worker rgb_lut,
287*c8dee2aaSAndroid Build Coastguard Worker rgb_lut,
288*c8dee2aaSAndroid Build Coastguard Worker rgb_lut),
289*c8dee2aaSAndroid Build Coastguard Worker std::move(cf));
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker this->node()->setColorFilter(std::move(cf));
293*c8dee2aaSAndroid Build Coastguard Worker }
294*c8dee2aaSAndroid Build Coastguard Worker
295*c8dee2aaSAndroid Build Coastguard Worker ChannelMapper fRGBMapper,
296*c8dee2aaSAndroid Build Coastguard Worker fRMapper,
297*c8dee2aaSAndroid Build Coastguard Worker fGMapper,
298*c8dee2aaSAndroid Build Coastguard Worker fBMapper,
299*c8dee2aaSAndroid Build Coastguard Worker fAMapper;
300*c8dee2aaSAndroid Build Coastguard Worker
301*c8dee2aaSAndroid Build Coastguard Worker ClipInfo fClip;
302*c8dee2aaSAndroid Build Coastguard Worker
303*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = DiscardableAdapterBase<ProLevelsEffectAdapter, sksg::ExternalColorFilter>;
304*c8dee2aaSAndroid Build Coastguard Worker };
305*c8dee2aaSAndroid Build Coastguard Worker
306*c8dee2aaSAndroid Build Coastguard Worker } // namespace
307*c8dee2aaSAndroid Build Coastguard Worker
attachEasyLevelsEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const308*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> EffectBuilder::attachEasyLevelsEffect(const skjson::ArrayValue& jprops,
309*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> layer) const {
310*c8dee2aaSAndroid Build Coastguard Worker return fBuilder->attachDiscardableAdapter<EasyLevelsEffectAdapter>(jprops,
311*c8dee2aaSAndroid Build Coastguard Worker std::move(layer),
312*c8dee2aaSAndroid Build Coastguard Worker fBuilder);
313*c8dee2aaSAndroid Build Coastguard Worker }
314*c8dee2aaSAndroid Build Coastguard Worker
attachProLevelsEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const315*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> EffectBuilder::attachProLevelsEffect(const skjson::ArrayValue& jprops,
316*c8dee2aaSAndroid Build Coastguard Worker sk_sp<sksg::RenderNode> layer) const {
317*c8dee2aaSAndroid Build Coastguard Worker return fBuilder->attachDiscardableAdapter<ProLevelsEffectAdapter>(jprops,
318*c8dee2aaSAndroid Build Coastguard Worker std::move(layer),
319*c8dee2aaSAndroid Build Coastguard Worker fBuilder);
320*c8dee2aaSAndroid Build Coastguard Worker }
321*c8dee2aaSAndroid Build Coastguard Worker
322*c8dee2aaSAndroid Build Coastguard Worker } // namespace internal
323*c8dee2aaSAndroid Build Coastguard Worker } // namespace skottie
324