Chromium Code Reviews| 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" |
| 11 #include "SkData.h" | 11 #include "SkData.h" |
| 12 #include "SkPixelRef.h" | 12 #include "SkPixelRef.h" |
| 13 #include "SkPtrRecorder.h" | 13 #include "SkPtrRecorder.h" |
| 14 #include "SkStream.h" | 14 #include "SkStream.h" |
| 15 #include "SkTypeface.h" | 15 #include "SkTypeface.h" |
| 16 | 16 |
| 17 SkWriteBuffer::SkWriteBuffer(uint32_t flags) | 17 SkWriteBuffer::SkWriteBuffer(uint32_t flags) |
| 18 : fFlags(flags) | 18 : fFlags(flags) |
| 19 , fFactorySet(nullptr) | 19 , fFactorySet(nullptr) |
| 20 , fBitmapHeap(nullptr) | 20 , fBitmapHeap(nullptr) |
| 21 , fTFSet(nullptr) { | 21 , fTFSet(nullptr) |
| 22 , fNextIndex(1) { | |
| 22 } | 23 } |
| 23 | 24 |
| 24 SkWriteBuffer::SkWriteBuffer(void* storage, size_t storageSize, uint32_t flags) | 25 SkWriteBuffer::SkWriteBuffer(void* storage, size_t storageSize, uint32_t flags) |
| 25 : fFlags(flags) | 26 : fFlags(flags) |
| 26 , fFactorySet(nullptr) | 27 , fFactorySet(nullptr) |
| 27 , fWriter(storage, storageSize) | 28 , fWriter(storage, storageSize) |
| 28 , fBitmapHeap(nullptr) | 29 , fBitmapHeap(nullptr) |
| 29 , fTFSet(nullptr) { | 30 , fTFSet(nullptr) |
| 31 , fNextIndex(1) { | |
| 30 } | 32 } |
| 31 | 33 |
| 32 SkWriteBuffer::~SkWriteBuffer() { | 34 SkWriteBuffer::~SkWriteBuffer() { |
| 33 SkSafeUnref(fFactorySet); | 35 SkSafeUnref(fFactorySet); |
| 34 SkSafeUnref(fBitmapHeap); | 36 SkSafeUnref(fBitmapHeap); |
| 35 SkSafeUnref(fTFSet); | 37 SkSafeUnref(fTFSet); |
| 36 } | 38 } |
| 37 | 39 |
| 38 void SkWriteBuffer::writeByteArray(const void* data, size_t size) { | 40 void SkWriteBuffer::writeByteArray(const void* data, size_t size) { |
| 39 fWriter.write32(SkToU32(size)); | 41 fWriter.write32(SkToU32(size)); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 if (serializer) { | 253 if (serializer) { |
| 252 serializer->ref(); | 254 serializer->ref(); |
| 253 SkASSERT(nullptr == fBitmapHeap); | 255 SkASSERT(nullptr == fBitmapHeap); |
| 254 SkSafeUnref(fBitmapHeap); | 256 SkSafeUnref(fBitmapHeap); |
| 255 fBitmapHeap = nullptr; | 257 fBitmapHeap = nullptr; |
| 256 } | 258 } |
| 257 } | 259 } |
| 258 | 260 |
| 259 void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { | 261 void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { |
| 260 /* | 262 /* |
| 261 * If we have a factoryset, then the first 32bits tell us... | 263 * If this is not a validating buffer, then the first 32bits tell us... |
| 262 * 0: failure to write the flattenable | 264 * 0: failure to write the flattenable |
| 263 * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet | 265 * >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 */ | 266 */ |
| 270 if (nullptr == flattenable) { | 267 if (nullptr == flattenable) { |
| 271 if (this->isValidating()) { | 268 if (this->isValidating()) { |
| 272 this->writeString(""); | 269 this->writeString(""); |
| 273 } else if (fFactorySet != nullptr) { | 270 } else { |
| 274 this->write32(0); | 271 this->write32(0); |
| 275 } else { | |
| 276 this->writeFunctionPtr(nullptr); | |
| 277 } | 272 } |
| 278 return; | 273 return; |
| 279 } | 274 } |
| 280 | 275 |
| 281 SkFlattenable::Factory factory = flattenable->getFactory(); | 276 const char* name; |
| 282 SkASSERT(factory != nullptr); | 277 SkFlattenable::Factory factory; |
| 278 if (this->isValidating() || !fFactorySet) { | |
| 279 name = flattenable->getTypeName(); | |
| 280 SkASSERT(name); | |
| 281 } else { | |
| 282 factory = flattenable->getFactory(); | |
| 283 SkASSERT(factory); | |
| 284 } | |
| 283 | 285 |
| 284 /* | 286 /* |
| 285 * We can write 1 of 3 versions of the flattenable: | 287 * We can write 1 of 3 versions of the flattenable: |
| 286 * 1. function-ptr : this is the fastest for the reader, but assumes that | 288 * 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 | 289 * 2. index into fFactorySet : This is assumes the writer will later |
| 289 * resolve the function-ptrs into strings for its reader. SkPicture | 290 * resolve the function-ptrs into strings for its reader. SkPicture |
| 290 * does exactly this, by writing a table of names (matching the indices ) | 291 * does exactly this, by writing a table of names (matching the indices ) |
| 291 * up front in its serialized form. | 292 * up front in its serialized form. |
| 292 * 3. index into fNamedFactorySet. fNamedFactorySet will also store the | 293 * 3. index into fFlattenableDict (plus string if necessary): We store |
| 293 * name. SkGPipe uses this technique so it can write the name to its | 294 * the string to allow the reader to specify its own factories after |
| 294 * stream before writing the flattenable. | 295 * write time. In order to improve compression, if we have already |
| 296 * written the string, we only write its index. | |
| 295 */ | 297 */ |
| 296 if (this->isValidating()) { | 298 if (this->isValidating()) { |
| 297 this->writeString(flattenable->getTypeName()); | 299 this->writeString(name); |
| 298 } else if (fFactorySet) { | 300 } else if (fFactorySet) { |
| 299 this->write32(fFactorySet->add(factory)); | 301 this->write32(fFactorySet->add(factory)); |
| 300 } else { | 302 } else { |
| 301 this->writeFunctionPtr((void*)factory); | 303 SkString key(name); |
| 304 uint32_t* indexPtr = fFlattenableDict.find(key); | |
| 305 if (indexPtr) { | |
|
mtklein
2016/04/19 18:14:55
I find it nice to scope these lookups a little tig
msarett
2016/04/19 18:55:51
Done.
| |
| 306 // Only write the index if the key is already in our dictionary. | |
| 307 this->write32(*indexPtr); | |
| 308 } else { | |
| 309 // Write the index and the key | |
| 310 this->write32(fNextIndex); | |
| 311 this->writeString(name); | |
| 312 | |
| 313 // Add key to dictionary | |
| 314 fFlattenableDict.set(key, fNextIndex); | |
| 315 fNextIndex++; | |
|
mtklein
2016/04/19 18:14:55
Is fNextIndex redundant with fFlattenableDict.coun
msarett
2016/04/19 18:55:51
Hmm yeah... Nice!
| |
| 316 } | |
| 302 } | 317 } |
| 303 | 318 |
| 304 // make room for the size of the flattened object | 319 // make room for the size of the flattened object |
| 305 (void)fWriter.reserve(sizeof(uint32_t)); | 320 (void)fWriter.reserve(sizeof(uint32_t)); |
| 306 // record the current size, so we can subtract after the object writes. | 321 // record the current size, so we can subtract after the object writes. |
| 307 size_t offset = fWriter.bytesWritten(); | 322 size_t offset = fWriter.bytesWritten(); |
| 308 // now flatten the object | 323 // now flatten the object |
| 309 flattenable->flatten(*this); | 324 flattenable->flatten(*this); |
| 310 size_t objSize = fWriter.bytesWritten() - offset; | 325 size_t objSize = fWriter.bytesWritten() - offset; |
| 311 // record the obj's size | 326 // record the obj's size |
| 312 fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); | 327 fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); |
| 313 } | 328 } |
| OLD | NEW |