1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "PathOpsExtendedTest.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "PathOpsThreadedCommon.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMatrix.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMutex.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRegion.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <stdlib.h>
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_MAC
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <sys/sysctl.h>
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// std::to_string isn't implemented on android
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <sstream>
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T>
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::string std_to_string(T value)
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::ostringstream os ;
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    os << value ;
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return os.str() ;
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot             SkDEBUGPARAMS(bool skipAssert)
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot             SkDEBUGPARAMS(const char* testName));
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SimplifyDebug(const SkPath& one, SkPath* result
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   SkDEBUGPARAMS(bool skipAssert)
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                   SkDEBUGPARAMS(const char* testName));
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char marker[] =
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "</div>\n"
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "\n"
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "<script type=\"text/javascript\">\n"
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "\n"
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "var testDivs = [\n";
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* opStrs[] = {
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "kDifference_SkPathOp",
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "kIntersect_SkPathOp",
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "kUnion_SkPathOp",
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "kXOR_PathOp",
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "kReverseDifference_SkPathOp",
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* opSuffixes[] = {
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "d",
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "i",
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "u",
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "o",
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    "r",
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class ExpectSuccess {
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNo,
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kYes,
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kFlaky
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class SkipAssert {
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNo,
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kYes
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class ExpectMatch {
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNo,
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kYes,
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kFlaky
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void showPathData(const SkPath& path) {
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::RawIter iter(path);
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint8_t verb;
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint firstPt = {0, 0}, lastPt = {0, 0};
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool firstPtSet = false;
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool lastPtSet = true;
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (firstPtSet && lastPtSet && firstPt != lastPt) {
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", lastPt.fX, lastPt.fY,
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            firstPt.fX, firstPt.fY);
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    lastPtSet = false;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                firstPt = pts[0];
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                firstPtSet = true;
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].fY,
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        pts[1].fX, pts[1].fY);
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPt = pts[1];
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPtSet = true;
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPt = pts[2];
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPtSet = true;
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},  //weight=%1.9g\n",
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        iter.conicWeight());
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPt = pts[2];
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPtSet = true;
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        pts[3].fX, pts[3].fY);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPt = pts[3];
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastPtSet = true;
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (firstPtSet && lastPtSet && firstPt != lastPt) {
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", lastPt.fX, lastPt.fY,
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            firstPt.fX, firstPt.fY);
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                firstPtSet = lastPtSet = false;
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDEBUGFAIL("bad verb");
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return;
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (firstPtSet && lastPtSet && firstPt != lastPt) {
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", lastPt.fX, lastPt.fY,
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                firstPt.fX, firstPt.fY);
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid showOp(const SkPathOp op) {
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (op) {
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kDifference_SkPathOp:
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("op difference\n");
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kIntersect_SkPathOp:
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("op intersect\n");
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUnion_SkPathOp:
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("op union\n");
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kXOR_SkPathOp:
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("op xor\n");
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kReverseDifference_SkPathOp:
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("op reverse difference\n");
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        default:
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(0);
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic char hexorator(int x) {
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (x < 10) {
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return x + '0';
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    x -= 10;
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(x < 26);
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return x + 'A';
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid ShowTestName(PathOpsThreadState* state, int a, int b, int c, int d) {
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[0] = hexorator(state->fA);
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[1] = hexorator(state->fB);
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[2] = hexorator(state->fC);
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[3] = hexorator(state->fD);
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[4] = hexorator(a);
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[5] = hexorator(b);
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[6] = hexorator(c);
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[7] = hexorator(d);
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state->fSerialNo[8] = '\0';
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("%s\n", state->fSerialNo);
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (strcmp(state->fSerialNo, state->fKey) == 0) {
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("%s\n", state->fPathStr.c_str());
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst int bitWidth = 64;
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst int bitHeight = 64;
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void scaleMatrix(const SkPath& one, const SkPath& two, SkMatrix& scale) {
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect larger = one.getBounds();
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    larger.join(two.getBounds());
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar largerWidth = larger.width();
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (largerWidth < 4) {
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        largerWidth = 4;
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar largerHeight = larger.height();
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (largerHeight < 4) {
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        largerHeight = 4;
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar hScale = (bitWidth - 2) / largerWidth;
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar vScale = (bitHeight - 2) / largerHeight;
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scale.reset();
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scale.preScale(hScale, vScale);
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    larger.fLeft *= hScale;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    larger.fRight *= hScale;
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    larger.fTop *= vScale;
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    larger.fBottom *= vScale;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : 16000 < larger.fRight ? 16000 - larger.fRight : 0;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0;
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scale.postTranslate(dx, dy);
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int pathsDrawTheSame(SkBitmap& bits, const SkPath& scaledOne, const SkPath& scaledTwo,
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int& error2x2) {
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (bits.width() == 0) {
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bits.allocN32Pixels(bitWidth * 2, bitHeight);
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCanvas canvas(bits);
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawColor(SK_ColorWHITE);
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.save();
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds1 = scaledOne.getBounds();
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawPath(scaledOne, paint);
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.restore();
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.save();
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawPath(scaledTwo, paint);
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.restore();
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int errors2 = 0;
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int errors = 0;
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int y = 0; y < bitHeight - 1; ++y) {
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint32_t* addr1 = bits.getAddr32(0, y);
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint32_t* addr2 = bits.getAddr32(0, y + 1);
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint32_t* addr3 = bits.getAddr32(bitWidth, y);
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int x = 0; x < bitWidth - 1; ++x) {
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // count 2x2 blocks
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bool err = addr1[x] != addr3[x];
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (err) {
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                errors2 += addr1[x + 1] != addr3[x + 1]
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                errors++;
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    error2x2 = errors2;
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return errors;
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int pathsDrawTheSame(const SkPath& one, const SkPath& two, SkBitmap& bits, SkPath& scaledOne,
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath& scaledTwo, int& error2x2) {
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix scale;
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaleMatrix(one, two, scale);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    one.transform(scale, &scaledOne);
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    two.transform(scale, &scaledTwo);
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return pathsDrawTheSame(bits, scaledOne, scaledTwo, error2x2);
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) {
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!drawPaths) {
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds1 = one.getBounds();
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds2 = two.getBounds();
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect larger = bounds1;
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    larger.join(bounds2);
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bits;
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char out[256];
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int bitWidth = SkScalarCeilToInt(larger.width()) + 2;
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (bitWidth * 2 + 1 >= (int) sizeof(out)) {
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int bitHeight = SkScalarCeilToInt(larger.height()) + 2;
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (bitHeight >= (int) sizeof(out)) {
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bits.allocN32Pixels(bitWidth * 2, bitHeight);
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkCanvas canvas(bits);
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawColor(SK_ColorWHITE);
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.save();
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawPath(one, paint);
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.restore();
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.save();
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.drawPath(two, paint);
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    canvas.restore();
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int y = 0; y < bitHeight; ++y) {
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint32_t* addr1 = bits.getAddr32(0, y);
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int x;
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char* outPtr = out;
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (x = 0; x < bitWidth; ++x) {
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *outPtr++ = '|';
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (x = bitWidth; x < bitWidth * 2; ++x) {
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *outPtr++ = '\0';
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("%s\n", out);
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint comparePaths(skiatest::Reporter* reporter, const char* filename, const SkPath& one,
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPath& two, SkBitmap& bitmap) {
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int errors2x2;
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath scaledOne, scaledTwo;
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (void) pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors2x2);
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (errors2x2 == 0) {
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return 0;
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int MAX_ERRORS = 9;
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkTDArray<SkPathOp> gTestOp;
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void showPathOpPath(const char* testName, const SkPath& one, const SkPath& two,
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPath& a, const SkPath& b, const SkPath& scaledOne, const SkPath& scaledTwo,
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPathOp shapeOp, const SkMatrix& scale) {
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT((unsigned) shapeOp < SK_ARRAY_COUNT(opStrs));
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!testName) {
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        testName = "xOp";
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("static void %s_%s(skiatest::Reporter* reporter, const char* filename) {\n",
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        testName, opSuffixes[shapeOp]);
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *gTestOp.append() = shapeOp;
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("    SkPath path, pathB;\n");
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPathOpsDebug::ShowOnePath(a, "path", false);
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPathOpsDebug::ShowOnePath(b, "pathB", false);
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("    testPathOp(reporter, path, pathB, %s, filename);\n", opStrs[shapeOp]);
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("}\n");
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    drawAsciiPaths(scaledOne, scaledTwo, true);
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(compareDebugOut3);
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int comparePaths(skiatest::Reporter* reporter, const char* testName, const SkPath& one,
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPath& scaledOne, const SkPath& two, const SkPath& scaledTwo, SkBitmap& bitmap,
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const SkMatrix& scale,
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ExpectMatch expectMatch) {
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int errors2x2;
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int MAX_ERRORS = 8;
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (void) pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2);
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (ExpectMatch::kNo == expectMatch) {
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (errors2x2 < MAX_ERRORS) {
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return 0;
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (errors2x2 == 0) {
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return 0;
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (ExpectMatch::kYes == expectMatch && errors2x2 >= MAX_ERRORS) {
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAutoMutexAcquire autoM(compareDebugOut3);
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("\n/*");
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, 0);
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf(" */\n");
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return errors2x2 >= MAX_ERRORS ? errors2x2 : 0;
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Default values for when reporter->verbose() is false.
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int testNumber = 55;
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const char* testName = "pathOpTest";
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void appendTestName(const char* nameSuffix, std::string& out) {
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out += testName;
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out += std_to_string(testNumber);
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ++testNumber;
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (nameSuffix) {
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        out.append(nameSuffix);
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void appendTest(const char* pathStr, const char* pathPrefix, const char* nameSuffix,
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       const char* testFunction, bool twoPaths, std::string& out) {
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("\n<div id=\"");
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTestName(nameSuffix, out);
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("\">\n");
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (pathPrefix) {
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        out.append(pathPrefix);
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append(pathStr);
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("</div>\n\n");
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append(marker);
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("    ");
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTestName(nameSuffix, out);
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append(",\n\n\n");
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("static void ");
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTestName(nameSuffix, out);
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("(skiatest::Reporter* reporter) {\n    SkPath path");
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (twoPaths) {
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        out.append(", pathB");
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append(";\n");
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (pathPrefix) {
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        out.append(pathPrefix);
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out += pathStr;
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out += "    ";
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out += testFunction;
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("static void (*firstTest)() = ");
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTestName(nameSuffix, out);
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append(";\n\n");
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("static struct {\n");
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("    void (*fun)();\n");
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("    const char* str;\n");
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("} tests[] = {\n");
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("    TEST(");
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTestName(nameSuffix, out);
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    out.append("),\n");
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(simplifyDebugOut);
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state,
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  const char* pathStr) {
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.setFillType(fillType);
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state.fReporter->bumpTestCount();
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!Simplify(path, &out)) {
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("%s did not expect failure\n", __FUNCTION__);
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(state.fReporter, 0);
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!state.fReporter->verbose()) {
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int result = comparePaths(state.fReporter, nullptr, path, out, *state.fBitmap);
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (result) {
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAutoMutexAcquire autoM(simplifyDebugOut);
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        std::string str;
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* pathPrefix = nullptr;
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* nameSuffix = nullptr;
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fillType == SkPath::kEvenOdd_FillType) {
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            pathPrefix = "    path.setFillType(SkPath::kEvenOdd_FillType);\n";
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            nameSuffix = "x";
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char testFunction[] = "testSimplify(reporter, path);";
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        appendTest(pathStr, pathPrefix, nameSuffix, testFunction, false, str);
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("%s", str.c_str());
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(state.fReporter, 0);
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    state.fReporter->bumpTestCount();
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return result == 0;
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool inner_simplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename,
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch) {
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 && DEBUG_SHOW_TEST_NAME
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    showPathData(path);
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath out;
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!SimplifyDebug(path, &out  SkDEBUGPARAMS(SkipAssert::kYes == skipAssert)
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDEBUGPARAMS(testName))) {
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ExpectSuccess::kYes == expectSuccess) {
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("%s did not expect %s failure\n", __FUNCTION__, filename);
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ExpectSuccess::kNo == expectSuccess) {
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("%s %s unexpected success\n", __FUNCTION__, filename);
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int errors = comparePaths(reporter, filename, path, out, bitmap);
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (ExpectMatch::kNo == expectMatch) {
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!errors) {
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("%s failing test %s now succeeds\n", __FUNCTION__, filename);
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (ExpectMatch::kYes == expectMatch && errors) {
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, 0);
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    reporter->bumpTestCount();
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return errors == 0;
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename) {
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return inner_simplify(reporter, path, filename, ExpectSuccess::kYes, SkipAssert::kNo,
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ExpectMatch::kYes);
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testSimplifyFuzz(skiatest::Reporter* reporter, const SkPath& path, const char* filename) {
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return inner_simplify(reporter, path, filename, ExpectSuccess::kFlaky, SkipAssert::kYes,
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ExpectMatch::kFlaky);
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testSimplifyCheck(skiatest::Reporter* reporter, const SkPath& path, const char* filename,
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool checkFail) {
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return inner_simplify(reporter, path, filename, checkFail ?
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ExpectSuccess::kYes : ExpectSuccess::kNo, SkipAssert::kNo, ExpectMatch::kNo);
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void showName(const SkPath& a, const SkPath& b, const SkPathOp shapeOp) {
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("\n");
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    showPathData(a);
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    showOp(shapeOp);
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    showPathData(b);
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPathOp shapeOp, const char* testName, ExpectSuccess expectSuccess,
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkipAssert skipAssert, ExpectMatch expectMatch) {
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 && DEBUG_SHOW_TEST_NAME
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    showName(a, b, shapeOp);
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath out;
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!OpDebug(a, b, shapeOp, &out  SkDEBUGPARAMS(SkipAssert::kYes == skipAssert)
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDEBUGPARAMS(testName))) {
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ExpectSuccess::kYes == expectSuccess) {
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("%s %s did not expect failure\n", __FUNCTION__, testName);
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, 0);
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ExpectSuccess::kNo == expectSuccess) {
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDebugf("%s %s unexpected success\n", __FUNCTION__, testName);
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, 0);
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!reporter->verbose()) {
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath pathOut, scaledPathOut;
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRegion rgnA, rgnB, openClip, rgnOut;
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    openClip.setRect(-16000, -16000, 16000, 16000);
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    rgnA.setPath(a, openClip);
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    rgnB.setPath(b, openClip);
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp);
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    rgnOut.getBoundaryPath(&pathOut);
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix scale;
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaleMatrix(a, b, scale);
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath scaledA, scaledB;
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledA.addPath(a, scale);
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledA.setFillType(a.getFillType());
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledB.addPath(b, scale);
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledB.setFillType(b.getFillType());
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledRgnA.setPath(scaledA, openClip);
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledRgnB.setPath(scaledB, openClip);
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp);
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledRgnOut.getBoundaryPath(&scaledPathOut);
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkBitmap bitmap;
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath scaledOut;
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledOut.addPath(out, scale);
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    scaledOut.setFillType(out.getFillType());
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap,
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            a, b, shapeOp, scale, expectMatch);
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    reporter->bumpTestCount();
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return result == 0;
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPathOp shapeOp, const char* testName) {
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return innerPathOp(reporter, a, b, shapeOp, testName, ExpectSuccess::kYes, SkipAssert::kNo,
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ExpectMatch::kYes);
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testPathOpCheck(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPathOp shapeOp, const char* testName, bool checkFail) {
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return innerPathOp(reporter, a, b, shapeOp, testName, checkFail ?
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ExpectSuccess::kYes : ExpectSuccess::kNo, SkipAssert::kNo, ExpectMatch::kNo);
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testPathOpFuzz(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkPathOp shapeOp, const char* testName) {
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return innerPathOp(reporter, a, b, shapeOp, testName, ExpectSuccess::kFlaky, SkipAssert::kYes,
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ExpectMatch::kFlaky);
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool testPathOpFail(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                 const SkPathOp shapeOp, const char* testName) {
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    showName(a, b, shapeOp);
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath orig;
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    orig.lineTo(54, 43);
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath out = orig;
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (Op(a, b, shapeOp, &out) ) {
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("%s test is expected to fail\n", __FUNCTION__);
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, 0);
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(out == orig);
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(gMutex);
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid initializeTests(skiatest::Reporter* reporter, const char* test) {
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (reporter->verbose()) {
624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAutoMutexAcquire lock(gMutex);
625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        testName = test;
626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t testNameSize = strlen(test);
627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkFILEStream inFile("../../experimental/Intersection/op.htm");
628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (inFile.isValid()) {
629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkTDArray<char> inData;
630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            inData.setCount((int) inFile.getLength());
631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            size_t inLen = inData.count();
632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            inFile.read(inData.begin(), inLen);
633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            inFile.close();
634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            char* insert = strstr(inData.begin(), marker);
635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (insert) {
636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                insert += sizeof(marker) - 1;
637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                testNumber = atoi(numLoc) + 1;
639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid PathOpsThreadState::outputProgress(const char* pathStr, SkPath::FillType pathFillType) {
645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char testFunction[] = "testSimplify(path);";
646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* pathPrefix = nullptr;
647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nameSuffix = nullptr;
648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (pathFillType == SkPath::kEvenOdd_FillType) {
649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        pathPrefix = "    path.setFillType(SkPath::kEvenOdd_FillType);\n";
650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        nameSuffix = "x";
651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTest(pathStr, pathPrefix, nameSuffix, testFunction, false, fPathStr);
653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid PathOpsThreadState::outputProgress(const char* pathStr, SkPathOp op) {
656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char testFunction[] = "testOp(path);";
657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT((size_t) op < SK_ARRAY_COUNT(opSuffixes));
658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nameSuffix = opSuffixes[op];
659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    appendTest(pathStr, nullptr, nameSuffix, testFunction, true, fPathStr);
660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid RunTestSet(skiatest::Reporter* reporter, TestDesc tests[], size_t count,
663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                void (*firstTest)(skiatest::Reporter* , const char* filename),
664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                void (*skipTest)(skiatest::Reporter* , const char* filename),
665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                void (*stopTest)(skiatest::Reporter* , const char* filename), bool reverse) {
666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t index;
667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (firstTest) {
668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        index = count - 1;
669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (index > 0 && tests[index].fun != firstTest) {
670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --index;
671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf("\n<div id=\"%s\">\n", tests[index].str);
674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        (*tests[index].fun)(reporter, tests[index].str);
676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (tests[index].fun == stopTest) {
677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    index = reverse ? count - 1 : 0;
681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t last = reverse ? 0 : count - 1;
682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool foundSkip = !skipTest;
683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (tests[index].fun == skipTest) {
685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            foundSkip = true;
686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (foundSkip && tests[index].fun != firstTest) {
688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #if DEBUG_SHOW_TEST_NAME
689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("\n<div id=\"%s\">\n", tests[index].str);
690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #endif
691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot             (*tests[index].fun)(reporter, tests[index].str);
692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (tests[index].fun == stopTest || index == last) {
694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        index += reverse ? -1 : 1;
697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (true);
698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_SHOW_TEST_NAME
699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf(
700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "\n"
701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "</div>\n"
702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "\n"
703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "<script type=\"text/javascript\">\n"
704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "\n"
705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "var testDivs = [\n"
706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    );
707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    index = reverse ? count - 1 : 0;
708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    last = reverse ? 0 : count - 1;
709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    foundSkip = !skipTest;
710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (tests[index].fun == skipTest) {
712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            foundSkip = true;
713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (foundSkip && tests[index].fun != firstTest) {
715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("    %s,\n", tests[index].str);
716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (tests[index].fun == stopTest || index == last) {
718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        index += reverse ? -1 : 1;
721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (true);
722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
724