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