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 "SkData.h" 9 #include "SkImageInfo.h" 10 #include "SkMalloc.h" 11 #include "SkMallocPixelRef.h" 12 #include "SkSafeMath.h" 13 14 void* sk_calloc_throw(size_t count, size_t elemSize) { 15 return sk_calloc_throw(SkSafeMath::Mul(count, elemSize)); 16 } 17 18 void* sk_malloc_throw(size_t count, size_t elemSize) { 19 return sk_malloc_throw(SkSafeMath::Mul(count, elemSize)); 20 } 21 22 void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize) { 23 return sk_realloc_throw(buffer, SkSafeMath::Mul(count, elemSize)); 24 } 25 26 void* sk_malloc_canfail(size_t count, size_t elemSize) { 27 return sk_malloc_canfail(SkSafeMath::Mul(count, elemSize)); 28 } 29 30 /////////////////////////////////////////////////////////////////////////////////////////////////// 31 32 // assumes ptr was allocated via sk_malloc 33 static void sk_free_releaseproc(void* ptr, void*) { 34 sk_free(ptr); 35 } 36 37 static bool is_valid(const SkImageInfo& info) { 38 if (info.width() < 0 || info.height() < 0 || 39 (unsigned)info.colorType() > (unsigned)kLastEnum_SkColorType || 40 (unsigned)info.alphaType() > (unsigned)kLastEnum_SkAlphaType) 41 { 42 return false; 43 } 44 return true; 45 } 46 47 sk_sp<SkPixelRef> SkMallocPixelRef::MakeDirect(const SkImageInfo& info, 48 void* addr, 49 size_t rowBytes) { 50 if (!is_valid(info)) { 51 return nullptr; 52 } 53 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, nullptr, nullptr)); 54 } 55 56 57 sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*allocProc)(size_t), 58 const SkImageInfo& info, 59 size_t requestedRowBytes) { 60 size_t rowBytes = requestedRowBytes; 61 if (rowBytes == 0) { 62 rowBytes = info.minRowBytes(); 63 // rowBytes can still be zero, if it overflowed (width * bytesPerPixel > size_t) 64 // or if colortype is unknown 65 } 66 if (!is_valid(info) || !info.validRowBytes(rowBytes)) { 67 return nullptr; 68 } 69 size_t size = 0; 70 if (!info.isEmpty() && rowBytes) { 71 size = info.computeByteSize(rowBytes); 72 if (SkImageInfo::ByteSizeOverflowed(size)) { 73 return nullptr; 74 } 75 } 76 void* addr = allocProc(size); 77 if (nullptr == addr) { 78 return nullptr; 79 } 80 81 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, 82 sk_free_releaseproc, nullptr)); 83 } 84 85 sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info, size_t rowBytes) { 86 return MakeUsing(sk_malloc_canfail, info, rowBytes); 87 } 88 89 sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info, 90 size_t rowBytes) { 91 return MakeUsing(sk_calloc_canfail, info, rowBytes); 92 } 93 94 static void sk_data_releaseproc(void*, void* dataPtr) { 95 (static_cast<SkData*>(dataPtr))->unref(); 96 } 97 98 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info, 99 size_t rowBytes, 100 void* addr, 101 SkMallocPixelRef::ReleaseProc proc, 102 void* context) { 103 if (!is_valid(info)) { 104 if (proc) { 105 proc(addr, context); 106 } 107 return nullptr; 108 } 109 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, proc, context)); 110 } 111 112 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info, 113 size_t rowBytes, 114 sk_sp<SkData> data) { 115 SkASSERT(data != nullptr); 116 if (!is_valid(info)) { 117 return nullptr; 118 } 119 // TODO: what should we return if computeByteSize returns 0? 120 // - the info was empty? 121 // - we overflowed computing the size? 122 if ((rowBytes < info.minRowBytes()) || (data->size() < info.computeByteSize(rowBytes))) { 123 return nullptr; 124 } 125 // must get this address before we call release 126 void* pixels = const_cast<void*>(data->data()); 127 SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes, 128 sk_data_releaseproc, data.release()); 129 pr->setImmutable(); // since we were created with (immutable) data 130 return sk_sp<SkPixelRef>(pr); 131 } 132 133 /////////////////////////////////////////////////////////////////////////////// 134 135 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage, 136 size_t rowBytes, 137 SkMallocPixelRef::ReleaseProc proc, 138 void* context) 139 : INHERITED(info.width(), info.height(), storage, rowBytes) 140 , fReleaseProc(proc) 141 , fReleaseProcContext(context) 142 {} 143 144 145 SkMallocPixelRef::~SkMallocPixelRef() { 146 if (fReleaseProc != nullptr) { 147 fReleaseProc(this->pixels(), fReleaseProcContext); 148 } 149 } 150