Flutter Engine
The Flutter Engine
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
6
7#include <memory>
8
15
16namespace impeller {
17
18/// A color matrix which inverts colors.
19// clang-format off
21 .array = {
22 -1.0, 0, 0, 1.0, 0, //
23 0, -1.0, 0, 1.0, 0, //
24 0, 0, -1.0, 1.0, 0, //
25 1.0, 1.0, 1.0, 1.0, 0 //
26 }
27};
28// clang-format on
29
30std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
31 const std::shared_ptr<Geometry>& geometry) const {
32 auto contents = color_source.GetContents(*this);
33
34 // Attempt to apply the color filter on the CPU first.
35 // Note: This is not just an optimization; some color sources rely on
36 // CPU-applied color filters to behave properly.
38 bool needs_color_filter = !!color_filter;
39 if (color_filter &&
40 contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
41 needs_color_filter = false;
42 }
43
44 contents->SetGeometry(geometry);
45 if (mask_blur_descriptor.has_value()) {
46 // If there's a mask blur and we need to apply the color filter on the GPU,
47 // we need to be careful to only apply the color filter to the source
48 // colors. CreateMaskBlur is able to handle this case.
49 return mask_blur_descriptor->CreateMaskBlur(
50 contents, needs_color_filter ? color_filter : nullptr);
51 }
52
53 return contents;
54}
55
56std::shared_ptr<Contents> Paint::WithFilters(
57 std::shared_ptr<Contents> input) const {
58 input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
59 auto image_filter =
61 if (image_filter) {
62 input = image_filter;
63 }
64 return input;
65}
66
67std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
68 std::shared_ptr<Contents> input,
69 const Matrix& effect_transform) const {
70 auto image_filter =
71 WithImageFilter(input, effect_transform,
73 if (image_filter) {
74 input = image_filter;
75 }
76 input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
77 return input;
78}
79
80std::shared_ptr<Contents> Paint::WithMaskBlur(std::shared_ptr<Contents> input,
81 bool is_solid_color,
82 const Matrix& ctm) const {
83 if (mask_blur_descriptor.has_value()) {
84 input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input),
85 is_solid_color, ctm);
86 }
87 return input;
88}
89
90std::shared_ptr<FilterContents> Paint::WithImageFilter(
91 const FilterInput::Variant& input,
92 const Matrix& effect_transform,
93 Entity::RenderingMode rendering_mode) const {
94 if (!image_filter) {
95 return nullptr;
96 }
97 auto filter = image_filter->WrapInput(FilterInput::Make(input));
98 filter->SetRenderingMode(rendering_mode);
99 filter->SetEffectTransform(effect_transform);
100 return filter;
101}
102
103std::shared_ptr<Contents> Paint::WithColorFilter(
104 std::shared_ptr<Contents> input,
105 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
106 // Image input types will directly set their color filter,
107 // if any. See `TiledTextureContents.SetColorFilter`.
109 return input;
110 }
111
113 if (!color_filter) {
114 return input;
115 }
116
117 // Attempt to apply the color filter on the CPU first.
118 // Note: This is not just an optimization; some color sources rely on
119 // CPU-applied color filters to behave properly.
120 if (input->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
121 return input;
122 }
123 return color_filter->WrapWithGPUColorFilter(FilterInput::Make(input),
124 absorb_opacity);
125}
126
127std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
128 std::shared_ptr<TextureContents> texture_contents) const {
131 texture_contents->SetSourceRect(
132 texture_contents->GetSourceRect().Expand(expand_amount, expand_amount));
133 auto mask = std::make_shared<SolidColorContents>();
134 mask->SetColor(Color::White());
135 std::optional<Rect> coverage = texture_contents->GetCoverage({});
136 std::shared_ptr<Geometry> geometry;
137 if (coverage) {
138 texture_contents->SetDestinationRect(
139 coverage.value().Expand(expand_amount, expand_amount));
140 geometry = Geometry::MakeRect(coverage.value());
141 }
142 mask->SetGeometry(geometry);
143 auto descriptor = texture_contents->GetSamplerDescriptor();
144 texture_contents->SetSamplerDescriptor(descriptor);
145 std::shared_ptr<FilterContents> blurred_mask =
148 geometry);
149
152 {FilterInput::Make(blurred_mask), FilterInput::Make(texture_contents)});
153}
154
155std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
156 std::shared_ptr<ColorSourceContents> color_source_contents,
157 const std::shared_ptr<ColorFilter>& color_filter) const {
158 // If it's a solid color and there is no color filter, then we can just get
159 // away with doing one Gaussian blur.
160 if (color_source_contents->IsSolidColor() && !color_filter) {
162 FilterInput::Make(color_source_contents), sigma, sigma,
163 Entity::TileMode::kDecal, style, color_source_contents->GetGeometry());
164 }
165
166 /// 1. Create an opaque white mask of the original geometry.
167
168 auto mask = std::make_shared<SolidColorContents>();
169 mask->SetColor(Color::White());
170 mask->SetGeometry(color_source_contents->GetGeometry());
171
172 /// 2. Blur the mask.
173
174 auto blurred_mask = FilterContents::MakeGaussianBlur(
176 color_source_contents->GetGeometry());
177
178 /// 3. Replace the geometry of the original color source with a rectangle that
179 /// covers the full region of the blurred mask. Note that geometry is in
180 /// local bounds.
181
182 auto expanded_local_bounds = blurred_mask->GetCoverage({});
183 if (!expanded_local_bounds.has_value()) {
184 expanded_local_bounds = Rect();
185 }
186 color_source_contents->SetGeometry(
187 Geometry::MakeRect(*expanded_local_bounds));
188 std::shared_ptr<Contents> color_contents = color_source_contents;
189
190 /// 4. Apply the user set color filter on the GPU, if applicable.
191
192 if (color_filter) {
193 color_contents = color_filter->WrapWithGPUColorFilter(
194 FilterInput::Make(color_source_contents),
196 }
197
198 /// 5. Composite the color source with the blurred mask.
199
202 {FilterInput::Make(blurred_mask), FilterInput::Make(color_contents)});
203}
204
205std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
206 const FilterInput::Ref& input,
207 bool is_solid_color,
208 const Matrix& ctm) const {
209 Vector2 blur_sigma(sigma.sigma, sigma.sigma);
210 if (!respect_ctm) {
211 blur_sigma /= Vector2(ctm.GetBasisX().Length(), ctm.GetBasisY().Length());
212 }
213 if (is_solid_color) {
214 return FilterContents::MakeGaussianBlur(input, Sigma(blur_sigma.x),
215 Sigma(blur_sigma.y),
217 }
218 return FilterContents::MakeBorderMaskBlur(input, Sigma(blur_sigma.x),
219 Sigma(blur_sigma.y), style);
220}
221
222std::shared_ptr<ColorFilter> Paint::GetColorFilter() const {
226 }
227 if (invert_colors) {
229 }
230 if (color_filter) {
231 return color_filter;
232 }
233 return nullptr;
234}
235
237 return !!color_filter || invert_colors;
238}
239
240} // namespace impeller
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
static std::shared_ptr< ColorFilter > MakeComposed(const std::shared_ptr< ColorFilter > &outer, const std::shared_ptr< ColorFilter > &inner)
Definition: color_filter.cc:40
static std::shared_ptr< ColorFilter > MakeMatrix(ColorMatrix color_matrix)
Definition: color_filter.cc:28
std::shared_ptr< ColorSourceContents > GetContents(const Paint &paint) const
static std::shared_ptr< FilterContents > MakeGaussianBlur(const FilterInput::Ref &input, Sigma sigma_x, Sigma sigma_y, Entity::TileMode tile_mode=Entity::TileMode::kDecal, BlurStyle mask_blur_style=BlurStyle::kNormal, const std::shared_ptr< Geometry > &mask_geometry=nullptr)
static std::shared_ptr< FilterContents > MakeBorderMaskBlur(FilterInput::Ref input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal)
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
std::variant< std::shared_ptr< FilterContents >, std::shared_ptr< Contents >, std::shared_ptr< Texture >, Rect > Variant
Definition: filter_input.h:37
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:89
Point Vector2
Definition: point.h:326
float Scalar
Definition: scalar.h:18
constexpr ColorMatrix kColorInversion
A color matrix which inverts colors.
Definition: paint.cc:20
TRect< Scalar > Rect
Definition: rect.h:769
SK_API sk_sp< PrecompileColorFilter > Matrix()
Scalar array[20]
Definition: color.h:118
static constexpr Color White()
Definition: color.h:266
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
constexpr Vector3 GetBasisY() const
Definition: matrix.h:307
constexpr Vector3 GetBasisX() const
Definition: matrix.h:305
std::shared_ptr< FilterContents > CreateMaskBlur(std::shared_ptr< ColorSourceContents > color_source_contents, const std::shared_ptr< ColorFilter > &color_filter) const
Definition: paint.cc:155
FilterContents::BlurStyle style
Definition: paint.h:49
ColorSource color_source
Definition: paint.h:69
std::shared_ptr< ColorFilter > GetColorFilter() const
Definition: paint.cc:222
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
Definition: paint.cc:236
std::shared_ptr< Contents > CreateContentsForGeometry(const std::shared_ptr< Geometry > &geometry) const
Definition: paint.cc:30
Style style
Definition: paint.h:75
bool invert_colors
Definition: paint.h:77
std::shared_ptr< ImageFilter > image_filter
Definition: paint.h:79
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:81
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:67
std::shared_ptr< Contents > WithFilters(std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
Definition: paint.cc:56
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
Definition: paint.cc:90
std::shared_ptr< ColorFilter > color_filter
Definition: paint.h:80
std::shared_ptr< Contents > WithMaskBlur(std::shared_ptr< Contents > input, bool is_solid_color, const Matrix &ctm) const
Definition: paint.cc:80
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
Scalar sigma
Definition: sigma.h:33
constexpr Scalar Length() const
Definition: vector.h:47