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