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, SkColorTable* ctable) {
     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 
     26     // these seem like good checks, but currently we have (at least) tests
     27     // that expect the pixelref to succeed even when there is a mismatch
     28     // with colortables. fix?
     29 #if 0
     30     if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
     31         return false;
     32     }
     33     if (kIndex8_SkColorType != info.fColorType && ctable) {
     34         return false;
     35     }
     36 #endif
     37     return true;
     38 }
     39 
     40 SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
     41                                               void* addr,
     42                                               size_t rowBytes,
     43                                               SkColorTable* ctable) {
     44     if (!is_valid(info, ctable)) {
     45         return NULL;
     46     }
     47     return SkNEW_ARGS(SkMallocPixelRef,
     48                       (info, addr, rowBytes, ctable, NULL, NULL));
     49 }
     50 
     51 
     52 SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
     53                                                 size_t requestedRowBytes,
     54                                                 SkColorTable* ctable) {
     55     if (!is_valid(info, ctable)) {
     56         return NULL;
     57     }
     58 
     59     int32_t minRB = SkToS32(info.minRowBytes());
     60     if (minRB < 0) {
     61         return NULL;    // allocation will be too large
     62     }
     63     if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
     64         return NULL;    // cannot meet requested rowbytes
     65     }
     66 
     67     int32_t rowBytes;
     68     if (requestedRowBytes) {
     69         rowBytes = SkToS32(requestedRowBytes);
     70     } else {
     71         rowBytes = minRB;
     72     }
     73 
     74     int64_t bigSize = (int64_t)info.height() * rowBytes;
     75     if (!sk_64_isS32(bigSize)) {
     76         return NULL;
     77     }
     78 
     79     size_t size = sk_64_asS32(bigSize);
     80     SkASSERT(size >= info.getSafeSize(rowBytes));
     81     void* addr = sk_malloc_flags(size, 0);
     82     if (NULL == addr) {
     83         return NULL;
     84     }
     85 
     86     return SkNEW_ARGS(SkMallocPixelRef,
     87                       (info, addr, rowBytes, ctable,
     88                        sk_free_releaseproc, NULL));
     89 }
     90 
     91 SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
     92                                                 size_t rowBytes,
     93                                                 SkColorTable* ctable,
     94                                                 void* addr,
     95                                                 SkMallocPixelRef::ReleaseProc proc,
     96                                                 void* context) {
     97     if (!is_valid(info, ctable)) {
     98         return NULL;
     99     }
    100     return SkNEW_ARGS(SkMallocPixelRef,
    101                       (info, addr, rowBytes, ctable, proc, context));
    102 }
    103 
    104 static void sk_data_releaseproc(void*, void* dataPtr) {
    105     (static_cast<SkData*>(dataPtr))->unref();
    106 }
    107 
    108 SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
    109                                                 size_t rowBytes,
    110                                                 SkColorTable* ctable,
    111                                                 SkData* data) {
    112     SkASSERT(data != NULL);
    113     if (!is_valid(info, ctable)) {
    114         return NULL;
    115     }
    116     if ((rowBytes < info.minRowBytes())
    117         || (data->size() < info.getSafeSize(rowBytes))) {
    118         return NULL;
    119     }
    120     data->ref();
    121     SkMallocPixelRef* pr
    122         = SkNEW_ARGS(SkMallocPixelRef,
    123                      (info, const_cast<void*>(data->data()), rowBytes, ctable,
    124                       sk_data_releaseproc, static_cast<void*>(data)));
    125     SkASSERT(pr != NULL);
    126     // We rely on the immutability of the pixels to make the
    127     // const_cast okay.
    128     pr->setImmutable();
    129     return pr;
    130 }
    131 
    132 ///////////////////////////////////////////////////////////////////////////////
    133 
    134 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    135                                    size_t rowBytes, SkColorTable* ctable,
    136                                    bool ownsPixels)
    137     : INHERITED(info)
    138     , fReleaseProc(ownsPixels ? sk_free_releaseproc : NULL)
    139     , fReleaseProcContext(NULL) {
    140     // This constructor is now DEPRICATED.
    141     SkASSERT(is_valid(info, ctable));
    142     SkASSERT(rowBytes >= info.minRowBytes());
    143 
    144     if (kIndex_8_SkColorType != info.colorType()) {
    145         ctable = NULL;
    146     }
    147 
    148     fStorage = storage;
    149     fCTable = ctable;
    150     fRB = rowBytes;
    151     SkSafeRef(ctable);
    152 
    153     this->setPreLocked(fStorage, rowBytes, fCTable);
    154 }
    155 
    156 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
    157                                    size_t rowBytes, SkColorTable* ctable,
    158                                    SkMallocPixelRef::ReleaseProc proc,
    159                                    void* context)
    160     : INHERITED(info)
    161     , fReleaseProc(proc)
    162     , fReleaseProcContext(context)
    163 {
    164     SkASSERT(is_valid(info, ctable));
    165     SkASSERT(rowBytes >= info.minRowBytes());
    166 
    167     if (kIndex_8_SkColorType != info.colorType()) {
    168         ctable = NULL;
    169     }
    170 
    171     fStorage = storage;
    172     fCTable = ctable;
    173     fRB = rowBytes;
    174     SkSafeRef(ctable);
    175 
    176     this->setPreLocked(fStorage, rowBytes, fCTable);
    177 }
    178 
    179 
    180 SkMallocPixelRef::~SkMallocPixelRef() {
    181     SkSafeUnref(fCTable);
    182     if (fReleaseProc != NULL) {
    183         fReleaseProc(fStorage, fReleaseProcContext);
    184     }
    185 }
    186 
    187 bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
    188     rec->fPixels = fStorage;
    189     rec->fRowBytes = fRB;
    190     rec->fColorTable = fCTable;
    191     return true;
    192 }
    193 
    194 void SkMallocPixelRef::onUnlockPixels() {
    195     // nothing to do
    196 }
    197 
    198 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
    199     return this->info().getSafeSize(fRB);
    200 }
    201 
    202 ///////////////////////////////////////////////////////////////////////////////
    203 
    204 SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t rowBytes,
    205                                                 SkColorTable* ctable) {
    206     return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable);
    207 }
    208