Flutter Impeller
impeller::Paint Struct Reference

#include <paint.h>

Classes

struct  MaskBlurDescriptor
 

Public Types

enum class  Style {
  kFill ,
  kStroke
}
 
using ImageFilterProc = std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)>
 
using MaskFilterProc = std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, bool is_solid_color, const Matrix &effect_transform)>
 
using ColorSourceProc = std::function< std::shared_ptr< ColorSourceContents >()>
 

Public Member Functions

std::shared_ptr< ContentsWithFilters (std::shared_ptr< Contents > input) const
 Wrap this paint's configured filters to the given contents. More...
 
std::shared_ptr< ContentsWithFiltersForSubpassTarget (std::shared_ptr< Contents > input, const Matrix &effect_transform=Matrix()) const
 Wrap this paint's configured filters to the given contents of subpass target. More...
 
bool HasColorFilter () const
 Whether this paint has a color filter that can apply opacity. More...
 
std::shared_ptr< ColorSourceContentsCreateContents () const
 
std::shared_ptr< ContentsWithMaskBlur (std::shared_ptr< Contents > input, bool is_solid_color, const Matrix &ctm) const
 
std::shared_ptr< FilterContentsWithImageFilter (const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
 

Static Public Member Functions

static bool CanApplyOpacityPeephole (const Paint &paint)
 Whether or not a save layer with the provided paint can perform the opacity peephole optimization. More...
 
static 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 stops monotonically increase from 0.0 to 1.0. More...
 

Public Attributes

Color color = Color::Black()
 
const flutter::DlColorSource * color_source = nullptr
 
const flutter::DlColorFilter * color_filter = nullptr
 
const flutter::DlImageFilter * image_filter = nullptr
 
StrokeParameters stroke
 
Style style = Style::kFill
 
BlendMode blend_mode = BlendMode::kSrcOver
 
bool invert_colors = false
 
std::optional< MaskBlurDescriptormask_blur_descriptor
 

Detailed Description

Definition at line 27 of file paint.h.

Member Typedef Documentation

◆ ColorSourceProc

using impeller::Paint::ColorSourceProc = std::function<std::shared_ptr<ColorSourceContents>()>

Definition at line 36 of file paint.h.

◆ ImageFilterProc

using impeller::Paint::ImageFilterProc = std::function<std::shared_ptr<FilterContents>( FilterInput::Ref, const Matrix& effect_transform, Entity::RenderingMode rendering_mode)>

Definition at line 28 of file paint.h.

◆ MaskFilterProc

using impeller::Paint::MaskFilterProc = std::function<std::shared_ptr<FilterContents>( FilterInput::Ref, bool is_solid_color, const Matrix& effect_transform)>

Definition at line 32 of file paint.h.

Member Enumeration Documentation

◆ Style

Enumerator
kFill 
kStroke 

Definition at line 47 of file paint.h.

47  {
48  kFill,
49  kStroke,
50  };

Member Function Documentation

◆ CanApplyOpacityPeephole()

static bool impeller::Paint::CanApplyOpacityPeephole ( const Paint paint)
inlinestatic

Whether or not a save layer with the provided paint can perform the opacity peephole optimization.

Definition at line 40 of file paint.h.

40  {
41  return paint.blend_mode == BlendMode::kSrcOver &&
42  paint.invert_colors == false &&
43  !paint.mask_blur_descriptor.has_value() &&
44  paint.image_filter == nullptr && paint.color_filter == nullptr;
45  }

References blend_mode, color_filter, image_filter, invert_colors, impeller::kSrcOver, and mask_blur_descriptor.

Referenced by impeller::Canvas::SaveLayer().

◆ ConvertStops()

void impeller::Paint::ConvertStops ( const flutter::DlGradientColorSourceBase *  gradient,
std::vector< Color > &  colors,
std::vector< float > &  stops 
)
static

Convert display list colors + stops into impeller colors and stops, taking care to ensure that the stops monotonically increase from 0.0 to 1.0.

The general process is:

  • Ensure that the first gradient stop value is 0.0. If not, insert a new stop with a value of 0.0 and use the first gradient color as this new stops color.
  • Ensure the last gradient stop value is 1.0. If not, insert a new stop with a value of 1.0 and use the last gradient color as this stops color.
  • Clamp all gradient values between the values of 0.0 and 1.0.
  • For all stop values, ensure that the values are monotonically increasing by clamping each value to a minimum of the previous stop value and itself. For example, with stop values of 0.0, 0.5, 0.4, 1.0, we would clamp such that the values were 0.0, 0.5, 0.5, 1.0.

Definition at line 37 of file paint.cc.

39  {
40  FML_DCHECK(gradient->stop_count() >= 2)
41  << "stop_count:" << gradient->stop_count();
42 
43  auto* dl_colors = gradient->colors();
44  auto* dl_stops = gradient->stops();
45  if (dl_stops[0] != 0.0) {
46  colors.emplace_back(skia_conversions::ToColor(dl_colors[0]));
47  stops.emplace_back(0);
48  }
49  for (auto i = 0; i < gradient->stop_count(); i++) {
50  colors.emplace_back(skia_conversions::ToColor(dl_colors[i]));
51  stops.emplace_back(std::clamp(dl_stops[i], 0.0f, 1.0f));
52  }
53  if (dl_stops[gradient->stop_count() - 1] != 1.0) {
54  colors.emplace_back(colors.back());
55  stops.emplace_back(1.0);
56  }
57  for (auto i = 1; i < gradient->stop_count(); i++) {
58  stops[i] = std::clamp(stops[i], stops[i - 1], stops[i]);
59  }
60 }
Color ToColor(const flutter::DlColor &color)

References impeller::skia_conversions::ToColor().

Referenced by CreateContents(), and impeller::testing::TEST().

◆ CreateContents()

std::shared_ptr< ColorSourceContents > impeller::Paint::CreateContents ( ) const

Definition at line 62 of file paint.cc.

62  {
63  if (color_source == nullptr) {
64  auto contents = std::make_shared<SolidColorContents>();
65  contents->SetColor(color);
66  return contents;
67  }
68 
69  switch (color_source->type()) {
70  case flutter::DlColorSourceType::kLinearGradient: {
71  const flutter::DlLinearGradientColorSource* linear =
72  color_source->asLinearGradient();
73  FML_DCHECK(linear);
74  auto start_point = linear->start_point();
75  auto end_point = linear->end_point();
76  std::vector<Color> colors;
77  std::vector<float> stops;
78  ConvertStops(linear, colors, stops);
79 
80  auto tile_mode = static_cast<Entity::TileMode>(linear->tile_mode());
81  auto effect_transform = linear->matrix();
82 
83  auto contents = std::make_shared<LinearGradientContents>();
84  contents->SetOpacityFactor(color.alpha);
85  contents->SetColors(std::move(colors));
86  contents->SetStops(std::move(stops));
87  contents->SetEndPoints(start_point, end_point);
88  contents->SetTileMode(tile_mode);
89  contents->SetEffectTransform(effect_transform);
90 
91  std::array<Point, 2> bounds{start_point, end_point};
92  auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
93  if (intrinsic_size.has_value()) {
94  contents->SetColorSourceSize(intrinsic_size->GetSize().Max({1, 1}));
95  }
96  return contents;
97  }
98  case flutter::DlColorSourceType::kRadialGradient: {
99  const flutter::DlRadialGradientColorSource* radialGradient =
100  color_source->asRadialGradient();
101  FML_DCHECK(radialGradient);
102  auto center = radialGradient->center();
103  auto radius = radialGradient->radius();
104  std::vector<Color> colors;
105  std::vector<float> stops;
106  ConvertStops(radialGradient, colors, stops);
107 
108  auto tile_mode =
109  static_cast<Entity::TileMode>(radialGradient->tile_mode());
110  auto effect_transform = radialGradient->matrix();
111 
112  auto contents = std::make_shared<RadialGradientContents>();
113  contents->SetOpacityFactor(color.alpha);
114  contents->SetColors(std::move(colors));
115  contents->SetStops(std::move(stops));
116  contents->SetCenterAndRadius(center, radius);
117  contents->SetTileMode(tile_mode);
118  contents->SetEffectTransform(effect_transform);
119 
120  auto radius_pt = Point(radius, radius);
121  std::array<Point, 2> bounds{center + radius_pt, center - radius_pt};
122  auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
123  if (intrinsic_size.has_value()) {
124  contents->SetColorSourceSize(intrinsic_size->GetSize().Max({1, 1}));
125  }
126  return contents;
127  }
128  case flutter::DlColorSourceType::kConicalGradient: {
129  const flutter::DlConicalGradientColorSource* conical_gradient =
130  color_source->asConicalGradient();
131  FML_DCHECK(conical_gradient);
132  Point center = conical_gradient->end_center();
133  DlScalar radius = conical_gradient->end_radius();
134  Point focus_center = conical_gradient->start_center();
135  DlScalar focus_radius = conical_gradient->start_radius();
136  std::vector<Color> colors;
137  std::vector<float> stops;
138  ConvertStops(conical_gradient, colors, stops);
139 
140  auto tile_mode =
141  static_cast<Entity::TileMode>(conical_gradient->tile_mode());
142  auto effect_transform = conical_gradient->matrix();
143 
144  std::shared_ptr<ConicalGradientContents> contents =
145  std::make_shared<ConicalGradientContents>();
146  contents->SetOpacityFactor(color.alpha);
147  contents->SetColors(std::move(colors));
148  contents->SetStops(std::move(stops));
149  contents->SetCenterAndRadius(center, radius);
150  contents->SetTileMode(tile_mode);
151  contents->SetEffectTransform(effect_transform);
152  contents->SetFocus(focus_center, focus_radius);
153 
154  auto radius_pt = Point(radius, radius);
155  std::array<Point, 2> bounds{center + radius_pt, center - radius_pt};
156  auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
157  if (intrinsic_size.has_value()) {
158  contents->SetColorSourceSize(intrinsic_size->GetSize().Max({1, 1}));
159  }
160  return contents;
161  }
162  case flutter::DlColorSourceType::kSweepGradient: {
163  const flutter::DlSweepGradientColorSource* sweepGradient =
164  color_source->asSweepGradient();
165  FML_DCHECK(sweepGradient);
166 
167  auto center = sweepGradient->center();
168  auto start_angle = Degrees(sweepGradient->start());
169  auto end_angle = Degrees(sweepGradient->end());
170  std::vector<Color> colors;
171  std::vector<float> stops;
172  ConvertStops(sweepGradient, colors, stops);
173 
174  auto tile_mode =
175  static_cast<Entity::TileMode>(sweepGradient->tile_mode());
176  auto effect_transform = sweepGradient->matrix();
177 
178  auto contents = std::make_shared<SweepGradientContents>();
179  contents->SetOpacityFactor(color.alpha);
180  contents->SetCenterAndAngles(center, start_angle, end_angle);
181  contents->SetColors(std::move(colors));
182  contents->SetStops(std::move(stops));
183  contents->SetTileMode(tile_mode);
184  contents->SetEffectTransform(effect_transform);
185 
186  return contents;
187  }
188  case flutter::DlColorSourceType::kImage: {
189  const flutter::DlImageColorSource* image_color_source =
190  color_source->asImage();
191  FML_DCHECK(image_color_source &&
192  image_color_source->image()->impeller_texture());
193  auto texture = image_color_source->image()->impeller_texture();
194  auto x_tile_mode = static_cast<Entity::TileMode>(
195  image_color_source->horizontal_tile_mode());
196  auto y_tile_mode = static_cast<Entity::TileMode>(
197  image_color_source->vertical_tile_mode());
198  auto sampler_descriptor =
199  skia_conversions::ToSamplerDescriptor(image_color_source->sampling());
200  // See https://github.com/flutter/flutter/issues/165205
201  flutter::DlMatrix effect_transform = image_color_source->matrix().To3x3();
202 
203  auto contents = std::make_shared<TiledTextureContents>();
204  contents->SetOpacityFactor(color.alpha);
205  contents->SetTexture(texture);
206  contents->SetTileModes(x_tile_mode, y_tile_mode);
207  contents->SetSamplerDescriptor(sampler_descriptor);
208  contents->SetEffectTransform(effect_transform);
209  if (color_filter || invert_colors) {
212  invert_colors = invert_colors](const FilterInput::Ref& input) {
213  if (invert_colors && color_filter) {
214  std::shared_ptr<FilterContents> color_filter_output =
216  color_filter, input,
218  return WrapWithInvertColors(
219  FilterInput::Make(color_filter_output),
221  }
222  if (color_filter) {
223  return WrapWithGPUColorFilter(
224  color_filter, input,
226  }
227  return WrapWithInvertColors(
229  };
230  contents->SetColorFilter(filter_proc);
231  }
232  contents->SetColorSourceSize(Size::Ceil(texture->GetSize()));
233  return contents;
234  }
235  case flutter::DlColorSourceType::kRuntimeEffect: {
236  const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
237  color_source->asRuntimeEffect();
238  auto runtime_stage =
239  runtime_effect_color_source->runtime_effect()->runtime_stage();
240  auto uniform_data = runtime_effect_color_source->uniform_data();
241  auto samplers = runtime_effect_color_source->samplers();
242 
243  std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
244 
245  for (auto& sampler : samplers) {
246  if (sampler == nullptr) {
247  VALIDATION_LOG << "Runtime effect sampler is null";
248  auto contents = std::make_shared<SolidColorContents>();
249  contents->SetColor(Color::BlackTransparent());
250  return contents;
251  }
252  auto* image = sampler->asImage();
253  if (!sampler->asImage()) {
254  VALIDATION_LOG << "Runtime effect sampler is not an image";
255  auto contents = std::make_shared<SolidColorContents>();
256  contents->SetColor(Color::BlackTransparent());
257  return contents;
258  }
259  FML_DCHECK(image->image()->impeller_texture());
260  texture_inputs.push_back({
261  .sampler_descriptor =
262  skia_conversions::ToSamplerDescriptor(image->sampling()),
263  .texture = image->image()->impeller_texture(),
264  });
265  }
266 
267  auto contents = std::make_shared<RuntimeEffectContents>();
268  contents->SetOpacityFactor(color.alpha);
269  contents->SetRuntimeStage(std::move(runtime_stage));
270  contents->SetUniformData(std::move(uniform_data));
271  contents->SetTextureInputs(std::move(texture_inputs));
272  return contents;
273  }
274  }
275  FML_UNREACHABLE();
276 }
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
std::function< std::shared_ptr< ColorFilterContents >(FilterInput::Ref)> ColorFilterProc
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
std::shared_ptr< ColorFilterContents > WrapWithGPUColorFilter(const flutter::DlColorFilter *filter, const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
Definition: color_filter.cc:24
std::shared_ptr< ColorFilterContents > WrapWithInvertColors(const std::shared_ptr< FilterInput > &input, ColorFilterContents::AbsorbOpacity absorb_opacity)
Definition: color_filter.cc:16
TPoint< Scalar > Point
Definition: point.h:327
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23
static constexpr Color BlackTransparent()
Definition: color.h:270
Scalar alpha
Definition: color.h:143
const flutter::DlColorFilter * color_filter
Definition: paint.h:77
const flutter::DlColorSource * color_source
Definition: paint.h:76
static 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: paint.cc:37
bool invert_colors
Definition: paint.h:83
Color color
Definition: paint.h:75
constexpr static std::optional< TRect > MakePointBounds(const U &value)
Definition: rect.h:165
constexpr TSize Ceil() const
Definition: size.h:114
#define VALIDATION_LOG
Definition: validation.h:91

References impeller::Color::alpha, impeller::Color::BlackTransparent(), impeller::TSize< Scalar >::Ceil(), color, color_filter, color_source, ConvertStops(), invert_colors, impeller::ColorFilterContents::kNo, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::skia_conversions::ToSamplerDescriptor(), VALIDATION_LOG, impeller::WrapWithGPUColorFilter(), and impeller::WrapWithInvertColors().

◆ HasColorFilter()

bool impeller::Paint::HasColorFilter ( ) const

Whether this paint has a color filter that can apply opacity.

Definition at line 469 of file paint.cc.

469  {
470  return color_filter || invert_colors;
471 }

Referenced by impeller::Canvas::DrawImageRect().

◆ WithFilters()

std::shared_ptr< Contents > impeller::Paint::WithFilters ( std::shared_ptr< Contents input) const

Wrap this paint's configured filters to the given contents.

Parameters
[in]inputThe contents to wrap with paint's filters.
Returns
The filter-wrapped contents. If there are no filters that need to be wrapped for the current paint configuration, the original contents is returned.

Definition at line 278 of file paint.cc.

279  {
280  input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
281  auto image_filter =
283  if (image_filter) {
284  input = image_filter;
285  }
286  return input;
287 }
const flutter::DlImageFilter * image_filter
Definition: paint.h:78
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
Definition: paint.cc:312

References image_filter, impeller::Entity::kDirect, impeller::ColorFilterContents::kYes, and WithImageFilter().

Referenced by impeller::Canvas::DrawAtlas(), impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawTextFrame(), and impeller::Canvas::DrawVertices().

◆ WithFiltersForSubpassTarget()

std::shared_ptr< Contents > impeller::Paint::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.

Parameters
[in]inputThe contents of subpass target to wrap with paint's filters.
Returns
The filter-wrapped contents. If there are no filters that need to be wrapped for the current paint configuration, the original contents is returned.

Definition at line 289 of file paint.cc.

291  {
292  auto image_filter =
293  WithImageFilter(input, effect_transform,
295  if (image_filter) {
296  input = image_filter;
297  }
298  input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
299  return input;
300 }

References image_filter, impeller::Entity::kSubpassPrependSnapshotTransform, impeller::ColorFilterContents::kYes, and WithImageFilter().

◆ WithImageFilter()

std::shared_ptr< FilterContents > impeller::Paint::WithImageFilter ( const FilterInput::Variant input,
const Matrix effect_transform,
Entity::RenderingMode  rendering_mode 
) const

Definition at line 312 of file paint.cc.

315  {
316  if (!image_filter) {
317  return nullptr;
318  }
319  auto filter = WrapInput(image_filter, FilterInput::Make(input));
320  filter->SetRenderingMode(rendering_mode);
321  filter->SetEffectTransform(effect_transform);
322  return filter;
323 }
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:18

References image_filter, impeller::FilterInput::Make(), and impeller::WrapInput().

Referenced by impeller::Canvas::SaveLayer(), WithFilters(), and WithFiltersForSubpassTarget().

◆ WithMaskBlur()

std::shared_ptr< Contents > impeller::Paint::WithMaskBlur ( std::shared_ptr< Contents input,
bool  is_solid_color,
const Matrix ctm 
) const

Definition at line 302 of file paint.cc.

304  {
305  if (mask_blur_descriptor.has_value()) {
306  input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input),
307  is_solid_color, ctm);
308  }
309  return input;
310 }
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:85

References impeller::FilterInput::Make(), and mask_blur_descriptor.

Member Data Documentation

◆ blend_mode

◆ color

◆ color_filter

const flutter::DlColorFilter* impeller::Paint::color_filter = nullptr

◆ color_source

const flutter::DlColorSource* impeller::Paint::color_source = nullptr

◆ image_filter

const flutter::DlImageFilter* impeller::Paint::image_filter = nullptr

◆ invert_colors

bool impeller::Paint::invert_colors = false

◆ mask_blur_descriptor

◆ stroke

◆ style


The documentation for this struct was generated from the following files: