| 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 * The first 32 bits 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: index (1-based) into fFactorySet or fFlattenableDict or |
| 264 * If we don't have a factoryset, then the first "ptr" is either the | 264 * the first character of a string |
| 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 */ | 265 */ |
| 270 if (nullptr == flattenable) { | 266 if (nullptr == flattenable) { |
| 271 if (this->isValidating()) { | 267 this->write32(0); |
| 272 this->writeString(""); | |
| 273 } else if (fFactorySet != nullptr) { | |
| 274 this->write32(0); | |
| 275 } else { | |
| 276 this->writeFunctionPtr(nullptr); | |
| 277 } | |
| 278 return; | 268 return; |
| 279 } | 269 } |
| 280 | 270 |
| 281 SkFlattenable::Factory factory = flattenable->getFactory(); | |
| 282 SkASSERT(factory != nullptr); | |
| 283 | |
| 284 /* | 271 /* |
| 285 * We can write 1 of 3 versions of the flattenable: | 272 * We can write 1 of 2 versions of the flattenable: |
| 286 * 1. function-ptr : this is the fastest for the reader, but assumes that | 273 * 1. index into fFactorySet : This assumes the writer will later |
| 287 * the writer and reader are in the same process. | |
| 288 * 2. index into fFactorySet : This is assumes the writer will later | |
| 289 * resolve the function-ptrs into strings for its reader. SkPicture | 274 * resolve the function-ptrs into strings for its reader. SkPicture |
| 290 * does exactly this, by writing a table of names (matching the indices
) | 275 * does exactly this, by writing a table of names (matching the indices
) |
| 291 * up front in its serialized form. | 276 * up front in its serialized form. |
| 292 * 3. index into fNamedFactorySet. fNamedFactorySet will also store the | 277 * 2. string name of the flattenable or index into fFlattenableDict: We |
| 293 * name. SkGPipe uses this technique so it can write the name to its | 278 * store the string to allow the reader to specify its own factories |
| 294 * stream before writing the flattenable. | 279 * after write time. In order to improve compression, if we have |
| 280 * already written the string, we write its index instead. |
| 295 */ | 281 */ |
| 296 if (this->isValidating()) { | 282 if (fFactorySet) { |
| 297 this->writeString(flattenable->getTypeName()); | 283 SkFlattenable::Factory factory = flattenable->getFactory(); |
| 298 } else if (fFactorySet) { | 284 SkASSERT(factory); |
| 299 this->write32(fFactorySet->add(factory)); | 285 this->write32(fFactorySet->add(factory)); |
| 300 } else { | 286 } else { |
| 301 this->writeFunctionPtr((void*)factory); | 287 const char* name = flattenable->getTypeName(); |
| 288 SkASSERT(name); |
| 289 SkString key(name); |
| 290 if (uint32_t* indexPtr = fFlattenableDict.find(key)) { |
| 291 // We will write the index as a 32-bit int. We want the first byte |
| 292 // that we send to be zero - this will act as a sentinel that we |
| 293 // have an index (not a string). This means that we will send the |
| 294 // the index shifted left by 8. The remaining 24-bits should be |
| 295 // plenty to store the index. Note that this strategy depends on |
| 296 // being little endian. |
| 297 SkASSERT(0 == *indexPtr >> 24); |
| 298 this->write32(*indexPtr << 8); |
| 299 } else { |
| 300 // Otherwise write the string. Clients should not use the empty |
| 301 // string as a name, or we will have a problem. |
| 302 SkASSERT(strcmp("", name)); |
| 303 this->writeString(name); |
| 304 |
| 305 // Add key to dictionary. |
| 306 fFlattenableDict.set(key, fFlattenableDict.count() + 1); |
| 307 } |
| 302 } | 308 } |
| 303 | 309 |
| 304 // make room for the size of the flattened object | 310 // make room for the size of the flattened object |
| 305 (void)fWriter.reserve(sizeof(uint32_t)); | 311 (void)fWriter.reserve(sizeof(uint32_t)); |
| 306 // record the current size, so we can subtract after the object writes. | 312 // record the current size, so we can subtract after the object writes. |
| 307 size_t offset = fWriter.bytesWritten(); | 313 size_t offset = fWriter.bytesWritten(); |
| 308 // now flatten the object | 314 // now flatten the object |
| 309 flattenable->flatten(*this); | 315 flattenable->flatten(*this); |
| 310 size_t objSize = fWriter.bytesWritten() - offset; | 316 size_t objSize = fWriter.bytesWritten() - offset; |
| 311 // record the obj's size | 317 // record the obj's size |
| 312 fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); | 318 fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize)); |
| 313 } | 319 } |
| OLD | NEW |