| 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/aiks/paint.h"
6
7 #include <memory>
8
9 #include "impeller/entity/contents/color_source_contents.h"
10 #include "impeller/entity/contents/filters/color_filter_contents.h"
11 #include "impeller/entity/contents/filters/filter_contents.h"
12 #include "impeller/entity/contents/solid_color_contents.h"
13 #include "impeller/entity/geometry/geometry.h"
14
15 namespace impeller {
16
17 std::shared_ptr<Contents> Paint::CreateContentsForEntity(const Path& path,
18 bool cover) const {
19 std::unique_ptr<Geometry> geometry;
20 switch (style) {
21 case Style::kFill:
22 geometry = cover ? Geometry::MakeCover() : Geometry::MakeFillPath(path);
23 break;
24 case Style::kStroke:
25 geometry =
26 cover ? Geometry::MakeCover()
27 : Geometry::MakeStrokePath(path, stroke_width, stroke_miter,
28 stroke_cap, stroke_join);
29 break;
30 }
31 return CreateContentsForGeometry(std::move(geometry));
32 }
33
34 std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
35 std::shared_ptr<Geometry> geometry) const {
36 auto contents = color_source.GetContents(*this);
37
38 // Attempt to apply the color filter on the CPU first.
39 // Note: This is not just an optimization; some color sources rely on
40 // CPU-applied color filters to behave properly.
41 bool needs_color_filter = !!color_filter;
42 if (color_filter &&
43 contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
44 needs_color_filter = false;
45 }
46
47 contents->SetGeometry(std::move(geometry));
48 if (mask_blur_descriptor.has_value()) {
49 // If there's a mask blur and we need to apply the color filter on the GPU,
50 // we need to be careful to only apply the color filter to the source
51 // colors. CreateMaskBlur is able to handle this case.
52 return mask_blur_descriptor->CreateMaskBlur(
53 contents, needs_color_filter ? color_filter : nullptr);
54 }
55
56 return contents;
57 }
58
59 std::shared_ptr<Contents> Paint::WithFilters(
60 std::shared_ptr<Contents> input) const {
61 input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
62 input = WithInvertFilter(input);
63 auto image_filter =
64 WithImageFilter(input, Matrix(), Entity::RenderingMode::kDirect);
65 if (image_filter) {
66 input = image_filter;
67 }
68 return input;
69 }
70
71 std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
72 std::shared_ptr<Contents> input,
73 const Matrix& effect_transform) const {
74 auto image_filter =
75 WithImageFilter(input, effect_transform, Entity::RenderingMode::kSubpass);
76 if (image_filter) {
77 input = image_filter;
78 }
79 input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
80 return input;
81 }
82
83 std::shared_ptr<Contents> Paint::WithMaskBlur(std::shared_ptr<Contents> input,
84 bool is_solid_color) const {
85 if (mask_blur_descriptor.has_value()) {
86 input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input),
87 is_solid_color);
88 }
89 return input;
90 }
91
92 std::shared_ptr<FilterContents> Paint::WithImageFilter(
93 const FilterInput::Variant& input,
94 const Matrix& effect_transform,
95 Entity::RenderingMode rendering_mode) const {
96 if (!image_filter) {
97 return nullptr;
98 }
99 auto filter = image_filter->WrapInput(FilterInput::Make(input));
100 filter->SetRenderingMode(rendering_mode);
101 filter->SetEffectTransform(effect_transform);
102 return filter;
103 }
104
105 std::shared_ptr<Contents> Paint::WithColorFilter(
106 std::shared_ptr<Contents> input,
107 ColorFilterContents::AbsorbOpacity absorb_opacity) const {
108 // Image input types will directly set their color filter,
109 // if any. See `TiledTextureContents.SetColorFilter`.
110 if (color_source.GetType() == ColorSource::Type::kImage) {
111 return input;
112 }
113
114 if (!color_filter) {
115 return input;
116 }
117
118 // Attempt to apply the color filter on the CPU first.
119 // Note: This is not just an optimization; some color sources rely on
120 // CPU-applied color filters to behave properly.
121 if (input->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
122 return input;
123 }
124
125 return color_filter->WrapWithGPUColorFilter(FilterInput::Make(input),
126 absorb_opacity);
127 }
128
129 /// A color matrix which inverts colors.
130 // clang-format off
131 constexpr ColorMatrix kColorInversion = {
132 .array = {
133 -1.0, 0, 0, 1.0, 0, //
134 0, -1.0, 0, 1.0, 0, //
135 0, 0, -1.0, 1.0, 0, //
136 1.0, 1.0, 1.0, 1.0, 0 //
137 }
138 };
139 // clang-format on
140
141 std::shared_ptr<Contents> Paint::WithInvertFilter(
142 std::shared_ptr<Contents> input) const {
143 if (!invert_colors) {
144 return input;
145 }
146
147 return ColorFilterContents::MakeColorMatrix(
148 {FilterInput::Make(std::move(input))}, kColorInversion);
149 }
150
151 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
152 std::shared_ptr<ColorSourceContents> color_source_contents,
153 const std::shared_ptr<ColorFilter>& color_filter) const {
154 // If it's a solid color and there is no color filter, then we can just get
155 // away with doing one Gaussian blur.
156 if (color_source_contents->IsSolidColor() && !color_filter) {
157 return FilterContents::MakeGaussianBlur(
158 FilterInput::Make(color_source_contents), sigma, sigma, style,
159 Entity::TileMode::kDecal);
160 }
161
162 /// 1. Create an opaque white mask of the original geometry.
163
164 auto mask = std::make_shared<SolidColorContents>();
165 mask->SetColor(Color::White());
166 mask->SetGeometry(color_source_contents->GetGeometry());
167
168 /// 2. Blur the mask.
169
170 auto blurred_mask = FilterContents::MakeGaussianBlur(
171 FilterInput::Make(mask), sigma, sigma, style, Entity::TileMode::kDecal);
172
173 /// 3. Replace the geometry of the original color source with a rectangle that
174 /// covers the full region of the blurred mask. Note that geometry is in
175 /// local bounds.
176
177 auto expanded_local_bounds = blurred_mask->GetCoverage({});
178 if (!expanded_local_bounds.has_value()) {
179 return nullptr;
180 }
181 color_source_contents->SetGeometry(
182 Geometry::MakeRect(*expanded_local_bounds));
183
184 std::shared_ptr<Contents> color_contents = color_source_contents;
185
186 /// 4. Apply the user set color filter on the GPU, if applicable.
187
188 if (color_filter) {
189 color_contents = color_filter->WrapWithGPUColorFilter(
190 FilterInput::Make(color_source_contents),
191 ColorFilterContents::AbsorbOpacity::kYes);
192 }
193
194 /// 5. Composite the color source with the blurred mask.
195
196 return ColorFilterContents::MakeBlend(
197 BlendMode::kSourceIn,
198 {FilterInput::Make(blurred_mask), FilterInput::Make(color_contents)});
199 }
200
201 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
202 const FilterInput::Ref& input,
203 bool is_solid_color) const {
204 if (is_solid_color) {
205 return FilterContents::MakeGaussianBlur(input, sigma, sigma, style,
206 Entity::TileMode::kDecal);
207 }
208 return FilterContents::MakeBorderMaskBlur(input, sigma, sigma, style);
209 }
210
211 bool Paint::HasColorFilter() const {
212 return !!color_filter;
213 }
214
215 } // namespace impeller
impeller::Paint::stroke_cap
Cap stroke_cap
Definition: paint.h:59
impeller::Paint::WithMaskBlur
std::shared_ptr< Contents > WithMaskBlur(std::shared_ptr< Contents > input, bool is_solid_color) const
Definition: paint.cc:83
impeller::ColorSource::GetContents
std::shared_ptr< ColorSourceContents > GetContents(const Paint &paint) const
Definition: color_source.cc:238
impeller::Paint::Style::kStroke
@ kStroke
solid_color_contents.h
impeller::Paint::CreateContentsForEntity
std::shared_ptr< Contents > CreateContentsForEntity(const Path &path={}, bool cover=false) const
Definition: paint.cc:17
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::Paint::MaskBlurDescriptor::sigma
Sigma sigma
Definition: paint.h:43
impeller::Entity::TileMode::kDecal
@ kDecal
impeller::Paint::MaskBlurDescriptor::style
FilterContents::BlurStyle style
Definition: paint.h:42
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:31
impeller::BlendMode::kSourceIn
@ kSourceIn
impeller::Geometry::MakeRect
static std::unique_ptr< Geometry > MakeRect(Rect rect)
Definition: geometry.cc:142
impeller::Paint::MaskBlurDescriptor::CreateMaskBlur
std::shared_ptr< FilterContents > CreateMaskBlur(std::shared_ptr< ColorSourceContents > color_source_contents, const std::shared_ptr< ColorFilter > &color_filter) const
Definition: paint.cc:151
impeller::Paint::color_source
ColorSource color_source
Definition: paint.h:55
impeller::Paint::stroke_miter
Scalar stroke_miter
Definition: paint.h:61
impeller::Paint::color_filter
std::shared_ptr< ColorFilter > color_filter
Definition: paint.h:67
impeller::FilterContents::MakeGaussianBlur
static std::shared_ptr< FilterContents > MakeGaussianBlur(const FilterInput::Ref &input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal, Entity::TileMode tile_mode=Entity::TileMode::kDecal)
Definition: filter_contents.cc:52
impeller::kColorInversion
constexpr ColorMatrix kColorInversion
A color matrix which inverts colors.
Definition: paint.cc:131
filter_contents.h
color_source_contents.h
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:54
impeller::Geometry::MakeStrokePath
static std::unique_ptr< Geometry > MakeStrokePath(const Path &path, Scalar stroke_width=0.0, Scalar miter_limit=4.0, Cap stroke_cap=Cap::kButt, Join stroke_join=Join::kMiter)
Definition: geometry.cc:125
impeller::Paint::style
Style style
Definition: paint.h:62
impeller::Paint::Style::kFill
@ kFill
impeller::ColorMatrix::array
Scalar array[20]
Definition: color.h:116
geometry.h
impeller::Color::White
static constexpr Color White()
Definition: color.h:254
impeller::Entity::RenderingMode::kDirect
@ kDirect
impeller::FilterInput::Variant
std::variant< std::shared_ptr< FilterContents >, std::shared_ptr< Contents >, std::shared_ptr< Texture >, Rect > Variant
Definition: filter_input.h:36
impeller::FilterContents::MakeBorderMaskBlur
static std::shared_ptr< FilterContents > MakeBorderMaskBlur(FilterInput::Ref input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal)
Definition: filter_contents.cc:66
color_filter_contents.h
impeller::Entity::RenderingMode::kSubpass
@ kSubpass
impeller::Geometry::MakeCover
static std::unique_ptr< Geometry > MakeCover()
Definition: geometry.cc:138
impeller::ColorSource::Type::kImage
@ kImage
impeller::Paint::WithImageFilter
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
Definition: paint.cc:92
impeller::Geometry::MakeFillPath
static std::unique_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:113
impeller::Paint::invert_colors
bool invert_colors
Definition: paint.h:64
impeller::Paint::CreateContentsForGeometry
std::shared_ptr< Contents > CreateContentsForGeometry(std::shared_ptr< Geometry > geometry) const
Definition: paint.cc:34
impeller::ColorFilterContents::MakeColorMatrix
static std::shared_ptr< ColorFilterContents > MakeColorMatrix(FilterInput::Ref input, const ColorMatrix &color_matrix)
Definition: color_filter_contents.cc:58
paint.h
impeller::Paint::HasColorFilter
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
Definition: paint.cc:211
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:26
impeller::ColorFilterContents::AbsorbOpacity::kYes
@ kYes
impeller::ColorMatrix
Definition: color.h:115
impeller::ColorFilterContents::MakeBlend
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.
Definition: color_filter_contents.cc:17
impeller::ColorFilterContents::AbsorbOpacity
AbsorbOpacity
Definition: color_filter_contents.h:13
impeller
Definition: aiks_context.cc:10
impeller::Paint::mask_blur_descriptor
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:68
impeller::Paint::stroke_width
Scalar stroke_width
Definition: paint.h:58
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:59
impeller::ColorSource::GetType
Type GetType() const
Definition: color_source.cc:234
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:36
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:71
impeller::Paint::image_filter
std::shared_ptr< ImageFilter > image_filter
Definition: paint.h:66
impeller::Paint::stroke_join
Join stroke_join
Definition: paint.h:60