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 "include/core/SkData.h" |
9 | #include "include/core/SkDataTable.h" |
10 | #include "include/private/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 | |