SkDataTable.cpp revision c9f3b38f67893b22c3e02a6a934bc676e36c5cfc
18c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com/*
28c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * Copyright 2013 Google Inc.
38c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com *
48c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * Use of this source code is governed by a BSD-style license that can be
58c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com * found in the LICENSE file.
68c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com */
78c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
88c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkData.h"
98c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkDataTable.h"
108c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com#include "SkFlattenableBuffers.h"
118c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
128c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSK_DEFINE_INST_COUNT(SkDataTable)
138c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
14cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgstatic void malloc_freeproc(void* context) {
15cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    sk_free(context);
16cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org}
178c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
18cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org// Makes empty table
19cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable() {
20cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fCount = 0;
21cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fElemSize = 0;   // 0 signals that we use fDir instead of fElems
22cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fU.fDir = NULL;
23cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProc = NULL;
24cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProcContext = NULL;
258c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
268c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
27cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable(const void* array, size_t elemSize, int count,
28cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                         FreeProc proc, void* context) {
29cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkASSERT(count > 0);
30c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com
31cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fCount = count;
32cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fElemSize = elemSize;   // non-zero signals we use fElems instead of fDir
33cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fU.fElems = (const char*)array;
34cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProc = proc;
35cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProcContext = context;
36cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org}
378c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
38cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) {
39cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkASSERT(count > 0);
40c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com
41cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fCount = count;
42cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fElemSize = 0;  // 0 signals that we use fDir instead of fElems
43cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fU.fDir = dir;
44cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProc = proc;
45cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProcContext = ctx;
46cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org}
47cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
48cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::~SkDataTable() {
49cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (fFreeProc) {
50cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        fFreeProc(fFreeProcContext);
518c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
52cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org}
538c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
548c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comsize_t SkDataTable::atSize(int index) const {
558c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    SkASSERT((unsigned)index < (unsigned)fCount);
56cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
57cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (fElemSize) {
58cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return fElemSize;
59cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    } else {
60cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return fU.fDir[index].fSize;
61cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
628c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
638c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
64cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgconst void* SkDataTable::at(int index, size_t* size) const {
658c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    SkASSERT((unsigned)index < (unsigned)fCount);
66cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
67cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (fElemSize) {
68cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        if (size) {
69cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            *size = fElemSize;
70cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        }
71cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return fU.fElems + index * fElemSize;
72cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    } else {
73cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        if (size) {
74cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            *size = fU.fDir[index].fSize;
75cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        }
76cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return fU.fDir[index].fPtr;
778c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
788c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
798c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
808c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTable::SkDataTable(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
81cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fElemSize = 0;
82cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fU.fElems = NULL;
83cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProc = NULL;
84cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fFreeProcContext = NULL;
85cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
868c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    fCount = buffer.read32();
87cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (fCount) {
88cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        fElemSize = buffer.read32();
89cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        if (fElemSize) {
90cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            size_t size = buffer.getArrayCount();
91cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            // size is the size of our elems data
92cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            SkASSERT(fCount * fElemSize == size);
93cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            void* addr = sk_malloc_throw(size);
94cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            if (buffer.readByteArray(addr) != size) {
95cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                sk_throw();
96cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            }
97cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            fU.fElems = (const char*)addr;
98cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            fFreeProcContext = addr;
99cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        } else {
100cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            size_t dataSize = buffer.read32();
101cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
102cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            size_t allocSize = fCount * sizeof(Dir) + dataSize;
103cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            void* addr = sk_malloc_throw(allocSize);
104cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            Dir* dir = (Dir*)addr;
105cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            char* elem = (char*)(dir + fCount);
106cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            for (int i = 0; i < fCount; ++i) {
107cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                dir[i].fPtr = elem;
108cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                dir[i].fSize = buffer.readByteArray(elem);
109cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                elem += dir[i].fSize;
110cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            }
111cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            fU.fDir = dir;
112cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            fFreeProcContext = addr;
113cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        }
114cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        fFreeProc = malloc_freeproc;
115cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
1168c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
1178c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1188c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comvoid SkDataTable::flatten(SkFlattenableWriteBuffer& buffer) const {
1198c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    this->INHERITED::flatten(buffer);
120cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
1218c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    buffer.write32(fCount);
122cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (fCount) {
123cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        buffer.write32(fElemSize);
124cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        if (fElemSize) {
125cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            buffer.writeByteArray(fU.fElems, fCount * fElemSize);
126cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        } else {
127cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            size_t dataSize = 0;
128cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            for (int i = 0; i < fCount; ++i) {
129cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                dataSize += fU.fDir[i].fSize;
130cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            }
131cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            buffer.write32(dataSize);
132cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            for (int i = 0; i < fCount; ++i) {
133cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                buffer.writeByteArray(fU.fDir[i].fPtr, fU.fDir[i].fSize);
134cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org            }
135cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        }
136cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
1378c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
1388c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1393cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com///////////////////////////////////////////////////////////////////////////////
1403cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com
1413cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.comSkDataTable* SkDataTable::NewEmpty() {
1423cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com    static SkDataTable* gEmpty;
1433cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com    if (NULL == gEmpty) {
144cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        gEmpty = SkNEW(SkDataTable);
1453cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com    }
1463cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com    gEmpty->ref();
1473cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com    return gEmpty;
1483cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com}
1493cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com
1508c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTable* SkDataTable::NewCopyArrays(const void * const * ptrs,
1518c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com                                        const size_t sizes[], int count) {
152cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (count <= 0) {
153cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return SkDataTable::NewEmpty();
1548c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
1558c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1568c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    size_t dataSize = 0;
1578c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    for (int i = 0; i < count; ++i) {
1588c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com        dataSize += sizes[i];
1598c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
1608c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
161cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    size_t bufferSize = count * sizeof(Dir) + dataSize;
1628c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    void* buffer = sk_malloc_throw(bufferSize);
1638c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
164cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    Dir* dir = (Dir*)buffer;
165cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    char* elem = (char*)(dir + count);
1668c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    for (int i = 0; i < count; ++i) {
167cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        dir[i].fPtr = elem;
168cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        dir[i].fSize = sizes[i];
169cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        memcpy(elem, ptrs[i], sizes[i]);
170cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        elem += sizes[i];
1718c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
172c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com
173cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    return SkNEW_ARGS(SkDataTable, (dir, count, malloc_freeproc, buffer));
1748c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
1758c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1768c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTable* SkDataTable::NewCopyArray(const void* array, size_t elemSize,
1778c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com                                       int count) {
178cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (count <= 0) {
179cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return SkDataTable::NewEmpty();
1808c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    }
18164b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com
182cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    size_t bufferSize = elemSize * count;
1838c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    void* buffer = sk_malloc_throw(bufferSize);
184cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    memcpy(buffer, array, bufferSize);
18564b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com
186cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    return SkNEW_ARGS(SkDataTable,
187cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                      (buffer, elemSize, count, malloc_freeproc, buffer));
188cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org}
18964b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com
190cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable* SkDataTable::NewArrayProc(const void* array, size_t elemSize,
191cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                                       int count, FreeProc proc, void* ctx) {
192cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (count <= 0) {
193cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return SkDataTable::NewEmpty();
194cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
195cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    return SkNEW_ARGS(SkDataTable, (array, elemSize, count, proc, ctx));
1968c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
1978c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
1988c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com///////////////////////////////////////////////////////////////////////////////
1998c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
200cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgstatic void chunkalloc_freeproc(void* context) {
201cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDELETE((SkChunkAlloc*)context);
202cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org}
203cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
2048c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comSkDataTableBuilder::SkDataTableBuilder(size_t minChunkSize)
205cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    : fHeap(NULL)
206cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    , fMinChunkSize(minChunkSize) {}
2078c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
208cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTableBuilder::~SkDataTableBuilder() { this->reset(); }
2098c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
210cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgvoid SkDataTableBuilder::reset(size_t minChunkSize) {
211cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fMinChunkSize = minChunkSize;
212cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fDir.reset();
213cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (fHeap) {
214cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        SkDELETE(fHeap);
215cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        fHeap = NULL;
216cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
2178c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
2188c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
2198c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comvoid SkDataTableBuilder::append(const void* src, size_t size) {
220cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (NULL == fHeap) {
221cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        fHeap = SkNEW_ARGS(SkChunkAlloc, (fMinChunkSize));
222cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
223cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
224cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    void* dst = fHeap->alloc(size, SkChunkAlloc::kThrow_AllocFailType);
2258c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com    memcpy(dst, src, size);
2268c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
227cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDataTable::Dir* dir = fDir.append();
228cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    dir->fPtr = dst;
229cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    dir->fSize = size;
2308c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
2318c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com
232cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable* SkDataTableBuilder::detachDataTable() {
233cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    const int count = fDir.count();
234cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    if (0 == count) {
235cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org        return SkDataTable::NewEmpty();
236cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    }
237cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
238cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    // Copy the dir into the heap;
239cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    void* dir = fHeap->alloc(count * sizeof(SkDataTable::Dir),
240cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                             SkChunkAlloc::kThrow_AllocFailType);
241cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    memcpy(dir, fDir.begin(), count * sizeof(SkDataTable::Dir));
242cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org
243cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    SkDataTable* table = SkNEW_ARGS(SkDataTable,
244cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                                    ((SkDataTable::Dir*)dir, count,
245cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org                                     chunkalloc_freeproc, fHeap));
246cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    // we have to detach our fHeap, since we are giving that to the table
247cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fHeap = NULL;
248cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    fDir.reset();
249cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org    return table;
2508c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com}
251