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 14static void sk_free_releaseproc(void* ptr, void*) { 15 sk_free(ptr); 16} 17 18static 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 40SkMallocPixelRef* 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 52SkMallocPixelRef* 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 91SkMallocPixelRef* 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 104static void sk_data_releaseproc(void*, void* dataPtr) { 105 (static_cast<SkData*>(dataPtr))->unref(); 106} 107 108SkMallocPixelRef* 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 134SkMallocPixelRef::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 156SkMallocPixelRef::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 180SkMallocPixelRef::~SkMallocPixelRef() { 181 SkSafeUnref(fCTable); 182 if (fReleaseProc != NULL) { 183 fReleaseProc(fStorage, fReleaseProcContext); 184 } 185} 186 187bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) { 188 rec->fPixels = fStorage; 189 rec->fRowBytes = fRB; 190 rec->fColorTable = fCTable; 191 return true; 192} 193 194void SkMallocPixelRef::onUnlockPixels() { 195 // nothing to do 196} 197 198size_t SkMallocPixelRef::getAllocatedSizeInBytes() const { 199 return this->info().getSafeSize(fRB); 200} 201 202/////////////////////////////////////////////////////////////////////////////// 203 204SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t rowBytes, 205 SkColorTable* ctable) { 206 return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable); 207} 208