| Index: tools/PictureRenderer.cpp
|
| diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
|
| index 2afd3745d18258a09ac36355d80b2634a27da93f..f71b9544e025781394eef60acf0ca519a1aa17fc 100644
|
| --- a/tools/PictureRenderer.cpp
|
| +++ b/tools/PictureRenderer.cpp
|
| @@ -22,6 +22,7 @@
|
| #include "SkImageEncoder.h"
|
| #include "SkMaskFilter.h"
|
| #include "SkMatrix.h"
|
| +#include "SkOSFile.h"
|
| #include "SkPicture.h"
|
| #include "SkPictureUtils.h"
|
| #include "SkPixelRef.h"
|
| @@ -50,32 +51,62 @@ 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.
|
| +/*
|
| + * TODO(epoger): Make constant strings consistent instead of mixing hypenated and camel-caps.
|
| + *
|
| + * TODO(epoger): Similar 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.
|
| + *
|
| + * Note that, as of https://codereview.chromium.org/226293002 , the JSON
|
| + * schema used here has started to differ from the one in gm_expectations.cpp .
|
| + * TODO(epoger): Consider getting GM and render_pictures to use the same JSON
|
| + * output module.
|
| */
|
| -const static char kJsonKey_ActualResults[] = "actual-results";
|
| -const static char kJsonKey_ActualResults_NoComparison[] = "no-comparison";
|
| -const static char kJsonKey_Hashtype_Bitmap_64bitMD5[] = "bitmap-64bitMD5";
|
| -
|
| -void ImageResultsSummary::add(const char *testName, uint64_t hash) {
|
| - Json::Value jsonTypeValuePair;
|
| - jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5));
|
| - jsonTypeValuePair.append(Json::UInt64(hash));
|
| - fActualResultsNoComparison[testName] = jsonTypeValuePair;
|
| +const static char kJsonKey_ActualResults[] = "actual-results";
|
| +const static char kJsonKey_Header[] = "header";
|
| +const static char kJsonKey_Header_Type[] = "type";
|
| +const static char kJsonKey_Header_Revision[] = "revision"; // unique within Type
|
| +const static char kJsonKey_Image_ChecksumAlgorithm[] = "checksumAlgorithm";
|
| +const static char kJsonKey_Image_ChecksumValue[] = "checksumValue";
|
| +const static char kJsonKey_Image_ComparisonResult[] = "comparisonResult";
|
| +const static char kJsonKey_Image_Filepath[] = "filepath";
|
| +const static char kJsonKey_Source_TiledImages[] = "tiled-images";
|
| +const static char kJsonKey_Source_WholeImage[] = "whole-image";
|
| +// Values (not keys) that are written out by this JSON generator
|
| +const static char kJsonValue_Header_Type[] = "ChecksummedImages";
|
| +const static int kJsonValue_Header_Revision = 1;
|
| +const static char kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5[] = "bitmap-64bitMD5";
|
| +const static char kJsonValue_Image_ComparisonResult_NoComparison[] = "no-comparison";
|
| +
|
| +void ImageResultsSummary::add(const char *sourceName, const char *fileName, uint64_t hash,
|
| + const int *tileNumber) {
|
| + Json::Value image;
|
| + image[kJsonKey_Image_ChecksumAlgorithm] = kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5;
|
| + image[kJsonKey_Image_ChecksumValue] = Json::UInt64(hash);
|
| + image[kJsonKey_Image_ComparisonResult] = kJsonValue_Image_ComparisonResult_NoComparison;
|
| + image[kJsonKey_Image_Filepath] = fileName;
|
| + if (NULL == tileNumber) {
|
| + fActualResults[sourceName][kJsonKey_Source_WholeImage] = image;
|
| + } else {
|
| + fActualResults[sourceName][kJsonKey_Source_TiledImages][*tileNumber] = image;
|
| + }
|
| }
|
|
|
| -void ImageResultsSummary::add(const char *testName, const SkBitmap& bitmap) {
|
| +void ImageResultsSummary::add(const char *sourceName, const char *fileName, const SkBitmap& bitmap,
|
| + const int *tileNumber) {
|
| uint64_t hash;
|
| SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
|
| - this->add(testName, hash);
|
| + this->add(sourceName, fileName, hash, tileNumber);
|
| }
|
|
|
| void ImageResultsSummary::writeToFile(const char *filename) {
|
| - Json::Value actualResults;
|
| - actualResults[kJsonKey_ActualResults_NoComparison] = fActualResultsNoComparison;
|
| + Json::Value header;
|
| + header[kJsonKey_Header_Type] = kJsonValue_Header_Type;
|
| + header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision;
|
| Json::Value root;
|
| - root[kJsonKey_ActualResults] = actualResults;
|
| + root[kJsonKey_Header] = header;
|
| + root[kJsonKey_ActualResults] = fActualResults;
|
| std::string jsonStdString = root.toStyledString();
|
| SkFILEWStream stream(filename);
|
| stream.write(jsonStdString.c_str(), jsonStdString.length());
|
| @@ -304,7 +335,7 @@ uint32_t PictureRenderer::recordFlags() {
|
| * @param inputFilename If we are writing out a binary image, use this to build its filename.
|
| * @param jsonSummaryPtr If not null, add image results to this summary.
|
| * @param useChecksumBasedFilenames If true, use checksum-based filenames when writing to disk.
|
| - * @param numberToAppend If not null, append this number to the filename.
|
| + * @param tileNumberPtr If not null, which tile number this image contains.
|
| * @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
|
| @@ -320,7 +351,7 @@ uint32_t PictureRenderer::recordFlags() {
|
| */
|
| static bool write(SkCanvas* canvas, const SkString& outputDir, const SkString& inputFilename,
|
| ImageResultsSummary *jsonSummaryPtr, bool useChecksumBasedFilenames,
|
| - const int* numberToAppend=NULL) {
|
| + const int* tileNumberPtr=NULL) {
|
| SkASSERT(canvas != NULL);
|
| if (NULL == canvas) {
|
| return false;
|
| @@ -337,40 +368,61 @@ static bool write(SkCanvas* canvas, const SkString& outputDir, const SkString& i
|
| canvas->readPixels(&bitmap, 0, 0);
|
| sk_tools::force_all_opaque(bitmap);
|
|
|
| - SkString outputFilename(inputFilename);
|
| - outputFilename.remove(outputFilename.size() - 4, 4);
|
| - if (NULL != numberToAppend) {
|
| - outputFilename.appendf("%i", *numberToAppend);
|
| - }
|
| - outputFilename.append(".png");
|
| + SkString escapedInputFilename(inputFilename);
|
| + replace_char(&escapedInputFilename, '.', '_');
|
| +
|
| // TODO(epoger): what about including the config type within outputFilename? That way,
|
| // we could combine results of different config types without conflicting filenames.
|
| -
|
| - if (NULL != jsonSummaryPtr) {
|
| + SkString outputFilename;
|
| + const char *outputSubdirPtr = NULL;
|
| + if (useChecksumBasedFilenames) {
|
| SkASSERT(!generatedHash);
|
| SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
|
| generatedHash = true;
|
|
|
| - jsonSummaryPtr->add(outputFilename.c_str(), hash);
|
| + outputSubdirPtr = escapedInputFilename.c_str();
|
| + outputFilename.set(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5);
|
| + outputFilename.append("_");
|
| + outputFilename.appendU64(hash);
|
| + } else {
|
| + outputFilename.set(escapedInputFilename);
|
| + if (NULL != tileNumberPtr) {
|
| + outputFilename.append("-tile");
|
| + outputFilename.appendS32(*tileNumberPtr);
|
| + }
|
| }
|
| + outputFilename.append(".png");
|
|
|
| - // Update outputFilename AFTER adding to JSON summary, but BEFORE writing out the image file.
|
| - if (useChecksumBasedFilenames) {
|
| + if (NULL != jsonSummaryPtr) {
|
| if (!generatedHash) {
|
| SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
|
| generatedHash = true;
|
| }
|
| - outputFilename.set(kJsonKey_Hashtype_Bitmap_64bitMD5);
|
| - outputFilename.append("_");
|
| - outputFilename.appendU64(hash);
|
| - outputFilename.append(".png");
|
| +
|
| + SkString outputRelativePath;
|
| + if (outputSubdirPtr) {
|
| + outputRelativePath.set(outputSubdirPtr);
|
| + outputRelativePath.append("/"); // always use "/", even on Windows
|
| + outputRelativePath.append(outputFilename);
|
| + } else {
|
| + outputRelativePath.set(outputFilename);
|
| + }
|
| +
|
| + jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(),
|
| + hash, tileNumberPtr);
|
| }
|
|
|
| SkASSERT(!outputDir.isEmpty()); // TODO(epoger): we want to remove this constraint,
|
| // as noted above
|
| - SkString fullPathname;
|
| - make_filepath(&fullPathname, outputDir, outputFilename);
|
| - return SkImageEncoder::EncodeFile(fullPathname.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
|
| + SkString dirPath;
|
| + if (outputSubdirPtr) {
|
| + dirPath = SkOSPath::SkPathJoin(outputDir.c_str(), outputSubdirPtr);
|
| + sk_mkdir(dirPath.c_str());
|
| + } else {
|
| + dirPath.set(outputDir);
|
| + }
|
| + SkString fullPath = SkOSPath::SkPathJoin(dirPath.c_str(), outputFilename.c_str());
|
| + return SkImageEncoder::EncodeFile(fullPath.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////
|
| @@ -394,8 +446,7 @@ bool RecordPictureRenderer::render(SkBitmap** out) {
|
| replayer->endRecording();
|
| if (!fOutputDir.isEmpty()) {
|
| // Record the new picture as a new SKP with PNG encoded bitmaps.
|
| - SkString skpPath;
|
| - make_filepath(&skpPath, fOutputDir, fInputFilename);
|
| + SkString skpPath = SkOSPath::SkPathJoin(fOutputDir.c_str(), fInputFilename.c_str());
|
| SkFILEWStream stream(skpPath.c_str());
|
| replayer->serialize(&stream, &encode_bitmap_to_data);
|
| return true;
|
|
|