| OLD | NEW |
| 1 #include "DMWriteTask.h" | 1 #include "DMWriteTask.h" |
| 2 | 2 |
| 3 #include "DMUtil.h" | 3 #include "DMUtil.h" |
| 4 #include "SkColorPriv.h" | 4 #include "SkColorPriv.h" |
| 5 #include "SkCommandLineFlags.h" | 5 #include "SkCommandLineFlags.h" |
| 6 #include "SkImageEncoder.h" | 6 #include "SkImageEncoder.h" |
| 7 #include "SkMallocPixelRef.h" |
| 8 #include "SkStream.h" |
| 7 #include "SkString.h" | 9 #include "SkString.h" |
| 8 #include "SkStream.h" | |
| 9 | 10 |
| 10 DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs."); | 11 DEFINE_string2(writePath, w, "", "If set, write GMs here as .pngs."); |
| 11 | 12 |
| 12 namespace DM { | 13 namespace DM { |
| 13 | 14 |
| 14 // Splits off the last N suffixes of name (splitting on _) and appends them to o
ut. | 15 // Splits off the last N suffixes of name (splitting on _) and appends them to o
ut. |
| 15 // Returns the total number of characters consumed. | 16 // Returns the total number of characters consumed. |
| 16 static int split_suffixes(int N, const char* name, SkTArray<SkString>* out) { | 17 static int split_suffixes(int N, const char* name, SkTArray<SkString>* out) { |
| 17 SkTArray<SkString> split; | 18 SkTArray<SkString> split; |
| 18 SkStrSplit(name, "_", &split); | 19 SkStrSplit(name, "_", &split); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 31 const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), &fSuffi
xes); | 32 const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), &fSuffi
xes); |
| 32 fGmName.set(name.c_str(), name.size()-totalSuffixLength); | 33 fGmName.set(name.c_str(), name.size()-totalSuffixLength); |
| 33 } | 34 } |
| 34 | 35 |
| 35 void WriteTask::makeDirOrFail(SkString dir) { | 36 void WriteTask::makeDirOrFail(SkString dir) { |
| 36 if (!sk_mkdir(dir.c_str())) { | 37 if (!sk_mkdir(dir.c_str())) { |
| 37 this->fail(); | 38 this->fail(); |
| 38 } | 39 } |
| 39 } | 40 } |
| 40 | 41 |
| 42 namespace { |
| 43 |
| 41 // One file that first contains a .png of an SkBitmap, then its raw pixels. | 44 // One file that first contains a .png of an SkBitmap, then its raw pixels. |
| 42 // We use this custom format to avoid premultiplied/unpremultiplied pixel conver
sions. | 45 // We use this custom format to avoid premultiplied/unpremultiplied pixel conver
sions. |
| 43 struct PngAndRaw { | 46 struct PngAndRaw { |
| 44 static bool Encode(SkBitmap bitmap, const char* path) { | 47 static bool Encode(SkBitmap bitmap, const char* path) { |
| 45 SkFILEWStream stream(path); | 48 SkFILEWStream stream(path); |
| 46 if (!stream.isValid()) { | 49 if (!stream.isValid()) { |
| 47 SkDebugf("Can't write %s.\n", path); | 50 SkDebugf("Can't write %s.\n", path); |
| 48 return false; | 51 return false; |
| 49 } | 52 } |
| 50 | 53 |
| 51 // Write a PNG first for humans and other tools to look at. | 54 // Write a PNG first for humans and other tools to look at. |
| 52 if (!SkImageEncoder::EncodeStream(&stream, bitmap, SkImageEncoder::kPNG_
Type, 100)) { | 55 if (!SkImageEncoder::EncodeStream(&stream, bitmap, SkImageEncoder::kPNG_
Type, 100)) { |
| 53 SkDebugf("Can't encode a PNG.\n"); | 56 SkDebugf("Can't encode a PNG.\n"); |
| 54 return false; | 57 return false; |
| 55 } | 58 } |
| 56 | 59 |
| 60 // Pad out so the raw pixels start 4-byte aligned. |
| 61 const uint32_t maxPadding = 0; |
| 62 const size_t pos = stream.bytesWritten(); |
| 63 stream.write(&maxPadding, SkAlign4(pos) - pos); |
| 64 |
| 57 // Then write our secret raw pixels that only DM reads. | 65 // Then write our secret raw pixels that only DM reads. |
| 58 SkAutoLockPixels lock(bitmap); | 66 SkAutoLockPixels lock(bitmap); |
| 59 return stream.write(bitmap.getPixels(), bitmap.getSize()); | 67 return stream.write(bitmap.getPixels(), bitmap.getSize()); |
| 60 } | 68 } |
| 61 | 69 |
| 62 // This assumes bitmap already has allocated pixels of the correct size. | 70 // This assumes bitmap already has allocated pixels of the correct size. |
| 63 static bool Decode(const char* path, SkBitmap* bitmap) { | 71 static bool Decode(const char* path, SkImageInfo info, SkBitmap* bitmap) { |
| 64 SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(path)); | 72 SkAutoTUnref<SkData> data(SkData::NewFromFileName(path)); |
| 65 if (NULL == stream.get()) { | 73 if (!data) { |
| 66 SkDebugf("Can't read %s.\n", path); | 74 SkDebugf("Can't read %s.\n", path); |
| 67 return false; | 75 return false; |
| 68 } | 76 } |
| 69 | 77 |
| 70 // The raw pixels are at the end of the stream. Seek ahead to skip beyo
nd the encoded PNG. | 78 // The raw pixels are at the end of the file. We'll skip the encoded PN
G at the front. |
| 71 const size_t bitmapBytes = bitmap->getSize(); | 79 const size_t rowBytes = info.minRowBytes(); // Assume densely packed. |
| 72 if (stream->getLength() < bitmapBytes) { | 80 const size_t bitmapBytes = info.getSafeSize(rowBytes); |
| 81 if (data->size() < bitmapBytes) { |
| 73 SkDebugf("%s is too small to contain the bitmap we're looking for.\n
", path); | 82 SkDebugf("%s is too small to contain the bitmap we're looking for.\n
", path); |
| 74 return false; | 83 return false; |
| 75 } | 84 } |
| 76 SkAssertResult(stream->seek(stream->getLength() - bitmapBytes)); | |
| 77 | 85 |
| 78 // Read the raw pixels. | 86 const size_t offset = data->size() - bitmapBytes; |
| 79 // TODO(mtklein): can we install a pixelref that just hangs onto the str
eam instead of | 87 SkAutoTUnref<SkPixelRef> pixels( |
| 80 // copying into a malloc'd buffer? | 88 SkMallocPixelRef::NewWithData(info, rowBytes, NULL/*ctable*/, data,
offset)); |
| 81 SkAutoLockPixels lock(*bitmap); | 89 SkASSERT(pixels); |
| 82 if (bitmapBytes != stream->read(bitmap->getPixels(), bitmapBytes)) { | |
| 83 SkDebugf("Couldn't read raw bitmap from %s at %lu of %lu.\n", | |
| 84 path, stream->getPosition(), stream->getLength()); | |
| 85 return false; | |
| 86 } | |
| 87 | 90 |
| 88 SkASSERT(stream->isAtEnd()); | 91 bitmap->setConfig(info, rowBytes); |
| 92 bitmap->setPixelRef(pixels); |
| 89 return true; | 93 return true; |
| 90 } | 94 } |
| 91 }; | 95 }; |
| 92 | 96 |
| 97 } // namespace |
| 98 |
| 93 void WriteTask::draw() { | 99 void WriteTask::draw() { |
| 94 SkString dir(FLAGS_writePath[0]); | 100 SkString dir(FLAGS_writePath[0]); |
| 95 this->makeDirOrFail(dir); | 101 this->makeDirOrFail(dir); |
| 96 for (int i = 0; i < fSuffixes.count(); i++) { | 102 for (int i = 0; i < fSuffixes.count(); i++) { |
| 97 dir = SkOSPath::SkPathJoin(dir.c_str(), fSuffixes[i].c_str()); | 103 dir = SkOSPath::SkPathJoin(dir.c_str(), fSuffixes[i].c_str()); |
| 98 this->makeDirOrFail(dir); | 104 this->makeDirOrFail(dir); |
| 99 } | 105 } |
| 100 SkString path = SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str()); | 106 SkString path = SkOSPath::SkPathJoin(dir.c_str(), fGmName.c_str()); |
| 101 path.append(".png"); | 107 path.append(".png"); |
| 102 if (!PngAndRaw::Encode(fBitmap, path.c_str())) { | 108 if (!PngAndRaw::Encode(fBitmap, path.c_str())) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 } | 143 } |
| 138 | 144 |
| 139 bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const { | 145 bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const { |
| 140 if (!FLAGS_writePath.isEmpty() && 0 == strcmp(FLAGS_writePath[0], fRoot)) { | 146 if (!FLAGS_writePath.isEmpty() && 0 == strcmp(FLAGS_writePath[0], fRoot)) { |
| 141 SkDebugf("We seem to be reading and writing %s concurrently. This won't
work.\n", fRoot); | 147 SkDebugf("We seem to be reading and writing %s concurrently. This won't
work.\n", fRoot); |
| 142 return false; | 148 return false; |
| 143 } | 149 } |
| 144 | 150 |
| 145 const SkString path = path_to_expected_image(fRoot, task); | 151 const SkString path = path_to_expected_image(fRoot, task); |
| 146 SkBitmap expected; | 152 SkBitmap expected; |
| 147 expected.allocPixels(bitmap.info()); | 153 if (!PngAndRaw::Decode(path.c_str(), bitmap.info(), &expected)) { |
| 148 if (!PngAndRaw::Decode(path.c_str(), &expected)) { | |
| 149 return false; | 154 return false; |
| 150 } | 155 } |
| 151 | 156 |
| 152 return BitmapsEqual(expected, bitmap); | 157 return BitmapsEqual(expected, bitmap); |
| 153 } | 158 } |
| 154 | 159 |
| 155 } // namespace DM | 160 } // namespace DM |
| OLD | NEW |