/*
|
* 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> 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));
|
}
|