Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Prev Previous commit
Next Next commit
adjust clipping of savelayer content and improve unit tests
  • Loading branch information
flar committed Oct 26, 2023
commit a387ec21647ad13502e04c4b228912d8b171a0c3
54 changes: 41 additions & 13 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2763,28 +2763,56 @@ TEST_P(AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly) {
TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) {
Canvas canvas;

auto texture = CreateTextureForFixture("airplane.jpg");
auto blur_filter = ImageFilter::MakeBlur(Sigma{5.0}, Sigma{5.0},
auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp);
auto image_source = ColorSource::MakeImage(texture, Entity::TileMode::kRepeat,
Entity::TileMode::kRepeat, {}, {});
Entity::TileMode::kDecal);

auto DrawLine = [&canvas](const Point& p0, const Point& p1, const Paint& p) {
auto path = PathBuilder{}
.AddLine(p0, p1)
.SetConvexity(Convexity::kConvex)
.TakePath();
Paint paint = p;
paint.style = Paint::Style::kStroke;
canvas.DrawPath(path, paint);
};
// Registration marks for the edge of the SaveLayer
DrawLine(Point(75, 100), Point(225, 100), {.color = Color::White()});
DrawLine(Point(75, 200), Point(225, 200), {.color = Color::White()});
DrawLine(Point(100, 75), Point(100, 225), {.color = Color::White()});
DrawLine(Point(200, 75), Point(200, 225), {.color = Color::White()});

canvas.SaveLayer({.image_filter = blur_filter},
Rect::MakeLTRB(100, 100, 200, 200));
{
// DrawPaint to verify correct behavior when the contents are unbounded.
canvas.DrawPaint({.color = Color::Yellow()});

// Contrasting rectangle to see interior blurring
canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
{.color = Color::Blue()});
}
canvas.Restore();

canvas.DrawPaint({.color_source = image_source});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

Paint blue = {.color = Color::Blue()};
Paint green = {.color = Color::Green()};
TEST_P(AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents) {
Canvas canvas;

canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175), blue);
auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kDecal);

canvas.DrawRect(Rect::MakeLTRB(125, 50, 175, 98), green);
canvas.DrawRect(Rect::MakeLTRB(202, 125, 250, 175), green);
canvas.DrawRect(Rect::MakeLTRB(125, 202, 175, 250), green);
canvas.DrawRect(Rect::MakeLTRB(50, 125, 98, 175), green);
canvas.SaveLayer({.image_filter = blur_filter}, std::nullopt);
{
// DrawPaint to verify correct behavior when the contents are unbounded.
canvas.DrawPaint({.color = Color::Yellow()});

// Contrasting rectangle to see interior blurring
canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
{.color = Color::Blue()});
}
canvas.Restore();

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
Expand Down
17 changes: 10 additions & 7 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,6 @@ std::optional<Rect> EntityPass::GetSubpassCoverage(
std::shared_ptr<FilterContents> image_filter =
subpass.delegate_->WithImageFilter(Rect(), subpass.xformation_);

if (subpass.bounds_limit_.has_value()) {
auto user_bounds_coverage =
subpass.bounds_limit_->TransformBounds(subpass.xformation_);
coverage_limit = Intersection(user_bounds_coverage, coverage_limit);
}

// If the subpass has an image filter, then its coverage space may deviate
// from the parent pass and make intersecting with the pass coverage limit
// unsafe.
Expand All @@ -207,8 +201,17 @@ std::optional<Rect> EntityPass::GetSubpassCoverage(
}

auto entities_coverage = subpass.GetElementsCoverage(coverage_limit);
// The entities don't cover anything. There is nothing to do.
if (!entities_coverage.has_value()) {
return std::nullopt;
}

return entities_coverage;
if (!subpass.bounds_limit_.has_value()) {
return entities_coverage;
}
auto user_bounds_coverage =
subpass.bounds_limit_->TransformBounds(subpass.xformation_);
return entities_coverage->Intersection(user_bounds_coverage);
}

EntityPass* EntityPass::GetSuperpass() const {
Expand Down