1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkData.h" 9cb93a386Sopenharmony_ci#include "include/core/SkDataTable.h" 10cb93a386Sopenharmony_ci#include "include/private/SkOnce.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_cistatic void malloc_freeproc(void* context) { 13cb93a386Sopenharmony_ci sk_free(context); 14cb93a386Sopenharmony_ci} 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci// Makes empty table 17cb93a386Sopenharmony_ciSkDataTable::SkDataTable() { 18cb93a386Sopenharmony_ci fCount = 0; 19cb93a386Sopenharmony_ci fElemSize = 0; // 0 signals that we use fDir instead of fElems 20cb93a386Sopenharmony_ci fU.fDir = nullptr; 21cb93a386Sopenharmony_ci fFreeProc = nullptr; 22cb93a386Sopenharmony_ci fFreeProcContext = nullptr; 23cb93a386Sopenharmony_ci} 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ciSkDataTable::SkDataTable(const void* array, size_t elemSize, int count, 26cb93a386Sopenharmony_ci FreeProc proc, void* context) { 27cb93a386Sopenharmony_ci SkASSERT(count > 0); 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci fCount = count; 30cb93a386Sopenharmony_ci fElemSize = elemSize; // non-zero signals we use fElems instead of fDir 31cb93a386Sopenharmony_ci fU.fElems = (const char*)array; 32cb93a386Sopenharmony_ci fFreeProc = proc; 33cb93a386Sopenharmony_ci fFreeProcContext = context; 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciSkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) { 37cb93a386Sopenharmony_ci SkASSERT(count > 0); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci fCount = count; 40cb93a386Sopenharmony_ci fElemSize = 0; // 0 signals that we use fDir instead of fElems 41cb93a386Sopenharmony_ci fU.fDir = dir; 42cb93a386Sopenharmony_ci fFreeProc = proc; 43cb93a386Sopenharmony_ci fFreeProcContext = ctx; 44cb93a386Sopenharmony_ci} 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciSkDataTable::~SkDataTable() { 47cb93a386Sopenharmony_ci if (fFreeProc) { 48cb93a386Sopenharmony_ci fFreeProc(fFreeProcContext); 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_cisize_t SkDataTable::atSize(int index) const { 53cb93a386Sopenharmony_ci SkASSERT((unsigned)index < (unsigned)fCount); 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci if (fElemSize) { 56cb93a386Sopenharmony_ci return fElemSize; 57cb93a386Sopenharmony_ci } else { 58cb93a386Sopenharmony_ci return fU.fDir[index].fSize; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci} 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ciconst void* SkDataTable::at(int index, size_t* size) const { 63cb93a386Sopenharmony_ci SkASSERT((unsigned)index < (unsigned)fCount); 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci if (fElemSize) { 66cb93a386Sopenharmony_ci if (size) { 67cb93a386Sopenharmony_ci *size = fElemSize; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci return fU.fElems + index * fElemSize; 70cb93a386Sopenharmony_ci } else { 71cb93a386Sopenharmony_ci if (size) { 72cb93a386Sopenharmony_ci *size = fU.fDir[index].fSize; 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci return fU.fDir[index].fPtr; 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci} 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_cisk_sp<SkDataTable> SkDataTable::MakeEmpty() { 81cb93a386Sopenharmony_ci static SkDataTable* singleton; 82cb93a386Sopenharmony_ci static SkOnce once; 83cb93a386Sopenharmony_ci once([]{ singleton = new SkDataTable(); }); 84cb93a386Sopenharmony_ci return sk_ref_sp(singleton); 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_cisk_sp<SkDataTable> SkDataTable::MakeCopyArrays(const void * const * ptrs, 88cb93a386Sopenharmony_ci const size_t sizes[], int count) { 89cb93a386Sopenharmony_ci if (count <= 0) { 90cb93a386Sopenharmony_ci return SkDataTable::MakeEmpty(); 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci size_t dataSize = 0; 94cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 95cb93a386Sopenharmony_ci dataSize += sizes[i]; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci size_t bufferSize = count * sizeof(Dir) + dataSize; 99cb93a386Sopenharmony_ci void* buffer = sk_malloc_throw(bufferSize); 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci Dir* dir = (Dir*)buffer; 102cb93a386Sopenharmony_ci char* elem = (char*)(dir + count); 103cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 104cb93a386Sopenharmony_ci dir[i].fPtr = elem; 105cb93a386Sopenharmony_ci dir[i].fSize = sizes[i]; 106cb93a386Sopenharmony_ci memcpy(elem, ptrs[i], sizes[i]); 107cb93a386Sopenharmony_ci elem += sizes[i]; 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci return sk_sp<SkDataTable>(new SkDataTable(dir, count, malloc_freeproc, buffer)); 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_cisk_sp<SkDataTable> SkDataTable::MakeCopyArray(const void* array, size_t elemSize, int count) { 114cb93a386Sopenharmony_ci if (count <= 0) { 115cb93a386Sopenharmony_ci return SkDataTable::MakeEmpty(); 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci size_t bufferSize = elemSize * count; 119cb93a386Sopenharmony_ci void* buffer = sk_malloc_throw(bufferSize); 120cb93a386Sopenharmony_ci memcpy(buffer, array, bufferSize); 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci return sk_sp<SkDataTable>(new SkDataTable(buffer, elemSize, count, malloc_freeproc, buffer)); 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_cisk_sp<SkDataTable> SkDataTable::MakeArrayProc(const void* array, size_t elemSize, int count, 126cb93a386Sopenharmony_ci FreeProc proc, void* ctx) { 127cb93a386Sopenharmony_ci if (count <= 0) { 128cb93a386Sopenharmony_ci return SkDataTable::MakeEmpty(); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci return sk_sp<SkDataTable>(new SkDataTable(array, elemSize, count, proc, ctx)); 131cb93a386Sopenharmony_ci} 132