| Index: tools/PictureRenderer.cpp
|
| diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp
|
| index 2afd3745d18258a09ac36355d80b2634a27da93f..3cc138e71cb8a7b7c6c56489ebb45453be44f272 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,31 +51,51 @@ 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): 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_ActualResults_NoComparison[] = "no-comparison";
|
| +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_Filepath[] = "filepath";
|
| +// 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";
|
| +
|
| +void ImageResultsSummary::add(const char *testName, const char *fileName, uint64_t hash) {
|
| + Json::Value node;
|
| + node[kJsonKey_Image_ChecksumAlgorithm] = kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5;
|
| + node[kJsonKey_Image_ChecksumValue] = Json::UInt64(hash);
|
| + node[kJsonKey_Image_Filepath] = fileName;
|
| + fActualResultsNoComparison[testName] = node;
|
| }
|
|
|
| -void ImageResultsSummary::add(const char *testName, const SkBitmap& bitmap) {
|
| +void ImageResultsSummary::add(const char *testName, const char *fileName, const SkBitmap& bitmap) {
|
| uint64_t hash;
|
| SkAssertResult(SkBitmapHasher::ComputeDigest(bitmap, &hash));
|
| - this->add(testName, hash);
|
| + this->add(testName, fileName, hash);
|
| }
|
|
|
| void ImageResultsSummary::writeToFile(const char *filename) {
|
| + Json::Value header;
|
| + header[kJsonKey_Header_Type] = kJsonValue_Header_Type;
|
| + header[kJsonKey_Header_Revision] = kJsonValue_Header_Revision;
|
| Json::Value actualResults;
|
| actualResults[kJsonKey_ActualResults_NoComparison] = fActualResultsNoComparison;
|
| Json::Value root;
|
| + root[kJsonKey_Header] = header;
|
| root[kJsonKey_ActualResults] = actualResults;
|
| std::string jsonStdString = root.toStyledString();
|
| SkFILEWStream stream(filename);
|
| @@ -337,40 +358,60 @@ 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");
|
| // TODO(epoger): what about including the config type within outputFilename? That way,
|
| // we could combine results of different config types without conflicting filenames.
|
| + SkString inputFilenameWithTileNumber(inputFilename);
|
| + if (NULL != numberToAppend) {
|
| + inputFilenameWithTileNumber.append("-tile");
|
| + inputFilenameWithTileNumber.appendS32(*numberToAppend);
|
| + }
|
| + SkString escapedInputFilenameWithTileNumber(inputFilenameWithTileNumber);
|
| + replace_char(&escapedInputFilenameWithTileNumber, '.', '_');
|
|
|
| - 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 = escapedInputFilenameWithTileNumber.c_str();
|
| + outputFilename.set(kJsonValue_Image_ChecksumAlgorithm_Bitmap64bitMD5);
|
| + outputFilename.append("_");
|
| + outputFilename.appendU64(hash);
|
| + } else {
|
| + outputFilename.set(escapedInputFilenameWithTileNumber);
|
| }
|
| + 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(inputFilenameWithTileNumber.c_str(), outputRelativePath.c_str(), hash);
|
| }
|
|
|
| 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 +435,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;
|
|
|