skdiff_image.cpp revision 667433ff5bc65680af31ca718d4cc29cce7b7040
1e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com/* 2e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * Copyright 2012 Google Inc. 3e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * 4e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * Use of this source code is governed by a BSD-style license that can be 5e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com * found in the LICENSE file. 6e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com */ 7e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff.h" 8e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "skdiff_utils.h" 9e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkBitmap.h" 10e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkData.h" 11e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkImageEncoder.h" 12e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkOSFile.h" 13e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkTDArray.h" 14e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkTemplates.h" 15e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#include "SkTypes.h" 16e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 1716b2dd05f0c5faca90b101c28ea01ff80257408abungeman@google.com#include <stdio.h> 1816b2dd05f0c5faca90b101c28ea01ff80257408abungeman@google.com 19e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com/// If outputDir.isEmpty(), don't write out diff files. 20e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comstatic void create_diff_images (DiffMetricProc dmp, 21e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const int colorThreshold, 22e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const SkString& baseFile, 23e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const SkString& comparisonFile, 24e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const SkString& outputDir, 25e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const SkString& outputFilename, 26e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord* drp) { 27e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkASSERT(!baseFile.isEmpty()); 28e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkASSERT(!comparisonFile.isEmpty()); 29e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 30e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFilename = baseFile; 31e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fFullPath = baseFile; 32e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kSpecified_Status; 33e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 34e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFilename = comparisonFile; 35e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fFullPath = comparisonFile; 36e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kSpecified_Status; 37e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 38e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkAutoDataUnref baseFileBits(read_file(drp->fBase.fFullPath.c_str())); 3949f085dddff10473b6ebf832a974288300224e60bsalomon if (baseFileBits) { 40e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kRead_Status; 41e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 42e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkAutoDataUnref comparisonFileBits(read_file(drp->fComparison.fFullPath.c_str())); 4349f085dddff10473b6ebf832a974288300224e60bsalomon if (comparisonFileBits) { 44e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kRead_Status; 45e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 4696fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == baseFileBits || nullptr == comparisonFileBits) { 4796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == baseFileBits) { 48e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fBase.fStatus = DiffResource::kCouldNotRead_Status; 49e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 5096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == comparisonFileBits) { 51e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fComparison.fStatus = DiffResource::kCouldNotRead_Status; 52e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 53e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 54e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return; 55e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 56e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 57e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (are_buffers_equal(baseFileBits, comparisonFileBits)) { 58e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kEqualBits_Result; 59e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return; 60e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 61e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 62667433ff5bc65680af31ca718d4cc29cce7b7040msarett get_bitmap(baseFileBits, drp->fBase, false); 63667433ff5bc65680af31ca718d4cc29cce7b7040msarett get_bitmap(comparisonFileBits, drp->fComparison, false); 64e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (DiffResource::kDecoded_Status != drp->fBase.fStatus || 65e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffResource::kDecoded_Status != drp->fComparison.fStatus) 66e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com { 67e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com drp->fResult = DiffRecord::kCouldNotCompare_Result; 68e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return; 69e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 70e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 71e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com create_and_write_diff_image(drp, dmp, colorThreshold, outputDir, outputFilename); 72e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com //TODO: copy fBase.fFilename and fComparison.fFilename to outputDir 73e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // svn and git often present tmp files to diff tools which are promptly deleted 74e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 75e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com //TODO: serialize drp to outputDir 76e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // write a tool to deserialize them and call print_diff_page 77e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 78e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkASSERT(DiffRecord::kUnknown_Result != drp->fResult); 79e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com} 80e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 81e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comstatic void usage (char * argv0) { 82e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("Skia image diff tool\n"); 83e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("\n" 84e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"Usage: \n" 85e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com" %s <baseFile> <comparisonFile>\n" , argv0); 86e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf( 87e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\nArguments:" 88e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --failonresult <result>: After comparing all file pairs, exit with nonzero" 89e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n return code (number of file pairs yielding this" 90e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n result) if any file pairs yielded this result." 91e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n This flag may be repeated, in which case the" 92e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n return code will be the number of fail pairs" 93e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n yielding ANY of these results." 94e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --failonstatus <baseStatus> <comparisonStatus>: exit with nonzero return" 95e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n code if any file pairs yeilded this status." 96e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --help: display this info" 97e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --listfilenames: list all filenames for each result type in stdout" 98e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --nodiffs: don't write out image diffs, just generate report on stdout" 99e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --outputdir: directory to write difference images" 100e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n --threshold <n>: only report differences > n (per color channel) [default 0]" 101e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n -u: ignored. Recognized for compatibility with svn diff." 102e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n -L: first occurrence label for base, second occurrence label for comparison." 103e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n Labels must be of the form \"<filename>(\t<specifier>)?\"." 104e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n The base <filename> will be used to create files in outputdir." 105e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n" 106e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n baseFile: baseline image file." 107e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n comparisonFile: comparison image file" 108e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n" 109e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\nIf no sort is specified, it will sort by fraction of pixels mismatching." 110e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com"\n"); 111e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com} 112e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 113e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comconst int kNoError = 0; 114e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comconst int kGenericError = -1; 115e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 116e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comint tool_main(int argc, char** argv); 117e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comint tool_main(int argc, char** argv) { 118e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffMetricProc diffProc = compute_diff_pmcolor; 119e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 120e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Maximum error tolerated in any one color channel in any one pixel before 121e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // a difference is reported. 122e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int colorThreshold = 0; 123e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString baseFile; 124e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString baseLabel; 125e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString comparisonFile; 126e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString comparisonLabel; 127e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString outputDir; 128e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 129e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool listFilenames = false; 130e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 131e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool failOnResultType[DiffRecord::kResultCount]; 132e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int i = 0; i < DiffRecord::kResultCount; i++) { 133e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnResultType[i] = false; 134e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 135e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 136e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool failOnStatusType[DiffResource::kStatusCount][DiffResource::kStatusCount]; 137e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 138e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 139e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnStatusType[base][comparison] = false; 140e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 141e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 142e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 143e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int i; 144e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int numUnflaggedArguments = 0; 145e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int numLabelArguments = 0; 146e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (i = 1; i < argc; i++) { 147e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--failonresult")) { 148e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 149e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("failonresult expects one argument.\n"); 150e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 151e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 152e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord::Result type = DiffRecord::getResultByName(argv[i]); 153e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (type != DiffRecord::kResultCount) { 154e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnResultType[type] = true; 155e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 156e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("ignoring unrecognized result <%s>\n", argv[i]); 157e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 158e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 159e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 160e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--failonstatus")) { 161e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 162e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("failonstatus missing base status.\n"); 163e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 164e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 165e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool baseStatuses[DiffResource::kStatusCount]; 166e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!DiffResource::getMatchingStatuses(argv[i], baseStatuses)) { 167e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("unrecognized base status <%s>\n", argv[i]); 168e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 169e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 170e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 171e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("failonstatus missing comparison status.\n"); 172e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 173e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 174e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com bool comparisonStatuses[DiffResource::kStatusCount]; 175e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!DiffResource::getMatchingStatuses(argv[i], comparisonStatuses)) { 176e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("unrecognized comarison status <%s>\n", argv[i]); 177e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 178e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 179e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int base = 0; base < DiffResource::kStatusCount; ++base) { 180e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com for (int comparison = 0; comparison < DiffResource::kStatusCount; ++comparison) { 181e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com failOnStatusType[base][comparison] |= 182e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com baseStatuses[base] && comparisonStatuses[comparison]; 183e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 184e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 185e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 186e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 187e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--help")) { 188e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com usage(argv[0]); 189e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return kNoError; 190e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 191e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--listfilenames")) { 192e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com listFilenames = true; 193e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 194e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 195e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--outputdir")) { 196e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 197e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("outputdir expects one argument.\n"); 198e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 199e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 200e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com outputDir.set(argv[i]); 201e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 202e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 203e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "--threshold")) { 204e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com colorThreshold = atoi(argv[++i]); 205e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 206e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 207e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "-u")) { 208e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com //we don't produce unified diffs, ignore parameter to work with svn diff 209e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 210e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 211e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!strcmp(argv[i], "-L")) { 212e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argc == ++i) { 213e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("label expects one argument.\n"); 214e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 215e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 216e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com switch (numLabelArguments++) { 217e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case 0: 218e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com baseLabel.set(argv[i]); 219e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 220e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case 1: 221e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com comparisonLabel.set(argv[i]); 222e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 223e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com default: 224e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("extra label argument <%s>\n", argv[i]); 225e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com usage(argv[0]); 226e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return kGenericError; 227e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 228e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 229e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 230e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (argv[i][0] != '-') { 231e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com switch (numUnflaggedArguments++) { 232e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case 0: 233e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com baseFile.set(argv[i]); 234e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 235e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com case 1: 236e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com comparisonFile.set(argv[i]); 237e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com continue; 238e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com default: 239e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("extra unflagged argument <%s>\n", argv[i]); 240e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com usage(argv[0]); 241e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return kGenericError; 242e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 243e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 244e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 245e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkDebugf("Unrecognized argument <%s>\n", argv[i]); 246e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com usage(argv[0]); 247e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return kGenericError; 248e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 249e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 250e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (numUnflaggedArguments != 2) { 251e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com usage(argv[0]); 252e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return kGenericError; 253e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 254e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 255e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (listFilenames) { 256e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Base file is [%s]\n", baseFile.c_str()); 257e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 258e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 259e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (listFilenames) { 260e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Comparison file is [%s]\n", comparisonFile.c_str()); 261e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 262e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 263e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (outputDir.isEmpty()) { 264e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (listFilenames) { 265e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Not writing any diffs. No output dir specified.\n"); 266e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 267e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 268e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (!outputDir.endsWith(PATH_DIV_STR)) { 269e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com outputDir.append(PATH_DIV_STR); 270e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 271e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (listFilenames) { 272e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Writing diffs. Output dir is [%s]\n", outputDir.c_str()); 273e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 274e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 275e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 276e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Some obscure documentation about diff/patch labels: 277e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 278e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Posix says the format is: <filename><tab><date> 279e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // It also states that if a filename contains <tab> or <newline> 280e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // the result is implementation defined 281e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 282e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Svn diff --diff-cmd provides labels of the form: <filename><tab><revision> 283e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 284e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Git diff --ext-diff does not supply arguments compatible with diff. 285e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // However, it does provide the filename directly. 286e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // skimagediff_git.sh: skimagediff %2 %5 -L "%1\t(%3)" -L "%1\t(%6)" 287e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 288e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Git difftool sets $LOCAL, $REMOTE, $MERGED, and $BASE instead of command line parameters. 289e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // difftool.<>.cmd: skimagediff $LOCAL $REMOTE -L "$MERGED\t(local)" -L "$MERGED\t(remote)" 290e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 291e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Diff will write any specified label verbatim. Without a specified label diff will write 292e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // <filename><tab><date> 293e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // However, diff will encode the filename as a cstring if the filename contains 294e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Any of <space> or <double quote> 295e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // A char less than 32 2965b7bac5ce162eee6d73c33373029a4e5a9f94683bungeman@google.com // Any escapable character \\, \a, \b, \t, \n, \v, \f, \r 297e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 298e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Patch decodes: 299e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // If first <non-white-space> is <double quote>, parse filename from cstring. 300e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // If there is a <tab> after the first <non-white-space>, filename is 301e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // [first <non-white-space>, the next run of <white-space> with an embedded <tab>). 302e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Otherwise the filename is [first <non-space>, the next <white-space>). 303e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // 304e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // The filename /dev/null means the file does not exist (used in adds and deletes). 305e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 306e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // Considering the above, skimagediff will consider the contents of a -L parameter as 307e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com // <filename>(\t<specifier>)? 308e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com SkString outputFile; 309e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 310e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (baseLabel.isEmpty()) { 311e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com baseLabel.set(baseFile); 312e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com outputFile = baseLabel; 313e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 314e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const char* baseLabelCstr = baseLabel.c_str(); 315e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com const char* tab = strchr(baseLabelCstr, '\t'); 31696fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == tab) { 317e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com outputFile = baseLabel; 318e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } else { 319e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com outputFile.set(baseLabelCstr, tab - baseLabelCstr); 320e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 321e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 322e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (comparisonLabel.isEmpty()) { 323e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com comparisonLabel.set(comparisonFile); 324e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 325e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Base: %s\n", baseLabel.c_str()); 326e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Comparison: %s\n", comparisonLabel.c_str()); 327e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 328e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com DiffRecord dr; 329e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com create_diff_images(diffProc, colorThreshold, baseFile, comparisonFile, outputDir, outputFile, 330e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com &dr); 331e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 332e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (DiffResource::isStatusFailed(dr.fBase.fStatus)) { 333e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Base %s.\n", DiffResource::getStatusDescription(dr.fBase.fStatus)); 334e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 335e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (DiffResource::isStatusFailed(dr.fComparison.fStatus)) { 336e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Comparison %s.\n", DiffResource::getStatusDescription(dr.fComparison.fStatus)); 337e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 338e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("Base and Comparison %s.\n", DiffRecord::getResultDescription(dr.fResult)); 339e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 340e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (DiffRecord::kDifferentPixels_Result == dr.fResult) { 341e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("%.4f%% of pixels differ", 100 * dr.fFractionDifference); 342e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf(" (%.4f%% weighted)", 100 * dr.fWeightedFraction); 343e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (dr.fFractionDifference < 0.01) { 344e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf(" %d pixels", static_cast<int>(dr.fFractionDifference * 345e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com dr.fBase.fBitmap.width() * 346e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com dr.fBase.fBitmap.height())); 347e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 348e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 349e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("\nAverage color mismatch: "); 350e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("%d", static_cast<int>(MAX3(dr.fAverageMismatchR, 351e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com dr.fAverageMismatchG, 352e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com dr.fAverageMismatchB))); 353e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("\nMax color mismatch: "); 354e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("%d", MAX3(dr.fMaxMismatchR, 355e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com dr.fMaxMismatchG, 356e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com dr.fMaxMismatchB)); 357e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("\n"); 358e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 359e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com printf("\n"); 360e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 361e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com int num_failing_results = 0; 362e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (failOnResultType[dr.fResult]) { 363e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com ++num_failing_results; 364e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 365e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com if (failOnStatusType[dr.fBase.fStatus][dr.fComparison.fStatus]) { 366e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com ++num_failing_results; 367e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com } 368e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 369e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return num_failing_results; 370e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com} 371e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com 372e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#if !defined SK_BUILD_FOR_IOS 373e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.comint main(int argc, char * const argv[]) { 374e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com return tool_main(argc, (char**) argv); 375e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com} 376e3c8ddfd03fdf587b4d8400718ae4bb6e9aa8b6dbungeman@google.com#endif 377