49 const uint8_t* build_lut(std::array<uint8_t, 256>& lut_storage,
50 const ClipInfo& clip_info)
const {
57 float clip[] = {0, 1};
58 const auto kLottieDoClip = 1;
76 auto dIn = in_1 - in_0,
91 in_0 += std::copysign(
kEpsilon, .5f - in_0);
96 dT = 1 / 255.0f / dIn;
98 for (
size_t i = 0;
i < 256; ++
i) {
99 const auto out = out_0 + dOut * std::pow(
std::max(t, 0.0f), g);
107 return lut_storage.data();
124class EasyLevelsEffectAdapter final :
public DiscardableAdapterBase<EasyLevelsEffectAdapter,
125 sksg::ExternalColorFilter> {
129 const AnimationBuilder* abuilder)
139 kClipToOutBlack_Index = 7,
140 kClipToOutWhite_Index = 8,
143 EffectBinder(jprops, *abuilder,
this)
144 .bind( kChannel_Index, fChannel )
145 .bind( kInBlack_Index, fMapper.fInBlack )
146 .bind( kInWhite_Index, fMapper.fInWhite )
147 .bind( kGamma_Index, fMapper.fGamma )
148 .bind( kOutBlack_Index, fMapper.fOutBlack)
149 .bind( kOutWhite_Index, fMapper.fOutWhite)
150 .bind(kClipToOutBlack_Index, fClip.fClipBlack )
151 .bind(kClipToOutWhite_Index, fClip.fClipWhite );
155 void onSync()
override {
165 std::array<uint8_t, 256> lut;
166 if (channel < kRGB_Channel || channel > kA_Channel || !fMapper.build_lut(lut, fClip)) {
167 this->node()->setColorFilter(
nullptr);
172 channel == kA_Channel ? lut.data() :
nullptr,
173 channel == kR_Channel || channel == kRGB_Channel ? lut.data() :
nullptr,
174 channel == kG_Channel || channel == kRGB_Channel ? lut.data() :
nullptr,
175 channel == kB_Channel || channel == kRGB_Channel ? lut.data() :
nullptr
179 ChannelMapper fMapper;
183 using INHERITED = DiscardableAdapterBase<EasyLevelsEffectAdapter, sksg::ExternalColorFilter>;
190class ProLevelsEffectAdapter final :
public DiscardableAdapterBase<ProLevelsEffectAdapter,
191 sksg::ExternalColorFilter> {
195 const AnimationBuilder* abuilder)
201 kRGBInBlack_Index = 3,
202 kRGBInWhite_Index = 4,
204 kRGBOutBlack_Index = 6,
205 kRGBOutWhite_Index = 7,
208 kRInBlack_Index = 10,
209 kRInWhite_Index = 11,
211 kROutBlack_Index = 13,
212 kROutWhite_Index = 14,
215 kGInBlack_Index = 17,
216 kGInWhite_Index = 18,
218 kGOutBlack_Index = 20,
219 kGOutWhite_Index = 21,
222 kBInBlack_Index = 24,
223 kBInWhite_Index = 25,
225 kBOutBlack_Index = 27,
226 kBOutWhite_Index = 28,
229 kAInBlack_Index = 31,
230 kAInWhite_Index = 32,
232 kAOutBlack_Index = 34,
233 kAOutWhite_Index = 35,
235 kClipToOutBlack_Index = 37,
236 kClipToOutWhite_Index = 38,
239 EffectBinder(jprops, *abuilder,
this)
240 .bind( kRGBInBlack_Index, fRGBMapper.fInBlack )
241 .bind( kRGBInWhite_Index, fRGBMapper.fInWhite )
242 .bind( kRGBGamma_Index, fRGBMapper.fGamma )
243 .bind(kRGBOutBlack_Index, fRGBMapper.fOutBlack)
244 .bind(kRGBOutWhite_Index, fRGBMapper.fOutWhite)
246 .bind( kRInBlack_Index, fRMapper.fInBlack )
247 .bind( kRInWhite_Index, fRMapper.fInWhite )
248 .bind( kRGamma_Index, fRMapper.fGamma )
249 .bind(kROutBlack_Index, fRMapper.fOutBlack)
250 .bind(kROutWhite_Index, fRMapper.fOutWhite)
252 .bind( kGInBlack_Index, fGMapper.fInBlack )
253 .bind( kGInWhite_Index, fGMapper.fInWhite )
254 .bind( kGGamma_Index, fGMapper.fGamma )
255 .bind(kGOutBlack_Index, fGMapper.fOutBlack)
256 .bind(kGOutWhite_Index, fGMapper.fOutWhite)
258 .bind( kBInBlack_Index, fBMapper.fInBlack )
259 .bind( kBInWhite_Index, fBMapper.fInWhite )
260 .bind( kBGamma_Index, fBMapper.fGamma )
261 .bind(kBOutBlack_Index, fBMapper.fOutBlack)
262 .bind(kBOutWhite_Index, fBMapper.fOutWhite)
264 .bind( kAInBlack_Index, fAMapper.fInBlack )
265 .bind( kAInWhite_Index, fAMapper.fInWhite )
266 .bind( kAGamma_Index, fAMapper.fGamma )
267 .bind(kAOutBlack_Index, fAMapper.fOutBlack)
268 .bind(kAOutWhite_Index, fAMapper.fOutWhite);
272 void onSync()
override {
273 std::array<uint8_t, 256> a_lut_storage,
279 fRMapper.build_lut(r_lut_storage, fClip),
280 fGMapper.build_lut(g_lut_storage, fClip),
281 fBMapper.build_lut(b_lut_storage, fClip));
284 if (
const auto* rgb_lut = fRGBMapper.build_lut(a_lut_storage, fClip)) {
292 this->node()->setColorFilter(std::move(cf));
295 ChannelMapper fRGBMapper,
303 using INHERITED = DiscardableAdapterBase<ProLevelsEffectAdapter, sksg::ExternalColorFilter>;
static void round(SkPoint *p)
static constexpr bool SkIsNaN(T x)
static constexpr float sk_ieee_float_divide(float numer, float denom)
static constexpr double kEpsilon
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define INHERITED(method,...)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkScalarTruncToInt(x)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
#define SK_ScalarNearlyZero
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
static sk_sp< SkColorFilter > Compose(const sk_sp< SkColorFilter > &outer, sk_sp< SkColorFilter > inner)
static sk_sp< SkColorFilter > TableARGB(const uint8_t tableA[256], const uint8_t tableR[256], const uint8_t tableG[256], const uint8_t tableB[256])
void attachDiscardableAdapter(sk_sp< T > adapter) const
static float max(float r, float g, float b)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)