Home | History | Annotate | Download | only in core
      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 "SkData.h"
      9 #include "SkDataTable.h"
     10 #include "SkOnce.h"
     11 
     12 static void malloc_freeproc(void* context) {
     13     sk_free(context);
     14 }
     15 
     16 // Makes empty table
     17 SkDataTable::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 
     25 SkDataTable::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 
     36 SkDataTable::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 
     46 SkDataTable::~SkDataTable() {
     47     if (fFreeProc) {
     48         fFreeProc(fFreeProcContext);
     49     }
     50 }
     51 
     52 size_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 
     62 const 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 
     80 sk_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 
     87 sk_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 
    113 sk_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 
    125 sk_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