mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] convert aiks blur tests to new canvas. (flutter/engine#54565)
Part of DL interop. Currently experiencing some ... issues with blur radius/sigma. EDIT: was rrect_blur vs gaussian: fixed now. Part of https://github.com/flutter/flutter/issues/142054 Reland because of CI issue?
This commit is contained in:
parent
eaca267327
commit
90dcf59597
@ -145,6 +145,7 @@
|
||||
../../../flutter/impeller/display_list/aiks_dl_atlas_unittests.cc
|
||||
../../../flutter/impeller/display_list/aiks_dl_basic_unittests.cc
|
||||
../../../flutter/impeller/display_list/aiks_dl_blend_unittests.cc
|
||||
../../../flutter/impeller/display_list/aiks_dl_blur_unittests.cc
|
||||
../../../flutter/impeller/display_list/aiks_dl_clip_unittests.cc
|
||||
../../../flutter/impeller/display_list/aiks_dl_gradient_unittests.cc
|
||||
../../../flutter/impeller/display_list/aiks_dl_opacity_unittests.cc
|
||||
|
||||
@ -58,6 +58,12 @@ struct DlColor {
|
||||
static constexpr DlColor kCornflowerBlue() {return DlColor(0xFF6495ED);};
|
||||
static constexpr DlColor kCrimson() {return DlColor(0xFFFF5733);};
|
||||
static constexpr DlColor kAqua() {return DlColor(0xFF00FFFF);};
|
||||
static constexpr DlColor kOrange() {return DlColor(0xFFFFA500);};
|
||||
static constexpr DlColor kPurple() {return DlColor(0xFF800080);};
|
||||
static constexpr DlColor kLimeGreen() {return DlColor(0xFF32CD32);};
|
||||
static constexpr DlColor kGreenYellow() {return DlColor(0xFFADFF2F);};
|
||||
static constexpr DlColor kDarkMagenta() {return DlColor(0xFF8B008B);};
|
||||
static constexpr DlColor kOrangeRed() {return DlColor(0xFFFF4500);};
|
||||
// clang-format on
|
||||
|
||||
constexpr bool isOpaque() const { return getAlpha() == 0xFF; }
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include "flutter/impeller/aiks/aiks_unittests.h"
|
||||
|
||||
#include "impeller/aiks/canvas.h"
|
||||
#include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
|
||||
#include "impeller/entity/render_target_cache.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
#include "impeller/playground/widgets.h"
|
||||
@ -20,210 +19,6 @@
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
|
||||
TEST_P(AiksTest, CanRenderMaskBlurHugeSigma) {
|
||||
Canvas canvas;
|
||||
canvas.DrawCircle({400, 400}, 300,
|
||||
{.color = Color::Green(),
|
||||
.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma(99999),
|
||||
}});
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderForegroundBlendWithMaskBlur) {
|
||||
// This case triggers the ForegroundPorterDuffBlend path. The color filter
|
||||
// should apply to the color only, and respect the alpha mask.
|
||||
Canvas canvas;
|
||||
canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
|
||||
canvas.DrawCircle({400, 400}, 200,
|
||||
{
|
||||
.color = Color::White(),
|
||||
.color_filter = ColorFilter::MakeBlend(
|
||||
BlendMode::kSource, Color::Green()),
|
||||
.mask_blur_descriptor =
|
||||
Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Radius(20),
|
||||
},
|
||||
});
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur) {
|
||||
// This case triggers the ForegroundAdvancedBlend path. The color filter
|
||||
// should apply to the color only, and respect the alpha mask.
|
||||
Canvas canvas;
|
||||
canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
|
||||
canvas.DrawCircle({400, 400}, 200,
|
||||
{
|
||||
.color = Color::Grey(),
|
||||
.color_filter = ColorFilter::MakeBlend(
|
||||
BlendMode::kColor, Color::Green()),
|
||||
.mask_blur_descriptor =
|
||||
Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Radius(20),
|
||||
},
|
||||
});
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderBackdropBlurInteractive) {
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
|
||||
static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
|
||||
auto [a, b] = DrawPlaygroundLine(point_a, point_b);
|
||||
|
||||
Canvas canvas;
|
||||
canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
|
||||
canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
|
||||
canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
|
||||
canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
|
||||
canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), {20, 20});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderBackdropBlur) {
|
||||
Canvas canvas;
|
||||
canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
|
||||
canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
|
||||
canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
|
||||
canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
|
||||
canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) {
|
||||
Canvas canvas;
|
||||
canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderClippedBlur) {
|
||||
Canvas canvas;
|
||||
canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
|
||||
canvas.DrawCircle(
|
||||
{400, 400}, 200,
|
||||
{
|
||||
.color = Color::Green(),
|
||||
.image_filter = ImageFilter::MakeBlur(
|
||||
Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kDecal),
|
||||
});
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, ClippedBlurFilterRendersCorrectlyInteractive) {
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
static PlaygroundPoint playground_point(Point(400, 400), 20,
|
||||
Color::Green());
|
||||
auto point = DrawPlaygroundPoint(playground_point);
|
||||
|
||||
Canvas canvas;
|
||||
canvas.Translate(point - Point(400, 400));
|
||||
Paint paint;
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Radius{120 * 3},
|
||||
};
|
||||
paint.color = Color::Red();
|
||||
PathBuilder builder{};
|
||||
builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
|
||||
canvas.DrawPath(builder.TakePath(), paint);
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, ClippedBlurFilterRendersCorrectly) {
|
||||
Canvas canvas;
|
||||
canvas.Translate(Point(0, -400));
|
||||
Paint paint;
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Radius{120 * 3},
|
||||
};
|
||||
paint.color = Color::Red();
|
||||
PathBuilder builder{};
|
||||
builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
|
||||
canvas.DrawPath(builder.TakePath(), paint);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, ClearBlendWithBlur) {
|
||||
Canvas canvas;
|
||||
Paint white;
|
||||
white.color = Color::Blue();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
|
||||
|
||||
Paint clear;
|
||||
clear.blend_mode = BlendMode::kClear;
|
||||
clear.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma(20),
|
||||
};
|
||||
|
||||
canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, BlurHasNoEdge) {
|
||||
Scalar sigma = 47.6;
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 50);
|
||||
ImGui::End();
|
||||
}
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.DrawPaint({});
|
||||
Paint blur = {
|
||||
.color = Color::Green(),
|
||||
.mask_blur_descriptor =
|
||||
Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma(sigma),
|
||||
},
|
||||
};
|
||||
canvas.DrawRect(Rect::MakeXYWH(300, 300, 200, 200), blur);
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, BlurredRectangleWithShader) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
@ -274,228 +69,6 @@ TEST_P(AiksTest, BlurredRectangleWithShader) {
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) {
|
||||
Canvas canvas;
|
||||
|
||||
Paint paint = {
|
||||
.color = Color::Blue(),
|
||||
.mask_blur_descriptor =
|
||||
Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma(0),
|
||||
},
|
||||
};
|
||||
|
||||
canvas.DrawCircle({300, 300}, 200, paint);
|
||||
canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
struct MaskBlurTestConfig {
|
||||
FilterContents::BlurStyle style = FilterContents::BlurStyle::kNormal;
|
||||
Scalar sigma = 1.0f;
|
||||
Scalar alpha = 1.0f;
|
||||
std::shared_ptr<ImageFilter> image_filter;
|
||||
bool invert_colors = false;
|
||||
BlendMode blend_mode = BlendMode::kSourceOver;
|
||||
};
|
||||
|
||||
static Picture MaskBlurVariantTest(const AiksTest& test_context,
|
||||
const MaskBlurTestConfig& config) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(test_context.GetContentScale());
|
||||
canvas.Scale(Vector2{0.8f, 0.8f});
|
||||
Paint paint;
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma{1},
|
||||
};
|
||||
|
||||
canvas.DrawPaint({.color = Color::AntiqueWhite()});
|
||||
|
||||
paint.mask_blur_descriptor->style = config.style;
|
||||
paint.mask_blur_descriptor->sigma = Sigma{config.sigma};
|
||||
paint.image_filter = config.image_filter;
|
||||
paint.invert_colors = config.invert_colors;
|
||||
paint.blend_mode = config.blend_mode;
|
||||
|
||||
const Scalar x = 50;
|
||||
const Scalar radius = 20.0f;
|
||||
const Scalar y_spacing = 100.0f;
|
||||
|
||||
Scalar y = 50;
|
||||
paint.color = Color::Crimson().WithAlpha(config.alpha);
|
||||
canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
|
||||
radius, 60.0f - radius),
|
||||
paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.color = Color::Blue().WithAlpha(config.alpha);
|
||||
canvas.DrawCircle({x + 25, y + 25}, radius, paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.color = Color::Green().WithAlpha(config.alpha);
|
||||
canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
|
||||
radius, 60.0f - radius),
|
||||
paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.color = Color::Purple().WithAlpha(config.alpha);
|
||||
canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
|
||||
{radius, radius}, //
|
||||
paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.color = Color::Orange().WithAlpha(config.alpha);
|
||||
canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
|
||||
{radius, 5.0f}, paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.color = Color::Maroon().WithAlpha(config.alpha);
|
||||
canvas.DrawPath(PathBuilder{}
|
||||
.MoveTo({x + 0, y + 60})
|
||||
.LineTo({x + 30, y + 0})
|
||||
.LineTo({x + 60, y + 60})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.color = Color::Maroon().WithAlpha(config.alpha);
|
||||
canvas.DrawPath(PathBuilder{}
|
||||
.AddArc(Rect::MakeXYWH(x + 5, y, 50, 50),
|
||||
Radians{kPi / 2}, Radians{kPi})
|
||||
.AddArc(Rect::MakeXYWH(x + 25, y, 50, 50),
|
||||
Radians{kPi / 2}, Radians{kPi})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
return canvas.EndRecordingAsPicture();
|
||||
}
|
||||
|
||||
static const std::map<std::string, MaskBlurTestConfig> kPaintVariations = {
|
||||
// 1. Normal style, translucent, zero sigma.
|
||||
{"NormalTranslucentZeroSigma",
|
||||
{.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = 0.0f,
|
||||
.alpha = 0.5f}},
|
||||
// 2. Normal style, translucent.
|
||||
{"NormalTranslucent",
|
||||
{.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f}},
|
||||
// 3. Solid style, translucent.
|
||||
{"SolidTranslucent",
|
||||
{.style = FilterContents::BlurStyle::kSolid,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f}},
|
||||
// 4. Solid style, opaque.
|
||||
{"SolidOpaque",
|
||||
{.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}},
|
||||
// 5. Solid style, translucent, color & image filtered.
|
||||
{"SolidTranslucentWithFilters",
|
||||
{.style = FilterContents::BlurStyle::kSolid,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f,
|
||||
.image_filter = ImageFilter::MakeBlur(Sigma{3},
|
||||
Sigma{3},
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp),
|
||||
.invert_colors = true}},
|
||||
// 6. Solid style, translucent, exclusion blended.
|
||||
{"SolidTranslucentExclusionBlend",
|
||||
{.style = FilterContents::BlurStyle::kSolid,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f,
|
||||
.blend_mode = BlendMode::kExclusion}},
|
||||
// 7. Inner style, translucent.
|
||||
{"InnerTranslucent",
|
||||
{.style = FilterContents::BlurStyle::kInner,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f}},
|
||||
// 8. Inner style, translucent, blurred.
|
||||
{"InnerTranslucentWithBlurImageFilter",
|
||||
{.style = FilterContents::BlurStyle::kInner,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f,
|
||||
.image_filter = ImageFilter::MakeBlur(Sigma{3},
|
||||
Sigma{3},
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp)}},
|
||||
// 9. Outer style, translucent.
|
||||
{"OuterTranslucent",
|
||||
{.style = FilterContents::BlurStyle::kOuter,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f}},
|
||||
// 10. Outer style, opaque, image filtered.
|
||||
{"OuterOpaqueWithBlurImageFilter",
|
||||
{.style = FilterContents::BlurStyle::kOuter,
|
||||
.sigma = 8.0f,
|
||||
.image_filter = ImageFilter::MakeBlur(Sigma{3},
|
||||
Sigma{3},
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp)}},
|
||||
};
|
||||
|
||||
#define MASK_BLUR_VARIANT_TEST(config) \
|
||||
TEST_P(AiksTest, MaskBlurVariantTest##config) { \
|
||||
ASSERT_TRUE(OpenPlaygroundHere( \
|
||||
MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \
|
||||
}
|
||||
|
||||
MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma)
|
||||
MASK_BLUR_VARIANT_TEST(NormalTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(SolidTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(SolidOpaque)
|
||||
MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters)
|
||||
MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend)
|
||||
MASK_BLUR_VARIANT_TEST(InnerTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter)
|
||||
MASK_BLUR_VARIANT_TEST(OuterTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter)
|
||||
|
||||
#undef MASK_BLUR_VARIANT_TEST
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurAtPeripheryVertical) {
|
||||
Canvas canvas;
|
||||
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.DrawRRect(Rect::MakeLTRB(0, 0, GetWindowSize().width, 100),
|
||||
Size(10, 10), Paint{.color = Color::LimeGreen()});
|
||||
canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
|
||||
Size(10, 10), Paint{.color = Color::Magenta()});
|
||||
canvas.ClipRect(Rect::MakeLTRB(100, 0, 200, GetWindowSize().height));
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurAtPeripheryHorizontal) {
|
||||
Canvas canvas;
|
||||
|
||||
canvas.Scale(GetContentScale());
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
canvas.DrawImageRect(
|
||||
std::make_shared<Image>(boston),
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
|
||||
Rect::MakeLTRB(0, 0, GetWindowSize().width, 100), Paint{});
|
||||
canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
|
||||
Size(10, 10), Paint{.color = Color::Magenta()});
|
||||
canvas.ClipRect(Rect::MakeLTRB(0, 50, GetWindowSize().width, 150));
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
#define FLT_FORWARD(mock, real, method) \
|
||||
EXPECT_CALL(*mock, method()) \
|
||||
.WillRepeatedly(::testing::Return(real->method()));
|
||||
@ -548,162 +121,6 @@ TEST_P(AiksTest, GaussianBlurWithoutDecalSupport) {
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurOneDimension) {
|
||||
Canvas canvas;
|
||||
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.Scale({0.5, 0.5, 1.0});
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
canvas.DrawImage(std::make_shared<Image>(boston), Point(100, 100), Paint{});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
// Smoketest to catch issues with the coverage hint.
|
||||
// Draws a rotated blurred image within a rectangle clip. The center of the clip
|
||||
// rectangle is the center of the rotated image. The entire area of the clip
|
||||
// rectangle should be filled with opaque colors output by the blur.
|
||||
TEST_P(AiksTest, GaussianBlurRotatedAndClipped) {
|
||||
Canvas canvas;
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
Rect bounds =
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
|
||||
Vector2 image_center = Vector2(bounds.GetSize() / 2);
|
||||
Paint paint = {.image_filter =
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kDecal)};
|
||||
Vector2 clip_size = {150, 75};
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.ClipRect(
|
||||
Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
|
||||
canvas.Translate({center.x, center.y, 0});
|
||||
canvas.Scale({0.6, 0.6, 1});
|
||||
canvas.Rotate(Degrees(25));
|
||||
|
||||
canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
|
||||
/*dest=*/bounds.Shift(-image_center), paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurScaledAndClipped) {
|
||||
Canvas canvas;
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
Rect bounds =
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
|
||||
Vector2 image_center = Vector2(bounds.GetSize() / 2);
|
||||
Paint paint = {.image_filter =
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kDecal)};
|
||||
Vector2 clip_size = {150, 75};
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.ClipRect(
|
||||
Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
|
||||
canvas.Translate({center.x, center.y, 0});
|
||||
canvas.Scale({0.6, 0.6, 1});
|
||||
|
||||
canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
|
||||
/*dest=*/bounds.Shift(-image_center), paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurRotatedAndClippedInteractive) {
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
|
||||
const Entity::TileMode tile_modes[] = {
|
||||
Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
|
||||
Entity::TileMode::kMirror, Entity::TileMode::kDecal};
|
||||
|
||||
static float rotation = 0;
|
||||
static float scale = 0.6;
|
||||
static int selected_tile_mode = 3;
|
||||
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
|
||||
ImGui::SliderFloat("Scale", &scale, 0, 2.0);
|
||||
ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
|
||||
sizeof(tile_mode_names) / sizeof(char*));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
Canvas canvas;
|
||||
Rect bounds =
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
|
||||
Vector2 image_center = Vector2(bounds.GetSize() / 2);
|
||||
Paint paint = {.image_filter =
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
tile_modes[selected_tile_mode])};
|
||||
static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
|
||||
static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
|
||||
auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.ClipRect(
|
||||
Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
|
||||
canvas.Translate({center.x, center.y, 0});
|
||||
canvas.Scale({scale, scale, 1});
|
||||
canvas.Rotate(Degrees(rotation));
|
||||
|
||||
canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
|
||||
/*dest=*/bounds.Shift(-image_center), paint);
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurRotatedNonUniform) {
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
|
||||
const Entity::TileMode tile_modes[] = {
|
||||
Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
|
||||
Entity::TileMode::kMirror, Entity::TileMode::kDecal};
|
||||
|
||||
static float rotation = 45;
|
||||
static float scale = 0.6;
|
||||
static int selected_tile_mode = 3;
|
||||
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
|
||||
ImGui::SliderFloat("Scale", &scale, 0, 2.0);
|
||||
ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
|
||||
sizeof(tile_mode_names) / sizeof(char*));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
Canvas canvas;
|
||||
Paint paint = {.color = Color::Green(),
|
||||
.image_filter =
|
||||
ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
tile_modes[selected_tile_mode])};
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.Translate({center.x, center.y, 0});
|
||||
canvas.Scale({scale, scale, 1});
|
||||
canvas.Rotate(Degrees(rotation));
|
||||
|
||||
canvas.DrawRRect(Rect::MakeXYWH(-100, -100, 200, 200), Size(10, 10), paint);
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
// This addresses a bug where tiny blurs could result in mip maps that beyond
|
||||
// the limits for the textures used for blurring.
|
||||
// See also: b/323402168
|
||||
@ -760,321 +177,5 @@ TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurAnimatedBackdrop) {
|
||||
// This test is for checking out how stable rendering is when content is
|
||||
// translated underneath a blur. Animating under a blur can cause
|
||||
// *shimmering* to happen as a result of pixel alignment.
|
||||
// See also: https://github.com/flutter/flutter/issues/140193
|
||||
auto boston = std::make_shared<Image>(
|
||||
CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true));
|
||||
ASSERT_TRUE(boston);
|
||||
int64_t count = 0;
|
||||
Scalar sigma = 20.0;
|
||||
Scalar freq = 0.1;
|
||||
Scalar amp = 50.0;
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 200);
|
||||
ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
|
||||
ImGui::SliderFloat("Amplitude", &, 1, 100);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
|
||||
canvas.DrawImage(boston,
|
||||
Point(1024 / 2 - boston->GetSize().width / 2,
|
||||
(768 / 2 - boston->GetSize().height / 2) + y),
|
||||
{});
|
||||
static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
|
||||
static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
|
||||
auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
|
||||
canvas.ClipRect(
|
||||
Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
|
||||
canvas.ClipRect(Rect::MakeLTRB(100, 100, 900, 700));
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(sigma), Sigma(sigma),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
count += 1;
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleInnerGradient) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
|
||||
Color{0.7568, 0.2627, 0.2118, 1.0}};
|
||||
std::vector<Scalar> stops = {0.0, 1.0};
|
||||
|
||||
Paint paint;
|
||||
paint.color_source = ColorSource::MakeLinearGradient(
|
||||
{0, 0}, {200, 200}, std::move(colors), std::move(stops),
|
||||
Entity::TileMode::kMirror, {});
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kInner,
|
||||
.sigma = Sigma(30),
|
||||
};
|
||||
canvas.DrawPath(PathBuilder()
|
||||
.MoveTo({200, 200})
|
||||
.LineTo({300, 400})
|
||||
.LineTo({100, 400})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleSolidGradient) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
|
||||
Color{0.7568, 0.2627, 0.2118, 1.0}};
|
||||
std::vector<Scalar> stops = {0.0, 1.0};
|
||||
|
||||
Paint paint;
|
||||
paint.color_source = ColorSource::MakeLinearGradient(
|
||||
{0, 0}, {200, 200}, std::move(colors), std::move(stops),
|
||||
Entity::TileMode::kMirror, {});
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kSolid,
|
||||
.sigma = Sigma(30),
|
||||
};
|
||||
canvas.DrawPath(PathBuilder()
|
||||
.MoveTo({200, 200})
|
||||
.LineTo({300, 400})
|
||||
.LineTo({100, 400})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleOuterGradient) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
|
||||
Color{0.7568, 0.2627, 0.2118, 1.0}};
|
||||
std::vector<Scalar> stops = {0.0, 1.0};
|
||||
|
||||
Paint paint;
|
||||
paint.color_source = ColorSource::MakeLinearGradient(
|
||||
{0, 0}, {200, 200}, std::move(colors), std::move(stops),
|
||||
Entity::TileMode::kMirror, {});
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kOuter,
|
||||
.sigma = Sigma(30),
|
||||
};
|
||||
canvas.DrawPath(PathBuilder()
|
||||
.MoveTo({200, 200})
|
||||
.LineTo({300, 400})
|
||||
.LineTo({100, 400})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleInner) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
Paint paint;
|
||||
paint.color = Color::Green();
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kInner,
|
||||
.sigma = Sigma(30),
|
||||
};
|
||||
canvas.DrawPath(PathBuilder()
|
||||
.MoveTo({200, 200})
|
||||
.LineTo({300, 400})
|
||||
.LineTo({100, 400})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleOuter) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
Paint paint;
|
||||
paint.color = Color::Green();
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kOuter,
|
||||
.sigma = Sigma(30),
|
||||
};
|
||||
canvas.DrawPath(PathBuilder()
|
||||
.MoveTo({200, 200})
|
||||
.LineTo({300, 400})
|
||||
.LineTo({100, 400})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleSolid) {
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
Paint paint;
|
||||
paint.color = Color::Green();
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kSolid,
|
||||
.sigma = Sigma(30),
|
||||
};
|
||||
canvas.DrawPath(PathBuilder()
|
||||
.MoveTo({200, 200})
|
||||
.LineTo({300, 400})
|
||||
.LineTo({100, 400})
|
||||
.Close()
|
||||
.TakePath(),
|
||||
paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, MaskBlurTexture) {
|
||||
Scalar sigma = 30;
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 500);
|
||||
ImGui::End();
|
||||
}
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
Paint paint;
|
||||
paint.color = Color::Green();
|
||||
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma(sigma),
|
||||
};
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
canvas.DrawImage(std::make_shared<Image>(boston), {200, 200}, paint);
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GuassianBlurUpdatesMipmapContents) {
|
||||
// This makes sure if mip maps are recycled across invocations of blurs the
|
||||
// contents get updated each frame correctly. If they aren't updated the color
|
||||
// inside the blur and outside the blur will be different.
|
||||
//
|
||||
// If there is some change to render target caching this could display a false
|
||||
// positive in the future. Also, if the LOD that is rendered is 1 it could
|
||||
// present a false positive.
|
||||
int32_t count = 0;
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
Canvas canvas;
|
||||
if (count++ == 0) {
|
||||
canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
|
||||
} else {
|
||||
canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()});
|
||||
}
|
||||
canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, MaskBlurDoesntStretchContents) {
|
||||
Scalar sigma = 70;
|
||||
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 500);
|
||||
ImGui::End();
|
||||
}
|
||||
Canvas canvas;
|
||||
canvas.Scale(GetContentScale());
|
||||
canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
|
||||
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
ColorSource image_source = ColorSource::MakeImage(
|
||||
boston, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
|
||||
|
||||
canvas.Transform(Matrix::MakeTranslation({100, 100, 0}) *
|
||||
Matrix::MakeScale({0.5, 0.5, 1.0}));
|
||||
Paint paint = {
|
||||
.color_source = image_source,
|
||||
.mask_blur_descriptor =
|
||||
Paint::MaskBlurDescriptor{
|
||||
.style = FilterContents::BlurStyle::kNormal,
|
||||
.sigma = Sigma(sigma),
|
||||
},
|
||||
};
|
||||
canvas.DrawRect(
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
|
||||
paint);
|
||||
|
||||
return canvas.EndRecordingAsPicture();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
@ -55,6 +55,7 @@ template("display_list_unittests_component") {
|
||||
"aiks_dl_atlas_unittests.cc",
|
||||
"aiks_dl_basic_unittests.cc",
|
||||
"aiks_dl_blend_unittests.cc",
|
||||
"aiks_dl_blur_unittests.cc",
|
||||
"aiks_dl_clip_unittests.cc",
|
||||
"aiks_dl_gradient_unittests.cc",
|
||||
"aiks_dl_opacity_unittests.cc",
|
||||
|
||||
@ -0,0 +1,977 @@
|
||||
// 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 "display_list/display_list.h"
|
||||
#include "display_list/dl_blend_mode.h"
|
||||
#include "display_list/dl_builder.h"
|
||||
#include "display_list/dl_color.h"
|
||||
#include "display_list/dl_paint.h"
|
||||
#include "display_list/dl_sampling_options.h"
|
||||
#include "display_list/dl_tile_mode.h"
|
||||
#include "display_list/effects/dl_color_filter.h"
|
||||
#include "display_list/effects/dl_color_source.h"
|
||||
#include "display_list/effects/dl_image_filter.h"
|
||||
#include "display_list/effects/dl_mask_filter.h"
|
||||
#include "flutter/impeller/aiks/aiks_unittests.h"
|
||||
|
||||
#include "impeller/display_list/dl_image_impeller.h"
|
||||
#include "impeller/playground/widgets.h"
|
||||
#include "include/core/SkRRect.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "third_party/imgui/imgui.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This is for tests of Canvas that are interested the results of rendering
|
||||
// blurs.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
|
||||
using namespace flutter;
|
||||
|
||||
TEST_P(AiksTest, CanRenderMaskBlurHugeSigma) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 99999));
|
||||
builder.DrawCircle({400, 400}, 300, paint);
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderForegroundBlendWithMaskBlur) {
|
||||
// This case triggers the ForegroundPorterDuffBlend path. The color filter
|
||||
// should apply to the color only, and respect the alpha mask.
|
||||
DisplayListBuilder builder;
|
||||
builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kWhite());
|
||||
|
||||
Sigma sigma = Radius(20);
|
||||
paint.setMaskFilter(
|
||||
DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
|
||||
paint.setColorFilter(
|
||||
DlBlendColorFilter::Make(DlColor::kGreen(), DlBlendMode::kSrc));
|
||||
builder.DrawCircle({400, 400}, 200, paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur) {
|
||||
// This case triggers the ForegroundAdvancedBlend path. The color filter
|
||||
// should apply to the color only, and respect the alpha mask.
|
||||
DisplayListBuilder builder;
|
||||
builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(
|
||||
DlColor::RGBA(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1.0f));
|
||||
|
||||
Sigma sigma = Radius(20);
|
||||
paint.setMaskFilter(
|
||||
DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
|
||||
paint.setColorFilter(
|
||||
DlBlendColorFilter::Make(DlColor::kGreen(), DlBlendMode::kColor));
|
||||
builder.DrawCircle({400, 400}, 200, paint);
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderBackdropBlurInteractive) {
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
|
||||
static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
|
||||
auto [a, b] = DrawPlaygroundLine(point_a, point_b);
|
||||
|
||||
DisplayListBuilder builder;
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kCornflowerBlue());
|
||||
builder.DrawCircle({100, 100}, 50, paint);
|
||||
|
||||
paint.setColor(DlColor::kGreenYellow());
|
||||
builder.DrawCircle({300, 200}, 100, paint);
|
||||
|
||||
paint.setColor(DlColor::kDarkMagenta());
|
||||
builder.DrawCircle({140, 170}, 75, paint);
|
||||
|
||||
paint.setColor(DlColor::kOrangeRed());
|
||||
builder.DrawCircle({180, 120}, 100, paint);
|
||||
|
||||
SkRRect rrect =
|
||||
SkRRect::MakeRectXY(SkRect::MakeLTRB(a.x, a.y, b.x, b.y), 20, 20);
|
||||
builder.ClipRRect(rrect);
|
||||
|
||||
DlPaint save_paint;
|
||||
save_paint.setBlendMode(DlBlendMode::kSrc);
|
||||
|
||||
auto backdrop_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kClamp);
|
||||
builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
|
||||
builder.Restore();
|
||||
|
||||
return builder.Build();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderBackdropBlur) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kCornflowerBlue());
|
||||
builder.DrawCircle({100, 100}, 50, paint);
|
||||
|
||||
paint.setColor(DlColor::kGreenYellow());
|
||||
builder.DrawCircle({300, 200}, 100, paint);
|
||||
|
||||
paint.setColor(DlColor::kDarkMagenta());
|
||||
builder.DrawCircle({140, 170}, 75, paint);
|
||||
|
||||
paint.setColor(DlColor::kOrangeRed());
|
||||
builder.DrawCircle({180, 120}, 100, paint);
|
||||
|
||||
SkRRect rrect =
|
||||
SkRRect::MakeRectXY(SkRect::MakeLTRB(75, 50, 375, 275), 20, 20);
|
||||
builder.ClipRRect(rrect);
|
||||
|
||||
DlPaint save_paint;
|
||||
save_paint.setBlendMode(DlBlendMode::kSrc);
|
||||
auto backdrop_filter = DlBlurImageFilter::Make(30, 30, DlTileMode::kClamp);
|
||||
builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kGreen());
|
||||
builder.DrawCircle({400, 400}, 300, paint);
|
||||
|
||||
DlPaint save_paint;
|
||||
save_paint.setBlendMode(DlBlendMode::kSrc);
|
||||
|
||||
auto backdrop_filter =
|
||||
DlBlurImageFilter::Make(999999, 999999, DlTileMode::kClamp);
|
||||
builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderClippedBlur) {
|
||||
DisplayListBuilder builder;
|
||||
builder.ClipRect(SkRect::MakeXYWH(100, 150, 400, 400));
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setImageFilter(DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal));
|
||||
builder.DrawCircle({400, 400}, 200, paint);
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, ClippedBlurFilterRendersCorrectlyInteractive) {
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
static PlaygroundPoint playground_point(Point(400, 400), 20,
|
||||
Color::Green());
|
||||
auto point = DrawPlaygroundPoint(playground_point);
|
||||
|
||||
DisplayListBuilder builder;
|
||||
auto location = point - Point(400, 400);
|
||||
builder.Translate(location.x, location.y);
|
||||
|
||||
DlPaint paint;
|
||||
Sigma sigma = Radius{120 * 3};
|
||||
paint.setMaskFilter(
|
||||
DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
|
||||
paint.setColor(DlColor::kRed());
|
||||
|
||||
SkPath path = SkPath::Rect(SkRect::MakeLTRB(0, 0, 800, 800));
|
||||
path.addCircle(0, 0, 0.5);
|
||||
builder.DrawPath(path, paint);
|
||||
return builder.Build();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, ClippedBlurFilterRendersCorrectly) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Translate(0, -400);
|
||||
DlPaint paint;
|
||||
|
||||
Sigma sigma = Radius{120 * 3};
|
||||
paint.setMaskFilter(
|
||||
DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
|
||||
paint.setColor(DlColor::kRed());
|
||||
|
||||
SkPath path = SkPath::Rect(SkRect::MakeLTRB(0, 0, 800, 800));
|
||||
path.addCircle(0, 0, 0.5);
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, ClearBlendWithBlur) {
|
||||
DisplayListBuilder builder;
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kBlue());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
|
||||
|
||||
DlPaint clear;
|
||||
clear.setBlendMode(DlBlendMode::kClear);
|
||||
clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
|
||||
|
||||
builder.DrawCircle({300.0, 300.0}, 200.0, clear);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, BlurHasNoEdge) {
|
||||
Scalar sigma = 47.6;
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 50);
|
||||
ImGui::End();
|
||||
}
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
builder.DrawPaint({});
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
|
||||
|
||||
builder.DrawRect(SkRect::MakeXYWH(300, 300, 200, 200), paint);
|
||||
return builder.Build();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kBlue());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
|
||||
|
||||
builder.DrawCircle({300, 300}, 200, paint);
|
||||
builder.DrawRect(SkRect::MakeLTRB(100, 300, 500, 600), paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
struct MaskBlurTestConfig {
|
||||
DlBlurStyle style = DlBlurStyle::kNormal;
|
||||
Scalar sigma = 1.0f;
|
||||
Scalar alpha = 1.0f;
|
||||
std::shared_ptr<DlImageFilter> image_filter;
|
||||
bool invert_colors = false;
|
||||
DlBlendMode blend_mode = DlBlendMode::kSrcOver;
|
||||
};
|
||||
|
||||
static sk_sp<DisplayList> MaskBlurVariantTest(
|
||||
const AiksTest& test_context,
|
||||
const MaskBlurTestConfig& config) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(test_context.GetContentScale().x,
|
||||
test_context.GetContentScale().y);
|
||||
builder.Scale(0.8f, 0.8f);
|
||||
|
||||
DlPaint draw_paint;
|
||||
draw_paint.setColor(
|
||||
DlColor::RGBA(Color::AntiqueWhite().red, Color::AntiqueWhite().green,
|
||||
Color::AntiqueWhite().blue, Color::AntiqueWhite().alpha));
|
||||
builder.DrawPaint(draw_paint);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
|
||||
paint.setInvertColors(config.invert_colors);
|
||||
paint.setImageFilter(config.image_filter);
|
||||
paint.setBlendMode(config.blend_mode);
|
||||
|
||||
const Scalar x = 50;
|
||||
const Scalar radius = 20.0f;
|
||||
const Scalar y_spacing = 100.0f;
|
||||
Scalar alpha = config.alpha * 255;
|
||||
|
||||
Scalar y = 50;
|
||||
paint.setColor(DlColor::kCrimson().withAlpha(alpha));
|
||||
builder.DrawRect(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
|
||||
radius, 60.0f - radius),
|
||||
paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.setColor(DlColor::kBlue().withAlpha(alpha));
|
||||
builder.DrawCircle({x + 25, y + 25}, radius, paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.setColor(DlColor::kGreen().withAlpha(alpha));
|
||||
builder.DrawOval(SkRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
|
||||
radius, 60.0f - radius),
|
||||
paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.setColor(DlColor::kPurple().withAlpha(alpha));
|
||||
SkRRect rrect =
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.setColor(DlColor::kOrange().withAlpha(alpha));
|
||||
|
||||
rrect =
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, 5.0);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
|
||||
y += y_spacing;
|
||||
paint.setColor(DlColor::kMaroon().withAlpha(alpha));
|
||||
|
||||
{
|
||||
SkPath path;
|
||||
path.moveTo(x + 0, y + 60);
|
||||
path.lineTo(x + 30, y + 0);
|
||||
path.lineTo(x + 60, y + 60);
|
||||
path.close();
|
||||
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
y += y_spacing;
|
||||
paint.setColor(DlColor::kMaroon().withAlpha(alpha));
|
||||
{
|
||||
SkPath path;
|
||||
path.addArc(SkRect::MakeXYWH(x + 5, y, 50, 50), 90, 180);
|
||||
path.addArc(SkRect::MakeXYWH(x + 25, y, 50, 50), 90, 180);
|
||||
path.close();
|
||||
builder.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
static const std::map<std::string, MaskBlurTestConfig> kPaintVariations = {
|
||||
// 1. Normal style, translucent, zero sigma.
|
||||
{"NormalTranslucentZeroSigma",
|
||||
{.style = DlBlurStyle::kNormal, .sigma = 0.0f, .alpha = 0.5f}},
|
||||
// 2. Normal style, translucent.
|
||||
{"NormalTranslucent",
|
||||
{.style = DlBlurStyle::kNormal, .sigma = 8.0f, .alpha = 0.5f}},
|
||||
// 3. Solid style, translucent.
|
||||
{"SolidTranslucent",
|
||||
{.style = DlBlurStyle::kSolid, .sigma = 8.0f, .alpha = 0.5f}},
|
||||
// 4. Solid style, opaque.
|
||||
{"SolidOpaque", {.style = DlBlurStyle::kSolid, .sigma = 8.0f}},
|
||||
// 5. Solid style, translucent, color & image filtered.
|
||||
{"SolidTranslucentWithFilters",
|
||||
{.style = DlBlurStyle::kSolid,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f,
|
||||
.image_filter = DlBlurImageFilter::Make(3, 3, DlTileMode::kClamp),
|
||||
.invert_colors = true}},
|
||||
// 6. Solid style, translucent, exclusion blended.
|
||||
{"SolidTranslucentExclusionBlend",
|
||||
{.style = DlBlurStyle::kSolid,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f,
|
||||
.blend_mode = DlBlendMode::kExclusion}},
|
||||
// 7. Inner style, translucent.
|
||||
{"InnerTranslucent",
|
||||
{.style = DlBlurStyle::kInner, .sigma = 8.0f, .alpha = 0.5f}},
|
||||
// 8. Inner style, translucent, blurred.
|
||||
{"InnerTranslucentWithBlurImageFilter",
|
||||
{.style = DlBlurStyle::kInner,
|
||||
.sigma = 8.0f,
|
||||
.alpha = 0.5f,
|
||||
.image_filter = DlBlurImageFilter::Make(3, 3, DlTileMode::kClamp)}},
|
||||
// 9. Outer style, translucent.
|
||||
{"OuterTranslucent",
|
||||
{.style = DlBlurStyle::kOuter, .sigma = 8.0f, .alpha = 0.5f}},
|
||||
// 10. Outer style, opaque, image filtered.
|
||||
{"OuterOpaqueWithBlurImageFilter",
|
||||
{.style = DlBlurStyle::kOuter,
|
||||
.sigma = 8.0f,
|
||||
.image_filter = DlBlurImageFilter::Make(3, 3, DlTileMode::kClamp)}},
|
||||
};
|
||||
|
||||
#define MASK_BLUR_VARIANT_TEST(config) \
|
||||
TEST_P(AiksTest, MaskBlurVariantTest##config) { \
|
||||
ASSERT_TRUE(OpenPlaygroundHere( \
|
||||
MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \
|
||||
}
|
||||
|
||||
MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma)
|
||||
MASK_BLUR_VARIANT_TEST(NormalTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(SolidTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(SolidOpaque)
|
||||
MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters)
|
||||
MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend)
|
||||
MASK_BLUR_VARIANT_TEST(InnerTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter)
|
||||
MASK_BLUR_VARIANT_TEST(OuterTranslucent)
|
||||
MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter)
|
||||
|
||||
#undef MASK_BLUR_VARIANT_TEST
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleInner) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
|
||||
|
||||
SkPath path;
|
||||
path.moveTo(200, 200);
|
||||
path.lineTo(300, 400);
|
||||
path.lineTo(100, 400);
|
||||
path.close();
|
||||
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleOuter) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
|
||||
|
||||
SkPath path;
|
||||
path.moveTo(200, 200);
|
||||
path.lineTo(300, 400);
|
||||
path.lineTo(100, 400);
|
||||
path.close();
|
||||
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleSolid) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
|
||||
|
||||
SkPath path;
|
||||
path.moveTo(200, 200);
|
||||
path.lineTo(300, 400);
|
||||
path.lineTo(100, 400);
|
||||
path.close();
|
||||
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, MaskBlurTexture) {
|
||||
Scalar sigma = 30;
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 500);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
|
||||
|
||||
builder.DrawImage(
|
||||
DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
|
||||
{200, 200}, DlImageSampling::kNearestNeighbor, &paint);
|
||||
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
return builder.Build();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, MaskBlurDoesntStretchContents) {
|
||||
Scalar sigma = 70;
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 500);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
|
||||
builder.Transform(SkMatrix::Translate(100, 100) *
|
||||
SkMatrix::Scale(0.5, 0.5));
|
||||
|
||||
paint.setColorSource(std::make_shared<DlImageColorSource>(
|
||||
DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
|
||||
DlImageSampling::kMipmapLinear));
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
|
||||
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, boston->GetSize().width,
|
||||
boston->GetSize().height),
|
||||
paint);
|
||||
|
||||
return builder.Build();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurAtPeripheryVertical) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
DlPaint paint;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
paint.setColor(DlColor::kLimeGreen());
|
||||
SkRRect rrect = SkRRect::MakeRectXY(
|
||||
SkRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
|
||||
paint.setColor(DlColor::kMagenta());
|
||||
rrect = SkRRect::MakeRectXY(
|
||||
SkRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
builder.ClipRect(SkRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
|
||||
|
||||
DlPaint save_paint;
|
||||
save_paint.setBlendMode(DlBlendMode::kSrc);
|
||||
|
||||
auto backdrop_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kClamp);
|
||||
|
||||
builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
|
||||
builder.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurAtPeripheryHorizontal) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
builder.DrawImageRect(
|
||||
DlImageImpeller::Make(boston),
|
||||
SkRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
|
||||
SkRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
|
||||
DlImageSampling::kNearestNeighbor);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kMagenta());
|
||||
|
||||
SkRRect rrect = SkRRect::MakeRectXY(
|
||||
SkRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
builder.ClipRect(SkRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
|
||||
|
||||
DlPaint save_paint;
|
||||
save_paint.setBlendMode(DlBlendMode::kSrc);
|
||||
|
||||
auto backdrop_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kClamp);
|
||||
builder.SaveLayer(nullptr, &save_paint, backdrop_filter.get());
|
||||
|
||||
builder.Restore();
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurAnimatedBackdrop) {
|
||||
// This test is for checking out how stable rendering is when content is
|
||||
// translated underneath a blur. Animating under a blur can cause
|
||||
// *shimmering* to happen as a result of pixel alignment.
|
||||
// See also: https://github.com/flutter/flutter/issues/140193
|
||||
auto boston =
|
||||
CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
|
||||
ASSERT_TRUE(boston);
|
||||
int64_t count = 0;
|
||||
Scalar sigma = 20.0;
|
||||
Scalar freq = 0.1;
|
||||
Scalar amp = 50.0;
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Sigma", &sigma, 0, 200);
|
||||
ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
|
||||
ImGui::SliderFloat("Amplitude", &, 1, 100);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
|
||||
builder.DrawImage(
|
||||
DlImageImpeller::Make(boston),
|
||||
SkPoint::Make(1024 / 2 - boston->GetSize().width / 2,
|
||||
(768 / 2 - boston->GetSize().height / 2) + y),
|
||||
DlImageSampling::kMipmapLinear);
|
||||
static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
|
||||
static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
|
||||
auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
|
||||
|
||||
builder.ClipRect(
|
||||
SkRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
|
||||
builder.ClipRect(SkRect::MakeLTRB(100, 100, 900, 700));
|
||||
|
||||
DlPaint paint;
|
||||
paint.setBlendMode(DlBlendMode::kSrc);
|
||||
|
||||
auto backdrop_filter =
|
||||
DlBlurImageFilter::Make(sigma, sigma, DlTileMode::kClamp);
|
||||
builder.SaveLayer(nullptr, &paint, backdrop_filter.get());
|
||||
count += 1;
|
||||
return builder.Build();
|
||||
};
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleInnerGradient) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
|
||||
DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
|
||||
std::vector<Scalar> stops = {0.0, 1.0};
|
||||
|
||||
paint = DlPaint{};
|
||||
paint.setColorSource(DlColorSource::MakeLinear(
|
||||
/*start_point=*/{0, 0},
|
||||
/*end_point=*/{200, 200},
|
||||
/*stop_count=*/colors.size(),
|
||||
/*colors=*/colors.data(),
|
||||
/*stops=*/stops.data(),
|
||||
/*tile_mode=*/DlTileMode::kMirror));
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
|
||||
|
||||
SkPath path;
|
||||
path.moveTo(200, 200);
|
||||
path.lineTo(300, 400);
|
||||
path.lineTo(100, 400);
|
||||
path.close();
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleSolidGradient) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
|
||||
DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
|
||||
std::vector<Scalar> stops = {0.0, 1.0};
|
||||
|
||||
paint = DlPaint{};
|
||||
paint.setColorSource(DlColorSource::MakeLinear(
|
||||
/*start_point=*/{0, 0},
|
||||
/*end_point=*/{200, 200},
|
||||
/*stop_count=*/colors.size(),
|
||||
/*colors=*/colors.data(),
|
||||
/*stops=*/stops.data(),
|
||||
/*tile_mode=*/DlTileMode::kMirror));
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
|
||||
|
||||
SkPath path;
|
||||
path.moveTo(200, 200);
|
||||
path.lineTo(300, 400);
|
||||
path.lineTo(100, 400);
|
||||
path.close();
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurStyleOuterGradient) {
|
||||
DisplayListBuilder builder;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
|
||||
builder.DrawPaint(paint);
|
||||
|
||||
std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
|
||||
DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
|
||||
std::vector<Scalar> stops = {0.0, 1.0};
|
||||
|
||||
paint = DlPaint{};
|
||||
paint.setColorSource(DlColorSource::MakeLinear(
|
||||
/*start_point=*/{0, 0},
|
||||
/*end_point=*/{200, 200},
|
||||
/*stop_count=*/colors.size(),
|
||||
/*colors=*/colors.data(),
|
||||
/*stops=*/stops.data(),
|
||||
/*tile_mode=*/DlTileMode::kMirror));
|
||||
paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
|
||||
|
||||
SkPath path;
|
||||
path.moveTo(200, 200);
|
||||
path.lineTo(300, 400);
|
||||
path.lineTo(100, 400);
|
||||
path.close();
|
||||
builder.DrawPath(path, paint);
|
||||
|
||||
// Draw another thing to make sure the clip area is reset.
|
||||
DlPaint red;
|
||||
red.setColor(DlColor::kRed());
|
||||
builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), red);
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurScaledAndClipped) {
|
||||
DisplayListBuilder builder;
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
Rect bounds =
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
|
||||
Vector2 image_center = Vector2(bounds.GetSize() / 2);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setImageFilter(DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal));
|
||||
|
||||
Vector2 clip_size = {150, 75};
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
auto rect =
|
||||
Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
|
||||
builder.ClipRect(SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
|
||||
rect.GetRight(), rect.GetBottom()));
|
||||
builder.Translate(center.x, center.y);
|
||||
builder.Scale(0.6, 0.6);
|
||||
|
||||
SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
|
||||
bounds.GetRight(), bounds.GetBottom());
|
||||
Rect dest = bounds.Shift(-image_center);
|
||||
SkRect sk_dst = SkRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
|
||||
dest.GetRight(), dest.GetBottom());
|
||||
builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
|
||||
/*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
|
||||
&paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurRotatedAndClippedInteractive) {
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
|
||||
const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
|
||||
DlTileMode::kMirror, DlTileMode::kDecal};
|
||||
|
||||
static float rotation = 0;
|
||||
static float scale = 0.6;
|
||||
static int selected_tile_mode = 3;
|
||||
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
|
||||
ImGui::SliderFloat("Scale", &scale, 0, 2.0);
|
||||
ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
|
||||
sizeof(tile_mode_names) / sizeof(char*));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
Rect bounds =
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
|
||||
Vector2 image_center = Vector2(bounds.GetSize() / 2);
|
||||
DlPaint paint;
|
||||
paint.setImageFilter(
|
||||
DlBlurImageFilter::Make(20, 20, tile_modes[selected_tile_mode]));
|
||||
|
||||
static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
|
||||
static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
|
||||
auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
builder.ClipRect(
|
||||
SkRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
|
||||
builder.Translate(center.x, center.y);
|
||||
builder.Scale(scale, scale);
|
||||
builder.Rotate(rotation);
|
||||
|
||||
SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
|
||||
bounds.GetRight(), bounds.GetBottom());
|
||||
Rect dest = bounds.Shift(-image_center);
|
||||
SkRect sk_dst = SkRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
|
||||
dest.GetRight(), dest.GetBottom());
|
||||
builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
|
||||
/*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
|
||||
&paint);
|
||||
return builder.Build();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurOneDimension) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
builder.Scale(0.5, 0.5);
|
||||
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
builder.DrawImage(DlImageImpeller::Make(boston), {100, 100}, {});
|
||||
|
||||
DlPaint paint;
|
||||
paint.setBlendMode(DlBlendMode::kSrc);
|
||||
|
||||
auto backdrop_filter = DlBlurImageFilter::Make(50, 0, DlTileMode::kClamp);
|
||||
builder.SaveLayer(nullptr, &paint, backdrop_filter.get());
|
||||
builder.Restore();
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
// Smoketest to catch issues with the coverage hint.
|
||||
// Draws a rotated blurred image within a rectangle clip. The center of the clip
|
||||
// rectangle is the center of the rotated image. The entire area of the clip
|
||||
// rectangle should be filled with opaque colors output by the blur.
|
||||
TEST_P(AiksTest, GaussianBlurRotatedAndClipped) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
|
||||
Rect bounds =
|
||||
Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
|
||||
|
||||
DlPaint paint;
|
||||
paint.setImageFilter(DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal));
|
||||
|
||||
Vector2 image_center = Vector2(bounds.GetSize() / 2);
|
||||
Vector2 clip_size = {150, 75};
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
|
||||
auto clip_bounds =
|
||||
Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
|
||||
builder.ClipRect(SkRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
|
||||
clip_bounds.GetRight(),
|
||||
clip_bounds.GetBottom()));
|
||||
builder.Translate(center.x, center.y);
|
||||
builder.Scale(0.6, 0.6);
|
||||
builder.Rotate(25);
|
||||
|
||||
auto dst_rect = bounds.Shift(-image_center);
|
||||
builder.DrawImageRect(
|
||||
DlImageImpeller::Make(boston), /*src=*/
|
||||
SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
|
||||
bounds.GetBottom()),
|
||||
/*dst=*/
|
||||
SkRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
|
||||
dst_rect.GetRight(), dst_rect.GetBottom()),
|
||||
DlImageSampling::kMipmapLinear, &paint);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, GaussianBlurRotatedNonUniform) {
|
||||
auto callback = [&]() -> sk_sp<DisplayList> {
|
||||
const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
|
||||
const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
|
||||
DlTileMode::kMirror, DlTileMode::kDecal};
|
||||
|
||||
static float rotation = 45;
|
||||
static float scale = 0.6;
|
||||
static int selected_tile_mode = 3;
|
||||
|
||||
if (AiksTest::ImGuiBegin("Controls", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
|
||||
ImGui::SliderFloat("Scale", &scale, 0, 2.0);
|
||||
ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
|
||||
sizeof(tile_mode_names) / sizeof(char*));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
DisplayListBuilder builder;
|
||||
|
||||
DlPaint paint;
|
||||
paint.setColor(DlColor::kGreen());
|
||||
paint.setImageFilter(
|
||||
DlBlurImageFilter::Make(50, 0, tile_modes[selected_tile_mode]));
|
||||
|
||||
Vector2 center = Vector2(1024, 768) / 2;
|
||||
builder.Scale(GetContentScale().x, GetContentScale().y);
|
||||
builder.Translate(center.x, center.y);
|
||||
builder.Scale(scale, scale);
|
||||
builder.Rotate(rotation);
|
||||
|
||||
SkRRect rrect =
|
||||
SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
|
||||
builder.DrawRRect(rrect, paint);
|
||||
return builder.Build();
|
||||
};
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
@ -702,9 +702,6 @@ impeller_Play_AiksTest_GaussianBlurWithoutDecalSupport_Metal.png
|
||||
impeller_Play_AiksTest_GradientStrokesRenderCorrectly_Metal.png
|
||||
impeller_Play_AiksTest_GradientStrokesRenderCorrectly_OpenGLES.png
|
||||
impeller_Play_AiksTest_GradientStrokesRenderCorrectly_Vulkan.png
|
||||
impeller_Play_AiksTest_GuassianBlurUpdatesMipmapContents_Metal.png
|
||||
impeller_Play_AiksTest_GuassianBlurUpdatesMipmapContents_OpenGLES.png
|
||||
impeller_Play_AiksTest_GuassianBlurUpdatesMipmapContents_Vulkan.png
|
||||
impeller_Play_AiksTest_ImageColorSourceEffectTransform_Metal.png
|
||||
impeller_Play_AiksTest_ImageColorSourceEffectTransform_OpenGLES.png
|
||||
impeller_Play_AiksTest_ImageColorSourceEffectTransform_Vulkan.png
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user