SkMallocPixelRef.cpp revision 57212f9469c8056bab3c85243dbb904e386eab95
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 12static 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 35SkMallocPixelRef* 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 45SkMallocPixelRef* 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 int64_t bigSize = (int64_t)info.fHeight * rowBytes; 68 if (!sk_64_isS32(bigSize)) { 69 return NULL; 70 } 71 72 size_t size = sk_64_asS32(bigSize); 73 void* addr = sk_malloc_flags(size, 0); 74 if (NULL == addr) { 75 return NULL; 76 } 77 78 return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true)); 79} 80 81/////////////////////////////////////////////////////////////////////////////// 82 83SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage, 84 size_t rowBytes, SkColorTable* ctable, 85 bool ownsPixels) 86 : INHERITED(info) 87 , fOwnPixels(ownsPixels) 88{ 89 SkASSERT(is_valid(info, ctable)); 90 SkASSERT(rowBytes >= info.minRowBytes()); 91 92 if (kIndex_8_SkColorType != info.fColorType) { 93 ctable = NULL; 94 } 95 96 fStorage = storage; 97 fCTable = ctable; 98 fRB = rowBytes; 99 SkSafeRef(ctable); 100 101 this->setPreLocked(fStorage, fCTable); 102} 103 104SkMallocPixelRef::~SkMallocPixelRef() { 105 SkSafeUnref(fCTable); 106 if (fOwnPixels) { 107 sk_free(fStorage); 108 } 109} 110 111void* SkMallocPixelRef::onLockPixels(SkColorTable** ctable) { 112 *ctable = fCTable; 113 return fStorage; 114} 115 116void SkMallocPixelRef::onUnlockPixels() { 117 // nothing to do 118} 119 120size_t SkMallocPixelRef::getAllocatedSizeInBytes() const { 121 return this->info().getSafeSize(fRB); 122} 123 124void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const { 125 this->INHERITED::flatten(buffer); 126 127 buffer.write32(fRB); 128 129 // TODO: replace this bulk write with a chunky one that can trim off any 130 // trailing bytes on each scanline (in case rowbytes > width*size) 131 size_t size = this->info().getSafeSize(fRB); 132 buffer.writeByteArray(fStorage, size); 133 buffer.writeBool(fCTable != NULL); 134 if (fCTable) { 135 fCTable->writeToBuffer(buffer); 136 } 137} 138 139SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) 140 : INHERITED(buffer, NULL) 141 , fOwnPixels(true) 142{ 143 fRB = buffer.read32(); 144 size_t size = this->info().getSafeSize(fRB); 145 if (buffer.validateAvailable(size)) { 146 fStorage = sk_malloc_throw(size); 147 buffer.readByteArray(fStorage, size); 148 } else { 149 fStorage = NULL; 150 } 151 152 if (buffer.readBool()) { 153 fCTable = SkNEW_ARGS(SkColorTable, (buffer)); 154 } else { 155 fCTable = NULL; 156 } 157 158 this->setPreLocked(fStorage, fCTable); 159} 160