OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkWriteBuffer.h" | 8 #include "SkWriteBuffer.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkBitmapHeap.h" | 10 #include "SkBitmapHeap.h" |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 if (serializer) { | 251 if (serializer) { |
252 serializer->ref(); | 252 serializer->ref(); |
253 SkASSERT(nullptr == fBitmapHeap); | 253 SkASSERT(nullptr == fBitmapHeap); |
254 SkSafeUnref(fBitmapHeap); | 254 SkSafeUnref(fBitmapHeap); |
255 fBitmapHeap = nullptr; | 255 fBitmapHeap = nullptr; |
256 } | 256 } |
257 } | 257 } |
258 | 258 |
259 void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { | 259 void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { |
260 /* | 260 /* |
261 * If we have a factoryset, then the first 32bits tell us... | 261 * If this is not a validating buffer, then the first 32bits tell us... |
262 * 0: failure to write the flattenable | 262 * 0: failure to write the flattenable |
263 * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet | 263 * >0: (1-based) index into fFactorySet or fFlattenableDict |
264 * If we don't have a factoryset, then the first "ptr" is either the | |
265 * factory, or null for failure. | |
266 * | |
267 * The distinction is important, since 0-index is 32bits (always), but a | |
268 * 0-functionptr might be 32 or 64 bits. | |
269 */ | 264 */ |
270 if (nullptr == flattenable) { | 265 if (nullptr == flattenable) { |
271 if (this->isValidating()) { | 266 if (this->isValidating()) { |
272 this->writeString(""); | 267 this->writeString(""); |
273 } else if (fFactorySet != nullptr) { | 268 } else { |
274 this->write32(0); | 269 this->write32(0); |
275 } else { | |
276 this->writeFunctionPtr(nullptr); | |
277 } | 270 } |
278 return; | 271 return; |
279 } | 272 } |
280 | 273 |
281 SkFlattenable::Factory factory = flattenable->getFactory(); | 274 const char* name; |
282 SkASSERT(factory != nullptr); | 275 SkFlattenable::Factory factory; |
276 if (this->isValidating() || !fFactorySet) { | |
277 name = flattenable->getTypeName(); | |
278 SkASSERT(name); | |
279 } else { | |
280 factory = flattenable->getFactory(); | |
281 SkASSERT(factory); | |
282 } | |
283 | 283 |
284 /* | 284 /* |
285 * We can write 1 of 3 versions of the flattenable: | 285 * We can write 1 of 3 versions of the flattenable: |
286 * 1. function-ptr : this is the fastest for the reader, but assumes that | 286 * 1. string : this is used by the validating read/write buffers. |
287 * the writer and reader are in the same process. | |
288 * 2. index into fFactorySet : This is assumes the writer will later | 287 * 2. index into fFactorySet : This is assumes the writer will later |
289 * resolve the function-ptrs into strings for its reader. SkPicture | 288 * resolve the function-ptrs into strings for its reader. SkPicture |
290 * does exactly this, by writing a table of names (matching the indices ) | 289 * does exactly this, by writing a table of names (matching the indices ) |
291 * up front in its serialized form. | 290 * up front in its serialized form. |
292 * 3. index into fNamedFactorySet. fNamedFactorySet will also store the | 291 * 3. index into fFlattenableDict (plus string if necessary): We store |
293 * name. SkGPipe uses this technique so it can write the name to its | 292 * the string to allow the reader to specify its own factories after |
294 * stream before writing the flattenable. | 293 * write time. In order to improve compression, if we have already |
294 * written the string, we only write its index. | |
295 */ | 295 */ |
296 if (this->isValidating()) { | 296 if (this->isValidating()) { |
297 this->writeString(flattenable->getTypeName()); | 297 this->writeString(name); |
298 } else if (fFactorySet) { | 298 } else if (fFactorySet) { |
299 this->write32(fFactorySet->add(factory)); | 299 this->write32(fFactorySet->add(factory)); |
300 } else { | 300 } else { |
301 this->writeFunctionPtr((void*)factory); | 301 SkString key(name); |
302 if (uint32_t* indexPtr = fFlattenableDict.find(key)) { | |
303 // We will write the index as a 32-bit int. We want the first byte | |
304 // that we send to be zero - this will act as a sentinel that we | |
305 // have an index (not a string). However, whether the "first" byte | |
306 // is high or low depends on the endianness. So we will guarantee | |
307 // that the first and last byte are zero. The middle 16-bits is | |
308 // plenty to store an index. | |
309 SkASSERT(0 == *indexPtr >> 16); | |
310 this->write32(*indexPtr << 8); | |
msarett
2016/04/20 17:20:59
There are more ways to do this:
(1) I originally a
| |
311 } else { | |
312 // Otherwise write the string. Clients should not use the empty | |
313 // string as a name, or we will have a problem. | |
314 SkASSERT(strcmp("", name)); | |
315 this->writeString(name); | |
316 | |
317 // Add key to dictionary | |
318 fFlattenableDict.set(key, fFlattenableDict.count() + 1); | |
319 } | |
302 } | 320 } |
303 | 321 |
304 // make room for the size of the flattened object | 322 // make room for the size of the flattened object |
305 (void)fWriter.reserve(sizeof(uint32_t)); | 323 (void)fWriter.reserve(sizeof(uint32_t)); |
306 // record the current size, so we can subtract after the object writes. | 324 // record the current size, so we can subtract after the object writes. |
307 size_t offset = fWriter.bytesWritten(); | 325 size_t offset = fWriter.bytesWritten(); |
308 // now flatten the object | 326 // now flatten the object |
309 flattenable->flatten(*this); | 327 flattenable->flatten(*this); |
310 size_t objSize = fWriter.bytesWritten() - offset; | 328 size_t objSize = fWriter.bytesWritten() - offset; |
311 // record the obj's size | 329 // record the obj's size |
312 fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); | 330 fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); |
313 } | 331 } |
OLD | NEW |