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
diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp
index 70bc221..b067a65 100644
--- a/tools/render_pictures_main.cpp
+++ b/tools/render_pictures_main.cpp
@@ -32,6 +32,8 @@
 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 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 @@
 };
 }
 
+/**
+ * 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 @@
         }
         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 @@
 
     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 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 @@
             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 @@
     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 @@
     }
 #endif
 #endif
+    if (FLAGS_writeJsonSummaryPath.count() == 1) {
+        jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]);
+    }
     return 0;
 }