| /* | |
| * 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 "include/core/SkData.h" | |
| #include "include/core/SkDataTable.h" | |
| #include "include/private/base/SkMalloc.h" | |
| #include "include/private/base/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> SkDataTable::MakeEmpty() { | |
| static SkDataTable* singleton; | |
| static SkOnce once; | |
| once([]{ singleton = new SkDataTable(); }); | |
| return sk_ref_sp(singleton); | |
| } | |
| sk_sp<SkDataTable> 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<SkDataTable>(new SkDataTable(dir, count, malloc_freeproc, buffer)); | |
| } | |
| sk_sp<SkDataTable> 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<SkDataTable>(new SkDataTable(buffer, elemSize, count, malloc_freeproc, buffer)); | |
| } | |
| sk_sp<SkDataTable> SkDataTable::MakeArrayProc(const void* array, size_t elemSize, int count, | |
| FreeProc proc, void* ctx) { | |
| if (count <= 0) { | |
| return SkDataTable::MakeEmpty(); | |
| } | |
| return sk_sp<SkDataTable>(new SkDataTable(array, elemSize, count, proc, ctx)); | |
| } |