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"
34 return builder.asReceiver();
38 return builder.CurrentAttributes();
43static std::vector<testing::DisplayListInvocationGroup>
allGroups =
49template <
typename BaseT>
61 return builder.Build();
68 uint32_t op_count = 0u;
69 size_t byte_count = 0u;
71 uint32_t render_op_depth_cost = 1u;
72 for (
size_t i = 0; i <
allGroups.size(); i++) {
74 size_t j = (i == g_index ? v_index : 0);
75 if (j >= group.variants.size()) {
82 invocation.
Invoke(receiver);
83 render_op_depth_cost =
92 if (v_index >=
allGroups[g_index].variants.size()) {
95 name +=
" variant " + std::to_string(v_index + 1);
98 EXPECT_EQ(dl->op_count(
false), op_count) <<
name;
100 EXPECT_EQ(dl->total_depth(), depth) <<
name;
124 EXPECT_EQ(builder_paint, defaults);
127 EXPECT_EQ(builder.GetTransform(),
SkMatrix());
128 EXPECT_EQ(builder.GetTransformFullPerspective(),
SkM44());
130 EXPECT_EQ(builder.GetLocalClipBounds(), cull_rect);
131 EXPECT_EQ(builder.GetDestinationClipBounds(), cull_rect);
133 EXPECT_EQ(builder.GetSaveCount(), 1);
145 const std::string& desc) {
148 renderer(builder,
paint, render_rect);
149 auto dl = builder.Build();
150 EXPECT_EQ(dl->op_count(), 1u) << desc;
151 EXPECT_EQ(dl->bounds(), expected_bounds) << desc;
155 const std::string& desc) {
158 rect.fLeft, rect.fBottom);
160 rect.fRight, rect.fTop);
162 rect.fLeft, rect.fTop);
163 auto empty_setup = [](
DlCanvas&) {};
165 ASSERT_TRUE(rect.fLeft < rect.fRight);
166 ASSERT_TRUE(rect.fTop < rect.fBottom);
167 ASSERT_FALSE(rect.isEmpty());
169 ASSERT_TRUE(invertedLR.
isEmpty());
171 ASSERT_TRUE(invertedTB.
isEmpty());
172 ASSERT_TRUE(invertedLTRB.
fLeft > invertedLTRB.
fRight);
173 ASSERT_TRUE(invertedLTRB.
fTop > invertedLTRB.
fBottom);
174 ASSERT_TRUE(invertedLTRB.
isEmpty());
179 ref_bounds, desc +
" LR swapped");
181 ref_bounds, desc +
" TB swapped");
183 ref_bounds, desc +
" LR&TB swapped");
194 SkRect stroke_bounds = rect.makeOutset(1.0f, 1.0f);
196 stroke_bounds, desc +
" LR swapped, sw 2");
198 stroke_bounds, desc +
" TB swapped, sw 2");
200 stroke_bounds, desc +
" LR&TB swapped, sw 2");
205 SkRect maskblur_bounds = rect.makeOutset(6.0f, 6.0f);
207 maskblur_bounds, desc +
" LR swapped, mask 2");
209 maskblur_bounds, desc +
" TB swapped, mask 2");
211 maskblur_bounds, desc +
" LR&TB swapped, mask 2");
216 SkRect erode_bounds = rect.makeInset(2.0f, 2.0f);
218 erode_bounds, desc +
" LR swapped, erode 2");
220 erode_bounds, desc +
" TB swapped, erode 2");
222 erode_bounds, desc +
" LR&TB swapped, erode 2");
232 check_defaults(builder);
237 auto dl = builder.Build();
238 EXPECT_EQ(dl->op_count(), 0u);
240 EXPECT_EQ(dl->total_depth(), 0u);
245 auto dl1 = builder.Build();
246 auto dl2 = builder.Build();
247 auto dl3 = builder.Build();
248 ASSERT_TRUE(dl1->Equals(dl2));
249 ASSERT_TRUE(dl2->Equals(dl3));
255 auto dl = builder.Build();
257 auto dl2 = builder.Build();
258 ASSERT_TRUE(dl->Equals(dl2));
266 builder.Translate(10.0f, 10.0f);
268 check_defaults(builder, cull_rect);
271 builder.Scale(10.0f, 10.0f);
273 check_defaults(builder, cull_rect);
276 builder.Skew(0.1f, 0.1f);
278 check_defaults(builder, cull_rect);
281 builder.Rotate(45.0f);
283 check_defaults(builder, cull_rect);
288 check_defaults(builder, cull_rect);
291 builder.Transform2DAffine(1.0f, 0.0f, 12.0f,
294 check_defaults(builder, cull_rect);
299 check_defaults(builder, cull_rect);
302 builder.TransformFullPerspective(1.0f, 0.0f, 0.0f, 12.0f,
303 0.0f, 1.0f, 0.0f, 35.0f,
304 0.0f, 0.0f, 1.0f, 5.0f,
305 0.0f, 0.0f, 0.0f, 1.0f);
307 check_defaults(builder, cull_rect);
314 builder.Translate(10.0f, 10.0f);
316 check_defaults(builder, cull_rect);
318 builder.Scale(10.0f, 10.0f);
320 check_defaults(builder, cull_rect);
322 builder.Skew(0.1f, 0.1f);
324 check_defaults(builder, cull_rect);
326 builder.Rotate(45.0f);
328 check_defaults(builder, cull_rect);
332 check_defaults(builder, cull_rect);
334 builder.Transform2DAffine(1.0f, 0.0f, 12.0f,
337 check_defaults(builder, cull_rect);
341 check_defaults(builder, cull_rect);
343 builder.TransformFullPerspective(1.0f, 0.0f, 0.0f, 12.0f,
344 0.0f, 1.0f, 0.0f, 35.0f,
345 0.0f, 0.0f, 1.0f, 5.0f,
346 0.0f, 0.0f, 0.0f, 1.0f);
348 check_defaults(builder, cull_rect);
356 builder.ClipRect({0.0f, 0.0f, 10.0f, 10.0f});
358 check_defaults(builder, cull_rect);
363 check_defaults(builder, cull_rect);
366 builder.ClipPath(
SkPath().addOval({0.0f, 0.0f, 10.0f, 10.0f}));
368 check_defaults(builder, cull_rect);
375 builder.ClipRect({0.0f, 0.0f, 10.0f, 10.0f});
377 check_defaults(builder, cull_rect);
381 check_defaults(builder, cull_rect);
383 builder.ClipPath(
SkPath().addOval({0.0f, 0.0f, 10.0f, 10.0f}));
385 check_defaults(builder, cull_rect);
395 check_defaults(builder, cull_rect);
399 check_defaults(builder, cull_rect);
403 check_defaults(builder, cull_rect);
407 check_defaults(builder, cull_rect);
411 check_defaults(builder, cull_rect);
415 check_defaults(builder, cull_rect);
419 check_defaults(builder, cull_rect);
423 check_defaults(builder, cull_rect);
427 check_defaults(builder, cull_rect);
431 check_defaults(builder, cull_rect);
435 check_defaults(builder, cull_rect);
439 check_defaults(builder, cull_rect);
443 check_defaults(builder, cull_rect);
447 check_defaults(builder, cull_rect);
455 ASSERT_EQ(builder.GetDestinationClipBounds(),
457 ASSERT_EQ(builder.GetLocalClipBounds().makeOutset(1, 1),
466 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
473 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
481 builder.ClipRect(clip_rect, ClipOp::kIntersect,
false);
482 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
491 builder.ClipRRect(clip_rrect, ClipOp::kIntersect,
false);
492 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
500 builder.ClipPath(clip_path, ClipOp::kIntersect,
false);
501 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
508 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
519 ASSERT_TRUE(cull_rect.
contains(clip_rect));
525 builder.ClipRect(clip_rect, ClipOp::kIntersect,
false);
526 builder.SaveLayer(&cull_rect, &layer_paint);
533 auto display_list = builder.Build();
535 ASSERT_EQ(display_list->op_count(), 6u);
536 EXPECT_EQ(display_list->total_depth(), 2u);
539 ASSERT_TRUE(result_rect.
intersect(clip_rect));
541 ASSERT_EQ(display_list->bounds(), result_rect);
552 ASSERT_TRUE(cull_rect.
contains(clip_rect));
558 builder.ClipRect(clip_rect, ClipOp::kIntersect,
false);
559 builder.SaveLayer(&cull_rect, &layer_paint);
566 auto display_list = builder.Build();
568 ASSERT_EQ(display_list->op_count(), 6u);
569 EXPECT_EQ(display_list->total_depth(), 2u);
572 ASSERT_TRUE(result_rect.
intersect(clip_rect));
574 ASSERT_EQ(display_list->bounds(), result_rect);
579 for (
size_t i = 0; i < group.variants.size(); i++) {
580 auto& invocation = group.variants[i];
582 auto desc = group.op_name +
"(variant " + std::to_string(i + 1) +
")";
583 ASSERT_EQ(dl->op_count(
false), invocation.op_count()) << desc;
584 ASSERT_EQ(dl->bytes(
false), invocation.byte_count()) << desc;
585 EXPECT_EQ(dl->total_depth(), invocation.depth_accumulated()) << desc;
593 for (
size_t i = 0; i < group.variants.size(); i++) {
596 group.op_name +
"(variant " + std::to_string(i + 1) +
" != empty)";
597 if (group.variants[i].is_empty()) {
599 ASSERT_TRUE(
empty->Equals(*dl)) << desc;
602 ASSERT_FALSE(
empty->Equals(*dl)) << desc;
610 for (
size_t i = 0; i < group.variants.size(); i++) {
619 group.op_name +
"(variant " + std::to_string(i + 1) +
" == copy)";
620 ASSERT_EQ(
copy->op_count(
false), dl->op_count(
false)) << desc;
621 ASSERT_EQ(
copy->bytes(
false), dl->bytes(
false)) << desc;
622 ASSERT_EQ(
copy->op_count(
true), dl->op_count(
true)) << desc;
623 ASSERT_EQ(
copy->bytes(
true), dl->bytes(
true)) << desc;
624 EXPECT_EQ(
copy->total_depth(), dl->total_depth()) << desc;
625 ASSERT_EQ(
copy->bounds(), dl->bounds()) << desc;
626 ASSERT_TRUE(
copy->Equals(*dl)) << desc;
627 ASSERT_TRUE(dl->Equals(*
copy)) << desc;
634 std::vector<sk_sp<DisplayList>> lists_a;
635 std::vector<sk_sp<DisplayList>> lists_b;
636 for (
size_t i = 0; i < group.variants.size(); i++) {
637 lists_a.push_back(Build(group.variants[i]));
638 lists_b.push_back(Build(group.variants[i]));
641 for (
size_t i = 0; i < lists_a.size(); i++) {
643 for (
size_t j = 0; j < lists_b.size(); j++) {
645 auto desc = group.op_name +
"(variant " + std::to_string(i + 1) +
646 " ==? variant " + std::to_string(j + 1) +
")";
648 (group.variants[i].is_empty() && group.variants[j].is_empty())) {
650 ASSERT_EQ(listA->op_count(
false), listB->op_count(
false)) << desc;
651 ASSERT_EQ(listA->bytes(
false), listB->bytes(
false)) << desc;
652 ASSERT_EQ(listA->op_count(
true), listB->op_count(
true)) << desc;
653 ASSERT_EQ(listA->bytes(
true), listB->bytes(
true)) << desc;
654 EXPECT_EQ(listA->total_depth(), listB->total_depth()) << desc;
655 ASSERT_EQ(listA->bounds(), listB->bounds()) << desc;
656 ASSERT_TRUE(listA->Equals(*listB)) << desc;
657 ASSERT_TRUE(listB->Equals(*listA)) << desc;
661 ASSERT_FALSE(listA->Equals(*listB)) << desc;
662 ASSERT_FALSE(listB->Equals(*listA)) << desc;
671 for (
size_t i = 0; i < group.variants.size(); i++) {
674 group.variants[i].Invoke(ToReceiver(builder1));
675 group.variants[i].Invoke(ToReceiver(builder2));
679 auto desc = group.op_name +
"(variant " + std::to_string(i + 1) +
" )";
680 ASSERT_EQ(dl1->op_count(
false), dl2->op_count(
false)) << desc;
681 ASSERT_EQ(dl1->bytes(
false), dl2->bytes(
false)) << desc;
682 ASSERT_EQ(dl1->op_count(
true), dl2->op_count(
true)) << desc;
683 ASSERT_EQ(dl1->bytes(
true), dl2->bytes(
true)) << desc;
684 EXPECT_EQ(dl1->total_depth(), dl2->total_depth()) << desc;
685 ASSERT_EQ(dl1->bounds(), dl2->bounds()) << desc;
686 ASSERT_EQ(dl1->total_depth(), dl2->total_depth()) << desc;
689 ASSERT_EQ(dl1->rtree().
get(),
nullptr) << desc;
690 ASSERT_NE(dl2->rtree().
get(),
nullptr) << desc;
706 ASSERT_EQ(dl->op_count(
false), 0u);
707 ASSERT_EQ(dl->op_count(
true), 0u);
708 EXPECT_EQ(dl->total_depth(), 0u);
718 ASSERT_EQ(dl->op_count(
false), 0u);
719 ASSERT_EQ(dl->op_count(
true), 0u);
720 EXPECT_EQ(dl->total_depth(), 0u);
725 ASSERT_TRUE(default_dl->Equals(*default_dl)) <<
"Default == itself";
726 for (
size_t gi = 0; gi <
allGroups.size(); gi++) {
729 auto desc =
"[Group " + group.op_name +
" omitted]";
730 ASSERT_TRUE(missing_dl->Equals(*missing_dl)) << desc <<
" == itself";
731 ASSERT_FALSE(missing_dl->Equals(*default_dl)) << desc <<
" != Default";
732 ASSERT_FALSE(default_dl->Equals(*missing_dl)) <<
"Default != " << desc;
733 for (
size_t vi = 0; vi < group.variants.size(); vi++) {
734 auto desc =
"[Group " + group.op_name +
" variant " +
735 std::to_string(vi + 1) +
"]";
737 ASSERT_TRUE(variant_dl->Equals(*variant_dl)) << desc <<
" == itself";
739 ASSERT_TRUE(variant_dl->Equals(*default_dl)) << desc <<
" == Default";
740 ASSERT_TRUE(default_dl->Equals(*variant_dl)) <<
"Default == " << desc;
742 ASSERT_FALSE(variant_dl->Equals(*default_dl)) << desc <<
" != Default";
743 ASSERT_FALSE(default_dl->Equals(*variant_dl)) <<
"Default != " << desc;
745 if (group.variants[vi].is_empty()) {
746 ASSERT_TRUE(variant_dl->Equals(*missing_dl)) << desc <<
" != omitted";
747 ASSERT_TRUE(missing_dl->Equals(*variant_dl)) <<
"omitted != " << desc;
749 ASSERT_FALSE(variant_dl->Equals(*missing_dl)) << desc <<
" != omitted";
750 ASSERT_FALSE(missing_dl->Equals(*variant_dl)) <<
"omitted != " << desc;
761 const float color_matrix[] = {
770 const float alpha_matrix[] = {
789 ASSERT_EQ(display_list->bounds(), rect);
802 ASSERT_EQ(display_list->bounds(), rect);
819 ASSERT_EQ(picture->
cullRect(), build_bounds);
835 ASSERT_EQ(display_list->bounds(), build_bounds);
849 ASSERT_EQ(display_list->bounds(), build_bounds);
864 ASSERT_EQ(display_list->bounds(), rect);
879 ASSERT_EQ(display_list->bounds(), build_bounds);
893 ASSERT_EQ(display_list->bounds(), build_bounds);
906 ASSERT_EQ(display_list->bounds(), build_bounds);
919 ASSERT_EQ(display_list->bounds(), build_bounds);
928 for (
int y = 10;
y <= 60;
y += 10) {
929 for (
int x = 10;
x <= 60;
x += 10) {
945 for (
int y = 10;
y <= 60;
y += 10) {
946 for (
int x = 10;
x <= 60;
x += 10) {
954 DlOpReceiver& outer_receiver = ToReceiver(outer_builder);
956 auto display_list = outer_builder.
Build();
958 ASSERT_EQ(display_list->op_count(), 1u);
959 ASSERT_EQ(display_list->op_count(
true), 36u);
960 EXPECT_EQ(display_list->total_depth(), 37u);
963 static_cast<int>(display_list->op_count()));
965 static_cast<int>(display_list->op_count(
true)));
998 display_list->Dispatch(dispatcher);
1021 display_list->Dispatch(dispatcher);
1030 receiver.
scale(20.0, 20.0);
1032 auto display_list = builder.Build();
1033 ASSERT_NE(display_list,
nullptr);
1040 display_list->Dispatch(dispatcher);
1047 bool expect_with_kSrc) {
1054 auto display_list = builder.Build();
1055 EXPECT_EQ(display_list->can_apply_group_opacity(), expect_for_op)
1057 <<
" " <<
name << std::endl
1067 auto display_list = builder.Build();
1068 EXPECT_EQ(display_list->can_apply_group_opacity(), expect_with_kSrc)
1070 <<
" receiver.setBlendMode(kSrc);" << std::endl
1071 <<
" " <<
name << std::endl
1076#define RUN_TESTS(body) \
1077 run_tests(#body, [](DlOpReceiver& receiver) { body }, true, false)
1078#define RUN_TESTS2(body, expect) \
1079 run_tests(#body, [](DlOpReceiver& receiver) { body }, expect, expect)
1094 SkPath().addOval({0, 0, 10, 10}).addOval({5, 5, 15, 15})););
1117 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
1118 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
1131 builder.DrawRect({0, 0, 10, 10},
DlPaint());
1132 builder.DrawRect({5, 5, 15, 15},
DlPaint());
1133 static auto display_list = builder.Build();
1148 for (
int i = 0; i < 10; i++) {
1151 auto display_list = builder.Build();
1152 EXPECT_FALSE(display_list->can_apply_group_opacity());
1159 for (
int i = 0; i < 10; i++) {
1163 auto display_list = builder.Build();
1164 EXPECT_TRUE(display_list->can_apply_group_opacity());
1171 for (
int i = 0; i < 10; i++) {
1175 auto display_list = builder.Build();
1176 EXPECT_TRUE(display_list->can_apply_group_opacity());
1186 auto display_list = builder.Build();
1187 EXPECT_TRUE(display_list->can_apply_group_opacity());
1197 auto display_list = builder.Build();
1198 EXPECT_FALSE(display_list->can_apply_group_opacity());
1208 auto display_list = builder.Build();
1209 EXPECT_TRUE(display_list->can_apply_group_opacity());
1219 auto display_list = builder.Build();
1220 EXPECT_TRUE(display_list->can_apply_group_opacity());
1227 receiver.
drawRect({50, 50, 100, 100});
1231 SkRect bounds = builder.Build()->bounds();
1242 expected_.push_back(expected);
1246 : expected_(
std::move(expected)) {}
1251 EXPECT_EQ(
options, expected_[save_layer_count_]);
1252 save_layer_count_++;
1258 std::vector<SaveLayerOptions> expected_;
1259 int save_layer_count_ = 0;
1271 receiver.
drawRect({10, 10, 20, 20});
1274 builder.Build()->Dispatch(expector);
1286 receiver.
drawRect({10, 10, 20, 20});
1289 builder.Build()->Dispatch(expector);
1301 receiver.
drawRect({10, 10, 20, 20});
1302 receiver.
drawRect({15, 15, 25, 25});
1305 builder.Build()->Dispatch(expector);
1322 receiver.
drawRect({10, 10, 20, 20});
1324 receiver.
drawRect({15, 15, 25, 25});
1329 builder.Build()->Dispatch(expector);
1330 EXPECT_EQ(expector.save_layer_count(), 3);
1345 receiver.
drawRect({10, 10, 20, 20});
1349 builder.Build()->Dispatch(expector);
1350 EXPECT_EQ(expector.save_layer_count(), 2);
1363 receiver.
drawRect({10, 10, 20, 20});
1366 builder.Build()->Dispatch(expector);
1380 receiver.
drawRect({10, 10, 20, 20});
1383 builder.Build()->Dispatch(expector);
1397 receiver.
drawRect({10, 10, 20, 20});
1400 builder.Build()->Dispatch(expector);
1414 receiver.
drawRect({10, 10, 20, 20});
1417 builder.Build()->Dispatch(expector);
1430 receiver.
drawRect({10, 10, 20, 20});
1433 builder.Build()->Dispatch(expector);
1446 receiver.
drawRect({10, 10, 20, 20});
1449 builder.Build()->Dispatch(expector);
1459 path1.
cubicTo(20.91f, 37.52f, 16.54f, 33.39f, 13.62f, 30.58f);
1462 path1.
cubicTo(8.39f, 25.15f, 1.61f, 18, 8.37f, 11.27f);
1463 path1.
cubicTo(10.18f, 9.46f, 12.37f, 9.58f, 14.49f, 11.58f);
1464 path1.
cubicTo(15.67f, 12.71f, 17.05f, 14.69f, 17.07f, 16.58f);
1465 path1.
cubicTo(17.0968f, 17.458f, 16.7603f, 18.3081f, 16.14f, 18.93f);
1466 path1.
cubicTo(15.8168f, 19.239f, 15.4653f, 19.5169f, 15.09f, 19.76f);
1467 path1.
cubicTo(14.27f, 20.33f, 14.21f, 20.44f, 14.27f, 20.62f);
1468 path1.
cubicTo(15.1672f, 22.3493f, 16.3239f, 23.9309f, 17.7f, 25.31f);
1469 path1.
cubicTo(19.0791f, 26.6861f, 20.6607f, 27.8428f, 22.39f, 28.74f);
1470 path1.
cubicTo(22.57f, 28.8f, 22.69f, 28.74f, 23.25f, 27.92f);
1471 path1.
cubicTo(23.5f, 27.566f, 23.778f, 27.231f, 24.08f, 26.92f);
1472 path1.
cubicTo(24.7045f, 26.3048f, 25.5538f, 25.9723f, 26.43f, 26);
1473 path1.
cubicTo(28.29f, 26, 30.27f, 27.4f, 31.43f, 28.58f);
1474 path1.
cubicTo(33.43f, 30.67f, 33.55f, 32.9f, 31.74f, 34.7f);
1475 path1.
cubicTo(30.1477f, 36.4508f, 27.906f, 37.4704f, 25.54f, 37.52f);
1478 path1.
cubicTo(10.6946f, 12.2571f, 10.2522f, 12.4819f, 9.95f, 12.85f);
1479 path1.
cubicTo(5.12f, 17.67f, 8.95f, 22.5f, 14.05f, 27.85f);
1482 path1.
cubicTo(20.52f, 34.06f, 25.35f, 37.89f, 30.16f, 33.06f);
1483 path1.
cubicTo(30.83f, 32.39f, 31.25f, 31.56f, 29.81f, 30.06f);
1484 path1.
cubicTo(28.9247f, 29.07f, 27.7359f, 28.4018f, 26.43f, 28.16f);
1485 path1.
cubicTo(26.1476f, 28.1284f, 25.8676f, 28.2367f, 25.68f, 28.45f);
1486 path1.
cubicTo(25.4633f, 28.6774f, 25.269f, 28.9252f, 25.1f, 29.19f);
1487 path1.
cubicTo(24.53f, 30.01f, 23.47f, 31.54f, 21.54f, 30.79f);
1489 path1.
cubicTo(19.4601f, 29.7156f, 17.6787f, 28.4133f, 16.13f, 26.86f);
1490 path1.
cubicTo(14.5748f, 25.3106f, 13.2693f, 23.5295f, 12.26f, 21.58f);
1492 path1.
cubicTo(11.45f, 19.51f, 12.97f, 18.44f, 13.8f, 17.88f);
1493 path1.
cubicTo(14.061f, 17.706f, 14.308f, 17.512f, 14.54f, 17.3f);
1494 path1.
cubicTo(14.7379f, 17.1067f, 14.8404f, 16.8359f, 14.82f, 16.56f);
1495 path1.
cubicTo(14.5978f, 15.268f, 13.9585f, 14.0843f, 13, 13.19f);
1496 path1.
cubicTo(12.5398f, 12.642f, 11.8824f, 12.2971f, 11.17f, 12.23f);
1501 path1.
cubicTo(24.7319f, 18.758f, 24.262f, 18.2881f, 23.68f, 18.28f);
1504 path1.
cubicTo(25.5153f, 16.0582f, 26.9863f, 17.5248f, 27, 19.34f);
1509 path1.
cubicTo(30.037f, 15.859f, 27.171f, 13.011f, 23.69f, 13);
1511 path1.
cubicTo(28.415f, 10.725f, 32.3f, 14.615f, 32.3f, 19.34f);
1518 path2.
cubicTo(35.265f, 12.979f, 30.041f, 7.755f, 23.69f, 7.75f);
1520 path2.
cubicTo(31.264f, 5.525f, 37.495f, 11.756f, 37.5f, 19.33f);
1527 builder.ClipRect({0, 0, 100, 100}, ClipOp::kIntersect,
true);
1530 builder.Transform2DAffine(2.17391, 0, -2547.83,
1534 builder.ClipRect({1172, 245, 1218, 294}, ClipOp::kIntersect,
true);
1536 builder.SaveLayer(
nullptr,
nullptr,
nullptr);
1539 builder.Transform2DAffine(1.4375, 0, 1164.09,
1540 0, 1.53125, 236.548);
1546 builder.Transform2DAffine(1.4375, 0, 1164.09,
1547 0, 1.53125, 236.548);
1561 EXPECT_FALSE(display_list->bounds().isEmpty());
1569 ASSERT_TRUE(max_bounds.
contains(min_bounds));
1571 EXPECT_TRUE(display_list->bounds().contains(min_bounds));
1574 EXPECT_EQ(display_list->bounds().roundOut(),
SkIRect::MakeWH(100, 100));
1575 EXPECT_EQ(display_list->op_count(), 19u);
1576 EXPECT_EQ(display_list->bytes(),
sizeof(
DisplayList) + 400u);
1577 EXPECT_EQ(display_list->total_depth(), 3u);
1586 SkM44 cur_m44 = builder.GetTransformFullPerspective();
1587 SkMatrix cur_matrix = builder.GetTransform();
1588 ASSERT_EQ(cur_m44, m44);
1589 ASSERT_EQ(cur_matrix, matrix);
1592 ASSERT_NE(builder.GetTransformFullPerspective(), m44);
1593 ASSERT_NE(builder.GetTransform(), cur_matrix);
1595 ASSERT_EQ(cur_m44, m44);
1596 ASSERT_EQ(cur_matrix, matrix);
1602 receiver.
scale(12.3, 14.5);
1605 SkM44 cur_m44 = builder.GetTransformFullPerspective();
1606 SkMatrix cur_matrix = builder.GetTransform();
1607 ASSERT_EQ(cur_m44, m44);
1608 ASSERT_EQ(cur_matrix, matrix);
1611 ASSERT_NE(builder.GetTransformFullPerspective(), m44);
1612 ASSERT_NE(builder.GetTransform(), cur_matrix);
1614 ASSERT_EQ(cur_m44, m44);
1615 ASSERT_EQ(cur_matrix, matrix);
1624 SkM44 cur_m44 = builder.GetTransformFullPerspective();
1625 SkMatrix cur_matrix = builder.GetTransform();
1626 ASSERT_EQ(cur_m44, m44);
1627 ASSERT_EQ(cur_matrix, matrix);
1630 ASSERT_NE(builder.GetTransformFullPerspective(), m44);
1631 ASSERT_NE(builder.GetTransform(), cur_matrix);
1633 ASSERT_EQ(cur_m44, m44);
1634 ASSERT_EQ(cur_matrix, matrix);
1640 receiver.
skew(12.3, 14.5);
1643 SkM44 cur_m44 = builder.GetTransformFullPerspective();
1644 SkMatrix cur_matrix = builder.GetTransform();
1645 ASSERT_EQ(cur_m44, m44);
1646 ASSERT_EQ(cur_matrix, matrix);
1649 ASSERT_NE(builder.GetTransformFullPerspective(), m44);
1650 ASSERT_NE(builder.GetTransform(), cur_matrix);
1652 ASSERT_EQ(cur_m44, m44);
1653 ASSERT_EQ(cur_matrix, matrix);
1665 SkM44 cur_m44 = builder.GetTransformFullPerspective();
1666 SkMatrix cur_matrix = builder.GetTransform();
1667 ASSERT_EQ(cur_m44, m44);
1668 ASSERT_EQ(cur_matrix, matrix);
1671 ASSERT_NE(builder.GetTransformFullPerspective(), m44);
1672 ASSERT_NE(builder.GetTransform(), cur_matrix);
1674 ASSERT_EQ(cur_m44, m44);
1675 ASSERT_EQ(cur_matrix, matrix);
1692 SkM44 cur_m44 = builder.GetTransformFullPerspective();
1693 SkMatrix cur_matrix = builder.GetTransform();
1694 ASSERT_EQ(cur_m44, m44);
1695 ASSERT_EQ(cur_matrix, matrix);
1698 ASSERT_NE(builder.GetTransformFullPerspective(), m44);
1699 ASSERT_NE(builder.GetTransform(), cur_matrix);
1701 ASSERT_EQ(cur_m44, m44);
1702 ASSERT_EQ(cur_matrix, matrix);
1709 receiver.
clipRect(clip_bounds, ClipOp::kIntersect,
false);
1712 SkRect initial_local_bounds = builder.GetLocalClipBounds();
1713 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
1714 ASSERT_EQ(initial_local_bounds, clip_bounds);
1715 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1718 receiver.
clipRect({0, 0, 15, 15}, ClipOp::kIntersect,
false);
1720 ASSERT_NE(builder.GetLocalClipBounds(), clip_bounds);
1721 ASSERT_NE(builder.GetDestinationClipBounds(), clip_bounds);
1723 ASSERT_EQ(initial_local_bounds, clip_bounds);
1724 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1728 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1729 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1732 receiver.
scale(2, 2);
1734 ASSERT_EQ(builder.GetLocalClipBounds(), scaled_clip_bounds);
1736 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
1740 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1741 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1749 receiver.
clipRect(clip_bounds, ClipOp::kIntersect,
true);
1752 SkRect initial_local_bounds = builder.GetLocalClipBounds();
1753 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
1754 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1755 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1758 receiver.
clipRect({0, 0, 15, 15}, ClipOp::kIntersect,
true);
1760 ASSERT_NE(builder.GetLocalClipBounds(), clip_expanded_bounds);
1761 ASSERT_NE(builder.GetDestinationClipBounds(), clip_expanded_bounds);
1763 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1764 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1768 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1769 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1772 receiver.
scale(2, 2);
1774 ASSERT_EQ(builder.GetLocalClipBounds(), scaled_expanded_bounds);
1776 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_expanded_bounds);
1780 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1781 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1790 receiver.
clipRect(clip_bounds_1, ClipOp::kIntersect,
false);
1792 receiver.
clipRect(clip_bounds_1, ClipOp::kIntersect,
false);
1793 ASSERT_TRUE(builder.GetDestinationClipBounds().isEmpty());
1797 receiver.
clipRect(clip_bounds_1, ClipOp::kIntersect,
false);
1799 receiver.
clipRect(clip_bounds_2, ClipOp::kIntersect,
false);
1800 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds_1);
1812 SkRect initial_local_bounds = builder.GetLocalClipBounds();
1813 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
1814 ASSERT_EQ(initial_local_bounds, clip_bounds);
1815 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1818 receiver.
clipRect({0, 0, 15, 15}, ClipOp::kIntersect,
false);
1820 ASSERT_NE(builder.GetLocalClipBounds(), clip_bounds);
1821 ASSERT_NE(builder.GetDestinationClipBounds(), clip_bounds);
1823 ASSERT_EQ(initial_local_bounds, clip_bounds);
1824 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1828 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1829 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1832 receiver.
scale(2, 2);
1834 ASSERT_EQ(builder.GetLocalClipBounds(), scaled_clip_bounds);
1836 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
1840 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1841 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1853 SkRect initial_local_bounds = builder.GetLocalClipBounds();
1854 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
1855 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1856 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1859 receiver.
clipRect({0, 0, 15, 15}, ClipOp::kIntersect,
true);
1861 ASSERT_NE(builder.GetLocalClipBounds(), clip_expanded_bounds);
1862 ASSERT_NE(builder.GetDestinationClipBounds(), clip_expanded_bounds);
1864 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1865 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1869 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1870 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1873 receiver.
scale(2, 2);
1875 ASSERT_EQ(builder.GetLocalClipBounds(), scaled_expanded_bounds);
1877 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_expanded_bounds);
1881 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1882 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1894 receiver.
clipRRect(clip1, ClipOp::kIntersect,
false);
1896 receiver.
clipRRect(clip1, ClipOp::kIntersect,
false);
1897 ASSERT_TRUE(builder.GetDestinationClipBounds().isEmpty());
1901 receiver.
clipRRect(clip1, ClipOp::kIntersect,
false);
1903 receiver.
clipRRect(clip2, ClipOp::kIntersect,
false);
1904 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds_1);
1916 SkRect initial_local_bounds = builder.GetLocalClipBounds();
1917 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
1918 ASSERT_EQ(initial_local_bounds, clip_bounds);
1919 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1922 receiver.
clipRect({0, 0, 15, 15}, ClipOp::kIntersect,
false);
1924 ASSERT_NE(builder.GetLocalClipBounds(), clip_bounds);
1925 ASSERT_NE(builder.GetDestinationClipBounds(), clip_bounds);
1927 ASSERT_EQ(initial_local_bounds, clip_bounds);
1928 ASSERT_EQ(initial_destination_bounds, clip_bounds);
1932 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1933 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1936 receiver.
scale(2, 2);
1938 ASSERT_EQ(builder.GetLocalClipBounds(), scaled_clip_bounds);
1940 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
1944 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1945 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1956 SkRect initial_local_bounds = builder.GetLocalClipBounds();
1957 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
1958 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1959 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1962 receiver.
clipRect({0, 0, 15, 15}, ClipOp::kIntersect,
true);
1964 ASSERT_NE(builder.GetLocalClipBounds(), clip_expanded_bounds);
1965 ASSERT_NE(builder.GetDestinationClipBounds(), clip_expanded_bounds);
1967 ASSERT_EQ(initial_local_bounds, clip_expanded_bounds);
1968 ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds);
1972 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1973 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1976 receiver.
scale(2, 2);
1978 ASSERT_EQ(builder.GetLocalClipBounds(), scaled_expanded_bounds);
1980 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_expanded_bounds);
1984 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
1985 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
1996 receiver.
clipPath(clip1, ClipOp::kIntersect,
false);
1998 receiver.
clipPath(clip1, ClipOp::kIntersect,
false);
1999 ASSERT_TRUE(builder.GetDestinationClipBounds().isEmpty());
2003 receiver.
clipPath(clip1, ClipOp::kIntersect,
false);
2005 receiver.
clipPath(clip2, ClipOp::kIntersect,
false);
2006 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
2015 receiver.
clipRect(clip_bounds, ClipOp::kIntersect,
false);
2018 SkRect initial_local_bounds = builder.GetLocalClipBounds();
2019 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
2020 ASSERT_EQ(initial_local_bounds, clip_bounds);
2021 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2023 receiver.
clipRect(diff_clip, ClipOp::kDifference,
false);
2024 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
2025 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
2037 SkRect initial_local_bounds = builder.GetLocalClipBounds();
2038 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
2039 ASSERT_EQ(initial_local_bounds, clip_bounds);
2040 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2042 receiver.
clipRRect(diff_clip, ClipOp::kDifference,
false);
2043 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
2044 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
2056 SkRect initial_local_bounds = builder.GetLocalClipBounds();
2057 SkRect initial_destination_bounds = builder.GetDestinationClipBounds();
2058 ASSERT_EQ(initial_local_bounds, clip_bounds);
2059 ASSERT_EQ(initial_destination_bounds, clip_bounds);
2061 receiver.
clipPath(diff_clip, ClipOp::kDifference,
false);
2062 ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds);
2063 ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds);
2074 ASSERT_EQ(builder.GetLocalClipBounds(), cull_rect);
2075 ASSERT_EQ(builder.GetDestinationClipBounds(), cull_rect);
2087 ASSERT_EQ(builder.GetLocalClipBounds(), clip_bounds);
2088 ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds);
2092 SkPoint horizontal_points[2] = {{10, 10}, {20, 10}};
2093 SkPoint vertical_points[2] = {{10, 10}, {10, 20}};
2097 receiver.
drawPoints(PointMode::kPolygon, 2, horizontal_points);
2098 SkRect bounds = builder.Build()->bounds();
2101 EXPECT_GE(bounds.width(), 10);
2106 receiver.
drawPoints(PointMode::kPolygon, 2, vertical_points);
2107 SkRect bounds = builder.Build()->bounds();
2110 EXPECT_GE(bounds.height(), 10);
2115 receiver.
drawPoints(PointMode::kPoints, 1, horizontal_points);
2116 SkRect bounds = builder.Build()->bounds();
2123 receiver.
drawPoints(PointMode::kPolygon, 2, horizontal_points);
2124 SkRect bounds = builder.Build()->bounds();
2133 receiver.
drawPoints(PointMode::kPolygon, 2, vertical_points);
2134 SkRect bounds = builder.Build()->bounds();
2143 receiver.
drawPoints(PointMode::kPoints, 1, horizontal_points);
2144 SkRect bounds = builder.Build()->bounds();
2152 std::vector<SkRect> expected_rects,
2153 const std::vector<int>& expected_indices) {
2154 std::vector<int> indices;
2155 rtree->search(query, &indices);
2156 EXPECT_EQ(indices, expected_indices);
2157 EXPECT_EQ(indices.size(), expected_indices.size());
2158 std::list<SkRect> rects = rtree->searchAndConsolidateRects(query);
2160 auto iterator = rects.cbegin();
2161 for (
int i : expected_indices) {
2163 EXPECT_EQ(*iterator++, expected_rects[i]);
2170 receiver.
drawRect({10, 10, 20, 20});
2171 receiver.
drawRect({50, 50, 60, 60});
2172 auto display_list = builder.Build();
2173 auto rtree = display_list->rtree();
2174 std::vector<SkRect> rects = {
2180 test_rtree(rtree, {5, 5, 10, 10}, rects, {});
2181 test_rtree(rtree, {20, 20, 25, 25}, rects, {});
2182 test_rtree(rtree, {45, 45, 50, 50}, rects, {});
2183 test_rtree(rtree, {60, 60, 65, 65}, rects, {});
2186 test_rtree(rtree, {5, 5, 11, 11}, rects, {0});
2187 test_rtree(rtree, {19, 19, 25, 25}, rects, {0});
2188 test_rtree(rtree, {45, 45, 51, 51}, rects, {1});
2189 test_rtree(rtree, {59, 59, 65, 65}, rects, {1});
2192 test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1});
2198 receiver.
drawRect({10, 10, 20, 20});
2200 receiver.
drawRect({50, 50, 60, 60});
2202 auto display_list = builder.Build();
2203 auto rtree = display_list->rtree();
2204 std::vector<SkRect> rects = {
2210 test_rtree(rtree, {5, 5, 10, 10}, rects, {});
2211 test_rtree(rtree, {20, 20, 25, 25}, rects, {});
2212 test_rtree(rtree, {45, 45, 50, 50}, rects, {});
2213 test_rtree(rtree, {60, 60, 65, 65}, rects, {});
2216 test_rtree(rtree, {5, 5, 11, 11}, rects, {0});
2217 test_rtree(rtree, {19, 19, 25, 25}, rects, {0});
2218 test_rtree(rtree, {45, 45, 51, 51}, rects, {1});
2219 test_rtree(rtree, {59, 59, 65, 65}, rects, {1});
2222 test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1});
2231 builder.DrawRect({10, 10, 20, 20}, default_paint);
2232 builder.SaveLayer(
nullptr, &filter_paint);
2235 builder.DrawRect({53, 53, 57, 57}, default_paint);
2237 auto display_list = builder.Build();
2238 auto rtree = display_list->rtree();
2239 std::vector<SkRect> rects = {
2245 test_rtree(rtree, {5, 5, 10, 10}, rects, {});
2246 test_rtree(rtree, {20, 20, 25, 25}, rects, {});
2247 test_rtree(rtree, {45, 45, 50, 50}, rects, {});
2248 test_rtree(rtree, {60, 60, 65, 65}, rects, {});
2251 test_rtree(rtree, {5, 5, 11, 11}, rects, {0});
2252 test_rtree(rtree, {19, 19, 25, 25}, rects, {0});
2253 test_rtree(rtree, {45, 45, 51, 51}, rects, {1});
2254 test_rtree(rtree, {59, 59, 65, 65}, rects, {1});
2257 test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1});
2262 DlOpReceiver& nested_dl_receiver = ToReceiver(nested_dl_builder);
2263 nested_dl_receiver.
drawRect({10, 10, 20, 20});
2264 nested_dl_receiver.
drawRect({50, 50, 60, 60});
2265 auto nested_display_list = nested_dl_builder.
Build();
2270 auto display_list = builder.Build();
2272 auto rtree = display_list->rtree();
2273 std::vector<SkRect> rects = {
2279 test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1});
2286 receiver.
drawRect({10, 10, 20, 20});
2288 receiver.
drawRect({50, 50, 60, 60});
2293 receiver2.
drawRect({10, 10, 20, 20});
2294 receiver2.
drawRect({50, 50, 60, 60});
2301 receiver.
drawRect({10, 10, 20, 20});
2306 receiver.
drawRect({50, 50, 60, 60});
2314 receiver2.
drawRect({10, 10, 20, 20});
2317 { receiver2.
drawRect({50, 50, 60, 60}); }
2330 receiver1.
scale(2, 2);
2331 receiver1.
clipRect({10, 10, 20, 20}, ClipOp::kIntersect,
false);
2332 receiver1.
drawRect({0, 0, 100, 100});
2336 auto display_list1 = builder1.
Build();
2342 receiver2.
scale(2, 2);
2343 receiver2.
clipRect({10, 10, 20, 20}, ClipOp::kIntersect,
false);
2344 receiver2.
drawRect({0, 0, 100, 100});
2346 auto display_list2 = builder2.
Build();
2356 receiver1.
drawRect({0, 0, 100, 100});
2357 receiver1.
scale(2, 2);
2360 auto display_list1 = builder1.
Build();
2365 receiver2.
drawRect({0, 0, 100, 100});
2366 receiver2.
scale(2, 2);
2368 auto display_list2 = builder2.
Build();
2377 const float alpha_matrix[] = {
2393 paint.setImageFilter(&color_filter_image_filter);
2394 builder.DrawRect(rect,
paint);
2409 builder.SaveLayer(&build_bounds);
2411 paint.setImageFilter(&color_filter_image_filter);
2412 builder.DrawRect(rect,
paint);
2437 receiver1.
drawRect({0, 0, 100, 100});
2443 receiver1.
drawRect({0, 0, 100, 100});
2445 auto display_list1 = builder1.
Build();
2454 receiver2.
drawRect({0, 0, 100, 100});
2461 receiver2.
drawRect({0, 0, 100, 100});
2463 auto display_list2 = builder2.
Build();
2474 receiver1.
drawRect({0, 0, 100, 100});
2477 auto display_list1 = builder1.
Build();
2483 receiver2.
drawRect({0, 0, 100, 100});
2485 auto display_list2 = builder2.
Build();
2499 receiver1.
drawRect({0, 0, 100, 100});
2502 auto display_list1 = builder1.
Build();
2511 receiver2.
drawRect({0, 0, 100, 100});
2513 auto display_list2 = builder2.
Build();
2524 receiver1.
drawRect({0, 0, 100, 100});
2527 auto display_list1 = builder1.
Build();
2533 receiver2.
drawRect({0, 0, 100, 100});
2535 auto display_list2 = builder2.
Build();
2545 receiver1.
skew(10, 10);
2546 receiver1.
drawRect({0, 0, 100, 100});
2549 auto display_list1 = builder1.
Build();
2554 receiver2.
skew(10, 10);
2555 receiver2.
drawRect({0, 0, 100, 100});
2557 auto display_list2 = builder2.
Build();
2568 receiver1.
drawRect({0, 0, 100, 100});
2571 auto display_list1 = builder1.
Build();
2577 receiver2.
drawRect({0, 0, 100, 100});
2579 auto display_list2 = builder2.
Build();
2589 receiver1.
scale(0.5, 0.5);
2590 receiver1.
drawRect({0, 0, 100, 100});
2593 auto display_list1 = builder1.
Build();
2598 receiver2.
scale(0.5, 0.5);
2599 receiver2.
drawRect({0, 0, 100, 100});
2601 auto display_list2 = builder2.
Build();
2613 receiver1.
drawRect({0, 0, 100, 100});
2619 receiver1.
drawRect({0, 0, 100, 100});
2621 auto display_list1 = builder1.
Build();
2628 receiver2.
drawRect({0, 0, 100, 100});
2634 receiver2.
drawRect({0, 0, 100, 100});
2635 auto display_list2 = builder2.
Build();
2647 receiver1.
drawRect({0, 0, 100, 100});
2653 receiver1.
drawRect({0, 0, 100, 100});
2655 auto display_list1 = builder1.
Build();
2662 receiver2.
drawRect({0, 0, 100, 100});
2668 receiver2.
drawRect({0, 0, 100, 100});
2669 auto display_list2 = builder2.
Build();
2680 receiver1.
drawRect({0, 0, 100, 100});
2686 receiver1.
drawRect({0, 0, 100, 100});
2688 auto display_list1 = builder1.
Build();
2694 receiver2.
drawRect({0, 0, 100, 100});
2700 receiver2.
drawRect({0, 0, 100, 100});
2701 auto display_list2 = builder2.
Build();
2712 receiver1.
drawRect({0, 0, 100, 100});
2714 receiver1.
drawRect({0, 0, 100, 100});
2716 auto display_list1 = builder1.
Build();
2720 receiver2.
drawRect({0, 0, 100, 100});
2721 receiver2.
drawRect({0, 0, 100, 100});
2722 auto display_list2 = builder2.
Build();
2732 receiver1.
scale(1.0, 1.0);
2733 receiver1.
drawRect({0, 0, 100, 100});
2735 receiver1.
drawRect({0, 0, 100, 100});
2737 auto display_list1 = builder1.
Build();
2741 receiver2.
drawRect({0, 0, 100, 100});
2742 receiver2.
drawRect({0, 0, 100, 100});
2743 auto display_list2 = builder2.
Build();
2754 receiver1.
drawRect({0, 0, 100, 100});
2756 receiver1.
drawRect({0, 0, 100, 100});
2758 auto display_list1 = builder1.
Build();
2762 receiver2.
drawRect({0, 0, 100, 100});
2763 receiver2.
drawRect({0, 0, 100, 100});
2764 auto display_list2 = builder2.
Build();
2774 receiver1.
skew(0, 0);
2775 receiver1.
drawRect({0, 0, 100, 100});
2777 receiver1.
drawRect({0, 0, 100, 100});
2779 auto display_list1 = builder1.
Build();
2783 receiver2.
drawRect({0, 0, 100, 100});
2784 receiver2.
drawRect({0, 0, 100, 100});
2785 auto display_list2 = builder2.
Build();
2799 receiver1.
drawRect({0, 0, 100, 100});
2805 receiver1.
drawRect({0, 0, 100, 100});
2807 auto display_list1 = builder1.
Build();
2811 receiver2.
drawRect({0, 0, 100, 100});
2812 receiver2.
drawRect({0, 0, 100, 100});
2813 auto display_list2 = builder2.
Build();
2824 receiver1.
drawRect({0, 0, 100, 100});
2826 receiver1.
drawRect({0, 0, 100, 100});
2828 auto display_list1 = builder1.
Build();
2832 receiver2.
drawRect({0, 0, 100, 100});
2833 receiver2.
drawRect({0, 0, 100, 100});
2834 auto display_list2 = builder2.
Build();
2849 receiver1.
drawRect({0, 0, 100, 100});
2851 receiver1.
drawRect({0, 0, 100, 100});
2853 auto display_list1 = builder1.
Build();
2857 receiver2.
drawRect({0, 0, 100, 100});
2858 receiver2.
drawRect({0, 0, 100, 100});
2859 auto display_list2 = builder2.
Build();
2874 receiver1.
drawRect({0, 0, 100, 100});
2876 receiver1.
drawRect({0, 0, 100, 100});
2878 auto display_list1 = builder1.
Build();
2884 receiver2.
drawRect({0, 0, 100, 100});
2886 receiver2.
drawRect({0, 0, 100, 100});
2888 auto display_list2 = builder2.
Build();
2900 ClipOp::kIntersect,
true);
2901 receiver1.
drawRect({0, 0, 100, 100});
2903 receiver1.
drawRect({0, 0, 100, 100});
2905 auto display_list1 = builder1.
Build();
2909 receiver2.
drawRect({0, 0, 100, 100});
2910 receiver2.
drawRect({0, 0, 100, 100});
2911 auto display_list2 = builder2.
Build();
2922 builder.DrawRect({10, 10, 20, 20}, default_paint);
2923 builder.ClipRect({50, 50, 60, 60}, ClipOp::kIntersect,
false);
2924 builder.SaveLayer(
nullptr, &filter_paint);
2928 builder.DrawRect({53, 53, 57, 57}, default_paint);
2930 auto display_list = builder.Build();
2931 auto rtree = display_list->rtree();
2932 std::vector<SkRect> rects = {
2938 test_rtree(rtree, {5, 5, 10, 10}, rects, {});
2939 test_rtree(rtree, {20, 20, 25, 25}, rects, {});
2940 test_rtree(rtree, {45, 45, 50, 50}, rects, {});
2941 test_rtree(rtree, {60, 60, 65, 65}, rects, {});
2944 test_rtree(rtree, {5, 5, 11, 11}, rects, {0});
2945 test_rtree(rtree, {19, 19, 25, 25}, rects, {0});
2946 test_rtree(rtree, {45, 45, 51, 51}, rects, {1});
2947 test_rtree(rtree, {59, 59, 65, 65}, rects, {1});
2950 test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1});
2955 DlOpReceiver& main_receiver = ToReceiver(main_builder);
2956 main_receiver.
drawRect({0, 0, 10, 10});
2957 main_receiver.
drawRect({20, 0, 30, 10});
2958 main_receiver.
drawRect({0, 20, 10, 30});
2959 main_receiver.
drawRect({20, 20, 30, 30});
2965 main->Dispatch(ToReceiver(culling_builder), cull_rect);
2979 SkIRect cull_rect = {11, 11, 19, 19};
2982 auto expected = expected_builder.
Build();
2984 test(cull_rect, expected);
2988 SkIRect cull_rect = {9, 9, 19, 19};
2991 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
2992 expected_receiver.
drawRect({0, 0, 10, 10});
2993 auto expected = expected_builder.
Build();
2995 test(cull_rect, expected);
2999 SkIRect cull_rect = {11, 9, 21, 19};
3002 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3003 expected_receiver.
drawRect({20, 0, 30, 10});
3004 auto expected = expected_builder.
Build();
3006 test(cull_rect, expected);
3010 SkIRect cull_rect = {9, 11, 19, 21};
3013 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3014 expected_receiver.
drawRect({0, 20, 10, 30});
3015 auto expected = expected_builder.
Build();
3017 test(cull_rect, expected);
3021 SkIRect cull_rect = {11, 11, 21, 21};
3024 DlOpReceiver& expected_receiver = ToReceiver(expected_builder);
3025 expected_receiver.
drawRect({20, 20, 30, 30});
3026 auto expected = expected_builder.
Build();
3028 test(cull_rect, expected);
3032 SkIRect cull_rect = {9, 9, 21, 21};
3040 builder.DrawCircle({10, 10}, 5,
DlPaint());
3043 builder.DrawRect({5, 5, 15, 15},
DlPaint());
3045 auto display_list = builder.Build();
3047 ASSERT_FALSE(display_list->can_apply_group_opacity());
3054 check_inverted_bounds(renderer,
"DrawRect");
3061 check_inverted_bounds(renderer,
"DrawRoundRect");
3068 check_inverted_bounds(renderer,
"DrawOval");
3075 check_inverted_bounds(renderer,
"DrawRectangularPath");
3082 check_inverted_bounds(renderer,
"DrawOvalPath");
3091 check_inverted_bounds(renderer,
"DrawRoundRectPath Clockwise");
3100 check_inverted_bounds(renderer,
"DrawRoundRectPath Counter-Clockwise");
3106 uint32_t expected_op_count = 0u,
3107 uint32_t expected_total_depth = 0u) {
3109 [init](
const std::string&
name,
3111 uint32_t expected_op_count = 0u,
3112 uint32_t expected_total_depth = 0u) {
3115 init(builder,
paint);
3117 auto list = builder.Build();
3118 if (list->op_count() != expected_op_count) {
3121 ASSERT_EQ(list->op_count(), expected_op_count) <<
name;
3122 EXPECT_EQ(list->total_depth(), expected_total_depth) <<
name;
3123 ASSERT_TRUE(list->bounds().isEmpty()) <<
name;
3126 name +
" DrawColor",
3128 builder.DrawColor(
paint.getColor(),
paint.getBlendMode());
3130 expected_op_count, expected_total_depth);
3132 name +
" DrawPaint",
3134 builder.DrawPaint(
paint);
3136 expected_op_count, expected_total_depth);
3140 builder.DrawRect({10, 10, 20, 20},
paint);
3142 expected_op_count, expected_total_depth);
3144 name +
" Other Draw Ops",
3146 builder.DrawLine({10, 10}, {20, 20},
paint);
3147 builder.DrawOval({10, 10, 20, 20},
paint);
3148 builder.DrawCircle({50, 50}, 20,
paint);
3154 builder.DrawArc({10, 10, 20, 20}, 45, 90,
true,
paint);
3155 SkPoint pts[] = {{10, 10}, {20, 20}};
3156 builder.DrawPoints(PointMode::kLines, 2, pts,
paint);
3161 SkRect{10.0f, 10.0f, 25.0f, 25.0f},
3163 builder.DrawImageNine(
TestImage1, {10, 10, 20, 20},
3166 SkRSXform xforms[] = {{1, 0, 10, 10}, {0, 1, 10, 10}};
3167 SkRect rects[] = {{10, 10, 20, 20}, {10, 20, 30, 20}};
3168 builder.DrawAtlas(
TestImage1, xforms, rects,
nullptr, 2,
3176 builder.DrawDisplayList(TestDisplayList1, paint.getOpacity());
3177 builder.DrawShadow(kTestPath1, paint.getColor(), 1, true, 1);
3180 expected_op_count, expected_total_depth);
3182 name +
" SaveLayer",
3184 builder.SaveLayer(
nullptr, &
paint,
nullptr);
3185 builder.DrawRect({10, 10, 20, 20},
DlPaint());
3188 expected_op_count, expected_total_depth);
3190 name +
" inside Save",
3193 builder.DrawRect({10, 10, 20, 20},
paint);
3196 expected_op_count, expected_total_depth);
3225 builder.ClipPath(
SkPath(), ClipOp::kIntersect,
false);
3231 builder.SaveLayer(
nullptr, &save_paint);
3241 builder.SaveLayer(
nullptr, &save_paint);
3247 builder.SaveLayer(
nullptr, &save_paint);
3250 "Nop inside SaveLayer",
3252 builder.SaveLayer(
nullptr,
nullptr);
3256 run_tests(
"DrawImage inside Culled SaveLayer",
3260 builder.SaveLayer(
nullptr, &save_paint);
3272 explicit Tester(
bool prefer_impeller_paths)
3273 : prefer_impeller_paths_(prefer_impeller_paths) {}
3275 bool PrefersImpellerPaths()
const override {
3276 return prefer_impeller_paths_;
3282 impeller_draw_path_calls_++;
3286 skia_clip_path_calls_++;
3289 void clipPath(
const CacheablePath&
cache,
ClipOp op,
bool is_aa)
override {
3290 impeller_clip_path_calls_++;
3293 virtual void drawShadow(
const SkPath& sk_path,
3296 bool transparent_occluder,
3298 skia_draw_shadow_calls_++;
3301 virtual void drawShadow(
const CacheablePath&
cache,
3304 bool transparent_occluder,
3306 impeller_draw_shadow_calls_++;
3309 int skia_draw_path_calls()
const {
return skia_draw_path_calls_; }
3310 int skia_clip_path_calls()
const {
return skia_draw_path_calls_; }
3311 int skia_draw_shadow_calls()
const {
return skia_draw_path_calls_; }
3312 int impeller_draw_path_calls()
const {
return impeller_draw_path_calls_; }
3313 int impeller_clip_path_calls()
const {
return impeller_draw_path_calls_; }
3314 int impeller_draw_shadow_calls()
const {
return impeller_draw_path_calls_; }
3317 const bool prefer_impeller_paths_;
3318 int skia_draw_path_calls_ = 0;
3319 int skia_clip_path_calls_ = 0;
3320 int skia_draw_shadow_calls_ = 0;
3321 int impeller_draw_path_calls_ = 0;
3322 int impeller_clip_path_calls_ = 0;
3323 int impeller_draw_shadow_calls_ = 0;
3329 ClipOp::kIntersect,
true);
3332 auto display_list = builder.Build();
3335 Tester skia_tester(
false);
3336 display_list->Dispatch(skia_tester);
3337 EXPECT_EQ(skia_tester.skia_draw_path_calls(), 1);
3338 EXPECT_EQ(skia_tester.skia_clip_path_calls(), 1);
3339 EXPECT_EQ(skia_tester.skia_draw_shadow_calls(), 1);
3340 EXPECT_EQ(skia_tester.impeller_draw_path_calls(), 0);
3341 EXPECT_EQ(skia_tester.impeller_clip_path_calls(), 0);
3342 EXPECT_EQ(skia_tester.impeller_draw_shadow_calls(), 0);
3346 Tester impeller_tester(
true);
3347 display_list->Dispatch(impeller_tester);
3348 EXPECT_EQ(impeller_tester.skia_draw_path_calls(), 0);
3349 EXPECT_EQ(impeller_tester.skia_clip_path_calls(), 0);
3350 EXPECT_EQ(impeller_tester.skia_draw_shadow_calls(), 0);
3351 EXPECT_EQ(impeller_tester.impeller_draw_path_calls(), 1);
3352 EXPECT_EQ(impeller_tester.impeller_clip_path_calls(), 1);
3353 EXPECT_EQ(impeller_tester.impeller_draw_shadow_calls(), 1);
3366 expected_.emplace_back(BoundsExpectation{
3374 bool clipped =
false) {
3380 expected_.emplace_back(BoundsExpectation{
3390 ASSERT_LT(save_layer_count_, expected_.size());
3391 auto expected = expected_[save_layer_count_];
3392 EXPECT_EQ(
options.bounds_from_caller(),
3393 expected.options.bounds_from_caller())
3394 <<
"expected bounds index " << save_layer_count_;
3395 EXPECT_EQ(
options.content_is_clipped(),
3396 expected.options.content_is_clipped())
3397 <<
"expected bounds index " << save_layer_count_;
3402 EXPECT_EQ(bounds, expected.bounds)
3403 <<
"expected bounds index " << save_layer_count_;
3405 save_layer_count_++;
3409 return save_layer_count_ == expected_.size();
3413 struct BoundsExpectation {
3418 std::vector<BoundsExpectation> expected_;
3419 size_t save_layer_count_ = 0;
3426 builder.SaveLayer(
nullptr,
nullptr);
3428 builder.DrawRect(rect,
DlPaint());
3431 auto display_list = builder.Build();
3435 display_list->Dispatch(expector);
3446 builder.SaveLayer(
nullptr,
nullptr);
3451 auto display_list = builder.Build();
3455 display_list->Dispatch(expector);
3466 builder.SaveLayer(
nullptr,
nullptr);
3471 auto display_list = builder.Build();
3475 display_list->Dispatch(expector);
3486 builder.SaveLayer(
nullptr,
nullptr);
3491 auto display_list = builder.Build();
3495 display_list->Dispatch(expector);
3503 builder.Translate(10.0f, 10.0f);
3504 builder.SaveLayer(
nullptr,
nullptr);
3506 builder.DrawRect(rect,
DlPaint());
3509 auto display_list = builder.Build();
3513 display_list->Dispatch(expector);
3521 builder.Scale(10.0f, 10.0f);
3522 builder.SaveLayer(
nullptr,
nullptr);
3524 builder.DrawRect(rect,
DlPaint());
3527 auto display_list = builder.Build();
3531 display_list->Dispatch(expector);
3539 builder.Rotate(45.0f);
3540 builder.SaveLayer(
nullptr,
nullptr);
3542 builder.DrawRect(rect,
DlPaint());
3545 auto display_list = builder.Build();
3549 display_list->Dispatch(expector);
3558 builder.Scale(10.0f, 10.0f);
3559 builder.SaveLayer(
nullptr,
nullptr);
3560 builder.TransformReset();
3561 builder.Scale(20.0f, 20.0f);
3564 builder.DrawRect(rect,
DlPaint());
3567 auto display_list = builder.Build();
3571 display_list->Dispatch(expector);
3579 builder.SaveLayer(
nullptr,
nullptr);
3581 builder.Translate(10.0f, 10.0f);
3582 builder.DrawRect(rect,
DlPaint());
3585 auto display_list = builder.Build();
3589 display_list->Dispatch(expector);
3597 builder.SaveLayer(
nullptr,
nullptr);
3599 builder.Scale(10.0f, 10.0f);
3600 builder.DrawRect(rect,
DlPaint());
3603 auto display_list = builder.Build();
3608 display_list->Dispatch(expector);
3616 builder.SaveLayer(
nullptr,
nullptr);
3618 builder.Rotate(45.0f);
3619 builder.DrawRect(rect,
DlPaint());
3622 auto display_list = builder.Build();
3627 display_list->Dispatch(expector);
3635 builder.SaveLayer(
nullptr,
nullptr);
3637 builder.SaveLayer(
nullptr,
nullptr);
3639 builder.DrawRect(rect,
DlPaint());
3644 auto display_list = builder.Build();
3649 display_list->Dispatch(expector);
3658 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3660 SkRect clip_rect = rect.makeOutset(100.0f, 100.0f);
3661 ASSERT_NE(clip_rect, rect);
3662 ASSERT_TRUE(clip_rect.
contains(rect));
3665 builder.ClipRect(clip_rect);
3666 builder.SaveLayer(
nullptr, &save_paint);
3668 builder.DrawRect(rect,
DlPaint());
3671 auto display_list = builder.Build();
3675 display_list->Dispatch(expector);
3684 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3686 SkRect clip_rect = rect.makeOutset(100.0f, 100.0f);
3687 ASSERT_NE(clip_rect, rect);
3688 ASSERT_TRUE(clip_rect.
contains(rect));
3691 builder.ClipRect(clip_rect);
3692 builder.SaveLayer(
nullptr,
nullptr);
3694 builder.SaveLayer(
nullptr, &save_paint);
3696 builder.DrawRect(rect,
DlPaint());
3701 auto display_list = builder.Build();
3706 display_list->Dispatch(expector);
3715 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3718 SkRect clip_rect = rect.makeOutset(100.0f, 100.0f);
3719 ASSERT_NE(clip_rect, rect);
3720 ASSERT_TRUE(clip_rect.
contains(rect));
3723 builder.ClipRect(clip_rect);
3724 builder.SaveLayer(
nullptr,
nullptr);
3729 auto display_list = builder.Build();
3733 display_list->Dispatch(expector);
3742 ASSERT_TRUE(
color_filter->modifies_transparent_black());
3744 SkRect clip_rect = rect.makeOutset(100.0f, 100.0f);
3745 ASSERT_NE(clip_rect, rect);
3746 ASSERT_TRUE(clip_rect.
contains(rect));
3749 builder.ClipRect(clip_rect);
3750 builder.SaveLayer(
nullptr,
nullptr);
3755 auto display_list = builder.Build();
3761 display_list->Dispatch(expector);
3770 builder.SaveLayer(&save_rect,
nullptr);
3772 builder.DrawRect(rect,
DlPaint());
3775 auto display_list = builder.Build();
3781 display_list->Dispatch(expector);
3791 builder.SaveLayer(&save_rect,
nullptr);
3793 builder.DrawRect(rect,
DlPaint());
3796 auto display_list = builder.Build();
3802 display_list->Dispatch(expector);
3813 : depth_expectations_(
std::move(expectations)) {}
3818 FAIL() <<
"save(no depth parameter) method should not be called";
3821 void save(uint32_t total_content_depth)
override {
3822 ASSERT_LT(index_, depth_expectations_.size());
3823 EXPECT_EQ(depth_expectations_[index_], total_content_depth)
3824 <<
"at index " << index_;
3833 FAIL() <<
"saveLayer(no depth parameter) method should not be called";
3838 uint32_t total_content_depth,
3840 ASSERT_LT(index_, depth_expectations_.size());
3841 EXPECT_EQ(depth_expectations_[index_], total_content_depth)
3842 <<
"at index " << index_;
3848 std::vector<uint32_t> depth_expectations_;
3854 auto child = child_builder.
Build();
3857 builder.DrawRect({10, 10, 20, 20},
DlPaint());
3861 builder.Translate(5, 5);
3862 builder.DrawRect({10, 10, 20, 20},
DlPaint());
3864 builder.DrawDisplayList(child, 1.0f);
3866 builder.SaveLayer(
nullptr,
nullptr);
3868 builder.DrawRect({12, 12, 22, 22},
DlPaint());
3869 builder.DrawRect({14, 14, 24, 24},
DlPaint());
3873 builder.DrawRect({16, 16, 26, 26},
DlPaint());
3874 builder.DrawRect({18, 18, 28, 28},
DlPaint());
3878 builder.DrawRect({16, 16, 26, 26},
DlPaint());
3879 builder.DrawRect({18, 18, 28, 28},
DlPaint());
3880 auto display_list = builder.Build();
3882 EXPECT_EQ(display_list->total_depth(), 11u);
3885 display_list->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 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 SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr) override
sk_sp< DisplayList > Build()
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
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)
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 setPathEffect(const DlPathEffect *effect)=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 DlPathEffect > getPathEffect() 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_bounds_from_caller() const
static const SaveLayerOptions kWithAttributes
SaveLayerOptions with_content_is_clipped() const
void saveLayer(const SkRect &bounds, const SaveLayerOptions &options, uint32_t total_content_depth, const DlImageFilter *backdrop) override
void saveLayer(const SkRect &bounds, SaveLayerOptions options, const DlImageFilter *backdrop) override
void save(uint32_t total_content_depth) override
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
SaveLayerOptionsExpector(const SaveLayerOptions &expected)
void saveLayer(const SkRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop) override
SaveLayerOptionsExpector(std::vector< SaveLayerOptions > expected)
#define RUN_TESTS2(body, expect)
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_DISALLOW_COPY_AND_ASSIGN(TypeName)
static void draw_rect(SkCanvas *canvas, SkImage *, const SkRect &r, sk_sp< SkImageFilter > imf)
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)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
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 std::vector< testing::DisplayListInvocationGroup > allGroups
static constexpr SkPoint kTestPoints[2]
static const SkRRect kTestRRect
static void test_rtree(const sk_sp< const DlRTree > &rtree, const SkRect &query, std::vector< SkRect > expected_rects, const std::vector< int > &expected_indices)
static const std::shared_ptr< DlPathEffect > kTestPathEffect1
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
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
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
@ kNormal
fuzzy inside and outside
@ kColorBurn
darken destination to reflect source
@ kSrcOver
r = s + (1-sa)*d
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
SkRect makeOutset(float dx, float dy) const
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()
uint32_t adjust_render_op_depth_cost(uint32_t previous_cost)
uint32_t depth_accumulated(uint32_t depth_scale=1u)
void Invoke(DlOpReceiver &builder)
#define EXPECT_TRUE(handle)