Flutter Engine
The Flutter Engine
BlackAndWhiteEffect.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 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
19
20#include <cstddef>
21#include <utility>
22
23namespace skjson {
24class ArrayValue;
25}
26
27namespace skottie::internal {
28namespace {
29
30// The B&W effect allows controlling individual luminance contribution of
31// primary and secondary colors.
32//
33// The implementation relies on computing primary/secondary relative weights
34// for the input color on the hue hexagon, and modulating based on weight
35// coefficients.
36//
37// Note:
38// - at least one of (dr,dg,db) is 0
39// - at least two of (wr,wg,wb) and two of (wy,wc,wm) are 0
40// => we are effectively selecting the color hue sextant without explicit branching
41//
42// (inspired by https://github.com/RoyiAvital/StackExchangeCodes/blob/master/SignalProcessing/Q688/ApplyBlackWhiteFilter.m)
43
45 static constexpr char BLACK_AND_WHITE_EFFECT[] =
46 "uniform half kR, kY, kG, kC, kB, kM;"
47
48 "half4 main(half4 c) {"
49 "half m = min(min(c.r, c.g), c.b),"
50
51 "dr = c.r - m,"
52 "dg = c.g - m,"
53 "db = c.b - m,"
54
55 // secondaries weights
56 "wy = min(dr,dg),"
57 "wc = min(dg,db),"
58 "wm = min(db,dr),"
59
60 // primaries weights
61 "wr = dr - wy - wm,"
62 "wg = dg - wy - wc,"
63 "wb = db - wc - wm,"
64
65 // final luminance
66 "l = m + kR*wr + kY*wy + kG*wg + kC*wc + kB*wb + kM*wm;"
67
68 "return half4(l, l, l, c.a);"
69 "}"
70 ;
71
72 static const SkRuntimeEffect* effect =
74 SkASSERT(effect);
75
76 return sk_ref_sp(effect);
77}
78
79class BlackAndWhiteAdapter final : public DiscardableAdapterBase<BlackAndWhiteAdapter,
80 sksg::ExternalColorFilter> {
81public:
82 BlackAndWhiteAdapter(const skjson::ArrayValue& jprops,
83 const AnimationBuilder& abuilder,
85 : INHERITED(sksg::ExternalColorFilter::Make(std::move(layer)))
86 , fEffect(make_effect())
87 {
88 SkASSERT(fEffect);
89
90 enum : size_t {
91 kReds_Index = 0,
92 kYellows_Index = 1,
93 kGreens_Index = 2,
94 kCyans_Index = 3,
95 kBlues_Index = 4,
96 kMagentas_Index = 5,
97 // TODO
98 // kTint_Index = 6,
99 // kTintColorIndex = 7,
100 };
101
102 EffectBinder(jprops, abuilder, this)
103 .bind( kReds_Index, fCoeffs[0])
104 .bind( kYellows_Index, fCoeffs[1])
105 .bind( kGreens_Index, fCoeffs[2])
106 .bind( kCyans_Index, fCoeffs[3])
107 .bind( kBlues_Index, fCoeffs[4])
108 .bind(kMagentas_Index, fCoeffs[5]);
109 }
110
111private:
112 void onSync() override {
113 struct {
114 float normalized_coeffs[6];
115 } coeffs = {
116 (fCoeffs[0] ) / 100,
117 (fCoeffs[1] ) / 100,
118 (fCoeffs[2] ) / 100,
119 (fCoeffs[3] ) / 100,
120 (fCoeffs[4] ) / 100,
121 (fCoeffs[5] ) / 100,
122 };
123
124 this->node()->setColorFilter(
126 }
127
128 const sk_sp<SkRuntimeEffect> fEffect;
129
130 ScalarValue fCoeffs[6];
131
132 using INHERITED = DiscardableAdapterBase<BlackAndWhiteAdapter, sksg::ExternalColorFilter>;
133};
134
135} // namespace
136
137sk_sp<sksg::RenderNode> EffectBuilder::attachBlackAndWhiteEffect(
138 const skjson::ArrayValue& jprops, sk_sp<sksg::RenderNode> layer) const {
139 return fBuilder->attachDiscardableAdapter<BlackAndWhiteAdapter>(jprops,
140 *fBuilder,
141 std::move(layer));
142}
143
144} // namespace skottie::internal
static sk_sp< Effect > make_effect()
Definition: RefCntTest.cpp:140
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define INHERITED(method,...)
Definition: SkRecorder.cpp:128
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition: SkData.cpp:111
static Result MakeForColorFilter(SkString sksl, const Options &)
sk_sp< SkColorFilter > makeColorFilter(sk_sp< const SkData > uniforms) const
T * release()
Definition: SkRefCnt.h:324
void attachDiscardableAdapter(sk_sp< T > adapter) const
Definition: SkottiePriv.h:139
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
SkScalar ScalarValue
Definition: SkottieValue.h:22
Definition: Skottie.h:32
Definition: ref_ptr.h:256
sk_sp< SkRuntimeEffect > effect