Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 5fc83bc

Browse files
[Impeller] make color source a variant instead of a closure. (#51853)
This would also me to create a type safe visitor to pull out the data required for #51778
1 parent 0da1b2e commit 5fc83bc

File tree

2 files changed

+220
-122
lines changed

2 files changed

+220
-122
lines changed

impeller/aiks/color_source.cc

Lines changed: 147 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "impeller/aiks/color_source.h"
66

77
#include <memory>
8+
#include <variant>
89
#include <vector>
910

1011
#include "impeller/aiks/paint.h"
@@ -29,12 +30,132 @@
2930

3031
namespace impeller {
3132

32-
ColorSource::ColorSource() noexcept
33-
: proc_([](const Paint& paint) -> std::shared_ptr<ColorSourceContents> {
34-
auto contents = std::make_shared<SolidColorContents>();
35-
contents->SetColor(paint.color);
36-
return contents;
37-
}){};
33+
namespace {
34+
35+
struct CreateContentsVisitor {
36+
explicit CreateContentsVisitor(const Paint& p_paint) : paint(p_paint) {}
37+
38+
const Paint& paint;
39+
40+
std::shared_ptr<ColorSourceContents> operator()(
41+
const LinearGradientData& data) {
42+
auto contents = std::make_shared<LinearGradientContents>();
43+
contents->SetOpacityFactor(paint.color.alpha);
44+
contents->SetColors(data.colors);
45+
contents->SetStops(data.stops);
46+
contents->SetEndPoints(data.start_point, data.end_point);
47+
contents->SetTileMode(data.tile_mode);
48+
contents->SetEffectTransform(data.effect_transform);
49+
50+
std::vector<Point> bounds{data.start_point, data.end_point};
51+
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
52+
if (intrinsic_size.has_value()) {
53+
contents->SetColorSourceSize(intrinsic_size->GetSize());
54+
}
55+
return contents;
56+
}
57+
58+
std::shared_ptr<ColorSourceContents> operator()(
59+
const RadialGradientData& data) {
60+
auto contents = std::make_shared<RadialGradientContents>();
61+
contents->SetOpacityFactor(paint.color.alpha);
62+
contents->SetColors(data.colors);
63+
contents->SetStops(data.stops);
64+
contents->SetCenterAndRadius(data.center, data.radius);
65+
contents->SetTileMode(data.tile_mode);
66+
contents->SetEffectTransform(data.effect_transform);
67+
68+
auto radius_pt = Point(data.radius, data.radius);
69+
std::vector<Point> bounds{data.center + radius_pt, data.center - radius_pt};
70+
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
71+
if (intrinsic_size.has_value()) {
72+
contents->SetColorSourceSize(intrinsic_size->GetSize());
73+
}
74+
return contents;
75+
}
76+
77+
std::shared_ptr<ColorSourceContents> operator()(
78+
const ConicalGradientData& data) {
79+
std::shared_ptr<ConicalGradientContents> contents =
80+
std::make_shared<ConicalGradientContents>();
81+
contents->SetOpacityFactor(paint.color.alpha);
82+
contents->SetColors(data.colors);
83+
contents->SetStops(data.stops);
84+
contents->SetCenterAndRadius(data.center, data.radius);
85+
contents->SetTileMode(data.tile_mode);
86+
contents->SetEffectTransform(data.effect_transform);
87+
contents->SetFocus(data.focus_center, data.focus_radius);
88+
89+
auto radius_pt = Point(data.radius, data.radius);
90+
std::vector<Point> bounds{data.center + radius_pt, data.center - radius_pt};
91+
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
92+
if (intrinsic_size.has_value()) {
93+
contents->SetColorSourceSize(intrinsic_size->GetSize());
94+
}
95+
return contents;
96+
}
97+
98+
std::shared_ptr<ColorSourceContents> operator()(
99+
const SweepGradientData& data) {
100+
auto contents = std::make_shared<SweepGradientContents>();
101+
contents->SetOpacityFactor(paint.color.alpha);
102+
contents->SetCenterAndAngles(data.center, data.start_angle, data.end_angle);
103+
contents->SetColors(data.colors);
104+
contents->SetStops(data.stops);
105+
contents->SetTileMode(data.tile_mode);
106+
contents->SetEffectTransform(data.effect_transform);
107+
108+
return contents;
109+
}
110+
111+
std::shared_ptr<ColorSourceContents> operator()(const ImageData& data) {
112+
auto contents = std::make_shared<TiledTextureContents>();
113+
contents->SetOpacityFactor(paint.color.alpha);
114+
contents->SetTexture(data.texture);
115+
contents->SetTileModes(data.x_tile_mode, data.y_tile_mode);
116+
contents->SetSamplerDescriptor(data.sampler_descriptor);
117+
contents->SetEffectTransform(data.effect_transform);
118+
if (paint.color_filter) {
119+
TiledTextureContents::ColorFilterProc filter_proc =
120+
[color_filter = paint.color_filter](FilterInput::Ref input) {
121+
return color_filter->WrapWithGPUColorFilter(
122+
std::move(input), ColorFilterContents::AbsorbOpacity::kNo);
123+
};
124+
contents->SetColorFilter(filter_proc);
125+
}
126+
contents->SetColorSourceSize(Size::Ceil(data.texture->GetSize()));
127+
return contents;
128+
}
129+
130+
std::shared_ptr<ColorSourceContents> operator()(
131+
const RuntimeEffectData& data) {
132+
auto contents = std::make_shared<RuntimeEffectContents>();
133+
contents->SetOpacityFactor(paint.color.alpha);
134+
contents->SetRuntimeStage(data.runtime_stage);
135+
contents->SetUniformData(data.uniform_data);
136+
contents->SetTextureInputs(data.texture_inputs);
137+
return contents;
138+
}
139+
140+
std::shared_ptr<ColorSourceContents> operator()(const std::monostate& data) {
141+
auto contents = std::make_shared<SolidColorContents>();
142+
contents->SetColor(paint.color);
143+
return contents;
144+
}
145+
146+
#if IMPELLER_ENABLE_3D
147+
std::shared_ptr<ColorSourceContents> operator()(const SceneData& data) {
148+
auto contents = std::make_shared<SceneContents>();
149+
contents->SetOpacityFactor(paint.color.alpha);
150+
contents->SetNode(data.scene_node);
151+
contents->SetCameraTransform(data.camera_transform);
152+
return contents;
153+
}
154+
#endif // IMPELLER_ENABLE_3D
155+
};
156+
} // namespace
157+
158+
ColorSource::ColorSource() noexcept : color_source_data_(std::monostate()) {}
38159

39160
ColorSource::~ColorSource() = default;
40161

@@ -50,24 +171,9 @@ ColorSource ColorSource::MakeLinearGradient(Point start_point,
50171
Matrix effect_transform) {
51172
ColorSource result;
52173
result.type_ = Type::kLinearGradient;
53-
result.proc_ = [start_point, end_point, colors = std::move(colors),
54-
stops = std::move(stops), tile_mode,
55-
effect_transform](const Paint& paint) {
56-
auto contents = std::make_shared<LinearGradientContents>();
57-
contents->SetOpacityFactor(paint.color.alpha);
58-
contents->SetColors(colors);
59-
contents->SetStops(stops);
60-
contents->SetEndPoints(start_point, end_point);
61-
contents->SetTileMode(tile_mode);
62-
contents->SetEffectTransform(effect_transform);
63-
64-
std::vector<Point> bounds{start_point, end_point};
65-
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
66-
if (intrinsic_size.has_value()) {
67-
contents->SetColorSourceSize(intrinsic_size->GetSize());
68-
}
69-
return contents;
70-
};
174+
result.color_source_data_ =
175+
LinearGradientData{start_point, end_point, std::move(colors),
176+
std::move(stops), tile_mode, effect_transform};
71177
return result;
72178
}
73179

@@ -81,27 +187,9 @@ ColorSource ColorSource::MakeConicalGradient(Point center,
81187
Matrix effect_transform) {
82188
ColorSource result;
83189
result.type_ = Type::kConicalGradient;
84-
result.proc_ = [center, radius, colors = std::move(colors),
85-
stops = std::move(stops), focus_center, focus_radius,
86-
tile_mode, effect_transform](const Paint& paint) {
87-
std::shared_ptr<ConicalGradientContents> contents =
88-
std::make_shared<ConicalGradientContents>();
89-
contents->SetOpacityFactor(paint.color.alpha);
90-
contents->SetColors(colors);
91-
contents->SetStops(stops);
92-
contents->SetCenterAndRadius(center, radius);
93-
contents->SetTileMode(tile_mode);
94-
contents->SetEffectTransform(effect_transform);
95-
contents->SetFocus(focus_center, focus_radius);
96-
97-
auto radius_pt = Point(radius, radius);
98-
std::vector<Point> bounds{center + radius_pt, center - radius_pt};
99-
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
100-
if (intrinsic_size.has_value()) {
101-
contents->SetColorSourceSize(intrinsic_size->GetSize());
102-
}
103-
return contents;
104-
};
190+
result.color_source_data_ = ConicalGradientData{
191+
center, radius, std::move(colors), std::move(stops),
192+
focus_center, focus_radius, tile_mode, effect_transform};
105193
return result;
106194
}
107195

@@ -113,25 +201,9 @@ ColorSource ColorSource::MakeRadialGradient(Point center,
113201
Matrix effect_transform) {
114202
ColorSource result;
115203
result.type_ = Type::kRadialGradient;
116-
result.proc_ = [center, radius, colors = std::move(colors),
117-
stops = std::move(stops), tile_mode,
118-
effect_transform](const Paint& paint) {
119-
auto contents = std::make_shared<RadialGradientContents>();
120-
contents->SetOpacityFactor(paint.color.alpha);
121-
contents->SetColors(colors);
122-
contents->SetStops(stops);
123-
contents->SetCenterAndRadius(center, radius);
124-
contents->SetTileMode(tile_mode);
125-
contents->SetEffectTransform(effect_transform);
126-
127-
auto radius_pt = Point(radius, radius);
128-
std::vector<Point> bounds{center + radius_pt, center - radius_pt};
129-
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
130-
if (intrinsic_size.has_value()) {
131-
contents->SetColorSourceSize(intrinsic_size->GetSize());
132-
}
133-
return contents;
134-
};
204+
result.color_source_data_ =
205+
RadialGradientData{center, radius, std::move(colors),
206+
std::move(stops), tile_mode, effect_transform};
135207
return result;
136208
}
137209

@@ -144,19 +216,9 @@ ColorSource ColorSource::MakeSweepGradient(Point center,
144216
Matrix effect_transform) {
145217
ColorSource result;
146218
result.type_ = Type::kSweepGradient;
147-
result.proc_ = [center, start_angle, end_angle, colors = std::move(colors),
148-
stops = std::move(stops), tile_mode,
149-
effect_transform](const Paint& paint) {
150-
auto contents = std::make_shared<SweepGradientContents>();
151-
contents->SetOpacityFactor(paint.color.alpha);
152-
contents->SetCenterAndAngles(center, start_angle, end_angle);
153-
contents->SetColors(colors);
154-
contents->SetStops(stops);
155-
contents->SetTileMode(tile_mode);
156-
contents->SetEffectTransform(effect_transform);
157-
158-
return contents;
159-
};
219+
result.color_source_data_ = SweepGradientData{
220+
center, start_angle, end_angle, std::move(colors),
221+
std::move(stops), tile_mode, effect_transform};
160222
return result;
161223
}
162224

@@ -167,26 +229,9 @@ ColorSource ColorSource::MakeImage(std::shared_ptr<Texture> texture,
167229
Matrix effect_transform) {
168230
ColorSource result;
169231
result.type_ = Type::kImage;
170-
result.proc_ = [texture = std::move(texture), x_tile_mode, y_tile_mode,
171-
sampler_descriptor = std::move(sampler_descriptor),
172-
effect_transform](const Paint& paint) {
173-
auto contents = std::make_shared<TiledTextureContents>();
174-
contents->SetOpacityFactor(paint.color.alpha);
175-
contents->SetTexture(texture);
176-
contents->SetTileModes(x_tile_mode, y_tile_mode);
177-
contents->SetSamplerDescriptor(sampler_descriptor);
178-
contents->SetEffectTransform(effect_transform);
179-
if (paint.color_filter) {
180-
TiledTextureContents::ColorFilterProc filter_proc =
181-
[color_filter = paint.color_filter](FilterInput::Ref input) {
182-
return color_filter->WrapWithGPUColorFilter(
183-
std::move(input), ColorFilterContents::AbsorbOpacity::kNo);
184-
};
185-
contents->SetColorFilter(filter_proc);
186-
}
187-
contents->SetColorSourceSize(Size::Ceil(texture->GetSize()));
188-
return contents;
189-
};
232+
result.color_source_data_ =
233+
ImageData{std::move(texture), x_tile_mode, y_tile_mode,
234+
std::move(sampler_descriptor), effect_transform};
190235
return result;
191236
}
192237

@@ -196,17 +241,9 @@ ColorSource ColorSource::MakeRuntimeEffect(
196241
std::vector<RuntimeEffectContents::TextureInput> texture_inputs) {
197242
ColorSource result;
198243
result.type_ = Type::kRuntimeEffect;
199-
result.proc_ = [runtime_stage = std::move(runtime_stage),
200-
uniform_data = std::move(uniform_data),
201-
texture_inputs =
202-
std::move(texture_inputs)](const Paint& paint) {
203-
auto contents = std::make_shared<RuntimeEffectContents>();
204-
contents->SetOpacityFactor(paint.color.alpha);
205-
contents->SetRuntimeStage(runtime_stage);
206-
contents->SetUniformData(uniform_data);
207-
contents->SetTextureInputs(texture_inputs);
208-
return contents;
209-
};
244+
result.color_source_data_ =
245+
RuntimeEffectData{std::move(runtime_stage), std::move(uniform_data),
246+
std::move(texture_inputs)};
210247
return result;
211248
}
212249

@@ -215,14 +252,7 @@ ColorSource ColorSource::MakeScene(std::shared_ptr<scene::Node> scene_node,
215252
Matrix camera_transform) {
216253
ColorSource result;
217254
result.type_ = Type::kScene;
218-
result.proc_ = [scene_node = std::move(scene_node),
219-
camera_transform](const Paint& paint) {
220-
auto contents = std::make_shared<SceneContents>();
221-
contents->SetOpacityFactor(paint.color.alpha);
222-
contents->SetNode(scene_node);
223-
contents->SetCameraTransform(camera_transform);
224-
return contents;
225-
};
255+
result.color_source_data_ = SceneData{scene_node, camera_transform};
226256
return result;
227257
}
228258
#endif // IMPELLER_ENABLE_3D
@@ -233,7 +263,7 @@ ColorSource::Type ColorSource::GetType() const {
233263

234264
std::shared_ptr<ColorSourceContents> ColorSource::GetContents(
235265
const Paint& paint) const {
236-
return proc_(paint);
266+
return std::visit(CreateContentsVisitor{paint}, color_source_data_);
237267
}
238268

239269
} // namespace impeller

0 commit comments

Comments
 (0)