1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkDataTable.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,188 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkData.h" 1.12 +#include "SkDataTable.h" 1.13 + 1.14 +static void malloc_freeproc(void* context) { 1.15 + sk_free(context); 1.16 +} 1.17 + 1.18 +// Makes empty table 1.19 +SkDataTable::SkDataTable() { 1.20 + fCount = 0; 1.21 + fElemSize = 0; // 0 signals that we use fDir instead of fElems 1.22 + fU.fDir = NULL; 1.23 + fFreeProc = NULL; 1.24 + fFreeProcContext = NULL; 1.25 +} 1.26 + 1.27 +SkDataTable::SkDataTable(const void* array, size_t elemSize, int count, 1.28 + FreeProc proc, void* context) { 1.29 + SkASSERT(count > 0); 1.30 + 1.31 + fCount = count; 1.32 + fElemSize = elemSize; // non-zero signals we use fElems instead of fDir 1.33 + fU.fElems = (const char*)array; 1.34 + fFreeProc = proc; 1.35 + fFreeProcContext = context; 1.36 +} 1.37 + 1.38 +SkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) { 1.39 + SkASSERT(count > 0); 1.40 + 1.41 + fCount = count; 1.42 + fElemSize = 0; // 0 signals that we use fDir instead of fElems 1.43 + fU.fDir = dir; 1.44 + fFreeProc = proc; 1.45 + fFreeProcContext = ctx; 1.46 +} 1.47 + 1.48 +SkDataTable::~SkDataTable() { 1.49 + if (fFreeProc) { 1.50 + fFreeProc(fFreeProcContext); 1.51 + } 1.52 +} 1.53 + 1.54 +size_t SkDataTable::atSize(int index) const { 1.55 + SkASSERT((unsigned)index < (unsigned)fCount); 1.56 + 1.57 + if (fElemSize) { 1.58 + return fElemSize; 1.59 + } else { 1.60 + return fU.fDir[index].fSize; 1.61 + } 1.62 +} 1.63 + 1.64 +const void* SkDataTable::at(int index, size_t* size) const { 1.65 + SkASSERT((unsigned)index < (unsigned)fCount); 1.66 + 1.67 + if (fElemSize) { 1.68 + if (size) { 1.69 + *size = fElemSize; 1.70 + } 1.71 + return fU.fElems + index * fElemSize; 1.72 + } else { 1.73 + if (size) { 1.74 + *size = fU.fDir[index].fSize; 1.75 + } 1.76 + return fU.fDir[index].fPtr; 1.77 + } 1.78 +} 1.79 + 1.80 +/////////////////////////////////////////////////////////////////////////////// 1.81 + 1.82 +SkDataTable* SkDataTable::NewEmpty() { 1.83 + static SkDataTable* gEmpty; 1.84 + if (NULL == gEmpty) { 1.85 + gEmpty = SkNEW(SkDataTable); 1.86 + } 1.87 + gEmpty->ref(); 1.88 + return gEmpty; 1.89 +} 1.90 + 1.91 +SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs, 1.92 + const size_t sizes[], int count) { 1.93 + if (count <= 0) { 1.94 + return SkDataTable::NewEmpty(); 1.95 + } 1.96 + 1.97 + size_t dataSize = 0; 1.98 + for (int i = 0; i < count; ++i) { 1.99 + dataSize += sizes[i]; 1.100 + } 1.101 + 1.102 + size_t bufferSize = count * sizeof(Dir) + dataSize; 1.103 + void* buffer = sk_malloc_throw(bufferSize); 1.104 + 1.105 + Dir* dir = (Dir*)buffer; 1.106 + char* elem = (char*)(dir + count); 1.107 + for (int i = 0; i < count; ++i) { 1.108 + dir[i].fPtr = elem; 1.109 + dir[i].fSize = sizes[i]; 1.110 + memcpy(elem, ptrs[i], sizes[i]); 1.111 + elem += sizes[i]; 1.112 + } 1.113 + 1.114 + return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer)); 1.115 +} 1.116 + 1.117 +SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize, 1.118 + int count) { 1.119 + if (count <= 0) { 1.120 + return SkDataTable::NewEmpty(); 1.121 + } 1.122 + 1.123 + size_t bufferSize = elemSize * count; 1.124 + void* buffer = sk_malloc_throw(bufferSize); 1.125 + memcpy(buffer, array, bufferSize); 1.126 + 1.127 + return SkNEW_ARGS(SkDataTable, 1.128 + (buffer, elemSize, count, malloc_freeproc, buffer)); 1.129 +} 1.130 + 1.131 +SkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize, 1.132 + int count, FreeProc proc, void* ctx) { 1.133 + if (count <= 0) { 1.134 + return SkDataTable::NewEmpty(); 1.135 + } 1.136 + return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx)); 1.137 +} 1.138 + 1.139 +/////////////////////////////////////////////////////////////////////////////// 1.140 + 1.141 +static void chunkalloc_freeproc(void* context) { 1.142 + SkDELETE((SkChunkAlloc*)context); 1.143 +} 1.144 + 1.145 +SkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize) 1.146 + : fHeap(NULL) 1.147 + , fMinChunkSize(minChunkSize) {} 1.148 + 1.149 +SkDataTableBuilder::~SkDataTableBuilder() { this->reset(); } 1.150 + 1.151 +void SkDataTableBuilder::reset(size_t minChunkSize) { 1.152 + fMinChunkSize = minChunkSize; 1.153 + fDir.reset(); 1.154 + if (fHeap) { 1.155 + SkDELETE(fHeap); 1.156 + fHeap = NULL; 1.157 + } 1.158 +} 1.159 + 1.160 +void SkDataTableBuilder::append(const void* src, size_t size) { 1.161 + if (NULL == fHeap) { 1.162 + fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize)); 1.163 + } 1.164 + 1.165 + void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType); 1.166 + memcpy(dst, src, size); 1.167 + 1.168 + SkDataTable::Dir* dir = fDir.append(); 1.169 + dir->fPtr = dst; 1.170 + dir->fSize = size; 1.171 +} 1.172 + 1.173 +SkDataTable* SkDataTableBuilder::detachDataTable() { 1.174 + const int count = fDir.count(); 1.175 + if (0 == count) { 1.176 + return SkDataTable::NewEmpty(); 1.177 + } 1.178 + 1.179 + // Copy the dir into the heap; 1.180 + void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir), 1.181 + SkChunkAlloc::kThrow_AllocFailType); 1.182 + memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir)); 1.183 + 1.184 + SkDataTable* table = SkNEW_ARGS(SkDataTable, 1.185 + ((SkDataTable::Dir*)dir, count, 1.186 + chunkalloc_freeproc, fHeap)); 1.187 + // we have to detach our fHeap, since we are giving that to the table 1.188 + fHeap = NULL; 1.189 + fDir.reset(); 1.190 + return table; 1.191 +}