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