diff options
Diffstat (limited to 'src/core/SkDataTable.cpp')
-rw-r--r-- | src/core/SkDataTable.cpp | 230 |
1 files changed, 168 insertions, 62 deletions
diff --git a/src/core/SkDataTable.cpp b/src/core/SkDataTable.cpp index 5c3bfefe2c..e5dbd8472b 100644 --- a/src/core/SkDataTable.cpp +++ b/src/core/SkDataTable.cpp @@ -11,46 +11,129 @@ SK_DEFINE_INST_COUNT(SkDataTable) -SkDataTable::SkDataTable(int count, SkData* data) - : fCount(count) - , fData(data) {} +static void malloc_freeproc(void* context) { + sk_free(context); +} -SkDataTable::~SkDataTable() { - fData->unref(); +// Makes empty table +SkDataTable::SkDataTable() { + fCount = 0; + fElemSize = 0; // 0 signals that we use fDir instead of fElems + fU.fDir = NULL; + fFreeProc = NULL; + fFreeProcContext = NULL; } -struct ElemHead { - const void* fPtr; - uintptr_t fSize; +SkDataTable::SkDataTable(const void* array, size_t elemSize, int count, + FreeProc proc, void* context) { + SkASSERT(count > 0); + + fCount = count; + fElemSize = elemSize; // non-zero signals we use fElems instead of fDir + fU.fElems = (const char*)array; + fFreeProc = proc; + fFreeProcContext = context; +} - static const ElemHead* Get(SkData* data) { - return (const ElemHead*)(data->data()); +SkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) { + SkASSERT(count > 0); + + fCount = count; + fElemSize = 0; // 0 signals that we use fDir instead of fElems + fU.fDir = dir; + fFreeProc = proc; + fFreeProcContext = ctx; +} + +SkDataTable::~SkDataTable() { + if (fFreeProc) { + fFreeProc(fFreeProcContext); } -}; +} size_t SkDataTable::atSize(int index) const { SkASSERT((unsigned)index < (unsigned)fCount); - return ElemHead::Get(fData)[index].fSize; + + if (fElemSize) { + return fElemSize; + } else { + return fU.fDir[index].fSize; + } } -const void* SkDataTable::atData(int index, size_t* size) const { +const void* SkDataTable::at(int index, size_t* size) const { SkASSERT((unsigned)index < (unsigned)fCount); - const ElemHead& head = ElemHead::Get(fData)[index]; - if (size) { - *size = head.fSize; + + if (fElemSize) { + if (size) { + *size = fElemSize; + } + return fU.fElems + index * fElemSize; + } else { + if (size) { + *size = fU.fDir[index].fSize; + } + return fU.fDir[index].fPtr; } - return head.fPtr; } SkDataTable::SkDataTable(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { + fElemSize = 0; + fU.fElems = NULL; + fFreeProc = NULL; + fFreeProcContext = NULL; + fCount = buffer.read32(); - fData = buffer.readFlattenableT<SkData>(); + if (fCount) { + fElemSize = buffer.read32(); + if (fElemSize) { + size_t size = buffer.getArrayCount(); + // size is the size of our elems data + SkASSERT(fCount * fElemSize == size); + void* addr = sk_malloc_throw(size); + if (buffer.readByteArray(addr) != size) { + sk_throw(); + } + fU.fElems = (const char*)addr; + fFreeProcContext = addr; + } else { + size_t dataSize = buffer.read32(); + + size_t allocSize = fCount * sizeof(Dir) + dataSize; + void* addr = sk_malloc_throw(allocSize); + Dir* dir = (Dir*)addr; + char* elem = (char*)(dir + fCount); + for (int i = 0; i < fCount; ++i) { + dir[i].fPtr = elem; + dir[i].fSize = buffer.readByteArray(elem); + elem += dir[i].fSize; + } + fU.fDir = dir; + fFreeProcContext = addr; + } + fFreeProc = malloc_freeproc; + } } void SkDataTable::flatten(SkFlattenableWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); + buffer.write32(fCount); - buffer.writeFlattenable(fData); + if (fCount) { + buffer.write32(fElemSize); + if (fElemSize) { + buffer.writeByteArray(fU.fElems, fCount * fElemSize); + } else { + size_t dataSize = 0; + for (int i = 0; i < fCount; ++i) { + dataSize += fU.fDir[i].fSize; + } + buffer.write32(dataSize); + for (int i = 0; i < fCount; ++i) { + buffer.writeByteArray(fU.fDir[i].fPtr, fU.fDir[i].fSize); + } + } + } } /////////////////////////////////////////////////////////////////////////////// @@ -58,7 +141,7 @@ void SkDataTable::flatten(SkFlattenableWriteBuffer& buffer) const { SkDataTable* SkDataTable::NewEmpty() { static SkDataTable* gEmpty; if (NULL == gEmpty) { - gEmpty = SkNEW_ARGS(SkDataTable, (0, SkData::NewEmpty())); + gEmpty = SkNEW(SkDataTable); } gEmpty->ref(); return gEmpty; @@ -66,80 +149,103 @@ SkDataTable* SkDataTable::NewEmpty() { SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs, const size_t sizes[], int count) { - if (count < 0) { - count = 0; + if (count <= 0) { + return SkDataTable::NewEmpty(); } - size_t headerSize = count * sizeof(ElemHead); size_t dataSize = 0; for (int i = 0; i < count; ++i) { dataSize += sizes[i]; } - size_t bufferSize = headerSize + dataSize; + size_t bufferSize = count * sizeof(Dir) + dataSize; void* buffer = sk_malloc_throw(bufferSize); - ElemHead* headerCurr = (ElemHead*)buffer; - char* dataCurr = (char*)buffer + headerSize; + Dir* dir = (Dir*)buffer; + char* elem = (char*)(dir + count); for (int i = 0; i < count; ++i) { - headerCurr[i].fPtr = dataCurr; - headerCurr[i].fSize = sizes[i]; - memcpy(dataCurr, ptrs[i], sizes[i]); - dataCurr += sizes[i]; + dir[i].fPtr = elem; + dir[i].fSize = sizes[i]; + memcpy(elem, ptrs[i], sizes[i]); + elem += sizes[i]; } - - return SkNEW_ARGS(SkDataTable, (count, - SkData::NewFromMalloc(buffer, bufferSize))); + + return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer)); } SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize, int count) { - if (count < 0) { - count = 0; + if (count <= 0) { + return SkDataTable::NewEmpty(); } - size_t headerSize = count * sizeof(ElemHead); - size_t dataSize = count * elemSize; - - size_t bufferSize = headerSize + dataSize; + size_t bufferSize = elemSize * count; void* buffer = sk_malloc_throw(bufferSize); + memcpy(buffer, array, bufferSize); - ElemHead* headerCurr = (ElemHead*)buffer; - char* dataCurr = (char*)buffer + headerSize; - for (int i = 0; i < count; ++i) { - headerCurr[i].fPtr = dataCurr; - headerCurr[i].fSize = elemSize; - dataCurr += elemSize; - } - memcpy((char*)buffer + headerSize, array, dataSize); + return SkNEW_ARGS(SkDataTable, + (buffer, elemSize, count, malloc_freeproc, buffer)); +} - return SkNEW_ARGS(SkDataTable, (count, - SkData::NewFromMalloc(buffer, bufferSize))); +SkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize, + int count, FreeProc proc, void* ctx) { + if (count <= 0) { + return SkDataTable::NewEmpty(); + } + return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx)); } /////////////////////////////////////////////////////////////////////////////// +static void chunkalloc_freeproc(void* context) { + SkDELETE((SkChunkAlloc*)context); +} + SkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize) - : fHeap(minChunkSize) {} + : fHeap(NULL) + , fMinChunkSize(minChunkSize) {} -SkDataTableBuilder::~SkDataTableBuilder() {} +SkDataTableBuilder::~SkDataTableBuilder() { this->reset(); } -void SkDataTableBuilder::reset() { - fSizes.reset(); - fPtrs.reset(); - fHeap.reset(); +void SkDataTableBuilder::reset(size_t minChunkSize) { + fMinChunkSize = minChunkSize; + fDir.reset(); + if (fHeap) { + SkDELETE(fHeap); + fHeap = NULL; + } } void SkDataTableBuilder::append(const void* src, size_t size) { - void* dst = fHeap.alloc(size, SkChunkAlloc::kThrow_AllocFailType); + if (NULL == fHeap) { + fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize)); + } + + void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType); memcpy(dst, src, size); - *fSizes.append() = size; - *fPtrs.append() = dst; + SkDataTable::Dir* dir = fDir.append(); + dir->fPtr = dst; + dir->fSize = size; } -SkDataTable* SkDataTableBuilder::createDataTable() { - SkASSERT(fSizes.count() == fPtrs.count()); - return SkDataTable::NewCopyArrays(fPtrs.begin(), fSizes.begin(), - fSizes.count()); +SkDataTable* SkDataTableBuilder::detachDataTable() { + const int count = fDir.count(); + if (0 == count) { + return SkDataTable::NewEmpty(); + } + + // Copy the dir into the heap; + void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir), + SkChunkAlloc::kThrow_AllocFailType); + memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir)); + + SkDataTable* table = SkNEW_ARGS(SkDataTable, + ((SkDataTable::Dir*)dir, count, + chunkalloc_freeproc, fHeap)); + // we have to detach our fHeap, since we are giving that to the table + fHeap = NULL; + fDir.reset(); + return table; } + |