diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 224e24571ac95..9a576142b2c72 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -140,6 +140,7 @@ ../../../flutter/impeller/compiler/shader_bundle_unittests.cc ../../../flutter/impeller/compiler/switches_unittests.cc ../../../flutter/impeller/core/allocator_unittests.cc +../../../flutter/impeller/display_list/aiks_dl_clip_unittests.cc ../../../flutter/impeller/display_list/aiks_dl_opacity_unittests.cc ../../../flutter/impeller/display_list/aiks_dl_path_unittests.cc ../../../flutter/impeller/display_list/dl_golden_unittests.cc diff --git a/display_list/dl_color.h b/display_list/dl_color.h index 8746b96e3120d..18c22d7709ebf 100644 --- a/display_list/dl_color.h +++ b/display_list/dl_color.h @@ -31,6 +31,9 @@ struct DlColor { static constexpr DlColor kMidGrey() {return DlColor(0xFF808080);}; static constexpr DlColor kLightGrey() {return DlColor(0xFFC0C0C0);}; static constexpr DlColor kAliceBlue() {return DlColor(0xFFF0F8FF);}; + static constexpr DlColor kFuchsia() {return DlColor(0xFFFF00FF);}; + static constexpr DlColor kMaroon() {return DlColor(0xFF800000);} + static constexpr DlColor kSkyBlue() {return DlColor(0xFF87CEEB);} // clang-format on constexpr bool isOpaque() const { return getAlpha() == 0xFF; } diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index cd0aa0f907691..79f472a2eac53 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -311,97 +311,6 @@ TEST_P(AiksTest, CanRenderSimpleClips) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -TEST_P(AiksTest, CanRenderNestedClips) { - Canvas canvas; - Paint paint; - paint.color = Color::Fuchsia(); - canvas.Save(); - canvas.ClipPath(PathBuilder{}.AddCircle({200, 400}, 300).TakePath()); - canvas.Restore(); - canvas.ClipPath(PathBuilder{}.AddCircle({600, 400}, 300).TakePath()); - canvas.ClipPath(PathBuilder{}.AddCircle({400, 600}, 300).TakePath()); - canvas.DrawRect(Rect::MakeXYWH(200, 200, 400, 400), paint); - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -TEST_P(AiksTest, CanRenderDifferenceClips) { - Paint paint; - Canvas canvas; - canvas.Translate({400, 400}); - - // Limit drawing to face circle with a clip. - canvas.ClipPath(PathBuilder{}.AddCircle(Point(), 200).TakePath()); - canvas.Save(); - - // Cut away eyes/mouth using difference clips. - canvas.ClipPath(PathBuilder{}.AddCircle({-100, -50}, 30).TakePath(), - Entity::ClipOperation::kDifference); - canvas.ClipPath(PathBuilder{}.AddCircle({100, -50}, 30).TakePath(), - Entity::ClipOperation::kDifference); - canvas.ClipPath(PathBuilder{} - .AddQuadraticCurve({-100, 50}, {0, 150}, {100, 50}) - .TakePath(), - Entity::ClipOperation::kDifference); - - // Draw a huge yellow rectangle to prove the clipping works. - paint.color = Color::Yellow(); - canvas.DrawRect(Rect::MakeXYWH(-1000, -1000, 2000, 2000), paint); - - // Remove the difference clips and draw hair that partially covers the eyes. - canvas.Restore(); - paint.color = Color::Maroon(); - canvas.DrawPath(PathBuilder{} - .MoveTo({200, -200}) - .HorizontalLineTo(-200) - .VerticalLineTo(-40) - .CubicCurveTo({0, -40}, {0, -80}, {200, -80}) - .TakePath(), - paint); - - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -TEST_P(AiksTest, CanRenderWithContiguousClipRestores) { - Canvas canvas; - - // Cover the whole canvas with red. - canvas.DrawPaint({.color = Color::Red()}); - - canvas.Save(); - - // Append two clips, the second resulting in empty coverage. - canvas.ClipPath( - PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath()); - canvas.ClipPath( - PathBuilder{}.AddRect(Rect::MakeXYWH(300, 300, 100, 100)).TakePath()); - - // Restore to no clips. - canvas.Restore(); - - // Replace the whole canvas with green. - canvas.DrawPaint({.color = Color::Green()}); - - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -TEST_P(AiksTest, ClipsUseCurrentTransform) { - std::array colors = {Color::White(), Color::Black(), - Color::SkyBlue(), Color::Red(), - Color::Yellow()}; - Canvas canvas; - Paint paint; - - canvas.Translate(Vector3(300, 300)); - for (int i = 0; i < 15; i++) { - canvas.Scale(Vector3(0.8, 0.8)); - - paint.color = colors[i % colors.size()]; - canvas.ClipPath(PathBuilder{}.AddCircle({0, 0}, 300).TakePath()); - canvas.DrawRect(Rect::MakeXYWH(-300, -300, 600, 600), paint); - } - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - TEST_P(AiksTest, CanSaveLayerStandalone) { Canvas canvas; diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn index 599259fc2f437..4c34486798443 100644 --- a/impeller/display_list/BUILD.gn +++ b/impeller/display_list/BUILD.gn @@ -52,6 +52,7 @@ impeller_component("display_list") { template("display_list_unittests_component") { target_name = invoker.target_name predefined_sources = [ + "aiks_dl_clip_unittests.cc", "aiks_dl_opacity_unittests.cc", "aiks_dl_path_unittests.cc", "dl_golden_unittests.cc", diff --git a/impeller/display_list/aiks_dl_clip_unittests.cc b/impeller/display_list/aiks_dl_clip_unittests.cc new file mode 100644 index 0000000000000..5576f343f9945 --- /dev/null +++ b/impeller/display_list/aiks_dl_clip_unittests.cc @@ -0,0 +1,121 @@ +// 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 "flutter/impeller/aiks/aiks_unittests.h" + +#include "flutter/display_list/dl_blend_mode.h" +#include "flutter/display_list/dl_builder.h" +#include "flutter/display_list/dl_color.h" +#include "flutter/display_list/dl_paint.h" +#include "flutter/display_list/effects/dl_color_filter.h" +#include "flutter/testing/testing.h" + +namespace impeller { +namespace testing { + +using namespace flutter; + +namespace { +SkPath CreateCircle(Scalar x, Scalar y, Scalar radius) { + SkPath path; + path.addCircle(x, y, radius); + return path; +} +} // namespace + +TEST_P(AiksTest, CanRenderNestedClips) { + DisplayListBuilder builder; + DlPaint paint; + paint.setColor(DlColor::kFuchsia()); + + builder.Save(); + builder.ClipPath(CreateCircle(200, 400, 300)); + builder.Restore(); + builder.ClipPath(CreateCircle(600, 400, 300)); + builder.ClipPath(CreateCircle(400, 600, 300)); + builder.DrawRect(SkRect::MakeXYWH(200, 200, 400, 400), paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +TEST_P(AiksTest, CanRenderDifferenceClips) { + DisplayListBuilder builder; + builder.Translate(400, 400); + + // Limit drawing to face circle with a clip. + builder.ClipPath(CreateCircle(0, 0, 200)); + builder.Save(); + + // Cut away eyes/mouth using difference clips. + builder.ClipPath(CreateCircle(-100, -50, 30), DlCanvas::ClipOp::kDifference); + builder.ClipPath(CreateCircle(100, -50, 30), DlCanvas::ClipOp::kDifference); + + SkPath path; + path.moveTo(-100, 50); + path.quadTo(0, 150, 100, 50); + builder.ClipPath(path, DlCanvas::ClipOp::kDifference); + + // Draw a huge yellow rectangle to prove the clipping works. + DlPaint paint; + paint.setColor(DlColor::kYellow()); + builder.DrawRect(SkRect::MakeXYWH(-1000, -1000, 2000, 2000), paint); + + // Remove the difference clips and draw hair that partially covers the eyes. + builder.Restore(); + paint.setColor(DlColor::kMaroon()); + SkPath path_2; + path_2.moveTo(200, -200); + path_2.lineTo(-200, -200); + path_2.lineTo(-200, -40); + path_2.cubicTo({0, -40}, {0, -80}, {200, -80}); + + builder.DrawPath(path_2, paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +TEST_P(AiksTest, CanRenderWithContiguousClipRestores) { + DisplayListBuilder builder; + + // Cover the whole canvas with red. + DlPaint paint; + paint.setColor(DlColor::kRed()); + builder.DrawPaint(paint); + + builder.Save(); + + // Append two clips, the second resulting in empty coverage. + builder.ClipRect(SkRect::MakeXYWH(100, 100, 100, 100)); + builder.ClipRect(SkRect::MakeXYWH(300, 300, 100, 100)); + + // Restore to no clips. + builder.Restore(); + + // Replace the whole canvas with green. + paint.setColor(DlColor::kGreen()); + builder.DrawPaint(paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +TEST_P(AiksTest, ClipsUseCurrentTransform) { + std::array colors = {DlColor::kWhite(), DlColor::kBlack(), + DlColor::kSkyBlue(), DlColor::kRed(), + DlColor::kYellow()}; + DisplayListBuilder builder; + DlPaint paint; + + builder.Translate(300, 300); + for (int i = 0; i < 15; i++) { + builder.Scale(0.8, 0.8); + + paint.setColor(colors[i % colors.size()]); + builder.ClipPath(CreateCircle(0, 0, 300)); + builder.DrawRect(SkRect::MakeXYWH(-300, -300, 600, 600), paint); + } + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +} // namespace testing +} // namespace impeller