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/SkString.h"
8#include "tests/PathOpsDebug.h"
9#include "tests/PathOpsExtendedTest.h"
10#include "tests/PathOpsThreadedCommon.h"
11
12#include <atomic>
13
14static int loopNo = 158;
15static std::atomic<int> gCubicsTestNo{0};
16
17static void testOpCubicsMain(PathOpsThreadState* data) {
18    SkASSERT(data);
19    const SkPathFillType fts[] = { SkPathFillType::kWinding, SkPathFillType::kEvenOdd };
20    PathOpsThreadState& state = *data;
21    SkString pathStr;
22    for (int a = 0 ; a < 6; ++a) {
23        for (int b = a + 1 ; b < 7; ++b) {
24            for (int c = 0 ; c < 6; ++c) {
25                for (int d = c + 1 ; d < 7; ++d) {
26                    for (auto e : fts) {
27    for (auto f : fts) {
28        SkPath pathA, pathB;
29        pathA.setFillType((SkPathFillType) e);
30        pathA.moveTo(SkIntToScalar(state.fA), SkIntToScalar(state.fB));
31        pathA.cubicTo(SkIntToScalar(state.fC), SkIntToScalar(state.fD), SkIntToScalar(b),
32                SkIntToScalar(a), SkIntToScalar(d), SkIntToScalar(c));
33        pathA.close();
34        pathB.setFillType((SkPathFillType) f);
35        pathB.moveTo(SkIntToScalar(a), SkIntToScalar(b));
36        pathB.cubicTo(SkIntToScalar(c), SkIntToScalar(d), SkIntToScalar(state.fB),
37                SkIntToScalar(state.fA), SkIntToScalar(state.fD), SkIntToScalar(state.fC));
38        pathB.close();
39        for (int op = 0 ; op <= kXOR_SkPathOp; ++op)    {
40            if (state.fReporter->verbose()) {
41                pathStr.printf("static void cubicOp%d(skiatest::Reporter* reporter,"
42                        " const char* filename) {\n", loopNo);
43                pathStr.appendf("    SkPath path, pathB;\n");
44                pathStr.appendf("    path.setFillType(SkPathFillType::k%s);\n",
45                        e == SkPathFillType::kWinding ? "Winding" : e == SkPathFillType::kEvenOdd
46                        ? "EvenOdd" : "?UNDEFINED");
47                pathStr.appendf("    path.moveTo(%d,%d);\n", state.fA, state.fB);
48                pathStr.appendf("    path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.fC, state.fD,
49                        b, a, d, c);
50                pathStr.appendf("    path.close();\n");
51                pathStr.appendf("    pathB.setFillType(SkPathFillType::k%s);\n",
52                        f == SkPathFillType::kWinding ? "Winding" : f == SkPathFillType::kEvenOdd
53                        ? "EvenOdd" : "?UNDEFINED");
54                pathStr.appendf("    pathB.moveTo(%d,%d);\n", a, b);
55                pathStr.appendf("    pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d,
56                        state.fB, state.fA, state.fD, state.fC);
57                pathStr.appendf("    pathB.close();\n");
58                pathStr.appendf("    testPathOp(reporter, path, pathB, %s, filename);\n",
59                        SkPathOpsDebug::OpStr((SkPathOp) op));
60                pathStr.appendf("}\n");
61                state.outputProgress(pathStr.c_str(), (SkPathOp) op);
62            }
63            SkString testName;
64            testName.printf("thread_cubics%d", ++gCubicsTestNo);
65            if (!testPathOp(state.fReporter, pathA, pathB, (SkPathOp) op, testName.c_str())) {
66                if (state.fReporter->verbose()) {
67                    ++loopNo;
68                    goto skipToNext;
69                }
70            }
71            if (PathOpsDebug::gCheckForDuplicateNames) return;
72        }
73    }
74                    }
75skipToNext: ;
76                }
77            }
78        }
79    }
80}
81
82DEF_TEST(PathOpsOpCubicsThreaded, reporter) {
83    initializeTests(reporter, "cubicOp");
84    PathOpsThreadedTestRunner testRunner(reporter);
85    for (int a = 0; a < 6; ++a) {  // outermost
86        for (int b = a + 1; b < 7; ++b) {
87            for (int c = 0 ; c < 6; ++c) {
88                for (int d = c + 1; d < 7; ++d) {
89                    *testRunner.fRunnables.append() =
90                            new PathOpsThreadedRunnable(&testOpCubicsMain, a, b, c, d, &testRunner);
91                }
92            }
93            if (!reporter->allowExtendedTest()) goto finish;
94        }
95    }
96finish:
97    testRunner.render();
98}
99