diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 8af28dcf5df54..eebf34fe76db2 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -47,6 +47,34 @@ using AiksTest = AiksPlayground; #endif INSTANTIATE_PLAYGROUND_SUITE(AiksTest); +TEST_P(AiksTest, RotateColorFilteredPath) { + Canvas canvas; + canvas.Concat(Matrix::MakeTranslation({300, 300})); + canvas.Concat(Matrix::MakeRotationZ(Radians(kPiOver2))); + auto arrow_stem = + PathBuilder{}.MoveTo({120, 190}).LineTo({120, 50}).TakePath(); + auto arrow_head = PathBuilder{} + .MoveTo({50, 120}) + .LineTo({120, 190}) + .LineTo({190, 120}) + .TakePath(); + auto paint = Paint{ + .stroke_width = 15.0, + .stroke_cap = Cap::kRound, + .stroke_join = Join::kRound, + .style = Paint::Style::kStroke, + .color_filter = + [](FilterInput::Ref input) { + return ColorFilterContents::MakeBlend( + BlendMode::kSourceIn, {std::move(input)}, Color::AliceBlue()); + }, + }; + + canvas.DrawPath(arrow_stem, paint); + canvas.DrawPath(arrow_head, paint); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + TEST_P(AiksTest, CanvasCTMCanBeUpdated) { Canvas canvas; Matrix identity; diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index b7ad908cd0160..5353417ea5095 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -2451,5 +2451,37 @@ TEST_P(EntityTest, InheritOpacityTest) { ASSERT_FALSE(runtime_effect->CanInheritOpacity(entity)); } +TEST_P(EntityTest, ColorFilterWithForegroundColorAdvancedBlend) { + auto image = CreateTextureForFixture("boston.jpg"); + auto filter = ColorFilterContents::MakeBlend( + BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red()); + + auto callback = [&](ContentContext& context, RenderPass& pass) -> bool { + Entity entity; + entity.SetTransformation(Matrix::MakeScale(GetContentScale()) * + Matrix::MakeTranslation({500, 300}) * + Matrix::MakeScale(Vector2{0.5, 0.5})); + entity.SetContents(filter); + return entity.Render(context, pass); + }; + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + +TEST_P(EntityTest, CoverageForStrokePathWithNegativeValuesInTransform) { + auto arrow_head = PathBuilder{} + .MoveTo({50, 120}) + .LineTo({120, 190}) + .LineTo({190, 120}) + .TakePath(); + auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound, + Join::kRound); + + auto transform = Matrix::MakeTranslation({300, 300}) * + Matrix::MakeRotationZ(Radians(kPiOver2)); + EXPECT_LT(transform.e[0][0], 0.f); + auto coverage = geometry->GetCoverage(transform); + ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155)); +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/geometry.cc b/impeller/entity/geometry.cc index 7e8ed784cb4da..612d9cb3a1af2 100644 --- a/impeller/entity/geometry.cc +++ b/impeller/entity/geometry.cc @@ -620,9 +620,11 @@ std::optional StrokePathGeometry::GetCoverage( return std::nullopt; } Scalar min_size = 1.0f / sqrt(std::abs(determinant)); - Vector2 max_radius_xy = transform.TransformDirection( - Vector2(max_radius, max_radius) * std::max(stroke_width_, min_size)); - + Vector2 max_radius_xy = + transform + .TransformDirection(Vector2(max_radius, max_radius) * + std::max(stroke_width_, min_size)) + .Abs(); return Rect(path_coverage.origin - max_radius_xy, Size(path_coverage.size.width + max_radius_xy.x * 2, path_coverage.size.height + max_radius_xy.y * 2));