aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-13 20:52:36 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-13 20:52:36 +0000
commita3f882c4756bd8b9b6449dcc60b6d884ee0cc8ed (patch)
tree57732aea29d2401783e38b2b4ec7ef8f521d2e55
parente132f5031fb700e34af1ea08b575b2c774393047 (diff)
render_pictures: add --writeJsonSummaryPath
Known issues: - JSON summary will be empty if --writePath not specified also - testNames within summary do not include the config (8888, gpu, etc.) BUG= R=rmistry@google.com Author: epoger@google.com Review URL: https://codereview.chromium.org/98643007 git-svn-id: http://skia.googlecode.com/svn/trunk@12680 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gyp/tools.gyp44
-rw-r--r--tools/PictureRenderer.cpp120
-rw-r--r--tools/PictureRenderer.h31
-rw-r--r--tools/render_pictures_main.cpp65
4 files changed, 207 insertions, 53 deletions
diff --git a/gyp/tools.gyp b/gyp/tools.gyp
index 04d4e3f0fc..fd381b7a32 100644
--- a/gyp/tools.gyp
+++ b/gyp/tools.gyp
@@ -141,8 +141,8 @@
'../tools/skhello.cpp',
],
'dependencies': [
- 'pdf.gyp:pdf',
'flags.gyp:flags',
+ 'pdf.gyp:pdf',
],
}],
],
@@ -158,10 +158,10 @@
'../src/utils/',
],
'dependencies': [
- 'skia_lib.gyp:skia_lib',
'flags.gyp:flags',
'gm.gyp:gm_expectations',
'jsoncpp.gyp:jsoncpp',
+ 'skia_lib.gyp:skia_lib',
'utils.gyp:utils',
],
},
@@ -174,13 +174,13 @@
'../src/utils/SkLua.cpp',
],
'dependencies': [
- 'skia_lib.gyp:skia_lib',
'effects.gyp:effects',
- 'utils.gyp:utils',
'images.gyp:images',
+ 'lua.gyp:lua',
'pdf.gyp:pdf',
'ports.gyp:ports',
- 'lua.gyp:lua',
+ 'skia_lib.gyp:skia_lib',
+ 'utils.gyp:utils',
],
},
{
@@ -192,16 +192,16 @@
'../src/utils/SkLua.cpp',
],
'dependencies': [
- 'skia_lib.gyp:skia_lib',
'effects.gyp:effects',
- 'utils.gyp:utils',
+ 'flags.gyp:flags',
'images.gyp:images',
+ 'lua.gyp:lua',
'tools.gyp:picture_renderer',
'tools.gyp:picture_utils',
'pdf.gyp:pdf',
'ports.gyp:ports',
- 'flags.gyp:flags',
- 'lua.gyp:lua',
+ 'skia_lib.gyp:skia_lib',
+ 'utils.gyp:utils',
],
},
{
@@ -217,10 +217,10 @@
'../src/pipe/utils/',
],
'dependencies': [
+ 'flags.gyp:flags',
'skia_lib.gyp:skia_lib',
'tools.gyp:picture_renderer',
'tools.gyp:picture_utils',
- 'flags.gyp:flags',
],
},
{
@@ -240,11 +240,11 @@
'../src/lazy/',
],
'dependencies': [
+ 'bench.gyp:bench_timer',
+ 'flags.gyp:flags',
'skia_lib.gyp:skia_lib',
'tools.gyp:picture_utils',
'tools.gyp:picture_renderer',
- 'bench.gyp:bench_timer',
- 'flags.gyp:flags',
],
},
{
@@ -268,10 +268,18 @@
'../src/pipe/utils/',
'../src/utils/',
],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ # needed for JSON headers used within PictureRenderer.h
+ '../third_party/externals/jsoncpp-chromium/overrides/include/',
+ '../third_party/externals/jsoncpp/include/',
+ ],
+ },
'dependencies': [
+ 'flags.gyp:flags',
+ 'jsoncpp.gyp:jsoncpp',
'skia_lib.gyp:skia_lib',
'tools.gyp:picture_utils',
- 'flags.gyp:flags',
],
'conditions': [
['skia_gpu == 1',
@@ -296,8 +304,8 @@
'../src/utils/',
],
'dependencies': [
- 'skia_lib.gyp:skia_lib',
'pdf.gyp:pdf',
+ 'skia_lib.gyp:skia_lib',
'tools.gyp:picture_utils',
],
'conditions': [
@@ -359,9 +367,9 @@
'../tools/pinspect.cpp',
],
'dependencies': [
+ 'flags.gyp:flags',
'skia_lib.gyp:skia_lib',
'tools.gyp:picture_renderer',
- 'flags.gyp:flags',
],
},
{
@@ -379,11 +387,11 @@
'../bench/TimerData.cpp',
],
'dependencies': [
- 'skia_lib.gyp:skia_lib',
'bench.gyp:bench_timer',
- 'tools.gyp:picture_utils',
- 'tools.gyp:picture_renderer',
'flags.gyp:flags',
+ 'skia_lib.gyp:skia_lib',
+ 'tools.gyp:picture_renderer',
+ 'tools.gyp:picture_utils',
],
},
{
diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
index c53bd08265..88ddc75137 100644
--- a/tools/PictureRenderer.cpp
+++ b/tools/PictureRenderer.cpp
@@ -8,6 +8,7 @@
#include "PictureRenderer.h"
#include "picture_utils.h"
#include "SamplePipeControllers.h"
+#include "SkBitmapHasher.h"
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDevice.h"
@@ -40,6 +41,39 @@ enum {
kDefaultTileHeight = 256
};
+/* TODO(epoger): These constants are already maintained in 2 other places:
+ * gm/gm_json.py and gm/gm_expectations.cpp. We shouldn't add yet a third place.
+ * Figure out a way to share the definitions instead.
+ */
+const static char kJsonKey_ActualResults[] = "actual-results";
+const static char kJsonKey_ActualResults_Failed[] = "failed";
+const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored";
+const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison";
+const static char kJsonKey_ActualResults_Succeeded[] = "succeeded";
+const static char kJsonKey_ExpectedResults[] = "expected-results";
+const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests";
+const static char kJsonKey_ExpectedResults_IgnoreFailure[] = "ignore-failure";
+const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5";
+
+void ImageResultsSummary::add(const char *testName, const SkBitmap& bitmap) {
+ uint64_t hash;
+ SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
+ Json::Value jsonTypeValuePair;
+ jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5));
+ jsonTypeValuePair.append(Json::UInt64(hash));
+ fActualResultsNoComparison[testName] = jsonTypeValuePair;
+}
+
+void ImageResultsSummary::writeToFile(const char *filename) {
+ Json::Value actualResults;
+ actualResults[kJsonKey_ActualResults_NoComparison] = fActualResultsNoComparison;
+ Json::Value root;
+ root[kJsonKey_ActualResults] = actualResults;
+ std::string jsonStdString = root.toStyledString();
+ SkFILEWStream stream(filename);
+ stream.write(jsonStdString.c_str(), jsonStdString.length());
+}
+
void PictureRenderer::init(SkPicture* pict) {
SkASSERT(NULL == fPicture);
SkASSERT(NULL == fCanvas.get());
@@ -217,14 +251,28 @@ uint32_t PictureRenderer::recordFlags() {
* @param canvas Must be non-null. Canvas to be written to a file.
* @param path Path for the file to be written. Should have no extension; write() will append
* an appropriate one. Passed in by value so it can be modified.
+ * @param jsonSummaryPtr If not null, add image results to this summary.
* @return bool True if the Canvas is written to a file.
+ *
+ * TODO(epoger): Right now, all canvases must pass through this function in order to be appended
+ * to the ImageResultsSummary. We need some way to add bitmaps to the ImageResultsSummary
+ * even if --writePath has not been specified (and thus this function is not called).
+ *
+ * One fix would be to pass in these path elements separately, and allow this function to be
+ * called even if --writePath was not specified...
+ * const char *outputDir // NULL if we don't want to write image files to disk
+ * const char *filename // name we use within JSON summary, and as the filename within outputDir
*/
-static bool write(SkCanvas* canvas, SkString path) {
+static bool write(SkCanvas* canvas, const SkString* path, ImageResultsSummary *jsonSummaryPtr) {
SkASSERT(canvas != NULL);
if (NULL == canvas) {
return false;
}
+ SkASSERT(path != NULL); // TODO(epoger): we want to remove this constraint, as noted above
+ SkString fullPathname(*path);
+ fullPathname.append(".png");
+
SkBitmap bitmap;
SkISize size = canvas->getDeviceSize();
sk_tools::setup_bitmap(&bitmap, size.width(), size.height());
@@ -232,22 +280,33 @@ static bool write(SkCanvas* canvas, SkString path) {
canvas->readPixels(&bitmap, 0, 0);
sk_tools::force_all_opaque(bitmap);
- // Since path is passed in by value, it is okay to modify it.
- path.append(".png");
- return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
+ if (NULL != jsonSummaryPtr) {
+ // EPOGER: This is a hacky way of constructing the filename associated with the
+ // image checksum; we assume that outputDir is not NULL, and we remove outputDir
+ // from fullPathname.
+ //
+ // EPOGER: what about including the config type within hashFilename? That way,
+ // we could combine results of different config types without conflicting filenames.
+ SkString hashFilename;
+ sk_tools::get_basename(&hashFilename, fullPathname);
+ jsonSummaryPtr->add(hashFilename.c_str(), bitmap);
+ }
+
+ return SkImageEncoder::EncodeFile(fullPathname.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
}
/**
- * If path is non NULL, append number to it, and call write(SkCanvas*, SkString) to write the
+ * If path is non NULL, append number to it, and call write() to write the
* provided canvas to a file. Returns true if path is NULL or if write() succeeds.
*/
-static bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number) {
+static bool writeAppendNumber(SkCanvas* canvas, const SkString* path, int number,
+ ImageResultsSummary *jsonSummaryPtr) {
if (NULL == path) {
return true;
}
SkString pathWithNumber(*path);
pathWithNumber.appendf("%i", number);
- return write(canvas, pathWithNumber);
+ return write(canvas, &pathWithNumber, jsonSummaryPtr);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -309,7 +368,7 @@ bool PipePictureRenderer::render(const SkString* path, SkBitmap** out) {
writer.endRecording();
fCanvas->flush();
if (NULL != path) {
- return write(fCanvas, *path);
+ return write(fCanvas, path, fJsonSummaryPtr);
}
if (NULL != out) {
*out = SkNEW(SkBitmap);
@@ -340,7 +399,7 @@ bool SimplePictureRenderer::render(const SkString* path, SkBitmap** out) {
fCanvas->drawPicture(*fPicture);
fCanvas->flush();
if (NULL != path) {
- return write(fCanvas, *path);
+ return write(fCanvas, path, fJsonSummaryPtr);
}
if (NULL != out) {
@@ -506,11 +565,22 @@ static void DrawTileToCanvas(SkCanvas* canvas, const SkRect& tileRect, T* playba
///////////////////////////////////////////////////////////////////////////////////////////////
-static void bitmapCopySubset(const SkBitmap& src, SkBitmap* dst, int xDst,
- int yDst) {
- for (int y = 0; y <src.height() && y + yDst < dst->height() ; y++) {
- for (int x = 0; x < src.width() && x + xDst < dst->width() ; x++) {
- *dst->getAddr32(xDst + x, yDst + y) = *src.getAddr32(x, y);
+/**
+ * Copies the entirety of the src bitmap (typically a tile) into a portion of the dst bitmap.
+ * If the src bitmap is too large to fit within the dst bitmap after the x and y
+ * offsets have been applied, any excess will be ignored (so only the top-left portion of the
+ * src bitmap will be copied).
+ *
+ * @param src source bitmap
+ * @param dst destination bitmap
+ * @param xOffset x-offset within destination bitmap
+ * @param yOffset y-offset within destination bitmap
+ */
+static void bitmapCopyAtOffset(const SkBitmap& src, SkBitmap* dst,
+ int xOffset, int yOffset) {
+ for (int y = 0; y <src.height() && y + yOffset < dst->height() ; y++) {
+ for (int x = 0; x < src.width() && x + xOffset < dst->width() ; x++) {
+ *dst->getAddr32(xOffset + x, yOffset + y) = *src.getAddr32(x, y);
}
}
}
@@ -545,12 +615,13 @@ bool TiledPictureRenderer::render(const SkString* path, SkBitmap** out) {
for (int i = 0; i < fTileRects.count(); ++i) {
DrawTileToCanvas(fCanvas, fTileRects[i], fPicture);
if (NULL != path) {
- success &= writeAppendNumber(fCanvas, path, i);
+ success &= writeAppendNumber(fCanvas, path, i, fJsonSummaryPtr);
}
if (NULL != out) {
if (fCanvas->readPixels(&bitmap, 0, 0)) {
- bitmapCopySubset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()),
- SkScalarFloorToInt(fTileRects[i].top()));
+ // Add this tile to the entire bitmap.
+ bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()),
+ SkScalarFloorToInt(fTileRects[i].top()));
} else {
success = false;
}
@@ -603,7 +674,7 @@ class CloneData : public SkRunnable {
public:
CloneData(SkPicture* clone, SkCanvas* canvas, SkTDArray<SkRect>& rects, int start, int end,
- SkRunnable* done)
+ SkRunnable* done, ImageResultsSummary* jsonSummaryPtr)
: fClone(clone)
, fCanvas(canvas)
, fPath(NULL)
@@ -611,7 +682,8 @@ public:
, fStart(start)
, fEnd(end)
, fSuccess(NULL)
- , fDone(done) {
+ , fDone(done)
+ , fJsonSummaryPtr(jsonSummaryPtr) {
SkASSERT(fDone != NULL);
}
@@ -626,7 +698,7 @@ public:
for (int i = fStart; i < fEnd; i++) {
DrawTileToCanvas(fCanvas, fRects[i], fClone);
- if (fPath != NULL && !writeAppendNumber(fCanvas, fPath, i)
+ if ((fPath != NULL) && !writeAppendNumber(fCanvas, fPath, i, fJsonSummaryPtr)
&& fSuccess != NULL) {
*fSuccess = false;
// If one tile fails to write to a file, do not continue drawing the rest.
@@ -635,8 +707,8 @@ public:
if (fBitmap != NULL) {
if (fCanvas->readPixels(&bitmap, 0, 0)) {
SkAutoLockPixels alp(*fBitmap);
- bitmapCopySubset(bitmap, fBitmap, SkScalarFloorToInt(fRects[i].left()),
- SkScalarFloorToInt(fRects[i].top()));
+ bitmapCopyAtOffset(bitmap, fBitmap, SkScalarFloorToInt(fRects[i].left()),
+ SkScalarFloorToInt(fRects[i].top()));
} else {
*fSuccess = false;
// If one tile fails to read pixels, do not continue drawing the rest.
@@ -669,6 +741,7 @@ private:
// and only set to false upon failure to write to a PNG.
SkRunnable* fDone;
SkBitmap* fBitmap;
+ ImageResultsSummary* fJsonSummaryPtr;
};
MultiCorePictureRenderer::MultiCorePictureRenderer(int threadCount)
@@ -704,7 +777,8 @@ void MultiCorePictureRenderer::init(SkPicture *pict) {
const int start = i * chunkSize;
const int end = SkMin32(start + chunkSize, fTileRects.count());
fCloneData[i] = SkNEW_ARGS(CloneData,
- (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown));
+ (pic, fCanvasPool[i], fTileRects, start, end, &fCountdown,
+ fJsonSummaryPtr));
}
}
diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h
index 6a84130ac6..6d886abfdc 100644
--- a/tools/PictureRenderer.h
+++ b/tools/PictureRenderer.h
@@ -11,6 +11,7 @@
#include "SkCanvas.h"
#include "SkCountdown.h"
#include "SkDrawFilter.h"
+#include "SkJSONCPP.h"
#include "SkMath.h"
#include "SkPaint.h"
#include "SkPicture.h"
@@ -37,6 +38,30 @@ namespace sk_tools {
class TiledPictureRenderer;
+/**
+ * Class for collecting image results (checksums) as we go.
+ */
+class ImageResultsSummary {
+public:
+ /**
+ * Adds this bitmap's hash to the summary of results.
+ *
+ * @param testName name of the test
+ * @param bitmap bitmap to store the hash of
+ */
+ void add(const char *testName, const SkBitmap& bitmap);
+
+ /**
+ * Writes the summary (as constructed so far) to a file.
+ *
+ * @param filename path to write the summary to
+ */
+ void writeToFile(const char *filename);
+
+private:
+ Json::Value fActualResultsNoComparison;
+};
+
class PictureRenderer : public SkRefCnt {
public:
@@ -183,6 +208,10 @@ public:
fGridInfo.fTileInterval.set(width, height);
}
+ void setJsonSummaryPtr(ImageResultsSummary* jsonSummaryPtr) {
+ fJsonSummaryPtr = jsonSummaryPtr;
+ }
+
bool isUsingBitmapDevice() {
return kBitmap_DeviceType == fDeviceType;
}
@@ -266,6 +295,7 @@ public:
PictureRenderer()
: fPicture(NULL)
+ , fJsonSummaryPtr(NULL)
, fDeviceType(kBitmap_DeviceType)
, fBBoxHierarchyType(kNone_BBoxHierarchyType)
, fScaleFactor(SK_Scalar1)
@@ -290,6 +320,7 @@ public:
protected:
SkAutoTUnref<SkCanvas> fCanvas;
SkPicture* fPicture;
+ ImageResultsSummary* fJsonSummaryPtr;
SkDeviceTypes fDeviceType;
BBoxHierarchyType fBBoxHierarchyType;
DrawFilterFlags fDrawFilters[SkDrawFilter::kTypeCount];
diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp
index 70bc22132b..b067a652bd 100644
--- a/tools/render_pictures_main.cpp
+++ b/tools/render_pictures_main.cpp
@@ -32,6 +32,8 @@ DECLARE_string(readPath);
DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded image, write it to a "
"file rather than decoding it. Requires writePath to be set. Skips drawing the full "
"skp to a file. Not compatible with deferImageDecoding.");
+DEFINE_string(writeJsonSummaryPath, "", "File to write a JSON summary of image results to. "
+ "TODO(epoger): Currently, this only works if --writePath is also specified.");
DEFINE_string2(writePath, w, "", "Directory to write the rendered images.");
DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered image to a "
"file, instead of an image for each tile.");
@@ -132,9 +134,12 @@ static bool write_image_to_file(const void* buffer, size_t size, SkBitmap* bitma
////////////////////////////////////////////////////////////////////////////////////////////////////
-static bool render_picture(const SkString& inputPath, const SkString* outputDir,
- sk_tools::PictureRenderer& renderer,
- SkBitmap** out) {
+/**
+ * Called only by render_picture().
+ */
+static bool render_picture_internal(const SkString& inputPath, const SkString* outputDir,
+ sk_tools::PictureRenderer& renderer,
+ SkBitmap** out) {
SkString inputFilename;
sk_tools::get_basename(&inputFilename, inputPath);
@@ -241,11 +246,21 @@ private:
};
}
+/**
+ * Render the SKP file(s) within inputPath, writing their bitmap images into outputDir.
+ *
+ * @param inputPath path to an individual SKP file, or a directory of SKP files
+ * @param outputDir if not NULL, write the image(s) generated into this directory
+ * @param renderer PictureRenderer to use to render the SKPs
+ * @param jsonSummaryPtr if not NULL, add the image(s) generated to this summary
+ */
static bool render_picture(const SkString& inputPath, const SkString* outputDir,
- sk_tools::PictureRenderer& renderer) {
+ sk_tools::PictureRenderer& renderer,
+ sk_tools::ImageResultsSummary *jsonSummaryPtr) {
int diffs[256] = {0};
SkBitmap* bitmap = NULL;
- bool success = render_picture(inputPath,
+ renderer.setJsonSummaryPtr(jsonSummaryPtr);
+ bool success = render_picture_internal(inputPath,
FLAGS_writeWholeImage ? NULL : outputDir,
renderer,
FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : NULL);
@@ -272,8 +287,8 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
}
SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRenderer);
- success = render_picture(inputPath, NULL, *referenceRenderer,
- &referenceBitmap);
+ success = render_picture_internal(inputPath, NULL, *referenceRenderer,
+ &referenceBitmap);
if (!success || NULL == referenceBitmap || NULL == referenceBitmap->getPixels()) {
SkDebugf("Failed to draw the reference picture.\n");
@@ -327,7 +342,24 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
if (FLAGS_writeWholeImage) {
sk_tools::force_all_opaque(*bitmap);
- if (NULL != outputDir && FLAGS_writeWholeImage) {
+
+ if (NULL != jsonSummaryPtr) {
+ // EPOGER: This is a hacky way of constructing the filename associated with the
+ // image checksum; we basically are repeating the logic of make_output_filepath()
+ // and code below here, within here.
+ // It would be better for the filename (without outputDir) to be passed in here,
+ // and used both for the checksum file and writing into outputDir.
+ //
+ // EPOGER: what about including the config type within hashFilename? That way,
+ // we could combine results of different config types without conflicting filenames.
+ SkString hashFilename;
+ sk_tools::get_basename(&hashFilename, inputPath);
+ hashFilename.remove(hashFilename.size() - 4, 4); // Remove ".skp"
+ hashFilename.append(".png");
+ jsonSummaryPtr->add(hashFilename.c_str(), *bitmap);
+ }
+
+ if (NULL != outputDir) {
SkString inputFilename;
sk_tools::get_basename(&inputFilename, inputPath);
SkString outputPath;
@@ -347,7 +379,8 @@ static bool render_picture(const SkString& inputPath, const SkString* outputDir,
static int process_input(const char* input, const SkString* outputDir,
- sk_tools::PictureRenderer& renderer) {
+ sk_tools::PictureRenderer& renderer,
+ sk_tools::ImageResultsSummary *jsonSummaryPtr) {
SkOSFile::Iter iter(input, "skp");
SkString inputFilename;
int failures = 0;
@@ -357,13 +390,13 @@ static int process_input(const char* input, const SkString* outputDir,
SkString inputPath;
SkString inputAsSkString(input);
sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename);
- if (!render_picture(inputPath, outputDir, renderer)) {
+ if (!render_picture(inputPath, outputDir, renderer, jsonSummaryPtr)) {
++failures;
}
} while(iter.next(&inputFilename));
} else if (SkStrEndsWith(input, ".skp")) {
SkString inputPath(input);
- if (!render_picture(inputPath, outputDir, renderer)) {
+ if (!render_picture(inputPath, outputDir, renderer, jsonSummaryPtr)) {
++failures;
}
} else {
@@ -427,10 +460,15 @@ int tool_main(int argc, char** argv) {
if (FLAGS_writePath.count() == 1) {
outputDir.set(FLAGS_writePath[0]);
}
+ sk_tools::ImageResultsSummary jsonSummary;
+ sk_tools::ImageResultsSummary* jsonSummaryPtr = NULL;
+ if (FLAGS_writeJsonSummaryPath.count() == 1) {
+ jsonSummaryPtr = &jsonSummary;
+ }
int failures = 0;
for (int i = 0; i < FLAGS_readPath.count(); i ++) {
- failures += process_input(FLAGS_readPath[i], &outputDir, *renderer.get());
+ failures += process_input(FLAGS_readPath[i], &outputDir, *renderer.get(), jsonSummaryPtr);
}
if (failures != 0) {
SkDebugf("Failed to render %i pictures.\n", failures);
@@ -447,6 +485,9 @@ int tool_main(int argc, char** argv) {
}
#endif
#endif
+ if (FLAGS_writeJsonSummaryPath.count() == 1) {
+ jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]);
+ }
return 0;
}