blob: 5c3bfefe2c167f3a6973df5885b324fbd39b5586 [file] [log] [blame]
reed@google.com8c5c7a92013-04-19 20:16:01 +00001/*
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#include "SkFlattenableBuffers.h"
11
12SK_DEFINE_INST_COUNT(SkDataTable)
13
14SkDataTable::SkDataTable(int count, SkData* data)
15 : fCount(count)
16 , fData(data) {}
17
18SkDataTable::~SkDataTable() {
19 fData->unref();
20}
21
22struct ElemHead {
23 const void* fPtr;
24 uintptr_t fSize;
25
26 static const ElemHead* Get(SkData* data) {
27 return (const ElemHead*)(data->data());
28 }
29};
30
31size_t SkDataTable::atSize(int index) const {
32 SkASSERT((unsigned)index < (unsigned)fCount);
33 return ElemHead::Get(fData)[index].fSize;
34}
35
36const void* SkDataTable::atData(int index, size_t* size) const {
37 SkASSERT((unsigned)index < (unsigned)fCount);
38 const ElemHead& head = ElemHead::Get(fData)[index];
39 if (size) {
40 *size = head.fSize;
41 }
42 return head.fPtr;
43}
44
45SkDataTable::SkDataTable(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
46 fCount = buffer.read32();
47 fData = buffer.readFlattenableT<SkData>();
48}
49
50void SkDataTable::flatten(SkFlattenableWriteBuffer& buffer) const {
51 this->INHERITED::flatten(buffer);
52 buffer.write32(fCount);
53 buffer.writeFlattenable(fData);
54}
55
reed@google.com3cceb9f2013-04-19 20:22:39 +000056///////////////////////////////////////////////////////////////////////////////
57
58SkDataTable* SkDataTable::NewEmpty() {
59 static SkDataTable* gEmpty;
60 if (NULL == gEmpty) {
61 gEmpty = SkNEW_ARGS(SkDataTable, (0, SkData::NewEmpty()));
62 }
63 gEmpty->ref();
64 return gEmpty;
65}
66
reed@google.com8c5c7a92013-04-19 20:16:01 +000067SkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs,
68 const size_t sizes[], int count) {
69 if (count < 0) {
70 count = 0;
71 }
72
73 size_t headerSize = count * sizeof(ElemHead);
74 size_t dataSize = 0;
75 for (int i = 0; i < count; ++i) {
76 dataSize += sizes[i];
77 }
78
79 size_t bufferSize = headerSize + dataSize;
80 void* buffer = sk_malloc_throw(bufferSize);
81
82 ElemHead* headerCurr = (ElemHead*)buffer;
83 char* dataCurr = (char*)buffer + headerSize;
84 for (int i = 0; i < count; ++i) {
85 headerCurr[i].fPtr = dataCurr;
86 headerCurr[i].fSize = sizes[i];
87 memcpy(dataCurr, ptrs[i], sizes[i]);
88 dataCurr += sizes[i];
89 }
90
91 return SkNEW_ARGS(SkDataTable, (count,
92 SkData::NewFromMalloc(buffer, bufferSize)));
93}
94
95SkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize,
96 int count) {
97 if (count < 0) {
98 count = 0;
99 }
skia.committer@gmail.com64b682c2013-04-20 07:01:07 +0000100
reed@google.com8c5c7a92013-04-19 20:16:01 +0000101 size_t headerSize = count * sizeof(ElemHead);
102 size_t dataSize = count * elemSize;
skia.committer@gmail.com64b682c2013-04-20 07:01:07 +0000103
reed@google.com8c5c7a92013-04-19 20:16:01 +0000104 size_t bufferSize = headerSize + dataSize;
105 void* buffer = sk_malloc_throw(bufferSize);
skia.committer@gmail.com64b682c2013-04-20 07:01:07 +0000106
reed@google.com8c5c7a92013-04-19 20:16:01 +0000107 ElemHead* headerCurr = (ElemHead*)buffer;
108 char* dataCurr = (char*)buffer + headerSize;
109 for (int i = 0; i < count; ++i) {
110 headerCurr[i].fPtr = dataCurr;
111 headerCurr[i].fSize = elemSize;
112 dataCurr += elemSize;
113 }
114 memcpy((char*)buffer + headerSize, array, dataSize);
skia.committer@gmail.com64b682c2013-04-20 07:01:07 +0000115
reed@google.com8c5c7a92013-04-19 20:16:01 +0000116 return SkNEW_ARGS(SkDataTable, (count,
117 SkData::NewFromMalloc(buffer, bufferSize)));
118}
119
120///////////////////////////////////////////////////////////////////////////////
121
122SkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize)
123 : fHeap(minChunkSize) {}
124
125SkDataTableBuilder::~SkDataTableBuilder() {}
126
127void SkDataTableBuilder::reset() {
128 fSizes.reset();
129 fPtrs.reset();
130 fHeap.reset();
131}
132
133void SkDataTableBuilder::append(const void* src, size_t size) {
134 void* dst = fHeap.alloc(size, SkChunkAlloc::kThrow_AllocFailType);
135 memcpy(dst, src, size);
136
137 *fSizes.append() = size;
138 *fPtrs.append() = dst;
139}
140
141SkDataTable* SkDataTableBuilder::createDataTable() {
142 SkASSERT(fSizes.count() == fPtrs.count());
143 return SkDataTable::NewCopyArrays(fPtrs.begin(), fSizes.begin(),
144 fSizes.count());
145}