Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkSGColorFilter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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
9
17
18#include <cmath>
19#include <cstddef>
20#include <cstdint>
21#include <utility>
22
23class SkCanvas;
24enum class SkBlendMode;
25struct SkPoint;
26
27namespace sksg {
28
31
32void ColorFilter::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
33 const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateColorFilter(fColorFilter);
34
35 this->INHERITED::onRender(canvas, local_ctx);
36}
37
39 // TODO: we likely need to do something more sophisticated than delegate to descendants here.
40 return this->INHERITED::onNodeAt(p);
41}
42
44 SkASSERT(this->hasInval());
45
46 fColorFilter = this->onRevalidateFilter();
47
48 return this->INHERITED::onRevalidate(ic, ctm);
49}
50
55
56ExternalColorFilter::ExternalColorFilter(sk_sp<RenderNode> child) : INHERITED(std::move(child)) {}
57
59
60void ExternalColorFilter::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
61 const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateColorFilter(fColorFilter);
62
63 this->INHERITED::onRender(canvas, local_ctx);
64}
65
67 SkBlendMode mode) {
68 return (child && color) ? sk_sp<ModeColorFilter>(new ModeColorFilter(std::move(child),
69 std::move(color), mode))
70 : nullptr;
71}
72
73ModeColorFilter::ModeColorFilter(sk_sp<RenderNode> child, sk_sp<Color> color, SkBlendMode mode)
74 : INHERITED(std::move(child))
75 , fColor(std::move(color))
76 , fMode(mode) {
77 this->observeInval(fColor);
78}
79
83
85 fColor->revalidate(nullptr, SkMatrix::I());
86 return SkColorFilters::Blend(fColor->getColor(), fMode);
87}
88
91 return Make(std::move(child), { std::move(c0), std::move(c1) });
92}
93
95 std::vector<sk_sp<Color>> colors) {
96 return (child && colors.size() > 1)
97 ? sk_sp<GradientColorFilter>(new GradientColorFilter(std::move(child), std::move(colors)))
98 : nullptr;
99}
100
101GradientColorFilter::GradientColorFilter(sk_sp<RenderNode> child, std::vector<sk_sp<Color>> colors)
102 : INHERITED(std::move(child))
103 , fColors(std::move(colors)) {
104 for (const auto& color : fColors) {
105 this->observeInval(color);
106 }
107}
108
110 for (const auto& color : fColors) {
111 this->unobserveInval(color);
112 }
113}
114
115namespace {
116
117sk_sp<SkColorFilter> Make2ColorGradient(const sk_sp<Color>& color0, const sk_sp<Color>& color1) {
118 const auto c0 = SkColor4f::FromColor(color0->getColor()),
119 c1 = SkColor4f::FromColor(color1->getColor());
120
121 const auto dR = c1.fR - c0.fR,
122 dG = c1.fG - c0.fG,
123 dB = c1.fB - c0.fB;
124
125 // A 2-color gradient can be expressed as a color matrix (and combined with the luminance
126 // calculation). First, the luminance:
127 //
128 // L = [r,g,b] . [kR,kG,kB]
129 //
130 // We can compute it using a color matrix (result stored in R):
131 //
132 // | kR, kG, kB, 0, 0 | r' = L
133 // | 0, 0, 0, 0, 0 | g' = 0
134 // | 0, 0, 0, 0, 0 | b' = 0
135 // | 0, 0, 0, 1, 0 | a' = a
136 //
137 // Then we want to interpolate component-wise, based on L:
138 //
139 // r' = c0.r + (c1.r - c0.r) * L = c0.r + dR*L
140 // g' = c0.g + (c1.g - c0.g) * L = c0.g + dG*L
141 // b' = c0.b + (c1.b - c0.b) * L = c0.b + dB*L
142 // a' = a
143 //
144 // This can be expressed as another color matrix (when L is stored in R):
145 //
146 // | dR, 0, 0, 0, c0.r |
147 // | dG, 0, 0, 0, c0.g |
148 // | dB, 0, 0, 0, c0.b |
149 // | 0, 0, 0, 1, 0 |
150 //
151 // Composing these two, we get the total tint matrix:
152
153 const float tint_matrix[] = {
154 dR*SK_LUM_COEFF_R, dR*SK_LUM_COEFF_G, dR*SK_LUM_COEFF_B, 0, c0.fR,
155 dG*SK_LUM_COEFF_R, dG*SK_LUM_COEFF_G, dG*SK_LUM_COEFF_B, 0, c0.fG,
156 dB*SK_LUM_COEFF_R, dB*SK_LUM_COEFF_G, dB*SK_LUM_COEFF_B, 0, c0.fB,
157 0, 0, 0, 1, 0,
158 };
159
160 return SkColorFilters::Matrix(tint_matrix);
161}
162
163sk_sp<SkColorFilter> MakeNColorGradient(const std::vector<sk_sp<Color>>& colors) {
164 // For N colors, we build a gradient color table.
165 uint8_t rTable[256], gTable[256], bTable[256];
166
167 SkASSERT(colors.size() > 2);
168 const auto span_count = colors.size() - 1;
169
170 size_t span_start = 0;
171 for (size_t i = 0; i < span_count; ++i) {
172 const auto span_stop = static_cast<size_t>(std::round((i + 1) * 255.0f / span_count)),
173 span_size = span_stop - span_start;
174 if (span_start > span_stop) {
175 // Degenerate case.
176 continue;
177 }
178 SkASSERT(span_stop <= 255);
179
180 // Fill the gradient in [span_start,span_stop] -> [c0,c1]
181 const SkColor c0 = colors[i ]->getColor(),
182 c1 = colors[i + 1]->getColor();
183 float r = SkColorGetR(c0),
184 g = SkColorGetG(c0),
185 b = SkColorGetB(c0);
186 const float dR = (SkColorGetR(c1) - r) / span_size,
187 dG = (SkColorGetG(c1) - g) / span_size,
188 dB = (SkColorGetB(c1) - b) / span_size;
189
190 for (size_t j = span_start; j <= span_stop; ++j) {
191 rTable[j] = static_cast<uint8_t>(std::round(r));
192 gTable[j] = static_cast<uint8_t>(std::round(g));
193 bTable[j] = static_cast<uint8_t>(std::round(b));
194 r += dR;
195 g += dG;
196 b += dB;
197 }
198
199 // Ensure we always advance.
200 span_start = span_stop + 1;
201 }
202 SkASSERT(span_start == 256);
203
204 const float luminance_matrix[] = {
208 0, 0, 0, 1, 0, // a' = a
209 };
210
211 return SkColorFilters::TableARGB(nullptr, rTable, gTable, bTable)
212 ->makeComposed(SkColorFilters::Matrix(luminance_matrix));
213}
214
215} // namespace
216
218 for (const auto& color : fColors) {
219 color->revalidate(nullptr, SkMatrix::I());
220 }
221
222 if (fWeight <= 0) {
223 return nullptr;
224 }
225
226 SkASSERT(fColors.size() > 1);
227 auto gradientCF = (fColors.size() > 2) ? MakeNColorGradient(fColors)
228 : Make2ColorGradient(fColors[0], fColors[1]);
229
230 return SkColorFilters::Lerp(fWeight, nullptr, std::move(gradientCF));
231}
232
233} // namespace sksg
SkColor4f color
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
#define SK_LUM_COEFF_B
#define SK_LUM_COEFF_R
#define SK_LUM_COEFF_G
#define SkColorGetR(color)
Definition SkColor.h:65
#define SkColorGetG(color)
Definition SkColor.h:69
uint32_t SkColor
Definition SkColor.h:37
#define SkColorGetB(color)
Definition SkColor.h:73
#define INHERITED(method,...)
sk_sp< SkColorFilter > makeComposed(sk_sp< SkColorFilter > inner) const
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkColorFilter > Lerp(float t, sk_sp< SkColorFilter > dst, sk_sp< SkColorFilter > src)
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])
static const SkMatrix & I()
const RenderNode * onNodeAt(const SkPoint &) const final
virtual sk_sp< SkColorFilter > onRevalidateFilter()=0
ColorFilter(sk_sp< RenderNode >)
SkRect onRevalidate(InvalidationController *, const SkMatrix &) final
void onRender(SkCanvas *, const RenderContext *) const final
const RenderNode * onNodeAt(const SkPoint &) const override
void onRender(SkCanvas *, const RenderContext *) const override
SkRect onRevalidate(InvalidationController *, const SkMatrix &) override
void onRender(SkCanvas *, const RenderContext *) const override
static sk_sp< ExternalColorFilter > Make(sk_sp< RenderNode > child)
sk_sp< SkColorFilter > onRevalidateFilter() override
static sk_sp< GradientColorFilter > Make(sk_sp< RenderNode > child, sk_sp< Color > c0, sk_sp< Color > c1)
sk_sp< SkColorFilter > onRevalidateFilter() override
static sk_sp< ModeColorFilter > Make(sk_sp< RenderNode > child, sk_sp< Color > color, SkBlendMode mode)
void observeInval(const sk_sp< Node > &)
Definition SkSGNode.cpp:61
void unobserveInval(const sk_sp< Node > &)
Definition SkSGNode.cpp:84
bool hasInval() const
Definition SkSGNode.h:60
ScopedRenderContext && modulateColorFilter(sk_sp< SkColorFilter >)
static bool b
PODArray< SkColor > colors
Definition SkRecords.h:276
Definition Skottie.h:32
Definition ref_ptr.h:256
static SkRGBA4f FromColor(SkColor color)
SkBlendMode fMode
Definition xfermodes.cpp:52