| Flutter Impeller |

paint.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/display_list/paint.h"
6
7 #include <memory>
8
9 #include "flutter/display_list/effects/dl_color_filter.h"
10 #include "flutter/display_list/effects/dl_color_sources.h"
11 #include "flutter/display_list/geometry/dl_path.h"
12 #include "fml/logging.h"
13 #include "impeller/display_list/color_filter.h"
14 #include "impeller/display_list/skia_conversions.h"
15 #include "impeller/entity/contents/color_source_contents.h"
16 #include "impeller/entity/contents/conical_gradient_contents.h"
17 #include "impeller/entity/contents/filters/color_filter_contents.h"
18 #include "impeller/entity/contents/filters/filter_contents.h"
19 #include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
20 #include "impeller/entity/contents/linear_gradient_contents.h"
21 #include "impeller/entity/contents/radial_gradient_contents.h"
22 #include "impeller/entity/contents/runtime_effect_contents.h"
23 #include "impeller/entity/contents/solid_color_contents.h"
24 #include "impeller/entity/contents/sweep_gradient_contents.h"
25 #include "impeller/entity/contents/tiled_texture_contents.h"
26 #include "impeller/entity/geometry/geometry.h"
27 #include "impeller/entity/geometry/rect_geometry.h"
28
29 namespace impeller {
30
31 using DlScalar = flutter::DlScalar;
32 using DlPoint = flutter::DlPoint;
33 using DlRect = flutter::DlRect;
34 using DlIRect = flutter::DlIRect;
35 using DlPath = flutter::DlPath;
36
37 std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
38 if (color_source == nullptr) {
39 auto contents = std::make_shared<SolidColorContents>();
40 contents->SetColor(color);
41 return contents;
42 }
43
44 switch (color_source->type()) {
45 case flutter::DlColorSourceType::kLinearGradient: {
46 const flutter::DlLinearGradientColorSource* linear =
47 color_source->asLinearGradient();
48 FML_DCHECK(linear);
49 auto start_point = linear->start_point();
50 auto end_point = linear->end_point();
51 std::vector<Color> colors;
52 std::vector<float> stops;
53 skia_conversions::ConvertStops(linear, colors, stops);
54
55 auto tile_mode = static_cast<Entity::TileMode>(linear->tile_mode());
56 auto effect_transform = linear->matrix();
57
58 auto contents = std::make_shared<LinearGradientContents>();
59 contents->SetOpacityFactor(color.alpha);
60 contents->SetColors(std::move(colors));
61 contents->SetStops(std::move(stops));
62 contents->SetEndPoints(start_point, end_point);
63 contents->SetTileMode(tile_mode);
64 contents->SetEffectTransform(effect_transform);
65
66 std::array<Point, 2> bounds{start_point, end_point};
67 auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
68 if (intrinsic_size.has_value()) {
69 contents->SetColorSourceSize(intrinsic_size->GetSize().Max({1, 1}));
70 }
71 return contents;
72 }
73 case flutter::DlColorSourceType::kRadialGradient: {
74 const flutter::DlRadialGradientColorSource* radialGradient =
75 color_source->asRadialGradient();
76 FML_DCHECK(radialGradient);
77 auto center = radialGradient->center();
78 auto radius = radialGradient->radius();
79 std::vector<Color> colors;
80 std::vector<float> stops;
81 skia_conversions::ConvertStops(radialGradient, colors, stops);
82
83 auto tile_mode =
84 static_cast<Entity::TileMode>(radialGradient->tile_mode());
85 auto effect_transform = radialGradient->matrix();
86
87 auto contents = std::make_shared<RadialGradientContents>();
88 contents->SetOpacityFactor(color.alpha);
89 contents->SetColors(std::move(colors));
90 contents->SetStops(std::move(stops));
91 contents->SetCenterAndRadius(center, radius);
92 contents->SetTileMode(tile_mode);
93 contents->SetEffectTransform(effect_transform);
94
95 auto radius_pt = Point(radius, radius);
96 std::array<Point, 2> bounds{center + radius_pt, center - radius_pt};
97 auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
98 if (intrinsic_size.has_value()) {
99 contents->SetColorSourceSize(intrinsic_size->GetSize().Max({1, 1}));
100 }
101 return contents;
102 }
103 case flutter::DlColorSourceType::kConicalGradient: {
104 const flutter::DlConicalGradientColorSource* conical_gradient =
105 color_source->asConicalGradient();
106 FML_DCHECK(conical_gradient);
107 Point center = conical_gradient->end_center();
108 DlScalar radius = conical_gradient->end_radius();
109 Point focus_center = conical_gradient->start_center();
110 DlScalar focus_radius = conical_gradient->start_radius();
111 std::vector<Color> colors;
112 std::vector<float> stops;
113 skia_conversions::ConvertStops(conical_gradient, colors, stops);
114
115 auto tile_mode =
116 static_cast<Entity::TileMode>(conical_gradient->tile_mode());
117 auto effect_transform = conical_gradient->matrix();
118
119 std::shared_ptr<ConicalGradientContents> contents =
120 std::make_shared<ConicalGradientContents>();
121 contents->SetOpacityFactor(color.alpha);
122 contents->SetColors(std::move(colors));
123 contents->SetStops(std::move(stops));
124 contents->SetCenterAndRadius(center, radius);
125 contents->SetTileMode(tile_mode);
126 contents->SetEffectTransform(effect_transform);
127 contents->SetFocus(focus_center, focus_radius);
128
129 auto radius_pt = Point(radius, radius);
130 std::array<Point, 2> bounds{center + radius_pt, center - radius_pt};
131 auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
132 if (intrinsic_size.has_value()) {
133 contents->SetColorSourceSize(intrinsic_size->GetSize().Max({1, 1}));
134 }
135 return contents;
136 }
137 case flutter::DlColorSourceType::kSweepGradient: {
138 const flutter::DlSweepGradientColorSource* sweepGradient =
139 color_source->asSweepGradient();
140 FML_DCHECK(sweepGradient);
141
142 auto center = sweepGradient->center();
143 auto start_angle = Degrees(sweepGradient->start());
144 auto end_angle = Degrees(sweepGradient->end());
145 std::vector<Color> colors;
146 std::vector<float> stops;
147 skia_conversions::ConvertStops(sweepGradient, colors, stops);
148
149 auto tile_mode =
150 static_cast<Entity::TileMode>(sweepGradient->tile_mode());
151 auto effect_transform = sweepGradient->matrix();
152
153 auto contents = std::make_shared<SweepGradientContents>();
154 contents->SetOpacityFactor(color.alpha);
155 contents->SetCenterAndAngles(center, start_angle, end_angle);
156 contents->SetColors(std::move(colors));
157 contents->SetStops(std::move(stops));
158 contents->SetTileMode(tile_mode);
159 contents->SetEffectTransform(effect_transform);
160
161 return contents;
162 }
163 case flutter::DlColorSourceType::kImage: {
164 const flutter::DlImageColorSource* image_color_source =
165 color_source->asImage();
166 FML_DCHECK(image_color_source &&
167 image_color_source->image()->impeller_texture());
168 auto texture = image_color_source->image()->impeller_texture();
169 auto x_tile_mode = static_cast<Entity::TileMode>(
170 image_color_source->horizontal_tile_mode());
171 auto y_tile_mode = static_cast<Entity::TileMode>(
172 image_color_source->vertical_tile_mode());
173 auto sampler_descriptor =
174 skia_conversions::ToSamplerDescriptor(image_color_source->sampling());
175 auto effect_transform = image_color_source->matrix();
176
177 auto contents = std::make_shared<TiledTextureContents>();
178 contents->SetOpacityFactor(color.alpha);
179 contents->SetTexture(texture);
180 contents->SetTileModes(x_tile_mode, y_tile_mode);
181 contents->SetSamplerDescriptor(sampler_descriptor);
182 contents->SetEffectTransform(effect_transform);
183 if (color_filter || invert_colors) {
184 TiledTextureContents::ColorFilterProc filter_proc =
185 [color_filter = color_filter,
186 invert_colors = invert_colors](const FilterInput::Ref& input) {
187 if (invert_colors && color_filter) {
188 std::shared_ptr<FilterContents> color_filter_output =
189 WrapWithGPUColorFilter(
190 color_filter, input,
191 ColorFilterContents::AbsorbOpacity::kNo);
192 return WrapWithInvertColors(
193 FilterInput::Make(color_filter_output),
194 ColorFilterContents::AbsorbOpacity::kNo);
195 }
196 if (color_filter) {
197 return WrapWithGPUColorFilter(
198 color_filter, input,
199 ColorFilterContents::AbsorbOpacity::kNo);
200 }
201 return WrapWithInvertColors(
202 input, ColorFilterContents::AbsorbOpacity::kNo);
203 };
204 contents->SetColorFilter(filter_proc);
205 }
206 contents->SetColorSourceSize(Size::Ceil(texture->GetSize()));
207 return contents;
208 }
209 case flutter::DlColorSourceType::kRuntimeEffect: {
210 const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
211 color_source->asRuntimeEffect();
212 auto runtime_stage =
213 runtime_effect_color_source->runtime_effect()->runtime_stage();
214 auto uniform_data = runtime_effect_color_source->uniform_data();
215 auto samplers = runtime_effect_color_source->samplers();
216
217 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
218
219 for (auto& sampler : samplers) {
220 if (sampler == nullptr) {
221 return nullptr;
222 }
223 auto* image = sampler->asImage();
224 if (!sampler->asImage()) {
225 return nullptr;
226 }
227 FML_DCHECK(image->image()->impeller_texture());
228 texture_inputs.push_back({
229 .sampler_descriptor =
230 skia_conversions::ToSamplerDescriptor(image->sampling()),
231 .texture = image->image()->impeller_texture(),
232 });
233 }
234
235 auto contents = std::make_shared<RuntimeEffectContents>();
236 contents->SetOpacityFactor(color.alpha);
237 contents->SetRuntimeStage(std::move(runtime_stage));
238 contents->SetUniformData(std::move(uniform_data));
239 contents->SetTextureInputs(std::move(texture_inputs));
240 return contents;
241 }
242 }
243 FML_UNREACHABLE();
244 }
245
246 std::shared_ptr<Contents> Paint::WithFilters(
247 std::shared_ptr<Contents> input) const {
248 input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
249 auto image_filter =
250 WithImageFilter(input, Matrix(), Entity::RenderingMode::kDirect);
251 if (image_filter) {
252 input = image_filter;
253 }
254 return input;
255 }
256
257 std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
258 std::shared_ptr<Contents> input,
259 const Matrix& effect_transform) const {
260 auto image_filter =
261 WithImageFilter(input, effect_transform,
262 Entity::RenderingMode::kSubpassPrependSnapshotTransform);
263 if (image_filter) {
264 input = image_filter;
265 }
266 input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
267 return input;
268 }
269
270 std::shared_ptr<Contents> Paint::WithMaskBlur(std::shared_ptr<Contents> input,
271 bool is_solid_color,
272 const Matrix& ctm) const {
273 if (mask_blur_descriptor.has_value()) {
274 input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input),
275 is_solid_color, ctm);
276 }
277 return input;
278 }
279
280 std::shared_ptr<FilterContents> Paint::WithImageFilter(
281 const FilterInput::Variant& input,
282 const Matrix& effect_transform,
283 Entity::RenderingMode rendering_mode) const {
284 if (!image_filter) {
285 return nullptr;
286 }
287 auto filter = WrapInput(image_filter, FilterInput::Make(input));
288 filter->SetRenderingMode(rendering_mode);
289 filter->SetEffectTransform(effect_transform);
290 return filter;
291 }
292
293 std::shared_ptr<Contents> Paint::WithColorFilter(
294 std::shared_ptr<Contents> input,
295 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
296 // Image input types will directly set their color filter,
297 // if any. See `TiledTextureContents.SetColorFilter`.
298 if (color_source &&
299 color_source->type() == flutter::DlColorSourceType::kImage) {
300 return input;
301 }
302
303 if (!color_filter && !invert_colors) {
304 return input;
305 }
306
307 // Attempt to apply the color filter on the CPU first.
308 // Note: This is not just an optimization; some color sources rely on
309 // CPU-applied color filters to behave properly.
310 if (input->ApplyColorFilter([&](Color color) -> Color {
311 if (color_filter) {
312 color = GetCPUColorFilterProc(color_filter)(color);
313 }
314 if (invert_colors) {
315 color = color.ApplyColorMatrix(kColorInversion);
316 }
317 return color;
318 })) {
319 return input;
320 }
321
322 if (color_filter) {
323 input = WrapWithGPUColorFilter(color_filter, FilterInput::Make(input),
324 absorb_opacity);
325 }
326 if (invert_colors) {
327 input = WrapWithInvertColors(FilterInput::Make(input), absorb_opacity);
328 }
329
330 return input;
331 }
332
333 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
334 std::shared_ptr<TextureContents> texture_contents,
335 RectGeometry* rect_geom) const {
336 Scalar expand_amount = GaussianBlurFilterContents::CalculateBlurRadius(
337 GaussianBlurFilterContents::ScaleSigma(sigma.sigma));
338 texture_contents->SetSourceRect(
339 texture_contents->GetSourceRect().Expand(expand_amount, expand_amount));
340 auto mask = std::make_shared<SolidColorContents>();
341 mask->SetColor(Color::White());
342 std::optional<Rect> coverage = texture_contents->GetCoverage({});
343 Geometry* geometry = nullptr;
344 if (coverage) {
345 texture_contents->SetDestinationRect(
346 coverage.value().Expand(expand_amount, expand_amount));
347 *rect_geom = RectGeometry(coverage.value());
348 geometry = rect_geom;
349 }
350 mask->SetGeometry(geometry);
351 auto descriptor = texture_contents->GetSamplerDescriptor();
352 texture_contents->SetSamplerDescriptor(descriptor);
353 std::shared_ptr<FilterContents> blurred_mask =
354 FilterContents::MakeGaussianBlur(FilterInput::Make(mask), sigma, sigma,
355 Entity::TileMode::kDecal, style,
356 geometry);
357
358 return ColorFilterContents::MakeBlend(
359 BlendMode::kSourceIn,
360 {FilterInput::Make(blurred_mask), FilterInput::Make(texture_contents)});
361 }
362
363 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
364 std::shared_ptr<ColorSourceContents> color_source_contents,
365 const flutter::DlColorFilter* color_filter,
366 bool invert_colors,
367 RectGeometry* rect_geom) const {
368 // If it's a solid color then we can just get away with doing one Gaussian
369 // blur. The color filter will always be applied on the CPU.
370 if (color_source_contents->IsSolidColor()) {
371 return FilterContents::MakeGaussianBlur(
372 FilterInput::Make(color_source_contents), sigma, sigma,
373 Entity::TileMode::kDecal, style, color_source_contents->GetGeometry());
374 }
375
376 /// 1. Create an opaque white mask of the original geometry.
377
378 auto mask = std::make_shared<SolidColorContents>();
379 mask->SetColor(Color::White());
380 mask->SetGeometry(color_source_contents->GetGeometry());
381
382 /// 2. Blur the mask.
383
384 auto blurred_mask = FilterContents::MakeGaussianBlur(
385 FilterInput::Make(mask), sigma, sigma, Entity::TileMode::kDecal, style,
386 color_source_contents->GetGeometry());
387
388 /// 3. Replace the geometry of the original color source with a rectangle that
389 /// covers the full region of the blurred mask. Note that geometry is in
390 /// local bounds.
391
392 auto expanded_local_bounds = blurred_mask->GetCoverage({});
393 if (!expanded_local_bounds.has_value()) {
394 expanded_local_bounds = Rect();
395 }
396 *rect_geom = RectGeometry(expanded_local_bounds.value());
397 color_source_contents->SetGeometry(rect_geom);
398 std::shared_ptr<Contents> color_contents = color_source_contents;
399
400 /// 4. Apply the user set color filter on the GPU, if applicable.
401 if (color_filter) {
402 color_contents =
403 WrapWithGPUColorFilter(color_filter, FilterInput::Make(color_contents),
404 ColorFilterContents::AbsorbOpacity::kYes);
405 }
406 if (invert_colors) {
407 color_contents =
408 WrapWithInvertColors(FilterInput::Make(color_contents),
409 ColorFilterContents::AbsorbOpacity::kYes);
410 }
411
412 /// 5. Composite the color source with the blurred mask.
413
414 return ColorFilterContents::MakeBlend(
415 BlendMode::kSourceIn,
416 {FilterInput::Make(blurred_mask), FilterInput::Make(color_contents)});
417 }
418
419 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
420 const FilterInput::Ref& input,
421 bool is_solid_color,
422 const Matrix& ctm) const {
423 Vector2 blur_sigma(sigma.sigma, sigma.sigma);
424 if (!respect_ctm) {
425 blur_sigma /=
426 Vector2(ctm.GetBasisX().GetLength(), ctm.GetBasisY().GetLength());
427 }
428 if (is_solid_color) {
429 return FilterContents::MakeGaussianBlur(input, Sigma(blur_sigma.x),
430 Sigma(blur_sigma.y),
431 Entity::TileMode::kDecal, style);
432 }
433 return FilterContents::MakeBorderMaskBlur(input, Sigma(blur_sigma.x),
434 Sigma(blur_sigma.y), style);
435 }
436
437 bool Paint::HasColorFilter() const {
438 return color_filter || invert_colors;
439 }
440
441 } // namespace impeller
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
geometry.h
impeller::skia_conversions::ConvertStops
void ConvertStops(const flutter::DlGradientColorSourceBase *gradient, std::vector< Color > &colors, std::vector< float > &stops)
Convert display list colors + stops into impeller colors and stops, taking care to ensure that the st...
Definition: skia_conversions.cc:116
solid_color_contents.h
impeller::skia_conversions::ToSamplerDescriptor
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Definition: skia_conversions.cc:141
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:28
impeller::Paint::color
Color color
Definition: paint.h:74
impeller::WrapWithInvertColors
std::shared_ptr< ColorFilterContents > WrapWithInvertColors(const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
Definition: color_filter.cc:16
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
tiled_texture_contents.h
impeller::Vector2
Point Vector2
Definition: point.h:331
impeller::TSize< Scalar >::Ceil
constexpr TSize Ceil() const
Definition: size.h:114
impeller::ColorFilterContents::AbsorbOpacity::kNo
@ kNo
impeller::Color::alpha
Scalar alpha
Definition: color.h:142
rect_geometry.h
impeller::DlIRect
flutter::DlIRect DlIRect
Definition: dl_dispatcher.h:26
gaussian_blur_filter_contents.h
impeller::Paint::color_filter
const flutter::DlColorFilter * color_filter
Definition: paint.h:76
sweep_gradient_contents.h
impeller::TiledTextureContents::ColorFilterProc
std::function< std::shared_ptr< ColorFilterContents >(FilterInput::Ref)> ColorFilterProc
Definition: tiled_texture_contents.h:26
impeller::TRect< Scalar >::MakePointBounds
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:165
runtime_effect_contents.h
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
filter_contents.h
color_filter.h
skia_conversions.h
color_source_contents.h
conical_gradient_contents.h
impeller::WrapWithGPUColorFilter
std::shared_ptr< ColorFilterContents > WrapWithGPUColorFilter(const flutter::DlColorFilter *filter, const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
Definition: color_filter.cc:24
impeller::DlRect
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
impeller::Paint::color_source
const flutter::DlColorSource * color_source
Definition: paint.h:75
impeller::RectGeometry
Definition: rect_geometry.h:12
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
impeller::Entity::RenderingMode::kDirect
@ kDirect
impeller::Paint::image_filter
const flutter::DlImageFilter * image_filter
Definition: paint.h:77
impeller::FilterInput::Variant
std::variant< std::shared_ptr< FilterContents >, std::shared_ptr< Contents >, std::shared_ptr< Texture >, Rect > Variant
Definition: filter_input.h:37
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792
impeller::Vector3::GetLength
constexpr Scalar GetLength() const
Definition: vector.h:47
color_filter_contents.h
impeller::Entity::TileMode
TileMode
Definition: entity.h:42
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::WrapInput
std::shared_ptr< FilterContents > WrapInput(const flutter::DlImageFilter *filter, const FilterInput::Ref &input)
Generate a new FilterContents using this filter's configuration.
Definition: image_filter.cc:17
impeller::Paint::WithMaskBlur
std::shared_ptr< Contents > WithMaskBlur(std::shared_ptr< Contents > input, bool is_solid_color, const Matrix &ctm) const
Definition: paint.cc:270
impeller::Paint::WithImageFilter
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
Definition: paint.cc:280
impeller::Geometry
Definition: geometry.h:50
impeller::Entity::RenderingMode::kSubpassPrependSnapshotTransform
@ kSubpassPrependSnapshotTransform
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::TPoint< Scalar >
impeller::Paint::invert_colors
bool invert_colors
Definition: paint.h:85
impeller::Degrees
Definition: scalar.h:51
radial_gradient_contents.h
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:27
impeller::ColorFilterContents::AbsorbOpacity::kYes
@ kYes
impeller::Paint::CreateContents
std::shared_ptr< ColorSourceContents > CreateContents() const
Definition: paint.cc:37
impeller::Color::ApplyColorMatrix
Color ApplyColorMatrix(const ColorMatrix &color_matrix) const
A color filter that transforms colors through a 4x5 color matrix.
Definition: color.cc:301
paint.h
impeller::ColorFilterContents::AbsorbOpacity
AbsorbOpacity
Definition: color_filter_contents.h:14
impeller::Matrix::GetBasisY
constexpr Vector3 GetBasisY() const
Definition: matrix.h:324
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23
impeller
Definition: allocation.cc:12
impeller::Paint::mask_blur_descriptor
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:87
impeller::Matrix::GetBasisX
constexpr Vector3 GetBasisX() const
Definition: matrix.h:322
impeller::Paint::WithFilters
std::shared_ptr< Contents > WithFilters(std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
Definition: paint.cc:246
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Paint::WithFiltersForSubpassTarget
std::shared_ptr< Contents > WithFiltersForSubpassTarget(std::shared_ptr< Contents > input, const Matrix &effect_transform=Matrix()) const
Wrap this paint's configured filters to the given contents of subpass target.
Definition: paint.cc:257
impeller::kColorInversion
static const constexpr ColorMatrix kColorInversion
A color matrix which inverts colors.
Definition: color_filter.h:16
linear_gradient_contents.h