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