blob: 9c4303347a7f542541e1bcfb7aa984dce0c85481 [file] [log] [blame]
/*
* 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;
}