| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "impeller/aiks/color_source.h" |
| |
| #include <memory> |
| #include <variant> |
| #include <vector> |
| |
| #include "impeller/aiks/paint.h" |
| #include "impeller/core/sampler_descriptor.h" |
| #include "impeller/entity/contents/conical_gradient_contents.h" |
| #include "impeller/entity/contents/filters/color_filter_contents.h" |
| #include "impeller/entity/contents/linear_gradient_contents.h" |
| #include "impeller/entity/contents/radial_gradient_contents.h" |
| #include "impeller/entity/contents/runtime_effect_contents.h" |
| #include "impeller/entity/contents/solid_color_contents.h" |
| #include "impeller/entity/contents/sweep_gradient_contents.h" |
| #include "impeller/entity/contents/tiled_texture_contents.h" |
| #include "impeller/geometry/color.h" |
| #include "impeller/geometry/matrix.h" |
| #include "impeller/geometry/scalar.h" |
| #include "impeller/runtime_stage/runtime_stage.h" |
| |
| #if IMPELLER_ENABLE_3D |
| #include "impeller/entity/contents/scene_contents.h" // nogncheck |
| #include "impeller/scene/node.h" // nogncheck |
| #endif // IMPELLER_ENABLE_3D |
| |
| namespace impeller { |
| |
| 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; |
| |
| ColorSource ColorSource::MakeColor() { |
| return {}; |
| } |
| |
| ColorSource ColorSource::MakeLinearGradient(Point start_point, |
| Point end_point, |
| std::vector<Color> colors, |
| std::vector<Scalar> stops, |
| Entity::TileMode tile_mode, |
| Matrix effect_transform) { |
| ColorSource result; |
| result.type_ = Type::kLinearGradient; |
| result.color_source_data_ = |
| LinearGradientData{start_point, end_point, std::move(colors), |
| std::move(stops), tile_mode, effect_transform}; |
| return result; |
| } |
| |
| ColorSource ColorSource::MakeConicalGradient(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) { |
| ColorSource result; |
| result.type_ = Type::kConicalGradient; |
| result.color_source_data_ = ConicalGradientData{ |
| center, radius, std::move(colors), std::move(stops), |
| focus_center, focus_radius, tile_mode, effect_transform}; |
| return result; |
| } |
| |
| ColorSource ColorSource::MakeRadialGradient(Point center, |
| Scalar radius, |
| std::vector<Color> colors, |
| std::vector<Scalar> stops, |
| Entity::TileMode tile_mode, |
| Matrix effect_transform) { |
| ColorSource result; |
| result.type_ = Type::kRadialGradient; |
| result.color_source_data_ = |
| RadialGradientData{center, radius, std::move(colors), |
| std::move(stops), tile_mode, effect_transform}; |
| return result; |
| } |
| |
| ColorSource ColorSource::MakeSweepGradient(Point center, |
| Degrees start_angle, |
| Degrees end_angle, |
| std::vector<Color> colors, |
| std::vector<Scalar> stops, |
| Entity::TileMode tile_mode, |
| Matrix effect_transform) { |
| ColorSource result; |
| result.type_ = Type::kSweepGradient; |
| result.color_source_data_ = SweepGradientData{ |
| center, start_angle, end_angle, std::move(colors), |
| std::move(stops), tile_mode, effect_transform}; |
| return result; |
| } |
| |
| ColorSource ColorSource::MakeImage(std::shared_ptr<Texture> texture, |
| Entity::TileMode x_tile_mode, |
| Entity::TileMode y_tile_mode, |
| SamplerDescriptor sampler_descriptor, |
| Matrix effect_transform) { |
| ColorSource result; |
| result.type_ = Type::kImage; |
| result.color_source_data_ = |
| ImageData{std::move(texture), x_tile_mode, y_tile_mode, |
| std::move(sampler_descriptor), effect_transform}; |
| return result; |
| } |
| |
| ColorSource ColorSource::MakeRuntimeEffect( |
| std::shared_ptr<RuntimeStage> runtime_stage, |
| std::shared_ptr<std::vector<uint8_t>> uniform_data, |
| std::vector<RuntimeEffectContents::TextureInput> texture_inputs) { |
| ColorSource result; |
| result.type_ = Type::kRuntimeEffect; |
| result.color_source_data_ = |
| RuntimeEffectData{std::move(runtime_stage), std::move(uniform_data), |
| std::move(texture_inputs)}; |
| return result; |
| } |
| |
| #if IMPELLER_ENABLE_3D |
| ColorSource ColorSource::MakeScene(std::shared_ptr<scene::Node> scene_node, |
| Matrix camera_transform) { |
| ColorSource result; |
| result.type_ = Type::kScene; |
| result.color_source_data_ = SceneData{scene_node, camera_transform}; |
| return result; |
| } |
| #endif // IMPELLER_ENABLE_3D |
| |
| ColorSource::Type ColorSource::GetType() const { |
| return type_; |
| } |
| |
| std::shared_ptr<ColorSourceContents> ColorSource::GetContents( |
| const Paint& paint) const { |
| return std::visit(CreateContentsVisitor{paint}, color_source_data_); |
| } |
| |
| const ColorSourceData& ColorSource::GetData() const { |
| return color_source_data_; |
| } |
| |
| } // namespace impeller |