7#include <unordered_set>
11#include "flutter/display_list/display_list.h"
12#include "flutter/display_list/dl_blend_mode.h"
13#include "flutter/display_list/dl_builder.h"
14#include "flutter/display_list/dl_paint.h"
15#include "flutter/display_list/geometry/dl_rtree.h"
16#include "flutter/display_list/skia/dl_sk_dispatcher.h"
17#include "flutter/display_list/testing/dl_test_snippets.h"
18#include "flutter/display_list/utils/dl_receiver_utils.h"
19#include "flutter/fml/logging.h"
20#include "flutter/fml/math.h"
21#include "flutter/testing/assertions_skia.h"
22#include "flutter/testing/display_list_testing.h"
23#include "flutter/testing/testing.h"
38 return builder.CurrentAttributes();
47static std::vector<testing::DisplayListInvocationGroup>
allGroups =
53template <
typename BaseT>
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);
79 if (j >=
group.variants.size()) {
86 invocation.
Invoke(receiver);
87 render_op_depth_cost =
96 if (v_index >=
allGroups[g_index].variants.size()) {
102 EXPECT_EQ(dl->op_count(
false), op_count) <<
name;
104 EXPECT_EQ(dl->total_depth(), depth) <<
name;
127 EXPECT_EQ(builder_paint, defaults);
131 EXPECT_EQ(
builder.GetTransformFullPerspective(),
SkM44());
133 EXPECT_EQ(
builder.GetLocalClipBounds(), cull_rect);
134 EXPECT_EQ(
builder.GetDestinationClipBounds(), cull_rect);
136 EXPECT_EQ(
builder.GetSaveCount(), 1);
148 const std::string&
desc) {
153 EXPECT_EQ(dl->op_count(), 1u) <<
desc;
154 EXPECT_EQ(dl->bounds(), expected_bounds) <<
desc;
158 const std::string&
desc) {
166 auto empty_setup = [](
DlCanvas&) {};
168 ASSERT_TRUE(
rect.fLeft <
rect.fRight);
169 ASSERT_TRUE(
rect.fTop <
rect.fBottom);
170 ASSERT_FALSE(
rect.isEmpty());
172 ASSERT_TRUE(invertedLR.
isEmpty());
174 ASSERT_TRUE(invertedTB.
isEmpty());
175 ASSERT_TRUE(invertedLTRB.
fLeft > invertedLTRB.
fRight);
176 ASSERT_TRUE(invertedLTRB.
fTop > invertedLTRB.
fBottom);
177 ASSERT_TRUE(invertedLTRB.
isEmpty());
182 ref_bounds,
desc +
" LR swapped");
184 ref_bounds,
desc +
" TB swapped");
186 ref_bounds,
desc +
" LR&TB swapped");
197 SkRect stroke_bounds =
rect.makeOutset(1.0f, 1.0f);
199 stroke_bounds,
desc +
" LR swapped, sw 2");
201 stroke_bounds,
desc +
" TB swapped, sw 2");
203 stroke_bounds,
desc +
" LR&TB swapped, sw 2");
208 SkRect maskblur_bounds =
rect.makeOutset(6.0f, 6.0f);
210 maskblur_bounds,
desc +
" LR swapped, mask 2");
212 maskblur_bounds,
desc +
" TB swapped, mask 2");
214 maskblur_bounds,
desc +
" LR&TB swapped, mask 2");
219 SkRect erode_bounds =
rect.makeInset(2.0f, 2.0f);
221 erode_bounds,
desc +
" LR swapped, erode 2");
223 erode_bounds,
desc +
" TB swapped, erode 2");
225 erode_bounds,
desc +
" LR&TB swapped, erode 2");
241 EXPECT_EQ(dl->op_count(), 0u);
243 EXPECT_EQ(dl->total_depth(), 0u);
251 ASSERT_TRUE(dl1->Equals(dl2));
252 ASSERT_TRUE(dl2->Equals(dl3));
261 ASSERT_TRUE(dl->Equals(dl2));
269 builder.Translate(10.0f, 10.0f);
271 check_defaults(
builder, cull_rect);
276 check_defaults(
builder, cull_rect);
281 check_defaults(
builder, cull_rect);
286 check_defaults(
builder, cull_rect);
291 check_defaults(
builder, cull_rect);
294 builder.Transform2DAffine(1.0f, 0.0f, 12.0f,
297 check_defaults(
builder, cull_rect);
302 check_defaults(
builder, cull_rect);
305 builder.TransformFullPerspective(1.0f, 0.0f, 0.0f, 12.0f,
306 0.0f, 1.0f, 0.0f, 35.0f,
307 0.0f, 0.0f, 1.0f, 5.0f,
308 0.0f, 0.0f, 0.0f, 1.0f);
310 check_defaults(
builder, cull_rect);
317 builder.Translate(10.0f, 10.0f);
319 check_defaults(
builder, cull_rect);
323 check_defaults(
builder, cull_rect);
327 check_defaults(
builder, cull_rect);
331 check_defaults(
builder, cull_rect);
335 check_defaults(
builder, cull_rect);
337 builder.Transform2DAffine(1.0f, 0.0f, 12.0f,
340 check_defaults(
builder, cull_rect);
344 check_defaults(
builder, cull_rect);
346 builder.TransformFullPerspective(1.0f, 0.0f, 0.0f, 12.0f,
347 0.0f, 1.0f, 0.0f, 35.0f,
348 0.0f, 0.0f, 1.0f, 5.0f,
349 0.0f, 0.0f, 0.0f, 1.0f);
351 check_defaults(
builder, cull_rect);
359 builder.ClipRect({0.0f, 0.0f, 10.0f, 10.0f});
361 check_defaults(
builder, cull_rect);
366 check_defaults(
builder, cull_rect);
369 builder.ClipPath(
SkPath().addOval({0.0f, 0.0f, 10.0f, 10.0f}));
371 check_defaults(
builder, cull_rect);
378 builder.ClipRect({0.0f, 0.0f, 10.0f, 10.0f});
380 check_defaults(
builder, cull_rect);
384 check_defaults(
builder, cull_rect);
386 builder.ClipPath(
SkPath().addOval({0.0f, 0.0f, 10.0f, 10.0f}));
388 check_defaults(
builder, cull_rect);
398 check_defaults(
builder, cull_rect);
402 check_defaults(
builder, cull_rect);
406 check_defaults(
builder, cull_rect);
410 check_defaults(
builder, cull_rect);
414 check_defaults(
builder, cull_rect);
418 check_defaults(
builder, cull_rect);
422 check_defaults(
builder, cull_rect);
426 check_defaults(
builder, cull_rect);
430 check_defaults(
builder, cull_rect);
434 check_defaults(
builder, cull_rect);
438 check_defaults(
builder, cull_rect);
442 check_defaults(
builder, cull_rect);
446 check_defaults(
builder, cull_rect);
454 ASSERT_EQ(
builder.GetDestinationClipBounds(),
456 ASSERT_EQ(
builder.GetLocalClipBounds().makeOutset(1, 1),
465 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
472 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
481 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
491 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
500 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
507 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
518 ASSERT_TRUE(cull_rect.
contains(clip_rect));
525 builder.SaveLayer(&cull_rect, &layer_paint);
532 auto display_list =
builder.Build();
534 EXPECT_EQ(display_list->op_count(), 6u);
535 EXPECT_EQ(display_list->total_depth(), 2u);
538 ASSERT_TRUE(result_rect.
intersect(clip_rect));
540 EXPECT_EQ(display_list->bounds(), result_rect);
551 ASSERT_TRUE(cull_rect.
contains(clip_rect));
558 builder.SaveLayer(&cull_rect, &layer_paint);
565 auto display_list =
builder.Build();
567 EXPECT_EQ(display_list->op_count(), 6u);
568 EXPECT_EQ(display_list->total_depth(), 2u);
571 ASSERT_TRUE(result_rect.
intersect(clip_rect));
573 EXPECT_EQ(display_list->bounds(), result_rect);
588 ASSERT_TRUE(filter->map_local_bounds(
draw_rect, mapped_rect));
589 ASSERT_TRUE(mapped_rect.
intersects(cull_rect));
592 builder.SaveLayer(&cull_rect, &layer_paint);
597 auto display_list =
builder.Build();
599 EXPECT_EQ(display_list->op_count(), 2u);
600 EXPECT_EQ(display_list->total_depth(), 1u);
602 EXPECT_TRUE(display_list->bounds().isEmpty()) << display_list->bounds();
618 ASSERT_TRUE(filter->map_local_bounds(
draw_rect, mapped_rect));
619 ASSERT_TRUE(mapped_rect.
intersects(cull_rect));
622 builder.SaveLayer(&cull_rect, &layer_paint);
627 auto display_list =
builder.Build();
629 EXPECT_EQ(display_list->op_count(), 2u);
630 EXPECT_EQ(display_list->total_depth(), 1u);
632 EXPECT_TRUE(display_list->bounds().isEmpty()) << display_list->bounds();
637 for (
size_t i = 0;
i <
group.variants.size();
i++) {
638 auto& invocation =
group.variants[
i];
641 EXPECT_EQ(dl->op_count(
false), invocation.op_count()) <<
desc;
642 EXPECT_EQ(dl->bytes(
false), invocation.byte_count()) <<
desc;
643 EXPECT_EQ(dl->total_depth(), invocation.depth_accumulated()) <<
desc;
651 for (
size_t i = 0;
i <
group.variants.size();
i++) {
655 if (
group.variants[
i].is_empty()) {
660 ASSERT_FALSE(
empty->Equals(*dl)) <<
desc;
668 for (
size_t i = 0;
i <
group.variants.size();
i++) {
679 ASSERT_EQ(
copy->op_count(
false), dl->op_count(
false)) <<
desc;
680 ASSERT_EQ(
copy->bytes(
false), dl->bytes(
false)) <<
desc;
681 ASSERT_EQ(
copy->op_count(
true), dl->op_count(
true)) <<
desc;
682 ASSERT_EQ(
copy->bytes(
true), dl->bytes(
true)) <<
desc;
683 EXPECT_EQ(
copy->total_depth(), dl->total_depth()) <<
desc;
684 ASSERT_EQ(
copy->bounds(), dl->bounds()) <<
desc;
685 ASSERT_TRUE(
copy->Equals(*dl)) <<
desc;
686 ASSERT_TRUE(dl->Equals(*
copy)) <<
desc;
693 std::vector<sk_sp<DisplayList>> lists_a;
694 std::vector<sk_sp<DisplayList>> lists_b;
695 for (
size_t i = 0;
i <
group.variants.size();
i++) {
700 for (
size_t i = 0;
i < lists_a.size();
i++) {
702 for (
size_t j = 0; j < lists_b.size(); j++) {
707 (
group.variants[
i].is_empty() &&
group.variants[j].is_empty())) {
709 ASSERT_EQ(listA->op_count(
false), listB->op_count(
false)) <<
desc;
710 ASSERT_EQ(listA->bytes(
false), listB->bytes(
false)) <<
desc;
711 ASSERT_EQ(listA->op_count(
true), listB->op_count(
true)) <<
desc;
712 ASSERT_EQ(listA->bytes(
true), listB->bytes(
true)) <<
desc;
713 EXPECT_EQ(listA->total_depth(), listB->total_depth()) <<
desc;
714 ASSERT_EQ(listA->bounds(), listB->bounds()) <<
desc;
715 ASSERT_TRUE(listA->Equals(*listB)) <<
desc;
716 ASSERT_TRUE(listB->Equals(*listA)) <<
desc;
720 ASSERT_FALSE(listA->Equals(*listB)) <<
desc;
721 ASSERT_FALSE(listB->Equals(*listA)) <<
desc;
730 for (
size_t i = 0;
i <
group.variants.size();
i++) {
733 group.variants[
i].Invoke(ToReceiver(builder1));
734 group.variants[
i].Invoke(ToReceiver(builder2));
739 ASSERT_EQ(dl1->op_count(
false), dl2->op_count(
false)) <<
desc;
740 ASSERT_EQ(dl1->bytes(
false), dl2->bytes(
false)) <<
desc;
741 ASSERT_EQ(dl1->op_count(
true), dl2->op_count(
true)) <<
desc;
742 ASSERT_EQ(dl1->bytes(
true), dl2->bytes(
true)) <<
desc;
743 EXPECT_EQ(dl1->total_depth(), dl2->total_depth()) <<
desc;
744 ASSERT_EQ(dl1->bounds(), dl2->bounds()) <<
desc;
745 ASSERT_EQ(dl1->total_depth(), dl2->total_depth()) <<
desc;
748 ASSERT_EQ(dl1->rtree().
get(),
nullptr) <<
desc;
749 ASSERT_NE(dl2->rtree().
get(),
nullptr) <<
desc;
765 ASSERT_EQ(dl->op_count(
false), 0u);
766 ASSERT_EQ(dl->op_count(
true), 0u);
767 EXPECT_EQ(dl->total_depth(), 0u);
777 ASSERT_EQ(dl->op_count(
false), 0u);
778 ASSERT_EQ(dl->op_count(
true), 0u);
779 EXPECT_EQ(dl->total_depth(), 0u);
784 ASSERT_TRUE(default_dl->Equals(*default_dl)) <<
"Default == itself";
785 for (
size_t gi = 0; gi <
allGroups.size(); gi++) {
788 auto desc =
"[Group " +
group.op_name +
" omitted]";
789 ASSERT_TRUE(missing_dl->Equals(*missing_dl)) <<
desc <<
" == itself";
790 ASSERT_FALSE(missing_dl->Equals(*default_dl)) <<
desc <<
" != Default";
791 ASSERT_FALSE(default_dl->Equals(*missing_dl)) <<
"Default != " <<
desc;
792 for (
size_t vi = 0; vi <
group.variants.size(); vi++) {
793 auto desc =
"[Group " +
group.op_name +
" variant " +
796 ASSERT_TRUE(variant_dl->Equals(*variant_dl)) <<
desc <<
" == itself";
798 ASSERT_TRUE(variant_dl->Equals(*default_dl)) <<
desc <<
" == Default";
799 ASSERT_TRUE(default_dl->Equals(*variant_dl)) <<
"Default == " <<
desc;
801 ASSERT_FALSE(variant_dl->Equals(*default_dl)) <<
desc <<
" != Default";
802 ASSERT_FALSE(default_dl->Equals(*variant_dl)) <<
"Default != " <<
desc;
804 if (
group.variants[vi].is_empty()) {
805 ASSERT_TRUE(variant_dl->Equals(*missing_dl)) <<
desc <<
" != omitted";
806 ASSERT_TRUE(missing_dl->Equals(*variant_dl)) <<
"omitted != " <<
desc;
808 ASSERT_FALSE(variant_dl->Equals(*missing_dl)) <<
desc <<
" != omitted";
809 ASSERT_FALSE(missing_dl->Equals(*variant_dl)) <<
"omitted != " <<
desc;
820 const float color_matrix[] = {
829 const float alpha_matrix[] = {
848 ASSERT_EQ(display_list->bounds(),
rect);
861 ASSERT_EQ(display_list->bounds(),
rect);
894 ASSERT_EQ(display_list->bounds(), build_bounds);
908 ASSERT_EQ(display_list->bounds(), build_bounds);
923 ASSERT_EQ(display_list->bounds(),
rect);
938 ASSERT_EQ(display_list->bounds(), build_bounds);
952 ASSERT_EQ(display_list->bounds(), build_bounds);
965 ASSERT_EQ(display_list->bounds(), build_bounds);
978 ASSERT_EQ(display_list->bounds(), build_bounds);
987 for (
int y = 10;
y <= 60;
y += 10) {
988 for (
int x = 10;
x <= 60;
x += 10) {
1004 for (
int y = 10;
y <= 60;
y += 10) {
1005 for (
int x = 10;
x <= 60;
x += 10) {
1013 DlOpReceiver& outer_receiver = ToReceiver(outer_builder);
1015 auto display_list = outer_builder.
Build();
1017 ASSERT_EQ(display_list->op_count(), 1u);
1018 ASSERT_EQ(display_list->op_count(
true), 36u);
1019 EXPECT_EQ(display_list->total_depth(), 37u);
1022 static_cast<int>(display_list->op_count()));
1024 static_cast<int>(display_list->op_count(
true)));
1057 display_list->Dispatch(dispatcher);
1080 display_list->Dispatch(dispatcher);
1089 receiver.
scale(20.0, 20.0);
1091 auto display_list =
builder.Build();
1092 ASSERT_NE(display_list,
nullptr);
1099 display_list->Dispatch(dispatcher);
1106 bool expect_with_kSrc) {
1113 auto display_list =
builder.Build();
1114 EXPECT_EQ(display_list->can_apply_group_opacity(), expect_for_op)
1116 <<
" " <<
name << std::endl
1126 auto display_list =
builder.Build();
1127 EXPECT_EQ(display_list->can_apply_group_opacity(), expect_with_kSrc)
1129 <<
" receiver.setBlendMode(kSrc);" << std::endl
1130 <<
" " <<
name << std::endl
1135#define RUN_TESTS(body) \
1136 run_tests(#body, [](DlOpReceiver& receiver) { body }, true, false)
1137#define RUN_TESTS2(body, expect) \
1138 run_tests(#body, [](DlOpReceiver& receiver) { body }, expect, expect)
1153 SkPath().addOval({0, 0, 10, 10}).addOval({5, 5, 15, 15})););
1177 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
1192 static auto display_list =
builder.Build();
1206 for (
int i = 0;
i < 10;
i++) {
1209 auto display_list =
builder.Build();
1210 EXPECT_FALSE(display_list->can_apply_group_opacity());
1215 for (
int i = 0;
i < 10;
i++) {
1218 auto display_list =
builder.Build();
1219 EXPECT_TRUE(display_list->can_apply_group_opacity());
1229 auto display_list =
builder.Build();
1230 EXPECT_TRUE(display_list->can_apply_group_opacity());
1237 for (
int i = 0;
i < 10;
i++) {
1241 auto display_list =
builder.Build();
1242 EXPECT_TRUE(display_list->can_apply_group_opacity());
1249 for (
int i = 0;
i < 10;
i++) {
1253 auto display_list =
builder.Build();
1254 EXPECT_TRUE(display_list->can_apply_group_opacity());
1264 auto display_list =
builder.Build();
1265 EXPECT_TRUE(display_list->can_apply_group_opacity());
1275 auto display_list =
builder.Build();
1276 EXPECT_FALSE(display_list->can_apply_group_opacity());
1286 auto display_list =
builder.Build();
1287 EXPECT_TRUE(display_list->can_apply_group_opacity());
1297 auto display_list =
builder.Build();
1298 EXPECT_TRUE(display_list->can_apply_group_opacity());
1305 receiver.
drawRect({50, 50, 100, 100});
1330 expected_.push_back(expected);
1334 : expected_(
std::move(expected)) {}
1344 uint32_t total_content_depth,
1348 ASSERT_LT(save_layer_count_, expected_.size());
1349 auto expect = expected_[save_layer_count_++];
1350 if (expect.options.has_value()) {
1351 EXPECT_EQ(
options, expect.options.value()) << label;
1353 if (expect.max_blend_mode.has_value()) {
1354 EXPECT_EQ(max_content_blend_mode, expect.max_blend_mode.value()) << label;
1359 return save_layer_count_ == expected_.size();
1363 std::vector<Expectations> expected_;
1364 size_t save_layer_count_ = 0;
1376 receiver.
drawRect({10, 10, 20, 20});
1379 builder.Build()->Dispatch(expector);
1391 receiver.
drawRect({10, 10, 20, 20});
1394 builder.Build()->Dispatch(expector);
1406 receiver.
drawRect({10, 10, 20, 20});
1407 receiver.
drawRect({15, 15, 25, 25});
1410 builder.Build()->Dispatch(expector);
1427 receiver.
drawRect({10, 10, 20, 20});
1429 receiver.
drawRect({15, 15, 25, 25});
1434 builder.Build()->Dispatch(expector);
1450 receiver.
drawRect({10, 10, 20, 20});
1454 builder.Build()->Dispatch(expector);
1468 receiver.
drawRect({10, 10, 20, 20});
1471 builder.Build()->Dispatch(expector);
1485 receiver.
drawRect({10, 10, 20, 20});
1488 builder.Build()->Dispatch(expector);
1502 receiver.
drawRect({10, 10, 20, 20});
1505 builder.Build()->Dispatch(expector);
1519 receiver.
drawRect({10, 10, 20, 20});
1522 builder.Build()->Dispatch(expector);
1535 receiver.
drawRect({10, 10, 20, 20});
1538 builder.Build()->Dispatch(expector);
1551 receiver.
drawRect({10, 10, 20, 20});
1554 builder.Build()->Dispatch(expector);
1564 path1.
cubicTo(20.91f, 37.52f, 16.54f, 33.39f, 13.62f, 30.58f);
1567 path1.
cubicTo(8.39f, 25.15f, 1.61f, 18, 8.37f, 11.27f);
1568 path1.
cubicTo(10.18f, 9.46f, 12.37f, 9.58f, 14.49f, 11.58f);
1569 path1.
cubicTo(15.67f, 12.71f, 17.05f, 14.69f, 17.07f, 16.58f);
1570 path1.
cubicTo(17.0968f, 17.458f, 16.7603f, 18.3081f, 16.14f, 18.93f);
1571 path1.
cubicTo(15.8168f, 19.239f, 15.4653f, 19.5169f, 15.09f, 19.76f);
1572 path1.
cubicTo(14.27f, 20.33f, 14.21f, 20.44f, 14.27f, 20.62f);
1573 path1.
cubicTo(15.1672f, 22.3493f, 16.3239f, 23.9309f, 17.7f, 25.31f);
1574 path1.
cubicTo(19.0791f, 26.6861f, 20.6607f, 27.8428f, 22.39f, 28.74f);
1575 path1.
cubicTo(22.57f, 28.8f, 22.69f, 28.74f, 23.25f, 27.92f);
1576 path1.
cubicTo(23.5f, 27.566f, 23.778f, 27.231f, 24.08f, 26.92f);
1577 path1.
cubicTo(24.7045f, 26.3048f, 25.5538f, 25.9723f, 26.43f, 26);
1578 path1.
cubicTo(28.29f, 26, 30.27f, 27.4f, 31.43f, 28.58f);
1579 path1.
cubicTo(33.43f, 30.67f, 33.55f, 32.9f, 31.74f, 34.7f);
1580 path1.
cubicTo(30.1477f, 36.4508f, 27.906f, 37.4704f, 25.54f, 37.52f);
1583 path1.
cubicTo(10.6946f, 12.2571f, 10.2522f, 12.4819f, 9.95f, 12.85f);
1584 path1.
cubicTo(5.12f, 17.67f, 8.95f, 22.5f, 14.05f, 27.85f);
1587 path1.
cubicTo(20.52f, 34.06f, 25.35f, 37.89f, 30.16f, 33.06f);
1588 path1.
cubicTo(30.83f, 32.39f, 31.25f, 31.56f, 29.81f, 30.06f);
1589 path1.
cubicTo(28.9247f, 29.07f, 27.7359f, 28.4018f, 26.43f, 28.16f);
1590 path1.
cubicTo(26.1476f, 28.1284f, 25.8676f, 28.2367f, 25.68f, 28.45f);
1591 path1.
cubicTo(25.4633f, 28.6774f, 25.269f, 28.9252f, 25.1f, 29.19f);
1592 path1.
cubicTo(24.53f, 30.01f, 23.47f, 31.54f, 21.54f, 30.79f);
1594 path1.
cubicTo(19.4601f, 29.7156f, 17.6787f, 28.4133f, 16.13f, 26.86f);
1595 path1.
cubicTo(14.5748f, 25.3106f, 13.2693f, 23.5295f, 12.26f, 21.58f);
1597 path1.
cubicTo(11.45f, 19.51f, 12.97f, 18.44f, 13.8f, 17.88f);
1598 path1.
cubicTo(14.061f, 17.706f, 14.308f, 17.512f, 14.54f, 17.3f);
1599 path1.
cubicTo(14.7379f, 17.1067f, 14.8404f, 16.8359f, 14.82f, 16.56f);
1600 path1.
cubicTo(14.5978f, 15.268f, 13.9585f, 14.0843f, 13, 13.19f);
1601 path1.
cubicTo(12.5398f, 12.642f, 11.8824f, 12.2971f, 11.17f, 12.23f);
1606 path1.
cubicTo(24.7319f, 18.758f, 24.262f, 18.2881f, 23.68f, 18.28f);
1609 path1.
cubicTo(25.5153f, 16.0582f, 26.9863f, 17.5248f, 27, 19.34f);
1614 path1.
cubicTo(30.037f, 15.859f, 27.171f, 13.011f, 23.69f, 13);
1616 path1.
cubicTo(28.415f, 10.725f, 32.3f, 14.615f, 32.3f, 19.34f);
1623 path2.
cubicTo(35.265f, 12.979f, 30.041f, 7.755f, 23.69f, 7.75f);
1625 path2.
cubicTo(31.264f, 5.525f, 37.495f, 11.756f, 37.5f, 19.33f);
1635 builder.Transform2DAffine(2.17391, 0, -2547.83,
1641 builder.SaveLayer(
nullptr,
nullptr,
nullptr);
1644 builder.Transform2DAffine(1.4375, 0, 1164.09,
1645 0, 1.53125, 236.548);
1651 builder.Transform2DAffine(1.4375, 0, 1164.09,
1652 0, 1.53125, 236.548);
1666 EXPECT_FALSE(display_list->bounds().isEmpty());
1674 ASSERT_TRUE(max_bounds.
contains(min_bounds));
1676 EXPECT_TRUE(display_list->bounds().contains(min_bounds));
1679 EXPECT_EQ(display_list->bounds().roundOut(),
SkIRect::MakeWH(100, 100));
1680 EXPECT_EQ(display_list->op_count(), 19u);
1681 EXPECT_EQ(display_list->bytes(),
sizeof(
DisplayList) + 408u);
1682 EXPECT_EQ(display_list->total_depth(), 3u);
1693 ASSERT_EQ(cur_m44, m44);
1694 ASSERT_EQ(cur_matrix,
matrix);
1697 ASSERT_NE(
builder.GetTransformFullPerspective(), m44);
1698 ASSERT_NE(
builder.GetTransform(), cur_matrix);
1700 ASSERT_EQ(cur_m44, m44);
1701 ASSERT_EQ(cur_matrix,
matrix);
1707 receiver.
scale(12.3, 14.5);
1712 ASSERT_EQ(cur_m44, m44);
1713 ASSERT_EQ(cur_matrix,
matrix);
1716 ASSERT_NE(
builder.GetTransformFullPerspective(), m44);
1717 ASSERT_NE(
builder.GetTransform(), cur_matrix);
1719 ASSERT_EQ(cur_m44, m44);
1720 ASSERT_EQ(cur_matrix,
matrix);
1731 ASSERT_EQ(cur_m44, m44);
1732 ASSERT_EQ(cur_matrix,
matrix);
1735 ASSERT_NE(
builder.GetTransformFullPerspective(), m44);
1736 ASSERT_NE(
builder.GetTransform(), cur_matrix);
1738 ASSERT_EQ(cur_m44, m44);
1739 ASSERT_EQ(cur_matrix,
matrix);
1745 receiver.
skew(12.3, 14.5);
1750 ASSERT_EQ(cur_m44, m44);
1751 ASSERT_EQ(cur_matrix,
matrix);
1754 ASSERT_NE(
builder.GetTransformFullPerspective(), m44);
1755 ASSERT_NE(
builder.GetTransform(), cur_matrix);
1757 ASSERT_EQ(cur_m44, m44);
1758 ASSERT_EQ(cur_matrix,
matrix);
1772 ASSERT_EQ(cur_m44, m44);
1773 ASSERT_EQ(cur_matrix,
matrix);
1776 ASSERT_NE(
builder.GetTransformFullPerspective(), m44);
1777 ASSERT_NE(
builder.GetTransform(), cur_matrix);
1779 ASSERT_EQ(cur_m44, m44);
1780 ASSERT_EQ(cur_matrix,
matrix);
1799 ASSERT_EQ(cur_m44, m44);
1800 ASSERT_EQ(cur_matrix,
matrix);
1803 ASSERT_NE(
builder.GetTransformFullPerspective(), m44);
1804 ASSERT_NE(
builder.GetTransform(), cur_matrix);
1806 ASSERT_EQ(cur_m44, m44);
1807 ASSERT_EQ(cur_matrix,
matrix);
1818 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
1819 ASSERT_EQ(initial_local_bounds, clip_bounds);
1820 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1825 ASSERT_NE(
builder.GetLocalClipBounds(), clip_bounds);
1826 ASSERT_NE(
builder.GetDestinationClipBounds(), clip_bounds);
1828 ASSERT_EQ(initial_local_bounds, clip_bounds);
1829 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1833 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1834 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1837 receiver.
scale(2, 2);
1839 ASSERT_EQ(
builder.GetLocalClipBounds(), scaled_clip_bounds);
1841 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
1845 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1846 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1858 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
1859 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1860 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1865 ASSERT_NE(
builder.GetLocalClipBounds(), clip_expanded_bounds);
1866 ASSERT_NE(
builder.GetDestinationClipBounds(), clip_expanded_bounds);
1868 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1869 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1873 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1874 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1877 receiver.
scale(2, 2);
1879 ASSERT_EQ(
builder.GetLocalClipBounds(), scaled_expanded_bounds);
1881 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_expanded_bounds);
1885 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1886 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1898 ASSERT_TRUE(
builder.GetDestinationClipBounds().isEmpty());
1905 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds_1);
1918 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
1919 ASSERT_EQ(initial_local_bounds, clip_bounds);
1920 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1925 ASSERT_NE(
builder.GetLocalClipBounds(), clip_bounds);
1926 ASSERT_NE(
builder.GetDestinationClipBounds(), clip_bounds);
1928 ASSERT_EQ(initial_local_bounds, clip_bounds);
1929 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1933 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1934 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1937 receiver.
scale(2, 2);
1939 ASSERT_EQ(
builder.GetLocalClipBounds(), scaled_clip_bounds);
1941 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
1945 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1946 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1959 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
1960 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1961 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1966 ASSERT_NE(
builder.GetLocalClipBounds(), clip_expanded_bounds);
1967 ASSERT_NE(
builder.GetDestinationClipBounds(), clip_expanded_bounds);
1969 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1970 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1974 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1975 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
1978 receiver.
scale(2, 2);
1980 ASSERT_EQ(
builder.GetLocalClipBounds(), scaled_expanded_bounds);
1982 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_expanded_bounds);
1986 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
1987 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2002 ASSERT_TRUE(
builder.GetDestinationClipBounds().isEmpty());
2009 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds_1);
2022 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
2023 ASSERT_EQ(initial_local_bounds, clip_bounds);
2024 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2029 ASSERT_NE(
builder.GetLocalClipBounds(), clip_bounds);
2030 ASSERT_NE(
builder.GetDestinationClipBounds(), clip_bounds);
2032 ASSERT_EQ(initial_local_bounds, clip_bounds);
2033 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2037 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2038 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2041 receiver.
scale(2, 2);
2043 ASSERT_EQ(
builder.GetLocalClipBounds(), scaled_clip_bounds);
2045 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
2049 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2050 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2062 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
2063 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2064 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2069 ASSERT_NE(
builder.GetLocalClipBounds(), clip_expanded_bounds);
2070 ASSERT_NE(
builder.GetDestinationClipBounds(), clip_expanded_bounds);
2072 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
2073 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
2077 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2078 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2081 receiver.
scale(2, 2);
2083 ASSERT_EQ(
builder.GetLocalClipBounds(), scaled_expanded_bounds);
2085 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_expanded_bounds);
2089 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2090 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2104 ASSERT_TRUE(
builder.GetDestinationClipBounds().isEmpty());
2111 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
2124 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
2125 ASSERT_EQ(initial_local_bounds, clip_bounds);
2126 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2129 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2130 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2143 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
2144 ASSERT_EQ(initial_local_bounds, clip_bounds);
2145 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2148 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2149 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2162 SkRect initial_destination_bounds =
builder.GetDestinationClipBounds();
2163 ASSERT_EQ(initial_local_bounds, clip_bounds);
2164 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2167 ASSERT_EQ(
builder.GetLocalClipBounds(), initial_local_bounds);
2168 ASSERT_EQ(
builder.GetDestinationClipBounds(), initial_destination_bounds);
2179 ASSERT_EQ(
builder.GetLocalClipBounds(), cull_rect);
2180 ASSERT_EQ(
builder.GetDestinationClipBounds(), cull_rect);
2192 ASSERT_EQ(
builder.GetLocalClipBounds(), clip_bounds);
2193 ASSERT_EQ(
builder.GetDestinationClipBounds(), clip_bounds);
2197 SkPoint horizontal_points[2] = {{10, 10}, {20, 10}};
2198 SkPoint vertical_points[2] = {{10, 10}, {10, 20}};
2206 EXPECT_GE(
bounds.width(), 10);
2215 EXPECT_GE(
bounds.height(), 10);
2255#define TEST_RTREE(rtree, query, expected_rects, expected_indices) \
2256 test_rtree(rtree, query, expected_rects, expected_indices, __FILE__, __LINE__)
2260 std::vector<SkRect> expected_rects,
2261 const std::vector<int>& expected_indices,
2262 const std::string&
file,
2264 std::vector<int> indices;
2266 rtree->search(query, &indices);
2267 EXPECT_EQ(indices, expected_indices) << label;
2268 EXPECT_EQ(indices.size(), expected_indices.size()) << label;
2269 std::list<SkRect> rects = rtree->searchAndConsolidateRects(query,
false);
2271 auto iterator = rects.cbegin();
2272 for (
int i : expected_indices) {
2273 ASSERT_TRUE(iterator != rects.cend()) << label;
2274 EXPECT_EQ(*iterator++, expected_rects[
i]) << label;
2281 std::vector<SkRect> rects = {
2287 auto display_list =
builder.Build();
2288 auto rtree = display_list->rtree();
2304 std::vector<int>({0, 1}));
2310 receiver.
drawRect({10, 10, 20, 20});
2312 receiver.
drawRect({50, 50, 60, 60});
2314 auto display_list =
builder.Build();
2315 auto rtree = display_list->rtree();
2316 std::vector<SkRect> rects = {
2335 std::vector<int>({0, 1}));
2344 builder.DrawRect({10, 10, 20, 20}, default_paint);
2345 builder.SaveLayer(
nullptr, &filter_paint);
2348 builder.DrawRect({53, 53, 57, 57}, default_paint);
2350 auto display_list =
builder.Build();
2351 auto rtree = display_list->rtree();
2352 std::vector<SkRect> rects = {
2370 auto expected_indices = std::vector<int>{0, 1};
2376 DlOpReceiver& nested_dl_receiver = ToReceiver(nested_dl_builder);
2377 nested_dl_receiver.
drawRect({10, 10, 20, 20});
2378 nested_dl_receiver.
drawRect({50, 50, 60, 60});
2379 auto nested_display_list = nested_dl_builder.
Build();
2384 auto display_list =
builder.Build();
2386 auto rtree = display_list->rtree();
2387 std::vector<SkRect> rects = {
2394 std::vector<int>({0, 1}));
2401 receiver.
drawRect({10, 10, 20, 20});
2403 receiver.
drawRect({50, 50, 60, 60});
2408 receiver2.
drawRect({10, 10, 20, 20});
2409 receiver2.
drawRect({50, 50, 60, 60});
2416 receiver.
drawRect({10, 10, 20, 20});
2421 receiver.
drawRect({50, 50, 60, 60});
2429 receiver2.
drawRect({10, 10, 20, 20});
2432 { receiver2.
drawRect({50, 50, 60, 60}); }
2445 receiver1.
scale(2, 2);
2447 receiver1.
drawRect({0, 0, 100, 100});
2451 auto display_list1 = builder1.
Build();
2457 receiver2.
scale(2, 2);
2459 receiver2.
drawRect({0, 0, 100, 100});
2461 auto display_list2 = builder2.
Build();
2471 receiver1.
drawRect({0, 0, 100, 100});
2472 receiver1.
scale(2, 2);
2475 auto display_list1 = builder1.
Build();
2480 receiver2.
drawRect({0, 0, 100, 100});
2481 receiver2.
scale(2, 2);
2483 auto display_list2 = builder2.
Build();
2492 const float alpha_matrix[] = {
2508 paint.setImageFilter(&color_filter_image_filter);
2524 builder.SaveLayer(&build_bounds);
2526 paint.setImageFilter(&color_filter_image_filter);
2552 receiver1.
drawRect({0, 0, 100, 100});
2558 receiver1.
drawRect({0, 0, 100, 100});
2560 auto display_list1 = builder1.
Build();
2569 receiver2.
drawRect({0, 0, 100, 100});
2576 receiver2.
drawRect({0, 0, 100, 100});
2578 auto display_list2 = builder2.
Build();
2589 receiver1.
drawRect({0, 0, 100, 100});
2592 auto display_list1 = builder1.
Build();
2598 receiver2.
drawRect({0, 0, 100, 100});
2600 auto display_list2 = builder2.
Build();
2614 receiver1.
drawRect({0, 0, 100, 100});
2617 auto display_list1 = builder1.
Build();
2626 receiver2.
drawRect({0, 0, 100, 100});
2628 auto display_list2 = builder2.
Build();
2639 receiver1.
drawRect({0, 0, 100, 100});
2642 auto display_list1 = builder1.
Build();
2648 receiver2.
drawRect({0, 0, 100, 100});
2650 auto display_list2 = builder2.
Build();
2660 receiver1.
skew(10, 10);
2661 receiver1.
drawRect({0, 0, 100, 100});
2664 auto display_list1 = builder1.
Build();
2669 receiver2.
skew(10, 10);
2670 receiver2.
drawRect({0, 0, 100, 100});
2672 auto display_list2 = builder2.
Build();
2683 receiver1.
drawRect({0, 0, 100, 100});
2686 auto display_list1 = builder1.
Build();
2692 receiver2.
drawRect({0, 0, 100, 100});
2694 auto display_list2 = builder2.
Build();
2704 receiver1.
scale(0.5, 0.5);
2705 receiver1.
drawRect({0, 0, 100, 100});
2708 auto display_list1 = builder1.
Build();
2713 receiver2.
scale(0.5, 0.5);
2714 receiver2.
drawRect({0, 0, 100, 100});
2716 auto display_list2 = builder2.
Build();
2728 receiver1.
drawRect({0, 0, 100, 100});
2734 receiver1.
drawRect({0, 0, 100, 100});
2736 auto display_list1 = builder1.
Build();
2743 receiver2.
drawRect({0, 0, 100, 100});
2749 receiver2.
drawRect({0, 0, 100, 100});
2750 auto display_list2 = builder2.
Build();
2762 receiver1.
drawRect({0, 0, 100, 100});
2768 receiver1.
drawRect({0, 0, 100, 100});
2770 auto display_list1 = builder1.
Build();
2777 receiver2.
drawRect({0, 0, 100, 100});
2783 receiver2.
drawRect({0, 0, 100, 100});
2784 auto display_list2 = builder2.
Build();
2795 receiver1.
drawRect({0, 0, 100, 100});
2801 receiver1.
drawRect({0, 0, 100, 100});
2803 auto display_list1 = builder1.
Build();
2809 receiver2.
drawRect({0, 0, 100, 100});
2815 receiver2.
drawRect({0, 0, 100, 100});
2816 auto display_list2 = builder2.
Build();
2827 receiver1.
drawRect({0, 0, 100, 100});
2829 receiver1.
drawRect({0, 0, 100, 100});
2831 auto display_list1 = builder1.
Build();
2835 receiver2.
drawRect({0, 0, 100, 100});
2836 receiver2.
drawRect({0, 0, 100, 100});
2837 auto display_list2 = builder2.
Build();
2847 receiver1.
scale(1.0, 1.0);
2848 receiver1.
drawRect({0, 0, 100, 100});
2850 receiver1.
drawRect({0, 0, 100, 100});
2852 auto display_list1 = builder1.
Build();
2856 receiver2.
drawRect({0, 0, 100, 100});
2857 receiver2.
drawRect({0, 0, 100, 100});
2858 auto display_list2 = builder2.
Build();
2869 receiver1.
drawRect({0, 0, 100, 100});
2871 receiver1.
drawRect({0, 0, 100, 100});
2873 auto display_list1 = builder1.
Build();
2877 receiver2.
drawRect({0, 0, 100, 100});
2878 receiver2.
drawRect({0, 0, 100, 100});
2879 auto display_list2 = builder2.
Build();
2889 receiver1.
skew(0, 0);
2890 receiver1.
drawRect({0, 0, 100, 100});
2892 receiver1.
drawRect({0, 0, 100, 100});
2894 auto display_list1 = builder1.
Build();
2898 receiver2.
drawRect({0, 0, 100, 100});
2899 receiver2.
drawRect({0, 0, 100, 100});
2900 auto display_list2 = builder2.
Build();
2914 receiver1.
drawRect({0, 0, 100, 100});
2920 receiver1.
drawRect({0, 0, 100, 100});
2922 auto display_list1 = builder1.
Build();
2926 receiver2.
drawRect({0, 0, 100, 100});
2927 receiver2.
drawRect({0, 0, 100, 100});
2928 auto display_list2 = builder2.
Build();
2939 receiver1.
drawRect({0, 0, 100, 100});
2941 receiver1.
drawRect({0, 0, 100, 100});
2943 auto display_list1 = builder1.
Build();
2947 receiver2.
drawRect({0, 0, 100, 100});
2948 receiver2.
drawRect({0, 0, 100, 100});
2949 auto display_list2 = builder2.
Build();
2964 receiver1.
drawRect({0, 0, 100, 100});
2966 receiver1.
drawRect({0, 0, 100, 100});
2968 auto display_list1 = builder1.
Build();
2972 receiver2.
drawRect({0, 0, 100, 100});
2973 receiver2.
drawRect({0, 0, 100, 100});
2974 auto display_list2 = builder2.
Build();
2989 receiver1.
drawRect({0, 0, 100, 100});
2991 receiver1.
drawRect({0, 0, 100, 100});
2993 auto display_list1 = builder1.
Build();
2999 receiver2.
drawRect({0, 0, 100, 100});
3001 receiver2.
drawRect({0, 0, 100, 100});
3003 auto display_list2 = builder2.
Build();
3016 receiver1.
drawRect({0, 0, 100, 100});
3018 receiver1.
drawRect({0, 0, 100, 100});
3020 auto display_list1 = builder1.
Build();
3024 receiver2.
drawRect({0, 0, 100, 100});
3025 receiver2.
drawRect({0, 0, 100, 100});
3026 auto display_list2 = builder2.
Build();
3037 builder.DrawRect({10, 10, 20, 20}, default_paint);
3039 builder.SaveLayer(
nullptr, &filter_paint);
3043 builder.DrawRect({53, 53, 57, 57}, default_paint);
3045 auto display_list =
builder.Build();
3046 auto rtree = display_list->rtree();
3047 std::vector<SkRect> rects = {
3066 std::vector<int>({0, 1}));
3071 DlOpReceiver& main_receiver = ToReceiver(main_builder);
3072 main_receiver.
drawRect({0, 0, 10, 10});
3073 main_receiver.
drawRect({20, 0, 30, 10});
3074 main_receiver.
drawRect({0, 20, 10, 30});
3075 main_receiver.
drawRect({20, 20, 30, 30});
3081 main->Dispatch(ToReceiver(culling_builder), cull_rect);
3095 SkIRect cull_rect = {11, 11, 19, 19};
3098 auto expected = expected_builder.
Build();
3100 test(cull_rect, expected);
3104 SkIRect cull_rect = {9, 9, 19, 19};
3107 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3108 expected_receiver.
drawRect({0, 0, 10, 10});
3109 auto expected = expected_builder.
Build();
3111 test(cull_rect, expected);
3115 SkIRect cull_rect = {11, 9, 21, 19};
3118 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3119 expected_receiver.
drawRect({20, 0, 30, 10});
3120 auto expected = expected_builder.
Build();
3122 test(cull_rect, expected);
3126 SkIRect cull_rect = {9, 11, 19, 21};
3129 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3130 expected_receiver.
drawRect({0, 20, 10, 30});
3131 auto expected = expected_builder.
Build();
3133 test(cull_rect, expected);
3137 SkIRect cull_rect = {11, 11, 21, 21};
3140 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3141 expected_receiver.
drawRect({20, 20, 30, 30});
3142 auto expected = expected_builder.
Build();
3144 test(cull_rect, expected);
3148 SkIRect cull_rect = {9, 9, 21, 21};
3161 auto display_list =
builder.Build();
3163 ASSERT_FALSE(display_list->can_apply_group_opacity());
3170 check_inverted_bounds(
renderer,
"DrawRect");
3177 check_inverted_bounds(
renderer,
"DrawRoundRect");
3184 check_inverted_bounds(
renderer,
"DrawOval");
3191 check_inverted_bounds(
renderer,
"DrawRectangularPath");
3198 check_inverted_bounds(
renderer,
"DrawOvalPath");
3207 check_inverted_bounds(
renderer,
"DrawRoundRectPath Clockwise");
3216 check_inverted_bounds(
renderer,
"DrawRoundRectPath Counter-Clockwise");
3222 uint32_t expected_op_count = 0u,
3223 uint32_t expected_total_depth = 0u) {
3227 uint32_t expected_op_count = 0u,
3228 uint32_t expected_total_depth = 0u) {
3234 if (list->op_count() != expected_op_count) {
3237 ASSERT_EQ(list->op_count(), expected_op_count) <<
name;
3238 EXPECT_EQ(list->total_depth(), expected_total_depth) <<
name;
3239 ASSERT_TRUE(list->bounds().isEmpty()) <<
name;
3242 name +
" DrawColor",
3246 expected_op_count, expected_total_depth);
3248 name +
" DrawPaint",
3252 expected_op_count, expected_total_depth);
3258 expected_op_count, expected_total_depth);
3260 name +
" Other Draw Ops",
3270 builder.DrawArc({10, 10, 20, 20}, 45, 90,
true,
paint);
3271 SkPoint pts[] = {{10, 10}, {20, 20}};
3277 SkRect{10.0f, 10.0f, 25.0f, 25.0f},
3283 SkRect rects[] = {{10, 10, 20, 20}, {10, 20, 30, 20}};
3292 builder.DrawDisplayList(TestDisplayList1, paint.getOpacity());
3293 builder.DrawShadow(kTestPath1, paint.getColor(), 1, true, 1);
3296 expected_op_count, expected_total_depth);
3298 name +
" SaveLayer",
3304 expected_op_count, expected_total_depth);
3306 name +
" inside Save",
3312 expected_op_count, expected_total_depth);
3347 builder.SaveLayer(
nullptr, &save_paint);
3357 builder.SaveLayer(
nullptr, &save_paint);
3363 builder.SaveLayer(
nullptr, &save_paint);
3366 "Nop inside SaveLayer",
3368 builder.SaveLayer(
nullptr,
nullptr);
3372 run_tests(
"DrawImage inside Culled SaveLayer",
3376 builder.SaveLayer(
nullptr, &save_paint);
3388 explicit Tester(
bool prefer_impeller_paths)
3389 : prefer_impeller_paths_(prefer_impeller_paths) {}
3391 bool PrefersImpellerPaths()
const override {
3392 return prefer_impeller_paths_;
3398 impeller_draw_path_calls_++;
3402 skia_clip_path_calls_++;
3406 impeller_clip_path_calls_++;
3409 virtual void drawShadow(
const SkPath& sk_path,
3412 bool transparent_occluder,
3414 skia_draw_shadow_calls_++;
3417 virtual void drawShadow(
const CacheablePath&
cache,
3420 bool transparent_occluder,
3422 impeller_draw_shadow_calls_++;
3425 int skia_draw_path_calls()
const {
return skia_draw_path_calls_; }
3426 int skia_clip_path_calls()
const {
return skia_draw_path_calls_; }
3427 int skia_draw_shadow_calls()
const {
return skia_draw_path_calls_; }
3428 int impeller_draw_path_calls()
const {
return impeller_draw_path_calls_; }
3429 int impeller_clip_path_calls()
const {
return impeller_draw_path_calls_; }
3430 int impeller_draw_shadow_calls()
const {
return impeller_draw_path_calls_; }
3433 const bool prefer_impeller_paths_;
3434 int skia_draw_path_calls_ = 0;
3435 int skia_clip_path_calls_ = 0;
3436 int skia_draw_shadow_calls_ = 0;
3437 int impeller_draw_path_calls_ = 0;
3438 int impeller_clip_path_calls_ = 0;
3439 int impeller_draw_shadow_calls_ = 0;
3448 auto display_list =
builder.Build();
3451 Tester skia_tester(
false);
3452 display_list->Dispatch(skia_tester);
3453 EXPECT_EQ(skia_tester.skia_draw_path_calls(), 1);
3454 EXPECT_EQ(skia_tester.skia_clip_path_calls(), 1);
3455 EXPECT_EQ(skia_tester.skia_draw_shadow_calls(), 1);
3456 EXPECT_EQ(skia_tester.impeller_draw_path_calls(), 0);
3457 EXPECT_EQ(skia_tester.impeller_clip_path_calls(), 0);
3458 EXPECT_EQ(skia_tester.impeller_draw_shadow_calls(), 0);
3462 Tester impeller_tester(
true);
3463 display_list->Dispatch(impeller_tester);
3464 EXPECT_EQ(impeller_tester.skia_draw_path_calls(), 0);
3465 EXPECT_EQ(impeller_tester.skia_clip_path_calls(), 0);
3466 EXPECT_EQ(impeller_tester.skia_draw_shadow_calls(), 0);
3467 EXPECT_EQ(impeller_tester.impeller_draw_path_calls(), 1);
3468 EXPECT_EQ(impeller_tester.impeller_clip_path_calls(), 1);
3469 EXPECT_EQ(impeller_tester.impeller_draw_shadow_calls(), 1);
3482 expected_.emplace_back(BoundsExpectation{
3490 bool clipped =
false) {
3496 expected_.emplace_back(BoundsExpectation{
3506 ASSERT_LT(save_layer_count_, expected_.size());
3507 auto expected = expected_[save_layer_count_];
3508 EXPECT_EQ(
options.bounds_from_caller(),
3509 expected.options.bounds_from_caller())
3510 <<
"expected bounds index " << save_layer_count_;
3511 EXPECT_EQ(
options.content_is_clipped(),
3512 expected.options.content_is_clipped())
3513 <<
"expected bounds index " << save_layer_count_;
3518 EXPECT_EQ(
bounds, expected.bounds)
3519 <<
"expected bounds index " << save_layer_count_;
3521 save_layer_count_++;
3525 return save_layer_count_ == expected_.size();
3529 struct BoundsExpectation {
3534 std::vector<BoundsExpectation> expected_;
3535 size_t save_layer_count_ = 0;
3542 builder.SaveLayer(
nullptr,
nullptr);
3547 auto display_list =
builder.Build();
3551 display_list->Dispatch(expector);
3562 builder.SaveLayer(
nullptr,
nullptr);
3567 auto display_list =
builder.Build();
3571 display_list->Dispatch(expector);
3582 builder.SaveLayer(
nullptr,
nullptr);
3587 auto display_list =
builder.Build();
3591 display_list->Dispatch(expector);
3602 builder.SaveLayer(
nullptr,
nullptr);
3607 auto display_list =
builder.Build();
3611 display_list->Dispatch(expector);
3619 builder.Translate(10.0f, 10.0f);
3620 builder.SaveLayer(
nullptr,
nullptr);
3625 auto display_list =
builder.Build();
3629 display_list->Dispatch(expector);
3638 builder.SaveLayer(
nullptr,
nullptr);
3643 auto display_list =
builder.Build();
3647 display_list->Dispatch(expector);
3656 builder.SaveLayer(
nullptr,
nullptr);
3661 auto display_list =
builder.Build();
3665 display_list->Dispatch(expector);
3675 builder.SaveLayer(
nullptr,
nullptr);
3683 auto display_list =
builder.Build();
3687 display_list->Dispatch(expector);
3695 builder.SaveLayer(
nullptr,
nullptr);
3697 builder.Translate(10.0f, 10.0f);
3701 auto display_list =
builder.Build();
3705 display_list->Dispatch(expector);
3713 builder.SaveLayer(
nullptr,
nullptr);
3719 auto display_list =
builder.Build();
3724 display_list->Dispatch(expector);
3732 builder.SaveLayer(
nullptr,
nullptr);
3738 auto display_list =
builder.Build();
3743 display_list->Dispatch(expector);
3751 builder.SaveLayer(
nullptr,
nullptr);
3753 builder.SaveLayer(
nullptr,
nullptr);
3760 auto display_list =
builder.Build();
3765 display_list->Dispatch(expector);
3774 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3776 SkRect clip_rect =
rect.makeOutset(100.0f, 100.0f);
3777 ASSERT_NE(clip_rect,
rect);
3782 builder.SaveLayer(
nullptr, &save_paint);
3787 auto display_list =
builder.Build();
3791 display_list->Dispatch(expector);
3800 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3802 SkRect clip_rect =
rect.makeOutset(100.0f, 100.0f);
3803 ASSERT_NE(clip_rect,
rect);
3808 builder.SaveLayer(
nullptr,
nullptr);
3810 builder.SaveLayer(
nullptr, &save_paint);
3817 auto display_list =
builder.Build();
3819 EXPECT_EQ(display_list->bounds(), clip_rect);
3824 display_list->Dispatch(expector);
3833 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3836 SkRect clip_rect =
rect.makeOutset(100.0f, 100.0f);
3837 ASSERT_NE(clip_rect,
rect);
3842 builder.SaveLayer(
nullptr,
nullptr);
3847 auto display_list =
builder.Build();
3851 display_list->Dispatch(expector);
3860 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3862 SkRect clip_rect =
rect.makeOutset(100.0f, 100.0f);
3863 ASSERT_NE(clip_rect,
rect);
3868 builder.SaveLayer(
nullptr,
nullptr);
3873 auto display_list =
builder.Build();
3879 display_list->Dispatch(expector);
3888 builder.SaveLayer(&save_rect,
nullptr);
3893 auto display_list =
builder.Build();
3897 display_list->Dispatch(expector);
3907 builder.SaveLayer(&save_rect,
nullptr);
3912 auto display_list =
builder.Build();
3916 display_list->Dispatch(expector);
3927 : depth_expectations_(
std::move(expectations)) {}
3932 FAIL() <<
"save(no depth parameter) method should not be called";
3935 void save(uint32_t total_content_depth)
override {
3936 ASSERT_LT(index_, depth_expectations_.size());
3937 EXPECT_EQ(depth_expectations_[index_], total_content_depth)
3938 <<
"at index " << index_;
3947 FAIL() <<
"saveLayer(no depth parameter) method should not be called";
3952 uint32_t total_content_depth,
3955 ASSERT_LT(index_, depth_expectations_.size());
3956 EXPECT_EQ(depth_expectations_[index_], total_content_depth)
3957 <<
"at index " << index_;
3962 return index_ == depth_expectations_.size();
3967 std::vector<uint32_t> depth_expectations_;
3973 auto child = child_builder.
Build();
3983 builder.DrawDisplayList(child, 1.0f);
3985 builder.SaveLayer(
nullptr,
nullptr);
3999 auto display_list =
builder.Build();
4001 EXPECT_EQ(display_list->total_depth(), 11u);
4004 display_list->Dispatch(expector);
4015 0.5f, 0.0f, 0.0f, 0.0f, 0.5f,
4016 0.5f, 0.0f, 0.0f, 0.0f, 0.5f,
4017 0.5f, 0.0f, 0.0f, 0.0f, 0.5f,
4018 0.5f, 0.0f, 0.0f, 0.0f, 0.5f
4023 builder.SaveLayer(
nullptr, &save_paint);
4033 std::vector<int> indices;
4034 dl->rtree()->search(
SkRect::MakeLTRB(0.0f, 0.0f, 500.0f, 500.0f), &indices);
4035 ASSERT_EQ(indices.size(), 3u);
4036 EXPECT_EQ(dl->rtree()->id(indices[0]), save_layer_id);
4037 EXPECT_EQ(dl->rtree()->id(indices[1]), draw_rect_id);
4038 EXPECT_EQ(dl->rtree()->id(indices[2]), restore_id);
4049 builder.SaveLayer(
nullptr, &save_paint);
4067 builder.SaveLayer(
nullptr, &save_paint);
4083 EXPECT_FALSE(
builder.Build()->can_apply_group_opacity());
4098 EXPECT_FALSE(
builder.Build()->can_apply_group_opacity());
4114 EXPECT_EQ(
builder.Build()->max_root_blend_mode(), expect)
4115 <<
"testing " <<
mode;
4152 builder.SaveLayer(
nullptr,
nullptr);
4161 dl->Dispatch(expector);
4169 builder.SaveLayer(
nullptr, &save_paint);
4178 dl->Dispatch(expector);
4214 builder.SaveLayer(
nullptr,
nullptr);
4219 builder.SaveLayer(
nullptr,
nullptr);
4242 dl->Dispatch(expector);
4248 EXPECT_FALSE(
builder.Build()->root_has_backdrop_filter());
4254 EXPECT_FALSE(
builder.Build()->root_has_backdrop_filter());
4272 dl->Dispatch(expector);
4278 builder.SaveLayer(
nullptr,
nullptr);
4292 EXPECT_FALSE(dl->root_has_backdrop_filter());
4297 dl->Dispatch(expector);
4305 auto child_dl = child_builder.
Build();
4307 EXPECT_FALSE(child_dl->root_has_backdrop_filter());
4311 auto parent_dl = parent_builder.
Build();
4313 EXPECT_FALSE(parent_dl->root_has_backdrop_filter());
4323 auto child_dl = child_builder.
Build();
4325 EXPECT_TRUE(child_dl->root_has_backdrop_filter());
4329 auto parent_dl = parent_builder.
Build();
4331 EXPECT_TRUE(parent_dl->root_has_backdrop_filter());
4334#define CLIP_EXPECTOR(name) ClipExpector name(__FILE__, __LINE__)
4342 std::variant<SkRect, SkRRect, SkPath>
shape;
4347 switch (
shape.index()) {
4365 EXPECT_EQ(index_, clip_expectations_.size()) << label();
4370 bool is_aa =
false) {
4371 clip_expectations_.push_back({
4381 bool is_aa =
false) {
4382 clip_expectations_.push_back({
4392 bool is_aa =
false) {
4393 clip_expectations_.push_back({
4403 bool is_aa)
override {
4404 check(
rect, clip_op, is_aa);
4408 bool is_aa)
override {
4409 check(
rrect, clip_op, is_aa);
4413 bool is_aa)
override {
4414 check(
path, clip_op, is_aa);
4419 std::vector<Expectation> clip_expectations_;
4421 template <
typename T>
4422 void check(
T shape,
ClipOp clip_op,
bool is_aa) {
4423 ASSERT_LT(index_, clip_expectations_.size())
4424 << label() << std::endl
4425 <<
"extra clip shape = " << shape;
4426 auto expected = clip_expectations_[index_];
4427 EXPECT_EQ(expected.clip_op, clip_op) << label();
4428 EXPECT_EQ(expected.is_aa, is_aa) << label();
4429 if (!std::holds_alternative<T>(expected.shape)) {
4430 EXPECT_TRUE(std::holds_alternative<T>(expected.shape))
4431 << label() <<
", expected type: " << expected.shape_name();
4433 EXPECT_EQ(std::get<T>(expected.shape), shape) << label();
4438 const std::string file_;
4441 std::string label() {
4463 cull_builder.
Scale(DPR, DPR);
4465 auto cull_dl = cull_builder.
Build();
4469 cull_dl->Dispatch(expector);
4478 auto cull_dl = cull_builder.
Build();
4482 cull_dl->Dispatch(expector);
4487 auto smaller_clip =
clip.makeInset(1.0f, 1.0f);
4492 auto cull_dl = cull_builder.
Build();
4497 cull_dl->Dispatch(expector);
4502 auto larger_clip =
clip.makeOutset(1.0f, 1.0f);
4506 cull_builder.
Save();
4509 auto cull_dl = cull_builder.
Build();
4513 cull_dl->Dispatch(expector);
4518 auto larger_clip =
clip.makeOutset(1.0f, 1.0f);
4521 cull_builder.
Save();
4526 auto cull_dl = cull_builder.
Build();
4531 cull_dl->Dispatch(expector);
4536 auto smaller_clip =
clip.makeInset(1.0f, 1.0f);
4537 auto smallest_clip =
clip.makeInset(2.0f, 2.0f);
4541 cull_builder.
Save();
4545 auto cull_dl = cull_builder.
Build();
4550 cull_dl->Dispatch(expector);
4555 auto smaller_clip =
clip.makeInset(1.0f, 1.0f);
4556 auto smallest_clip =
clip.makeInset(2.0f, 2.0f);
4560 cull_builder.
Save();
4565 auto cull_dl = cull_builder.
Build();
4571 cull_dl->Dispatch(expector);
4581 auto cull_dl = cull_builder.
Build();
4585 cull_dl->Dispatch(expector);
4595 auto cull_dl = cull_builder.
Build();
4600 cull_dl->Dispatch(expector);
4606 path.moveTo(0.0f, 0.0f);
4607 path.lineTo(1000.0f, 0.0f);
4608 path.lineTo(0.0f, 1000.0f);
4624 auto cull_dl = cull_builder.
Build();
4629 cull_dl->Dispatch(expector);
4635 path.addRect(
clip.makeOutset(1.0f, 1.0f));
4640 auto cull_dl = cull_builder.
Build();
4644 cull_dl->Dispatch(expector);
4649 auto smaller_clip =
clip.makeInset(1.0f, 1.0f);
4651 path.addRect(smaller_clip);
4656 auto cull_dl = cull_builder.
Build();
4662 cull_dl->Dispatch(expector);
4674 auto cull_dl = cull_builder.
Build();
4678 cull_dl->Dispatch(expector);
4690 auto cull_dl = cull_builder.
Build();
4696 cull_dl->Dispatch(expector);
constexpr SkColor SK_ColorBLUE
constexpr SkColor SK_ColorRED
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
constexpr SkColor SK_ColorBLACK
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
int main(int argc, char **argv)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
void drawRect(const SkRect &rect, const SkPaint &paint)
SkRect getLocalClipBounds() const
SkM44 getLocalToDevice() const
SkMatrix getTotalMatrix() const
SkIRect getDeviceClipBounds() const
void drawPicture(const SkPicture *picture)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
static SkMatrix RotateDeg(SkScalar deg)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
static SkMatrix Skew(SkScalar kx, SkScalar ky)
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
SkPath & moveTo(SkScalar x, SkScalar y)
void setFillType(SkPathFillType ft)
SkPath & lineTo(SkScalar x, SkScalar y)
SkPath & addRoundRect(const SkRect &rect, SkScalar rx, SkScalar ry, SkPathDirection dir=SkPathDirection::kCW)
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
SkCanvas * getRecordingCanvas()
sk_sp< SkPicture > finishRecordingAsPicture()
virtual SkRect cullRect() const =0
virtual int approximateOpCount(bool nested=false) const =0
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
static SkRRect MakeEmpty()
static constexpr SkRect kMaxCullRect
void DrawRect(const SkRect &rect, const DlPaint &paint) override
void ClipRRect(const SkRRect &rrect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
void Scale(SkScalar sx, SkScalar sy) override
void SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr) override
sk_sp< DisplayList > Build()
void ClipRect(const SkRect &rect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1) override
void ClipPath(const SkPath &path, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
static std::shared_ptr< DlColorFilter > Make(DlColor color, DlBlendMode mode)
static std::shared_ptr< DlImageFilter > Make(SkScalar sigma_x, SkScalar sigma_y, DlTileMode tile_mode)
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 DrawRect(const SkRect &rect, const DlPaint &paint)=0
@ 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
virtual void DrawRRect(const SkRRect &rrect, const DlPaint &paint)=0
virtual void DrawOval(const SkRect &bounds, const DlPaint &paint)=0
virtual void DrawPath(const SkPath &path, const DlPaint &paint)=0
static std::shared_ptr< DlImageFilter > Make(const std::shared_ptr< const DlColorFilter > &filter)
static std::shared_ptr< DlColorFilter > Make(const float matrix[20])
static std::shared_ptr< DlImageFilter > Make(const SkMatrix &matrix, DlImageSampling sampling)
Internal API for rendering recorded display lists to backends.
virtual void drawImageRect(const sk_sp< DlImage > image, const SkRect &src, const SkRect &dst, DlImageSampling sampling, bool render_with_attributes, SrcRectConstraint constraint=SrcRectConstraint::kFast)=0
virtual void drawArc(const SkRect &oval_bounds, SkScalar start_degrees, SkScalar sweep_degrees, bool use_center)=0
virtual void saveLayer(const SkRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop=nullptr)=0
virtual void drawRect(const SkRect &rect)=0
virtual void setStrokeMiter(float limit)=0
virtual void clipRect(const SkRect &rect, ClipOp clip_op, bool is_aa)=0
virtual void transformReset()=0
virtual void drawImage(const sk_sp< DlImage > image, const SkPoint point, DlImageSampling sampling, bool render_with_attributes)=0
virtual void drawCircle(const SkPoint ¢er, SkScalar radius)=0
virtual void drawVertices(const DlVertices *vertices, DlBlendMode mode)=0
virtual void drawPath(const CacheablePath &cache)
virtual void drawPoints(PointMode mode, uint32_t count, const SkPoint points[])=0
virtual void skew(SkScalar sx, SkScalar sy)=0
virtual void drawOval(const SkRect &bounds)=0
virtual void drawRRect(const SkRRect &rrect)=0
virtual void drawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1)=0
virtual void setStrokeWidth(float width)=0
virtual void setMaskFilter(const DlMaskFilter *filter)=0
virtual void drawDRRect(const SkRRect &outer, const SkRRect &inner)=0
virtual void setColorFilter(const DlColorFilter *filter)=0
virtual void drawImageNine(const sk_sp< DlImage > image, const SkIRect ¢er, const SkRect &dst, DlFilterMode filter, bool render_with_attributes)=0
virtual void setAntiAlias(bool aa)=0
virtual void clipRRect(const SkRRect &rrect, ClipOp clip_op, bool is_aa)=0
virtual void drawColor(DlColor color, DlBlendMode mode)=0
virtual void drawAtlas(const sk_sp< DlImage > atlas, const SkRSXform xform[], const SkRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const SkRect *cull_rect, bool render_with_attributes)=0
virtual void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt)=0
virtual void translate(SkScalar tx, SkScalar ty)=0
virtual void clipPath(const CacheablePath &cache, ClipOp clip_op, bool is_aa)
virtual void scale(SkScalar sx, SkScalar sy)=0
virtual void setStrokeJoin(DlStrokeJoin join)=0
virtual void drawShadow(const CacheablePath &cache, const DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr)
virtual void drawLine(const SkPoint &p0, const SkPoint &p1)=0
virtual void setImageFilter(const DlImageFilter *filter)=0
virtual void setColorSource(const DlColorSource *source)=0
virtual void rotate(SkScalar degrees)=0
virtual void drawPaint()=0
virtual void setDrawStyle(DlDrawStyle style)=0
virtual void drawTextBlob(const sk_sp< SkTextBlob > blob, SkScalar x, SkScalar y)=0
virtual void setBlendMode(DlBlendMode mode)=0
virtual void transformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt)=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
DlPaint & setColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
DlPaint & setMaskFilter(const std::shared_ptr< DlMaskFilter > &filter)
float getStrokeMiter() const
std::shared_ptr< const DlColorSource > getColorSource() const
DlStrokeJoin getStrokeJoin() const
DlPaint & setStrokeWidth(float width)
DlPaint & setAlpha(uint8_t alpha)
DlPaint & setBlendMode(DlBlendMode mode)
DlDrawStyle getDrawStyle() const
std::shared_ptr< const DlMaskFilter > getMaskFilter() const
std::shared_ptr< const DlColorFilter > getColorFilter() const
DlPaint & setImageFilter(const std::shared_ptr< const DlImageFilter > &filter)
float getStrokeWidth() const
std::shared_ptr< const DlImageFilter > getImageFilter() const
DlPaint & setDrawStyle(DlDrawStyle style)
DlPaint & setStrokeJoin(DlStrokeJoin join)
bool isInvertColors() const
Backend implementation of |DlOpReceiver| for |SkCanvas|.
static const SaveLayerOptions kNoAttributes
SaveLayerOptions with_can_distribute_opacity() const
SaveLayerOptions with_contains_backdrop_filter() const
static const SaveLayerOptions kWithAttributes
ClipExpector & addExpectation(const SkPath &path, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)
void clipRect(const SkRect &rect, DlCanvas::ClipOp clip_op, bool is_aa) override
void clipPath(const SkPath &path, DlCanvas::ClipOp clip_op, bool is_aa) override
ClipExpector(const std::string &file, int line)
void clipRRect(const SkRRect &rrect, DlCanvas::ClipOp clip_op, bool is_aa) override
ClipExpector & addExpectation(const SkRRect &rrect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)
ClipExpector & addExpectation(const SkRect &rect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)
void saveLayer(const SkRect &bounds, SaveLayerOptions options, const DlImageFilter *backdrop) override
void saveLayer(const SkRect &bounds, const SaveLayerOptions &options, uint32_t total_content_depth, DlBlendMode max_content_mode, const DlImageFilter *backdrop) override
void save(uint32_t total_content_depth) override
bool all_depths_checked() const
DepthExpector(std::vector< uint32_t > expectations)
static DlOpReceiver & ToReceiver(DisplayListBuilder &builder)
static void check_inverted_bounds(DlRenderer &renderer, const std::string &desc)
const std::function< void(DlCanvas &, DlPaint &, SkRect &rect)> DlRenderer
const std::function< void(DlCanvas &)> DlSetup
static void check_defaults(DisplayListBuilder &builder, const SkRect &cull_rect=DisplayListBuilder::kMaxCullRect)
static sk_sp< DisplayList > Build(size_t g_index, size_t v_index)
static void verify_inverted_bounds(DlSetup &setup, DlRenderer &renderer, DlPaint paint, SkRect render_rect, SkRect expected_bounds, const std::string &desc)
DisplayListTestBase()=default
static sk_sp< DisplayList > Build(DisplayListInvocation &invocation)
SaveLayerBoundsExpector & addSuppliedExpectation(const SkRect &bounds, bool clipped=false)
SaveLayerBoundsExpector & addComputedExpectation(const SkRect &bounds)
bool all_bounds_checked() const
SaveLayerBoundsExpector()
void saveLayer(const SkRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop) override
void saveLayer(const SkRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop) override
bool all_expectations_checked() const
virtual void saveLayer(const SkRect &bounds, const SaveLayerOptions &options, uint32_t total_content_depth, DlBlendMode max_content_blend_mode, const DlImageFilter *backdrop=nullptr)
SaveLayerExpector(std::vector< Expectations > expected)
SaveLayerExpector(const Expectations &expected)
#define CLIP_EXPECTOR(name)
#define RUN_TESTS2(body, expect)
#define TEST_RTREE(rtree, query, expected_rects, expected_indices)
std::shared_ptr< DlMaskFilter > mask_filter
static void draw_paint(SkCanvas *canvas, const SkRect &r, sk_sp< SkImageFilter > imf)
#define FAIL(name, result)
EMSCRIPTEN_KEEPALIVE void empty()
#define FML_LOG(severity)
#define FML_UNREACHABLE()
Dart_NativeFunction function
static float max(float r, float g, float b)
static void drawPath(SkPath &path, SkCanvas *canvas, SkColor color, const SkRect &clip, SkPaint::Cap cap, SkPaint::Join join, SkPaint::Style style, SkPathFillType fill, SkScalar strokeWidth)
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
sk_sp< const SkPicture > picture
clipPath(r.path, r.opAA.op(), r.opAA.aa())) DRAW(ClipRRect
sk_sp< const SkImageFilter > backdrop
PODArray< SkRSXform > xforms
sk_sp< SkBlender > blender SkRect rect
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
def Build(configs, env, options)
TEST_F(DisplayListTest, Defaults)
constexpr SkRect kTestBounds
static const DlBlurMaskFilter kTestMaskFilter1(DlBlurStyle::kNormal, 3.0)
bool DisplayListsNE_Verbose(const DisplayList *a, const DisplayList *b)
static const SkPath kTestPath1
static const DlImageColorSource kTestSource1(TestImage1, DlTileMode::kClamp, DlTileMode::kMirror, kLinearSampling)
static void test_rtree(const sk_sp< const DlRTree > &rtree, const SkRect &query, std::vector< SkRect > expected_rects, const std::vector< int > &expected_indices, const std::string &file, int line)
static std::vector< testing::DisplayListInvocationGroup > allGroups
static constexpr SkPoint kTestPoints[2]
static const SkRRect kTestRRect
static const DlMatrixColorFilter kTestMatrixColorFilter1(kRotateColorMatrix)
static DlImageSampling kLinearSampling
static std::shared_ptr< const DlVertices > TestVertices1
bool DisplayListsEQ_Verbose(const DisplayList *a, const DisplayList *b)
static DlImageSampling kNearestSampling
sk_sp< SkTextBlob > GetTestTextBlob(int index)
static const DlBlurImageFilter kTestBlurImageFilter1(5.0, 5.0, DlTileMode::kClamp)
std::vector< DisplayListInvocationGroup > CreateAllGroups()
static sk_sp< DisplayList > TestDisplayList1
impeller::Scalar DlScalar
DlPaint DisplayListBuilderTestingAttributes(DisplayListBuilder &builder)
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
DlOpReceiver & DisplayListBuilderTestingAccessor(DisplayListBuilder &builder)
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
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent Remove all existing persistent cache This is mainly for debugging purposes such as reproducing the shader compilation jank trace to file
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
@ kNormal
fuzzy inside and outside
it will be possible to load the file into Perfetto s trace viewer 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
int DisplayListBuilderTestingLastOpIndex(DisplayListBuilder &builder)
@ kColorBurn
darken destination to reflect source
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kSrcOver
r = s + (1-sa)*d
@ kLastMode
last valid value
static void draw_rect(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
flutter::SaveLayerOptions SaveLayerOptions
static SkString to_string(int n)
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
static SkImageInfo MakeN32Premul(int width, int height)
static SkRect Make(const SkISize &size)
static constexpr SkRect MakeEmpty()
SkScalar fBottom
larger y-axis bounds
bool intersect(const SkRect &r)
SkScalar fLeft
smaller x-axis bounds
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
bool intersects(const SkRect &r) const
SkScalar fRight
larger x-axis bounds
bool contains(SkScalar x, SkScalar y) const
static constexpr SkRect MakeWH(float w, float h)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
SkScalar fTop
smaller y-axis bounds
static constexpr DlColor kWhite()
static constexpr DlColor kBlue()
static constexpr DlColor kTransparent()
static constexpr DlColor kRed()
std::variant< SkRect, SkRRect, SkPath > shape
uint32_t adjust_render_op_depth_cost(uint32_t previous_cost)
uint32_t depth_accumulated(uint32_t depth_scale=1u)
void Invoke(DlOpReceiver &builder)
Expectations(DlBlendMode mode)
std::optional< DlBlendMode > max_blend_mode
std::optional< SaveLayerOptions > options
Expectations(SaveLayerOptions o)
static void setup(SkCanvas *canvas, SkPaint *paint, const SkBitmap &bm, SkFilterMode fm, SkTileMode tmx, SkTileMode tmy)
#define EXPECT_TRUE(handle)