Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2011 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 "SkMallocPixelRef.h"
      9 #include "SkBitmap.h"
     10 #include "SkReadBuffer.h"
     11 #include "SkSafeMath.h"
     12 #include "SkWriteBuffer.h"
     13 
     14 void* sk_calloc_throw(size_t count, size_t elemSize) {
     15     return sk_calloc_throw(SkSafeMath::Mul(count, elemSize));
     16 }
     17 
     18 void* sk_malloc_throw(size_t count, size_t elemSize) {
     19     return sk_malloc_throw(SkSafeMath::Mul(count, elemSize));
     20 }
     21 
     22 void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize) {
     23     return sk_realloc_throw(buffer, SkSafeMath::Mul(count, elemSize));
     24 }
     25 
     26 void* sk_malloc_canfail(size_t count, size_t elemSize) {
     27     return sk_malloc_canfail(SkSafeMath::Mul(count, elemSize));
     28 }
     29 
     30 ///////////////////////////////////////////////////////////////////////////////////////////////////
     31 
     32 // assumes ptr was allocated via sk_malloc
     33 static void sk_free_releaseproc(void* ptr, void*) {
     34     sk_free(ptr);
     35 }
     36 
     37 static bool is_valid(const SkImageInfo& info) {
     38     if (info.width() < 0 || info.height() < 0 ||
     39         (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType ||
     40         (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType)
     41     {
     42         return false;
     43     }
     44     return true;
     45 }
     46 
     47 sk_sp<SkPixelRef> SkMallocPixelRef::MakeDirect(const SkImageInfo& info,
     48                                                void* addr,
     49                                                size_t rowBytes) {
     50     if (!is_valid(info)) {
     51         return nullptr;
     52     }
     53     return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, nullptr, nullptr));
     54 }
     55 
     56 
     57 sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*allocProc)(size_t),
     58                                               const SkImageInfo& info,
     59                                               size_t requestedRowBytes) {
     60     size_t rowBytes = requestedRowBytes;
     61     if (rowBytes == 0) {
     62         rowBytes = info.minRowBytes();
     63         // rowBytes can still be zero, if it overflowed (width * bytesPerPixel > size_t)
     64         // or if colortype is unknown
     65     }
     66     if (!is_valid(info) || !info.validRowBytes(rowBytes)) {
     67         return nullptr;
     68     }
     69     size_t size = 0;
     70     if (!info.isEmpty() && rowBytes) {
     71         size = info.computeByteSize(rowBytes);
     72         if (SkImageInfo::ByteSizeOverflowed(size)) {
     73             return nullptr;
     74         }
     75     }
     76     void* addr = allocProc(size);
     77     if (nullptr == addr) {
     78         return nullptr;
     79     }
     80 
     81     return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes,
     82                                                   sk_free_releaseproc, nullptr));
     83 }
     84 
     85 sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info, size_t rowBytes) {
     86     return MakeUsing(sk_malloc_canfail, info, rowBytes);
     87 }
     88 
     89 sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info,
     90                                                size_t rowBytes) {
     91     return MakeUsing(sk_calloc_canfail, info, rowBytes);
     92 }
     93 
     94 static void sk_data_releaseproc(void*, void* dataPtr) {
     95     (static_cast<SkData*>(dataPtr))->unref();
     96 }
     97 
     98 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info,
     99                                                  size_t rowBytes,
    100                                                  void* addr,
    101                                                  SkMallocPixelRef::ReleaseProc proc,
    102                                                  void* context) {
    103     if (!is_valid(info)) {
    104         if (proc) {
    105             proc(addr, context);
    106         }
    107         return nullptr;
    108     }
    109     return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, proc, context));
    110 }
    111 
    112 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info,
    113                                                  size_t rowBytes,
    114                                                  sk_sp<SkData> data) {
    115     SkASSERT(data != nullptr);
    116     if (!is_valid(info)) {
    117         return nullptr;
    118     }
    119     // TODO: what should we return if computeByteSize returns 0?
    120     // - the info was empty?
    121     // - we overflowed computing the size?
    122     if ((rowBytes < info.minRowBytes()) || (data->size() < info.computeByteSize(rowBytes))) {
    123         return nullptr;
    124     }
    125     // must get this address before we call release
    126     void* pixels = const_cast<void*>(data->data());
    127     SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes,
    128                                           sk_data_releaseproc, data.release());
    129     pr->setImmutable(); // since we were created with (immutable) data
    130     return sk_sp<SkPixelRef>(pr);
    131 }
    132 
    133 ///////////////////////////////////////////////////////////////////////////////
    134 
    135 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    136                                    size_t rowBytes,
    137                                    SkMallocPixelRef::ReleaseProc proc,
    138                                    void* context)
    139     : INHERITED(info.width(), info.height(), storage, rowBytes)
    140     , fReleaseProc(proc)
    141     , fReleaseProcContext(context)
    142 {}
    143 
    144 
    145 SkMallocPixelRef::~SkMallocPixelRef() {
    146     if (fReleaseProc != nullptr) {
    147         fReleaseProc(this->pixels(), fReleaseProcContext);
    148     }
    149 }
    150