blob: c0f028c55f0b563b8c1723fea11a8b23192b5b91 [file] [log] [blame]
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +00001
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +00002#include "SkBitmap.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +00003#include "SkCanvas.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +00004#include "SkColor.h"
5#include "SkColorPriv.h"
6#include "SkDevice.h"
7#include "SkGraphics.h"
caryclark@google.comcffbcc32013-06-04 17:59:42 +00008#include "SkImageDecoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +00009#include "SkImageEncoder.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000010#include "SkOSFile.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000011#include "SkPathOpsDebug.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000012#include "SkPicture.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000013#include "SkRTConf.h"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000014#include "SkTSort.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000015#include "SkStream.h"
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +000016#include "SkString.h"
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000017#include "SkTArray.h"
18#include "SkTDArray.h"
19#include "SkThreadPool.h"
20#include "SkTime.h"
21#include "Test.h"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000022
23#ifdef SK_BUILD_FOR_WIN
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000024 #define PATH_SLASH "\\"
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000025 #define IN_DIR "D:\\skp\\slave"
26 #define OUT_DIR "D:\\skpOut\\1\\"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000027#else
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000028 #define PATH_SLASH "/"
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +000029 #define IN_DIR "/skp/2311328-7fc2228/slave"
30 #define OUT_DIR "/skpOut/2/"
caryclark@google.com07e97fc2013-07-08 17:17:02 +000031#endif
32
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +000033const struct {
34 int directory;
35 const char* filename;
36} skipOverSept[] = {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +000037 { 9, "http___www_catingueiraonline_com_.skp"}, // infinite loop
38 {13, "http___www_galaxystwo_com_.skp"}, // infinite loop
39 {15, "http___www_giffingtool_com_.skp"}, // joinCoincidence / findT / assert
40 {15, "http___www_thaienews_blogspot_com_.skp"}, // infinite loop
41 {17, "http___www_gruposejaumdivulgador_com_br_.skp"}, // calcCoincidentWinding asserts zeroSpan
42 {18, "http___www_argus_presse_fr_.skp"}, // can't find winding of remaining vertical edge
43 {21, "http___www_fashionscandal_com_.skp"}, // infinite loop
44 {21, "http___www_kenlevine_blogspot_com_.skp"}, // infinite loop
45 {25, "http___www_defense_studies_blogspot_com_.skp"}, // infinite loop
46 {27, "http___www_brokeroutpost_com_.skp"}, // suspect infinite loop
47 {28, "http___www_jaimebatistadasilva_blogspot_com_br_.skp"}, // suspect infinite loop
48 {28, "http___www_odia_com_br_.skp"}, // !simple->isClosed()
49 {29, "http___www_hubbyscook_com_.skp"}, // joinCoincidence / findT / assert
50 {30, "http___www_spankystokes_com_.skp"}, // suspect infinite loop
51 {32, "http___www_adalbertoday_blogspot_com_br_.skp"}, // suspect infinite loop
52 {32, "http___www_galery_annisa_com_.skp"}, // suspect infinite loop
53 {33, "http___www_pindosiya_com_.skp"}, // line quad intersection SkIntersections::assert
54 {36, "http___www_educationalcraft_com_.skp"}, // cubic / cubic near end / assert in SkIntersections::insert (missing skp test)
55 {36, "http___www_shaam_org_.skp"}, // suspect infinite loop
56 {36, "http___www_my_pillow_book_blogspot_gr_.skp"}, // suspect infinite loop
57 {39, "http___www_opbeat_com_.skp"}, // suspect infinite loop
58 {40, "http___www_phototransferapp_com_.skp"}, // !simple->isClosed()
59 {41, "http___www_freeismylife_com_.skp"}, // suspect infinite loop
60 {41, "http___www_accordidelmomento_com_.skp"}, // suspect infinite loop
61 {41, "http___www_evolvehq_com_.skp"}, // joinCoincidence / findT / assert
62 {44, "http___www_contextualnewsfeeds_com_.skp"}, // !simple->isClosed()
63 {44, "http___www_cooksnaps_com_.skp"}, // !simple->isClosed()
64 {44, "http___www_helha_be_.skp"}, // !simple->isClosed()
65 {45, "http___www_blondesmakemoney_blogspot_com_.skp"}, // suspect infinite loop
66 {46, "http___www_cheaphealthygood_blogspot_com_.skp"}, // suspect infinite loop
67 {47, "http___www_ajitvadakayil_blogspot_in_.skp"}, // suspect infinite loop
68 {49, "http___www_karnivool_com_au_.skp"}, // SkOpAngle::setSector SkASSERT(fSectorStart >= 0);
69 {49, "http___www_tunero_de_.skp"}, // computeonesumreverse calls markwinding with 0 winding
70 {49, "http___www_thaienews_blogspot_sg_.skp"}, // suspect infinite loop
71 {50, "http___www_docgelo_com_.skp"}, // rightAngleWinding (probably same as argus_presse)
72 {53, "http___www_lojaanabotafogo_com_br_.skp"}, // rrect validate assert
73 {54, "http___www_odecktestanswer2013_blogspot_in_.skp"}, // suspect infinite loop
74 {54, "http___www_cleristonsilva_com_br_.skp"}, // suspect infinite loop
75 {56, "http___www_simplysaru_com_.skp"}, // joinCoincidence / findT / assert
76 {57, "http___www_koukfamily_blogspot_gr_.skp"}, // suspect infinite loop
77 {57, "http___www_dinar2010_blogspot_com_.skp"}, // suspect infinite loop
78 {58, "http___www_artblart_com_.skp"}, // rightAngleWinding
79 {59, "http___www_accrispin_blogspot_com_.skp"}, // suspect infinite loop
80 {59, "http___www_vicisitudysordidez_blogspot_com_es_.skp"}, // suspect infinite loop
81 {60, "http___www_thehousingbubbleblog_com_.skp"}, // suspect infinite loop
82 {61, "http___www_jessicaslens_wordpress_com_.skp"}, // joinCoincidence / findT / assert
83 {61, "http___www_partsdata_de_.skp"}, // cubic-cubic intersection reduce checkLinear assert
84 {62, "http___www_blondesmakemoney_blogspot_com_au_.skp"}, // suspect infinite loop
85 {62, "http___www_intellibriefs_blogspot_in_.skp"}, // suspect infinite loop
86 {63, "http___www_tankerenemy_com_.skp"}, // suspect infinite loop
87 {65, "http___www_kpopexplorer_net_.skp"}, // joinCoincidence / findT / assert
88 {65, "http___www_bestthingsinbeauty_blogspot_com_.skp"}, // suspect infinite loop
89 {65, "http___www_wartepop_blogspot_com_br_.skp"}, // !simple->isClosed()
90 {65, "http___www_eolake_blogspot_com_.skp"}, // suspect infinite loop
91 {67, "http___www_cacadordemisterio_blogspot_com_br_.skp"}, // suspect infinite loop
92 {69, "http___www_misnotasyapuntes_blogspot_mx_.skp"}, // suspect infinite loop
93 {69, "http___www_awalkintheparknyc_blogspot_com_.skp"}, // suspect infinite loop
94 {71, "http___www_lokado_de_.skp"}, // joinCoincidence / findT / assert
95 {72, "http___www_karlosdesanjuan_blogspot_com_.skp"}, // suspect infinite loop
96 {73, "http___www_cyberlawsinindia_blogspot_in_.skp"}, // suspect infinite loop
97 {73, "http___www_taxiemmovimento_blogspot_com_br_.skp"}, // suspect infinite loop
98 {74, "http___www_giveusliberty1776_blogspot_com_.skp"}, // suspect infinite loop
99 {75, "http___www_e_cynical_blogspot_gr_.skp"}, // suspect infinite loop
100 {76, "http___www_seopack_blogspot_com_.skp"}, // SkOpAngle::setSector SkASSERT(fSectorStart >= 0);
101 {77, "http___www_sunsky_russia_com_.skp"}, // joinCoincidence / findT / assert (no op test, already fixed hopefully)
102 {78, "http___www_bisnisonlineinfo_com_.skp"}, // suspect infinite loop
103 {79, "http___www_danielsgroupcpa_com_.skp"}, // joinCoincidence / findT / assert (no op test, already fixed hopefully)
104 {80, "http___www_clinique_portugal_com_.skp"}, // suspect infinite loop
105 {81, "http___www_europebusines_blogspot_com_.skp"}, // suspect infinite loop
106 {82, "http___www_apopsignomi_blogspot_gr_.skp"}, // suspect infinite loop
107 {85, "http___www_ajitvadakayil_blogspot_com_.skp"}, // suspect infinite loop
108 {86, "http___www_madhousefamilyreviews_blogspot_co_uk_.skp"}, // suspect infinite loop
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000109};
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000110
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000111size_t skipOverSeptCount = sizeof(skipOverSept) / sizeof(skipOverSept[0]);
112
113enum TestStep {
114 kCompareBits,
115 kEncodeFiles,
116};
117
118enum {
119 kMaxLength = 128,
120 kMaxFiles = 128,
121 kSmallLimit = 1000,
122};
123
124struct TestResult {
125 void init(int dirNo) {
126 fDirNo = dirNo;
127 sk_bzero(fFilename, sizeof(fFilename));
128 fTestStep = kCompareBits;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000129 fScale = 1;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000130 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000131
132 SkString status() {
133 SkString outStr;
134 outStr.printf("%s %d %d\n", fFilename, fPixelError, fTime);
135 return outStr;
136 }
137
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000138 SkString progress() {
139 SkString outStr;
140 outStr.printf("dir=%d %s ", fDirNo, fFilename);
141 if (fPixelError) {
142 outStr.appendf(" err=%d", fPixelError);
143 }
144 if (fTime) {
145 outStr.appendf(" time=%d", fTime);
146 }
147 if (fScale != 1) {
148 outStr.appendf(" scale=%d", fScale);
149 }
150 outStr.appendf("\n");
151 return outStr;
152
153 }
154
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000155 static void Test(int dirNo, const char* filename, TestStep testStep) {
156 TestResult test;
157 test.init(dirNo);
158 test.fTestStep = testStep;
159 strcpy(test.fFilename, filename);
160 test.testOne();
161 }
162
163 void test(int dirNo, const SkString& filename) {
164 init(dirNo);
165 strcpy(fFilename, filename.c_str());
166 testOne();
167 }
168
169 void testOne();
170
171 char fFilename[kMaxLength];
172 TestStep fTestStep;
173 int fDirNo;
174 int fPixelError;
175 int fTime;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000176 int fScale;
177};
178
179class SortByPixel : public TestResult {
180public:
181 bool operator<(const SortByPixel& rh) const {
182 return fPixelError < rh.fPixelError;
183 }
184};
185
186class SortByTime : public TestResult {
187public:
188 bool operator<(const SortByTime& rh) const {
189 return fTime < rh.fTime;
190 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000191};
192
193struct TestState {
194 void init(int dirNo, skiatest::Reporter* reporter) {
195 fReporter = reporter;
196 fResult.init(dirNo);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000197 }
198
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000199 SkTDArray<SortByPixel> fPixelWorst;
200 SkTDArray<SortByTime> fSlowest;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000201 skiatest::Reporter* fReporter;
202 TestResult fResult;
203};
204
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000205struct TestRunner {
206 TestRunner(skiatest::Reporter* reporter, int threadCount)
207 : fNumThreads(threadCount)
208 , fReporter(reporter) {
209 }
210
211 ~TestRunner();
212 void render();
213 int fNumThreads;
214 SkTDArray<class TestRunnable*> fRunnables;
215 skiatest::Reporter* fReporter;
216};
217
218class TestRunnable : public SkRunnable {
219public:
220 TestRunnable(void (*testFun)(TestState*), int dirNo, TestRunner* runner) {
221 fState.init(dirNo, runner->fReporter);
222 fTestFun = testFun;
223 }
224
225 virtual void run() SK_OVERRIDE {
226 SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
227 (*fTestFun)(&fState);
228 }
229
230 TestState fState;
231 void (*fTestFun)(TestState*);
232};
233
234TestRunner::~TestRunner() {
235 for (int index = 0; index < fRunnables.count(); index++) {
236 SkDELETE(fRunnables[index]);
237 }
238}
239
240void TestRunner::render() {
241 SkThreadPool pool(fNumThreads);
242 for (int index = 0; index < fRunnables.count(); ++ index) {
243 pool.add(fRunnables[index]);
244 }
245}
246
247////////////////////////////////////////////////
248
249static const char outOpDir[] = OUT_DIR "opClip";
250static const char outOldDir[] = OUT_DIR "oldClip";
251static const char outSkpDir[] = OUT_DIR "skpTest";
252static const char outDiffDir[] = OUT_DIR "outTest";
253static const char outStatusDir[] = OUT_DIR "statusTest";
254
255static SkString make_filepath(int dirNo, const char* dir, const char* name) {
256 SkString path(dir);
257 if (dirNo) {
258 path.appendf("%d", dirNo);
259 }
260 path.append(PATH_SLASH);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000261 path.append(name);
262 return path;
263}
264
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000265static SkString make_in_dir_name(int dirNo) {
266 SkString dirName(IN_DIR);
267 dirName.appendf("%d", dirNo);
268 if (!sk_exists(dirName.c_str())) {
269 SkDebugf("could not read dir %s\n", dirName.c_str());
270 return SkString();
271 }
272 return dirName;
273}
274
275static bool make_one_out_dir(const char* outDirStr) {
276 SkString outDir = make_filepath(0, outDirStr, "");
277 if (!sk_exists(outDir.c_str())) {
278 if (!sk_mkdir(outDir.c_str())) {
279 SkDebugf("could not create dir %s\n", outDir.c_str());
280 return false;
281 }
282 }
283 return true;
284}
285
286static bool make_out_dirs() {
287 SkString outDir = make_filepath(0, OUT_DIR, "");
288 if (!sk_exists(outDir.c_str())) {
289 if (!sk_mkdir(outDir.c_str())) {
290 SkDebugf("could not create dir %s\n", outDir.c_str());
291 return false;
292 }
293 }
294 return make_one_out_dir(outOldDir)
295 && make_one_out_dir(outOpDir)
296 && make_one_out_dir(outSkpDir)
297 && make_one_out_dir(outDiffDir)
298 && make_one_out_dir(outStatusDir);
299}
300
301static SkString make_png_name(const char* filename) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000302 SkString pngName = SkString(filename);
303 pngName.remove(pngName.size() - 3, 3);
304 pngName.append("png");
305 return pngName;
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000306}
307
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000308static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
309 const int kRowCount = 3;
310 const int kThreshold = 3;
311 int width = SkTMin(gr.width(), sk.width());
312 if (width < kRowCount) {
313 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000314 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000315 int height = SkTMin(gr.height(), sk.height());
316 if (height < kRowCount) {
317 return true;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000318 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000319 int errorTotal = 0;
320 SkTArray<int, true> errorRows;
321 errorRows.push_back_n(width * kRowCount);
322 SkAutoLockPixels autoGr(gr);
323 SkAutoLockPixels autoSk(sk);
324 for (int y = 0; y < height; ++y) {
325 SkPMColor* grRow = gr.getAddr32(0, y);
326 SkPMColor* skRow = sk.getAddr32(0, y);
327 int* base = &errorRows[0];
328 int* cOut = &errorRows[y % kRowCount];
329 for (int x = 0; x < width; ++x) {
330 SkPMColor grColor = grRow[x];
331 SkPMColor skColor = skRow[x];
332 int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
333 int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
334 int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
335 int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
336 if (error < kThreshold || x < 2) {
337 continue;
338 }
339 if (base[x - 2] < kThreshold
340 || base[width + x - 2] < kThreshold
341 || base[width * 2 + x - 2] < kThreshold
342 || base[x - 1] < kThreshold
343 || base[width + x - 1] < kThreshold
344 || base[width * 2 + x - 1] < kThreshold
345 || base[x] < kThreshold
346 || base[width + x] < kThreshold
347 || base[width * 2 + x] < kThreshold) {
348 continue;
349 }
350 errorTotal += error;
351 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000352 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000353 return errorTotal;
354}
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000355
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000356static bool addError(TestState* data, const TestResult& testResult) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000357 if (testResult.fPixelError <= 0 && testResult.fTime <= 0) {
358 return false;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000359 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000360 int worstCount = data->fPixelWorst.count();
361 int pixelError = testResult.fPixelError;
362 if (pixelError > 0) {
363 for (int index = 0; index < worstCount; ++index) {
364 if (pixelError > data->fPixelWorst[index].fPixelError) {
365 data->fPixelWorst[index] = *(SortByPixel*) &testResult;
366 return true;
367 }
368 }
369 }
370 int slowCount = data->fSlowest.count();
371 int time = testResult.fTime;
372 if (time > 0) {
373 for (int index = 0; index < slowCount; ++index) {
374 if (time > data->fSlowest[index].fTime) {
375 data->fSlowest[index] = *(SortByTime*) &testResult;
376 return true;
377 }
378 }
379 }
380 if (pixelError > 0 && worstCount < kMaxFiles) {
381 *data->fPixelWorst.append() = *(SortByPixel*) &testResult;
382 return true;
383 }
384 if (time > 0 && slowCount < kMaxFiles) {
385 *data->fSlowest.append() = *(SortByTime*) &testResult;
386 return true;
387 }
388 return false;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000389}
390
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000391static SkMSec timePict(SkPicture* pic, SkCanvas* canvas) {
392 canvas->save();
393 int pWidth = pic->width();
394 int pHeight = pic->height();
395 const int maxDimension = 1000;
396 const int slices = 3;
397 int xInterval = SkTMax(pWidth - maxDimension, 0) / (slices - 1);
398 int yInterval = SkTMax(pHeight - maxDimension, 0) / (slices - 1);
skia.committer@gmail.comf54ad6f2013-11-02 07:02:02 +0000399 SkRect rect = {0, 0, SkIntToScalar(SkTMin(maxDimension, pWidth)),
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000400 SkIntToScalar(SkTMin(maxDimension, pHeight))};
401 canvas->clipRect(rect);
402 SkMSec start = SkTime::GetMSecs();
403 for (int x = 0; x < slices; ++x) {
404 for (int y = 0; y < slices; ++y) {
405 pic->draw(canvas);
406 canvas->translate(0, SkIntToScalar(yInterval));
407 }
408 canvas->translate(SkIntToScalar(xInterval), SkIntToScalar(-yInterval * slices));
409 }
410 SkMSec end = SkTime::GetMSecs();
411 canvas->restore();
412 return end - start;
413}
414
415static void drawPict(SkPicture* pic, SkCanvas* canvas, int scale) {
416 canvas->clear(SK_ColorWHITE);
417 if (scale != 1) {
418 canvas->save();
419 canvas->scale(1.0f / scale, 1.0f / scale);
420 }
421 pic->draw(canvas);
422 if (scale != 1) {
423 canvas->restore();
424 }
425}
426
427static void writePict(const SkBitmap& bitmap, const char* outDir, const char* pngName) {
428 SkString outFile = make_filepath(0, outDir, pngName);
429 if (!SkImageEncoder::EncodeFile(outFile.c_str(), bitmap,
430 SkImageEncoder::kPNG_Type, 100)) {
431 SkDebugf("unable to encode gr %s (width=%d height=%d)\n", pngName,
432 bitmap.width(), bitmap.height());
433 }
434}
435
436void TestResult::testOne() {
437 SkPicture* pic = NULL;
438 {
439 #if DEBUG_SHOW_TEST_NAME
440 if (fTestStep == kCompareBits) {
441 SkString testName(fFilename);
442 const char http[] = "http";
443 if (testName.startsWith(http)) {
444 testName.remove(0, sizeof(http) - 1);
445 }
446 while (testName.startsWith("_")) {
447 testName.remove(0, 1);
448 }
449 const char dotSkp[] = ".skp";
450 if (testName.endsWith(dotSkp)) {
451 size_t len = testName.size();
452 testName.remove(len - (sizeof(dotSkp) - 1), sizeof(dotSkp) - 1);
453 }
454 testName.prepend("skp");
455 testName.append("1");
456 strncpy(DEBUG_FILENAME_STRING, testName.c_str(), DEBUG_FILENAME_STRING_LENGTH);
457 } else if (fTestStep == kEncodeFiles) {
458 strncpy(DEBUG_FILENAME_STRING, "", DEBUG_FILENAME_STRING_LENGTH);
459 }
460 #endif
461 SkString path = make_filepath(fDirNo, IN_DIR, fFilename);
462 SkFILEStream stream(path.c_str());
463 if (!stream.isValid()) {
464 SkDebugf("invalid stream %s\n", path.c_str());
465 goto finish;
466 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000467 pic = SkPicture::CreateFromStream(&stream, &SkImageDecoder::DecodeMemory);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000468 if (!pic) {
469 SkDebugf("unable to decode %s\n", fFilename);
470 goto finish;
471 }
472 int width = pic->width();
473 int height = pic->height();
474 SkBitmap oldBitmap, opBitmap;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000475 fScale = 1;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000476 while (width / fScale > 32767 || height / fScale > 32767) {
477 ++fScale;
478 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000479 do {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000480 int dimX = (width + fScale - 1) / fScale;
481 int dimY = (height + fScale - 1) / fScale;
mike@reedtribe.orgdeee4962014-02-13 14:41:43 +0000482 if (oldBitmap.allocN32Pixels(dimX, dimY) &&
483 opBitmap.allocN32Pixels(dimX, dimY)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000484 break;
485 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000486 SkDebugf("-%d-", fScale);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000487 } while (++fScale < 256);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000488 if (fScale >= 256) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000489 SkDebugf("unable to allocate bitmap for %s (w=%d h=%d)\n", fFilename,
490 width, height);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000491 goto finish;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000492 }
493 oldBitmap.eraseColor(SK_ColorWHITE);
494 SkCanvas oldCanvas(oldBitmap);
495 oldCanvas.setAllowSimplifyClip(false);
496 opBitmap.eraseColor(SK_ColorWHITE);
497 SkCanvas opCanvas(opBitmap);
498 opCanvas.setAllowSimplifyClip(true);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000499 drawPict(pic, &oldCanvas, fScale);
500 drawPict(pic, &opCanvas, fScale);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000501 if (fTestStep == kCompareBits) {
502 fPixelError = similarBits(oldBitmap, opBitmap);
503 int oldTime = timePict(pic, &oldCanvas);
504 int opTime = timePict(pic, &opCanvas);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000505 fTime = SkTMax(0, oldTime - opTime);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000506 } else if (fTestStep == kEncodeFiles) {
507 SkString pngStr = make_png_name(fFilename);
508 const char* pngName = pngStr.c_str();
509 writePict(oldBitmap, outOldDir, pngName);
510 writePict(opBitmap, outOpDir, pngName);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000511 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000512 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000513finish:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000514 if (pic) {
515 pic->unref();
516 }
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000517}
518
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000519static SkString makeStatusString(int dirNo) {
520 SkString statName;
521 statName.printf("stats%d.txt", dirNo);
522 SkString statusFile = make_filepath(0, outStatusDir, statName.c_str());
523 return statusFile;
524}
525
526class PreParser {
527public:
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000528 PreParser(int dirNo, bool threaded)
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000529 : fDirNo(dirNo)
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000530 , fIndex(0)
531 , fThreaded(threaded) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000532 SkString statusPath = makeStatusString(dirNo);
533 if (!sk_exists(statusPath.c_str())) {
534 return;
535 }
536 SkFILEStream reader;
537 reader.setPath(statusPath.c_str());
538 while (fetch(reader, &fResults.push_back()))
539 ;
540 fResults.pop_back();
541 }
542
543 bool fetch(SkFILEStream& reader, TestResult* result) {
544 char c;
545 int i = 0;
546 result->init(fDirNo);
547 result->fPixelError = 0;
548 result->fTime = 0;
549 do {
550 bool readOne = reader.read(&c, 1) != 0;
551 if (!readOne) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000552// SkASSERT(i == 0); // the current text may be incomplete -- if so, ignore it
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000553 return false;
554 }
555 if (c == ' ') {
556 result->fFilename[i++] = '\0';
557 break;
558 }
559 result->fFilename[i++] = c;
560 SkASSERT(i < kMaxLength);
561 } while (true);
562 do {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000563 if (!reader.read(&c, 1)) {
564 return false;
skia.committer@gmail.come02c5da2014-04-26 03:04:35 +0000565 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000566 if (c == ' ') {
567 break;
568 }
569 SkASSERT(c >= '0' && c <= '9');
570 result->fPixelError = result->fPixelError * 10 + (c - '0');
571 } while (true);
572 bool minus = false;
573 do {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000574 if (!reader.read(&c, 1)) {
575 return false;
576 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000577 if (c == '\n') {
578 break;
579 }
580 if (c == '-') {
581 minus = true;
582 continue;
583 }
584 SkASSERT(c >= '0' && c <= '9');
585 result->fTime = result->fTime * 10 + (c - '0');
586 } while (true);
587 if (minus) {
588 result->fTime = -result->fTime;
589 }
590 return true;
591 }
592
593 bool match(const SkString& filename, SkFILEWStream* stream, TestResult* result) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000594 if (fThreaded) {
595 for (int index = 0; index < fResults.count(); ++index) {
596 const TestResult& test = fResults[index];
597 if (filename.equals(test.fFilename)) {
598 *result = test;
599 SkString outStr(result->status());
600 stream->write(outStr.c_str(), outStr.size());
601 return true;
602 }
603 }
604 } else if (fIndex < fResults.count()) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000605 *result = fResults[fIndex++];
606 SkASSERT(filename.equals(result->fFilename));
607 SkString outStr(result->status());
608 stream->write(outStr.c_str(), outStr.size());
609 return true;
610 }
611 return false;
612 }
613
614private:
615 int fDirNo;
616 int fIndex;
617 SkTArray<TestResult, true> fResults;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000618 bool fThreaded;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000619};
620
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000621static bool doOneDir(TestState* state, bool threaded) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000622 int dirNo = state->fResult.fDirNo;
623 skiatest::Reporter* reporter = state->fReporter;
624 SkString dirName = make_in_dir_name(dirNo);
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000625 if (!dirName.size()) {
626 return false;
627 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000628 SkOSFile::Iter iter(dirName.c_str(), "skp");
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000629 SkString filename;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000630 int testCount = 0;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000631 PreParser preParser(dirNo, threaded);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000632 SkFILEWStream statusStream(makeStatusString(dirNo).c_str());
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000633 while (iter.next(&filename)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000634 for (size_t index = 0; index < skipOverSeptCount; ++index) {
635 if (skipOverSept[index].directory == dirNo
636 && strcmp(filename.c_str(), skipOverSept[index].filename) == 0) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000637 goto checkEarlyExit;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000638 }
639 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000640 if (preParser.match(filename, &statusStream, &state->fResult)) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000641 (void) addError(state, state->fResult);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000642 ++testCount;
643 goto checkEarlyExit;
644 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000645 {
646 TestResult& result = state->fResult;
647 result.test(dirNo, filename);
648 SkString outStr(result.status());
649 statusStream.write(outStr.c_str(), outStr.size());
650 statusStream.flush();
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000651 if (addError(state, result)) {
652 SkDebugf("%s", result.progress().c_str());
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000653 }
654 }
655 ++testCount;
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000656 if (reporter->verbose()) {
657 SkDebugf(".");
658 if (++testCount % 100 == 0) {
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000659 SkDebugf("%d\n", testCount);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000660 }
skia.committer@gmail.com2b34fe02013-05-08 07:01:40 +0000661 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000662checkEarlyExit:
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000663 if (0 && testCount >= 1) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000664 return true;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000665 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000666 }
667 return true;
668}
669
670static bool initTest() {
671#if !defined SK_BUILD_FOR_WIN && !defined SK_BUILD_FOR_MAC
672 SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
673 SK_CONF_SET("images.png.suppressDecoderWarnings", true);
674#endif
675 return make_out_dirs();
676}
677
678static void encodeFound(skiatest::Reporter* reporter, TestState& state) {
679 if (reporter->verbose()) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000680 SkTDArray<SortByPixel*> worst;
681 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
682 *worst.append() = &state.fPixelWorst[index];
683 }
684 SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1);
685 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
686 const TestResult& result = *worst[index];
687 SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError);
688 }
689 SkTDArray<SortByTime*> slowest;
690 for (int index = 0; index < state.fSlowest.count(); ++index) {
691 *slowest.append() = &state.fSlowest[index];
692 }
693 SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1);
694 for (int index = 0; index < slowest.count(); ++index) {
695 const TestResult& result = *slowest[index];
696 SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000697 }
698 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000699 for (int index = 0; index < state.fPixelWorst.count(); ++index) {
700 const TestResult& result = state.fPixelWorst[index];
701 TestResult::Test(result.fDirNo, result.fFilename, kEncodeFiles);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000702 if (state.fReporter->verbose()) SkDebugf("+");
703 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000704}
705
tfarina@chromium.org78e7b4e2014-01-02 21:45:03 +0000706DEF_TEST(PathOpsSkpClip, reporter) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000707 if (!initTest()) {
708 return;
709 }
710 SkTArray<TestResult, true> errors;
711 TestState state;
712 state.init(0, reporter);
713 for (int dirNo = 1; dirNo <= 100; ++dirNo) {
714 if (reporter->verbose()) {
715 SkDebugf("dirNo=%d\n", dirNo);
716 }
717 state.fResult.fDirNo = dirNo;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000718 if (!doOneDir(&state, false)) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000719 break;
720 }
721 }
722 encodeFound(reporter, state);
723}
724
725static void testSkpClipMain(TestState* data) {
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000726 (void) doOneDir(data, true);
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000727}
728
tfarina@chromium.org78e7b4e2014-01-02 21:45:03 +0000729DEF_TEST(PathOpsSkpClipThreaded, reporter) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000730 if (!initTest()) {
731 return;
732 }
733 int threadCount = reporter->allowThreaded() ? SkThreadPool::kThreadPerCore : 1;
734 TestRunner testRunner(reporter, threadCount);
735 for (int dirNo = 1; dirNo <= 100; ++dirNo) {
736 *testRunner.fRunnables.append() = SkNEW_ARGS(TestRunnable,
737 (&testSkpClipMain, dirNo, &testRunner));
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000738 }
739 testRunner.render();
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000740 TestState state;
741 state.init(0, reporter);
742 for (int dirNo = 1; dirNo <= 100; ++dirNo) {
743 TestState& testState = testRunner.fRunnables[dirNo - 1]->fState;
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000744 for (int inner = 0; inner < testState.fPixelWorst.count(); ++inner) {
745 SkASSERT(testState.fResult.fDirNo == dirNo);
746 addError(&state, testState.fPixelWorst[inner]);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000747 }
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000748 }
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000749 encodeFound(reporter, state);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000750}
751
tfarina@chromium.org78e7b4e2014-01-02 21:45:03 +0000752DEF_TEST(PathOpsSkpClipOneOff, reporter) {
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000753 if (!initTest()) {
754 return;
755 }
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000756 const int testIndex = 43 - 37;
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000757 int dirNo = skipOverSept[testIndex].directory;
758 SkAssertResult(make_in_dir_name(dirNo).size());
759 SkString filename(skipOverSept[testIndex].filename);
760 TestResult state;
761 state.test(dirNo, filename);
762 if (reporter->verbose()) {
763 SkDebugf("%s", state.status().c_str());
764 }
765 state.fTestStep = kEncodeFiles;
766 state.testOne();
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000767}