[Impeller] Reland: Refactor color source resolution to use explicit factory types (flutter/engine#37677)

* [Impeller] Reland: Refactor color source resolution to use explicit factory types
This commit is contained in:
Brandon DeRosier 2022-11-16 11:48:40 -08:00 committed by GitHub
parent 7bbe571f14
commit 82b8d83fb8
16 changed files with 1009 additions and 573 deletions

View File

@ -1030,6 +1030,8 @@ FILE: ../../../flutter/impeller/aiks/aiks_playground.h
FILE: ../../../flutter/impeller/aiks/aiks_unittests.cc
FILE: ../../../flutter/impeller/aiks/canvas.cc
FILE: ../../../flutter/impeller/aiks/canvas.h
FILE: ../../../flutter/impeller/aiks/color_source_factory.cc
FILE: ../../../flutter/impeller/aiks/color_source_factory.h
FILE: ../../../flutter/impeller/aiks/image.cc
FILE: ../../../flutter/impeller/aiks/image.h
FILE: ../../../flutter/impeller/aiks/paint.cc
@ -1129,6 +1131,10 @@ FILE: ../../../flutter/impeller/compiler/types.cc
FILE: ../../../flutter/impeller/compiler/types.h
FILE: ../../../flutter/impeller/compiler/utilities.cc
FILE: ../../../flutter/impeller/compiler/utilities.h
FILE: ../../../flutter/impeller/display_list/conversion_utilities.cc
FILE: ../../../flutter/impeller/display_list/conversion_utilities.h
FILE: ../../../flutter/impeller/display_list/display_list_color_source_factory.cc
FILE: ../../../flutter/impeller/display_list/display_list_color_source_factory.h
FILE: ../../../flutter/impeller/display_list/display_list_dispatcher.cc
FILE: ../../../flutter/impeller/display_list/display_list_dispatcher.h
FILE: ../../../flutter/impeller/display_list/display_list_image_impeller.cc

View File

@ -10,6 +10,8 @@ impeller_component("aiks") {
"aiks_context.h",
"canvas.cc",
"canvas.h",
"color_source_factory.cc",
"color_source_factory.h",
"image.cc",
"image.h",
"paint.cc",

View File

@ -4,7 +4,9 @@
#include <array>
#include <cmath>
#include <functional>
#include <iostream>
#include <memory>
#include <tuple>
#include <utility>
@ -31,6 +33,35 @@ namespace testing {
using AiksTest = AiksPlayground;
INSTANTIATE_PLAYGROUND_SUITE(AiksTest);
class ProcColorSourceFactory final : public ColorSourceFactory {
public:
using ColorSourceProc = std::function<std::shared_ptr<ColorSourceContents>()>;
static std::shared_ptr<ColorSourceFactory> Make(ColorSourceType type,
ColorSourceProc proc) {
auto result = std::make_shared<ProcColorSourceFactory>();
result->type_ = type;
result->proc_ = std::move(proc);
return result;
}
// |ColorSourceFactory|
~ProcColorSourceFactory() override = default;
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> MakeContents() override {
assert(proc_ != nullptr);
return proc_();
}
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType GetType() override { return type_; }
private:
ColorSourceType type_ = ColorSourceType::kColor;
ColorSourceProc proc_ = nullptr;
};
TEST_P(AiksTest, CanvasCTMCanBeUpdated) {
Canvas canvas;
Matrix identity;
@ -153,14 +184,16 @@ TEST_P(AiksTest, CanRenderTiledTexture) {
descriptor.mip_filter = mip_filters[selected_mip_filter];
descriptor.min_filter = min_mag_filters[selected_min_mag_filter];
descriptor.mag_filter = min_mag_filters[selected_min_mag_filter];
paint.color_source = [texture, x_tile_mode, y_tile_mode, descriptor]() {
auto contents = std::make_shared<TiledTextureContents>();
contents->SetTexture(texture);
contents->SetTileModes(x_tile_mode, y_tile_mode);
contents->SetSamplerDescriptor(descriptor);
contents->SetMatrix(matrix);
return contents;
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kImage,
[texture, x_tile_mode, y_tile_mode, descriptor]() {
auto contents = std::make_shared<TiledTextureContents>();
contents->SetTexture(texture);
contents->SetTileModes(x_tile_mode, y_tile_mode);
contents->SetSamplerDescriptor(descriptor);
contents->SetMatrix(matrix);
return contents;
});
paint.color = Color(1, 1, 1, alpha);
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
@ -332,19 +365,20 @@ TEST_P(AiksTest, CanRenderLinearGradient) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 0.0}};
std::vector<Scalar> stops = {0.0, 1.0};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 0.0}};
std::vector<Scalar> stops = {0.0, 1.0};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
paint.color = Color(1.0, 1.0, 1.0, alpha);
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
@ -383,33 +417,34 @@ TEST_P(AiksTest, CanRenderLinearGradientManyColors) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0,
(1.0 / 6.0) * 1,
(1.0 / 6.0) * 2,
(1.0 / 6.0) * 3,
(1.0 / 6.0) * 4,
(1.0 / 6.0) * 5,
1.0,
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() {
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0,
(1.0 / 6.0) * 1,
(1.0 / 6.0) * 2,
(1.0 / 6.0) * 3,
(1.0 / 6.0) * 4,
(1.0 / 6.0) * 5,
1.0,
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
paint.color = Color(1.0, 1.0, 1.0, alpha);
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
@ -456,16 +491,17 @@ TEST_P(AiksTest, CanRenderLinearGradientWayManyColors) {
current_stop += 1 / 2000.0;
}
stops[2000 - 1] = 1.0;
paint.color_source = [tile_mode, stops = std::move(stops),
colors = std::move(colors)]() {
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kLinearGradient,
[tile_mode, stops = std::move(stops), colors = std::move(colors)]() {
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};
@ -501,28 +537,29 @@ TEST_P(AiksTest, CanRenderLinearGradientManyColorsUnevenStops) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0,
16.0 / 62.0, 32.0 / 62.0, 1.0,
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() {
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0,
16.0 / 62.0, 32.0 / 62.0, 1.0,
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {200, 200});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};
@ -558,19 +595,20 @@ TEST_P(AiksTest, CanRenderRadialGradient) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kRadialGradient, [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
auto contents = std::make_shared<RadialGradientContents>();
contents->SetCenterAndRadius({100, 100}, 100);
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
auto contents = std::make_shared<RadialGradientContents>();
contents->SetCenterAndRadius({100, 100}, 100);
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};
@ -606,33 +644,34 @@ TEST_P(AiksTest, CanRenderRadialGradientManyColors) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0,
(1.0 / 6.0) * 1,
(1.0 / 6.0) * 2,
(1.0 / 6.0) * 3,
(1.0 / 6.0) * 4,
(1.0 / 6.0) * 5,
1.0,
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kRadialGradient, [tile_mode]() {
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0,
(1.0 / 6.0) * 1,
(1.0 / 6.0) * 2,
(1.0 / 6.0) * 3,
(1.0 / 6.0) * 4,
(1.0 / 6.0) * 5,
1.0,
};
auto contents = std::make_shared<RadialGradientContents>();
contents->SetCenterAndRadius({100, 100}, 100);
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
auto contents = std::make_shared<RadialGradientContents>();
contents->SetCenterAndRadius({100, 100}, 100);
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};
@ -668,18 +707,19 @@ TEST_P(AiksTest, CanRenderSweepGradient) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
auto contents = std::make_shared<SweepGradientContents>();
contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135));
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kSweepGradient, [tile_mode]() {
auto contents = std::make_shared<SweepGradientContents>();
contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135));
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};
@ -715,33 +755,34 @@ TEST_P(AiksTest, CanRenderSweepGradientManyColors) {
Paint paint;
canvas.Translate({100.0, 100.0, 0});
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
auto contents = std::make_shared<SweepGradientContents>();
contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135));
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0,
(1.0 / 6.0) * 1,
(1.0 / 6.0) * 2,
(1.0 / 6.0) * 3,
(1.0 / 6.0) * 4,
(1.0 / 6.0) * 5,
1.0,
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kSweepGradient, [tile_mode]() {
auto contents = std::make_shared<SweepGradientContents>();
contents->SetCenterAndAngles({100, 100}, Degrees(45), Degrees(135));
std::vector<Color> colors = {
Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
std::vector<Scalar> stops = {
0.0,
(1.0 / 6.0) * 1,
(1.0 / 6.0) * 2,
(1.0 / 6.0) * 3,
(1.0 / 6.0) * 4,
(1.0 / 6.0) * 5,
1.0,
};
contents->SetStops(std::move(stops));
contents->SetColors(std::move(colors));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
contents->SetStops(std::move(stops));
contents->SetColors(std::move(colors));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
canvas.DrawRect({0, 0, 600, 600}, paint);
return renderer.Render(canvas.EndRecordingAsPicture(), render_target);
};
@ -751,20 +792,21 @@ TEST_P(AiksTest, CanRenderSweepGradientManyColors) {
TEST_P(AiksTest, CanRenderDifferentShapesWithSameColorSource) {
Canvas canvas;
Paint paint;
paint.color_source = []() {
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {100, 100});
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {
0.0,
1.0,
};
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(Entity::TileMode::kRepeat);
return contents;
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kLinearGradient, []() {
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {100, 100});
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {
0.0,
1.0,
};
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(Entity::TileMode::kRepeat);
return contents;
});
canvas.Save();
canvas.Translate({100, 100, 0});
canvas.DrawRect({0, 0, 200, 200}, paint);
@ -1452,24 +1494,25 @@ TEST_P(AiksTest, GradientStrokesRenderCorrectly) {
paint.color = Color(1.0, 1.0, 1.0, alpha);
paint.stroke_width = 10;
auto tile_mode = tile_modes[selected_tile_mode];
paint.color_source = [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
Matrix matrix = {
1, 0, 0, 0, //
0, 1, 0, 0, //
0, 0, 1, 0, //
0, 0, 0, 1 //
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {50, 50});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
paint.color_source = ProcColorSourceFactory::Make(
ColorSourceFactory::ColorSourceType::kLinearGradient, [tile_mode]() {
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
Color{0.1294, 0.5882, 0.9529, 1.0}};
std::vector<Scalar> stops = {0.0, 1.0};
Matrix matrix = {
1, 0, 0, 0, //
0, 1, 0, 0, //
0, 0, 1, 0, //
0, 0, 0, 1 //
};
auto contents = std::make_shared<LinearGradientContents>();
contents->SetEndPoints({0, 0}, {50, 50});
contents->SetColors(std::move(colors));
contents->SetStops(std::move(stops));
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
});
Path path = PathBuilder{}
.MoveTo({20, 20})

View File

@ -160,9 +160,7 @@ void Canvas::DrawPaint(const Paint& paint) {
bool Canvas::AttemptDrawBlurredRRect(const Rect& rect,
Scalar corner_radius,
const Paint& paint) {
if (paint.color_source == nullptr ||
paint.color_source_type != Paint::ColorSourceType::kColor ||
paint.style != Paint::Style::kFill) {
if (!paint.color_source || paint.style != Paint::Style::kFill) {
return false;
}
@ -375,7 +373,7 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame,
void Canvas::DrawVertices(const Vertices& vertices,
BlendMode blend_mode,
Paint paint) {
const Paint& paint) {
auto geometry = Geometry::MakeVertices(vertices);
Entity entity;
@ -383,9 +381,8 @@ void Canvas::DrawVertices(const Vertices& vertices,
entity.SetStencilDepth(GetStencilDepth());
entity.SetBlendMode(paint.blend_mode);
if (paint.color_source.has_value()) {
auto& source = paint.color_source.value();
auto contents = source();
if (paint.color_source) {
auto contents = paint.color_source->MakeContents();
contents->SetGeometry(std::move(geometry));
contents->SetAlpha(paint.color.alpha);
entity.SetContents(paint.WithFilters(std::move(contents), true));

View File

@ -99,7 +99,7 @@ class Canvas {
void DrawVertices(const Vertices& vertices,
BlendMode blend_mode,
Paint paint);
const Paint& paint);
void DrawAtlas(const std::shared_ptr<Image>& atlas,
std::vector<Matrix> transforms,

View File

@ -0,0 +1,11 @@
// 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_factory.h"
namespace impeller {
ColorSourceFactory::~ColorSourceFactory() = default;
} // namespace impeller

View File

@ -0,0 +1,32 @@
// 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.
#pragma once
#include <memory>
#include "impeller/entity/contents/color_source_contents.h"
namespace impeller {
class ColorSourceFactory {
public:
enum class ColorSourceType {
kColor,
kImage,
kLinearGradient,
kRadialGradient,
kConicalGradient,
kSweepGradient,
kRuntimeEffect,
};
virtual ~ColorSourceFactory();
virtual std::shared_ptr<ColorSourceContents> MakeContents() = 0;
virtual ColorSourceType GetType() = 0;
};
} // namespace impeller

View File

@ -27,9 +27,8 @@ std::shared_ptr<Contents> Paint::CreateContentsForEntity(const Path& path,
std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
std::unique_ptr<Geometry> geometry) const {
if (color_source.has_value()) {
auto& source = color_source.value();
auto contents = source();
if (color_source) {
auto contents = color_source->MakeContents();
contents->SetGeometry(std::move(geometry));
contents->SetAlpha(color.alpha);
return contents;

View File

@ -7,6 +7,7 @@
#include <memory>
#include "flutter/fml/macros.h"
#include "impeller/aiks/color_source_factory.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
@ -29,23 +30,12 @@ struct Paint {
FilterInput::Ref,
bool is_solid_color,
const Matrix& effect_transform)>;
using ColorSourceProc = std::function<std::shared_ptr<ColorSourceContents>()>;
enum class Style {
kFill,
kStroke,
};
enum class ColorSourceType {
kColor,
kImage,
kLinearGradient,
kRadialGradient,
kConicalGradient,
kSweepGradient,
kRuntimeEffect,
};
struct MaskBlurDescriptor {
FilterContents::BlurStyle style;
Sigma sigma;
@ -56,10 +46,9 @@ struct Paint {
const Matrix& effect_matrix) const;
};
Color color = Color::Black();
std::optional<ColorSourceProc> color_source;
ColorSourceType color_source_type = ColorSourceType::kColor;
std::shared_ptr<ColorSourceFactory> color_source;
Color color = Color::Black();
Scalar stroke_width = 0.0;
Cap stroke_cap = Cap::kButt;
Join stroke_join = Join::kMiter;

View File

@ -6,6 +6,10 @@ import("//flutter/impeller/tools/impeller.gni")
impeller_component("display_list") {
sources = [
"conversion_utilities.cc",
"conversion_utilities.h",
"display_list_color_source_factory.cc",
"display_list_color_source_factory.h",
"display_list_dispatcher.cc",
"display_list_dispatcher.h",
"display_list_image_impeller.cc",

View File

@ -0,0 +1,179 @@
// 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/display_list/conversion_utilities.h"
namespace impeller {
BlendMode ToBlendMode(flutter::DlBlendMode mode) {
switch (mode) {
case flutter::DlBlendMode::kClear:
return BlendMode::kClear;
case flutter::DlBlendMode::kSrc:
return BlendMode::kSource;
case flutter::DlBlendMode::kDst:
return BlendMode::kDestination;
case flutter::DlBlendMode::kSrcOver:
return BlendMode::kSourceOver;
case flutter::DlBlendMode::kDstOver:
return BlendMode::kDestinationOver;
case flutter::DlBlendMode::kSrcIn:
return BlendMode::kSourceIn;
case flutter::DlBlendMode::kDstIn:
return BlendMode::kDestinationIn;
case flutter::DlBlendMode::kSrcOut:
return BlendMode::kSourceOut;
case flutter::DlBlendMode::kDstOut:
return BlendMode::kDestinationOut;
case flutter::DlBlendMode::kSrcATop:
return BlendMode::kSourceATop;
case flutter::DlBlendMode::kDstATop:
return BlendMode::kDestinationATop;
case flutter::DlBlendMode::kXor:
return BlendMode::kXor;
case flutter::DlBlendMode::kPlus:
return BlendMode::kPlus;
case flutter::DlBlendMode::kModulate:
return BlendMode::kModulate;
case flutter::DlBlendMode::kScreen:
return BlendMode::kScreen;
case flutter::DlBlendMode::kOverlay:
return BlendMode::kOverlay;
case flutter::DlBlendMode::kDarken:
return BlendMode::kDarken;
case flutter::DlBlendMode::kLighten:
return BlendMode::kLighten;
case flutter::DlBlendMode::kColorDodge:
return BlendMode::kColorDodge;
case flutter::DlBlendMode::kColorBurn:
return BlendMode::kColorBurn;
case flutter::DlBlendMode::kHardLight:
return BlendMode::kHardLight;
case flutter::DlBlendMode::kSoftLight:
return BlendMode::kSoftLight;
case flutter::DlBlendMode::kDifference:
return BlendMode::kDifference;
case flutter::DlBlendMode::kExclusion:
return BlendMode::kExclusion;
case flutter::DlBlendMode::kMultiply:
return BlendMode::kMultiply;
case flutter::DlBlendMode::kHue:
return BlendMode::kHue;
case flutter::DlBlendMode::kSaturation:
return BlendMode::kSaturation;
case flutter::DlBlendMode::kColor:
return BlendMode::kColor;
case flutter::DlBlendMode::kLuminosity:
return BlendMode::kLuminosity;
}
FML_UNREACHABLE();
}
Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) {
switch (tile_mode) {
case flutter::DlTileMode::kClamp:
return Entity::TileMode::kClamp;
case flutter::DlTileMode::kRepeat:
return Entity::TileMode::kRepeat;
case flutter::DlTileMode::kMirror:
return Entity::TileMode::kMirror;
case flutter::DlTileMode::kDecal:
return Entity::TileMode::kDecal;
}
}
impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlImageSampling options) {
impeller::SamplerDescriptor desc;
switch (options) {
case flutter::DlImageSampling::kNearestNeighbor:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
desc.label = "Nearest Sampler";
break;
case flutter::DlImageSampling::kLinear:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
desc.label = "Linear Sampler";
break;
case flutter::DlImageSampling::kMipmapLinear:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
desc.mip_filter = impeller::MipFilter::kLinear;
desc.label = "Mipmap Linear Sampler";
break;
default:
break;
}
return desc;
}
impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlFilterMode options) {
impeller::SamplerDescriptor desc;
switch (options) {
case flutter::DlFilterMode::kNearest:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
desc.label = "Nearest Sampler";
break;
case flutter::DlFilterMode::kLinear:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
desc.label = "Linear Sampler";
break;
default:
break;
}
return desc;
}
Matrix ToMatrix(const SkMatrix& m) {
return Matrix{
// clang-format off
m[0], m[3], 0, m[6],
m[1], m[4], 0, m[7],
0, 0, 1, 0,
m[2], m[5], 0, m[8],
// clang-format on
};
}
Point ToPoint(const SkPoint& point) {
return Point::MakeXY(point.fX, point.fY);
}
Color ToColor(const SkColor& color) {
return {
static_cast<Scalar>(SkColorGetR(color) / 255.0), //
static_cast<Scalar>(SkColorGetG(color) / 255.0), //
static_cast<Scalar>(SkColorGetB(color) / 255.0), //
static_cast<Scalar>(SkColorGetA(color) / 255.0) //
};
}
std::vector<Color> ToColors(const flutter::DlColor colors[], int count) {
auto result = std::vector<Color>();
if (colors == nullptr) {
return result;
}
for (int i = 0; i < count; i++) {
result.push_back(ToColor(colors[i]));
}
return result;
}
std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count) {
auto result = std::vector<Matrix>();
for (int i = 0; i < count; i++) {
auto form = xform[i];
// clang-format off
auto matrix = Matrix{
form.fSCos, form.fSSin, 0, 0,
-form.fSSin, form.fSCos, 0, 0,
0, 0, 1, 0,
form.fTx, form.fTy, 0, 1
};
// clang-format on
result.push_back(matrix);
}
return result;
}
} // namespace impeller

View File

@ -0,0 +1,69 @@
// 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.
#pragma once
#include <vector>
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_color.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_tile_mode.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/matrix.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPoint.h"
namespace impeller {
#define UNIMPLEMENTED \
FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
BlendMode ToBlendMode(flutter::DlBlendMode mode);
Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode);
impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlImageSampling options);
impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlFilterMode options);
Matrix ToMatrix(const SkMatrix& m);
Point ToPoint(const SkPoint& point);
Color ToColor(const SkColor& color);
std::vector<Color> ToColors(const flutter::DlColor colors[], int count);
std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count);
// Convert display list colors + stops into impeller colors and stops, taking
// care to ensure that the stops always start with 0.0 and end with 1.0.
template <typename T>
void ConvertStops(T* gradient,
std::vector<Color>* colors,
std::vector<float>* stops) {
FML_DCHECK(gradient->stop_count() >= 2);
auto* dl_colors = gradient->colors();
auto* dl_stops = gradient->stops();
if (dl_stops[0] != 0.0) {
colors->emplace_back(ToColor(dl_colors[0]));
stops->emplace_back(0);
}
for (auto i = 0; i < gradient->stop_count(); i++) {
colors->emplace_back(ToColor(dl_colors[i]));
stops->emplace_back(dl_stops[i]);
}
if (stops->back() != 1.0) {
colors->emplace_back(colors->back());
stops->emplace_back(1.0);
}
}
} // namespace impeller

View File

@ -0,0 +1,286 @@
// 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/display_list/display_list_color_source_factory.h"
#include <memory>
#include "flutter/display_list/display_list_color_source.h"
#include "impeller/display_list/conversion_utilities.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/sweep_gradient_contents.h"
#include "impeller/entity/contents/tiled_texture_contents.h"
namespace impeller {
//------------------------------------------------------------------------------
/// DlColorSourceFactory
///
DlColorSourceFactory::DlColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source)
: dl_color_source_(dl_color_source){};
DlColorSourceFactory::~DlColorSourceFactory() = default;
//------------------------------------------------------------------------------
/// DlImageColorSourceFactory
///
DlImageColorSourceFactory::DlImageColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source)
: DlColorSourceFactory(dl_color_source){};
DlImageColorSourceFactory::~DlImageColorSourceFactory() = default;
std::shared_ptr<ColorSourceFactory> DlImageColorSourceFactory::Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source) {
if (!dl_color_source->asImage()) {
return nullptr;
}
return std::shared_ptr<DlImageColorSourceFactory>(
new DlImageColorSourceFactory(dl_color_source));
}
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> DlImageColorSourceFactory::MakeContents() {
const flutter::DlImageColorSource* image_color_source =
dl_color_source_->asImage();
FML_DCHECK(image_color_source &&
image_color_source->image()->impeller_texture());
auto texture = image_color_source->image()->impeller_texture();
auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode());
auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode());
auto desc = ToSamplerDescriptor(image_color_source->sampling());
auto matrix = ToMatrix(image_color_source->matrix());
auto contents = std::make_shared<TiledTextureContents>();
contents->SetTexture(texture);
contents->SetTileModes(x_tile_mode, y_tile_mode);
contents->SetSamplerDescriptor(desc);
contents->SetMatrix(matrix);
return contents;
}
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType DlImageColorSourceFactory::GetType() {
return ColorSourceFactory::ColorSourceType::kImage;
}
//------------------------------------------------------------------------------
/// DlLinearGradientColorSourceFactory
///
DlLinearGradientColorSourceFactory::DlLinearGradientColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source)
: DlColorSourceFactory(dl_color_source){};
DlLinearGradientColorSourceFactory::~DlLinearGradientColorSourceFactory() =
default;
std::shared_ptr<ColorSourceFactory> DlLinearGradientColorSourceFactory::Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source) {
if (!dl_color_source->asImage()) {
return nullptr;
}
return std::shared_ptr<ColorSourceFactory>(
new DlLinearGradientColorSourceFactory(dl_color_source));
}
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents>
DlLinearGradientColorSourceFactory::MakeContents() {
const flutter::DlLinearGradientColorSource* linear =
dl_color_source_->asLinearGradient();
FML_DCHECK(linear);
auto start_point = ToPoint(linear->start_point());
auto end_point = ToPoint(linear->end_point());
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(linear, &colors, &stops);
auto tile_mode = ToTileMode(linear->tile_mode());
auto matrix = ToMatrix(linear->matrix());
auto contents = std::make_shared<LinearGradientContents>();
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetEndPoints(start_point, end_point);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
}
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType
DlLinearGradientColorSourceFactory::GetType() {
return ColorSourceFactory::ColorSourceType::kLinearGradient;
}
//------------------------------------------------------------------------------
/// DlRadialGradientColorSourceFactory
///
DlRadialGradientColorSourceFactory::DlRadialGradientColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source)
: DlColorSourceFactory(dl_color_source){};
DlRadialGradientColorSourceFactory::~DlRadialGradientColorSourceFactory() =
default;
std::shared_ptr<ColorSourceFactory> DlRadialGradientColorSourceFactory::Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source) {
if (!dl_color_source->asImage()) {
return nullptr;
}
return std::shared_ptr<ColorSourceFactory>(
new DlRadialGradientColorSourceFactory(dl_color_source));
}
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents>
DlRadialGradientColorSourceFactory::MakeContents() {
const flutter::DlRadialGradientColorSource* radial_gradient =
dl_color_source_->asRadialGradient();
FML_DCHECK(radial_gradient);
auto center = ToPoint(radial_gradient->center());
auto radius = radial_gradient->radius();
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(radial_gradient, &colors, &stops);
auto tile_mode = ToTileMode(radial_gradient->tile_mode());
auto matrix = ToMatrix(radial_gradient->matrix());
auto contents = std::make_shared<RadialGradientContents>();
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetCenterAndRadius(center, radius);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
}
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType
DlRadialGradientColorSourceFactory::GetType() {
return ColorSourceFactory::ColorSourceType::kRadialGradient;
}
//------------------------------------------------------------------------------
/// DlSweepGradientColorSourceFactory
///
DlSweepGradientColorSourceFactory::DlSweepGradientColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source)
: DlColorSourceFactory(dl_color_source){};
DlSweepGradientColorSourceFactory::~DlSweepGradientColorSourceFactory() =
default;
std::shared_ptr<ColorSourceFactory> DlSweepGradientColorSourceFactory::Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source) {
if (!dl_color_source->asImage()) {
return nullptr;
}
return std::shared_ptr<ColorSourceFactory>(
new DlSweepGradientColorSourceFactory(dl_color_source));
}
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents>
DlSweepGradientColorSourceFactory::MakeContents() {
const flutter::DlSweepGradientColorSource* sweep_gradient =
dl_color_source_->asSweepGradient();
FML_DCHECK(sweep_gradient);
auto center = ToPoint(sweep_gradient->center());
auto start_angle = Degrees(sweep_gradient->start());
auto end_angle = Degrees(sweep_gradient->end());
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(sweep_gradient, &colors, &stops);
auto tile_mode = ToTileMode(sweep_gradient->tile_mode());
auto matrix = ToMatrix(sweep_gradient->matrix());
auto contents = std::make_shared<SweepGradientContents>();
contents->SetCenterAndAngles(center, start_angle, end_angle);
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
}
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType
DlSweepGradientColorSourceFactory::GetType() {
return ColorSourceFactory::ColorSourceType::kSweepGradient;
}
//------------------------------------------------------------------------------
/// DlRuntimeEffectColorSourceFactory
///
DlRuntimeEffectColorSourceFactory::DlRuntimeEffectColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source)
: DlColorSourceFactory(dl_color_source){};
DlRuntimeEffectColorSourceFactory::~DlRuntimeEffectColorSourceFactory() =
default;
std::shared_ptr<ColorSourceFactory> DlRuntimeEffectColorSourceFactory::Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source) {
if (!dl_color_source->asImage()) {
return nullptr;
}
return std::shared_ptr<ColorSourceFactory>(
new DlRuntimeEffectColorSourceFactory(dl_color_source));
}
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents>
DlRuntimeEffectColorSourceFactory::MakeContents() {
const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
dl_color_source_->asRuntimeEffect();
auto runtime_stage =
runtime_effect_color_source->runtime_effect()->runtime_stage();
auto uniform_data = runtime_effect_color_source->uniform_data();
auto samplers = runtime_effect_color_source->samplers();
std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
for (auto& sampler : samplers) {
if (sampler == nullptr) {
return nullptr;
}
auto* image = sampler->asImage();
if (!sampler->asImage()) {
UNIMPLEMENTED;
return nullptr;
}
FML_DCHECK(image->image()->impeller_texture());
texture_inputs.push_back({
.sampler_descriptor = ToSamplerDescriptor(image->sampling()),
.texture = image->image()->impeller_texture(),
});
}
auto contents = std::make_shared<RuntimeEffectContents>();
contents->SetRuntimeStage(runtime_stage);
contents->SetUniformData(uniform_data);
contents->SetTextureInputs(texture_inputs);
return contents;
}
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType
DlRuntimeEffectColorSourceFactory::GetType() {
return ColorSourceFactory::ColorSourceType::kRuntimeEffect;
}
} // namespace impeller

View File

@ -0,0 +1,146 @@
// 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.
#pragma once
#include <memory>
#include "flutter/display_list/display_list_color_source.h"
#include "impeller/aiks/color_source_factory.h"
#include "impeller/entity/contents/color_source_contents.h"
namespace impeller {
//------------------------------------------------------------------------------
/// DlColorSourceFactory
///
class DlColorSourceFactory : public ColorSourceFactory {
public:
// |ColorSourceFactory|
~DlColorSourceFactory() override;
protected:
explicit DlColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
std::shared_ptr<flutter::DlColorSource> dl_color_source_;
};
//------------------------------------------------------------------------------
/// DlImageColorSourceFactory
///
class DlImageColorSourceFactory final : public DlColorSourceFactory {
public:
static std::shared_ptr<ColorSourceFactory> Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
// |ColorSourceFactory|
~DlImageColorSourceFactory() override;
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> MakeContents() override;
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType GetType() override;
private:
explicit DlImageColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
};
//------------------------------------------------------------------------------
/// DlLinearGradientColorSourceFactory
///
class DlLinearGradientColorSourceFactory final : public DlColorSourceFactory {
public:
static std::shared_ptr<ColorSourceFactory> Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
// |ColorSourceFactory|
~DlLinearGradientColorSourceFactory() override;
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> MakeContents() override;
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType GetType() override;
private:
explicit DlLinearGradientColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
};
//------------------------------------------------------------------------------
/// DlRadialGradientColorSourceFactory
///
class DlRadialGradientColorSourceFactory final : public DlColorSourceFactory {
public:
static std::shared_ptr<ColorSourceFactory> Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
// |ColorSourceFactory|
~DlRadialGradientColorSourceFactory() override;
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> MakeContents() override;
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType GetType() override;
private:
explicit DlRadialGradientColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
};
//------------------------------------------------------------------------------
/// DlSweepGradientColorSourceFactory
///
class DlSweepGradientColorSourceFactory final : public DlColorSourceFactory {
public:
static std::shared_ptr<ColorSourceFactory> Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
// |ColorSourceFactory|
~DlSweepGradientColorSourceFactory() override;
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> MakeContents() override;
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType GetType() override;
private:
explicit DlSweepGradientColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
};
//------------------------------------------------------------------------------
/// DlRuntimeEffectColorSourceFactory
///
class DlRuntimeEffectColorSourceFactory final : public DlColorSourceFactory {
public:
static std::shared_ptr<ColorSourceFactory> Make(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
// |ColorSourceFactory|
~DlRuntimeEffectColorSourceFactory() override;
// |ColorSourceFactory|
std::shared_ptr<ColorSourceContents> MakeContents() override;
// |ColorSourceFactory|
ColorSourceFactory::ColorSourceType GetType() override;
private:
explicit DlRuntimeEffectColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source);
};
} // namespace impeller

View File

@ -19,6 +19,8 @@
#include "display_list/display_list_tile_mode.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "impeller/display_list/conversion_utilities.h"
#include "impeller/display_list/display_list_color_source_factory.h"
#include "impeller/display_list/display_list_image_impeller.h"
#include "impeller/display_list/nine_patch_converter.h"
#include "impeller/display_list/vertices_converter.h"
@ -43,142 +45,10 @@
namespace impeller {
#define UNIMPLEMENTED \
FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
DisplayListDispatcher::DisplayListDispatcher() = default;
DisplayListDispatcher::~DisplayListDispatcher() = default;
static BlendMode ToBlendMode(flutter::DlBlendMode mode) {
switch (mode) {
case flutter::DlBlendMode::kClear:
return BlendMode::kClear;
case flutter::DlBlendMode::kSrc:
return BlendMode::kSource;
case flutter::DlBlendMode::kDst:
return BlendMode::kDestination;
case flutter::DlBlendMode::kSrcOver:
return BlendMode::kSourceOver;
case flutter::DlBlendMode::kDstOver:
return BlendMode::kDestinationOver;
case flutter::DlBlendMode::kSrcIn:
return BlendMode::kSourceIn;
case flutter::DlBlendMode::kDstIn:
return BlendMode::kDestinationIn;
case flutter::DlBlendMode::kSrcOut:
return BlendMode::kSourceOut;
case flutter::DlBlendMode::kDstOut:
return BlendMode::kDestinationOut;
case flutter::DlBlendMode::kSrcATop:
return BlendMode::kSourceATop;
case flutter::DlBlendMode::kDstATop:
return BlendMode::kDestinationATop;
case flutter::DlBlendMode::kXor:
return BlendMode::kXor;
case flutter::DlBlendMode::kPlus:
return BlendMode::kPlus;
case flutter::DlBlendMode::kModulate:
return BlendMode::kModulate;
case flutter::DlBlendMode::kScreen:
return BlendMode::kScreen;
case flutter::DlBlendMode::kOverlay:
return BlendMode::kOverlay;
case flutter::DlBlendMode::kDarken:
return BlendMode::kDarken;
case flutter::DlBlendMode::kLighten:
return BlendMode::kLighten;
case flutter::DlBlendMode::kColorDodge:
return BlendMode::kColorDodge;
case flutter::DlBlendMode::kColorBurn:
return BlendMode::kColorBurn;
case flutter::DlBlendMode::kHardLight:
return BlendMode::kHardLight;
case flutter::DlBlendMode::kSoftLight:
return BlendMode::kSoftLight;
case flutter::DlBlendMode::kDifference:
return BlendMode::kDifference;
case flutter::DlBlendMode::kExclusion:
return BlendMode::kExclusion;
case flutter::DlBlendMode::kMultiply:
return BlendMode::kMultiply;
case flutter::DlBlendMode::kHue:
return BlendMode::kHue;
case flutter::DlBlendMode::kSaturation:
return BlendMode::kSaturation;
case flutter::DlBlendMode::kColor:
return BlendMode::kColor;
case flutter::DlBlendMode::kLuminosity:
return BlendMode::kLuminosity;
}
FML_UNREACHABLE();
}
static Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) {
switch (tile_mode) {
case flutter::DlTileMode::kClamp:
return Entity::TileMode::kClamp;
case flutter::DlTileMode::kRepeat:
return Entity::TileMode::kRepeat;
case flutter::DlTileMode::kMirror:
return Entity::TileMode::kMirror;
case flutter::DlTileMode::kDecal:
return Entity::TileMode::kDecal;
}
}
static impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlImageSampling options) {
impeller::SamplerDescriptor desc;
switch (options) {
case flutter::DlImageSampling::kNearestNeighbor:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
desc.label = "Nearest Sampler";
break;
case flutter::DlImageSampling::kLinear:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
desc.label = "Linear Sampler";
break;
case flutter::DlImageSampling::kMipmapLinear:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
desc.mip_filter = impeller::MipFilter::kLinear;
desc.label = "Mipmap Linear Sampler";
break;
default:
break;
}
return desc;
}
static impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlFilterMode options) {
impeller::SamplerDescriptor desc;
switch (options) {
case flutter::DlFilterMode::kNearest:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
desc.label = "Nearest Sampler";
break;
case flutter::DlFilterMode::kLinear:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear;
desc.label = "Linear Sampler";
break;
default:
break;
}
return desc;
}
static Matrix ToMatrix(const SkMatrix& m) {
return Matrix{
// clang-format off
m[0], m[3], 0, m[6],
m[1], m[4], 0, m[7],
0, 0, 1, 0,
m[2], m[5], 0, m[8],
// clang-format on
};
}
// |flutter::Dispatcher|
void DisplayListDispatcher::setAntiAlias(bool aa) {
// Nothing to do because AA is implicit.
@ -255,255 +125,46 @@ void DisplayListDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) {
}
}
static Point ToPoint(const SkPoint& point) {
return Point::MakeXY(point.fX, point.fY);
}
static Color ToColor(const SkColor& color) {
return {
static_cast<Scalar>(SkColorGetR(color) / 255.0), //
static_cast<Scalar>(SkColorGetG(color) / 255.0), //
static_cast<Scalar>(SkColorGetB(color) / 255.0), //
static_cast<Scalar>(SkColorGetA(color) / 255.0) //
};
}
static std::vector<Color> ToColors(const flutter::DlColor colors[], int count) {
auto result = std::vector<Color>();
if (colors == nullptr) {
return result;
static std::shared_ptr<ColorSourceFactory> ToColorSourceFactory(
const std::shared_ptr<flutter::DlColorSource>& dl_color_source) {
if (!dl_color_source) {
return nullptr;
}
for (int i = 0; i < count; i++) {
result.push_back(ToColor(colors[i]));
}
return result;
}
static std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count) {
auto result = std::vector<Matrix>();
for (int i = 0; i < count; i++) {
auto form = xform[i];
// clang-format off
auto matrix = Matrix{
form.fSCos, form.fSSin, 0, 0,
-form.fSSin, form.fSCos, 0, 0,
0, 0, 1, 0,
form.fTx, form.fTy, 0, 1
};
// clang-format on
result.push_back(matrix);
}
return result;
}
// Convert display list colors + stops into impeller colors and stops, taking
// care to ensure that the stops always start with 0.0 and end with 1.0.
template <typename T>
static void ConvertStops(T* gradient,
std::vector<Color>* colors,
std::vector<float>* stops) {
FML_DCHECK(gradient->stop_count() >= 2);
auto* dl_colors = gradient->colors();
auto* dl_stops = gradient->stops();
if (dl_stops[0] != 0.0) {
colors->emplace_back(ToColor(dl_colors[0]));
stops->emplace_back(0);
}
for (auto i = 0; i < gradient->stop_count(); i++) {
colors->emplace_back(ToColor(dl_colors[i]));
stops->emplace_back(dl_stops[i]);
}
if (stops->back() != 1.0) {
colors->emplace_back(colors->back());
stops->emplace_back(1.0);
}
}
static std::optional<Paint::ColorSourceType> ToColorSourceType(
flutter::DlColorSourceType type) {
switch (type) {
switch (dl_color_source->type()) {
case flutter::DlColorSourceType::kColor:
return Paint::ColorSourceType::kColor;
return nullptr;
case flutter::DlColorSourceType::kImage:
return Paint::ColorSourceType::kImage;
return DlImageColorSourceFactory::Make(dl_color_source->shared());
case flutter::DlColorSourceType::kLinearGradient:
return Paint::ColorSourceType::kLinearGradient;
return DlLinearGradientColorSourceFactory::Make(
dl_color_source->shared());
case flutter::DlColorSourceType::kRadialGradient:
return Paint::ColorSourceType::kRadialGradient;
case flutter::DlColorSourceType::kConicalGradient:
return Paint::ColorSourceType::kConicalGradient;
return DlRadialGradientColorSourceFactory::Make(
dl_color_source->shared());
case flutter::DlColorSourceType::kSweepGradient:
return Paint::ColorSourceType::kSweepGradient;
return DlSweepGradientColorSourceFactory::Make(dl_color_source->shared());
case flutter::DlColorSourceType::kRuntimeEffect:
return Paint::ColorSourceType::kRuntimeEffect;
return DlRuntimeEffectColorSourceFactory::Make(dl_color_source->shared());
case flutter::DlColorSourceType::kConicalGradient:
case flutter::DlColorSourceType::kUnknown:
return std::nullopt;
UNIMPLEMENTED;
return nullptr;
}
}
// |flutter::Dispatcher|
void DisplayListDispatcher::setColorSource(
const flutter::DlColorSource* source) {
if (!source) {
paint_.color_source = std::nullopt;
paint_.color_source_type = Paint::ColorSourceType::kColor;
const flutter::DlColorSource* dl_color_source) {
if (!dl_color_source) {
paint_.color_source = nullptr;
return;
}
std::optional<Paint::ColorSourceType> type =
ToColorSourceType(source->type());
paint_.color_source = ToColorSourceFactory(dl_color_source->shared());
if (!type.has_value()) {
FML_LOG(ERROR) << "Requested ColorSourceType::kUnknown";
paint_.color_source = std::nullopt;
paint_.color_source_type = Paint::ColorSourceType::kColor;
return;
}
paint_.color_source_type = type.value();
switch (type.value()) {
case Paint::ColorSourceType::kColor: {
const flutter::DlColorColorSource* color = source->asColor();
paint_.color_source = std::nullopt;
setColor(color->color());
FML_DCHECK(color);
return;
}
case Paint::ColorSourceType::kLinearGradient: {
const flutter::DlLinearGradientColorSource* linear =
source->asLinearGradient();
FML_DCHECK(linear);
auto start_point = ToPoint(linear->start_point());
auto end_point = ToPoint(linear->end_point());
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(linear, &colors, &stops);
auto tile_mode = ToTileMode(linear->tile_mode());
auto matrix = ToMatrix(linear->matrix());
paint_.color_source = [start_point, end_point, colors = std::move(colors),
stops = std::move(stops), tile_mode, matrix]() {
auto contents = std::make_shared<LinearGradientContents>();
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetEndPoints(start_point, end_point);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
return;
}
case Paint::ColorSourceType::kRadialGradient: {
const flutter::DlRadialGradientColorSource* radialGradient =
source->asRadialGradient();
FML_DCHECK(radialGradient);
auto center = ToPoint(radialGradient->center());
auto radius = radialGradient->radius();
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(radialGradient, &colors, &stops);
auto tile_mode = ToTileMode(radialGradient->tile_mode());
auto matrix = ToMatrix(radialGradient->matrix());
paint_.color_source = [center, radius, colors = std::move(colors),
stops = std::move(stops), tile_mode, matrix]() {
auto contents = std::make_shared<RadialGradientContents>();
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetCenterAndRadius(center, radius);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
return;
}
case Paint::ColorSourceType::kSweepGradient: {
const flutter::DlSweepGradientColorSource* sweepGradient =
source->asSweepGradient();
FML_DCHECK(sweepGradient);
auto center = ToPoint(sweepGradient->center());
auto start_angle = Degrees(sweepGradient->start());
auto end_angle = Degrees(sweepGradient->end());
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(sweepGradient, &colors, &stops);
auto tile_mode = ToTileMode(sweepGradient->tile_mode());
auto matrix = ToMatrix(sweepGradient->matrix());
paint_.color_source = [center, start_angle, end_angle,
colors = std::move(colors),
stops = std::move(stops), tile_mode, matrix]() {
auto contents = std::make_shared<SweepGradientContents>();
contents->SetCenterAndAngles(center, start_angle, end_angle);
contents->SetColors(colors);
contents->SetStops(stops);
contents->SetTileMode(tile_mode);
contents->SetMatrix(matrix);
return contents;
};
return;
}
case Paint::ColorSourceType::kImage: {
const flutter::DlImageColorSource* image_color_source = source->asImage();
FML_DCHECK(image_color_source &&
image_color_source->image()->impeller_texture());
auto texture = image_color_source->image()->impeller_texture();
auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode());
auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode());
auto desc = ToSamplerDescriptor(image_color_source->sampling());
auto matrix = ToMatrix(image_color_source->matrix());
paint_.color_source = [texture, x_tile_mode, y_tile_mode, desc,
matrix]() {
auto contents = std::make_shared<TiledTextureContents>();
contents->SetTexture(texture);
contents->SetTileModes(x_tile_mode, y_tile_mode);
contents->SetSamplerDescriptor(desc);
contents->SetMatrix(matrix);
return contents;
};
return;
}
case Paint::ColorSourceType::kRuntimeEffect: {
const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
source->asRuntimeEffect();
auto runtime_stage =
runtime_effect_color_source->runtime_effect()->runtime_stage();
auto uniform_data = runtime_effect_color_source->uniform_data();
auto samplers = runtime_effect_color_source->samplers();
std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
for (auto& sampler : samplers) {
if (sampler == nullptr) {
return;
}
auto* image = sampler->asImage();
if (!sampler->asImage()) {
UNIMPLEMENTED;
return;
}
FML_DCHECK(image->image()->impeller_texture());
texture_inputs.push_back({
.sampler_descriptor = ToSamplerDescriptor(image->sampling()),
.texture = image->image()->impeller_texture(),
});
}
paint_.color_source = [runtime_stage, uniform_data, texture_inputs]() {
auto contents = std::make_shared<RuntimeEffectContents>();
contents->SetRuntimeStage(runtime_stage);
contents->SetUniformData(uniform_data);
contents->SetTextureInputs(texture_inputs);
return contents;
};
return;
}
case Paint::ColorSourceType::kConicalGradient:
UNIMPLEMENTED;
break;
if (const flutter::DlColorColorSource* color = dl_color_source->asColor()) {
setColor(color->color());
}
}

View File

@ -1054,5 +1054,17 @@ TEST_P(DisplayListTest, MaskBlursApplyCorrectlyToColorSources) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(DisplayListTest, CanSetNullColorSource) {
flutter::DisplayListBuilder builder;
builder.setColorSource(nullptr);
flutter::DlPaint paint;
paint.setColor(flutter::DlColor::kGreen());
builder.drawPaint(paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
} // namespace testing
} // namespace impeller