| Index: dm/DMWriteTask.cpp
|
| diff --git a/dm/DMWriteTask.cpp b/dm/DMWriteTask.cpp
|
| index 2a129a57b16351380ac4e77644c44c0ae011119e..00dfffc198f04d773b22243b9190b17c1854cdb8 100644
|
| --- a/dm/DMWriteTask.cpp
|
| +++ b/dm/DMWriteTask.cpp
|
| @@ -10,6 +10,8 @@
|
| #include "SkStream.h"
|
| #include "SkString.h"
|
|
|
| +DEFINE_bool(nameByHash, false, "If true, write .../hash.png instead of .../mode/config/name.png");
|
| +
|
| namespace DM {
|
|
|
| // Splits off the last N suffixes of name (splitting on _) and appends them to out.
|
| @@ -35,7 +37,7 @@ inline static SkString find_base_name(const Task& parent, SkTArray<SkString>* su
|
|
|
| struct JsonData {
|
| SkString name;
|
| - SkMD5::Digest md5;
|
| + SkString md5; // In ASCII, so 32 bytes long.
|
| };
|
| SkTArray<JsonData> gJsonData;
|
| SK_DECLARE_STATIC_MUTEX(gJsonDataLock);
|
| @@ -86,39 +88,73 @@ static bool save_data_to_file(SkStreamAsset* data, const char* path) {
|
| return true;
|
| }
|
|
|
| -void WriteTask::draw() {
|
| - SkString dir(FLAGS_writePath[0]);
|
| -#if SK_BUILD_FOR_IOS
|
| - if (dir.equals("@")) {
|
| - dir.set(FLAGS_resourcePath[0]);
|
| - }
|
| -#endif
|
| - this->makeDirOrFail(dir);
|
| - for (int i = 0; i < fSuffixes.count(); i++) {
|
| - dir = SkOSPath::Join(dir.c_str(), fSuffixes[i].c_str());
|
| - this->makeDirOrFail(dir);
|
| +static SkString finish_hash(SkMD5* hasher) {
|
| + SkMD5::Digest digest;
|
| + hasher->finish(digest);
|
| +
|
| + SkString out;
|
| + for (int i = 0; i < 16; i++) {
|
| + out.appendf("%02x", digest.data[i]);
|
| }
|
| + return out;
|
| +}
|
|
|
| - // FIXME: MD5 is really slow. Let's use a different hash.
|
| +static SkString hash(const SkBitmap& src) {
|
| SkMD5 hasher;
|
| - if (fData.get()) {
|
| - hasher.write(fData->getMemoryBase(), fData->getLength());
|
| - } else {
|
| - SkAutoLockPixels lock(fBitmap);
|
| - hasher.write(fBitmap.getPixels(), fBitmap.getSize());
|
| + {
|
| + SkAutoLockPixels lock(src);
|
| + hasher.write(src.getPixels(), src.getSize());
|
| }
|
| + return finish_hash(&hasher);
|
| +}
|
|
|
| - JsonData entry;
|
| - entry.name = fFullName;
|
| - hasher.finish(entry.md5);
|
| +static SkString hash(SkStreamAsset* src) {
|
| + SkMD5 hasher;
|
| + hasher.write(src->getMemoryBase(), src->getLength());
|
| + return finish_hash(&hasher);
|
| +}
|
| +
|
| +void WriteTask::draw() {
|
| + JsonData entry = {
|
| + fFullName,
|
| + fData ? hash(fData) : hash(fBitmap),
|
| + };
|
|
|
| {
|
| SkAutoMutexAcquire lock(&gJsonDataLock);
|
| gJsonData.push_back(entry);
|
| }
|
|
|
| - SkString path = SkOSPath::Join(dir.c_str(), fBaseName.c_str());
|
| - path.append(fExtension);
|
| + SkString dir(FLAGS_writePath[0]);
|
| +#if SK_BUILD_FOR_IOS
|
| + if (dir.equals("@")) {
|
| + dir.set(FLAGS_resourcePath[0]);
|
| + }
|
| +#endif
|
| + this->makeDirOrFail(dir);
|
| +
|
| + SkString path;
|
| + if (FLAGS_nameByHash) {
|
| + // Flat directory of hash-named files.
|
| + path = SkOSPath::Join(dir.c_str(), entry.md5.c_str());
|
| + path.append(fExtension);
|
| + // We're content-addressed, so it's possible two threads race to write
|
| + // this file. We let the first one win. This also means we won't
|
| + // overwrite identical files from previous runs.
|
| + if (sk_exists(path.c_str())) {
|
| + return;
|
| + }
|
| + } else {
|
| + // Nested by mode, config, etc.
|
| + for (int i = 0; i < fSuffixes.count(); i++) {
|
| + dir = SkOSPath::Join(dir.c_str(), fSuffixes[i].c_str());
|
| + this->makeDirOrFail(dir);
|
| + }
|
| + path = SkOSPath::Join(dir.c_str(), fBaseName.c_str());
|
| + path.append(fExtension);
|
| + // The path is unique, so two threads can't both write to the same file.
|
| + // If already present we overwrite here, since the content may have changed.
|
| + }
|
|
|
| const bool ok = fData.get() ? save_data_to_file(fData.get(), path.c_str())
|
| : save_bitmap_to_file(fBitmap, path.c_str());
|
| @@ -176,22 +212,9 @@ bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const {
|
| return true; // No expectations.
|
| }
|
|
|
| - const char* md5Ascii = fJson[name.c_str()].asCString();
|
| - uint8_t md5[16];
|
| -
|
| - for (int j = 0; j < 16; j++) {
|
| - sscanf(md5Ascii + (j*2), "%02hhx", md5 + j);
|
| - }
|
| -
|
| - SkMD5 hasher;
|
| - {
|
| - SkAutoLockPixels lock(bitmap);
|
| - hasher.write(bitmap.getPixels(), bitmap.getSize());
|
| - }
|
| - SkMD5::Digest digest;
|
| - hasher.finish(digest);
|
| -
|
| - return 0 == memcmp(md5, digest.data, 16);
|
| + const char* expected = fJson[name.c_str()].asCString();
|
| + SkString actual = hash(bitmap);
|
| + return actual.equals(expected);
|
| }
|
|
|
| void WriteTask::DumpJson() {
|
| @@ -204,11 +227,7 @@ void WriteTask::DumpJson() {
|
| {
|
| SkAutoMutexAcquire lock(&gJsonDataLock);
|
| for (int i = 0; i < gJsonData.count(); i++) {
|
| - char md5Ascii[32];
|
| - for (int j = 0; j < 16; j++) {
|
| - sprintf(md5Ascii + (j*2), "%02x", gJsonData[i].md5.data[j]);
|
| - }
|
| - root[gJsonData[i].name.c_str()] = md5Ascii;
|
| + root[gJsonData[i].name.c_str()] = gJsonData[i].md5.c_str();
|
| }
|
| }
|
|
|
|
|