7#include <unordered_set>
25#if IMPELLER_SUPPORTS_RENDERING
37 return builder.asReceiver();
41 return builder.CurrentAttributes();
45 return builder.LastOpIndex();
50static std::vector<testing::DisplayListInvocationGroup>
allGroups =
53template <
typename BaseT>
65 return builder.
Build();
68 static sk_sp<DisplayList>
Build(
size_t g_index,
size_t v_index) {
72 uint32_t op_count = 0u;
73 size_t byte_count = 0u;
75 uint32_t render_op_depth_cost = 1u;
78 size_t j = (
i == g_index ? v_index : 0);
86 invocation.
Invoke(receiver);
87 render_op_depth_cost =
90 sk_sp<DisplayList> dl = builder.
Build();
96 if (v_index >=
allGroups[g_index].variants.size()) {
99 name +=
" variant " + std::to_string(v_index + 1);
102 EXPECT_EQ(dl->op_count(
false), op_count) <<
name;
104 EXPECT_EQ(dl->total_depth(), depth) <<
name;
127 EXPECT_EQ(builder_paint, defaults);
146 const std::string& desc) {
149 renderer(builder, paint, render_rect);
150 auto dl = builder.
Build();
151 EXPECT_EQ(dl->op_count(), 1u) << desc;
152 EXPECT_EQ(dl->GetBounds(), expected_bounds) << desc;
156 const std::string& desc) {
164 auto empty_setup = [](
DlCanvas&) {};
170 ASSERT_TRUE(invertedLR.
IsEmpty());
172 ASSERT_TRUE(invertedTB.
IsEmpty());
175 ASSERT_TRUE(invertedLTRB.
IsEmpty());
180 ref_bounds, desc +
" LR swapped");
182 ref_bounds, desc +
" TB swapped");
184 ref_bounds, desc +
" LR&TB swapped");
197 stroke_bounds, desc +
" LR swapped, sw 2");
199 stroke_bounds, desc +
" TB swapped, sw 2");
201 stroke_bounds, desc +
" LR&TB swapped, sw 2");
208 maskblur_bounds, desc +
" LR swapped, mask 2");
210 maskblur_bounds, desc +
" TB swapped, mask 2");
212 maskblur_bounds, desc +
" LR&TB swapped, mask 2");
219 erode_bounds, desc +
" LR swapped, erode 2");
221 erode_bounds, desc +
" TB swapped, erode 2");
223 erode_bounds, desc +
" LR&TB swapped, erode 2");
233 check_defaults(builder);
238 auto dl = builder.
Build();
239 EXPECT_EQ(dl->op_count(), 0u);
241 EXPECT_EQ(dl->total_depth(), 0u);
246 auto dl1 = builder.
Build();
247 auto dl2 = builder.
Build();
248 auto dl3 = builder.
Build();
249 ASSERT_TRUE(dl1->Equals(dl2));
250 ASSERT_TRUE(dl2->Equals(dl3));
258 auto dl1 = builder.
Build();
259 EXPECT_EQ(dl1->op_count(), 1u);
265 auto dl2 = builder.
Build();
266 EXPECT_EQ(dl2->op_count(), 0u);
268 EXPECT_EQ(dl2->GetBounds(),
DlRect());
278 for (
int i = 0;
i <= max_type;
i++) {
284 for (
int i = 0;
i <= max_category;
i++) {
293 auto dl = builder.
Build();
295 EXPECT_EQ(dl->GetOpType(
i), DisplayListOpType::kDrawRect)
305 auto dl = builder.
Build();
308 EXPECT_FALSE(dl->Dispatch(receiver, -1));
309 EXPECT_FALSE(dl->Dispatch(receiver, dl->GetRecordCount()));
313 EXPECT_EQ(dl->GetOpCategory(dl->GetRecordCount()),
326 auto dl = builder.
Build();
329 EXPECT_EQ(dl->GetRecordCount(), 1u);
330 EXPECT_TRUE(dl->Dispatch(receiver, 0u));
331 EXPECT_EQ(dl->GetOpType(0u), DisplayListOpType::kDrawRect);
339 auto dl = builder.
Build();
341 auto dl2 = builder.
Build();
342 ASSERT_TRUE(dl->Equals(dl2));
352 check_defaults(builder, cull_rect);
355 builder.
Scale(10.0f, 10.0f);
357 check_defaults(builder, cull_rect);
360 builder.
Skew(0.1f, 0.1f);
362 check_defaults(builder, cull_rect);
367 check_defaults(builder, cull_rect);
372 check_defaults(builder, cull_rect);
378 check_defaults(builder, cull_rect);
382 0.0f, 1.0f, 0.0f, 35.0f,
383 0.0f, 0.0f, 1.0f, 5.0f,
384 0.0f, 0.0f, 0.0f, 1.0f);
386 check_defaults(builder, cull_rect);
395 check_defaults(builder, cull_rect);
397 builder.
Scale(10.0f, 10.0f);
399 check_defaults(builder, cull_rect);
401 builder.
Skew(0.1f, 0.1f);
403 check_defaults(builder, cull_rect);
407 check_defaults(builder, cull_rect);
411 check_defaults(builder, cull_rect);
416 check_defaults(builder, cull_rect);
419 0.0f, 1.0f, 0.0f, 35.0f,
420 0.0f, 0.0f, 1.0f, 5.0f,
421 0.0f, 0.0f, 0.0f, 1.0f);
423 check_defaults(builder, cull_rect);
433 check_defaults(builder, cull_rect);
439 check_defaults(builder, cull_rect);
444 check_defaults(builder, cull_rect);
453 check_defaults(builder, cull_rect);
458 check_defaults(builder, cull_rect);
462 check_defaults(builder, cull_rect);
472 check_defaults(builder, cull_rect);
476 check_defaults(builder, cull_rect);
480 check_defaults(builder, cull_rect);
484 check_defaults(builder, cull_rect);
488 check_defaults(builder, cull_rect);
492 check_defaults(builder, cull_rect);
496 check_defaults(builder, cull_rect);
500 check_defaults(builder, cull_rect);
504 check_defaults(builder, cull_rect);
508 check_defaults(builder, cull_rect);
512 check_defaults(builder, cull_rect);
516 check_defaults(builder, cull_rect);
520 check_defaults(builder, cull_rect);
539 auto NaN = std::numeric_limits<DlScalar>::quiet_NaN();
590 ASSERT_TRUE(cull_rect.
Contains(clip_rect));
591 ASSERT_TRUE(cull_rect.
Contains(draw_rect));
597 builder.
SaveLayer(cull_rect, &layer_paint);
604 auto display_list = builder.
Build();
606 EXPECT_EQ(display_list->op_count(), 6u);
607 EXPECT_EQ(display_list->total_depth(), 2u);
613 EXPECT_EQ(display_list->GetBounds(), result_rect);
624 ASSERT_TRUE(cull_rect.
Contains(clip_rect));
625 ASSERT_TRUE(cull_rect.
Contains(draw_rect));
631 builder.
SaveLayer(cull_rect, &layer_paint);
638 auto display_list = builder.
Build();
640 EXPECT_EQ(display_list->op_count(), 6u);
641 EXPECT_EQ(display_list->total_depth(), 2u);
647 EXPECT_EQ(display_list->GetBounds(), result_rect);
662 ASSERT_TRUE(filter->map_local_bounds(draw_rect, mapped_rect));
666 builder.
SaveLayer(cull_rect, &layer_paint);
671 auto display_list = builder.
Build();
673 EXPECT_EQ(display_list->op_count(), 2u);
674 EXPECT_EQ(display_list->total_depth(), 1u);
676 EXPECT_TRUE(display_list->GetBounds().IsEmpty()) << display_list->GetBounds();
692 ASSERT_TRUE(filter->map_local_bounds(draw_rect, mapped_rect));
696 builder.
SaveLayer(cull_rect, &layer_paint);
701 auto display_list = builder.
Build();
703 EXPECT_EQ(display_list->op_count(), 2u);
704 EXPECT_EQ(display_list->total_depth(), 1u);
706 EXPECT_TRUE(display_list->GetBounds().IsEmpty()) << display_list->GetBounds();
711 for (
size_t i = 0;
i < group.variants.size();
i++) {
712 auto& invocation = group.variants[
i];
713 sk_sp<DisplayList> dl = Build(invocation);
714 auto desc = group.op_name +
"(variant " + std::to_string(
i + 1) +
")";
715 EXPECT_EQ(dl->op_count(
false), invocation.op_count()) << desc;
716 EXPECT_EQ(dl->bytes(
false), invocation.byte_count()) << desc;
717 EXPECT_EQ(dl->total_depth(), invocation.depth_accumulated()) << desc;
725 for (
size_t i = 0;
i < group.variants.size();
i++) {
726 sk_sp<DisplayList> dl = Build(group.variants[
i]);
728 group.op_name +
"(variant " + std::to_string(
i + 1) +
" != empty)";
729 if (group.variants[
i].is_empty()) {
731 ASSERT_TRUE(empty->Equals(*dl)) << desc;
734 ASSERT_FALSE(empty->Equals(*dl)) << desc;
742 for (
size_t i = 0;
i < group.variants.size();
i++) {
743 sk_sp<DisplayList> dl = Build(group.variants[
i]);
749 sk_sp<DisplayList> copy = copy_builder.
Build();
751 group.op_name +
"(variant " + std::to_string(
i + 1) +
" == copy)";
753 ASSERT_EQ(copy->op_count(
false), dl->op_count(
false)) << desc;
754 ASSERT_EQ(copy->GetRecordCount(), dl->GetRecordCount());
755 ASSERT_EQ(copy->bytes(
false), dl->bytes(
false)) << desc;
756 ASSERT_EQ(copy->op_count(
true), dl->op_count(
true)) << desc;
757 ASSERT_EQ(copy->bytes(
true), dl->bytes(
true)) << desc;
758 ASSERT_EQ(copy->total_depth(), dl->total_depth()) << desc;
759 ASSERT_EQ(copy->GetBounds(), dl->GetBounds()) << desc;
760 ASSERT_TRUE(copy->Equals(*dl)) << desc;
761 ASSERT_TRUE(dl->Equals(*copy)) << desc;
768 for (
size_t i = 0;
i < group.variants.size();
i++) {
769 sk_sp<DisplayList> dl = Build(group.variants[
i]);
774 for (
DlIndex i = 0;
i < dl->GetRecordCount();
i++) {
776 EXPECT_NE(dl->GetOpCategory(
i),
778 EXPECT_TRUE(dl->Dispatch(r,
i));
780 sk_sp<DisplayList> copy = copy_builder.
Build();
782 group.op_name +
"(variant " + std::to_string(
i + 1) +
" == copy)";
784 ASSERT_EQ(copy->op_count(
false), dl->op_count(
false)) << desc;
785 ASSERT_EQ(copy->GetRecordCount(), dl->GetRecordCount());
786 ASSERT_EQ(copy->bytes(
false), dl->bytes(
false)) << desc;
787 ASSERT_EQ(copy->op_count(
true), dl->op_count(
true)) << desc;
788 ASSERT_EQ(copy->bytes(
true), dl->bytes(
true)) << desc;
789 ASSERT_EQ(copy->total_depth(), dl->total_depth()) << desc;
790 ASSERT_EQ(copy->GetBounds(), dl->GetBounds()) << desc;
791 ASSERT_TRUE(copy->Equals(*dl)) << desc;
792 ASSERT_TRUE(dl->Equals(*copy)) << desc;
799 std::vector<sk_sp<DisplayList>> lists_a;
800 std::vector<sk_sp<DisplayList>> lists_b;
801 for (
size_t i = 0;
i < group.variants.size();
i++) {
802 lists_a.push_back(Build(group.variants[
i]));
803 lists_b.push_back(Build(group.variants[
i]));
806 for (
size_t i = 0;
i < lists_a.size();
i++) {
807 const sk_sp<DisplayList>& listA = lists_a[
i];
808 for (
size_t j = 0; j < lists_b.size(); j++) {
809 const sk_sp<DisplayList>& listB = lists_b[j];
810 auto desc = group.op_name +
"(variant " + std::to_string(
i + 1) +
811 " ==? variant " + std::to_string(j + 1) +
")";
813 (group.variants[
i].is_empty() && group.variants[j].is_empty())) {
815 ASSERT_EQ(listA->op_count(
false), listB->op_count(
false)) << desc;
816 ASSERT_EQ(listA->bytes(
false), listB->bytes(
false)) << desc;
817 ASSERT_EQ(listA->op_count(
true), listB->op_count(
true)) << desc;
818 ASSERT_EQ(listA->bytes(
true), listB->bytes(
true)) << desc;
819 EXPECT_EQ(listA->total_depth(), listB->total_depth()) << desc;
820 ASSERT_EQ(listA->GetBounds(), listB->GetBounds()) << desc;
821 ASSERT_TRUE(listA->Equals(*listB)) << desc;
822 ASSERT_TRUE(listB->Equals(*listA)) << desc;
826 ASSERT_FALSE(listA->Equals(*listB)) << desc;
827 ASSERT_FALSE(listB->Equals(*listA)) << desc;
836 for (
size_t i = 0;
i < group.variants.size();
i++) {
839 group.variants[
i].Invoke(ToReceiver(builder1));
840 group.variants[
i].Invoke(ToReceiver(builder2));
841 sk_sp<DisplayList> dl1 = builder1.
Build();
842 sk_sp<DisplayList> dl2 = builder2.
Build();
844 auto desc = group.op_name +
"(variant " + std::to_string(
i + 1) +
" )";
845 ASSERT_EQ(dl1->op_count(
false), dl2->op_count(
false)) << desc;
846 ASSERT_EQ(dl1->bytes(
false), dl2->bytes(
false)) << desc;
847 ASSERT_EQ(dl1->op_count(
true), dl2->op_count(
true)) << desc;
848 ASSERT_EQ(dl1->bytes(
true), dl2->bytes(
true)) << desc;
849 EXPECT_EQ(dl1->total_depth(), dl2->total_depth()) << desc;
850 ASSERT_EQ(dl1->GetBounds(), dl2->GetBounds()) << desc;
851 ASSERT_EQ(dl1->total_depth(), dl2->total_depth()) << desc;
854 ASSERT_EQ(dl1->rtree().get(),
nullptr) << desc;
855 ASSERT_NE(dl2->rtree().get(),
nullptr) << desc;
867 sk_sp<DisplayList> dl = builder.
Build();
870 ASSERT_EQ(dl->op_count(
false), 0u);
871 ASSERT_EQ(dl->op_count(
true), 0u);
872 EXPECT_EQ(dl->total_depth(), 0u);
879 sk_sp<DisplayList> dl = builder.
Build();
882 ASSERT_EQ(dl->op_count(
false), 0u);
883 ASSERT_EQ(dl->op_count(
true), 0u);
884 EXPECT_EQ(dl->total_depth(), 0u);
888 sk_sp<DisplayList> default_dl = Build(
allGroups.size(), 0);
889 ASSERT_TRUE(default_dl->Equals(*default_dl)) <<
"Default == itself";
890 for (
size_t gi = 0; gi <
allGroups.size(); gi++) {
892 sk_sp<DisplayList> missing_dl = Build(gi, group.
variants.size());
893 auto desc =
"[Group " + group.
op_name +
" omitted]";
894 ASSERT_TRUE(missing_dl->Equals(*missing_dl)) << desc <<
" == itself";
895 ASSERT_FALSE(missing_dl->Equals(*default_dl)) << desc <<
" != Default";
896 ASSERT_FALSE(default_dl->Equals(*missing_dl)) <<
"Default != " << desc;
897 for (
size_t vi = 0; vi < group.
variants.size(); vi++) {
898 auto desc =
"[Group " + group.
op_name +
" variant " +
899 std::to_string(vi + 1) +
"]";
900 sk_sp<DisplayList> variant_dl = Build(gi, vi);
901 ASSERT_TRUE(variant_dl->Equals(*variant_dl)) << desc <<
" == itself";
903 ASSERT_TRUE(variant_dl->Equals(*default_dl)) << desc <<
" == Default";
904 ASSERT_TRUE(default_dl->Equals(*variant_dl)) <<
"Default == " << desc;
906 ASSERT_FALSE(variant_dl->Equals(*default_dl)) << desc <<
" != Default";
907 ASSERT_FALSE(default_dl->Equals(*variant_dl)) <<
"Default != " << desc;
909 if (group.
variants[vi].is_empty()) {
910 ASSERT_TRUE(variant_dl->Equals(*missing_dl)) << desc <<
" != omitted";
911 ASSERT_TRUE(missing_dl->Equals(*variant_dl)) <<
"omitted != " << desc;
913 ASSERT_FALSE(variant_dl->Equals(*missing_dl)) << desc <<
" != omitted";
914 ASSERT_FALSE(missing_dl->Equals(*variant_dl)) <<
"omitted != " << desc;
925 const float color_matrix[] = {
934 const float alpha_matrix[] = {
949 sk_sp<DisplayList> display_list = builder.
Build();
950 ASSERT_EQ(display_list->GetBounds(), rect);
958 builder.
SaveLayer(save_bounds, &save_paint);
961 sk_sp<DisplayList> display_list = builder.
Build();
962 ASSERT_EQ(display_list->GetBounds(), rect);
972 builder.
SaveLayer(save_bounds, &save_paint);
975 sk_sp<DisplayList> display_list = builder.
Build();
976 ASSERT_EQ(display_list->GetBounds(), build_bounds);
985 builder.
SaveLayer(std::nullopt, &save_paint);
988 sk_sp<DisplayList> display_list = builder.
Build();
989 ASSERT_EQ(display_list->GetBounds(), build_bounds);
999 builder.
SaveLayer(save_bounds, &save_paint);
1002 sk_sp<DisplayList> display_list = builder.
Build();
1003 ASSERT_EQ(display_list->GetBounds(), rect);
1013 builder.
SaveLayer(save_bounds, &save_paint);
1016 sk_sp<DisplayList> display_list = builder.
Build();
1017 ASSERT_EQ(display_list->GetBounds(), build_bounds);
1026 builder.
SaveLayer(std::nullopt, &save_paint);
1029 sk_sp<DisplayList> display_list = builder.
Build();
1030 ASSERT_EQ(display_list->GetBounds(), build_bounds);
1038 builder.
SaveLayer(save_bounds, &save_paint);
1041 sk_sp<DisplayList> display_list = builder.
Build();
1042 ASSERT_EQ(display_list->GetBounds(), build_bounds);
1050 builder.
SaveLayer(std::nullopt, &save_paint);
1053 sk_sp<DisplayList> display_list = builder.
Build();
1054 ASSERT_EQ(display_list->GetBounds(), build_bounds);
1061 for (
int y = 10;
y <= 60;
y += 10) {
1062 for (
int x = 10;
x <= 60;
x += 10) {
1071 auto display_list = outer_builder.
Build();
1073 ASSERT_EQ(display_list->op_count(), 1u);
1074 ASSERT_EQ(display_list->op_count(
true), 36u);
1075 EXPECT_EQ(display_list->total_depth(), 37u);
1100 ASSERT_EQ(dl_matrix, matrix);
1114 ASSERT_NE(dl_matrix, matrix);
1120 builder.
Scale(20.0, 20.0);
1126 auto run_tests = [](
const std::string&
name,
1128 bool expect_for_op,
bool expect_with_kSrc) {
1134 build(builder, paint);
1135 auto display_list = builder.
Build();
1136 EXPECT_EQ(display_list->can_apply_group_opacity(), expect_for_op)
1138 <<
" " <<
name << std::endl
1147 build(builder, paint);
1148 auto display_list = builder.
Build();
1149 EXPECT_EQ(display_list->can_apply_group_opacity(), expect_with_kSrc)
1151 <<
" receiver.setBlendMode(kSrc);" << std::endl
1152 <<
" " <<
name << std::endl
1157#define RUN_TESTS(body) \
1159 #body, [](DlCanvas& canvas, const DlPaint& paint) { body }, true, false)
1161#define RUN_TESTS2(body, expect) \
1163 #body, [](DlCanvas& canvas, const DlPaint& paint) { body }, expect, \
1230 static auto display_list = builder.
Build();
1235#if IMPELLER_SUPPORTS_RENDERING
1249 for (
int i = 0;
i < 10;
i++) {
1252 auto display_list = builder.
Build();
1253 EXPECT_FALSE(display_list->can_apply_group_opacity());
1258 for (
int i = 0;
i < 10;
i++) {
1261 auto display_list = builder.
Build();
1262 EXPECT_TRUE(display_list->can_apply_group_opacity());
1272 auto display_list = builder.
Build();
1273 EXPECT_TRUE(display_list->can_apply_group_opacity());
1278 builder.
SaveLayer(std::nullopt,
nullptr);
1279 for (
int i = 0;
i < 10;
i++) {
1283 auto display_list = builder.
Build();
1284 EXPECT_TRUE(display_list->can_apply_group_opacity());
1290 builder.
SaveLayer(std::nullopt, &save_paint);
1291 for (
int i = 0;
i < 10;
i++) {
1295 auto display_list = builder.
Build();
1296 EXPECT_TRUE(display_list->can_apply_group_opacity());
1307 builder.
SaveLayer(std::nullopt,
nullptr);
1310 auto display_list = builder.
Build();
1311 EXPECT_TRUE(display_list->can_apply_group_opacity());
1318 builder.
SaveLayer(std::nullopt, &save_paint);
1321 auto display_list = builder.
Build();
1322 EXPECT_FALSE(display_list->can_apply_group_opacity());
1327 builder.
SaveLayer(std::nullopt,
nullptr);
1329 DlPaint().setBlendMode(DlBlendMode::kSrc));
1331 auto display_list = builder.
Build();
1332 EXPECT_TRUE(display_list->can_apply_group_opacity());
1338 builder.
SaveLayer(std::nullopt, &save_paint);
1340 DlPaint().setBlendMode(DlBlendMode::kSrc));
1342 auto display_list = builder.
Build();
1343 EXPECT_TRUE(display_list->can_apply_group_opacity());
1349 builder.
SaveLayer(std::nullopt, &save_paint);
1360#define SAVE_LAYER_EXPECTOR(name) SaveLayerExpector name(__FILE__, __LINE__)
1376 std::optional<SaveLayerOptionsTester>
tester;
1380::std::ostream&
operator<<(::std::ostream& os,
1381 const SaveLayerExpectations& expect) {
1382 os <<
"SaveLayerExpectation(";
1383 if (expect.options.has_value()) {
1384 os <<
"options: " << expect.options.value();
1386 if (expect.tester.has_value()) {
1387 os <<
"option tester: " << &expect.tester.value();
1389 if (expect.max_blend_mode.has_value()) {
1390 os <<
"max_blend: " << expect.max_blend_mode.value();
1403 : file_(file), line_(line), detail_(
"") {}
1406 EXPECT_EQ(save_layer_count_, expected_.size()) << label();
1407 while (save_layer_count_ < expected_.size()) {
1408 auto expect = expected_[save_layer_count_];
1409 FML_LOG(ERROR) <<
"leftover expectation[" << save_layer_count_
1410 <<
"] = " << expect;
1411 save_layer_count_++;
1421 expected_.push_back(expected);
1438 std::optional<int64_t> backdrop_id)
override {
1444 uint32_t total_content_depth,
1447 std::optional<int64_t> backdrop_id = std::nullopt) {
1448 ASSERT_LT(save_layer_count_, expected_.size()) << label();
1449 auto expect = expected_[save_layer_count_];
1450 if (expect.options.has_value()) {
1451 EXPECT_EQ(options, expect.options.value()) << label();
1453 if (expect.tester.has_value()) {
1454 EXPECT_TRUE(expect.tester.value()(options)) << label();
1456 if (expect.max_blend_mode.has_value()) {
1457 EXPECT_EQ(max_content_blend_mode, expect.max_blend_mode.value())
1460 save_layer_count_++;
1464 return save_layer_count_ == expected_.size();
1469 mutable std::vector<SaveLayerExpectations> expected_;
1470 size_t save_layer_count_ = 0;
1472 const std::string file_;
1474 std::string detail_;
1476 std::string label() {
1477 std::string label =
"at index " + std::to_string(save_layer_count_) +
1479 ":" + std::to_string(line_);
1480 if (detail_.length() > 0) {
1481 label = label +
" (" + detail_ +
")";
1489 expector.addExpectation(
1495 builder.
SaveLayer(std::nullopt, &save_paint);
1499 builder.
Build()->Dispatch(expector);
1500 EXPECT_TRUE(expector.all_expectations_checked());
1505 expector.addExpectation(
1509 builder.
SaveLayer(std::nullopt,
nullptr);
1513 builder.
Build()->Dispatch(expector);
1514 EXPECT_TRUE(expector.all_expectations_checked());
1524 builder.
SaveLayer(std::nullopt, &save_paint);
1529 builder.
Build()->Dispatch(expector);
1530 EXPECT_TRUE(expector.all_expectations_checked());
1545 builder.
SaveLayer(std::nullopt, &save_paint);
1546 builder.
SaveLayer(std::nullopt, &save_paint);
1548 builder.
SaveLayer(std::nullopt, &save_paint);
1554 builder.
Build()->Dispatch(expector);
1555 EXPECT_TRUE(expector.all_expectations_checked());
1569 builder.
SaveLayer(std::nullopt, &save_paint);
1570 builder.
SaveLayer(std::nullopt,
nullptr);
1575 builder.
Build()->Dispatch(expector);
1576 EXPECT_TRUE(expector.all_expectations_checked());
1587 builder.
SaveLayer(std::nullopt, &save_paint);
1591 builder.
Build()->Dispatch(expector);
1592 EXPECT_TRUE(expector.all_expectations_checked());
1603 builder.
SaveLayer(std::nullopt, &save_paint);
1607 builder.
Build()->Dispatch(expector);
1608 EXPECT_TRUE(expector.all_expectations_checked());
1619 builder.
SaveLayer(std::nullopt, &save_paint);
1623 builder.
Build()->Dispatch(expector);
1624 EXPECT_TRUE(expector.all_expectations_checked());
1629 expector.addExpectation(
1635 builder.
SaveLayer(std::nullopt, &save_paint);
1636 DlPaint draw_paint = save_paint;
1641 builder.
Build()->Dispatch(expector);
1642 EXPECT_TRUE(expector.all_expectations_checked());
1652 builder.
SaveLayer(std::nullopt, &save_paint);
1653 DlPaint draw_paint = save_paint;
1658 builder.
Build()->Dispatch(expector);
1659 EXPECT_TRUE(expector.all_expectations_checked());
1669 builder.
SaveLayer(std::nullopt, &save_paint);
1670 DlPaint draw_paint = save_paint;
1675 builder.
Build()->Dispatch(expector);
1676 EXPECT_TRUE(expector.all_expectations_checked());
1683 path_builder1.
MoveTo({25.54f, 37.52f});
1687 path_builder1.
LineTo({13, 30});
1688 path_builder1.
LineTo({12.45f, 29.42f});
1699 {16.7603f, 18.3081f},
1702 {15.4653f, 19.5169f},
1708 {16.3239f, 23.9309f},
1711 {20.6607f, 27.8428f},
1720 {25.5538f, 25.9723f},
1729 {27.906f, 37.4704f},
1731 path_builder1.
Close();
1732 path_builder1.
MoveTo({11.17f, 12.23f});
1734 {10.2522f, 12.4819f},
1739 path_builder1.
LineTo({14.62f, 28.45f});
1740 path_builder1.
LineTo({15.16f, 28.96f});
1748 {27.7359f, 28.4018f},
1751 {25.8676f, 28.2367f},
1754 {25.269f, 28.9252f},
1759 path_builder1.
LineTo({21.41f, 30.72f});
1761 {17.6787f, 28.4133f},
1764 {13.2693f, 23.5295f},
1766 path_builder1.
LineTo({12.2f, 21.44f});
1774 {14.8404f, 16.8359f},
1777 {13.9585f, 14.0843f},
1780 {11.8824f, 12.2971f},
1782 path_builder1.
LineTo({11.17f, 12.23f});
1783 path_builder1.
Close();
1784 path_builder1.
MoveTo({27, 19.34f});
1785 path_builder1.
LineTo({24.74f, 19.34f});
1787 {24.262f, 18.2881f},
1789 path_builder1.
LineTo({23.68f, 16.05f});
1790 path_builder1.
LineTo({23.7f, 16.05f});
1792 {26.9863f, 17.5248f},
1794 path_builder1.
LineTo({27, 19.34f});
1795 path_builder1.
Close();
1796 path_builder1.
MoveTo({32.3f, 19.34f});
1797 path_builder1.
LineTo({30.07f, 19.34f});
1801 path_builder1.
LineTo({23.69f, 10.72f});
1805 path_builder1.
Close();
1806 path_builder1.
SetFillType(DlPathFillType::kNonZero);
1810 path_builder2.
MoveTo({37.5f, 19.33f});
1811 path_builder2.
LineTo({35.27f, 19.33f});
1815 path_builder2.
LineTo({23.69f, 5.52f});
1819 path_builder2.
Close();
1820 path_builder2.
SetFillType(DlPathFillType::kNonZero);
1838 builder.
SaveLayer(std::nullopt,
nullptr,
nullptr);
1842 0, 1.53125, 236.548);
1849 0, 1.53125, 236.548);
1861 sk_sp<DisplayList> display_list = builder.
Build();
1863 EXPECT_FALSE(display_list->GetBounds().IsEmpty());
1871 ASSERT_TRUE(max_bounds.
Contains(min_bounds));
1872 EXPECT_TRUE(max_bounds.
Contains(display_list->GetBounds()));
1873 EXPECT_TRUE(display_list->GetBounds().Contains(min_bounds));
1878 EXPECT_EQ(display_list->op_count(), 19u);
1879 EXPECT_EQ(display_list->bytes(),
sizeof(
DisplayList) + 408u);
1880 EXPECT_EQ(display_list->total_depth(), 3u);
1888 ASSERT_EQ(cur_matrix, matrix);
1891 ASSERT_NE(builder.
GetMatrix(), cur_matrix);
1893 ASSERT_EQ(cur_matrix, matrix);
1898 builder.
Scale(12.3, 14.5);
1901 ASSERT_EQ(cur_matrix, matrix);
1904 ASSERT_NE(builder.
GetMatrix(), cur_matrix);
1906 ASSERT_EQ(cur_matrix, matrix);
1914 ASSERT_EQ(cur_matrix, matrix);
1917 ASSERT_NE(builder.
GetMatrix(), cur_matrix);
1919 ASSERT_EQ(cur_matrix, matrix);
1924 builder.
Skew(12.3f, 14.5f);
1927 ASSERT_EQ(cur_matrix, matrix);
1930 ASSERT_NE(builder.
GetMatrix(), cur_matrix);
1932 ASSERT_EQ(cur_matrix, matrix);
1940 1.0f, 5.0f, 0.0f, 14.5,
1941 0.0f, 0.0f, 1.0f, 0.0f,
1942 0.0f, 0.0f, 0.0f, 1.0f
1945 ASSERT_EQ(cur_matrix, matrix);
1948 ASSERT_NE(builder.
GetMatrix(), cur_matrix);
1950 ASSERT_EQ(cur_matrix, matrix);
1956 1.0f, 5.0f, 3.0f, 14.5f,
1957 0.0f, 0.0f, 7.0f, 16.2f,
1958 0.0f, 0.0f, 0.0f, 1.0f);
1960 1.0f, 5.0f, 3.0f, 14.5f,
1961 0.0f, 0.0f, 7.0f, 16.2f,
1962 0.0f, 0.0f, 0.0f, 1.0f);
1964 ASSERT_EQ(cur_matrix, matrix);
1967 ASSERT_NE(builder.
GetMatrix(), cur_matrix);
1969 ASSERT_EQ(cur_matrix, matrix);
1980 ASSERT_EQ(initial_local_bounds, clip_bounds);
1981 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1989 ASSERT_EQ(initial_local_bounds, clip_bounds);
1990 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1998 builder.
Scale(2.0f, 2.0f);
2019 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2020 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2028 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2029 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2037 builder.
Scale(2, 2);
2077 ASSERT_EQ(initial_local_bounds, clip_bounds);
2078 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2086 ASSERT_EQ(initial_local_bounds, clip_bounds);
2087 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2095 builder.
Scale(2, 2);
2117 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2118 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2126 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2127 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2135 builder.
Scale(2, 2);
2179 ASSERT_EQ(initial_local_bounds, clip_bounds);
2180 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2188 ASSERT_EQ(initial_local_bounds, clip_bounds);
2189 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2197 builder.
Scale(2, 2);
2219 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2220 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2228 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2229 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2237 builder.
Scale(2, 2);
2281 ASSERT_EQ(initial_local_bounds, clip_bounds);
2282 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2301 ASSERT_EQ(initial_local_bounds, clip_bounds);
2302 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2320 ASSERT_EQ(initial_local_bounds, clip_bounds);
2321 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2384#define TEST_RTREE(rtree, query, expected_rects, expected_indices) \
2385 test_rtree(rtree, query, expected_rects, expected_indices, __FILE__, __LINE__)
2389 std::vector<DlRect> expected_rects,
2390 const std::vector<int>& expected_indices,
2391 const std::string& file,
2393 std::vector<int> indices;
2394 auto label =
"from " + file +
":" + std::to_string(line);
2395 rtree->search(query, &indices);
2396 EXPECT_EQ(indices, expected_indices) << label;
2397 EXPECT_EQ(indices.size(), expected_indices.size()) << label;
2398 std::list<DlRect> rects = rtree->searchAndConsolidateRects(query,
false);
2400 auto iterator = rects.cbegin();
2401 for (
int i : expected_indices) {
2402 ASSERT_TRUE(iterator != rects.cend()) << label;
2403 EXPECT_EQ(*iterator++, expected_rects[
i]) << label;
2409 std::vector<DlRect> rects = {
2415 auto display_list = builder.
Build();
2416 auto rtree = display_list->rtree();
2432 std::vector<int>({0, 1}));
2441 auto display_list = builder.
Build();
2442 auto rtree = display_list->rtree();
2443 std::vector<DlRect> rects = {
2462 std::vector<int>({0, 1}));
2472 builder.
SaveLayer(std::nullopt, &filter_paint);
2477 auto display_list = builder.
Build();
2478 auto rtree = display_list->rtree();
2479 std::vector<DlRect> rects = {
2497 auto expected_indices = std::vector<int>{0, 1};
2505 auto nested_display_list = nested_dl_builder.
Build();
2509 auto display_list = builder.
Build();
2511 auto rtree = display_list->rtree();
2512 std::vector<DlRect> rects = {
2519 std::vector<int>({0, 1}));
2573 builder1.
Scale(2, 2);
2583 auto display_list1 = builder1.
Build();
2589 builder2.
Scale(2, 2);
2595 auto display_list2 = builder2.
Build();
2604 builder1.
SaveLayer(std::nullopt,
nullptr);
2607 builder1.
Scale(2, 2);
2612 auto display_list1 = builder1.
Build();
2615 builder2.
SaveLayer(std::nullopt,
nullptr);
2618 builder2.
Scale(2, 2);
2621 auto display_list2 = builder2.
Build();
2630 const float alpha_matrix[] = {
2649 sk_sp<DisplayList> display_list1 = builder.
Build();
2655 sk_sp<DisplayList> display_list2 = builder2.
Build();
2668 sk_sp<DisplayList> display_list1 = builder.
Build();
2676 sk_sp<DisplayList> display_list2 = builder2.
Build();
2701 auto display_list1 = builder1.
Build();
2722 auto display_list2 = builder2.
Build();
2739 auto display_list1 = builder1.
Build();
2748 auto display_list2 = builder2.
Build();
2768 auto display_list1 = builder1.
Build();
2780 auto display_list2 = builder2.
Build();
2797 auto display_list1 = builder1.
Build();
2806 auto display_list2 = builder2.
Build();
2817 builder1.
Skew(10, 10);
2823 auto display_list1 = builder1.
Build();
2828 builder2.
Skew(10, 10);
2832 auto display_list2 = builder2.
Build();
2849 auto display_list1 = builder1.
Build();
2858 auto display_list2 = builder2.
Build();
2869 builder1.
Scale(0.5, 0.5);
2875 auto display_list1 = builder1.
Build();
2880 builder2.
Scale(0.5, 0.5);
2884 auto display_list2 = builder2.
Build();
2907 auto display_list1 = builder1.
Build();
2922 auto display_list2 = builder2.
Build();
2945 auto display_list1 = builder1.
Build();
2958 auto display_list2 = builder2.
Build();
2980 auto display_list1 = builder1.
Build();
2994 auto display_list2 = builder2.
Build();
3012 auto display_list1 = builder1.
Build();
3017 auto display_list2 = builder2.
Build();
3028 builder1.
Scale(1.0, 1.0);
3035 auto display_list1 = builder1.
Build();
3040 auto display_list2 = builder2.
Build();
3058 auto display_list1 = builder1.
Build();
3063 auto display_list2 = builder2.
Build();
3074 builder1.
Skew(0, 0);
3081 auto display_list1 = builder1.
Build();
3086 auto display_list2 = builder2.
Build();
3111 auto display_list1 = builder1.
Build();
3116 auto display_list2 = builder2.
Build();
3134 auto display_list1 = builder1.
Build();
3139 auto display_list2 = builder2.
Build();
3161 auto display_list1 = builder1.
Build();
3166 auto display_list2 = builder2.
Build();
3188 auto display_list1 = builder1.
Build();
3198 auto display_list2 = builder2.
Build();
3205 DlScalar NaN = std::numeric_limits<DlScalar>::quiet_NaN();
3219 auto display_list1 = builder1.
Build();
3224 auto display_list2 = builder2.
Build();
3238 builder.
SaveLayer(std::nullopt, &filter_paint);
3244 auto display_list = builder.
Build();
3245 auto rtree = display_list->rtree();
3246 std::vector<DlRect> rects = {
3265 std::vector<int>({0, 1}));
3279 main_builder.
DrawRect(rect1, paint1);
3280 main_builder.
DrawRect(rect2, paint2);
3281 main_builder.
DrawRect(rect3, paint3);
3282 main_builder.
DrawRect(rect4, paint4);
3285 auto test = [
main](
DlIRect cull_rect,
const sk_sp<DisplayList>& expected,
3286 const std::string& label) {
3291 main->Dispatch(ToReceiver(culling_builder), cull_rect);
3294 <<
"using cull rect " << cull_rect
3295 <<
" where " << label;
3300 main->Dispatch(ToReceiver(culling_builder), cull_rectf);
3303 <<
"using cull rect " << cull_rectf
3304 <<
" where " << label;
3310 auto indices =
main->GetCulledIndices(cull_rectf);
3312 EXPECT_TRUE(
main->Dispatch(receiver,
i));
3316 <<
"using culled indices on cull rect " << cull_rectf
3317 <<
" where " << label;
3325 auto expected = expected_builder.
Build();
3327 test(cull_rect, expected,
"no rects intersect");
3334 expected_builder.
DrawRect(rect1, paint1);
3335 auto expected = expected_builder.
Build();
3337 test(cull_rect, expected,
"rect 1 intersects");
3346 ToReceiver(expected_builder).setColor(paint1.
getColor());
3347 expected_builder.
DrawRect(rect2, paint2);
3348 auto expected = expected_builder.
Build();
3350 test(cull_rect, expected,
"rect 2 intersects");
3359 ToReceiver(expected_builder).setColor(paint1.
getColor());
3360 ToReceiver(expected_builder).setColor(paint2.
getColor());
3361 expected_builder.
DrawRect(rect3, paint3);
3362 auto expected = expected_builder.
Build();
3364 test(cull_rect, expected,
"rect 3 intersects");
3373 ToReceiver(expected_builder).setColor(paint1.
getColor());
3374 ToReceiver(expected_builder).setColor(paint2.
getColor());
3375 ToReceiver(expected_builder).setColor(paint3.
getColor());
3376 expected_builder.
DrawRect(rect4, paint4);
3377 auto expected = expected_builder.
Build();
3379 test(cull_rect, expected,
"rect 4 intersects");
3385 test(cull_rect,
main,
"all rects intersect");
3396 auto display_list = builder.
Build();
3398 ASSERT_FALSE(display_list->can_apply_group_opacity());
3405 check_inverted_bounds(renderer,
"DrawRect");
3412 check_inverted_bounds(renderer,
"DrawRoundRect");
3419 check_inverted_bounds(renderer,
"DrawOval");
3426 check_inverted_bounds(renderer,
"DrawRectangularPath");
3433 check_inverted_bounds(renderer,
"DrawOvalPath");
3441 check_inverted_bounds(renderer,
"DrawRoundRectPath Clockwise");
3449 check_inverted_bounds(renderer,
"DrawRoundRectPath Counter-Clockwise");
3453 auto run_tests = [](
const std::string&
name,
3455 uint32_t expected_op_count = 0u,
3456 uint32_t expected_total_depth = 0u) {
3458 [init](
const std::string&
name,
3460 uint32_t expected_op_count = 0u,
3461 uint32_t expected_total_depth = 0u) {
3464 init(builder, paint);
3465 build(builder, paint);
3466 auto list = builder.
Build();
3467 if (list->op_count() != expected_op_count) {
3470 ASSERT_EQ(list->op_count(), expected_op_count) <<
name;
3471 EXPECT_EQ(list->total_depth(), expected_total_depth) <<
name;
3472 ASSERT_TRUE(list->GetBounds().IsEmpty()) <<
name;
3475 name +
" DrawColor",
3479 expected_op_count, expected_total_depth);
3481 name +
" DrawPaint",
3485 expected_op_count, expected_total_depth);
3491 expected_op_count, expected_total_depth);
3493 name +
" Other Draw Ops",
3532#if IMPELLER_SUPPORTS_RENDERING
3544 expected_op_count, expected_total_depth);
3546 name +
" SaveLayer",
3548 builder.
SaveLayer(std::nullopt, &paint,
nullptr);
3552 expected_op_count, expected_total_depth);
3554 name +
" inside Save",
3560 expected_op_count, expected_total_depth);
3562 run_tests(
"transparent color",
3566 run_tests(
"0 alpha",
3574 run_tests(
"BlendMode::kDst",
3578 run_tests(
"Empty rect clip",
3582 run_tests(
"Empty rrect clip",
3586 run_tests(
"Empty path clip",
3590 run_tests(
"Transparent SaveLayer",
3594 builder.
SaveLayer(std::nullopt, &save_paint);
3596 run_tests(
"0 alpha SaveLayer",
3604 builder.
SaveLayer(std::nullopt, &save_paint);
3606 run_tests(
"Dst blended SaveLayer",
3610 builder.
SaveLayer(std::nullopt, &save_paint);
3613 "Nop inside SaveLayer",
3615 builder.
SaveLayer(std::nullopt,
nullptr);
3619 run_tests(
"DrawImage inside Culled SaveLayer",
3623 builder.
SaveLayer(std::nullopt, &save_paint);
3638 expected_.emplace_back(BoundsExpectation{
3646 bool clipped =
false) {
3652 expected_.emplace_back(BoundsExpectation{
3662 std::optional<int64_t> backdrop_id)
override {
3663 ASSERT_LT(save_layer_count_, expected_.size());
3664 auto expected = expected_[save_layer_count_];
3666 expected.options.bounds_from_caller())
3667 <<
"expected bounds index " << save_layer_count_;
3669 expected.options.content_is_clipped())
3670 <<
"expected bounds index " << save_layer_count_;
3675 EXPECT_EQ(bounds, expected.bounds)
3676 <<
"expected bounds index " << save_layer_count_;
3678 save_layer_count_++;
3682 return save_layer_count_ == expected_.size();
3686 struct BoundsExpectation {
3691 std::vector<BoundsExpectation> expected_;
3692 size_t save_layer_count_ = 0;
3699 builder.
SaveLayer(std::nullopt,
nullptr);
3704 auto display_list = builder.
Build();
3708 display_list->Dispatch(expector);
3719 builder.
SaveLayer(std::nullopt,
nullptr);
3721 builder.
DrawRect(rect, draw_paint);
3724 auto display_list = builder.
Build();
3728 display_list->Dispatch(expector);
3739 builder.
SaveLayer(std::nullopt,
nullptr);
3741 builder.
DrawRect(rect, draw_paint);
3744 auto display_list = builder.
Build();
3748 display_list->Dispatch(expector);
3759 builder.
SaveLayer(std::nullopt,
nullptr);
3761 builder.
DrawRect(rect, draw_paint);
3764 auto display_list = builder.
Build();
3768 display_list->Dispatch(expector);
3777 builder.
SaveLayer(std::nullopt,
nullptr);
3782 auto display_list = builder.
Build();
3786 display_list->Dispatch(expector);
3794 builder.
Scale(10.0f, 10.0f);
3795 builder.
SaveLayer(std::nullopt,
nullptr);
3800 auto display_list = builder.
Build();
3804 display_list->Dispatch(expector);
3813 builder.
SaveLayer(std::nullopt,
nullptr);
3818 auto display_list = builder.
Build();
3822 display_list->Dispatch(expector);
3831 builder.
Scale(10.0f, 10.0f);
3832 builder.
SaveLayer(std::nullopt,
nullptr);
3834 builder.
Scale(20.0f, 20.0f);
3840 auto display_list = builder.
Build();
3844 display_list->Dispatch(expector);
3852 builder.
SaveLayer(std::nullopt,
nullptr);
3858 auto display_list = builder.
Build();
3862 display_list->Dispatch(expector);
3870 builder.
SaveLayer(std::nullopt,
nullptr);
3872 builder.
Scale(10.0f, 10.0f);
3876 auto display_list = builder.
Build();
3881 display_list->Dispatch(expector);
3889 builder.
SaveLayer(std::nullopt,
nullptr);
3895 auto display_list = builder.
Build();
3900 display_list->Dispatch(expector);
3908 builder.
SaveLayer(std::nullopt,
nullptr);
3910 builder.
SaveLayer(std::nullopt,
nullptr);
3917 auto display_list = builder.
Build();
3922 display_list->Dispatch(expector);
3931 ASSERT_TRUE(color_filter->modifies_transparent_black());
3934 ASSERT_NE(clip_rect, rect);
3935 ASSERT_TRUE(clip_rect.
Contains(rect));
3939 builder.
SaveLayer(std::nullopt, &save_paint);
3944 auto display_list = builder.
Build();
3948 display_list->Dispatch(expector);
3957 ASSERT_TRUE(color_filter->modifies_transparent_black());
3960 ASSERT_NE(clip_rect, rect);
3961 ASSERT_TRUE(clip_rect.
Contains(rect));
3965 builder.
SaveLayer(std::nullopt,
nullptr);
3967 builder.
SaveLayer(std::nullopt, &save_paint);
3974 auto display_list = builder.
Build();
3976 EXPECT_EQ(display_list->GetBounds(), clip_rect);
3981 display_list->Dispatch(expector);
3990 ASSERT_TRUE(color_filter->modifies_transparent_black());
3994 ASSERT_NE(clip_rect, rect);
3995 ASSERT_TRUE(clip_rect.
Contains(rect));
3999 builder.
SaveLayer(std::nullopt,
nullptr);
4001 builder.
DrawRect(rect, draw_paint);
4004 auto display_list = builder.
Build();
4008 display_list->Dispatch(expector);
4017 ASSERT_TRUE(color_filter->modifies_transparent_black());
4020 ASSERT_NE(clip_rect, rect);
4021 ASSERT_TRUE(clip_rect.
Contains(rect));
4025 builder.
SaveLayer(std::nullopt,
nullptr);
4027 builder.
DrawRect(rect, draw_paint);
4030 auto display_list = builder.
Build();
4036 display_list->Dispatch(expector);
4050 auto display_list = builder.
Build();
4054 display_list->Dispatch(expector);
4069 auto display_list = builder.
Build();
4073 display_list->Dispatch(expector);
4088 ASSERT_FALSE(layer_bounds.
IsEmpty());
4089 ASSERT_FALSE(draw_rect.
IsEmpty());
4092 builder.
SaveLayer(layer_bounds,
nullptr);
4095 auto display_list = builder.
Build();
4099 display_list->Dispatch(expector);
4110 : depth_expectations_(
std::move(expectations)) {}
4115 FAIL() <<
"save(no depth parameter) method should not be called";
4118 void save(uint32_t total_content_depth)
override {
4119 ASSERT_LT(index_, depth_expectations_.size());
4120 EXPECT_EQ(depth_expectations_[index_], total_content_depth)
4121 <<
"at index " << index_;
4128 std::optional<int64_t> backdrop_id)
override {
4131 FAIL() <<
"saveLayer(no depth parameter) method should not be called";
4136 uint32_t total_content_depth,
4139 std::optional<int64_t> backdrop_id)
override {
4140 ASSERT_LT(index_, depth_expectations_.size());
4141 EXPECT_EQ(depth_expectations_[index_], total_content_depth)
4142 <<
"at index " << index_;
4147 return index_ == depth_expectations_.size();
4152 std::vector<uint32_t> depth_expectations_;
4159 auto child = child_builder.
Build();
4171 builder.
SaveLayer(std::nullopt,
nullptr);
4185 auto display_list = builder.
Build();
4187 EXPECT_EQ(display_list->total_depth(), 11u);
4190 display_list->Dispatch(expector);
4200 const float matrix[] = {
4201 0.5f, 0.0f, 0.0f, 0.0f, 0.5f,
4202 0.5f, 0.0f, 0.0f, 0.0f, 0.5f,
4203 0.5f, 0.0f, 0.0f, 0.0f, 0.5f,
4204 0.5f, 0.0f, 0.0f, 0.0f, 0.5f
4209 builder.
SaveLayer(std::nullopt, &save_paint);
4218 auto dl = builder.
Build();
4219 std::vector<int> indices;
4220 dl->rtree()->search(
DlRect::MakeLTRB(0.0f, 0.0f, 500.0f, 500.0f), &indices);
4221 ASSERT_EQ(indices.size(), 3u);
4222 EXPECT_EQ(dl->rtree()->id(indices[0]), save_layer_id);
4223 EXPECT_EQ(dl->rtree()->id(indices[1]), draw_rect_id);
4224 EXPECT_EQ(dl->rtree()->id(indices[2]), restore_id);
4236 builder.
SaveLayer(std::nullopt, &save_paint);
4242 auto dl = builder.
Build();
4243 EXPECT_EQ(dl->GetBounds(),
DlRect::MakeLTRB(120.0f, 120.0f, 125.0f, 125.0f));
4255 builder.
SaveLayer(std::nullopt, &save_paint);
4261 auto dl = builder.
Build();
4262 EXPECT_EQ(dl->GetBounds(),
DlRect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f));
4270 DlPaint().setBlendMode(DlBlendMode::kClear));
4271 EXPECT_FALSE(builder.
Build()->can_apply_group_opacity());
4281 DlPaint().setBlendMode(DlBlendMode::kClear));
4286 EXPECT_FALSE(builder.
Build()->can_apply_group_opacity());
4292 EXPECT_EQ(builder.
Build()->max_root_blend_mode(), DlBlendMode::kClear);
4301 (
mode == DlBlendMode::kDst) ? DlBlendMode::kClear :
mode;
4302 EXPECT_EQ(builder.
Build()->max_root_blend_mode(), expect)
4303 <<
"testing " <<
mode;
4306 for (
int i = 0; i < static_cast<int>(DlBlendMode::kLastMode);
i++) {
4316 builder.
Scale(2.0f, 2.0f);
4318 DlPaint().setBlendMode(DlBlendMode::kModulate));
4322 EXPECT_EQ(builder.
Build()->max_root_blend_mode(), DlBlendMode::kModulate);
4331 DlPaint().setBlendMode(DlBlendMode::kModulate));
4335 EXPECT_EQ(builder.
Build()->max_root_blend_mode(), DlBlendMode::kModulate);
4340 builder.
SaveLayer(std::nullopt,
nullptr);
4343 DlPaint().setBlendMode(DlBlendMode::kModulate));
4346 auto dl = builder.
Build();
4347 EXPECT_EQ(dl->max_root_blend_mode(), DlBlendMode::kSrcOver);
4349 expector.addExpectation(DlBlendMode::kModulate);
4350 dl->Dispatch(expector);
4351 EXPECT_TRUE(expector.all_expectations_checked());
4358 builder.
SaveLayer(std::nullopt, &save_paint);
4361 DlPaint().setBlendMode(DlBlendMode::kModulate));
4364 auto dl = builder.
Build();
4365 EXPECT_EQ(dl->max_root_blend_mode(), DlBlendMode::kScreen);
4367 expector.addExpectation(DlBlendMode::kModulate);
4368 dl->Dispatch(expector);
4369 EXPECT_TRUE(expector.all_expectations_checked());
4377 DlPaint().setBlendMode(DlBlendMode::kModulate));
4381 ASSERT_GT(DlBlendMode::kScreen, DlBlendMode::kModulate);
4383 DlPaint().setBlendMode(DlBlendMode::kScreen));
4388 ASSERT_LT(DlBlendMode::kSrc, DlBlendMode::kModulate);
4390 DlPaint().setBlendMode(DlBlendMode::kSrc));
4395 auto expect = std::max(DlBlendMode::kModulate, DlBlendMode::kScreen);
4396 expect = std::max(expect, DlBlendMode::kSrc);
4397 ASSERT_EQ(expect, DlBlendMode::kScreen);
4399 EXPECT_EQ(builder.
Build()->max_root_blend_mode(), DlBlendMode::kScreen);
4404 builder.
SaveLayer(std::nullopt,
nullptr);
4408 DlPaint().setBlendMode(DlBlendMode::kModulate));
4409 builder.
SaveLayer(std::nullopt,
nullptr);
4413 DlPaint().setBlendMode(DlBlendMode::kScreen));
4418 ASSERT_LT(DlBlendMode::kSrc, DlBlendMode::kModulate);
4420 DlPaint().setBlendMode(DlBlendMode::kSrc));
4426 auto expect = std::max(DlBlendMode::kModulate, DlBlendMode::kSrc);
4427 ASSERT_EQ(expect, DlBlendMode::kModulate);
4429 auto dl = builder.
Build();
4430 EXPECT_EQ(dl->max_root_blend_mode(), DlBlendMode::kSrcOver);
4433 .addExpectation(DlBlendMode::kModulate)
4434 .addExpectation(DlBlendMode::kScreen);
4435 dl->Dispatch(expector);
4436 EXPECT_TRUE(expector.all_expectations_checked());
4441 EXPECT_FALSE(builder.
Build()->root_has_backdrop_filter());
4447 EXPECT_FALSE(builder.
Build()->root_has_backdrop_filter());
4458 auto dl = builder.
Build();
4460 EXPECT_TRUE(dl->root_has_backdrop_filter());
4464 expector.addExpectation(
4466 dl->Dispatch(expector);
4467 EXPECT_TRUE(expector.all_expectations_checked());
4472 builder.
SaveLayer(std::nullopt,
nullptr);
4484 auto dl = builder.
Build();
4486 EXPECT_FALSE(dl->root_has_backdrop_filter());
4490 .with_contains_backdrop_filter()
4491 .with_content_is_unbounded())
4494 dl->Dispatch(expector);
4495 EXPECT_TRUE(expector.all_expectations_checked());
4501 DlPaint().setBlendMode(DlBlendMode::kMultiply));
4502 auto child_dl = child_builder.
Build();
4503 EXPECT_EQ(child_dl->max_root_blend_mode(), DlBlendMode::kMultiply);
4504 EXPECT_FALSE(child_dl->root_has_backdrop_filter());
4508 auto parent_dl = parent_builder.
Build();
4509 EXPECT_EQ(parent_dl->max_root_blend_mode(), DlBlendMode::kMultiply);
4510 EXPECT_FALSE(parent_dl->root_has_backdrop_filter());
4516 child_builder.
SaveLayer(std::nullopt,
nullptr, &backdrop);
4518 DlPaint().setBlendMode(DlBlendMode::kMultiply));
4520 auto child_dl = child_builder.
Build();
4521 EXPECT_EQ(child_dl->max_root_blend_mode(), DlBlendMode::kSrcOver);
4522 EXPECT_TRUE(child_dl->root_has_backdrop_filter());
4526 auto parent_dl = parent_builder.
Build();
4527 EXPECT_EQ(parent_dl->max_root_blend_mode(), DlBlendMode::kSrcOver);
4528 EXPECT_TRUE(parent_dl->root_has_backdrop_filter());
4531#define CLIP_EXPECTOR(name) ClipExpector name(__FILE__, __LINE__)
4534 std::variant<DlRect, DlRoundRect, DlRoundSuperellipse, DlPath>
shape;
4540 switch (
shape.index()) {
4542 return is_oval ?
"Oval" :
"Rect";
4544 return "DlRoundRect";
4546 return "DlRoundSuperellipse";
4555::std::ostream&
operator<<(::std::ostream& os,
const ClipExpectation& expect) {
4556 os <<
"Expectation(";
4557 switch (expect.shape.index()) {
4559 os << std::get<DlRect>(expect.shape);
4560 if (expect.is_oval) {
4565 os << std::get<DlRoundRect>(expect.shape);
4568 os << std::get<DlPath>(expect.shape).GetSkPath();
4573 os <<
", " << expect.clip_op;
4574 os <<
", " << expect.is_aa;
4586 : file_(file), line_(line) {}
4589 EXPECT_EQ(index_, clip_expectations_.size()) << label();
4590 while (index_ < clip_expectations_.size()) {
4591 auto expect = clip_expectations_[index_];
4592 FML_LOG(ERROR) <<
"leftover clip shape[" << index_ <<
"] = " << expect;
4599 bool is_aa =
false) {
4600 clip_expectations_.push_back({
4611 bool is_aa =
false) {
4612 clip_expectations_.push_back({
4623 bool is_aa =
false) {
4624 clip_expectations_.push_back({
4635 bool is_aa =
false) {
4636 clip_expectations_.push_back({
4646 check(rect, clip_op, is_aa);
4649 check(bounds, clip_op, is_aa,
true);
4653 bool is_aa)
override {
4654 check(rrect, clip_op, is_aa);
4658 bool is_aa)
override {
4659 check(rse, clip_op, is_aa);
4662 check(
path, clip_op, is_aa);
4667 std::vector<ClipExpectation> clip_expectations_;
4669 template <
typename T>
4670 void check(
const T& shape,
4673 bool is_oval =
false) {
4674 ASSERT_LT(index_, clip_expectations_.size())
4675 << label() << std::endl
4676 <<
"extra clip shape = " << shape << (is_oval ?
" (oval)" :
"");
4677 auto expected = clip_expectations_[index_];
4678 if (!std::holds_alternative<T>(expected.shape)) {
4679 EXPECT_TRUE(std::holds_alternative<T>(expected.shape))
4680 << label() <<
", expected type: " << expected.shape_name();
4682 EXPECT_EQ(std::get<T>(expected.shape), shape) << label();
4684 EXPECT_EQ(expected.is_oval, is_oval) << label();
4685 EXPECT_EQ(expected.clip_op, clip_op) << label();
4686 EXPECT_EQ(expected.is_aa, is_aa) << label();
4690 const std::string file_;
4693 std::string label() {
4694 return "at index " + std::to_string(index_) +
4696 ":" + std::to_string(line_);
4715 cull_builder.
Scale(DPR, DPR);
4717 auto cull_dl = cull_builder.
Build();
4721 cull_dl->Dispatch(expector);
4730 auto cull_dl = cull_builder.
Build();
4734 cull_dl->Dispatch(expector);
4739 auto smaller_clip = clip.Expand(-1.0f, -1.0f);
4744 auto cull_dl = cull_builder.
Build();
4749 cull_dl->Dispatch(expector);
4754 auto larger_clip = clip.Expand(1.0f, 1.0f);
4758 cull_builder.
Save();
4761 auto cull_dl = cull_builder.
Build();
4765 cull_dl->Dispatch(expector);
4770 auto larger_clip = clip.Expand(1.0f, 1.0f);
4773 cull_builder.
Save();
4778 auto cull_dl = cull_builder.
Build();
4783 cull_dl->Dispatch(expector);
4788 auto smaller_clip = clip.Expand(-1.0f, -1.0f);
4789 auto smallest_clip = clip.Expand(-2.0f, -2.0f);
4793 cull_builder.
Save();
4797 auto cull_dl = cull_builder.
Build();
4802 cull_dl->Dispatch(expector);
4807 auto smaller_clip = clip.Expand(-1.0f, -1.0f);
4808 auto smallest_clip = clip.Expand(-2.0f, -2.0f);
4812 cull_builder.
Save();
4817 auto cull_dl = cull_builder.
Build();
4823 cull_dl->Dispatch(expector);
4832 auto encompassing_oval = clip.Expand(2.072f, 2.072f);
4837 auto cull_dl = cull_builder.
Build();
4841 cull_dl->Dispatch(expector);
4850 auto non_encompassing_oval = clip.Expand(2.071f, 2.071f);
4855 auto cull_dl = cull_builder.
Build();
4861 cull_dl->Dispatch(expector);
4867 ASSERT_FALSE(rrect.IsOval());
4872 auto cull_dl = cull_builder.
Build();
4876 cull_dl->Dispatch(expector);
4882 ASSERT_FALSE(rrect.IsOval());
4887 auto cull_dl = cull_builder.
Build();
4892 cull_dl->Dispatch(expector);
4898 path_builder.
MoveTo({0.0f, 0.0f});
4899 path_builder.
LineTo({1000.0f, 0.0f});
4900 path_builder.
LineTo({0.0f, 1000.0f});
4901 path_builder.
Close();
4909 ASSERT_TRUE(
path.Contains(clip.GetLeftTop()));
4910 ASSERT_TRUE(
path.Contains(clip.GetRightTop()));
4911 ASSERT_TRUE(
path.Contains(clip.GetRightBottom()));
4912 ASSERT_TRUE(
path.Contains(clip.GetLeftBottom()));
4917 auto cull_dl = cull_builder.
Build();
4922 cull_dl->Dispatch(expector);
4932 auto cull_dl = cull_builder.
Build();
4936 cull_dl->Dispatch(expector);
4941 auto smaller_clip = clip.Expand(-1.0f, -1.0f);
4947 auto cull_dl = cull_builder.
Build();
4953 cull_dl->Dispatch(expector);
4962 auto encompassing_oval = clip.Expand(2.072f, 2.072f);
4968 auto cull_dl = cull_builder.
Build();
4972 cull_dl->Dispatch(expector);
4981 auto non_encompassing_oval = clip.Expand(2.071f, 2.071f);
4987 auto cull_dl = cull_builder.
Build();
4994 cull_dl->Dispatch(expector);
5000 ASSERT_FALSE(
path.IsOval());
5005 auto cull_dl = cull_builder.
Build();
5009 cull_dl->Dispatch(expector);
5015 ASSERT_FALSE(rrect.IsOval());
5021 auto cull_dl = cull_builder.
Build();
5027 cull_dl->Dispatch(expector);
5031 constexpr size_t vertex_count = 2000000;
5032 auto points = std::vector<DlPoint>();
5033 points.reserve(vertex_count);
5034 auto colors = std::vector<DlColor>();
5035 colors.reserve(vertex_count);
5036 for (
size_t i = 0;
i < vertex_count;
i++) {
5040 ASSERT_EQ(
points.size(), vertex_count);
5041 ASSERT_EQ(colors.size(), vertex_count);
5044 ASSERT_GT(vertices->size(), 1u << 24);
5047 for (
int i = 0;
i < 1000;
i++) {
5049 for (
int j = 0; j < 16; j++) {
5050 builder.
SaveLayer(std::nullopt,
nullptr, backdrop.get());
5054 auto dl = builder.
Build();
5063 auto dl = builder.
Build();
5067 auto expect_dl = expected.
Build();
5077 auto dl = builder.
Build();
5081 auto expect_dl = expected.
Build();
5091 auto dl = builder.
Build();
5095 auto expect_dl = expected.
Build();
5107 auto dl = builder.
Build();
5111 auto expect_dl = expected.
Build();
5124 auto dl = builder.
Build();
5128 auto expect_dl = expected.
Build();
5141 auto dl = builder.
Build();
5145 auto expect_dl = expected.
Build();
5158 auto dl = builder.
Build();
5162 auto expect_dl = expected.
Build();
5178 auto dl = builder.
Build();
5183 auto expect_dl = expected.
Build();
5197 auto dl = builder.
Build();
5202 auto expect_dl = expected.
Build();
5211 ASSERT_TRUE(clip_path.
IsRect(
nullptr));
5217 auto dl = builder.
Build();
5222 auto expect_dl = expected.
Build();
5231 ASSERT_TRUE(clip_path.
IsOval(
nullptr));
5237 auto dl = builder.
Build();
5242 auto expect_dl = expected.
Build();
5258 auto dl = builder.
Build();
5263 auto expect_dl = expected.
Build();
5278 auto dl = builder.
Build();
5283 auto expect_dl = expected.
Build();
5298 auto dl = builder.
Build();
5303 auto expect_dl = expected.
Build();
5312 using Renderer =
const std::function<void(
DlCanvas&)>;
5313 auto test_bounded = [](
const std::string& label,
const Renderer& renderer) {
5317 auto display_list = builder.
Build();
5319 EXPECT_EQ(display_list->GetBounds(), draw_rect) << label;
5320 EXPECT_FALSE(display_list->root_is_unbounded()) << label;
5325 builder.
SaveLayer(std::nullopt,
nullptr);
5328 auto display_list = builder.
Build();
5330 EXPECT_EQ(display_list->GetBounds(), draw_rect) << label;
5331 EXPECT_FALSE(display_list->root_is_unbounded()) << label;
5339 display_list->Dispatch(expector);
5343 test_bounded(
"DrawLine", [](
DlCanvas& builder) {
5354 test_bounded(
"DrawDashedLine", [](
DlCanvas& builder) {
5373 test_bounded(
"DrawRect", [](
DlCanvas& builder) {
5377 test_bounded(
"DrawOval", [](
DlCanvas& builder) {
5381 test_bounded(
"DrawCircle", [](
DlCanvas& builder) {
5386 test_bounded(
"DrawRoundRect", [](
DlCanvas& builder) {
5391 test_bounded(
"DrawDiffRoundRect", [](
DlCanvas& builder) {
5398 test_bounded(
"DrawArc", [](
DlCanvas& builder) {
5402 test_bounded(
"DrawPathEvenOdd", [](
DlCanvas& builder) {
5408 test_bounded(
"DrawPathWinding", [](
DlCanvas& builder) {
5415 std::stringstream ss;
5416 ss <<
"DrawPoints(" <<
mode <<
")";
5418 DlPoint points[4] = {
5419 DlPoint(draw_rect.GetLeft() + 1.0f, draw_rect.GetTop() + 1.0f),
5420 DlPoint(draw_rect.GetRight() - 1.0f, draw_rect.GetTop() + 1.0f),
5421 DlPoint(draw_rect.GetRight() - 1.0f, draw_rect.GetBottom() - 1.0f),
5422 DlPoint(draw_rect.GetLeft() + 1.0f, draw_rect.GetBottom() - 1.0f),
5440 test_bounded(
"DrawVerticesTriangles", [](
DlCanvas& builder) {
5442 DlPoint(draw_rect.GetLeft(), draw_rect.GetTop()),
5443 DlPoint(draw_rect.GetRight(), draw_rect.GetTop()),
5444 DlPoint(draw_rect.GetRight(), draw_rect.GetBottom()),
5445 DlPoint(draw_rect.GetRight(), draw_rect.GetBottom()),
5446 DlPoint(draw_rect.GetLeft(), draw_rect.GetBottom()),
5447 DlPoint(draw_rect.GetLeft(), draw_rect.GetTop()),
5451 vertices.store_vertices(
points);
5452 builder.
DrawVertices(vertices.build(), DlBlendMode::kSrcOver, DlPaint());
5455 test_bounded(
"DrawVerticesTriangleStrip", [](DlCanvas& builder) {
5457 DlPoint(draw_rect.GetLeft(), draw_rect.GetTop()),
5458 DlPoint(draw_rect.GetRight(), draw_rect.GetTop()),
5459 DlPoint(draw_rect.GetRight(), draw_rect.GetBottom()),
5460 DlPoint(draw_rect.GetLeft(), draw_rect.GetBottom()),
5461 DlPoint(draw_rect.GetLeft(), draw_rect.GetTop()),
5462 DlPoint(draw_rect.GetRight(), draw_rect.GetTop()),
5466 vertices.store_vertices(
points);
5467 builder.DrawVertices(vertices.build(), DlBlendMode::kSrcOver,
DlPaint());
5470 test_bounded(
"DrawVerticesTriangleFan", [](DlCanvas& builder) {
5472 draw_rect.GetCenter(),
5473 DlPoint(draw_rect.GetLeft(), draw_rect.GetTop()),
5474 DlPoint(draw_rect.GetRight(), draw_rect.GetTop()),
5475 DlPoint(draw_rect.GetRight(), draw_rect.GetBottom()),
5476 DlPoint(draw_rect.GetLeft(), draw_rect.GetBottom()),
5480 vertices.store_vertices(
points);
5481 builder.DrawVertices(vertices.build(), DlBlendMode::kSrcOver,
DlPaint());
5484 test_bounded(
"DrawImage", [](DlCanvas& builder) {
5486 builder.DrawImage(
image,
DlPoint(draw_rect.GetLeft(), draw_rect.GetTop()),
5490 test_bounded(
"DrawImageRect", [](DlCanvas& builder) {
5495 test_bounded(
"DrawImageNine", [](DlCanvas& builder) {
5501 test_bounded(
"DrawTextBlob", [](DlCanvas& builder) {
5505 ASSERT_LT(blob->bounds().width(), draw_rect.GetWidth());
5506 ASSERT_LT(blob->bounds().height(), draw_rect.GetHeight());
5510 builder.DrawText(
text, draw_rect.GetLeft() - blob->bounds().left(),
5511 draw_rect.GetTop() - blob->bounds().top(),
DlPaint());
5512 builder.DrawText(
text, draw_rect.GetRight() - blob->bounds().right(),
5513 draw_rect.GetBottom() - blob->bounds().bottom(),
5517#if IMPELLER_SUPPORTS_RENDERING
5518 test_bounded(
"DrawTextFrame", [](DlCanvas& builder) {
5522 ASSERT_LT(blob->bounds().width(), draw_rect.GetWidth());
5523 ASSERT_LT(blob->bounds().height(), draw_rect.GetHeight());
5528 builder.DrawText(
text, draw_rect.GetLeft() - blob->bounds().left(),
5529 draw_rect.GetTop() - blob->bounds().top(),
DlPaint());
5530 builder.DrawText(
text, draw_rect.GetRight() - blob->bounds().right(),
5531 draw_rect.GetBottom() - blob->bounds().bottom(),
5536 test_bounded(
"DrawBoundedDisplayList", [](DlCanvas& builder) {
5537 DisplayListBuilder nested_builder(root_cull);
5538 nested_builder.DrawRect(draw_rect,
DlPaint());
5539 auto nested_display_list = nested_builder.Build();
5541 EXPECT_EQ(nested_display_list->GetBounds(), draw_rect);
5542 ASSERT_FALSE(nested_display_list->root_is_unbounded());
5544 builder.DrawDisplayList(nested_display_list);
5547 test_bounded(
"DrawShadow", [](DlCanvas& builder) {
5551 auto shadow_bounds =
5555 ASSERT_LT(shadow_bounds.GetWidth(), draw_rect.GetWidth());
5556 ASSERT_LT(shadow_bounds.GetHeight(), draw_rect.GetHeight());
5560 path.
WithOffset(draw_rect.GetLeftTop() - shadow_bounds.GetLeftTop());
5563 shadow_bounds.GetRightBottom());
5567 for (
int i = 0; i <= static_cast<int>(DlBlendMode::kLastMode);
i++) {
5569 if (mode == DlBlendMode::kDst) {
5573 std::stringstream ss;
5574 ss <<
"DrawRectWith" <<
mode;
5575 test_bounded(ss.str(), [mode](DlCanvas& builder) {
5577 builder.DrawRect(draw_rect, DlPaint().setBlendMode(mode).setAlpha(0x7f));
5587 using Renderer =
const std::function<void(
DlCanvas&)>;
5588 auto test_unbounded = [](
const std::string& label,
5589 const Renderer& renderer,
5590 int extra_save_layers = 0) {
5594 auto display_list = builder.
Build();
5596 EXPECT_EQ(display_list->GetBounds(), root_cull) << label;
5597 EXPECT_TRUE(display_list->root_is_unbounded()) << label;
5604 auto display_list = builder.
Build();
5606 EXPECT_EQ(display_list->GetBounds(), clip_rect) << label;
5607 EXPECT_FALSE(display_list->root_is_unbounded()) << label;
5612 builder.
SaveLayer(std::nullopt,
nullptr);
5615 auto display_list = builder.
Build();
5617 EXPECT_EQ(display_list->GetBounds(), root_cull) << label;
5618 EXPECT_FALSE(display_list->root_is_unbounded()) << label;
5626 for (
int i = 0;
i < extra_save_layers;
i++) {
5627 expector.addOpenExpectation();
5629 display_list->Dispatch(expector);
5634 builder.
SaveLayer(std::nullopt,
nullptr);
5638 auto display_list = builder.
Build();
5640 EXPECT_EQ(display_list->GetBounds(), clip_rect) << label;
5641 EXPECT_FALSE(display_list->root_is_unbounded()) << label;
5649 for (
int i = 0;
i < extra_save_layers;
i++) {
5650 expector.addOpenExpectation();
5652 display_list->Dispatch(expector);
5656 test_unbounded(
"DrawPaint", [](
DlCanvas& builder) {
5660 test_unbounded(
"DrawColor", [](
DlCanvas& builder) {
5664 test_unbounded(
"Clear", [](
DlCanvas& builder) {
5668 test_unbounded(
"DrawUnboundedDisplayList", [](
DlCanvas& builder) {
5671 auto nested_display_list = nested_builder.
Build();
5673 EXPECT_EQ(nested_display_list->GetBounds(), root_cull);
5674 ASSERT_TRUE(nested_display_list->root_is_unbounded());
5679 test_unbounded(
"DrawRectWithUnboundedImageFilter", [](
DlCanvas& builder) {
5682 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
5683 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
5684 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
5685 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
5690 ASSERT_TRUE(unbounded_cf->modifies_transparent_black());
5694 ASSERT_EQ(unbounded_if->map_local_bounds(draw_rect, output_bounds),
5701 "SaveLayerWithBackdropFilter",
5704 builder.
SaveLayer(std::nullopt,
nullptr, filter.get());
5720 ASSERT_TRUE(frame_bounds.
Contains(clip_rect));
5721 ASSERT_TRUE(frame_bounds.
Contains(draw_rect1));
5722 ASSERT_TRUE(frame_bounds.
Contains(draw_rect2));
5723 ASSERT_TRUE(frame_bounds.
Contains(cull_rect));
5725 ASSERT_TRUE(frame_clip.
Contains(clip_rect));
5726 ASSERT_TRUE(frame_clip.
Contains(draw_rect1));
5727 ASSERT_TRUE(frame_clip.
Contains(draw_rect2));
5728 ASSERT_TRUE(frame_clip.
Contains(cull_rect));
5746 builder.
SaveLayer(std::nullopt,
nullptr, bdf_filter.get());
5755 auto display_list = builder.
Build();
5759 display_list->Dispatch(ToReceiver(unculled), frame_bounds);
5760 auto unculled_dl = unculled.
Build();
5767 display_list->Dispatch(ToReceiver(culled), cull_rect);
5768 auto culled_dl = culled.
Build();
5781 auto expected_dl = expected.
Build();
5792 std::vector<DlPoint>
points(2050);
5806 EXPECT_TRUE(!!builder.
Build());
5812 std::vector<DlPoint>
points(40000);
5816 EXPECT_TRUE(!!builder.
Build());
5821 kTestRuntimeEffect1, {}, std::make_shared<std::vector<uint8_t>>());
5823 kTestRuntimeEffect1, {}, std::make_shared<std::vector<uint8_t>>());
5831 EXPECT_TRUE(builder.
Build()->can_apply_group_opacity());
5842 EXPECT_FALSE(builder.
Build()->can_apply_group_opacity());
5853 EXPECT_FALSE(builder.
Build()->can_apply_group_opacity());
5862 builder.
SaveLayer(std::nullopt,
nullptr);
5867 auto display_list = builder.
Build();
5868 EXPECT_TRUE(display_list->can_apply_group_opacity());
5874 display_list->Dispatch(expector);
5883 builder.
SaveLayer(std::nullopt,
nullptr);
5888 auto display_list = builder.
Build();
5889 EXPECT_TRUE(display_list->can_apply_group_opacity());
5895 display_list->Dispatch(expector);
5905 builder.
SaveLayer(std::nullopt,
nullptr);
5907 builder.
SaveLayer(std::nullopt,
nullptr);
5913 builder.
SaveLayer(std::nullopt,
nullptr);
5922 auto display_list = builder.
Build();
5923 EXPECT_TRUE(display_list->can_apply_group_opacity());
5938 display_list->Dispatch(expector);
int main(int argc, char **argv)
void DrawOval(const DlRect &bounds, const DlPaint &paint) override
static constexpr DlRect kMaxCullRect
void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast) override
void DrawVertices(const std::shared_ptr< DlVertices > &vertices, DlBlendMode mode, const DlPaint &paint) override
void DrawImageNine(const sk_sp< DlImage > &image, const DlIRect ¢er, const DlRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr) override
void DrawAtlas(const sk_sp< DlImage > &atlas, const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const DlRect *cullRect, const DlPaint *paint=nullptr) override
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void DrawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter, const DlPaint &paint) override
void DrawShadow(const DlPath &path, const DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
Draws the shadow of the given |path| rendered in the provided |color| (which is only consulted for it...
void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
void DrawColor(DlColor color, DlBlendMode mode) override
DlMatrix GetMatrix() const override
void DrawCircle(const DlPoint ¢er, DlScalar radius, const DlPaint &paint) override
void TransformReset() override
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void DrawLine(const DlPoint &p0, const DlPoint &p1, const DlPaint &paint) override
void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void Rotate(DlScalar degrees) override
void DrawText(const std::shared_ptr< DlText > &text, DlScalar x, DlScalar y, const DlPaint &paint) override
void Scale(DlScalar sx, DlScalar sy) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1) override
void Skew(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void Transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void DrawPaint(const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
DlRect GetDestinationClipCoverage() const override
void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawPoints(DlPointMode mode, uint32_t count, const DlPoint pts[], const DlPaint &paint) override
void ClipOval(const DlRect &bounds, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
DlRect GetLocalClipCoverage() const override
int GetSaveCount() const override
void TransformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void DrawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner, const DlPaint &paint) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
Developer-facing API for rendering anything within the engine.
virtual void DrawPaint(const DlPaint &paint)=0
virtual void DrawCircle(const DlPoint ¢er, DlScalar radius, const DlPaint &paint)=0
virtual void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint)=0
virtual void DrawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1)=0
virtual void DrawImageNine(const sk_sp< DlImage > &image, const DlIRect ¢er, const DlRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr)=0
virtual void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)=0
virtual void DrawLine(const DlPoint &p0, const DlPoint &p1, const DlPaint &paint)=0
virtual void DrawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner, const DlPaint &paint)=0
virtual void DrawRect(const DlRect &rect, const DlPaint &paint)=0
virtual void DrawVertices(const std::shared_ptr< DlVertices > &vertices, DlBlendMode mode, const DlPaint &paint)=0
virtual void DrawText(const std::shared_ptr< DlText > &text, DlScalar x, DlScalar y, const DlPaint &paint)=0
virtual void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr)=0
virtual void DrawOval(const DlRect &bounds, const DlPaint &paint)=0
virtual void DrawColor(DlColor color, DlBlendMode mode=DlBlendMode::kSrcOver)=0
virtual void DrawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length, const DlPaint &paint)=0
virtual void DrawPath(const DlPath &path, const DlPaint &paint)=0
virtual void DrawPoints(DlPointMode mode, uint32_t count, const DlPoint pts[], const DlPaint &paint)=0
void Clear(DlColor color)
virtual void DrawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter, const DlPaint &paint)=0
virtual void DrawAtlas(const sk_sp< DlImage > &atlas, const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const DlRect *cullRect, const DlPaint *paint=nullptr)=0
virtual void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast)=0
static DlRect ComputeShadowBounds(const DlPath &path, float elevation, DlScalar dpr, const DlMatrix &ctm)
Compute the local coverage for a |DrawShadow| operation using the given parameters (excluding the col...
virtual void DrawShadow(const DlPath &path, const DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr)=0
Draws the shadow of the given |path| rendered in the provided |color| (which is only consulted for it...
static std::shared_ptr< const DlColorFilter > MakeBlend(DlColor color, DlBlendMode mode)
static std::shared_ptr< const DlColorFilter > MakeMatrix(const float matrix[20])
static std::shared_ptr< DlColorSource > MakeRuntimeEffect(sk_sp< DlRuntimeEffect > runtime_effect, std::vector< std::shared_ptr< DlColorSource > > samplers, std::shared_ptr< std::vector< uint8_t > > uniform_data)
static std::shared_ptr< DlImageFilter > MakeBlur(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static std::shared_ptr< DlImageFilter > MakeRuntimeEffect(sk_sp< DlRuntimeEffect > runtime_effect, std::vector< std::shared_ptr< DlColorSource > > samplers, std::shared_ptr< std::vector< uint8_t > > uniform_data)
static std::shared_ptr< DlImageFilter > MakeColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
static std::shared_ptr< DlImageFilter > MakeMatrix(const DlMatrix &matrix, DlImageSampling sampling)
Internal API for rendering recorded display lists to backends.
virtual void setStrokeMiter(float limit)=0
virtual void setStrokeWidth(float width)=0
virtual void setMaskFilter(const DlMaskFilter *filter)=0
virtual void setColorFilter(const DlColorFilter *filter)=0
virtual void setAntiAlias(bool aa)=0
virtual void setStrokeJoin(DlStrokeJoin join)=0
virtual void setImageFilter(const DlImageFilter *filter)=0
virtual void setColorSource(const DlColorSource *source)=0
virtual void setDrawStyle(DlDrawStyle style)=0
virtual void setBlendMode(DlBlendMode mode)=0
virtual void setColor(DlColor color)=0
virtual void setInvertColors(bool invert)=0
virtual void setStrokeCap(DlStrokeCap cap)=0
DlStrokeCap getStrokeCap() const
DlPaint & setColor(DlColor color)
DlPaint & setAntiAlias(bool isAntiAlias)
DlBlendMode getBlendMode() const
float getStrokeMiter() const
DlStrokeJoin getStrokeJoin() const
DlPaint & setStrokeCap(DlStrokeCap cap)
DlPaint & setStrokeWidth(float width)
DlPaint & setAlpha(uint8_t alpha)
DlPaint & setBlendMode(DlBlendMode mode)
const std::shared_ptr< const DlMaskFilter > & getMaskFilter() const
DlScalar getOpacity() const
DlDrawStyle getDrawStyle() const
DlPaint & setImageFilter(std::nullptr_t filter)
const std::shared_ptr< const DlColorSource > & getColorSource() const
const std::shared_ptr< DlImageFilter > & getImageFilter() const
float getStrokeWidth() const
const std::shared_ptr< const DlColorFilter > & getColorFilter() const
DlPaint & setMaskFilter(std::nullptr_t filter)
DlPaint & setDrawStyle(DlDrawStyle style)
DlPaint & setStrokeJoin(DlStrokeJoin join)
DlPaint & setColorFilter(std::nullptr_t filter)
DlPaint & setColorSource(std::nullptr_t source)
bool isInvertColors() const
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
DlPathBuilder & SetFillType(DlPathFillType fill_type)
Set the fill type that should be used to determine the interior of this path to the indicated |fill_t...
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & Close()
The path is closed back to the location of the most recent MoveTo call. Contours that are filled are ...
DlPathBuilder & CubicCurveTo(DlPoint cp1, DlPoint cp2, DlPoint p2)
Draw a cubic bezier curve from the current point to the indicated point p2, using the indicated point...
bool IsRect(DlRect *rect=nullptr, bool *is_closed=nullptr) const
static DlPath MakeRectLTRB(DlScalar left, DlScalar top, DlScalar right, DlScalar bottom)
DlPath WithOffset(const DlPoint offset) const
static DlPath MakeRoundRect(const DlRoundRect &rrect)
static DlPath MakeCircle(const DlPoint center, DlScalar radius)
static DlPath MakeRect(const DlRect &rect)
static DlPath MakeRoundRectXY(const DlRect &rect, DlScalar x_radius, DlScalar y_radius, bool counter_clock_wise=false)
bool IsRoundRect(DlRoundRect *rrect=nullptr) const
static DlPath MakeOvalLTRB(DlScalar left, DlScalar top, DlScalar right, DlScalar bottom)
DlPath WithFillType(DlPathFillType type) const
static DlPath MakeOval(const DlRect &bounds)
bool IsOval(DlRect *bounds=nullptr) const
static std::shared_ptr< DlTextImpeller > MakeFromBlob(const sk_sp< SkTextBlob > &blob)
static std::shared_ptr< DlTextImpeller > Make(const std::shared_ptr< impeller::TextFrame > &frame)
static std::shared_ptr< DlTextSkia > Make(const sk_sp< SkTextBlob > &blob)
static constexpr Flags kNone
static std::shared_ptr< DlVertices > Make(DlVertexMode mode, int vertex_count, const DlPoint vertices[], const DlPoint texture_coordinates[], const DlColor colors[], int index_count=0, const uint16_t indices[]=nullptr, const DlRect *bounds=nullptr)
Constructs a DlVector with compact inline storage for all of its required and optional lists of data.
bool content_is_clipped() const
static const SaveLayerOptions kNoAttributes
SaveLayerOptions with_bounds_from_caller() const
bool bounds_from_caller() const
bool content_is_unbounded() const
static const SaveLayerOptions kWithAttributes
SaveLayerOptions with_content_is_clipped() const
bool can_distribute_opacity() const
void clipOval(const DlRect &bounds, DlClipOp clip_op, bool is_aa) override
void clipRect(const DlRect &rect, DlClipOp clip_op, bool is_aa) override
ClipExpector & addExpectation(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)
void clipPath(const DlPath &path, DlClipOp clip_op, bool is_aa) override
ClipExpector & addExpectation(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)
ClipExpector(const std::string &file, int line)
void clipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op, bool is_aa) override
void clipRoundSuperellipse(const DlRoundSuperellipse &rse, DlClipOp clip_op, bool is_aa) override
ClipExpector & addExpectation(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)
ClipExpector & addOvalExpectation(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)
void saveLayer(const DlRect &bounds, const SaveLayerOptions &options, uint32_t total_content_depth, DlBlendMode max_content_mode, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void saveLayer(const DlRect &bounds, SaveLayerOptions options, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void save(uint32_t total_content_depth) override
bool all_depths_checked() const
DepthExpector(std::vector< uint32_t > expectations)
uint32_t GetOpsReceived()
static DlOpReceiver & ToReceiver(DisplayListBuilder &builder)
static void check_inverted_bounds(DlRenderer &renderer, const std::string &desc)
const std::function< void(DlCanvas &)> DlSetup
static void check_defaults(DisplayListBuilder &builder, const DlRect &cull_rect=DisplayListBuilder::kMaxCullRect)
static sk_sp< DisplayList > Build(size_t g_index, size_t v_index)
DisplayListTestBase()=default
static void verify_inverted_bounds(DlSetup &setup, DlRenderer &renderer, DlPaint paint, DlRect render_rect, DlRect expected_bounds, const std::string &desc)
static sk_sp< DisplayList > Build(DisplayListInvocation &invocation)
const std::function< void(DlCanvas &, DlPaint &, DlRect &)> DlRenderer
SaveLayerBoundsExpector & addComputedExpectation(const DlRect &bounds)
bool all_bounds_checked() const
void saveLayer(const DlRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
SaveLayerBoundsExpector & addSuppliedExpectation(const DlRect &bounds, bool clipped=false)
SaveLayerBoundsExpector()
bool all_expectations_checked() const
void saveLayer(const DlRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
SaveLayerExpector(const std::string &file, int line)
SaveLayerExpector & addOpenExpectation()
SaveLayerExpector & addExpectation(const SaveLayerExpectations &expected)
SaveLayerExpector & addDetail(const std::string &detail)
virtual void saveLayer(const DlRect &bounds, const SaveLayerOptions &options, uint32_t total_content_depth, DlBlendMode max_content_blend_mode, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)
SaveLayerExpector & addExpectation(const SaveLayerOptionsTester &tester)
#define CLIP_EXPECTOR(name)
#define SAVE_LAYER_EXPECTOR(name)
#define RUN_TESTS2(body, expect)
#define TEST_RTREE(rtree, query, expected_rects, expected_indices)
FlutterVulkanImage * image
#define FML_LOG(severity)
#define FML_UNREACHABLE()
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
TEST_F(DisplayListTest, Defaults)
static const DlBlurMaskFilter kTestMaskFilter1(DlBlurStyle::kNormal, 3.0)
bool DisplayListsNE_Verbose(const DisplayList *a, const DisplayList *b)
constexpr DlPoint kTestPoints[]
static const auto kTestMatrixColorFilter1
static std::vector< testing::DisplayListInvocationGroup > allGroups
static const std::shared_ptr< DlColorSource > kTestSource1
constexpr DlRect kTestBounds
static const DlPath kTestPath1
sk_sp< DlImage > MakeTestImage(int w, int h, int checker_size)
static void test_rtree(const sk_sp< const DlRTree > &rtree, const DlRect &query, std::vector< DlRect > expected_rects, const std::vector< int > &expected_indices, const std::string &file, int line)
static DlImageSampling kLinearSampling
::std::ostream & operator<<(::std::ostream &os, const SaveLayerExpectations &expect)
bool DisplayListsEQ_Verbose(const DisplayList *a, const DisplayList *b)
static DlImageSampling kNearestSampling
sk_sp< SkTextBlob > GetTestTextBlob(int index)
std::function< bool(const SaveLayerOptions &options)> SaveLayerOptionsTester
static const DlBlurImageFilter kTestBlurImageFilter1(5.0, 5.0, DlTileMode::kClamp)
std::vector< DisplayListInvocationGroup > CreateAllGroups()
static const std::shared_ptr< DlVertices > kTestVertices1
static const DlRoundRect kTestRRect
static sk_sp< DisplayList > TestDisplayList1
impeller::Scalar DlScalar
DlPaint DisplayListBuilderTestingAttributes(DisplayListBuilder &builder)
constexpr bool DlScalarNearlyEqual(DlScalar x, DlScalar y, DlScalar tolerance=kEhCloseEnough)
impeller::RoundRect DlRoundRect
impeller::Matrix DlMatrix
impeller::Degrees DlDegrees
DlOpReceiver & DisplayListBuilderTestingAccessor(DisplayListBuilder &builder)
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
@ kTriangles
The vertices are taken 3 at a time to form a triangle.
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
impeller::IRect32 DlIRect
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
@ kNormal
fuzzy inside and outside
impeller::BlendMode DlBlendMode
TEST_F(EngineAnimatorTest, AnimatorAcceptsMultipleRenders)
int DisplayListBuilderTestingLastOpIndex(DisplayListBuilder &builder)
static constexpr DlColor kMagenta()
static constexpr DlColor kWhite()
static constexpr DlColor kBlue()
static constexpr DlColor kBlack()
static constexpr DlColor kTransparent()
static constexpr DlColor kRed()
static constexpr DlColor kGreen()
std::variant< DlRect, DlRoundRect, DlRoundSuperellipse, DlPath > shape
std::vector< DisplayListInvocation > variants
uint32_t adjust_render_op_depth_cost(uint32_t previous_cost)
uint32_t depth_accumulated(uint32_t depth_scale=1u)
void Invoke(DlOpReceiver &builder)
SaveLayerExpectations(const SaveLayerOptionsTester &t)
std::optional< SaveLayerOptions > options
SaveLayerExpectations(DlBlendMode mode)
SaveLayerExpectations(const SaveLayerOptions &o)
std::optional< SaveLayerOptionsTester > tester
std::optional< DlBlendMode > max_blend_mode
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
constexpr bool IsIdentity() const
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
static RoundRect MakeOval(const Rect &rect)
static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
static RoundRect MakeRect(const Rect &rect)
constexpr auto GetBottom() const
static constexpr TRect MakeWH(Type width, Type height)
constexpr auto GetTop() const
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
constexpr bool IntersectsWithRect(const TRect &o) const
constexpr auto GetLeft() const
RoundOut(const TRect< U > &r)
constexpr auto GetRight() const
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TRect TransformAndClipBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle, clipped against the near clippin...
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TRect IntersectionOrEmpty(const TRect &o) const
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
std::vector< Point > points