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) { 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 return true; 26 } 27 28 sk_sp<SkPixelRef> SkMallocPixelRef::MakeDirect(const SkImageInfo& info, 29 void* addr, 30 size_t rowBytes) { 31 if (!is_valid(info)) { 32 return nullptr; 33 } 34 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, nullptr, nullptr)); 35 } 36 37 38 sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*alloc)(size_t), 39 const SkImageInfo& info, 40 size_t requestedRowBytes) { 41 if (!is_valid(info)) { 42 return nullptr; 43 } 44 45 // only want to permit 31bits of rowBytes 46 int64_t minRB = (int64_t)info.minRowBytes64(); 47 if (minRB < 0 || !sk_64_isS32(minRB)) { 48 return nullptr; // allocation will be too large 49 } 50 if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) { 51 return nullptr; // cannot meet requested rowbytes 52 } 53 54 int32_t rowBytes; 55 if (requestedRowBytes) { 56 rowBytes = SkToS32(requestedRowBytes); 57 } else { 58 rowBytes = minRB; 59 } 60 61 int64_t bigSize = (int64_t)info.height() * rowBytes; 62 if (!sk_64_isS32(bigSize)) { 63 return nullptr; 64 } 65 66 size_t size = sk_64_asS32(bigSize); 67 SkASSERT(size >= info.getSafeSize(rowBytes)); 68 void* addr = alloc(size); 69 if (nullptr == addr) { 70 return nullptr; 71 } 72 73 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, 74 sk_free_releaseproc, nullptr)); 75 } 76 77 sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info, 78 size_t rowBytes) { 79 auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); }; 80 return MakeUsing(sk_malloc_nothrow, info, rowBytes); 81 } 82 83 sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info, 84 size_t rowBytes) { 85 return MakeUsing(sk_calloc, info, rowBytes); 86 } 87 88 static void sk_data_releaseproc(void*, void* dataPtr) { 89 (static_cast<SkData*>(dataPtr))->unref(); 90 } 91 92 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info, 93 size_t rowBytes, 94 void* addr, 95 SkMallocPixelRef::ReleaseProc proc, 96 void* context) { 97 if (!is_valid(info)) { 98 if (proc) { 99 proc(addr, context); 100 } 101 return nullptr; 102 } 103 return sk_sp<SkPixelRef>(new SkMallocPixelRef(info, addr, rowBytes, proc, context)); 104 } 105 106 sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info, 107 size_t rowBytes, 108 sk_sp<SkData> data) { 109 SkASSERT(data != nullptr); 110 if (!is_valid(info)) { 111 return nullptr; 112 } 113 if ((rowBytes < info.minRowBytes()) || (data->size() < info.getSafeSize(rowBytes))) { 114 return nullptr; 115 } 116 // must get this address before we call release 117 void* pixels = const_cast<void*>(data->data()); 118 SkPixelRef* pr = new SkMallocPixelRef(info, pixels, rowBytes, 119 sk_data_releaseproc, data.release()); 120 pr->setImmutable(); // since we were created with (immutable) data 121 return sk_sp<SkPixelRef>(pr); 122 } 123 124 /////////////////////////////////////////////////////////////////////////////// 125 126 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage, 127 size_t rowBytes, 128 SkMallocPixelRef::ReleaseProc proc, 129 void* context) 130 : INHERITED(info.width(), info.height(), storage, rowBytes) 131 , fReleaseProc(proc) 132 , fReleaseProcContext(context) 133 {} 134 135 136 SkMallocPixelRef::~SkMallocPixelRef() { 137 if (fReleaseProc != nullptr) { 138 fReleaseProc(this->pixels(), fReleaseProcContext); 139 } 140 } 141