xref: /third_party/skia/src/core/SkDataTable.cpp (revision cb93a386)
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
12static void malloc_freeproc(void* context) {
13    sk_free(context);
14}
15
16// Makes empty table
17SkDataTable::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
25SkDataTable::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
36SkDataTable::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
46SkDataTable::~SkDataTable() {
47    if (fFreeProc) {
48        fFreeProc(fFreeProcContext);
49    }
50}
51
52size_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
62const 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
80sk_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
87sk_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
113sk_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
125sk_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