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 "SkCommonFlags.h" | 5 #include "SkCommonFlags.h" |
6 #include "SkImageEncoder.h" | 6 #include "SkImageEncoder.h" |
7 #include "SkMD5.h" | 7 #include "SkMD5.h" |
8 #include "SkMallocPixelRef.h" | 8 #include "SkMallocPixelRef.h" |
9 #include "SkOSFile.h" | 9 #include "SkOSFile.h" |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 SkASSERT(fData.get()); | 60 SkASSERT(fData.get()); |
61 SkASSERT(fData->unique()); | 61 SkASSERT(fData->unique()); |
62 } | 62 } |
63 | 63 |
64 void WriteTask::makeDirOrFail(SkString dir) { | 64 void WriteTask::makeDirOrFail(SkString dir) { |
65 if (!sk_mkdir(dir.c_str())) { | 65 if (!sk_mkdir(dir.c_str())) { |
66 this->fail(); | 66 this->fail(); |
67 } | 67 } |
68 } | 68 } |
69 | 69 |
70 static bool save_bitmap_to_file(SkBitmap bitmap, const char* path) { | 70 static SkStreamAsset* encode_to_png(const SkBitmap& bitmap) { |
71 SkFILEWStream stream(path); | 71 SkDynamicMemoryWStream png; |
72 if (!stream.isValid() || | 72 if (!SkImageEncoder::EncodeStream(&png, bitmap, SkImageEncoder::kPNG_Type, 1
00)) { |
73 !SkImageEncoder::EncodeStream(&stream, bitmap, SkImageEncoder::kPNG_Type
, 100)) { | 73 return NULL; |
74 SkDebugf("Can't write a PNG to %s.\n", path); | |
75 return false; | |
76 } | 74 } |
77 return true; | 75 png.copyToData()->unref(); // Forces detachAsStream() to be contiguous. |
| 76 return png.detachAsStream(); |
78 } | 77 } |
79 | 78 |
80 // Does not take ownership of data. | 79 static SkString get_md5(SkStreamAsset* src) { |
81 static bool save_data_to_file(SkStreamAsset* data, const char* path) { | |
82 data->rewind(); | |
83 SkFILEWStream stream(path); | |
84 if (!stream.isValid() || !stream.writeStream(data, data->getLength())) { | |
85 SkDebugf("Can't write data to %s.\n", path); | |
86 return false; | |
87 } | |
88 return true; | |
89 } | |
90 | |
91 static SkString finish_hash(SkMD5* hasher) { | |
92 SkMD5::Digest digest; | |
93 hasher->finish(digest); | |
94 | |
95 SkString out; | |
96 for (int i = 0; i < 16; i++) { | |
97 out.appendf("%02x", digest.data[i]); | |
98 } | |
99 return out; | |
100 } | |
101 | |
102 static SkString hash(const SkBitmap& src) { | |
103 SkMD5 hasher; | |
104 { | |
105 SkAutoLockPixels lock(src); | |
106 hasher.write(src.getPixels(), src.getSize()); | |
107 } | |
108 return finish_hash(&hasher); | |
109 } | |
110 | |
111 static SkString hash(SkStreamAsset* src) { | |
112 SkMD5 hasher; | 80 SkMD5 hasher; |
113 hasher.write(src->getMemoryBase(), src->getLength()); | 81 hasher.write(src->getMemoryBase(), src->getLength()); |
114 return finish_hash(&hasher); | 82 SkMD5::Digest digest; |
| 83 hasher.finish(digest); |
| 84 |
| 85 SkString md5; |
| 86 for (int i = 0; i < 16; i++) { |
| 87 md5.appendf("%02x", digest.data[i]); |
| 88 } |
| 89 return md5; |
115 } | 90 } |
116 | 91 |
117 void WriteTask::draw() { | 92 void WriteTask::draw() { |
118 JsonData entry = { | 93 if (!fData.get()) { |
119 fFullName, | 94 fData.reset(encode_to_png(fBitmap)); |
120 fData ? hash(fData) : hash(fBitmap), | 95 if (!fData.get()) { |
121 }; | 96 this->fail("Can't encode to PNG."); |
| 97 } |
| 98 } |
122 | 99 |
| 100 JsonData entry = { fFullName, get_md5(fData) }; |
123 { | 101 { |
124 SkAutoMutexAcquire lock(&gJsonDataLock); | 102 SkAutoMutexAcquire lock(&gJsonDataLock); |
125 gJsonData.push_back(entry); | 103 gJsonData.push_back(entry); |
126 } | 104 } |
127 | 105 |
128 SkString dir(FLAGS_writePath[0]); | 106 SkString dir(FLAGS_writePath[0]); |
129 #if SK_BUILD_FOR_IOS | 107 #if SK_BUILD_FOR_IOS |
130 if (dir.equals("@")) { | 108 if (dir.equals("@")) { |
131 dir.set(FLAGS_resourcePath[0]); | 109 dir.set(FLAGS_resourcePath[0]); |
132 } | 110 } |
(...skipping 16 matching lines...) Expand all Loading... |
149 for (int i = 0; i < fSuffixes.count(); i++) { | 127 for (int i = 0; i < fSuffixes.count(); i++) { |
150 dir = SkOSPath::Join(dir.c_str(), fSuffixes[i].c_str()); | 128 dir = SkOSPath::Join(dir.c_str(), fSuffixes[i].c_str()); |
151 this->makeDirOrFail(dir); | 129 this->makeDirOrFail(dir); |
152 } | 130 } |
153 path = SkOSPath::Join(dir.c_str(), fBaseName.c_str()); | 131 path = SkOSPath::Join(dir.c_str(), fBaseName.c_str()); |
154 path.append(fExtension); | 132 path.append(fExtension); |
155 // The path is unique, so two threads can't both write to the same file. | 133 // The path is unique, so two threads can't both write to the same file. |
156 // If already present we overwrite here, since the content may have chan
ged. | 134 // If already present we overwrite here, since the content may have chan
ged. |
157 } | 135 } |
158 | 136 |
159 const bool ok = fData.get() ? save_data_to_file(fData.get(), path.c_str()) | 137 SkFILEWStream file(path.c_str()); |
160 : save_bitmap_to_file(fBitmap, path.c_str()); | 138 if (!file.isValid()) { |
161 if (!ok) { | 139 return this->fail("Can't open file."); |
162 this->fail(); | 140 } |
| 141 |
| 142 fData->rewind(); |
| 143 if (!file.writeStream(fData, fData->getLength())) { |
| 144 return this->fail("Can't write to file."); |
163 } | 145 } |
164 } | 146 } |
165 | 147 |
166 SkString WriteTask::name() const { | 148 SkString WriteTask::name() const { |
167 SkString name("writing "); | 149 SkString name("writing "); |
168 for (int i = 0; i < fSuffixes.count(); i++) { | 150 for (int i = 0; i < fSuffixes.count(); i++) { |
169 name.appendf("%s/", fSuffixes[i].c_str()); | 151 name.appendf("%s/", fSuffixes[i].c_str()); |
170 } | 152 } |
171 name.append(fBaseName.c_str()); | 153 name.append(fBaseName.c_str()); |
172 return name; | 154 return name; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 return expectations.detach(); | 188 return expectations.detach(); |
207 } | 189 } |
208 | 190 |
209 bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const { | 191 bool WriteTask::Expectations::check(const Task& task, SkBitmap bitmap) const { |
210 const SkString name = task.name(); | 192 const SkString name = task.name(); |
211 if (fJson[name.c_str()].isNull()) { | 193 if (fJson[name.c_str()].isNull()) { |
212 return true; // No expectations. | 194 return true; // No expectations. |
213 } | 195 } |
214 | 196 |
215 const char* expected = fJson[name.c_str()].asCString(); | 197 const char* expected = fJson[name.c_str()].asCString(); |
216 SkString actual = hash(bitmap); | 198 SkAutoTDelete<SkStreamAsset> png(encode_to_png(bitmap)); |
| 199 SkString actual = get_md5(png); |
217 return actual.equals(expected); | 200 return actual.equals(expected); |
218 } | 201 } |
219 | 202 |
220 void WriteTask::DumpJson() { | 203 void WriteTask::DumpJson() { |
221 if (FLAGS_writePath.isEmpty()) { | 204 if (FLAGS_writePath.isEmpty()) { |
222 return; | 205 return; |
223 } | 206 } |
224 | 207 |
225 // FIXME: This JSON format is a complete MVP strawman. | 208 // FIXME: This JSON format is a complete MVP strawman. |
226 Json::Value root; | 209 Json::Value root; |
227 { | 210 { |
228 SkAutoMutexAcquire lock(&gJsonDataLock); | 211 SkAutoMutexAcquire lock(&gJsonDataLock); |
229 for (int i = 0; i < gJsonData.count(); i++) { | 212 for (int i = 0; i < gJsonData.count(); i++) { |
230 root[gJsonData[i].name.c_str()] = gJsonData[i].md5.c_str(); | 213 root[gJsonData[i].name.c_str()] = gJsonData[i].md5.c_str(); |
231 } | 214 } |
232 } | 215 } |
233 | 216 |
234 SkString path = SkOSPath::Join(FLAGS_writePath[0], "dm.json"); | 217 SkString path = SkOSPath::Join(FLAGS_writePath[0], "dm.json"); |
235 SkFILEWStream stream(path.c_str()); | 218 SkFILEWStream stream(path.c_str()); |
236 stream.writeText(Json::StyledWriter().write(root).c_str()); | 219 stream.writeText(Json::StyledWriter().write(root).c_str()); |
237 stream.flush(); | 220 stream.flush(); |
238 } | 221 } |
239 | 222 |
240 } // namespace DM | 223 } // namespace DM |
OLD | NEW |