xref: /aosp_15_r20/external/skia/tests/PathOpsOpRectThreadedTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2012 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 #include "include/core/SkPath.h"
8 #include "include/core/SkPathTypes.h"
9 #include "include/core/SkScalar.h"
10 #include "include/core/SkString.h"
11 #include "include/core/SkTypes.h"
12 #include "include/pathops/SkPathOps.h"
13 #include "include/private/base/SkTDArray.h"
14 #include "src/pathops/SkPathOpsDebug.h"
15 #include "tests/PathOpsDebug.h"
16 #include "tests/PathOpsExtendedTest.h"
17 #include "tests/PathOpsThreadedCommon.h"
18 #include "tests/Test.h"
19 
20 #include <atomic>
21 #include <initializer_list>
22 
23 // four rects, of four sizes
24 // for 3 smaller sizes, tall, wide
25     // top upper mid lower bottom aligned (3 bits, 5 values)
26     // same with x (3 bits, 5 values)
27 // not included, square, tall, wide (2 bits)
28 // cw or ccw (1 bit)
29 
30 static int loopNo = 6;
31 static std::atomic<int> gRectsTestNo{0};
32 
testPathOpsRectsMain(PathOpsThreadState * data)33 static void testPathOpsRectsMain(PathOpsThreadState* data)
34 {
35     SkASSERT(data);
36     const SkPathFillType fts[] = { SkPathFillType::kWinding, SkPathFillType::kEvenOdd };
37     PathOpsThreadState& state = *data;
38     SkString pathStr;
39     for (int a = 0 ; a < 6; ++a) {
40         for (int b = a + 1 ; b < 7; ++b) {
41             for (int c = 0 ; c < 6; ++c) {
42                 for (int d = c + 1 ; d < 7; ++d) {
43                     for (auto e : fts) {
44     for (auto f : fts)   {
45         SkPath pathA, pathB;
46         pathA.setFillType((SkPathFillType) e);
47         pathA.addRect(SkIntToScalar(state.fA), SkIntToScalar(state.fA), SkIntToScalar(state.fB),
48                 SkIntToScalar(state.fB), SkPathDirection::kCW);
49         pathA.addRect(SkIntToScalar(state.fC), SkIntToScalar(state.fC), SkIntToScalar(state.fD),
50                 SkIntToScalar(state.fD), SkPathDirection::kCW);
51         pathA.close();
52         pathB.setFillType((SkPathFillType) f);
53         pathB.addRect(SkIntToScalar(a), SkIntToScalar(a), SkIntToScalar(b),
54                 SkIntToScalar(b), SkPathDirection::kCW);
55         pathB.addRect(SkIntToScalar(c), SkIntToScalar(c), SkIntToScalar(d),
56                 SkIntToScalar(d), SkPathDirection::kCW);
57         pathB.close();
58         for (int op = 0 ; op <= kXOR_SkPathOp; ++op)    {
59             if (state.fReporter->verbose()) {
60                 pathStr.printf(
61                         "static void rects%d(skiatest::Reporter* reporter,"
62                         "const char* filename) {\n", loopNo);
63                 pathStr.appendf("    SkPath path, pathB;");
64                 pathStr.appendf("    path.setFillType(SkPathFillType::k%s);\n",
65                         e == SkPathFillType::kWinding ? "Winding" : e == SkPathFillType::kEvenOdd
66                         ? "EvenOdd" : "?UNDEFINED");
67                 pathStr.appendf("    path.addRect(%d, %d, %d, %d,"
68                         " SkPathDirection::kCW);\n", state.fA, state.fA, state.fB, state.fB);
69                 pathStr.appendf("    path.addRect(%d, %d, %d, %d,"
70                         " SkPathDirection::kCW);\n", state.fC, state.fC, state.fD, state.fD);
71                 pathStr.appendf("    pathB.setFillType(SkPathFillType::k%s);\n",
72                         f == SkPathFillType::kWinding ? "Winding" : f == SkPathFillType::kEvenOdd
73                         ? "EvenOdd" : "?UNDEFINED");
74                 pathStr.appendf("    pathB.addRect(%d, %d, %d, %d,"
75                         " SkPathDirection::kCW);\n", a, a, b, b);
76                 pathStr.appendf("    pathB.addRect(%d, %d, %d, %d,"
77                         " SkPathDirection::kCW);\n", c, c, d, d);
78                 pathStr.appendf("    testPathOp(reporter, path, pathB, %s, filename);\n",
79                         SkPathOpsDebug::OpStr((SkPathOp) op));
80                 pathStr.appendf("}\n\n");
81                 state.outputProgress(pathStr.c_str(), (SkPathOp) op);
82             }
83             SkString testName;
84             testName.printf("thread_rects%d", ++gRectsTestNo);
85             if (!testPathOp(state.fReporter, pathA, pathB, (SkPathOp) op, testName.c_str())) {
86                 if (state.fReporter->verbose()) {
87                     ++loopNo;
88                     goto skipToNext;
89                 }
90             }
91             if (PathOpsDebug::gCheckForDuplicateNames) return;
92         }
93     }
94                     }
95 skipToNext: ;
96                 }
97             }
98         }
99     }
100 }
101 
DEF_TEST(PathOpsRectsThreaded,reporter)102 DEF_TEST(PathOpsRectsThreaded, reporter) {
103     initializeTests(reporter, "testOp");
104     PathOpsThreadedTestRunner testRunner(reporter);
105     for (int a = 0; a < 6; ++a) {  // outermost
106         for (int b = a + 1; b < 7; ++b) {
107             for (int c = 0 ; c < 6; ++c) {
108                 for (int d = c + 1; d < 7; ++d) {
109                     *testRunner.fRunnables.append() = new PathOpsThreadedRunnable(
110                             &testPathOpsRectsMain, a, b, c, d, &testRunner);
111                 }
112             }
113             if (!reporter->allowExtendedTest()) goto finish;
114        }
115     }
116 finish:
117     testRunner.render();
118 }
119 
120 static std::atomic<int> gFastTestNo{0};
121 
testPathOpsFastMain(PathOpsThreadState * data)122 static void testPathOpsFastMain(PathOpsThreadState* data)
123 {
124     SkASSERT(data);
125     const SkPathFillType fts[] = {
126         SkPathFillType::kWinding,        SkPathFillType::kEvenOdd,
127         SkPathFillType::kInverseWinding, SkPathFillType::kInverseEvenOdd
128     };
129     PathOpsThreadState& state = *data;
130     SkString pathStr;
131     int step = data->fReporter->allowExtendedTest() ? 2 : 5;
132     for (bool a : { false, true } ) {
133         for (bool b : { false, true } ) {
134             for (int c = 0; c < 6; c += step) {
135                 for (int d = 0; d < 6; d += step) {
136         for (auto e : fts) {
137             for (auto f : fts) {
138         SkPath pathA, pathB;
139         pathA.setFillType(e);
140         if (a) {
141         pathA.addRect(SkIntToScalar(state.fA), SkIntToScalar(state.fA), SkIntToScalar(state.fB) + c,
142                 SkIntToScalar(state.fB), SkPathDirection::kCW);
143         }
144         pathA.close();
145         pathB.setFillType(f);
146         if (b) {
147         pathB.addRect(SkIntToScalar(state.fC), SkIntToScalar(state.fC), SkIntToScalar(state.fD) + d,
148                 SkIntToScalar(state.fD), SkPathDirection::kCW);
149         }
150         pathB.close();
151         const char* fillTypeStr[] = { "Winding", "EvenOdd", "InverseWinding", "InverseEvenOdd" };
152         for (int op = 0; op <= kXOR_SkPathOp; ++op)    {
153             if (state.fReporter->verbose()) {
154                 pathStr.printf(
155                         "static void fast%d(skiatest::Reporter* reporter,"
156                         "const char* filename) {\n", loopNo);
157                 pathStr.appendf("    SkPath path, pathB;");
158                 pathStr.appendf("    path.setFillType(SkPathFillType::k%s);\n", fillTypeStr[(int)e]);
159                 if (a) {
160                     pathStr.appendf("    path.addRect(%d, %d, %d, %d,"
161                           " SkPathDirection::kCW);\n", state.fA, state.fA, state.fB + c, state.fB);
162                 }
163                 pathStr.appendf("    path.setFillType(SkPathFillType::k%s);\n", fillTypeStr[(int)f]);
164                 if (b) {
165                     pathStr.appendf("    path.addRect(%d, %d, %d, %d,"
166                           " SkPathDirection::kCW);\n", state.fC, state.fC, state.fD + d, state.fD);
167                 }
168                 pathStr.appendf("    testPathOp(reporter, path, pathB, %s, filename);\n",
169                         SkPathOpsDebug::OpStr((SkPathOp) op));
170                 pathStr.appendf("}\n\n");
171                 state.outputProgress(pathStr.c_str(), (SkPathOp) op);
172             }
173             SkString testName;
174             testName.printf("fast%d", ++gFastTestNo);
175             if (!testPathOp(state.fReporter, pathA, pathB, (SkPathOp) op, testName.c_str())) {
176                 if (state.fReporter->verbose()) {
177                     ++loopNo;
178                     goto skipToNext;
179                 }
180             }
181             if (PathOpsDebug::gCheckForDuplicateNames) return;
182         }
183     }
184                     }
185 skipToNext: ;
186                 }
187             }
188         }
189     }
190 }
191 
DEF_TEST(PathOpsFastThreaded,reporter)192 DEF_TEST(PathOpsFastThreaded, reporter) {
193     initializeTests(reporter, "testOp");
194     PathOpsThreadedTestRunner testRunner(reporter);
195     int step = reporter->allowExtendedTest() ? 2 : 5;
196     for (int a = 0; a < 6; a += step) {  // outermost
197         for (int b = a + 1; b < 7; b += step) {
198             for (int c = 0 ; c < 6; c += step) {
199                 for (int d = c + 1; d < 7; d += step) {
200                     *testRunner.fRunnables.append() = new PathOpsThreadedRunnable(
201                             &testPathOpsFastMain, a, b, c, d, &testRunner);
202                 }
203             }
204        }
205     }
206     testRunner.render();
207 }
208