diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/core/SkDataTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/core/SkDataTable.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,188 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkData.h" +#include "SkDataTable.h" + +static void malloc_freeproc(void* context) { + sk_free(context); +} + +// 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; +} + +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; +} + +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); + + if (fElemSize) { + return fElemSize; + } else { + return fU.fDir[index].fSize; + } +} + +const void* SkDataTable::at(int index, size_t* size) const { + SkASSERT((unsigned)index < (unsigned)fCount); + + if (fElemSize) { + if (size) { + *size = fElemSize; + } + return fU.fElems + index * fElemSize; + } else { + if (size) { + *size = fU.fDir[index].fSize; + } + return fU.fDir[index].fPtr; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +SkDataTable* SkDataTable::NewEmpty() { + static SkDataTable* gEmpty; + if (NULL == gEmpty) { + gEmpty = SkNEW(SkDataTable); + } + gEmpty->ref(); + return gEmpty; +} + +SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs, + const size_t sizes[], int count) { + if (count <= 0) { + return SkDataTable::NewEmpty(); + } + + size_t dataSize = 0; + for (int i = 0; i < count; ++i) { + dataSize += sizes[i]; + } + + size_t bufferSize = count * sizeof(Dir) + dataSize; + void* buffer = sk_malloc_throw(bufferSize); + + Dir* dir = (Dir*)buffer; + char* elem = (char*)(dir + count); + for (int i = 0; i < count; ++i) { + dir[i].fPtr = elem; + dir[i].fSize = sizes[i]; + memcpy(elem, ptrs[i], sizes[i]); + elem += sizes[i]; + } + + return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer)); +} + +SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize, + int count) { + if (count <= 0) { + return SkDataTable::NewEmpty(); + } + + size_t bufferSize = elemSize * count; + void* buffer = sk_malloc_throw(bufferSize); + memcpy(buffer, array, bufferSize); + + return SkNEW_ARGS(SkDataTable, + (buffer, elemSize, count, malloc_freeproc, buffer)); +} + +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(NULL) + , fMinChunkSize(minChunkSize) {} + +SkDataTableBuilder::~SkDataTableBuilder() { this->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) { + if (NULL == fHeap) { + fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize)); + } + + void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType); + memcpy(dst, src, size); + + SkDataTable::Dir* dir = fDir.append(); + dir->fPtr = dst; + dir->fSize = size; +} + +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; +}