19e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com/*
29e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com * Copyright 2012 Google Inc.
39e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com *
49e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
59e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com * found in the LICENSE file.
69e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com */
764334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com
8d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com#include "DataTypes.h"
9cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com#include "EdgeWalker_Test.h"
10cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com#include "Intersection_Tests.h"
11cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com#include "SkBitmap.h"
12cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com#include "SkCanvas.h"
1345a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com#include "SkMatrix.h"
14cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com#include "SkPaint.h"
1559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#include "SkStream.h"
1659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
17fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com#include <algorithm>
1859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#include <errno.h>
1959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#include <pthread.h>
2059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#include <unistd.h>
2159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#include <sys/types.h>
2259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#include <sys/sysctl.h>
23cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com
2478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#undef SkASSERT
2578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
2678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com
2759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comstatic const char marker[] =
2859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    "</div>\n"
2959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    "\n"
3059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    "<script type=\"text/javascript\">\n"
3159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    "\n"
3259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    "var testDivs = [\n";
3324bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com
344eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.comstatic const char* opStrs[] = {
354eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "kDifference_Op",
364eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "kIntersect_Op",
374eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "kUnion_Op",
384eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "kXor_Op",
394eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com};
404eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com
414eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.comstatic const char* opSuffixes[] = {
424eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "d",
434eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "i",
444eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "u",
454eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    "x",
464eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com};
474eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com
4824bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.comstatic const char preferredFilename[] = "/flash/debug/XX.txt";
4924bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.comstatic const char backupFilename[] = "../../experimental/Intersection/debugXX.txt";
5059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
512e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.comstatic bool gShowPath = false;
52198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.comstatic bool gComparePaths = true;
53c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.comstatic bool gShowOutputProgress = false;
544eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.comstatic bool gComparePathsAssert = true;
5559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comstatic bool gPathStrAssert = true;
566aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.comstatic bool gUsePhysicalFiles = false;
57cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com
588f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.comstatic void showPathContour(SkPath::Iter& iter) {
59cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    uint8_t verb;
60cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkPoint pts[4];
61cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
62cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        switch (verb) {
63cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            case SkPath::kMove_Verb:
64beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com                SkDebugf("path.moveTo(%1.9g,%1.9g);\n", pts[0].fX, pts[0].fY);
65cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                continue;
66cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            case SkPath::kLine_Verb:
67beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com                SkDebugf("path.lineTo(%1.9g,%1.9g);\n", pts[1].fX, pts[1].fY);
68cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                break;
69cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            case SkPath::kQuad_Verb:
70beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com                SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
71cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                    pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
72cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                break;
73cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            case SkPath::kCubic_Verb:
74beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com                SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
75beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com                    pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
76cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                break;
77cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            case SkPath::kClose_Verb:
78cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                SkDebugf("path.close();\n");
798f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com                break;
80cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            default:
81cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                SkDEBUGFAIL("bad verb");
82cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com                return;
83cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        }
84cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    }
85cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com}
86cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com
874eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.comvoid showPath(const SkPath& path, const char* str) {
884eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    SkDebugf("%s\n", !str ? "original:" : str);
89d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    showPath(path);
90d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com}
91d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com
92d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.comvoid showPath(const SkPath& path) {
934eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    SkPath::Iter iter(path, true);
948f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com    int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0;
958f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com    if (rectCount > 0) {
968f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        SkTDArray<SkRect> rects;
978f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        SkTDArray<SkPath::Direction> directions;
988f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        rects.setCount(rectCount);
998f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        directions.setCount(rectCount);
1008f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        path.rectContours(rects.begin(), directions.begin());
1018f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        for (int contour = 0; contour < rectCount; ++contour) {
1028f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com            const SkRect& rect = rects[contour];
1034eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
1044eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com                    rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
1054eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com                    ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
1064eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        }
1078f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com        return;
1084eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    }
1098f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com    iter.setPath(path, true);
1108f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com    showPathContour(iter);
1114eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com}
1124eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com
113d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.comvoid showPathData(const SkPath& path) {
114d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    SkPath::Iter iter(path, true);
115d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    uint8_t verb;
116d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    SkPoint pts[4];
117d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
118d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        switch (verb) {
119d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            case SkPath::kMove_Verb:
120d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                continue;
121d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            case SkPath::kLine_Verb:
122d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY);
123d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                break;
124d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            case SkPath::kQuad_Verb:
125d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
126d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                    pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
127d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                break;
128d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            case SkPath::kCubic_Verb:
129d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
130d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                    pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, pts[3].fX, pts[3].fY);
131d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                break;
132d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            case SkPath::kClose_Verb:
133d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                break;
134d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            default:
135d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                SkDEBUGFAIL("bad verb");
136d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com                return;
137d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        }
138d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    }
139d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com}
140d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com
141d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.comvoid showOp(const ShapeOp op) {
142d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    switch (op) {
143d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        case kDifference_Op:
144d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            SkDebugf("op difference\n");
145d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            break;
146d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        case kIntersect_Op:
147d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            SkDebugf("op intersect\n");
148d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            break;
149d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        case kUnion_Op:
150d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            SkDebugf("op union\n");
151d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            break;
152d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        case kXor_Op:
153d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            SkDebugf("op xor\n");
154d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            break;
155d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com        default:
156d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com            SkASSERT(0);
157d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    }
158d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com}
159d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com
16045a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.comstatic void showPath(const SkPath& path, const char* str, const SkMatrix& scale) {
16145a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    SkPath scaled;
16245a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    SkMatrix inverse;
16345a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    bool success = scale.invert(&inverse);
16445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    if (!success) SkASSERT(0);
16545a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    path.transform(inverse, &scaled);
16645a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    showPath(scaled, str);
16745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com}
16845a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com
16945a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.comconst int bitWidth = 64;
17045a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.comconst int bitHeight = 64;
17122b460cef604c4737b9e221901e1940681255c01skia.committer@gmail.com
17286adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.comstatic void scaleMatrix(const SkPath& one, const SkPath& two, SkMatrix& scale) {
173c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    SkRect larger = one.getBounds();
174c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    larger.join(two.getBounds());
175c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    SkScalar largerWidth = larger.width();
176c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    if (largerWidth < 4) {
177c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        largerWidth = 4;
178c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    }
179c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    SkScalar largerHeight = larger.height();
180c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    if (largerHeight < 4) {
181c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        largerHeight = 4;
182c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    }
183c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    SkScalar hScale = (bitWidth - 2) / largerWidth;
184c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    SkScalar vScale = (bitHeight - 2) / largerHeight;
185c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    scale.reset();
186c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    scale.preScale(hScale, vScale);
18786adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com}
188be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.com
18986adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.comstatic int pathsDrawTheSame(SkBitmap& bits, const SkPath& scaledOne, const SkPath& scaledTwo,
19086adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com        int& error2x2) {
19186adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    if (bits.width() == 0) {
19286adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com        bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
19386adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com        bits.allocPixels();
19486adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    }
195be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.com    SkCanvas canvas(bits);
196cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawColor(SK_ColorWHITE);
197cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkPaint paint;
198cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.save();
19986adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    const SkRect& bounds1 = scaledOne.getBounds();
200cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
201c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    canvas.drawPath(scaledOne, paint);
202cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.restore();
203cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.save();
204cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
205c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    canvas.drawPath(scaledTwo, paint);
206cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.restore();
207c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    int errors2 = 0;
208198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com    int errors = 0;
209c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    for (int y = 0; y < bitHeight - 1; ++y) {
210cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        uint32_t* addr1 = bits.getAddr32(0, y);
211c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        uint32_t* addr2 = bits.getAddr32(0, y + 1);
212c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        uint32_t* addr3 = bits.getAddr32(bitWidth, y);
213c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
214c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        for (int x = 0; x < bitWidth - 1; ++x) {
215c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com            // count 2x2 blocks
216c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com            bool err = addr1[x] != addr3[x];
217c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com            if (err) {
218c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com                errors2 += addr1[x + 1] != addr3[x + 1]
219c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com                        && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
220c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com                errors++;
221c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com            }
222cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        }
223cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    }
224d1688744d537d928699b6069f99c4470a0f6e772caryclark@google.com    if (errors2 >= 6 || errors > 160) {
225c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        SkDebugf("%s errors2=%d errors=%d\n", __FUNCTION__, errors2, errors);
226c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    }
227c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    error2x2 = errors2;
228198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com    return errors;
229198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com}
230198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com
23186adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.comstatic int pathsDrawTheSame(const SkPath& one, const SkPath& two, SkBitmap& bits, SkPath& scaledOne,
23286adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com        SkPath& scaledTwo, int& error2x2) {
23386adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    SkMatrix scale;
23486adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaleMatrix(one, two, scale);
23586adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    one.transform(scale, &scaledOne);
23686adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    two.transform(scale, &scaledTwo);
23786adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    return pathsDrawTheSame(bits, scaledOne, scaledTwo, error2x2);
23886adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com}
23986adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com
240c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.combool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) {
241cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    if (!drawPaths) {
242752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com        return true;
243cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    }
244cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    const SkRect& bounds1 = one.getBounds();
245cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    const SkRect& bounds2 = two.getBounds();
246cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkRect larger = bounds1;
247cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    larger.join(bounds2);
248cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkBitmap bits;
249752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    char out[256];
250cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    int bitWidth = SkScalarCeil(larger.width()) + 2;
251752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    if (bitWidth * 2 + 1 >= (int) sizeof(out)) {
252752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com        return false;
253752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    }
254cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    int bitHeight = SkScalarCeil(larger.height()) + 2;
255752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    if (bitHeight >= (int) sizeof(out)) {
256752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com        return false;
257752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    }
258cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
259cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    bits.allocPixels();
260cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkCanvas canvas(bits);
261cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawColor(SK_ColorWHITE);
262cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkPaint paint;
263cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.save();
264cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
265cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawPath(one, paint);
266cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.restore();
267cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.save();
268fb173424e915e696a73067d616ce4f39a407261acaryclark@google.com    canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
269cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawPath(two, paint);
270cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.restore();
271cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    for (int y = 0; y < bitHeight; ++y) {
272cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        uint32_t* addr1 = bits.getAddr32(0, y);
273cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        int x;
274cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        char* outPtr = out;
275cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        for (x = 0; x < bitWidth; ++x) {
276cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
277cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        }
278cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        *outPtr++ = '|';
279cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        for (x = bitWidth; x < bitWidth * 2; ++x) {
280cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
281cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        }
282cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        *outPtr++ = '\0';
283cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        SkDebugf("%s\n", out);
284cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    }
285752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    return true;
286cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com}
287cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com
288d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.comstatic void showSimplifiedPath(const SkPath& one, const SkPath& two,
2894eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        const SkPath& scaledOne, const SkPath& scaledTwo) {
2904eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    showPath(one, "original:");
2914eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    showPath(two, "simplified:");
2924eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    drawAsciiPaths(scaledOne, scaledTwo, true);
2934eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com}
2944eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com
295be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.comint comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap) {
296c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    int errors2x2;
2974eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    SkPath scaledOne, scaledTwo;
2984eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    int errors = pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors2x2);
299c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    if (errors2x2 == 0) {
300198e054b33051a6cd5f606ccbc8d539cefc5631fcaryclark@google.com        return 0;
301cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    }
3028f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com    const int MAX_ERRORS = 9;
3034eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) {
3044eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        showSimplifiedPath(one, two, scaledOne, scaledTwo);
3054eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    }
306c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    if (errors2x2 > MAX_ERRORS && gComparePathsAssert) {
307a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com        SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
3084eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        showSimplifiedPath(one, two, scaledOne, scaledTwo);
3094eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        SkASSERT(0);
3104eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    }
3114eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
3124eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com}
3134eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com
314d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.comstatic void showShapeOpPath(const SkPath& one, const SkPath& two, const SkPath& a, const SkPath& b,
315044679ef8c08e1f01afadf5bc08251fe8597df81skia.committer@gmail.com        const SkPath& scaledOne, const SkPath& scaledTwo, const ShapeOp shapeOp,
31645a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        const SkMatrix& scale) {
3174eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    SkASSERT((unsigned) shapeOp < sizeof(opStrs) / sizeof(opStrs[0]));
3184eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    showPath(a, "minuend:");
3194eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    SkDebugf("op: %s\n", opStrs[shapeOp]);
3204eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    showPath(b, "subtrahend:");
3214aaaaeace7e617ddc473645756fb7c20790bc270caryclark@google.com    // the region often isn't very helpful since it approximates curves with a lot of line-tos
3224aaaaeace7e617ddc473645756fb7c20790bc270caryclark@google.com    if (0) showPath(scaledOne, "region:", scale);
3234eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    showPath(two, "op result:");
3244eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    drawAsciiPaths(scaledOne, scaledTwo, true);
3254eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com}
3264eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com
32745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.comstatic int comparePaths(const SkPath& one, const SkPath& scaledOne, const SkPath& two,
32886adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com        const SkPath& scaledTwo,
32945a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        SkBitmap& bitmap, const SkPath& a, const SkPath& b, const ShapeOp shapeOp,
33045a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        const SkMatrix& scale) {
3314eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    int errors2x2;
33286adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    int errors = pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2);
3334eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    if (errors2x2 == 0) {
3344eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        return 0;
3354eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    }
3364eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    const int MAX_ERRORS = 8;
3374eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    if (errors2x2 == MAX_ERRORS || errors2x2 == MAX_ERRORS - 1) {
33845a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        showShapeOpPath(one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
3394eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    }
3404eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com    if (errors2x2 > MAX_ERRORS && gComparePathsAssert) {
3414eeda37a7456876cb8d509a4ea43c7f4c684477acaryclark@google.com        SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
34245a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        showShapeOpPath(one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
3432e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com        SkASSERT(0);
3442e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com    }
345c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
346cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com}
347cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com
348cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com// doesn't work yet
349cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.comvoid comparePathsTiny(const SkPath& one, const SkPath& two) {
350cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    const SkRect& bounds1 = one.getBounds();
351cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    const SkRect& bounds2 = two.getBounds();
352cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkRect larger = bounds1;
353cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    larger.join(bounds2);
354cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkBitmap bits;
355cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    int bitWidth = SkScalarCeil(larger.width()) + 2;
356cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    int bitHeight = SkScalarCeil(larger.height()) + 2;
357cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    bits.setConfig(SkBitmap::kA1_Config, bitWidth * 2, bitHeight);
358cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    bits.allocPixels();
359cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkCanvas canvas(bits);
360cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawColor(SK_ColorWHITE);
361cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    SkPaint paint;
362cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.save();
363cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
364cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawPath(one, paint);
365cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.restore();
366cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.save();
367cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.translate(-bounds2.fLeft + 1, -bounds2.fTop + 1);
368cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.drawPath(two, paint);
369cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    canvas.restore();
370cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    for (int y = 0; y < bitHeight; ++y) {
371cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        uint8_t* addr1 = bits.getAddr1(0, y);
372cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        uint8_t* addr2 = bits.getAddr1(bitWidth, y);
3731ab0aac67247bf3ec1f23b220456d316d9a80b45caryclark@google.com        for (unsigned x = 0; x < bits.rowBytes(); ++x) {
374cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com            SkASSERT(addr1[x] == addr2[x]);
375cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com        }
376cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com    }
377cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com}
378cd4421df5012b75c792c6c8bf2c5ee0410921c15caryclark@google.com
379be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.combool testSimplify(const SkPath& path, bool fill, SkPath& out, SkBitmap& bitmap) {
3802e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com    if (gShowPath) {
3812e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com        showPath(path);
3822e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com    }
3832e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com    simplify(path, fill, out);
384752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    if (!gComparePaths) {
385752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com        return true;
386752b60e633a349c5b9f7bcc6a28b8064fc77bb41caryclark@google.com    }
387be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.com    return comparePaths(path, out, bitmap) == 0;
3882e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com}
38978e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com
39024bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.combool testSimplifyx(SkPath& path, bool useXor, SkPath& out, State4& state,
39159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        const char* pathStr) {
39224bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
39324bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    path.setFillType(fillType);
3948dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    if (gShowPath) {
3958dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com        showPath(path);
3968dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    }
3978dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    simplifyx(path, out);
3988dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    if (!gComparePaths) {
3998dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com        return true;
4008dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    }
401be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.com    int result = comparePaths(path, out, state.bitmap);
40259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    if (result && gPathStrAssert) {
403d1688744d537d928699b6069f99c4470a0f6e772caryclark@google.com        SkDebugf("addTest %s\n", state.filename);
40459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        char temp[8192];
40559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        bzero(temp, sizeof(temp));
40659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        SkMemoryWStream stream(temp, sizeof(temp));
407b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        const char* pathPrefix = NULL;
408b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        const char* nameSuffix = NULL;
409b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        if (fillType == SkPath::kEvenOdd_FillType) {
410b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com            pathPrefix = "    path.setFillType(SkPath::kEvenOdd_FillType);\n";
411b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com            nameSuffix = "x";
412b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        }
413b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        const char testFunction[] = "testSimplifyx(path);";
414b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        outputToStream(state, pathStr, pathPrefix, nameSuffix, testFunction, stream);
41559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        SkDebugf(temp);
41659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        SkASSERT(0);
41759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
41859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    return result == 0;
4198dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com}
4208dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com
4218dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.combool testSimplifyx(const SkPath& path) {
4228dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    SkPath out;
4238dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    simplifyx(path, out);
4248dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com    SkBitmap bitmap;
425be584d782020fe0d413a9ab4e9a57a13b1ac1032reed@google.com    int result = comparePaths(path, out, bitmap);
42624bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    if (result && gPathStrAssert) {
42724bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        SkASSERT(0);
42824bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    }
42924bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    return result == 0;
4308dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com}
4318dcf114db9762c02d217beba6e29dffa4e92d298caryclark@google.com
43231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.combool testShapeOp(const SkPath& a, const SkPath& b, const ShapeOp shapeOp) {
433d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com#if FORCE_RELEASE == 0
434d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    showPathData(a);
435d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    showOp(shapeOp);
436d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com    showPathData(b);
437d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com#endif
43831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    SkPath out;
43931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    operate(a, b, shapeOp, out);
44086adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    SkPath pathOut, scaledPathOut;
44131143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    SkRegion rgnA, rgnB, openClip, rgnOut;
44231143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    openClip.setRect(-16000, -16000, 16000, 16000);
44331143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    rgnA.setPath(a, openClip);
44431143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    rgnB.setPath(b, openClip);
44531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp);
44631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    rgnOut.getBoundaryPath(&pathOut);
44786adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com
44886adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    SkMatrix scale;
44986adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaleMatrix(a, b, scale);
45086adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
45186adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    SkPath scaledA, scaledB;
45286adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledA.addPath(a, scale);
45386adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledA.setFillType(a.getFillType());
45486adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledB.addPath(b, scale);
45586adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledB.setFillType(b.getFillType());
45686adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledRgnA.setPath(scaledA, openClip);
45786adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledRgnB.setPath(scaledB, openClip);
45886adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp);
45986adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledRgnOut.getBoundaryPath(&scaledPathOut);
46031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    SkBitmap bitmap;
46186adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    SkPath scaledOut;
46286adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledOut.addPath(out, scale);
46386adc0d414496185972a7191aca904e9e7223d7dcaryclark@google.com    scaledOut.setFillType(out.getFillType());
46445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    int result = comparePaths(pathOut, scaledPathOut, out, scaledOut, bitmap, a, b, shapeOp, scale);
46531143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    if (result && gPathStrAssert) {
46631143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com        SkASSERT(0);
46731143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    }
46831143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com    return result == 0;
46931143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com}
47031143cf37fa38dc98f71c71e518ecc21c83b5e27caryclark@google.com
47159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comconst int maxThreadsAllocated = 64;
47259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comstatic int maxThreads = 1;
47359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comstatic int threadIndex;
47459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comState4 threadState[maxThreadsAllocated];
47559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comstatic int testNumber;
47659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comstatic const char* testName;
4776aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.comstatic bool debugThreads = false;
47859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
47959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comState4* State4::queue = NULL;
48059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.compthread_mutex_t State4::addQueue = PTHREAD_MUTEX_INITIALIZER;
48159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.compthread_cond_t State4::checkQueue = PTHREAD_COND_INITIALIZER;
48259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
48378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.comState4::State4() {
48478e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 150 * 2, 100);
48578e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com    bitmap.allocPixels();
48678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com}
48778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com
48859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comvoid createThread(State4* statePtr, void* (*testFun)(void* )) {
48959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    int threadError = pthread_create(&statePtr->threadID, NULL, testFun,
49078e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com            (void*) statePtr);
49178e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com    SkASSERT(!threadError);
49278e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com}
49378e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com
49459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comint dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d) {
49559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    int testsRun = 0;
49603f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com    State4* statePtr;
49759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    if (!gRunTestsInOneThread) {
49859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        pthread_mutex_lock(&State4::addQueue);
49959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        if (threadIndex < maxThreads) {
50059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr = &threadState[threadIndex];
50159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->testsRun = 0;
50259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->a = a;
50359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->b = b;
50459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->c = c;
50559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->d = d;
50659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->done = false;
50759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->index = threadIndex;
50859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->last = false;
50959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            if (debugThreads) SkDebugf("%s %d create done=%d last=%d\n", __FUNCTION__,
51059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    statePtr->index, statePtr->done, statePtr->last);
51159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            pthread_cond_init(&statePtr->initialized, NULL);
51259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            ++threadIndex;
51359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            createThread(statePtr, testFun);
51459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        } else {
51559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            while (!State4::queue) {
51659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
51759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
51859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            }
51959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr = State4::queue;
52059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            testsRun += statePtr->testsRun;
52159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->testsRun = 0;
52259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->a = a;
52359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->b = b;
52459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->c = c;
52559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->d = d;
52659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            statePtr->done = false;
52759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            State4::queue = NULL;
52859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            for (int index = 0; index < maxThreads; ++index) {
52959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                if (threadState[index].done) {
53059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    State4::queue = &threadState[index];
53159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                }
53259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            }
53359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            if (debugThreads) SkDebugf("%s %d init done=%d last=%d queued=%d\n", __FUNCTION__,
53459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    statePtr->index, statePtr->done, statePtr->last,
53559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    State4::queue ? State4::queue->index : -1);
53659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            pthread_cond_signal(&statePtr->initialized);
53759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        }
53859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        pthread_mutex_unlock(&State4::addQueue);
53959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    } else {
54003f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr = &threadState[0];
541c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com        testsRun += statePtr->testsRun;
54203f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->testsRun = 0;
54303f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->a = a;
54403f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->b = b;
54503f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->c = c;
54603f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->d = d;
54703f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->done = false;
54803f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->index = threadIndex;
54903f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        statePtr->last = false;
55003f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        (*testFun)(statePtr);
55159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
55259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    return testsRun;
55359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com}
55459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
55559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comvoid initializeTests(const char* test, size_t testNameSize) {
55659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    testName = test;
55759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    if (!gRunTestsInOneThread) {
55859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        int threads = -1;
55959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        size_t size = sizeof(threads);
56059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
56159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        if (threads > 0) {
56259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            maxThreads = threads;
56359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        } else {
56459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            maxThreads = 8;
56559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        }
56659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
56703f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com    SkFILEStream inFile("../../experimental/Intersection/op.htm");
56803f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com    if (inFile.isValid()) {
56903f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        SkTDArray<char> inData;
57003f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        inData.setCount(inFile.getLength());
57103f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        size_t inLen = inData.count();
57203f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        inFile.read(inData.begin(), inLen);
57303f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        inFile.setPath(NULL);
574a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com        char* insert = strstr(inData.begin(), marker);
57503f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        if (insert) {
57603f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com            insert += sizeof(marker) - 1;
57703f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com            const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
57803f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com            testNumber = atoi(numLoc) + 1;
57959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        }
58059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
58124bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    const char* filename = preferredFilename;
58224bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    SkFILEWStream preferredTest(filename);
58324bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    if (!preferredTest.isValid()) {
58424bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        filename = backupFilename;
58524bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        SkFILEWStream backupTest(filename);
58624bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        SkASSERT(backupTest.isValid());
58724bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    }
58859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    for (int index = 0; index < maxThreads; ++index) {
58959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        State4* statePtr = &threadState[index];
59059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        strcpy(statePtr->filename, filename);
59124bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        size_t len = strlen(filename);
59224bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        SkASSERT(statePtr->filename[len - 6] == 'X');
59324bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        SkASSERT(statePtr->filename[len - 5] == 'X');
59424bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        statePtr->filename[len - 6] = '0' + index / 10;
59524bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com        statePtr->filename[len - 5] = '0' + index % 10;
59678e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com    }
59778e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com    threadIndex = 0;
59878e17130f396d8b2157116c2504e357192f87ed1caryclark@google.com}
59959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
60024bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.comvoid outputProgress(const State4& state, const char* pathStr, SkPath::FillType pathFillType) {
601c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    if (gRunTestsInOneThread && gShowOutputProgress) {
60203f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        if (pathFillType == SkPath::kEvenOdd_FillType) {
60303f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com            SkDebugf("    path.setFillType(SkPath::kEvenOdd_FillType);\n", pathStr);
60459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        }
60503f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        SkDebugf("%s\n", pathStr);
60603f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com    }
607b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    const char testFunction[] = "testSimplifyx(path);";
608b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    const char* pathPrefix = NULL;
609b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    const char* nameSuffix = NULL;
610b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    if (pathFillType == SkPath::kEvenOdd_FillType) {
611b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        pathPrefix = "    path.setFillType(SkPath::kEvenOdd_FillType);\n";
612b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        nameSuffix = "x";
613b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    }
6146aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com    if (gUsePhysicalFiles) {
6156aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com        SkFILEWStream outFile(state.filename);
6166aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com        if (!outFile.isValid()) {
6176aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com            SkASSERT(0);
6186aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com            return;
6196aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com        }
620b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        outputToStream(state, pathStr, pathPrefix, nameSuffix, testFunction, outFile);
62103f970652e07c6832cae41fa374cb68ca80d472ccaryclark@google.com        return;
62259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
6236aea33f92c611d6fdc88bc2352c5c966168af83bcaryclark@google.com    SkFILEWStream outRam(state.filename);
624b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    outputToStream(state, pathStr, pathPrefix, nameSuffix, testFunction, outRam);
62559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com}
62659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
627b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.comvoid outputProgress(const State4& state, const char* pathStr, ShapeOp op) {
628b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    SkString testFunc("testShapeOp(path, pathB, ");
629b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    testFunc += opStrs[op];
630b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    testFunc += ");";
631b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    const char* testFunction = testFunc.c_str();
632b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    if (gRunTestsInOneThread && gShowOutputProgress) {
633b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        SkDebugf("%s\n", pathStr);
634b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        SkDebugf("    %s\n", testFunction);
635b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    }
636b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    const char* nameSuffix = opSuffixes[op];
637b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    if (gUsePhysicalFiles) {
638b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        SkFILEWStream outFile(state.filename);
639b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        if (!outFile.isValid()) {
640b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com            SkASSERT(0);
641b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com            return;
642b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        }
643b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        outputToStream(state, pathStr, NULL, nameSuffix, testFunction, outFile);
644b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        return;
645b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    }
646b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    SkFILEWStream outRam(state.filename);
647b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    outputToStream(state, pathStr, NULL, nameSuffix, testFunction, outRam);
648b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com}
649b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com
650b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.comstatic void writeTestName(const char* nameSuffix, SkWStream& outFile) {
65159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText(testName);
65259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeDecAsText(testNumber);
653b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    if (nameSuffix) {
654b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        outFile.writeText(nameSuffix);
65524bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    }
65624bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com}
65724bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com
658b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.comvoid outputToStream(const State4& state, const char* pathStr, const char* pathPrefix,
659b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        const char* nameSuffix,
660b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        const char* testFunction, SkWStream& outFile) {
66124bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    outFile.writeText("<div id=\"");
662b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    writeTestName(nameSuffix, outFile);
66359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("\">\n");
664b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    if (pathPrefix) {
665b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        outFile.writeText(pathPrefix);
66624bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    }
66759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText(pathStr);
66859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("</div>\n\n");
669a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
67059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText(marker);
67159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("    ");
672b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    writeTestName(nameSuffix, outFile);
67359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText(",\n\n\n");
674a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com
67559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("static void ");
676b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    writeTestName(nameSuffix, outFile);
677aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com    outFile.writeText("() {\n    SkPath path");
678aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com    if (!pathPrefix) {
679aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com        outFile.writeText(", pathB");
680aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com    }
681aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com    outFile.writeText(";\n");
682b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    if (pathPrefix) {
683b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com        outFile.writeText(pathPrefix);
68424bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com    }
68559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText(pathStr);
686b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    outFile.writeText("    ");
687b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    outFile.writeText(testFunction);
688b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    outFile.writeText("\n}\n\n");
68959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("static void (*firstTest)() = ");
690b1c42bbdcff20257b30d155fe014d3e04233de45caryclark@google.com    writeTestName(nameSuffix, outFile);
69159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText(";\n\n");
69259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
69359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("static struct {\n");
69459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("    void (*fun)();\n");
69559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("    const char* str;\n");
69659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("} tests[] = {\n");
69759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("    TEST(");
6988f9f468b0555e95b8fc3cf4e6ee1f1fbf5492a1bcaryclark@google.com    writeTestName(nameSuffix, outFile);
69959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.writeText("),\n");
70059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    outFile.flush();
70159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com}
70259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
70359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.combool runNextTestSet(State4& state) {
70459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    if (gRunTestsInOneThread) {
70559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        return false;
70659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
70759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    pthread_mutex_lock(&State4::addQueue);
70859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    state.done = true;
70959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    State4::queue = &state;
71059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    if (debugThreads) SkDebugf("%s %d checkQueue done=%d last=%d\n", __FUNCTION__, state.index,
71159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        state.done, state.last);
71259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    pthread_cond_signal(&State4::checkQueue);
71359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    while (state.done && !state.last) {
71459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        if (debugThreads) SkDebugf("%s %d done=%d last=%d\n", __FUNCTION__, state.index, state.done, state.last);
71559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        pthread_cond_wait(&state.initialized, &State4::addQueue);
71659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
71759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    pthread_mutex_unlock(&State4::addQueue);
71859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    return !state.last;
71959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com}
72059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com
72159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.comint waitForCompletion() {
72259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    int testsRun = 0;
72359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    if (!gRunTestsInOneThread) {
72459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        pthread_mutex_lock(&State4::addQueue);
72559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        int runningThreads = maxThreads;
72659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        int index;
72759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        while (runningThreads > 0) {
72859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            while (!State4::queue) {
72959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
73059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
73159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            }
73259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            while (State4::queue) {
73359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                --runningThreads;
73459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                SkDebugf("•");
73559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                State4::queue->last = true;
73624bec79d6f3d71ff97b50db72461a3892bd4f6b5caryclark@google.com                State4* next = NULL;
73759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                for (index = 0; index < maxThreads; ++index) {
73859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    State4& test = threadState[index];
73959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    if (test.done && !test.last) {
74059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                        next = &test;
74159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    }
74259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                }
74359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                if (debugThreads) SkDebugf("%s %d next=%d deQueue\n", __FUNCTION__,
74459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                    State4::queue->index, next ? next->index : -1);
74559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                pthread_cond_signal(&State4::queue->initialized);
74659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com                State4::queue = next;
74759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            }
74859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        }
74959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        pthread_mutex_unlock(&State4::addQueue);
75059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        for (index = 0; index < maxThreads; ++index) {
75159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            pthread_join(threadState[index].threadID, NULL);
75259823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com            testsRun += threadState[index].testsRun;
75359823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        }
75459823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com        SkDebugf("\n");
75559823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    }
75659823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#ifdef SK_DEBUG
75759823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    gDebugMaxWindSum = SK_MaxS32;
75859823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    gDebugMaxWindValue = SK_MaxS32;
75959823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com#endif
76059823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com    return testsRun;
76159823f7f3ba43c7c6bc1fa8c600b093ecb4236aacaryclark@google.com}
762