/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkOrderedWriteBuffer.h" #include "SkTypeface.h" SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize) : fWriter(minSize) { } SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize) : fWriter(minSize, storage, storageSize) { } void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { /* * If we have a factoryset, then the first 32bits tell us... * 0: failure to write the flattenable * <0: we store the negative of the (1-based) index * >0: the length of the name * If we don't have a factoryset, then the first "ptr" is either the * factory, or null for failure. * * The distinction is important, since 0-index is 32bits (always), but a * 0-functionptr might be 32 or 64 bits. */ SkFlattenable::Factory factory = NULL; if (flattenable) { factory = flattenable->getFactory(); } if (NULL == factory) { if (fFactorySet) { this->write32(0); } else { this->writeFunctionPtr(NULL); } return; } /* * We can write 1 of 3 versions of the flattenable: * 1. function-ptr : this is the fastest for the reader, but assumes that * the writer and reader are in the same process. * 2. index into fFactorySet : This is assumes the writer will later * resolve the function-ptrs into strings for its reader. SkPicture * does exactly this, by writing a table of names (matching the indices) * up front in its serialized form. * 3. names : Reuse fFactorySet to store indices, but only after we've * written the name the first time. SkGPipe uses this technique, as it * doesn't require the reader to be told to know the table of names * up front. */ if (fFactorySet) { if (this->inlineFactoryNames()) { int index = fFactorySet->find(factory); if (index) { // we write the negative of the index, to distinguish it from // the length of a string this->write32(-index); } else { const char* name = SkFlattenable::FactoryToName(factory); if (NULL == name) { this->write32(0); return; } this->writeString(name); index = fFactorySet->add(factory); } } else { // we write the negative of the index, to distinguish it from // the length of a string this->write32(-(int)fFactorySet->add(factory)); } } else { this->writeFunctionPtr((void*)factory); } // make room for the size of the flatttened object (void)this->reserve(sizeof(uint32_t)); // record the current size, so we can subtract after the object writes. uint32_t offset = this->size(); // now flatten the object flattenObject(flattenable, *this); uint32_t objSize = this->size() - offset; // record the obj's size *fWriter.peek32(offset - sizeof(uint32_t)) = objSize; } void SkOrderedWriteBuffer::writeFunctionPtr(void* proc) { SkASSERT(!this->isCrossProcess()); *(void**)this->reserve(sizeof(void*)) = proc; }