blob: 4129ab472bab76dc4b1bcf50f68b61697f327229 [file] [log] [blame]
caryclark@google.comcd4421d2012-03-01 19:16:31 +00001#include "EdgeWalker_Test.h"
2#include "Intersection_Tests.h"
3#include "SkBitmap.h"
4#include "SkCanvas.h"
5#include "SkPaint.h"
caryclark@google.com59823f72012-08-09 18:17:47 +00006#include "SkStream.h"
7
caryclark@google.comfb173422012-04-10 18:28:55 +00008#include <algorithm>
caryclark@google.com59823f72012-08-09 18:17:47 +00009#include <assert.h>
10#include <errno.h>
11#include <pthread.h>
12#include <unistd.h>
13#include <sys/types.h>
14#include <sys/sysctl.h>
caryclark@google.comcd4421d2012-03-01 19:16:31 +000015
caryclark@google.com78e17132012-04-17 11:40:34 +000016#undef SkASSERT
17#define SkASSERT(cond) while (!(cond)) { sk_throw(); }
18
caryclark@google.com59823f72012-08-09 18:17:47 +000019static const char marker[] =
20 "</div>\n"
21 "\n"
22 "<script type=\"text/javascript\">\n"
23 "\n"
24 "var testDivs = [\n";
caryclark@google.com24bec792012-08-20 12:43:57 +000025
26static const char preferredFilename[] = "/flash/debug/XX.txt";
27static const char backupFilename[] = "../../experimental/Intersection/debugXX.txt";
caryclark@google.com59823f72012-08-09 18:17:47 +000028
caryclark@google.com2e7f4c82012-03-20 21:11:59 +000029static bool gShowPath = false;
caryclark@google.com198e0542012-03-30 18:47:02 +000030static bool gComparePaths = true;
caryclark@google.coma3f05fa2012-06-01 17:44:28 +000031//static bool gDrawLastAsciiPaths = true;
caryclark@google.comc899ad92012-08-23 15:24:42 +000032//static bool gDrawAllAsciiPaths = false;
33static bool gShowOutputProgress = false;
34static bool gShowAsciiPaths = true;
caryclark@google.com59823f72012-08-09 18:17:47 +000035static bool gComparePathsAssert = false;
36static bool gPathStrAssert = true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +000037
caryclark@google.com2e7f4c82012-03-20 21:11:59 +000038void showPath(const SkPath& path, const char* str) {
caryclark@google.com752b60e2012-03-22 21:11:17 +000039 SkDebugf("%s\n", !str ? "original:" : str);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000040 SkPath::Iter iter(path, true);
41 uint8_t verb;
42 SkPoint pts[4];
43 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
44 switch (verb) {
45 case SkPath::kMove_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000046 SkDebugf("path.moveTo(%1.9g, %1.9g);\n", pts[0].fX, pts[0].fY);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000047 continue;
48 case SkPath::kLine_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000049 SkDebugf("path.lineTo(%1.9g, %1.9g);\n", pts[1].fX, pts[1].fY);
caryclark@google.comcd4421d2012-03-01 19:16:31 +000050 break;
51 case SkPath::kQuad_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000052 SkDebugf("path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
caryclark@google.comcd4421d2012-03-01 19:16:31 +000053 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
54 break;
55 case SkPath::kCubic_Verb:
caryclark@google.comd88e0892012-03-27 13:23:51 +000056 SkDebugf("path.cubicTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
caryclark@google.comcd4421d2012-03-01 19:16:31 +000057 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
58 pts[3].fX, pts[3].fY);
59 break;
60 case SkPath::kClose_Verb:
61 SkDebugf("path.close();\n");
62 continue;
63 default:
64 SkDEBUGFAIL("bad verb");
65 return;
66 }
67 }
68}
69
caryclark@google.com198e0542012-03-30 18:47:02 +000070static int pathsDrawTheSame(const SkPath& one, const SkPath& two,
caryclark@google.comc899ad92012-08-23 15:24:42 +000071 SkBitmap& bits, SkCanvas* c, int& error2x2) {
caryclark@google.com198e0542012-03-30 18:47:02 +000072 SkCanvas* canvasPtr = c;
73 if (!c) {
74 canvasPtr = new SkCanvas(bits);
75 }
caryclark@google.comc899ad92012-08-23 15:24:42 +000076 const int bitWidth = 64;
77 const int bitHeight = 64;
78 if (bits.width() == 0) {
caryclark@google.com198e0542012-03-30 18:47:02 +000079 bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
80 bits.allocPixels();
81 canvasPtr->setBitmapDevice(bits);
82 }
caryclark@google.comc899ad92012-08-23 15:24:42 +000083 SkRect larger = one.getBounds();
84 larger.join(two.getBounds());
85 SkScalar largerWidth = larger.width();
86 if (largerWidth < 4) {
87 largerWidth = 4;
88 }
89 SkScalar largerHeight = larger.height();
90 if (largerHeight < 4) {
91 largerHeight = 4;
92 }
93 SkScalar hScale = (bitWidth - 2) / largerWidth;
94 SkScalar vScale = (bitHeight - 2) / largerHeight;
95 SkMatrix scale;
96 scale.reset();
97 scale.preScale(hScale, vScale);
98 SkPath scaledOne, scaledTwo;
99 one.transform(scale, &scaledOne);
100 two.transform(scale, &scaledTwo);
101 const SkRect& bounds1 = scaledOne.getBounds();
caryclark@google.com198e0542012-03-30 18:47:02 +0000102 SkCanvas& canvas = *canvasPtr;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000103 canvas.drawColor(SK_ColorWHITE);
104 SkPaint paint;
105 canvas.save();
106 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
caryclark@google.comc899ad92012-08-23 15:24:42 +0000107 canvas.drawPath(scaledOne, paint);
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000108 canvas.restore();
109 canvas.save();
110 canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
caryclark@google.comc899ad92012-08-23 15:24:42 +0000111 canvas.drawPath(scaledTwo, paint);
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000112 canvas.restore();
caryclark@google.comc899ad92012-08-23 15:24:42 +0000113 int errors2 = 0;
caryclark@google.com198e0542012-03-30 18:47:02 +0000114 int errors = 0;
caryclark@google.comc899ad92012-08-23 15:24:42 +0000115 for (int y = 0; y < bitHeight - 1; ++y) {
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000116 uint32_t* addr1 = bits.getAddr32(0, y);
caryclark@google.comc899ad92012-08-23 15:24:42 +0000117 uint32_t* addr2 = bits.getAddr32(0, y + 1);
118 uint32_t* addr3 = bits.getAddr32(bitWidth, y);
119 uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
120 for (int x = 0; x < bitWidth - 1; ++x) {
121 // count 2x2 blocks
122 bool err = addr1[x] != addr3[x];
123 if (err) {
124 errors2 += addr1[x + 1] != addr3[x + 1]
125 && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
126 errors++;
127 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000128 }
129 }
caryclark@google.com198e0542012-03-30 18:47:02 +0000130 if (!c) {
131 delete canvasPtr;
132 }
caryclark@google.comc899ad92012-08-23 15:24:42 +0000133 if (errors2 >= 2 || errors > 96) {
134 SkDebugf("%s errors2=%d errors=%d\n", __FUNCTION__, errors2, errors);
135 }
136 if (errors2 >= 3 || errors > 192) {
137 drawAsciiPaths(scaledOne, scaledTwo, true);
138 }
139 error2x2 = errors2;
caryclark@google.com198e0542012-03-30 18:47:02 +0000140 return errors;
141}
142
caryclark@google.comc899ad92012-08-23 15:24:42 +0000143bool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) {
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000144 if (!drawPaths) {
caryclark@google.com752b60e2012-03-22 21:11:17 +0000145 return true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000146 }
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000147 if (gShowAsciiPaths) {
148 showPath(one, "one:");
149 showPath(two, "two:");
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000150 }
151 const SkRect& bounds1 = one.getBounds();
152 const SkRect& bounds2 = two.getBounds();
153 SkRect larger = bounds1;
154 larger.join(bounds2);
155 SkBitmap bits;
caryclark@google.com752b60e2012-03-22 21:11:17 +0000156 char out[256];
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000157 int bitWidth = SkScalarCeil(larger.width()) + 2;
caryclark@google.com752b60e2012-03-22 21:11:17 +0000158 if (bitWidth * 2 + 1 >= (int) sizeof(out)) {
159 return false;
160 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000161 int bitHeight = SkScalarCeil(larger.height()) + 2;
caryclark@google.com752b60e2012-03-22 21:11:17 +0000162 if (bitHeight >= (int) sizeof(out)) {
163 return false;
164 }
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000165 bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
166 bits.allocPixels();
167 SkCanvas canvas(bits);
168 canvas.drawColor(SK_ColorWHITE);
169 SkPaint paint;
170 canvas.save();
171 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
172 canvas.drawPath(one, paint);
173 canvas.restore();
174 canvas.save();
caryclark@google.comfb173422012-04-10 18:28:55 +0000175 canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000176 canvas.drawPath(two, paint);
177 canvas.restore();
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000178 for (int y = 0; y < bitHeight; ++y) {
179 uint32_t* addr1 = bits.getAddr32(0, y);
180 int x;
181 char* outPtr = out;
182 for (x = 0; x < bitWidth; ++x) {
183 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
184 }
185 *outPtr++ = '|';
186 for (x = bitWidth; x < bitWidth * 2; ++x) {
187 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
188 }
189 *outPtr++ = '\0';
190 SkDebugf("%s\n", out);
191 }
caryclark@google.com752b60e2012-03-22 21:11:17 +0000192 return true;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000193}
194
caryclark@google.com1577e8f2012-05-22 17:01:14 +0000195int comparePaths(const SkPath& one, const SkPath& two, SkBitmap& bitmap,
caryclark@google.com198e0542012-03-30 18:47:02 +0000196 SkCanvas* canvas) {
caryclark@google.comc899ad92012-08-23 15:24:42 +0000197 int errors2x2;
198 int errors = pathsDrawTheSame(one, two, bitmap, canvas, errors2x2);
199 if (errors2x2 == 0) {
caryclark@google.com198e0542012-03-30 18:47:02 +0000200 return 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000201 }
caryclark@google.comc899ad92012-08-23 15:24:42 +0000202 const int MAX_ERRORS = 4;
203 if (errors2x2 > MAX_ERRORS && gComparePathsAssert) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000204 SkDebugf("%s errors=%d\n", __FUNCTION__, errors);
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000205 showPath(one);
206 showPath(two, "simplified:");
207 SkASSERT(0);
208 }
caryclark@google.comc899ad92012-08-23 15:24:42 +0000209 return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
caryclark@google.comcd4421d2012-03-01 19:16:31 +0000210}
211
212// doesn't work yet
213void comparePathsTiny(const SkPath& one, const SkPath& two) {
214 const SkRect& bounds1 = one.getBounds();
215 const SkRect& bounds2 = two.getBounds();
216 SkRect larger = bounds1;
217 larger.join(bounds2);
218 SkBitmap bits;
219 int bitWidth = SkScalarCeil(larger.width()) + 2;
220 int bitHeight = SkScalarCeil(larger.height()) + 2;
221 bits.setConfig(SkBitmap::kA1_Config, bitWidth * 2, bitHeight);
222 bits.allocPixels();
223 SkCanvas canvas(bits);
224 canvas.drawColor(SK_ColorWHITE);
225 SkPaint paint;
226 canvas.save();
227 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
228 canvas.drawPath(one, paint);
229 canvas.restore();
230 canvas.save();
231 canvas.translate(-bounds2.fLeft + 1, -bounds2.fTop + 1);
232 canvas.drawPath(two, paint);
233 canvas.restore();
234 for (int y = 0; y < bitHeight; ++y) {
235 uint8_t* addr1 = bits.getAddr1(0, y);
236 uint8_t* addr2 = bits.getAddr1(bitWidth, y);
237 for (int x = 0; x < bits.rowBytes(); ++x) {
238 SkASSERT(addr1[x] == addr2[x]);
239 }
240 }
241}
242
caryclark@google.com198e0542012-03-30 18:47:02 +0000243bool testSimplify(const SkPath& path, bool fill, SkPath& out, SkBitmap& bitmap,
244 SkCanvas* canvas) {
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000245 if (gShowPath) {
246 showPath(path);
247 }
248 simplify(path, fill, out);
caryclark@google.com752b60e2012-03-22 21:11:17 +0000249 if (!gComparePaths) {
250 return true;
251 }
caryclark@google.com198e0542012-03-30 18:47:02 +0000252 return comparePaths(path, out, bitmap, canvas) == 0;
caryclark@google.com2e7f4c82012-03-20 21:11:59 +0000253}
caryclark@google.com78e17132012-04-17 11:40:34 +0000254
caryclark@google.com24bec792012-08-20 12:43:57 +0000255bool testSimplifyx(SkPath& path, bool useXor, SkPath& out, State4& state,
caryclark@google.com59823f72012-08-09 18:17:47 +0000256 const char* pathStr) {
caryclark@google.com24bec792012-08-20 12:43:57 +0000257 SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
258 path.setFillType(fillType);
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000259 if (gShowPath) {
260 showPath(path);
261 }
262 simplifyx(path, out);
263 if (!gComparePaths) {
264 return true;
265 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000266 int result = comparePaths(path, out, state.bitmap, state.canvas);
267 if (result && gPathStrAssert) {
268 char temp[8192];
269 bzero(temp, sizeof(temp));
270 SkMemoryWStream stream(temp, sizeof(temp));
caryclark@google.com24bec792012-08-20 12:43:57 +0000271 outputToStream(state, pathStr, fillType, stream);
caryclark@google.com59823f72012-08-09 18:17:47 +0000272 SkDebugf(temp);
273 SkASSERT(0);
274 }
275 return result == 0;
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000276}
277
278bool testSimplifyx(const SkPath& path) {
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000279 SkPath out;
280 simplifyx(path, out);
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000281 SkBitmap bitmap;
caryclark@google.com24bec792012-08-20 12:43:57 +0000282 int result = comparePaths(path, out, bitmap, 0);
283 if (result && gPathStrAssert) {
284 SkASSERT(0);
285 }
286 return result == 0;
caryclark@google.com8dcf1142012-07-02 20:27:02 +0000287}
288
caryclark@google.com59823f72012-08-09 18:17:47 +0000289const int maxThreadsAllocated = 64;
290static int maxThreads = 1;
291static int threadIndex;
292State4 threadState[maxThreadsAllocated];
293static int testNumber;
294static const char* testName;
295static bool debugThreads = false;
296
297State4* State4::queue = NULL;
298pthread_mutex_t State4::addQueue = PTHREAD_MUTEX_INITIALIZER;
299pthread_cond_t State4::checkQueue = PTHREAD_COND_INITIALIZER;
300
caryclark@google.com78e17132012-04-17 11:40:34 +0000301State4::State4() {
302 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 150 * 2, 100);
303 bitmap.allocPixels();
304 canvas = new SkCanvas(bitmap);
305}
306
caryclark@google.com59823f72012-08-09 18:17:47 +0000307void createThread(State4* statePtr, void* (*testFun)(void* )) {
308 int threadError = pthread_create(&statePtr->threadID, NULL, testFun,
caryclark@google.com78e17132012-04-17 11:40:34 +0000309 (void*) statePtr);
310 SkASSERT(!threadError);
311}
312
caryclark@google.com59823f72012-08-09 18:17:47 +0000313int dispatchTest4(void* (*testFun)(void* ), int a, int b, int c, int d) {
314 int testsRun = 0;
caryclark@google.com03f97062012-08-21 13:13:52 +0000315 State4* statePtr;
caryclark@google.com59823f72012-08-09 18:17:47 +0000316 if (!gRunTestsInOneThread) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000317 pthread_mutex_lock(&State4::addQueue);
318 if (threadIndex < maxThreads) {
319 statePtr = &threadState[threadIndex];
320 statePtr->testsRun = 0;
321 statePtr->a = a;
322 statePtr->b = b;
323 statePtr->c = c;
324 statePtr->d = d;
325 statePtr->done = false;
326 statePtr->index = threadIndex;
327 statePtr->last = false;
328 if (debugThreads) SkDebugf("%s %d create done=%d last=%d\n", __FUNCTION__,
329 statePtr->index, statePtr->done, statePtr->last);
330 pthread_cond_init(&statePtr->initialized, NULL);
331 ++threadIndex;
332 createThread(statePtr, testFun);
333 } else {
334 while (!State4::queue) {
335 if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
336 pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
337 }
338 statePtr = State4::queue;
339 testsRun += statePtr->testsRun;
340 statePtr->testsRun = 0;
341 statePtr->a = a;
342 statePtr->b = b;
343 statePtr->c = c;
344 statePtr->d = d;
345 statePtr->done = false;
346 State4::queue = NULL;
347 for (int index = 0; index < maxThreads; ++index) {
348 if (threadState[index].done) {
349 State4::queue = &threadState[index];
350 }
351 }
352 if (debugThreads) SkDebugf("%s %d init done=%d last=%d queued=%d\n", __FUNCTION__,
353 statePtr->index, statePtr->done, statePtr->last,
354 State4::queue ? State4::queue->index : -1);
355 pthread_cond_signal(&statePtr->initialized);
356 }
357 pthread_mutex_unlock(&State4::addQueue);
358 } else {
caryclark@google.com03f97062012-08-21 13:13:52 +0000359 statePtr = &threadState[0];
caryclark@google.comc899ad92012-08-23 15:24:42 +0000360 testsRun += statePtr->testsRun;
caryclark@google.com03f97062012-08-21 13:13:52 +0000361 statePtr->testsRun = 0;
362 statePtr->a = a;
363 statePtr->b = b;
364 statePtr->c = c;
365 statePtr->d = d;
366 statePtr->done = false;
367 statePtr->index = threadIndex;
368 statePtr->last = false;
369 (*testFun)(statePtr);
caryclark@google.com78e17132012-04-17 11:40:34 +0000370 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000371 return testsRun;
372}
373
374void initializeTests(const char* test, size_t testNameSize) {
375 testName = test;
376 if (!gRunTestsInOneThread) {
377 int threads = -1;
378 size_t size = sizeof(threads);
379 sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
380 if (threads > 0) {
381 maxThreads = threads;
382 } else {
383 maxThreads = 8;
384 }
385 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000386 SkFILEStream inFile("../../experimental/Intersection/op.htm");
387 if (inFile.isValid()) {
388 SkTDArray<char> inData;
389 inData.setCount(inFile.getLength());
390 size_t inLen = inData.count();
391 inFile.read(inData.begin(), inLen);
392 inFile.setPath(NULL);
393 char* insert = strstr(inData.begin(), marker);
394 if (insert) {
395 insert += sizeof(marker) - 1;
396 const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
397 testNumber = atoi(numLoc) + 1;
caryclark@google.com59823f72012-08-09 18:17:47 +0000398 }
399 }
caryclark@google.com24bec792012-08-20 12:43:57 +0000400 const char* filename = preferredFilename;
401 SkFILEWStream preferredTest(filename);
402 if (!preferredTest.isValid()) {
403 filename = backupFilename;
404 SkFILEWStream backupTest(filename);
405 SkASSERT(backupTest.isValid());
406 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000407 for (int index = 0; index < maxThreads; ++index) {
408 State4* statePtr = &threadState[index];
409 strcpy(statePtr->filename, filename);
caryclark@google.com24bec792012-08-20 12:43:57 +0000410 size_t len = strlen(filename);
411 SkASSERT(statePtr->filename[len - 6] == 'X');
412 SkASSERT(statePtr->filename[len - 5] == 'X');
413 statePtr->filename[len - 6] = '0' + index / 10;
414 statePtr->filename[len - 5] = '0' + index % 10;
caryclark@google.com59823f72012-08-09 18:17:47 +0000415 }
caryclark@google.com78e17132012-04-17 11:40:34 +0000416 threadIndex = 0;
417}
caryclark@google.com59823f72012-08-09 18:17:47 +0000418
caryclark@google.com24bec792012-08-20 12:43:57 +0000419void outputProgress(const State4& state, const char* pathStr, SkPath::FillType pathFillType) {
caryclark@google.comc899ad92012-08-23 15:24:42 +0000420 if (gRunTestsInOneThread && gShowOutputProgress) {
caryclark@google.com03f97062012-08-21 13:13:52 +0000421 if (pathFillType == SkPath::kEvenOdd_FillType) {
422 SkDebugf(" path.setFillType(SkPath::kEvenOdd_FillType);\n", pathStr);
caryclark@google.com59823f72012-08-09 18:17:47 +0000423 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000424 SkDebugf("%s\n", pathStr);
caryclark@google.com59823f72012-08-09 18:17:47 +0000425 }
caryclark@google.com03f97062012-08-21 13:13:52 +0000426 SkFILEWStream outFile(state.filename);
427 if (!outFile.isValid()) {
428 SkASSERT(0);
429 return;
430 }
431 outputToStream(state, pathStr, pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000432}
433
caryclark@google.com24bec792012-08-20 12:43:57 +0000434static void writeTestName(SkPath::FillType pathFillType, SkWStream& outFile) {
caryclark@google.com59823f72012-08-09 18:17:47 +0000435 outFile.writeText(testName);
436 outFile.writeDecAsText(testNumber);
caryclark@google.com24bec792012-08-20 12:43:57 +0000437 if (pathFillType == SkPath::kEvenOdd_FillType) {
438 outFile.writeText("x");
439 }
440}
441
442void outputToStream(const State4& state, const char* pathStr, SkPath::FillType pathFillType, SkWStream& outFile) {
443 outFile.writeText("<div id=\"");
444 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000445 outFile.writeText("\">\n");
caryclark@google.com24bec792012-08-20 12:43:57 +0000446 if (pathFillType == SkPath::kEvenOdd_FillType) {
447 outFile.writeText(" path.setFillType(SkPath::kEvenOdd_FillType);\n");
448 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000449 outFile.writeText(pathStr);
450 outFile.writeText("</div>\n\n");
451
452 outFile.writeText(marker);
453 outFile.writeText(" ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000454 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000455 outFile.writeText(",\n\n\n");
456
457 outFile.writeText("static void ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000458 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000459 outFile.writeText("() {\n SkPath path;\n");
caryclark@google.com24bec792012-08-20 12:43:57 +0000460 if (pathFillType == SkPath::kEvenOdd_FillType) {
461 outFile.writeText(" path.setFillType(SkPath::kEvenOdd_FillType);\n");
462 }
caryclark@google.com59823f72012-08-09 18:17:47 +0000463 outFile.writeText(pathStr);
464 outFile.writeText(" testSimplifyx(path);\n}\n\n");
465 outFile.writeText("static void (*firstTest)() = ");
caryclark@google.com24bec792012-08-20 12:43:57 +0000466 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000467 outFile.writeText(";\n\n");
468
469 outFile.writeText("static struct {\n");
470 outFile.writeText(" void (*fun)();\n");
471 outFile.writeText(" const char* str;\n");
472 outFile.writeText("} tests[] = {\n");
473 outFile.writeText(" TEST(");
caryclark@google.com24bec792012-08-20 12:43:57 +0000474 writeTestName(pathFillType, outFile);
caryclark@google.com59823f72012-08-09 18:17:47 +0000475 outFile.writeText("),\n");
476 outFile.flush();
477}
478
479bool runNextTestSet(State4& state) {
480 if (gRunTestsInOneThread) {
481 return false;
482 }
483 pthread_mutex_lock(&State4::addQueue);
484 state.done = true;
485 State4::queue = &state;
486 if (debugThreads) SkDebugf("%s %d checkQueue done=%d last=%d\n", __FUNCTION__, state.index,
487 state.done, state.last);
488 pthread_cond_signal(&State4::checkQueue);
489 while (state.done && !state.last) {
490 if (debugThreads) SkDebugf("%s %d done=%d last=%d\n", __FUNCTION__, state.index, state.done, state.last);
491 pthread_cond_wait(&state.initialized, &State4::addQueue);
492 }
493 pthread_mutex_unlock(&State4::addQueue);
494 return !state.last;
495}
496
497int waitForCompletion() {
498 int testsRun = 0;
499 if (!gRunTestsInOneThread) {
500 pthread_mutex_lock(&State4::addQueue);
501 int runningThreads = maxThreads;
502 int index;
503 while (runningThreads > 0) {
504 while (!State4::queue) {
505 if (debugThreads) SkDebugf("%s checkQueue\n", __FUNCTION__);
506 pthread_cond_wait(&State4::checkQueue, &State4::addQueue);
507 }
508 while (State4::queue) {
509 --runningThreads;
510 SkDebugf("•");
511 State4::queue->last = true;
caryclark@google.com24bec792012-08-20 12:43:57 +0000512 State4* next = NULL;
caryclark@google.com59823f72012-08-09 18:17:47 +0000513 for (index = 0; index < maxThreads; ++index) {
514 State4& test = threadState[index];
515 if (test.done && !test.last) {
516 next = &test;
517 }
518 }
519 if (debugThreads) SkDebugf("%s %d next=%d deQueue\n", __FUNCTION__,
520 State4::queue->index, next ? next->index : -1);
521 pthread_cond_signal(&State4::queue->initialized);
522 State4::queue = next;
523 }
524 }
525 pthread_mutex_unlock(&State4::addQueue);
526 for (index = 0; index < maxThreads; ++index) {
527 pthread_join(threadState[index].threadID, NULL);
528 testsRun += threadState[index].testsRun;
529 }
530 SkDebugf("\n");
531 }
532#ifdef SK_DEBUG
533 gDebugMaxWindSum = SK_MaxS32;
534 gDebugMaxWindValue = SK_MaxS32;
535#endif
536 return testsRun;
537}