• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
malloc_freeproc(void * context)11 static void malloc_freeproc(void* context) {
12     sk_free(context);
13 }
14 
15 // Makes empty table
SkDataTable()16 SkDataTable::SkDataTable() {
17     fCount = 0;
18     fElemSize = 0;   // 0 signals that we use fDir instead of fElems
19     fU.fDir = NULL;
20     fFreeProc = NULL;
21     fFreeProcContext = NULL;
22 }
23 
SkDataTable(const void * array,size_t elemSize,int count,FreeProc proc,void * context)24 SkDataTable::SkDataTable(const void* array, size_t elemSize, int count,
25                          FreeProc proc, void* context) {
26     SkASSERT(count > 0);
27 
28     fCount = count;
29     fElemSize = elemSize;   // non-zero signals we use fElems instead of fDir
30     fU.fElems = (const char*)array;
31     fFreeProc = proc;
32     fFreeProcContext = context;
33 }
34 
SkDataTable(const Dir * dir,int count,FreeProc proc,void * ctx)35 SkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) {
36     SkASSERT(count > 0);
37 
38     fCount = count;
39     fElemSize = 0;  // 0 signals that we use fDir instead of fElems
40     fU.fDir = dir;
41     fFreeProc = proc;
42     fFreeProcContext = ctx;
43 }
44 
~SkDataTable()45 SkDataTable::~SkDataTable() {
46     if (fFreeProc) {
47         fFreeProc(fFreeProcContext);
48     }
49 }
50 
atSize(int index) const51 size_t SkDataTable::atSize(int index) const {
52     SkASSERT((unsigned)index < (unsigned)fCount);
53 
54     if (fElemSize) {
55         return fElemSize;
56     } else {
57         return fU.fDir[index].fSize;
58     }
59 }
60 
at(int index,size_t * size) const61 const void* SkDataTable::at(int index, size_t* size) const {
62     SkASSERT((unsigned)index < (unsigned)fCount);
63 
64     if (fElemSize) {
65         if (size) {
66             *size = fElemSize;
67         }
68         return fU.fElems + index * fElemSize;
69     } else {
70         if (size) {
71             *size = fU.fDir[index].fSize;
72         }
73         return fU.fDir[index].fPtr;
74     }
75 }
76 
77 ///////////////////////////////////////////////////////////////////////////////
78 
NewEmpty()79 SkDataTable* SkDataTable::NewEmpty() {
80     static SkDataTable* gEmpty;
81     if (NULL == gEmpty) {
82         gEmpty = SkNEW(SkDataTable);
83     }
84     gEmpty->ref();
85     return gEmpty;
86 }
87 
NewCopyArrays(const void * const * ptrs,const size_t sizes[],int count)88 SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs,
89                                         const size_t sizes[], int count) {
90     if (count <= 0) {
91         return SkDataTable::NewEmpty();
92     }
93 
94     size_t dataSize = 0;
95     for (int i = 0; i < count; ++i) {
96         dataSize += sizes[i];
97     }
98 
99     size_t bufferSize = count * sizeof(Dir) + dataSize;
100     void* buffer = sk_malloc_throw(bufferSize);
101 
102     Dir* dir = (Dir*)buffer;
103     char* elem = (char*)(dir + count);
104     for (int i = 0; i < count; ++i) {
105         dir[i].fPtr = elem;
106         dir[i].fSize = sizes[i];
107         memcpy(elem, ptrs[i], sizes[i]);
108         elem += sizes[i];
109     }
110 
111     return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer));
112 }
113 
NewCopyArray(const void * array,size_t elemSize,int count)114 SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize,
115                                        int count) {
116     if (count <= 0) {
117         return SkDataTable::NewEmpty();
118     }
119 
120     size_t bufferSize = elemSize * count;
121     void* buffer = sk_malloc_throw(bufferSize);
122     memcpy(buffer, array, bufferSize);
123 
124     return SkNEW_ARGS(SkDataTable,
125                       (buffer, elemSize, count, malloc_freeproc, buffer));
126 }
127 
NewArrayProc(const void * array,size_t elemSize,int count,FreeProc proc,void * ctx)128 SkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize,
129                                        int count, FreeProc proc, void* ctx) {
130     if (count <= 0) {
131         return SkDataTable::NewEmpty();
132     }
133     return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx));
134 }
135 
136 ///////////////////////////////////////////////////////////////////////////////
137 
chunkalloc_freeproc(void * context)138 static void chunkalloc_freeproc(void* context) {
139     SkDELETE((SkChunkAlloc*)context);
140 }
141 
SkDataTableBuilder(size_t minChunkSize)142 SkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize)
143     : fHeap(NULL)
144     , fMinChunkSize(minChunkSize) {}
145 
~SkDataTableBuilder()146 SkDataTableBuilder::~SkDataTableBuilder() { this->reset(); }
147 
reset(size_t minChunkSize)148 void SkDataTableBuilder::reset(size_t minChunkSize) {
149     fMinChunkSize = minChunkSize;
150     fDir.reset();
151     if (fHeap) {
152         SkDELETE(fHeap);
153         fHeap = NULL;
154     }
155 }
156 
append(const void * src,size_t size)157 void SkDataTableBuilder::append(const void* src, size_t size) {
158     if (NULL == fHeap) {
159         fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize));
160     }
161 
162     void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType);
163     memcpy(dst, src, size);
164 
165     SkDataTable::Dir* dir = fDir.append();
166     dir->fPtr = dst;
167     dir->fSize = size;
168 }
169 
detachDataTable()170 SkDataTable* SkDataTableBuilder::detachDataTable() {
171     const int count = fDir.count();
172     if (0 == count) {
173         return SkDataTable::NewEmpty();
174     }
175 
176     // Copy the dir into the heap;
177     void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir),
178                              SkChunkAlloc::kThrow_AllocFailType);
179     memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir));
180 
181     SkDataTable* table = SkNEW_ARGS(SkDataTable,
182                                     ((SkDataTable::Dir*)dir, count,
183                                      chunkalloc_freeproc, fHeap));
184     // we have to detach our fHeap, since we are giving that to the table
185     fHeap = NULL;
186     fDir.reset();
187     return table;
188 }
189