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