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 "SkWriteBuffer.h"
     12 
     13 // assumes ptr was allocated via sk_malloc
     14 static void sk_free_releaseproc(void* ptr, void*) {
     15     sk_free(ptr);
     16 }
     17 
     18 static bool is_valid(const SkImageInfo& info) {
     19     if (info.width() < 0 || info.height() < 0 ||
     20         (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType ||
     21         (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType)
     22     {
     23         return false;
     24     }
     25     return true;
     26 }
     27 
     28 sk_sp<SkPixelRef> SkMallocPixelRef::MakeDirect(const SkImageInfo& info,
     29                                                void* addr,
     30                                                size_t rowBytes) {
     31     if (!is_valid(info)) {
     32         return nullptr;
     33     }
     34     return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, nullptr, nullptr));
     35 }
     36 
     37 
     38  sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*alloc)(size_t),
     39                                                const SkImageInfo& info,
     40                                                size_t requestedRowBytes) {
     41     if (!is_valid(info)) {
     42         return nullptr;
     43     }
     44 
     45     // only want to permit 31bits of rowBytes
     46     int64_t minRB = (int64_t)info.minRowBytes64();
     47     if (minRB < 0 || !sk_64_isS32(minRB)) {
     48         return nullptr;    // allocation will be too large
     49     }
     50     if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
     51         return nullptr;    // cannot meet requested rowbytes
     52     }
     53 
     54     int32_t rowBytes;
     55     if (requestedRowBytes) {
     56         rowBytes = SkToS32(requestedRowBytes);
     57     } else {
     58         rowBytes = minRB;
     59     }
     60 
     61     int64_t bigSize = (int64_t)info.height() * rowBytes;
     62     if (!sk_64_isS32(bigSize)) {
     63         return nullptr;
     64     }
     65 
     66     size_t size = sk_64_asS32(bigSize);
     67     SkASSERT(size >= info.getSafeSize(rowBytes));
     68     void* addr = alloc(size);
     69     if (nullptr == addr) {
     70         return nullptr;
     71     }
     72 
     73      return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes,
     74                                                    sk_free_releaseproc, nullptr));
     75 }
     76 
     77 sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info,
     78                                                 size_t rowBytes) {
     79     auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
     80     return MakeUsing(sk_malloc_nothrow, info, rowBytes);
     81 }
     82 
     83 sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info,
     84                                                size_t rowBytes) {
     85     return MakeUsing(sk_calloc, info, rowBytes);
     86 }
     87 
     88 static void sk_data_releaseproc(void*, void* dataPtr) {
     89     (static_cast<SkData*>(dataPtr))->unref();
     90 }
     91 
     92 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info,
     93                                                  size_t rowBytes,
     94                                                  void* addr,
     95                                                  SkMallocPixelRef::ReleaseProc proc,
     96                                                  void* context) {
     97     if (!is_valid(info)) {
     98         if (proc) {
     99             proc(addr, context);
    100         }
    101         return nullptr;
    102     }
    103     return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, proc, context));
    104 }
    105 
    106 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info,
    107                                                 size_t rowBytes,
    108                                                 sk_sp<SkData> data) {
    109     SkASSERT(data != nullptr);
    110     if (!is_valid(info)) {
    111         return nullptr;
    112     }
    113     if ((rowBytes < info.minRowBytes()) || (data->size() < info.getSafeSize(rowBytes))) {
    114         return nullptr;
    115     }
    116     // must get this address before we call release
    117     void* pixels = const_cast<void*>(data->data());
    118     SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes,
    119                                           sk_data_releaseproc, data.release());
    120     pr->setImmutable(); // since we were created with (immutable) data
    121     return sk_sp<SkPixelRef>(pr);
    122 }
    123 
    124 ///////////////////////////////////////////////////////////////////////////////
    125 
    126 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    127                                    size_t rowBytes,
    128                                    SkMallocPixelRef::ReleaseProc proc,
    129                                    void* context)
    130     : INHERITED(info.width(), info.height(), storage, rowBytes)
    131     , fReleaseProc(proc)
    132     , fReleaseProcContext(context)
    133 {}
    134 
    135 
    136 SkMallocPixelRef::~SkMallocPixelRef() {
    137     if (fReleaseProc != nullptr) {
    138         fReleaseProc(this->pixels(), fReleaseProcContext);
    139     }
    140 }
    141