mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] make color source a variant instead of a closure. (flutter/engine#51853)
This would also me to create a type safe visitor to pull out the data required for https://github.com/flutter/engine/pull/51778
This commit is contained in:
parent
9404f5112e
commit
aa63d0d282
@ -5,6 +5,7 @@
|
||||
#include "impeller/aiks/color_source.h"
|
||||
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "impeller/aiks/paint.h"
|
||||
@ -29,12 +30,132 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
ColorSource::ColorSource() noexcept
|
||||
: proc_([](const Paint& paint) -> std::shared_ptr<ColorSourceContents> {
|
||||
auto contents = std::make_shared<SolidColorContents>();
|
||||
contents->SetColor(paint.color);
|
||||
return contents;
|
||||
}){};
|
||||
namespace {
|
||||
|
||||
struct CreateContentsVisitor {
|
||||
explicit CreateContentsVisitor(const Paint& p_paint) : paint(p_paint) {}
|
||||
|
||||
const Paint& paint;
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(
|
||||
const LinearGradientData& data) {
|
||||
auto contents = std::make_shared<LinearGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetColors(data.colors);
|
||||
contents->SetStops(data.stops);
|
||||
contents->SetEndPoints(data.start_point, data.end_point);
|
||||
contents->SetTileMode(data.tile_mode);
|
||||
contents->SetEffectTransform(data.effect_transform);
|
||||
|
||||
std::vector<Point> bounds{data.start_point, data.end_point};
|
||||
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
|
||||
if (intrinsic_size.has_value()) {
|
||||
contents->SetColorSourceSize(intrinsic_size->GetSize());
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(
|
||||
const RadialGradientData& data) {
|
||||
auto contents = std::make_shared<RadialGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetColors(data.colors);
|
||||
contents->SetStops(data.stops);
|
||||
contents->SetCenterAndRadius(data.center, data.radius);
|
||||
contents->SetTileMode(data.tile_mode);
|
||||
contents->SetEffectTransform(data.effect_transform);
|
||||
|
||||
auto radius_pt = Point(data.radius, data.radius);
|
||||
std::vector<Point> bounds{data.center + radius_pt, data.center - radius_pt};
|
||||
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
|
||||
if (intrinsic_size.has_value()) {
|
||||
contents->SetColorSourceSize(intrinsic_size->GetSize());
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(
|
||||
const ConicalGradientData& data) {
|
||||
std::shared_ptr<ConicalGradientContents> contents =
|
||||
std::make_shared<ConicalGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetColors(data.colors);
|
||||
contents->SetStops(data.stops);
|
||||
contents->SetCenterAndRadius(data.center, data.radius);
|
||||
contents->SetTileMode(data.tile_mode);
|
||||
contents->SetEffectTransform(data.effect_transform);
|
||||
contents->SetFocus(data.focus_center, data.focus_radius);
|
||||
|
||||
auto radius_pt = Point(data.radius, data.radius);
|
||||
std::vector<Point> bounds{data.center + radius_pt, data.center - radius_pt};
|
||||
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
|
||||
if (intrinsic_size.has_value()) {
|
||||
contents->SetColorSourceSize(intrinsic_size->GetSize());
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(
|
||||
const SweepGradientData& data) {
|
||||
auto contents = std::make_shared<SweepGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetCenterAndAngles(data.center, data.start_angle, data.end_angle);
|
||||
contents->SetColors(data.colors);
|
||||
contents->SetStops(data.stops);
|
||||
contents->SetTileMode(data.tile_mode);
|
||||
contents->SetEffectTransform(data.effect_transform);
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(const ImageData& data) {
|
||||
auto contents = std::make_shared<TiledTextureContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetTexture(data.texture);
|
||||
contents->SetTileModes(data.x_tile_mode, data.y_tile_mode);
|
||||
contents->SetSamplerDescriptor(data.sampler_descriptor);
|
||||
contents->SetEffectTransform(data.effect_transform);
|
||||
if (paint.color_filter) {
|
||||
TiledTextureContents::ColorFilterProc filter_proc =
|
||||
[color_filter = paint.color_filter](FilterInput::Ref input) {
|
||||
return color_filter->WrapWithGPUColorFilter(
|
||||
std::move(input), ColorFilterContents::AbsorbOpacity::kNo);
|
||||
};
|
||||
contents->SetColorFilter(filter_proc);
|
||||
}
|
||||
contents->SetColorSourceSize(Size::Ceil(data.texture->GetSize()));
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(
|
||||
const RuntimeEffectData& data) {
|
||||
auto contents = std::make_shared<RuntimeEffectContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetRuntimeStage(data.runtime_stage);
|
||||
contents->SetUniformData(data.uniform_data);
|
||||
contents->SetTextureInputs(data.texture_inputs);
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> operator()(const std::monostate& data) {
|
||||
auto contents = std::make_shared<SolidColorContents>();
|
||||
contents->SetColor(paint.color);
|
||||
return contents;
|
||||
}
|
||||
|
||||
#if IMPELLER_ENABLE_3D
|
||||
std::shared_ptr<ColorSourceContents> operator()(const SceneData& data) {
|
||||
auto contents = std::make_shared<SceneContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetNode(data.scene_node);
|
||||
contents->SetCameraTransform(data.camera_transform);
|
||||
return contents;
|
||||
}
|
||||
#endif // IMPELLER_ENABLE_3D
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ColorSource::ColorSource() noexcept : color_source_data_(std::monostate()) {}
|
||||
|
||||
ColorSource::~ColorSource() = default;
|
||||
|
||||
@ -50,24 +171,9 @@ ColorSource ColorSource::MakeLinearGradient(Point start_point,
|
||||
Matrix effect_transform) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kLinearGradient;
|
||||
result.proc_ = [start_point, end_point, colors = std::move(colors),
|
||||
stops = std::move(stops), tile_mode,
|
||||
effect_transform](const Paint& paint) {
|
||||
auto contents = std::make_shared<LinearGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetColors(colors);
|
||||
contents->SetStops(stops);
|
||||
contents->SetEndPoints(start_point, end_point);
|
||||
contents->SetTileMode(tile_mode);
|
||||
contents->SetEffectTransform(effect_transform);
|
||||
|
||||
std::vector<Point> bounds{start_point, end_point};
|
||||
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
|
||||
if (intrinsic_size.has_value()) {
|
||||
contents->SetColorSourceSize(intrinsic_size->GetSize());
|
||||
}
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ =
|
||||
LinearGradientData{start_point, end_point, std::move(colors),
|
||||
std::move(stops), tile_mode, effect_transform};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -81,27 +187,9 @@ ColorSource ColorSource::MakeConicalGradient(Point center,
|
||||
Matrix effect_transform) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kConicalGradient;
|
||||
result.proc_ = [center, radius, colors = std::move(colors),
|
||||
stops = std::move(stops), focus_center, focus_radius,
|
||||
tile_mode, effect_transform](const Paint& paint) {
|
||||
std::shared_ptr<ConicalGradientContents> contents =
|
||||
std::make_shared<ConicalGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetColors(colors);
|
||||
contents->SetStops(stops);
|
||||
contents->SetCenterAndRadius(center, radius);
|
||||
contents->SetTileMode(tile_mode);
|
||||
contents->SetEffectTransform(effect_transform);
|
||||
contents->SetFocus(focus_center, focus_radius);
|
||||
|
||||
auto radius_pt = Point(radius, radius);
|
||||
std::vector<Point> bounds{center + radius_pt, center - radius_pt};
|
||||
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
|
||||
if (intrinsic_size.has_value()) {
|
||||
contents->SetColorSourceSize(intrinsic_size->GetSize());
|
||||
}
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ = ConicalGradientData{
|
||||
center, radius, std::move(colors), std::move(stops),
|
||||
focus_center, focus_radius, tile_mode, effect_transform};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -113,25 +201,9 @@ ColorSource ColorSource::MakeRadialGradient(Point center,
|
||||
Matrix effect_transform) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kRadialGradient;
|
||||
result.proc_ = [center, radius, colors = std::move(colors),
|
||||
stops = std::move(stops), tile_mode,
|
||||
effect_transform](const Paint& paint) {
|
||||
auto contents = std::make_shared<RadialGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetColors(colors);
|
||||
contents->SetStops(stops);
|
||||
contents->SetCenterAndRadius(center, radius);
|
||||
contents->SetTileMode(tile_mode);
|
||||
contents->SetEffectTransform(effect_transform);
|
||||
|
||||
auto radius_pt = Point(radius, radius);
|
||||
std::vector<Point> bounds{center + radius_pt, center - radius_pt};
|
||||
auto intrinsic_size = Rect::MakePointBounds(bounds.begin(), bounds.end());
|
||||
if (intrinsic_size.has_value()) {
|
||||
contents->SetColorSourceSize(intrinsic_size->GetSize());
|
||||
}
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ =
|
||||
RadialGradientData{center, radius, std::move(colors),
|
||||
std::move(stops), tile_mode, effect_transform};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -144,19 +216,9 @@ ColorSource ColorSource::MakeSweepGradient(Point center,
|
||||
Matrix effect_transform) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kSweepGradient;
|
||||
result.proc_ = [center, start_angle, end_angle, colors = std::move(colors),
|
||||
stops = std::move(stops), tile_mode,
|
||||
effect_transform](const Paint& paint) {
|
||||
auto contents = std::make_shared<SweepGradientContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetCenterAndAngles(center, start_angle, end_angle);
|
||||
contents->SetColors(colors);
|
||||
contents->SetStops(stops);
|
||||
contents->SetTileMode(tile_mode);
|
||||
contents->SetEffectTransform(effect_transform);
|
||||
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ = SweepGradientData{
|
||||
center, start_angle, end_angle, std::move(colors),
|
||||
std::move(stops), tile_mode, effect_transform};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -167,26 +229,9 @@ ColorSource ColorSource::MakeImage(std::shared_ptr<Texture> texture,
|
||||
Matrix effect_transform) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kImage;
|
||||
result.proc_ = [texture = std::move(texture), x_tile_mode, y_tile_mode,
|
||||
sampler_descriptor = std::move(sampler_descriptor),
|
||||
effect_transform](const Paint& paint) {
|
||||
auto contents = std::make_shared<TiledTextureContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetTexture(texture);
|
||||
contents->SetTileModes(x_tile_mode, y_tile_mode);
|
||||
contents->SetSamplerDescriptor(sampler_descriptor);
|
||||
contents->SetEffectTransform(effect_transform);
|
||||
if (paint.color_filter) {
|
||||
TiledTextureContents::ColorFilterProc filter_proc =
|
||||
[color_filter = paint.color_filter](FilterInput::Ref input) {
|
||||
return color_filter->WrapWithGPUColorFilter(
|
||||
std::move(input), ColorFilterContents::AbsorbOpacity::kNo);
|
||||
};
|
||||
contents->SetColorFilter(filter_proc);
|
||||
}
|
||||
contents->SetColorSourceSize(Size::Ceil(texture->GetSize()));
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ =
|
||||
ImageData{std::move(texture), x_tile_mode, y_tile_mode,
|
||||
std::move(sampler_descriptor), effect_transform};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -196,17 +241,9 @@ ColorSource ColorSource::MakeRuntimeEffect(
|
||||
std::vector<RuntimeEffectContents::TextureInput> texture_inputs) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kRuntimeEffect;
|
||||
result.proc_ = [runtime_stage = std::move(runtime_stage),
|
||||
uniform_data = std::move(uniform_data),
|
||||
texture_inputs =
|
||||
std::move(texture_inputs)](const Paint& paint) {
|
||||
auto contents = std::make_shared<RuntimeEffectContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetRuntimeStage(runtime_stage);
|
||||
contents->SetUniformData(uniform_data);
|
||||
contents->SetTextureInputs(texture_inputs);
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ =
|
||||
RuntimeEffectData{std::move(runtime_stage), std::move(uniform_data),
|
||||
std::move(texture_inputs)};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -215,14 +252,7 @@ ColorSource ColorSource::MakeScene(std::shared_ptr<scene::Node> scene_node,
|
||||
Matrix camera_transform) {
|
||||
ColorSource result;
|
||||
result.type_ = Type::kScene;
|
||||
result.proc_ = [scene_node = std::move(scene_node),
|
||||
camera_transform](const Paint& paint) {
|
||||
auto contents = std::make_shared<SceneContents>();
|
||||
contents->SetOpacityFactor(paint.color.alpha);
|
||||
contents->SetNode(scene_node);
|
||||
contents->SetCameraTransform(camera_transform);
|
||||
return contents;
|
||||
};
|
||||
result.color_source_data_ = SceneData{scene_node, camera_transform};
|
||||
return result;
|
||||
}
|
||||
#endif // IMPELLER_ENABLE_3D
|
||||
@ -233,7 +263,7 @@ ColorSource::Type ColorSource::GetType() const {
|
||||
|
||||
std::shared_ptr<ColorSourceContents> ColorSource::GetContents(
|
||||
const Paint& paint) const {
|
||||
return proc_(paint);
|
||||
return std::visit(CreateContentsVisitor{paint}, color_source_data_);
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -7,9 +7,9 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/entity/contents/runtime_effect_contents.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
@ -25,6 +25,77 @@ namespace impeller {
|
||||
|
||||
struct Paint;
|
||||
|
||||
struct LinearGradientData {
|
||||
Point start_point;
|
||||
Point end_point;
|
||||
std::vector<Color> colors;
|
||||
std::vector<Scalar> stops;
|
||||
Entity::TileMode tile_mode;
|
||||
Matrix effect_transform;
|
||||
};
|
||||
|
||||
struct RadialGradientData {
|
||||
Point center;
|
||||
Scalar radius;
|
||||
std::vector<Color> colors;
|
||||
std::vector<Scalar> stops;
|
||||
Entity::TileMode tile_mode;
|
||||
Matrix effect_transform;
|
||||
};
|
||||
|
||||
struct ConicalGradientData {
|
||||
Point center;
|
||||
Scalar radius;
|
||||
std::vector<Color> colors;
|
||||
std::vector<Scalar> stops;
|
||||
Point focus_center;
|
||||
Scalar focus_radius;
|
||||
Entity::TileMode tile_mode;
|
||||
Matrix effect_transform;
|
||||
};
|
||||
|
||||
struct SweepGradientData {
|
||||
Point center;
|
||||
Degrees start_angle;
|
||||
Degrees end_angle;
|
||||
std::vector<Color> colors;
|
||||
std::vector<Scalar> stops;
|
||||
Entity::TileMode tile_mode;
|
||||
Matrix effect_transform;
|
||||
};
|
||||
|
||||
struct ImageData {
|
||||
std::shared_ptr<Texture> texture;
|
||||
Entity::TileMode x_tile_mode;
|
||||
Entity::TileMode y_tile_mode;
|
||||
SamplerDescriptor sampler_descriptor;
|
||||
Matrix effect_transform;
|
||||
};
|
||||
|
||||
struct RuntimeEffectData {
|
||||
std::shared_ptr<RuntimeStage> runtime_stage;
|
||||
std::shared_ptr<std::vector<uint8_t>> uniform_data;
|
||||
std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
|
||||
};
|
||||
|
||||
#if IMPELLER_ENABLE_3D
|
||||
struct SceneData {
|
||||
std::shared_ptr<scene::Node> scene_node;
|
||||
Matrix camera_transform;
|
||||
};
|
||||
#endif // IMPELLER_ENABLE_3D
|
||||
|
||||
using ColorSourceData = std::variant<LinearGradientData,
|
||||
RadialGradientData,
|
||||
ConicalGradientData,
|
||||
SweepGradientData,
|
||||
ImageData,
|
||||
RuntimeEffectData,
|
||||
#if IMPELLER_ENABLE_3D
|
||||
SceneData,
|
||||
#endif // IMPELLER_ENABLE_3D
|
||||
std::monostate>;
|
||||
|
||||
class ColorSource {
|
||||
public:
|
||||
enum class Type {
|
||||
@ -38,9 +109,6 @@ class ColorSource {
|
||||
kScene,
|
||||
};
|
||||
|
||||
using ColorSourceProc =
|
||||
std::function<std::shared_ptr<ColorSourceContents>(const Paint& paint)>;
|
||||
|
||||
ColorSource() noexcept;
|
||||
|
||||
~ColorSource();
|
||||
@ -100,7 +168,7 @@ class ColorSource {
|
||||
|
||||
private:
|
||||
Type type_ = Type::kColor;
|
||||
ColorSourceProc proc_;
|
||||
ColorSourceData color_source_data_;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user