Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: dm/DMWriteTask.cpp

Issue 788243008: Sketch DM refactor. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: better failure messages, disable a few things temporarily to try to go green Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « dm/DMWriteTask.h ('k') | dm/README » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #include "DMWriteTask.h"
2
3 #include "DMJsonWriter.h"
4 #include "DMUtil.h"
5 #include "SkColorPriv.h"
6 #include "SkCommonFlags.h"
7 #include "SkData.h"
8 #include "SkImageEncoder.h"
9 #include "SkMD5.h"
10 #include "SkMallocPixelRef.h"
11 #include "SkOSFile.h"
12 #include "SkStream.h"
13 #include "SkString.h"
14
15 DEFINE_bool(nameByHash, false, "If true, write .../hash.png instead of .../mode/ config/name.png");
16
17 namespace DM {
18
19 // Splits off the last N suffixes of name (splitting on _) and appends them to o ut.
20 // Returns the total number of characters consumed.
21 static int split_suffixes(int N, const char* name, SkTArray<SkString>* out) {
22 SkTArray<SkString> split;
23 SkStrSplit(name, "_", &split);
24 int consumed = 0;
25 for (int i = 0; i < N; i++) {
26 // We're splitting off suffixes from the back to front.
27 out->push_back(split[split.count()-i-1]);
28 consumed += SkToInt(out->back().size() + 1); // Add one for the _.
29 }
30 return consumed;
31 }
32
33 inline static SkString find_base_name(const Task& parent, SkTArray<SkString>* su ffixList) {
34 const int suffixes = parent.depth() + 1;
35 const SkString& name = parent.name();
36 const int totalSuffixLength = split_suffixes(suffixes, name.c_str(), suffixL ist);
37 return SkString(name.c_str(), name.size() - totalSuffixLength);
38 }
39
40 WriteTask::WriteTask(const Task& parent, const char* sourceType, SkBitmap bitmap )
41 : CpuTask(parent)
42 , fBaseName(find_base_name(parent, &fSuffixes))
43 , fSourceType(sourceType)
44 , fBitmap(bitmap)
45 , fData(NULL)
46 , fExtension(".png") {
47 }
48
49 WriteTask::WriteTask(const Task& parent,
50 const char* sourceType,
51 SkStreamAsset *data,
52 const char* ext)
53 : CpuTask(parent)
54 , fBaseName(find_base_name(parent, &fSuffixes))
55 , fSourceType(sourceType)
56 , fData(data)
57 , fExtension(ext) {
58 SkASSERT(fData.get());
59 SkASSERT(fData->unique());
60 }
61
62 void WriteTask::makeDirOrFail(SkString dir) {
63 // This can be a little racy, so if it fails check to see if someone else su cceeded.
64 if (!sk_mkdir(dir.c_str()) && !sk_isdir(dir.c_str())) {
65 this->fail("Can't make directory.");
66 }
67 }
68
69 static SkString get_md5_string(SkMD5* hasher) {
70 SkMD5::Digest digest;
71 hasher->finish(digest);
72
73 SkString md5;
74 for (int i = 0; i < 16; i++) {
75 md5.appendf("%02x", digest.data[i]);
76 }
77 return md5;
78 }
79
80 static SkString get_md5(const void* ptr, size_t len) {
81 SkMD5 hasher;
82 hasher.write(ptr, len);
83 return get_md5_string(&hasher);
84 }
85
86 static bool write_asset(SkStreamAsset* input, SkWStream* output) {
87 return input->rewind() && output->writeStream(input, input->getLength());
88 }
89
90 static SkString get_md5(SkStreamAsset* stream) {
91 SkMD5 hasher;
92 write_asset(stream, &hasher);
93 return get_md5_string(&hasher);
94 }
95
96 static bool encode_png(const SkBitmap& src, SkFILEWStream* file) {
97 SkBitmap bm;
98 // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first.
99 if (src.info().colorType() == kAlpha_8_SkColorType) {
100 if (!src.copyTo(&bm, kN32_SkColorType)) {
101 return false;
102 }
103 } else {
104 bm = src;
105 }
106 return SkImageEncoder::EncodeStream(file, bm, SkImageEncoder::kPNG_Type, 100 );
107 }
108
109 void WriteTask::draw() {
110 SkString md5;
111 {
112 SkAutoLockPixels lock(fBitmap);
113 md5 = fData ? get_md5(fData)
114 : get_md5(fBitmap.getPixels(), fBitmap.getSize());
115 }
116
117 SkASSERT(fSuffixes.count() > 0);
118 SkString config = fSuffixes.back();
119 SkString mode("direct");
120 if (fSuffixes.count() > 1) {
121 mode = fSuffixes.fromBack(1);
122 }
123
124 {
125 const JsonWriter::BitmapResult entry = { fBaseName,
126 config,
127 mode,
128 fSourceType,
129 md5 };
130 JsonWriter::AddBitmapResult(entry);
131 }
132
133 SkString dir(FLAGS_writePath[0]);
134 #if defined(SK_BUILD_FOR_IOS)
135 if (dir.equals("@")) {
136 dir.set(FLAGS_resourcePath[0]);
137 }
138 #endif
139 this->makeDirOrFail(dir);
140
141 SkString path;
142 if (FLAGS_nameByHash) {
143 // Flat directory of hash-named files.
144 path = SkOSPath::Join(dir.c_str(), md5.c_str());
145 path.append(fExtension);
146 // We're content-addressed, so it's possible two threads race to write
147 // this file. We let the first one win. This also means we won't
148 // overwrite identical files from previous runs.
149 if (sk_exists(path.c_str())) {
150 return;
151 }
152 } else {
153 // Nested by mode, config, etc.
154 for (int i = 0; i < fSuffixes.count(); i++) {
155 dir = SkOSPath::Join(dir.c_str(), fSuffixes[i].c_str());
156 this->makeDirOrFail(dir);
157 }
158 path = SkOSPath::Join(dir.c_str(), fBaseName.c_str());
159 path.append(fExtension);
160 // The path is unique, so two threads can't both write to the same file.
161 // If already present we overwrite here, since the content may have chan ged.
162 }
163
164 SkFILEWStream file(path.c_str());
165 if (!file.isValid()) {
166 return this->fail("Can't open file.");
167 }
168
169 bool ok = fData ? write_asset(fData, &file)
170 : encode_png(fBitmap, &file);
171 if (!ok) {
172 return this->fail("Can't write to file.");
173 }
174 }
175
176 SkString WriteTask::name() const {
177 SkString name("writing ");
178 for (int i = 0; i < fSuffixes.count(); i++) {
179 name.appendf("%s/", fSuffixes[i].c_str());
180 }
181 name.append(fBaseName.c_str());
182 return name;
183 }
184
185 bool WriteTask::shouldSkip() const {
186 return FLAGS_writePath.isEmpty();
187 }
188
189 } // namespace DM
OLDNEW
« no previous file with comments | « dm/DMWriteTask.h ('k') | dm/README » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698