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 "SkFlattenableBuffers.h"
     11 
     12 static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
     13     if (info.fWidth < 0 ||
     14         info.fHeight < 0 ||
     15         (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
     16         (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
     17     {
     18         return false;
     19     }
     20 
     21     // these seem like good checks, but currently we have (at least) tests
     22     // that expect the pixelref to succeed even when there is a mismatch
     23     // with colortables. fix?
     24 #if 0
     25     if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
     26         return false;
     27     }
     28     if (kIndex8_SkColorType != info.fColorType && NULL != ctable) {
     29         return false;
     30     }
     31 #endif
     32     return true;
     33 }
     34 
     35 SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
     36                                               void* addr,
     37                                               size_t rowBytes,
     38                                               SkColorTable* ctable) {
     39     if (!is_valid(info, ctable)) {
     40         return NULL;
     41     }
     42     return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
     43 }
     44 
     45 SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
     46                                                 size_t requestedRowBytes,
     47                                                 SkColorTable* ctable) {
     48     if (!is_valid(info, ctable)) {
     49         return NULL;
     50     }
     51 
     52     int32_t minRB = info.minRowBytes();
     53     if (minRB < 0) {
     54         return NULL;    // allocation will be too large
     55     }
     56     if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
     57         return NULL;    // cannot meet requested rowbytes
     58     }
     59 
     60     int32_t rowBytes;
     61     if (requestedRowBytes) {
     62         rowBytes = requestedRowBytes;
     63     } else {
     64         rowBytes = minRB;
     65     }
     66 
     67     Sk64 bigSize;
     68     bigSize.setMul(info.fHeight, rowBytes);
     69     if (!bigSize.is32()) {
     70         return NULL;
     71     }
     72 
     73     size_t size = bigSize.get32();
     74     void* addr = sk_malloc_flags(size, 0);
     75     if (NULL == addr) {
     76         return NULL;
     77     }
     78 
     79     return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
     80 }
     81 
     82 ///////////////////////////////////////////////////////////////////////////////
     83 
     84 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
     85                                    size_t rowBytes, SkColorTable* ctable,
     86                                    bool ownsPixels)
     87     : INHERITED(info)
     88     , fOwnPixels(ownsPixels)
     89 {
     90     SkASSERT(is_valid(info, ctable));
     91     SkASSERT(rowBytes >= info.minRowBytes());
     92 
     93     if (kIndex_8_SkColorType != info.fColorType) {
     94         ctable = NULL;
     95     }
     96 
     97     fStorage = storage;
     98     fCTable = ctable;
     99     fRB = rowBytes;
    100     SkSafeRef(ctable);
    101 
    102     this->setPreLocked(fStorage, fCTable);
    103 }
    104 
    105 SkMallocPixelRef::~SkMallocPixelRef() {
    106     SkSafeUnref(fCTable);
    107     if (fOwnPixels) {
    108         sk_free(fStorage);
    109     }
    110 }
    111 
    112 void* SkMallocPixelRef::onLockPixels(SkColorTable** ctable) {
    113     *ctable = fCTable;
    114     return fStorage;
    115 }
    116 
    117 void SkMallocPixelRef::onUnlockPixels() {
    118     // nothing to do
    119 }
    120 
    121 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
    122     return this->info().getSafeSize(fRB);
    123 }
    124 
    125 void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
    126     this->INHERITED::flatten(buffer);
    127 
    128     buffer.write32(fRB);
    129 
    130     // TODO: replace this bulk write with a chunky one that can trim off any
    131     // trailing bytes on each scanline (in case rowbytes > width*size)
    132     size_t size = this->info().getSafeSize(fRB);
    133     buffer.writeByteArray(fStorage, size);
    134     buffer.writeBool(fCTable != NULL);
    135     if (fCTable) {
    136         fCTable->writeToBuffer(buffer);
    137     }
    138 }
    139 
    140 SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
    141     : INHERITED(buffer, NULL)
    142     , fOwnPixels(true)
    143 {
    144     fRB = buffer.read32();
    145     size_t size = buffer.isValid() ? this->info().getSafeSize(fRB) : 0;
    146     fStorage = sk_malloc_throw(size);
    147     buffer.readByteArray(fStorage, size);
    148     if (buffer.readBool()) {
    149         fCTable = SkNEW_ARGS(SkColorTable, (buffer));
    150     } else {
    151         fCTable = NULL;
    152     }
    153 
    154     this->setPreLocked(fStorage, fCTable);
    155 }
    156