1945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com/* 2945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com * Copyright 2013 Google Inc. 3945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com * 4945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com * Use of this source code is governed by a BSD-style license that can be 5945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com * found in the LICENSE file. 6945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com */ 7945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 8945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com#include "SkBitmap.h" 9945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com#include "SkImageDecoder.h" 10945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com#include "SkOSFile.h" 11cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com#include "SkRunnable.h" 1254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger#include "SkSize.h" 13945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com#include "SkStream.h" 14c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com#include "SkTDict.h" 15406654be7a930b484159f5bca107d3b11d8a9edemtklein#include "SkTaskGroup.h" 16945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 1721b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana// from the tools directory for replace_char(...) 1821b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana#include "picture_utils.h" 1921b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana 20945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com#include "SkDiffContext.h" 2154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger#include "SkImageDiffer.h" 22945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com#include "skpdiff_util.h" 23945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 24945708ad9494322e2bc26776ccb741776205b4b8zachr@google.comSkDiffContext::SkDiffContext() { 25945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com fDiffers = NULL; 26945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com fDifferCount = 0; 27945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 28945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 29945708ad9494322e2bc26776ccb741776205b4b8zachr@google.comSkDiffContext::~SkDiffContext() { 3049f085dddff10473b6ebf832a974288300224e60bsalomon if (fDiffers) { 31945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDELETE_ARRAY(fDiffers); 32945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 33945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 34945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 3554f1ad8bb5bdd2ac2ea7981427abeb193383d449epogervoid SkDiffContext::setAlphaMaskDir(const SkString& path) { 36513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com if (!path.isEmpty() && sk_mkdir(path.c_str())) { 3754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger fAlphaMaskDir = path; 3854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger } 3954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger} 4054f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 4154f1ad8bb5bdd2ac2ea7981427abeb193383d449epogervoid SkDiffContext::setRgbDiffDir(const SkString& path) { 4254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger if (!path.isEmpty() && sk_mkdir(path.c_str())) { 4354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger fRgbDiffDir = path; 4454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger } 4554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger} 4654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 4754f1ad8bb5bdd2ac2ea7981427abeb193383d449epogervoid SkDiffContext::setWhiteDiffDir(const SkString& path) { 4854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger if (!path.isEmpty() && sk_mkdir(path.c_str())) { 4954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger fWhiteDiffDir = path; 50513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 51513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com} 52513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 5321b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephanavoid SkDiffContext::setLongNames(const bool useLongNames) { 5421b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana longNames = useLongNames; 5521b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana} 5621b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana 57945708ad9494322e2bc26776ccb741776205b4b8zachr@google.comvoid SkDiffContext::setDiffers(const SkTDArray<SkImageDiffer*>& differs) { 58945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Delete whatever the last array of differs was 5949f085dddff10473b6ebf832a974288300224e60bsalomon if (fDiffers) { 60945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDELETE_ARRAY(fDiffers); 61945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com fDiffers = NULL; 62945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com fDifferCount = 0; 63945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 64945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 65945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Copy over the new differs 66945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com fDifferCount = differs.count(); 67945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com fDiffers = SkNEW_ARRAY(SkImageDiffer*, fDifferCount); 68945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com differs.copy(fDiffers); 69945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 70945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 71513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.comstatic SkString get_common_prefix(const SkString& a, const SkString& b) { 72513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com const size_t maxPrefixLength = SkTMin(a.size(), b.size()); 73513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com SkASSERT(maxPrefixLength > 0); 74513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com for (size_t x = 0; x < maxPrefixLength; ++x) { 75513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com if (a[x] != b[x]) { 76513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com SkString result; 77513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com result.set(a.c_str(), x); 78513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return result; 79513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 80513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 81513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com if (a.size() > b.size()) { 82513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return b; 83513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } else { 84513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com return a; 85513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 86513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com} 87513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 8821b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephanastatic SkString get_combined_name(const SkString& a, const SkString& b) { 89406654be7a930b484159f5bca107d3b11d8a9edemtklein // Note (stephana): We must keep this function in sync with 9021b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana // getImageDiffRelativeUrl() in static/loader.js (under rebaseline_server). 9121b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana SkString result = a; 9221b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana result.append("-vs-"); 9321b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana result.append(b); 9421b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana sk_tools::replace_char(&result, '.', '_'); 9521b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana return result; 9621b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana} 9721b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana 98945708ad9494322e2bc26776ccb741776205b4b8zachr@google.comvoid SkDiffContext::addDiff(const char* baselinePath, const char* testPath) { 99945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Load the images at the paths 100945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkBitmap baselineBitmap; 101945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkBitmap testBitmap; 102945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (!SkImageDecoder::DecodeFile(baselinePath, &baselineBitmap)) { 103945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Failed to load bitmap \"%s\"\n", baselinePath); 104945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com return; 105945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 106945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (!SkImageDecoder::DecodeFile(testPath, &testBitmap)) { 107945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Failed to load bitmap \"%s\"\n", testPath); 108945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com return; 109945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 110945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 111945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Setup a record for this diff 112efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com fRecordMutex.acquire(); 113efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com DiffRecord* newRecord = fRecords.addToHead(DiffRecord()); 114efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com fRecordMutex.release(); 115945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 116513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com // compute the common name 117a8e2e1504b9af6ba791637f228debaa23953064atfarina SkString baseName = SkOSPath::Basename(baselinePath); 118a8e2e1504b9af6ba791637f228debaa23953064atfarina SkString testName = SkOSPath::Basename(testPath); 11921b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana 12021b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana if (longNames) { 12121b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana newRecord->fCommonName = get_combined_name(baseName, testName); 12221b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana } else { 12321b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana newRecord->fCommonName = get_common_prefix(baseName, testName); 12421b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana } 12521b342d19c71fa5abe7e4aa5cfb518fd04cb9d67stephana newRecord->fCommonName.append(".png"); 126513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 127efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com newRecord->fBaselinePath = baselinePath; 128efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com newRecord->fTestPath = testPath; 12954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger newRecord->fSize = SkISize::Make(baselineBitmap.width(), baselineBitmap.height()); 130efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 13154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // only generate diff images if we have a place to store them 13254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger SkImageDiffer::BitmapsToCreate bitmapsToCreate; 13354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger bitmapsToCreate.alphaMask = !fAlphaMaskDir.isEmpty(); 13454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger bitmapsToCreate.rgbDiff = !fRgbDiffDir.isEmpty(); 13554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger bitmapsToCreate.whiteDiff = !fWhiteDiffDir.isEmpty(); 136513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 137945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Perform each diff 138945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com for (int differIndex = 0; differIndex < fDifferCount; differIndex++) { 139945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkImageDiffer* differ = fDiffers[differIndex]; 140efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 141efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com // Copy the results into data for this record 142efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com DiffData& diffData = newRecord->fDiffs.push_back(); 143efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com diffData.fDiffName = differ->getName(); 144efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 14554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger if (!differ->diff(&baselineBitmap, &testBitmap, bitmapsToCreate, &diffData.fResult)) { 14654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // if the diff failed, record -1 as the result 14754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // TODO(djsollen): Record more detailed information about exactly what failed. 14854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // (Image dimension mismatch? etc.) See http://skbug.com/2710 ('make skpdiff 14954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // report more detail when it fails to compare two images') 15027d7ede2e64bddeacce4a0d83bc055bf966cce2fdjsollen@google.com diffData.fResult.result = -1; 151efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com continue; 152513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com } 153513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 15454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger if (bitmapsToCreate.alphaMask 155efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result 156efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com && !diffData.fResult.poiAlphaMask.empty() 157efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com && !newRecord->fCommonName.isEmpty()) { 158efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 159a8e2e1504b9af6ba791637f228debaa23953064atfarina newRecord->fAlphaMaskPath = SkOSPath::Join(fAlphaMaskDir.c_str(), 160a8e2e1504b9af6ba791637f228debaa23953064atfarina newRecord->fCommonName.c_str()); 161efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 162efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com // compute the image diff and output it 163efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com SkBitmap copy; 16428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org diffData.fResult.poiAlphaMask.copyTo(©, kN32_SkColorType); 16554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger SkImageEncoder::EncodeFile(newRecord->fAlphaMaskPath.c_str(), copy, 166efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com SkImageEncoder::kPNG_Type, 100); 167513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com 168efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com // cleanup the existing bitmap to free up resources; 169efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com diffData.fResult.poiAlphaMask.reset(); 170efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 17154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger bitmapsToCreate.alphaMask = false; 17254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger } 17354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 17454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger if (bitmapsToCreate.rgbDiff 17554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result 17654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger && !diffData.fResult.rgbDiffBitmap.empty() 17754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger && !newRecord->fCommonName.isEmpty()) { 17854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // TODO(djsollen): Rather than taking the max r/g/b diffs that come back from 17954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // a particular differ and storing them as toplevel fields within 18054f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // newRecord, we should extend outputRecords() to report optional 18154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // fields for each differ (not just "result" and "pointsOfInterest"). 18254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // See http://skbug.com/2712 ('allow skpdiff to report different sets 18354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // of result fields for different comparison algorithms') 18454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger newRecord->fMaxRedDiff = diffData.fResult.maxRedDiff; 18554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger newRecord->fMaxGreenDiff = diffData.fResult.maxGreenDiff; 18654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger newRecord->fMaxBlueDiff = diffData.fResult.maxBlueDiff; 18754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 188a8e2e1504b9af6ba791637f228debaa23953064atfarina newRecord->fRgbDiffPath = SkOSPath::Join(fRgbDiffDir.c_str(), 189a8e2e1504b9af6ba791637f228debaa23953064atfarina newRecord->fCommonName.c_str()); 19054f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger SkImageEncoder::EncodeFile(newRecord->fRgbDiffPath.c_str(), 19154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger diffData.fResult.rgbDiffBitmap, 19254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger SkImageEncoder::kPNG_Type, 100); 19354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger diffData.fResult.rgbDiffBitmap.reset(); 19454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger bitmapsToCreate.rgbDiff = false; 19554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger } 19654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 19754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger if (bitmapsToCreate.whiteDiff 19854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result 19954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger && !diffData.fResult.whiteDiffBitmap.empty() 20054f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger && !newRecord->fCommonName.isEmpty()) { 201a8e2e1504b9af6ba791637f228debaa23953064atfarina newRecord->fWhiteDiffPath = SkOSPath::Join(fWhiteDiffDir.c_str(), 202a8e2e1504b9af6ba791637f228debaa23953064atfarina newRecord->fCommonName.c_str()); 20354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger SkImageEncoder::EncodeFile(newRecord->fWhiteDiffPath.c_str(), 20454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger diffData.fResult.whiteDiffBitmap, 20554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger SkImageEncoder::kPNG_Type, 100); 20654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger diffData.fResult.whiteDiffBitmap.reset(); 20754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger bitmapsToCreate.whiteDiff = false; 208945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 209945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 210945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 211945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 212cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.comclass SkThreadedDiff : public SkRunnable { 213cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.compublic: 214cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com SkThreadedDiff() : fDiffContext(NULL) { } 215cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com 216cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com void setup(SkDiffContext* diffContext, const SkString& baselinePath, const SkString& testPath) { 217cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com fDiffContext = diffContext; 218cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com fBaselinePath = baselinePath; 219cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com fTestPath = testPath; 220cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com } 221cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com 22236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void run() override { 223cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com fDiffContext->addDiff(fBaselinePath.c_str(), fTestPath.c_str()); 224cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com } 225cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com 226cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.comprivate: 227cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com SkDiffContext* fDiffContext; 228cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com SkString fBaselinePath; 229cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com SkString fTestPath; 230cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com}; 231945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 232945708ad9494322e2bc26776ccb741776205b4b8zachr@google.comvoid SkDiffContext::diffDirectories(const char baselinePath[], const char testPath[]) { 233945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Get the files in the baseline, we will then look for those inside the test path 234945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkTArray<SkString> baselineEntries; 235945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (!get_directory(baselinePath, &baselineEntries)) { 236945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Unable to open path \"%s\"\n", baselinePath); 237945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com return; 238945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 239945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 240406654be7a930b484159f5bca107d3b11d8a9edemtklein SkTaskGroup tg; 241cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com SkTArray<SkThreadedDiff> runnableDiffs; 242cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com runnableDiffs.reset(baselineEntries.count()); 243cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com 244cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com for (int x = 0; x < baselineEntries.count(); x++) { 245cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com const char* baseFilename = baselineEntries[x].c_str(); 246945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 247945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Find the real location of each file to compare 248a8e2e1504b9af6ba791637f228debaa23953064atfarina SkString baselineFile = SkOSPath::Join(baselinePath, baseFilename); 249a8e2e1504b9af6ba791637f228debaa23953064atfarina SkString testFile = SkOSPath::Join(testPath, baseFilename); 250945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 251945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Check that the test file exists and is a file 252945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (sk_exists(testFile.c_str()) && !sk_isdir(testFile.c_str())) { 253945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Queue up the comparison with the differ 254cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com runnableDiffs[x].setup(this, baselineFile, testFile); 255406654be7a930b484159f5bca107d3b11d8a9edemtklein tg.add(&runnableDiffs[x]); 256945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } else { 257945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Baseline file \"%s\" has no corresponding test file\n", baselineFile.c_str()); 258945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 259945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 260945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 261945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 262945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 263945708ad9494322e2bc26776ccb741776205b4b8zachr@google.comvoid SkDiffContext::diffPatterns(const char baselinePattern[], const char testPattern[]) { 264945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // Get the files in the baseline and test patterns. Because they are in sorted order, it's easy 265945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // to find corresponding images by matching entry indices. 266945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 267945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkTArray<SkString> baselineEntries; 268945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (!glob_files(baselinePattern, &baselineEntries)) { 269945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Unable to get pattern \"%s\"\n", baselinePattern); 270945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com return; 271945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 272945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 273945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkTArray<SkString> testEntries; 274945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (!glob_files(testPattern, &testEntries)) { 275945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Unable to get pattern \"%s\"\n", testPattern); 276945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com return; 277945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 278945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 279945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com if (baselineEntries.count() != testEntries.count()) { 280945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com SkDebugf("Baseline and test patterns do not yield corresponding number of files\n"); 281945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com return; 282945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 283945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 284406654be7a930b484159f5bca107d3b11d8a9edemtklein SkTaskGroup tg; 285cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com SkTArray<SkThreadedDiff> runnableDiffs; 286cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com runnableDiffs.reset(baselineEntries.count()); 287945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 288cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com for (int x = 0; x < baselineEntries.count(); x++) { 289cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com runnableDiffs[x].setup(this, baselineEntries[x], testEntries[x]); 290406654be7a930b484159f5bca107d3b11d8a9edemtklein tg.add(&runnableDiffs[x]); 291945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 2927260d7292bde966f038b8e166f3fe41ddd8f2099stephana tg.wait(); 293945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 294945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 295a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.comvoid SkDiffContext::outputRecords(SkWStream& stream, bool useJSONP) { 296efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com SkTLList<DiffRecord>::Iter iter(fRecords, SkTLList<DiffRecord>::Iter::kHead_IterStart); 297efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com DiffRecord* currentRecord = iter.get(); 298efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 299a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com if (useJSONP) { 300a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com stream.writeText("var SkPDiffRecords = {\n"); 30155173f2ecc8103b7675655f4a35990ac98050205zachr@google.com } else { 302a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com stream.writeText("{\n"); 303a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com } 30454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 30554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // TODO(djsollen): Would it be better to use the jsoncpp library to write out the JSON? 30654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // This manual approach is probably more efficient, but it sure is ugly. 30754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // See http://skbug.com/2713 ('make skpdiff use jsoncpp library to write out 30854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger // JSON output, instead of manual writeText() calls?') 309945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \"records\": [\n"); 31049f085dddff10473b6ebf832a974288300224e60bsalomon while (currentRecord) { 311945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" {\n"); 312945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 313a479aa1366734f80360a00e3020f5b148cb3c060zachr@google.com SkString baselineAbsPath = get_absolute_path(currentRecord->fBaselinePath); 314a479aa1366734f80360a00e3020f5b148cb3c060zachr@google.com SkString testAbsPath = get_absolute_path(currentRecord->fTestPath); 315a479aa1366734f80360a00e3020f5b148cb3c060zachr@google.com 3161e391b587085587d8b95038dac20063b40d47dd0djsollen@google.com stream.writeText(" \"commonName\": \""); 317513a7bffd344a2bba6e014ec08838ea0bbb8aa68djsollen@google.com stream.writeText(currentRecord->fCommonName.c_str()); 3181e391b587085587d8b95038dac20063b40d47dd0djsollen@google.com stream.writeText("\",\n"); 3191e391b587085587d8b95038dac20063b40d47dd0djsollen@google.com 320cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com stream.writeText(" \"differencePath\": \""); 32154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(get_absolute_path(currentRecord->fAlphaMaskPath).c_str()); 32254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText("\",\n"); 32354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 32454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"rgbDiffPath\": \""); 32554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(get_absolute_path(currentRecord->fRgbDiffPath).c_str()); 32654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText("\",\n"); 32754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 32854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"whiteDiffPath\": \""); 32954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(get_absolute_path(currentRecord->fWhiteDiffPath).c_str()); 330cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com stream.writeText("\",\n"); 331cbbf1ca304d35e3acd944609cf7a1c5127d0ca56djsollen@google.com 332945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \"baselinePath\": \""); 333a479aa1366734f80360a00e3020f5b148cb3c060zachr@google.com stream.writeText(baselineAbsPath.c_str()); 334945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText("\",\n"); 335945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 336945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \"testPath\": \""); 337a479aa1366734f80360a00e3020f5b148cb3c060zachr@google.com stream.writeText(testAbsPath.c_str()); 338945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText("\",\n"); 339945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 34054f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"width\": "); 34154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeDecAsText(currentRecord->fSize.width()); 34254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(",\n"); 34354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"height\": "); 34454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeDecAsText(currentRecord->fSize.height()); 34554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(",\n"); 34654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 34754f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"maxRedDiff\": "); 34854f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeDecAsText(currentRecord->fMaxRedDiff); 34954f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(",\n"); 35054f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"maxGreenDiff\": "); 35154f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeDecAsText(currentRecord->fMaxGreenDiff); 35254f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(",\n"); 35354f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(" \"maxBlueDiff\": "); 35454f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeDecAsText(currentRecord->fMaxBlueDiff); 35554f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger stream.writeText(",\n"); 35654f1ad8bb5bdd2ac2ea7981427abeb193383d449epoger 357945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \"diffs\": [\n"); 358945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); diffIndex++) { 359945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com DiffData& data = currentRecord->fDiffs[diffIndex]; 360945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" {\n"); 361945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 362945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \"differName\": \""); 363945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(data.fDiffName); 364945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText("\",\n"); 365945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 366945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \"result\": "); 367efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com stream.writeScalarAsText((SkScalar)data.fResult.result); 368945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(",\n"); 369945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 370efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com stream.writeText(" \"pointsOfInterest\": "); 371efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com stream.writeDecAsText(data.fResult.poiCount); 372efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com stream.writeText("\n"); 373efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 374945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" }"); 375945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 376945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // JSON does not allow trailing commas 37755173f2ecc8103b7675655f4a35990ac98050205zachr@google.com if (diffIndex + 1 < currentRecord->fDiffs.count()) { 378945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(","); 379945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 380945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" \n"); 381945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 382945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" ]\n"); 383945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 384945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" }"); 385945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com 386efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com currentRecord = iter.next(); 387efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com 388945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com // JSON does not allow trailing commas 38949f085dddff10473b6ebf832a974288300224e60bsalomon if (currentRecord) { 390945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(","); 391945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 392945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText("\n"); 393945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com } 394945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com stream.writeText(" ]\n"); 395a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com if (useJSONP) { 396a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com stream.writeText("};\n"); 39755173f2ecc8103b7675655f4a35990ac98050205zachr@google.com } else { 398a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com stream.writeText("}\n"); 399a95959c3fb4c502b45bc78f15b65cda1f21620e6zachr@google.com } 400945708ad9494322e2bc26776ccb741776205b4b8zachr@google.com} 401c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 402c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.comvoid SkDiffContext::outputCsv(SkWStream& stream) { 403c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com SkTDict<int> columns(2); 404c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com int cntColumns = 0; 405c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 406c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText("key"); 407c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 408efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com SkTLList<DiffRecord>::Iter iter(fRecords, SkTLList<DiffRecord>::Iter::kHead_IterStart); 409efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com DiffRecord* currentRecord = iter.get(); 410c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 411c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com // Write CSV header and create a dictionary of all columns. 41249f085dddff10473b6ebf832a974288300224e60bsalomon while (currentRecord) { 413c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); diffIndex++) { 414c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com DiffData& data = currentRecord->fDiffs[diffIndex]; 415c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com if (!columns.find(data.fDiffName)) { 416c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com columns.set(data.fDiffName, cntColumns); 417c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText(", "); 418c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText(data.fDiffName); 419c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com cntColumns++; 420c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 421c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 422efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com currentRecord = iter.next(); 423c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 424c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText("\n"); 425c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 426c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com double values[100]; 427c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com SkASSERT(cntColumns < 100); // Make the array larger, if we ever have so many diff types. 428c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 429efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com SkTLList<DiffRecord>::Iter iter2(fRecords, SkTLList<DiffRecord>::Iter::kHead_IterStart); 430efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com currentRecord = iter2.get(); 43149f085dddff10473b6ebf832a974288300224e60bsalomon while (currentRecord) { 432c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com for (int i = 0; i < cntColumns; i++) { 433c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com values[i] = -1; 434c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 435c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 436c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); diffIndex++) { 437c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com DiffData& data = currentRecord->fDiffs[diffIndex]; 438c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com int index = -1; 439c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com SkAssertResult(columns.find(data.fDiffName, &index)); 440c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com SkASSERT(index >= 0 && index < cntColumns); 441efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com values[index] = data.fResult.result; 442c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 443c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 444c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com const char* filename = currentRecord->fBaselinePath.c_str() + 445c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com strlen(currentRecord->fBaselinePath.c_str()) - 1; 446c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com while (filename > currentRecord->fBaselinePath.c_str() && *(filename - 1) != '/') { 447c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com filename--; 448c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 449c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 450c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText(filename); 451c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 452c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com for (int i = 0; i < cntColumns; i++) { 453c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com SkString str; 454c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com str.printf(", %f", values[i]); 455c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText(str.c_str()); 456c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 457c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com stream.writeText("\n"); 458c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com 459efc51b79a22348e3c2596e872609a7a4b018e531djsollen@google.com currentRecord = iter2.next(); 460c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com } 461c93c8ac625a89c14f392d46620abaf6edfabe02eedisonn@google.com} 462