1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff.h" 8e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff_html.h" 9e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff_utils.h" 10e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkBitmap.h" 1146256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com#include "SkData.h" 124b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com#include "SkImageEncoder.h" 134b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com#include "SkOSFile.h" 14bf111d7bc9ba3857433e30eae27f0272c34ed0fbBen Wagner#include "SkOSPath.h" 154b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com#include "SkStream.h" 161b3387b5cfef150c3237c6a8700b2d6f3730e4ceHal Canary#include "SkPixelRef.h" 17a7e9f05119174848c6be5028568f46eb5e85398ebungeman#include "../private/SkTDArray.h" 1876a834a107af38fb2e85413bc7a46e555c444a85reed#include "../private/SkTSearch.h" 194b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 2060e0fee6d4acff638ccc9670c4055aced529a7a0bungeman#include <stdlib.h> 2160e0fee6d4acff638ccc9670c4055aced529a7a0bungeman 224b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com/** 234b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * skdiff 244b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * 254b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * Given three directory names, expects to find identically-named files in 264b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * each of the first two; the first are treated as a set of baseline, 274b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * the second a set of variant images, and a diff image is written into the 284b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * third directory for each pair. 297d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com * Creates an index.html in the current third directory to compare each 304b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com * pair that does not match exactly. 3171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com * Recursively descends directories, unless run with --norecurse. 32be6188d64721850723c19d5a7a4f007a675300f4epoger@google.com * 33be6188d64721850723c19d5a7a4f007a675300f4epoger@google.com * Returns zero exit code if all images match across baseDir and comparisonDir. 344b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com */ 354b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 36a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.comtypedef SkTDArray<SkString*> StringArray; 37a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.comtypedef StringArray FileArray; 385fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 393a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breedstatic void add_unique_basename(StringArray* array, const SkString& filename) { 403a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed // trim off dirs 413a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed const char* src = filename.c_str(); 42bf111d7bc9ba3857433e30eae27f0272c34ed0fbBen Wagner const char* trimmed = strrchr(src, SkOSPath::SEPARATOR); 433a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed if (trimmed) { 443a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed trimmed += 1; // skip the separator 453a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } else { 463a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed trimmed = src; 473a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 483a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed const char* end = strrchr(trimmed, '.'); 493a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed if (!end) { 503a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed end = trimmed + strlen(trimmed); 513a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 523a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed SkString result(trimmed, end - trimmed); 533a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed 543a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed // only add unique entries 553a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed for (int i = 0; i < array->count(); ++i) { 563a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed if (*array->getAt(i) == result) { 573a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed return; 583a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 593a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 603a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed *array->append() = new SkString(result); 613a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed} 623a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed 639dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.comstruct DiffSummary { 649dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com DiffSummary () 65e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com : fNumMatches(0) 66e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com , fNumMismatches(0) 67e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com , fMaxMismatchV(0) 68fe9172705791848ebfe5b5630973b7e67305f64cbungeman , fMaxMismatchPercent(0) { } 699dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com 705fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com ~DiffSummary() { 71e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int i = 0; i < DiffRecord::kResultCount; ++i) { 7276222c0ef2c5e63d2d9875e1cdb89e52049c7754epoger@google.com fResultsOfType[i].deleteAll(); 7376222c0ef2c5e63d2d9875e1cdb89e52049c7754epoger@google.com } 74e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 75e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 76e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com fStatusOfType[base][comparison].deleteAll(); 77e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 780264fb4543b0d8cebe00f1ee32433784f4ceb074skia.committer@gmail.com } 795fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } 805fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 819dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com uint32_t fNumMatches; 829dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com uint32_t fNumMismatches; 839dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com uint32_t fMaxMismatchV; 849dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com float fMaxMismatchPercent; 859dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com 86e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com FileArray fResultsOfType[DiffRecord::kResultCount]; 87e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com FileArray fStatusOfType[DiffResource::kStatusCount][DiffResource::kStatusCount]; 88e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 893a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed StringArray fFailedBaseNames[DiffRecord::kResultCount]; 903a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed 91e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com void printContents(const FileArray& fileArray, 92e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const char* baseStatus, const char* comparisonStatus, 93e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool listFilenames) { 94e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int n = fileArray.count(); 95e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("%d file pairs %s in baseDir and %s in comparisonDir", 96e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com n, baseStatus, comparisonStatus); 97e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (listFilenames) { 98e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf(": "); 99e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int i = 0; i < n; ++i) { 100e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("%s ", fileArray[i]->c_str()); 101e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 102e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 103e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("\n"); 104e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 105e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 106e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com void printStatus(bool listFilenames, 107e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool failOnStatusType[DiffResource::kStatusCount] 108e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com [DiffResource::kStatusCount]) { 109e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com typedef DiffResource::Status Status; 110e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 111e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 112e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com Status baseStatus = static_cast<Status>(base); 113e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 114e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com Status comparisonStatus = static_cast<Status>(comparison); 115e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const FileArray& fileArray = fStatusOfType[base][comparison]; 116e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (fileArray.count() > 0) { 117e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (failOnStatusType[base][comparison]) { 118e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf(" [*] "); 119e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 120e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf(" [_] "); 121e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 122e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printContents(fileArray, 123e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffResource::getStatusDescription(baseStatus), 124e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffResource::getStatusDescription(comparisonStatus), 125e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com listFilenames); 126e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 127e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 128e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 129e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 1305fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 1313af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com // Print a line about the contents of this FileArray to stdout. 13246a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com void printContents(const FileArray& fileArray, const char* headerText, bool listFilenames) { 13376222c0ef2c5e63d2d9875e1cdb89e52049c7754epoger@google.com int n = fileArray.count(); 1343af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("%d file pairs %s", n, headerText); 1353af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com if (listFilenames) { 1363af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf(": "); 1373af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com for (int i = 0; i < n; ++i) { 1383af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("%s ", fileArray[i]->c_str()); 1395fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } 1405fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } 1413af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("\n"); 14276222c0ef2c5e63d2d9875e1cdb89e52049c7754epoger@google.com } 14376222c0ef2c5e63d2d9875e1cdb89e52049c7754epoger@google.com 144e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com void print(bool listFilenames, bool failOnResultType[DiffRecord::kResultCount], 145e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool failOnStatusType[DiffResource::kStatusCount] 146e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com [DiffResource::kStatusCount]) { 1473af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("\ncompared %d file pairs:\n", fNumMatches + fNumMismatches); 148e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int resultInt = 0; resultInt < DiffRecord::kResultCount; ++resultInt) { 149e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord::Result result = static_cast<DiffRecord::Result>(resultInt); 1503af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com if (failOnResultType[result]) { 1513af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("[*] "); 1523af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com } else { 1533af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("[_] "); 1543af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com } 155e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printContents(fResultsOfType[result], DiffRecord::getResultDescription(result), 156e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com listFilenames); 157e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (DiffRecord::kCouldNotCompare_Result == result) { 158e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printStatus(listFilenames, failOnStatusType); 159e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 16046a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com } 1613af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("(results marked with [*] will cause nonzero return value)\n"); 1623af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com printf("\nnumber of mismatching file pairs: %d\n", fNumMismatches); 1639dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com if (fNumMismatches > 0) { 1649dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com printf("Maximum pixel intensity mismatch %d\n", fMaxMismatchV); 16546a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com printf("Largest area mismatch was %.2f%% of pixels\n",fMaxMismatchPercent); 1669dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com } 1679dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com } 1689dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com 1693a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed void printfFailingBaseNames(const char separator[]) { 1703a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed for (int resultInt = 0; resultInt < DiffRecord::kResultCount; ++resultInt) { 1713a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed const StringArray& array = fFailedBaseNames[resultInt]; 1723a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed if (array.count()) { 1733a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed printf("%s [%d]%s", DiffRecord::ResultNames[resultInt], array.count(), separator); 1743a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed for (int j = 0; j < array.count(); ++j) { 1753a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed printf("%s%s", array[j]->c_str(), separator); 1763a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 1773a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed printf("\n"); 1783a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 1793a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 1803a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 1813a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed 1829dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com void add (DiffRecord* drp) { 18346256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com uint32_t mismatchValue; 184292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com 185e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (drp->fBase.fFilename.equals(drp->fComparison.fFilename)) { 186e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com fResultsOfType[drp->fResult].push(new SkString(drp->fBase.fFilename)); 187e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 188e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString* blame = new SkString("("); 189e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com blame->append(drp->fBase.fFilename); 190e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com blame->append(", "); 191e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com blame->append(drp->fComparison.fFilename); 192e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com blame->append(")"); 193e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com fResultsOfType[drp->fResult].push(blame); 194e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 195292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com switch (drp->fResult) { 196e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case DiffRecord::kEqualBits_Result: 197292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com fNumMatches++; 198292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com break; 199e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case DiffRecord::kEqualPixels_Result: 20046256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com fNumMatches++; 201292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com break; 202e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case DiffRecord::kDifferentSizes_Result: 2035fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com fNumMismatches++; 204292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com break; 205e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case DiffRecord::kDifferentPixels_Result: 2069dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com fNumMismatches++; 2079dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com if (drp->fFractionDifference * 100 > fMaxMismatchPercent) { 2089dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com fMaxMismatchPercent = drp->fFractionDifference * 100; 2099dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com } 21046256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com mismatchValue = MAX3(drp->fMaxMismatchR, drp->fMaxMismatchG, 21146256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com drp->fMaxMismatchB); 21246256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com if (mismatchValue > fMaxMismatchV) { 21346256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com fMaxMismatchV = mismatchValue; 2149dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com } 215292aff6aca8677d5159cc2f7fa2bb933a450f049epoger@google.com break; 216e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case DiffRecord::kCouldNotCompare_Result: 21746256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com fNumMismatches++; 218e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com fStatusOfType[drp->fBase.fStatus][drp->fComparison.fStatus].push( 219e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com new SkString(drp->fBase.fFilename)); 22046256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com break; 221e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case DiffRecord::kUnknown_Result: 22246256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com SkDEBUGFAIL("adding uncategorized DiffRecord"); 22346256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com break; 22446256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com default: 22546256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com SkDEBUGFAIL("adding DiffRecord with unhandled fResult value"); 22646256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com break; 2279dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com } 2283a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed 2293a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed switch (drp->fResult) { 2303a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed case DiffRecord::kEqualBits_Result: 2313a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed case DiffRecord::kEqualPixels_Result: 2323a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed break; 2333a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed default: 2343a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed add_unique_basename(&fFailedBaseNames[drp->fResult], drp->fBase.fFilename); 2353a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed break; 2363a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 2379dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com } 2389dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com}; 2399dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com 240a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com/// Returns true if string contains any of these substrings. 241a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.comstatic bool string_contains_any_of(const SkString& string, 242a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com const StringArray& substrings) { 243a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com for (int i = 0; i < substrings.count(); i++) { 244a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (string.contains(substrings[i]->c_str())) { 245a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com return true; 246a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 247a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 248a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com return false; 249a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com} 250a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com 25171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com/// Internal (potentially recursive) implementation of get_file_list. 25271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.comstatic void get_file_list_subdir(const SkString& rootDir, const SkString& subDir, 25371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com const StringArray& matchSubstrings, 25471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com const StringArray& nomatchSubstrings, 25571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com bool recurseIntoSubdirs, FileArray *files) { 25671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com bool isSubDirEmpty = subDir.isEmpty(); 25771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkString dir(rootDir); 25871329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (!isSubDirEmpty) { 25971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com dir.append(PATH_DIV_STR); 26071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com dir.append(subDir); 26171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 26271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com 26371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com // Iterate over files (not directories) within dir. 26471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkOSFile::Iter fileIterator(dir.c_str()); 26571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkString fileName; 26671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com while (fileIterator.next(&fileName, false)) { 26771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (fileName.startsWith(".")) { 26871329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com continue; 26971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 27071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkString pathRelativeToRootDir(subDir); 27171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (!isSubDirEmpty) { 27271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com pathRelativeToRootDir.append(PATH_DIV_STR); 27371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 27471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com pathRelativeToRootDir.append(fileName); 27571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (string_contains_any_of(pathRelativeToRootDir, matchSubstrings) && 27671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com !string_contains_any_of(pathRelativeToRootDir, nomatchSubstrings)) { 27771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com files->push(new SkString(pathRelativeToRootDir)); 27871329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 27971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 28071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com 28171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com // Recurse into any non-ignored subdirectories. 28271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (recurseIntoSubdirs) { 28371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkOSFile::Iter dirIterator(dir.c_str()); 28471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkString dirName; 28571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com while (dirIterator.next(&dirName, true)) { 28671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (dirName.startsWith(".")) { 28771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com continue; 28871329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 28971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com SkString pathRelativeToRootDir(subDir); 29071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (!isSubDirEmpty) { 29171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com pathRelativeToRootDir.append(PATH_DIV_STR); 29271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 29371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com pathRelativeToRootDir.append(dirName); 29471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (!string_contains_any_of(pathRelativeToRootDir, nomatchSubstrings)) { 29571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com get_file_list_subdir(rootDir, pathRelativeToRootDir, 29671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, 29771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com files); 29871329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 29971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 30071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 30171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com} 30271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com 30371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com/// Iterate over dir and get all files whose filename: 30471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com/// - matches any of the substrings in matchSubstrings, but... 30571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com/// - DOES NOT match any of the substrings in nomatchSubstrings 30671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com/// - DOES NOT start with a dot (.) 30771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com/// Adds the matching files to the list in *files. 308a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.comstatic void get_file_list(const SkString& dir, 309a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com const StringArray& matchSubstrings, 310a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com const StringArray& nomatchSubstrings, 31171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com bool recurseIntoSubdirs, FileArray *files) { 31271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com get_file_list_subdir(dir, SkString(""), 31371329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, 31471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com files); 3155fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com} 3165fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 3175fd53858f83776025e63de44b2e0a1822b932c39epoger@google.comstatic void release_file_list(FileArray *files) { 3185fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com files->deleteAll(); 3195fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com} 3205fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 3215fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com/// Comparison routines for qsort, sort by file names. 3225fd53858f83776025e63de44b2e0a1822b932c39epoger@google.comstatic int compare_file_name_metrics(SkString **lhs, SkString **rhs) { 3235fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com return strcmp((*lhs)->c_str(), (*rhs)->c_str()); 3245fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com} 3255fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 326e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comclass AutoReleasePixels { 327e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.compublic: 328e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com AutoReleasePixels(DiffRecord* drp) 329e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com : fDrp(drp) { 33096fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(drp != nullptr); 331e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 332e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com ~AutoReleasePixels() { 3331b3387b5cfef150c3237c6a8700b2d6f3730e4ceHal Canary fDrp->fBase.fBitmap.setPixelRef(nullptr, 0, 0); 3341b3387b5cfef150c3237c6a8700b2d6f3730e4ceHal Canary fDrp->fComparison.fBitmap.setPixelRef(nullptr, 0, 0); 3351b3387b5cfef150c3237c6a8700b2d6f3730e4ceHal Canary fDrp->fDifference.fBitmap.setPixelRef(nullptr, 0, 0); 3361b3387b5cfef150c3237c6a8700b2d6f3730e4ceHal Canary fDrp->fWhite.fBitmap.setPixelRef(nullptr, 0, 0); 337e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 338e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 339e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comprivate: 340e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord* fDrp; 341e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com}; 342e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 343e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comstatic void get_bounds(DiffResource& resource, const char* name) { 344e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (resource.fBitmap.empty() && !DiffResource::isStatusFailed(resource.fStatus)) { 34538d909ec2875f79952de08f36adfaac5680d2c53bungeman sk_sp<SkData> fileBits(read_file(resource.fFullPath.c_str())); 34638d909ec2875f79952de08f36adfaac5680d2c53bungeman if (fileBits) { 34742943c8aa9c611c18ad0f1a30a27669f3d82239creed get_bitmap(fileBits, resource, true); 34838d909ec2875f79952de08f36adfaac5680d2c53bungeman } else { 349e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("WARNING: couldn't read %s file <%s>\n", name, resource.fFullPath.c_str()); 350e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com resource.fStatus = DiffResource::kCouldNotRead_Status; 351e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 352e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 353e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com} 354e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 355e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comstatic void get_bounds(DiffRecord& drp) { 356e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com get_bounds(drp.fBase, "base"); 357e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com get_bounds(drp.fComparison, "comparison"); 358e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com} 359e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 36093d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#ifdef SK_OS_WIN 36193d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_RED "" 36293d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_GREEN "" 36393d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_YELLOW "" 36493d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_RESET "" 36593d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#else 36693d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_RED "\x1b[31m" 36793d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_GREEN "\x1b[32m" 36893d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_YELLOW "\x1b[33m" 36993d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define ANSI_COLOR_RESET "\x1b[0m" 37093d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#endif 37193d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org 37293d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org#define VERBOSE_STATUS(status,color,filename) if (verbose) printf( "[ " color " %10s " ANSI_COLOR_RESET " ] %s\n", status, filename->c_str()) 37393d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org 3744b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com/// Creates difference images, returns the number that have a 0 metric. 375a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com/// If outputDir.isEmpty(), don't write out diff files. 3769dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.comstatic void create_diff_images (DiffMetricProc dmp, 3779dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com const int colorThreshold, 3789dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com RecordArray* differences, 3799dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com const SkString& baseDir, 3809dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com const SkString& comparisonDir, 3819dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com const SkString& outputDir, 382a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com const StringArray& matchSubstrings, 383a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com const StringArray& nomatchSubstrings, 38471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com bool recurseIntoSubdirs, 385e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool getBounds, 38693d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org bool verbose, 3879dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com DiffSummary* summary) { 388a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com SkASSERT(!baseDir.isEmpty()); 389a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com SkASSERT(!comparisonDir.isEmpty()); 3904b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 3915fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com FileArray baseFiles; 3925fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com FileArray comparisonFiles; 3935fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 39471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com get_file_list(baseDir, matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, &baseFiles); 39571329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com get_file_list(comparisonDir, matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, 396a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com &comparisonFiles); 3975fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 398a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (!baseFiles.isEmpty()) { 399c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com qsort(baseFiles.begin(), baseFiles.count(), sizeof(SkString*), 400c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com SkCastForQSort(compare_file_name_metrics)); 401a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 402a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (!comparisonFiles.isEmpty()) { 403c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com qsort(comparisonFiles.begin(), comparisonFiles.count(), 404c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com sizeof(SkString*), SkCastForQSort(compare_file_name_metrics)); 405a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 40666008526673b55dcce69ba947186c5e9428a62e5epoger@google.com 407235cbf23c4836f87a4d53ac48345942ff605a739brianosman if (!outputDir.isEmpty()) { 408235cbf23c4836f87a4d53ac48345942ff605a739brianosman sk_mkdir(outputDir.c_str()); 409235cbf23c4836f87a4d53ac48345942ff605a739brianosman } 410235cbf23c4836f87a4d53ac48345942ff605a739brianosman 4115fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com int i = 0; 4125fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com int j = 0; 4135fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 4145fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com while (i < baseFiles.count() && 4155fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com j < comparisonFiles.count()) { 4164b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 417e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString basePath(baseDir); 418e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString comparisonPath(comparisonDir); 4195fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 420e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord *drp = new DiffRecord; 421e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int v = strcmp(baseFiles[i]->c_str(), comparisonFiles[j]->c_str()); 4225fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 4235fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com if (v < 0) { 4245fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com // in baseDir, but not in comparisonDir 425e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 426e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 427e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com basePath.append(*baseFiles[i]); 428e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com comparisonPath.append(*baseFiles[i]); 429e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 430e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFilename = *baseFiles[i]; 431e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath = basePath; 432e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kExists_Status; 433e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 434e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFilename = *baseFiles[i]; 435e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath = comparisonPath; 436e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kDoesNotExist_Status; 437e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 43893d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org VERBOSE_STATUS("MISSING", ANSI_COLOR_YELLOW, baseFiles[i]); 43993d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org 4405fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com ++i; 4415fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } else if (v > 0) { 4425fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com // in comparisonDir, but not in baseDir 443e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 444e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 445e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com basePath.append(*comparisonFiles[j]); 446e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com comparisonPath.append(*comparisonFiles[j]); 447e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 448e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFilename = *comparisonFiles[j]; 449e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath = basePath; 450e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kDoesNotExist_Status; 451e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 452e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFilename = *comparisonFiles[j]; 453e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath = comparisonPath; 454e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kExists_Status; 455e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 45693d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org VERBOSE_STATUS("MISSING", ANSI_COLOR_YELLOW, comparisonFiles[j]); 45793d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org 4585fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com ++j; 4595fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } else { 46046256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com // Found the same filename in both baseDir and comparisonDir. 461e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkASSERT(DiffRecord::kUnknown_Result == drp->fResult); 462e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 463e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com basePath.append(*baseFiles[i]); 464e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com comparisonPath.append(*comparisonFiles[j]); 465e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 466e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFilename = *baseFiles[i]; 467e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath = basePath; 468e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kExists_Status; 469e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 470e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFilename = *comparisonFiles[j]; 471e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath = comparisonPath; 472e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kExists_Status; 473e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 47438d909ec2875f79952de08f36adfaac5680d2c53bungeman sk_sp<SkData> baseFileBits(read_file(drp->fBase.fFullPath.c_str())); 47549f085dddff10473b6ebf832a974288300224e60bsalomon if (baseFileBits) { 476e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kRead_Status; 477e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 47838d909ec2875f79952de08f36adfaac5680d2c53bungeman sk_sp<SkData> comparisonFileBits(read_file(drp->fComparison.fFullPath.c_str())); 47949f085dddff10473b6ebf832a974288300224e60bsalomon if (comparisonFileBits) { 480e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kRead_Status; 481e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 48296fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == baseFileBits || nullptr == comparisonFileBits) { 48396fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == baseFileBits) { 484e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kCouldNotRead_Status; 48593d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org VERBOSE_STATUS("READ FAIL", ANSI_COLOR_RED, baseFiles[i]); 486e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 48796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == comparisonFileBits) { 488e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kCouldNotRead_Status; 48993d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org VERBOSE_STATUS("READ FAIL", ANSI_COLOR_RED, comparisonFiles[j]); 490e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 491e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 492e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 49338d909ec2875f79952de08f36adfaac5680d2c53bungeman } else if (are_buffers_equal(baseFileBits.get(), comparisonFileBits.get())) { 494e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kEqualBits_Result; 49593d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org VERBOSE_STATUS("MATCH", ANSI_COLOR_GREEN, baseFiles[i]); 49646256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com } else { 497e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com AutoReleasePixels arp(drp); 49842943c8aa9c611c18ad0f1a30a27669f3d82239creed get_bitmap(baseFileBits, drp->fBase, false); 49942943c8aa9c611c18ad0f1a30a27669f3d82239creed get_bitmap(comparisonFileBits, drp->fComparison, false); 50093d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org VERBOSE_STATUS("DIFFERENT", ANSI_COLOR_RED, baseFiles[i]); 501e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (DiffResource::kDecoded_Status == drp->fBase.fStatus && 502e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffResource::kDecoded_Status == drp->fComparison.fStatus) { 503e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com create_and_write_diff_image(drp, dmp, colorThreshold, 504e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com outputDir, drp->fBase.fFilename); 50546256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com } else { 506e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 50746256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com } 50846256ea736868e6df1a6102672fc4bb41f99d29depoger@google.com } 509e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 5105fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com ++i; 5115fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com ++j; 5124b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 513e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 514e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (getBounds) { 515e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com get_bounds(*drp); 516e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 517e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkASSERT(DiffRecord::kUnknown_Result != drp->fResult); 5185fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com differences->push(drp); 5195fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com summary->add(drp); 5205fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } 5215fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 5225fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com for (; i < baseFiles.count(); ++i) { 5235fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com // files only in baseDir 524e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord *drp = new DiffRecord(); 525e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFilename = *baseFiles[i]; 526e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath = baseDir; 527e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath.append(drp->fBase.fFilename); 528e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kExists_Status; 529e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 530e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFilename = *baseFiles[i]; 531e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath = comparisonDir; 532e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath.append(drp->fComparison.fFilename); 533e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kDoesNotExist_Status; 534e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 535e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 536e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (getBounds) { 537e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com get_bounds(*drp); 538e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 5395fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com differences->push(drp); 5405fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com summary->add(drp); 5415fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com } 5424b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 5435fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com for (; j < comparisonFiles.count(); ++j) { 5445fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com // files only in comparisonDir 545e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord *drp = new DiffRecord(); 546e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFilename = *comparisonFiles[j]; 547e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath = baseDir; 548e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath.append(drp->fBase.fFilename); 549e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kDoesNotExist_Status; 550e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 551e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFilename = *comparisonFiles[j]; 552e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath = comparisonDir; 553e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath.append(drp->fComparison.fFilename); 554e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kExists_Status; 555e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 556e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 557e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (getBounds) { 558e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com get_bounds(*drp); 559e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 5604b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com differences->push(drp); 5619dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com summary->add(drp); 5624b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 5635fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com 5645fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com release_file_list(&baseFiles); 5655fd53858f83776025e63de44b2e0a1822b932c39epoger@google.com release_file_list(&comparisonFiles); 5667d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com} 5674b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 5684b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.comstatic void usage (char * argv0) { 5694b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com SkDebugf("Skia baseline image diff tool\n"); 570a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com SkDebugf("\n" 571a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com"Usage: \n" 572e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com" %s <baseDir> <comparisonDir> [outputDir] \n", argv0); 573a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org SkDebugf( 57446a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\nArguments:" 575dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n --failonresult <result>: After comparing all file pairs, exit with nonzero" 576dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n return code (number of file pairs yielding this" 577dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n result) if any file pairs yielded this result." 578dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n This flag may be repeated, in which case the" 579dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n return code will be the number of fail pairs" 580dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n yielding ANY of these results." 581e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --failonstatus <baseStatus> <comparisonStatus>: exit with nonzero return" 582e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n code if any file pairs yielded this status." 58346a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --help: display this info" 58446a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --listfilenames: list all filenames for each result type in stdout" 585dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n --match <substring>: compare files whose filenames contain this substring;" 586dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n if unspecified, compare ALL files." 587dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n this flag may be repeated." 58846a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --nodiffs: don't write out image diffs or index.html, just generate" 58946a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n report on stdout" 590dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n --nomatch <substring>: regardless of --match, DO NOT compare files whose" 591dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n filenames contain this substring." 592dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com"\n this flag may be repeated." 59346a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --noprintdirs: do not print the directories used." 59471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com"\n --norecurse: do not recurse into subdirectories." 59546a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --sortbymaxmismatch: sort by worst color channel mismatch;" 59646a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n break ties with -sortbymismatch" 59746a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --sortbymismatch: sort by average color channel mismatch" 59846a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --threshold <n>: only report differences > n (per color channel) [default 0]" 59946a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n --weighted: sort by # pixels different weighted by color difference" 60046a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n" 60146a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n baseDir: directory to read baseline images from." 60246a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n comparisonDir: directory to read comparison images from" 60346a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n outputDir: directory to write difference images and index.html to;" 60446a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n defaults to comparisonDir" 60546a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n" 60646a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\nIf no sort is specified, it will sort by fraction of pixels mismatching." 60746a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com"\n"); 6084b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com} 6094b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 61070044cc4964c32e0125e46c3c5f7f82446ddda85epoger@google.comconst int kNoError = 0; 61170044cc4964c32e0125e46c3c5f7f82446ddda85epoger@google.comconst int kGenericError = -1; 61246a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com 613be28ee2974474800323ce4fabf62a839018be591Mike Kleinint main(int argc, char** argv) { 6144b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com DiffMetricProc diffProc = compute_diff_pmcolor; 61528060e7c940b07038bdaa3c5f8d1d87cf199e228epoger@google.com int (*sortProc)(const void*, const void*) = compare<CompareDiffMetrics>; 6164b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 6174b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com // Maximum error tolerated in any one color channel in any one pixel before 6184b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com // a difference is reported. 6194b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com int colorThreshold = 0; 6204b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com SkString baseDir; 6214b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com SkString comparisonDir; 6224b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com SkString outputDir; 623dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com 624a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com StringArray matchSubstrings; 625a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com StringArray nomatchSubstrings; 6264b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 627a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com bool generateDiffs = true; 62846a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com bool listFilenames = false; 62971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com bool printDirNames = true; 63071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com bool recurseIntoSubdirs = true; 63193d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org bool verbose = false; 6323a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed bool listFailingBase = false; 6337d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com 6344b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com RecordArray differences; 6359dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com DiffSummary summary; 6364b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 637e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool failOnResultType[DiffRecord::kResultCount]; 638e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int i = 0; i < DiffRecord::kResultCount; i++) { 6393af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com failOnResultType[i] = false; 6403af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com } 6413af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com 642e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount]; 643e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 644e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 645e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnStatusType[base][comparison] = false; 646e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 647e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 648e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 649a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com int i; 650a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com int numUnflaggedArguments = 0; 651a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com for (i = 1; i < argc; i++) { 652dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com if (!strcmp(argv[i], "--failonresult")) { 653e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 654e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("failonresult expects one argument.\n"); 655e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 656e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 657e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord::Result type = DiffRecord::getResultByName(argv[i]); 658e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (type != DiffRecord::kResultCount) { 659e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnResultType[type] = true; 660e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 661e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("ignoring unrecognized result <%s>\n", argv[i]); 662e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 663e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 664e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 665e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--failonstatus")) { 666e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 667e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("failonstatus missing base status.\n"); 668e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 669e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 670e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool baseStatuses[DiffResource::kStatusCount]; 671e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!DiffResource::getMatchingStatuses(argv[i], baseStatuses)) { 672e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("unrecognized base status <%s>\n", argv[i]); 673e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 674e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 675e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 676e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("failonstatus missing comparison status.\n"); 677e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 678e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 679e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool comparisonStatuses[DiffResource::kStatusCount]; 680e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!DiffResource::getMatchingStatuses(argv[i], comparisonStatuses)) { 681e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("unrecognized comarison status <%s>\n", argv[i]); 682e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 683e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 684e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 685e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 686e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnStatusType[base][comparison] |= 687e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com baseStatuses[base] && comparisonStatuses[comparison]; 688e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 689e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 69046a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com continue; 69146a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com } 6927d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com if (!strcmp(argv[i], "--help")) { 6934b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com usage(argv[0]); 69470044cc4964c32e0125e46c3c5f7f82446ddda85epoger@google.com return kNoError; 695a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 69646a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com if (!strcmp(argv[i], "--listfilenames")) { 69746a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com listFilenames = true; 698a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com continue; 699a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 70093d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org if (!strcmp(argv[i], "--verbose")) { 70193d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org verbose = true; 70293d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org continue; 70393d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org } 704a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (!strcmp(argv[i], "--match")) { 705a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com matchSubstrings.push(new SkString(argv[++i])); 706a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com continue; 707a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 70846a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com if (!strcmp(argv[i], "--nodiffs")) { 70946a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com generateDiffs = false; 71046a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com continue; 71146a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com } 712a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (!strcmp(argv[i], "--nomatch")) { 713a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com nomatchSubstrings.push(new SkString(argv[++i])); 714a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com continue; 715a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 71646a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com if (!strcmp(argv[i], "--noprintdirs")) { 71771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com printDirNames = false; 71871329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com continue; 71971329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com } 72071329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (!strcmp(argv[i], "--norecurse")) { 72171329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com recurseIntoSubdirs = false; 7224b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com continue; 7234b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 7247d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com if (!strcmp(argv[i], "--sortbymaxmismatch")) { 72528060e7c940b07038bdaa3c5f8d1d87cf199e228epoger@google.com sortProc = compare<CompareDiffMaxMismatches>; 7264b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com continue; 7274b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 72846a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com if (!strcmp(argv[i], "--sortbymismatch")) { 72946a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com sortProc = compare<CompareDiffMeanMismatches>; 7305b32529ab855764bf40f678f10d0e3045b990a94tomhudson@google.com continue; 7315b32529ab855764bf40f678f10d0e3045b990a94tomhudson@google.com } 73246a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com if (!strcmp(argv[i], "--threshold")) { 73346a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com colorThreshold = atoi(argv[++i]); 73446a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com continue; 73546a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com } 73646a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com if (!strcmp(argv[i], "--weighted")) { 73746a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com sortProc = compare<CompareDiffWeighted>; 738a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org continue; 739a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org } 7404b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com if (argv[i][0] != '-') { 741a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com switch (numUnflaggedArguments++) { 7424b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com case 0: 7434b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com baseDir.set(argv[i]); 7444b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com continue; 7454b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com case 1: 7464b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com comparisonDir.set(argv[i]); 7474b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com continue; 7484b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com case 2: 7494b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com outputDir.set(argv[i]); 7504b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com continue; 7514b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com default: 752a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com SkDebugf("extra unflagged argument <%s>\n", argv[i]); 7534b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com usage(argv[0]); 75470044cc4964c32e0125e46c3c5f7f82446ddda85epoger@google.com return kGenericError; 7554b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 7564b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 7573a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed if (!strcmp(argv[i], "--listFailingBase")) { 7583a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed listFailingBase = true; 7593a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed continue; 7603a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 7614b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 7624b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com SkDebugf("Unrecognized argument <%s>\n", argv[i]); 7634b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com usage(argv[0]); 76470044cc4964c32e0125e46c3c5f7f82446ddda85epoger@google.com return kGenericError; 7654b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 766a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com 767a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (numUnflaggedArguments == 2) { 7689dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com outputDir = comparisonDir; 769a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } else if (numUnflaggedArguments != 3) { 7709dc527bebfaca7c87a39302510399bb0d0fe770dtomhudson@google.com usage(argv[0]); 77170044cc4964c32e0125e46c3c5f7f82446ddda85epoger@google.com return kGenericError; 7724b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 7734b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 7741a315fe57e393bbafa32d5482fed052e39ffdc2ebsalomon@google.com if (!baseDir.endsWith(PATH_DIV_STR)) { 7751a315fe57e393bbafa32d5482fed052e39ffdc2ebsalomon@google.com baseDir.append(PATH_DIV_STR); 7764b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 77771329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (printDirNames) { 778a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org printf("baseDir is [%s]\n", baseDir.c_str()); 779a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org } 780a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com 7811a315fe57e393bbafa32d5482fed052e39ffdc2ebsalomon@google.com if (!comparisonDir.endsWith(PATH_DIV_STR)) { 7821a315fe57e393bbafa32d5482fed052e39ffdc2ebsalomon@google.com comparisonDir.append(PATH_DIV_STR); 7834b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 78471329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (printDirNames) { 785a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org printf("comparisonDir is [%s]\n", comparisonDir.c_str()); 786a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org } 787a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com 7881a315fe57e393bbafa32d5482fed052e39ffdc2ebsalomon@google.com if (!outputDir.endsWith(PATH_DIV_STR)) { 7891a315fe57e393bbafa32d5482fed052e39ffdc2ebsalomon@google.com outputDir.append(PATH_DIV_STR); 7904b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 791a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (generateDiffs) { 79271329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (printDirNames) { 793a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org printf("writing diffs to outputDir is [%s]\n", outputDir.c_str()); 794a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org } 795a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } else { 79671329d809a42889af8d2cadc4e43c60488a739a1epoger@google.com if (printDirNames) { 797a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org printf("not writing any diffs to outputDir [%s]\n", outputDir.c_str()); 798a6318194df095b47165d475ada2581b992d0c821keyar@chromium.org } 799a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com outputDir.set(""); 800a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 801a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com 802da4af24c9c52a80a0c9b4fbd2933f5939920c98cepoger@google.com // If no matchSubstrings were specified, match ALL strings 803da4af24c9c52a80a0c9b4fbd2933f5939920c98cepoger@google.com // (except for whatever nomatchSubstrings were specified, if any). 804a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (matchSubstrings.isEmpty()) { 805a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com matchSubstrings.push(new SkString("")); 806a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 8074b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com 808a611c3ea53c02ef80baa32fbfb9cca33f999378depoger@google.com create_diff_images(diffProc, colorThreshold, &differences, 809a611c3ea53c02ef80baa32fbfb9cca33f999378depoger@google.com baseDir, comparisonDir, outputDir, 810e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com matchSubstrings, nomatchSubstrings, recurseIntoSubdirs, generateDiffs, 81193d7bb6fc6e42d41e41ec9f38b540616d07925adcommit-bot@chromium.org verbose, &summary); 812e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com summary.print(listFilenames, failOnResultType, failOnStatusType); 8137d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com 8143a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed if (listFailingBase) { 8153a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed summary.printfFailingBaseNames("\n"); 8163a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed } 8173a3baf6c4bde1d64a40446ca0fcd91274cdb2f8breed 8187d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com if (differences.count()) { 819c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com qsort(differences.begin(), differences.count(), 820c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com sizeof(DiffRecord*), sortProc); 8217d04280a68430d6b472ee67dc8f6092127625e73tomhudson@google.com } 82266008526673b55dcce69ba947186c5e9428a62e5epoger@google.com 823a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com if (generateDiffs) { 824a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com print_diff_page(summary.fNumMatches, colorThreshold, differences, 825a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com baseDir, comparisonDir, outputDir); 826a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com } 82776222c0ef2c5e63d2d9875e1cdb89e52049c7754epoger@google.com 8284b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com for (i = 0; i < differences.count(); i++) { 8294b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com delete differences[i]; 8304b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com } 831a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com matchSubstrings.deleteAll(); 832a5f406e9984e09d084cc995895712eb3f8f1c3cfepoger@google.com nomatchSubstrings.deleteAll(); 833be6188d64721850723c19d5a7a4f007a675300f4epoger@google.com 834dfbf24e5e7112e99e8c9bed1fdaadc136f42a0d3epoger@google.com int num_failing_results = 0; 835e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int i = 0; i < DiffRecord::kResultCount; i++) { 8363af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com if (failOnResultType[i]) { 8373af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com num_failing_results += summary.fResultsOfType[i].count(); 8383af4ff46a7461f78c8ab24d1e8213b187e8472e2epoger@google.com } 83946a45963fa13082cbe0c800c92bccf2ac36c89b7epoger@google.com } 840e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!failOnResultType[DiffRecord::kCouldNotCompare_Result]) { 841e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 842e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 843e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (failOnStatusType[base][comparison]) { 844e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com num_failing_results += summary.fStatusOfType[base][comparison].count(); 845e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 846e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 847e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 848e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 84928659883618d3c015defe91de504af96bc98afdbepoger@google.com 85028659883618d3c015defe91de504af96bc98afdbepoger@google.com // On Linux (and maybe other platforms too), any results outside of the 85128659883618d3c015defe91de504af96bc98afdbepoger@google.com // range [0...255] are wrapped (mod 256). Do the conversion ourselves, to 85228659883618d3c015defe91de504af96bc98afdbepoger@google.com // make sure that we only return 0 when there were no failures. 85328659883618d3c015defe91de504af96bc98afdbepoger@google.com return (num_failing_results > 255) ? 255 : num_failing_results; 8544b33d28eb369622964d22d5cc4a6e3f0eb11a14ctomhudson@google.com} 855