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" 10feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman#include "SkOnce.h" 118c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 12cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgstatic void malloc_freeproc(void* context) { 13cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org sk_free(context); 14cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 158c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 16cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org// Makes empty table 17cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable() { 18cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fCount = 0; 19cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fElemSize = 0; // 0 signals that we use fDir instead of fElems 2096fcdcc219d2a0d3579719b84b28bede76efba64halcanary fU.fDir = nullptr; 2196fcdcc219d2a0d3579719b84b28bede76efba64halcanary fFreeProc = nullptr; 2296fcdcc219d2a0d3579719b84b28bede76efba64halcanary fFreeProcContext = nullptr; 238c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 248c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 25cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable(const void* array, size_t elemSize, int count, 26cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org FreeProc proc, void* context) { 27cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkASSERT(count > 0); 28c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com 29cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fCount = count; 30cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fElemSize = elemSize; // non-zero signals we use fElems instead of fDir 31cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fU.fElems = (const char*)array; 32cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc = proc; 33cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProcContext = context; 34cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 358c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 36cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::SkDataTable(const Dir* dir, int count, FreeProc proc, void* ctx) { 37cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org SkASSERT(count > 0); 38c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com 39cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fCount = count; 40cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fElemSize = 0; // 0 signals that we use fDir instead of fElems 41cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fU.fDir = dir; 42cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc = proc; 43cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProcContext = ctx; 44cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 45cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 46cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgSkDataTable::~SkDataTable() { 47cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fFreeProc) { 48cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org fFreeProc(fFreeProcContext); 498c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 50cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 518c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 528c5c7a905b708f7c0a991ca7c872af645544afefreed@google.comsize_t SkDataTable::atSize(int index) const { 538c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 54cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 55cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fElemSize) { 56cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fElemSize; 57cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } else { 58cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fU.fDir[index].fSize; 59cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 608c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 618c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 62cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.orgconst void* SkDataTable::at(int index, size_t* size) const { 638c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 64cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org 65cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (fElemSize) { 66cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (size) { 67cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org *size = fElemSize; 68cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 69cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fU.fElems + index * fElemSize; 70cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } else { 71cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (size) { 72cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org *size = fU.fDir[index].fSize; 73cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 74cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org return fU.fDir[index].fPtr; 758c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 768c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 778c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 783cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com/////////////////////////////////////////////////////////////////////////////// 793cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com 80feb3c1a57faee39dc10ac904f6b215ba50e286b4bungemansk_sp<SkDataTable> SkDataTable::MakeEmpty() { 81feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman static SkDataTable* singleton; 82feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman static SkOnce once; 83feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman once([]{ singleton = new SkDataTable(); }); 84feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return sk_ref_sp(singleton); 853cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com} 863cceb9f400583be4ec70da526c23fe81b68dc6eereed@google.com 87feb3c1a57faee39dc10ac904f6b215ba50e286b4bungemansk_sp<SkDataTable> SkDataTable::MakeCopyArrays(const void * const * ptrs, 88feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman const size_t sizes[], int count) { 89cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (count <= 0) { 90feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return SkDataTable::MakeEmpty(); 918c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 928c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 938c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com size_t dataSize = 0; 948c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com for (int i = 0; i < count; ++i) { 958c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com dataSize += sizes[i]; 968c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 978c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 98cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org size_t bufferSize = count * sizeof(Dir) + dataSize; 998c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com void* buffer = sk_malloc_throw(bufferSize); 1008c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 101cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org Dir* dir = (Dir*)buffer; 102cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org char* elem = (char*)(dir + count); 1038c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com for (int i = 0; i < count; ++i) { 104cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org dir[i].fPtr = elem; 105cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org dir[i].fSize = sizes[i]; 106cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org memcpy(elem, ptrs[i], sizes[i]); 107cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org elem += sizes[i]; 1088c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 109c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com 110feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return sk_sp<SkDataTable>(new SkDataTable(dir, count, malloc_freeproc, buffer)); 1118c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 1128c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com 113feb3c1a57faee39dc10ac904f6b215ba50e286b4bungemansk_sp<SkDataTable> SkDataTable::MakeCopyArray(const void* array, size_t elemSize, int count) { 114cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (count <= 0) { 115feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return SkDataTable::MakeEmpty(); 1168c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com } 11764b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com 118cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org size_t bufferSize = elemSize * count; 1198c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com void* buffer = sk_malloc_throw(bufferSize); 120cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org memcpy(buffer, array, bufferSize); 12164b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com 122feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return sk_sp<SkDataTable>(new SkDataTable(buffer, elemSize, count, malloc_freeproc, buffer)); 123cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org} 12464b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com 125feb3c1a57faee39dc10ac904f6b215ba50e286b4bungemansk_sp<SkDataTable> SkDataTable::MakeArrayProc(const void* array, size_t elemSize, int count, 126feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman FreeProc proc, void* ctx) { 127cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org if (count <= 0) { 128feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return SkDataTable::MakeEmpty(); 129cac3ae37522bf070244c723960d1689e53da4dcdmike@reedtribe.org } 130feb3c1a57faee39dc10ac904f6b215ba50e286b4bungeman return sk_sp<SkDataTable>(new SkDataTable(array, elemSize, count, proc, ctx)); 1318c5c7a905b708f7c0a991ca7c872af645544afefreed@google.com} 132