/* * 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" #include "SkOnce.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 = nullptr; fFreeProc = nullptr; fFreeProcContext = nullptr; } 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; } } /////////////////////////////////////////////////////////////////////////////// sk_sp SkDataTable::MakeEmpty() { static SkDataTable* singleton; static SkOnce once; once([]{ singleton = new SkDataTable(); }); return sk_ref_sp(singleton); } sk_sp SkDataTable::MakeCopyArrays(const void * const * ptrs, const size_t sizes[], int count) { if (count <= 0) { return SkDataTable::MakeEmpty(); } 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 sk_sp(new SkDataTable(dir, count, malloc_freeproc, buffer)); } sk_sp SkDataTable::MakeCopyArray(const void* array, size_t elemSize, int count) { if (count <= 0) { return SkDataTable::MakeEmpty(); } size_t bufferSize = elemSize * count; void* buffer = sk_malloc_throw(bufferSize); memcpy(buffer, array, bufferSize); return sk_sp(new SkDataTable(buffer, elemSize, count, malloc_freeproc, buffer)); } sk_sp SkDataTable::MakeArrayProc(const void* array, size_t elemSize, int count, FreeProc proc, void* ctx) { if (count <= 0) { return SkDataTable::MakeEmpty(); } return sk_sp(new SkDataTable(array, elemSize, count, proc, ctx)); }