2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkMallocPixelRef.h"
10 #include "SkFlattenableBuffers.h"
12 // assumes ptr was allocated via sk_malloc
13 static void sk_free_releaseproc(void* ptr, void*) {
17 static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
18 if (info.fWidth < 0 ||
20 (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
21 (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
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?
30 if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
33 if (kIndex8_SkColorType != info.fColorType && NULL != ctable) {
40 SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
43 SkColorTable* ctable) {
44 if (!is_valid(info, ctable)) {
47 return SkNEW_ARGS(SkMallocPixelRef,
48 (info, addr, rowBytes, ctable, NULL, NULL));
51 SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
52 size_t requestedRowBytes,
53 SkColorTable* ctable) {
54 if (!is_valid(info, ctable)) {
58 int32_t minRB = SkToS32(info.minRowBytes());
60 return NULL; // allocation will be too large
62 if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
63 return NULL; // cannot meet requested rowbytes
67 if (requestedRowBytes) {
68 rowBytes = SkToS32(requestedRowBytes);
73 int64_t bigSize = (int64_t)info.fHeight * rowBytes;
74 if (!sk_64_isS32(bigSize)) {
78 size_t size = sk_64_asS32(bigSize);
79 SkASSERT(size >= info.getSafeSize(rowBytes));
80 void* addr = sk_malloc_flags(size, 0);
85 return SkNEW_ARGS(SkMallocPixelRef,
86 (info, addr, rowBytes, ctable,
87 sk_free_releaseproc, NULL));
90 SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
94 SkMallocPixelRef::ReleaseProc proc,
96 if (!is_valid(info, ctable)) {
99 return SkNEW_ARGS(SkMallocPixelRef,
100 (info, addr, rowBytes, ctable, proc, context));
103 static void sk_data_releaseproc(void*, void* dataPtr) {
104 (static_cast<SkData*>(dataPtr))->unref();
107 SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
109 SkColorTable* ctable,
112 SkASSERT(data != NULL);
113 SkASSERT(offset <= data->size());
114 if (!is_valid(info, ctable)) {
117 if ((rowBytes < info.minRowBytes())
118 || ((data->size() - offset) < info.getSafeSize(rowBytes))) {
122 const void* ptr = static_cast<const void*>(data->bytes() + offset);
124 = SkNEW_ARGS(SkMallocPixelRef,
125 (info, const_cast<void*>(ptr), rowBytes, ctable,
126 sk_data_releaseproc, static_cast<void*>(data)));
127 SkASSERT(pr != NULL);
128 // We rely on the immutability of the pixels to make the
134 ///////////////////////////////////////////////////////////////////////////////
136 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
137 size_t rowBytes, SkColorTable* ctable,
140 , fReleaseProc(ownsPixels ? sk_free_releaseproc : NULL)
141 , fReleaseProcContext(NULL) {
142 // This constructor is now DEPRICATED.
143 SkASSERT(is_valid(info, ctable));
144 SkASSERT(rowBytes >= info.minRowBytes());
146 if (kIndex_8_SkColorType != info.fColorType) {
155 this->setPreLocked(fStorage, rowBytes, fCTable);
158 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
159 size_t rowBytes, SkColorTable* ctable,
160 SkMallocPixelRef::ReleaseProc proc,
164 , fReleaseProcContext(context)
166 SkASSERT(is_valid(info, ctable));
167 SkASSERT(rowBytes >= info.minRowBytes());
169 if (kIndex_8_SkColorType != info.fColorType) {
178 this->setPreLocked(fStorage, rowBytes, fCTable);
182 SkMallocPixelRef::~SkMallocPixelRef() {
183 SkSafeUnref(fCTable);
184 if (fReleaseProc != NULL) {
185 fReleaseProc(fStorage, fReleaseProcContext);
189 bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
190 rec->fPixels = fStorage;
191 rec->fRowBytes = fRB;
192 rec->fColorTable = fCTable;
196 void SkMallocPixelRef::onUnlockPixels() {
200 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
201 return this->info().getSafeSize(fRB);
204 void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
205 this->INHERITED::flatten(buffer);
207 buffer.write32(SkToU32(fRB));
209 // TODO: replace this bulk write with a chunky one that can trim off any
210 // trailing bytes on each scanline (in case rowbytes > width*size)
211 size_t size = this->info().getSafeSize(fRB);
212 buffer.writeByteArray(fStorage, size);
213 buffer.writeBool(fCTable != NULL);
215 fCTable->writeToBuffer(buffer);
219 SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
220 : INHERITED(buffer, NULL)
221 , fReleaseProc(sk_free_releaseproc)
222 , fReleaseProcContext(NULL)
224 fRB = buffer.read32();
225 size_t size = buffer.isValid() ? this->info().getSafeSize(fRB) : 0;
226 if (buffer.validateAvailable(size)) {
227 fStorage = sk_malloc_throw(size);
228 buffer.readByteArray(fStorage, size);
233 if (buffer.readBool()) {
234 fCTable = SkNEW_ARGS(SkColorTable, (buffer));
239 this->setPreLocked(fStorage, fRB, fCTable);
242 ///////////////////////////////////////////////////////////////////////////////
244 SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info,
245 SkColorTable* ctable) {
246 return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable);