1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkTypes.h"
9
10 #if !defined(SK_BUILD_FOR_GOOGLE3)
11
12 #include "SkRect.h"
13 #include "SkRectPriv.h"
14 #include "SkSGColor.h"
15 #include "SkSGDraw.h"
16 #include "SkSGGroup.h"
17 #include "SkSGInvalidationController.h"
18 #include "SkSGRect.h"
19 #include "SkSGTransform.h"
20 #include "SkTo.h"
21
22 #include "Test.h"
23
24 #include <vector>
25
check_inval(skiatest::Reporter * reporter,const sk_sp<sksg::Node> & root,const SkRect & expected_bounds,const SkRect & expected_inval_bounds,const std::vector<SkRect> * expected_damage)26 static void check_inval(skiatest::Reporter* reporter, const sk_sp<sksg::Node>& root,
27 const SkRect& expected_bounds,
28 const SkRect& expected_inval_bounds,
29 const std::vector<SkRect>* expected_damage) {
30 sksg::InvalidationController ic;
31 const auto bbox = root->revalidate(&ic, SkMatrix::I());
32
33 if (0) {
34 SkDebugf("** bbox: [%f %f %f %f], ibbox: [%f %f %f %f]\n",
35 bbox.fLeft, bbox.fTop, bbox.fRight, bbox.fBottom,
36 ic.bounds().left(), ic.bounds().top(), ic.bounds().right(), ic.bounds().bottom());
37 }
38
39 REPORTER_ASSERT(reporter, bbox == expected_bounds);
40 REPORTER_ASSERT(reporter, ic.bounds() == expected_inval_bounds);
41
42 if (expected_damage) {
43 const auto damage_count = SkTo<size_t>(ic.end() - ic.begin());
44 REPORTER_ASSERT(reporter, expected_damage->size() == damage_count);
45 for (size_t i = 0; i < std::min(expected_damage->size(), damage_count); ++i) {
46 const auto r1 = (*expected_damage)[i],
47 r2 = ic.begin()[i];
48 if (0) {
49 SkDebugf("*** expected inval: [%f %f %f %f], actual: [%f %f %f %f]\n",
50 r1.left(), r1.top(), r1.right(), r1.bottom(),
51 r2.left(), r2.top(), r2.right(), r2.bottom());
52 }
53 REPORTER_ASSERT(reporter, r1 == r2);
54 }
55 }
56 }
57
inval_test1(skiatest::Reporter * reporter)58 static void inval_test1(skiatest::Reporter* reporter) {
59 auto color = sksg::Color::Make(0xff000000);
60 auto r1 = sksg::Rect::Make(SkRect::MakeWH(100, 100)),
61 r2 = sksg::Rect::Make(SkRect::MakeWH(100, 100));
62 auto grp = sksg::Group::Make();
63 auto matrix = sksg::Matrix<SkMatrix>::Make(SkMatrix::I());
64 auto root = sksg::TransformEffect::Make(grp, matrix);
65
66 grp->addChild(sksg::Draw::Make(r1, color));
67 grp->addChild(sksg::Draw::Make(r2, color));
68
69 {
70 // Initial revalidation.
71 check_inval(reporter, root,
72 SkRect::MakeWH(100, 100),
73 SkRectPriv::MakeLargeS32(),
74 nullptr);
75 }
76
77 {
78 // Move r2 to (200 100).
79 r2->setL(200); r2->setT(100); r2->setR(300); r2->setB(200);
80 std::vector<SkRect> damage = { {0, 0, 100, 100}, { 200, 100, 300, 200} };
81 check_inval(reporter, root,
82 SkRect::MakeWH(300, 200),
83 SkRect::MakeWH(300, 200),
84 &damage);
85 }
86
87 {
88 // Update the common color.
89 color->setColor(0xffff0000);
90 std::vector<SkRect> damage = { {0, 0, 100, 100}, { 200, 100, 300, 200} };
91 check_inval(reporter, root,
92 SkRect::MakeWH(300, 200),
93 SkRect::MakeWH(300, 200),
94 &damage);
95 }
96
97 {
98 // Shrink r1.
99 r1->setR(50);
100 std::vector<SkRect> damage = { {0, 0, 100, 100}, { 0, 0, 50, 100} };
101 check_inval(reporter, root,
102 SkRect::MakeWH(300, 200),
103 SkRect::MakeWH(100, 100),
104 &damage);
105 }
106
107 {
108 // Update transform.
109 matrix->setMatrix(SkMatrix::MakeScale(2, 2));
110 std::vector<SkRect> damage = { {0, 0, 300, 200}, { 0, 0, 600, 400} };
111 check_inval(reporter, root,
112 SkRect::MakeWH(600, 400),
113 SkRect::MakeWH(600, 400),
114 &damage);
115 }
116
117 {
118 // Shrink r2 under transform.
119 r2->setR(250);
120 std::vector<SkRect> damage = { {400, 200, 600, 400}, { 400, 200, 500, 400} };
121 check_inval(reporter, root,
122 SkRect::MakeWH(500, 400),
123 SkRect::MakeLTRB(400, 200, 600, 400),
124 &damage);
125 }
126 }
127
inval_test2(skiatest::Reporter * reporter)128 static void inval_test2(skiatest::Reporter* reporter) {
129 auto color = sksg::Color::Make(0xff000000);
130 auto rect = sksg::Rect::Make(SkRect::MakeWH(100, 100));
131 auto m1 = sksg::Matrix<SkMatrix>::Make(SkMatrix::I()),
132 m2 = sksg::Matrix<SkMatrix>::Make(SkMatrix::I());
133 auto t1 = sksg::TransformEffect::Make(sksg::Draw::Make(rect, color),
134 sksg::Transform::MakeConcat(m1, m2)),
135 t2 = sksg::TransformEffect::Make(sksg::Draw::Make(rect, color), m1);
136 auto root = sksg::Group::Make();
137 root->addChild(t1);
138 root->addChild(t2);
139
140 {
141 // Initial revalidation.
142 check_inval(reporter, root,
143 SkRect::MakeWH(100, 100),
144 SkRectPriv::MakeLargeS32(),
145 nullptr);
146 }
147
148 {
149 // Update the shared color.
150 color->setColor(0xffff0000);
151 std::vector<SkRect> damage = { {0, 0, 100, 100}, { 0, 0, 100, 100} };
152 check_inval(reporter, root,
153 SkRect::MakeWH(100, 100),
154 SkRect::MakeWH(100, 100),
155 &damage);
156 }
157
158 {
159 // Update m2.
160 m2->setMatrix(SkMatrix::MakeScale(2, 2));
161 std::vector<SkRect> damage = { {0, 0, 100, 100}, { 0, 0, 200, 200} };
162 check_inval(reporter, root,
163 SkRect::MakeWH(200, 200),
164 SkRect::MakeWH(200, 200),
165 &damage);
166 }
167
168 {
169 // Update shared m1.
170 m1->setMatrix(SkMatrix::MakeTrans(100, 100));
171 std::vector<SkRect> damage = { { 0, 0, 200, 200}, // draw1 prev bounds
172 { 100, 100, 300, 300}, // draw1 new bounds
173 { 0, 0, 100, 100}, // draw2 prev bounds
174 { 100, 100, 200, 200} }; // draw2 new bounds
175 check_inval(reporter, root,
176 SkRect::MakeLTRB(100, 100, 300, 300),
177 SkRect::MakeLTRB( 0, 0, 300, 300),
178 &damage);
179 }
180
181 {
182 // Update shared rect.
183 rect->setR(50);
184 std::vector<SkRect> damage = { { 100, 100, 300, 300}, // draw1 prev bounds
185 { 100, 100, 200, 300}, // draw1 new bounds
186 { 100, 100, 200, 200}, // draw2 prev bounds
187 { 100, 100, 150, 200} }; // draw2 new bounds
188 check_inval(reporter, root,
189 SkRect::MakeLTRB(100, 100, 200, 300),
190 SkRect::MakeLTRB(100, 100, 300, 300),
191 &damage);
192 }
193 }
194
inval_group_remove(skiatest::Reporter * reporter)195 static void inval_group_remove(skiatest::Reporter* reporter) {
196 auto draw = sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeWH(100, 100)),
197 sksg::Color::Make(SK_ColorBLACK));
198 auto grp = sksg::Group::Make();
199
200 // Readding the child should not trigger asserts.
201 grp->addChild(draw);
202 grp->removeChild(draw);
203 grp->addChild(draw);
204 }
205
DEF_TEST(SGInvalidation,reporter)206 DEF_TEST(SGInvalidation, reporter) {
207 inval_test1(reporter);
208 inval_test2(reporter);
209 inval_group_remove(reporter);
210 }
211
212 #endif // !defined(SK_BUILD_FOR_GOOGLE3)
213