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

Side by Side Diff: src/core/SkWriteBuffer.cpp

Issue 1858323002: Enable flattening/unflattening with custom unflatten procs (Closed) Base URL: https://skia.googlesource.com/skia.git@flattenable
Patch Set: Avoid duping strings Created 4 years, 8 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
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698