Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkMallocPixelRef.cpp
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
12 // assumes ptr was allocated via sk_malloc
13 static void sk_free_releaseproc(void* ptr, void*) {
14     sk_free(ptr);
15 }
16
17 static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
18     if (info.fWidth < 0 ||
19         info.fHeight < 0 ||
20         (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
21         (unsigned)info.fAlphaType > (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 && NULL != ctable) {
34         return false;
35     }
36 #endif
37     return true;
38 }
39
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 SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
52                                                 size_t requestedRowBytes,
53                                                 SkColorTable* ctable) {
54     if (!is_valid(info, ctable)) {
55         return NULL;
56     }
57
58     int32_t minRB = SkToS32(info.minRowBytes());
59     if (minRB < 0) {
60         return NULL;    // allocation will be too large
61     }
62     if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
63         return NULL;    // cannot meet requested rowbytes
64     }
65
66     int32_t rowBytes;
67     if (requestedRowBytes) {
68         rowBytes = SkToS32(requestedRowBytes);
69     } else {
70         rowBytes = minRB;
71     }
72
73     int64_t bigSize = (int64_t)info.fHeight * rowBytes;
74     if (!sk_64_isS32(bigSize)) {
75         return NULL;
76     }
77
78     size_t size = sk_64_asS32(bigSize);
79     SkASSERT(size >= info.getSafeSize(rowBytes));
80     void* addr = sk_malloc_flags(size, 0);
81     if (NULL == addr) {
82         return NULL;
83     }
84
85     return SkNEW_ARGS(SkMallocPixelRef,
86                       (info, addr, rowBytes, ctable,
87                        sk_free_releaseproc, NULL));
88 }
89
90 SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
91                                                 size_t rowBytes,
92                                                 SkColorTable* ctable,
93                                                 void* addr,
94                                                 SkMallocPixelRef::ReleaseProc proc,
95                                                 void* context) {
96     if (!is_valid(info, ctable)) {
97         return NULL;
98     }
99     return SkNEW_ARGS(SkMallocPixelRef,
100                       (info, addr, rowBytes, ctable, proc, context));
101 }
102
103 static void sk_data_releaseproc(void*, void* dataPtr) {
104     (static_cast<SkData*>(dataPtr))->unref();
105 }
106
107 SkMallocPixelRef* SkMallocPixelRef::NewWithData(const SkImageInfo& info,
108                                                 size_t rowBytes,
109                                                 SkColorTable* ctable,
110                                                 SkData* data,
111                                                 size_t offset) {
112     SkASSERT(data != NULL);
113     SkASSERT(offset <= data->size());
114     if (!is_valid(info, ctable)) {
115         return NULL;
116     }
117     if ((rowBytes < info.minRowBytes())
118         || ((data->size() - offset) < info.getSafeSize(rowBytes))) {
119         return NULL;
120     }
121     data->ref();
122     const void* ptr = static_cast<const void*>(data->bytes() + offset);
123     SkMallocPixelRef* pr
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
129     // const_cast okay.
130     pr->setImmutable();
131     return pr;
132 }
133
134 ///////////////////////////////////////////////////////////////////////////////
135
136 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
137                                    size_t rowBytes, SkColorTable* ctable,
138                                    bool ownsPixels)
139     : INHERITED(info)
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());
145
146     if (kIndex_8_SkColorType != info.fColorType) {
147         ctable = NULL;
148     }
149
150     fStorage = storage;
151     fCTable = ctable;
152     fRB = rowBytes;
153     SkSafeRef(ctable);
154
155     this->setPreLocked(fStorage, rowBytes, fCTable);
156 }
157
158 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
159                                    size_t rowBytes, SkColorTable* ctable,
160                                    SkMallocPixelRef::ReleaseProc proc,
161                                    void* context)
162     : INHERITED(info)
163     , fReleaseProc(proc)
164     , fReleaseProcContext(context)
165 {
166     SkASSERT(is_valid(info, ctable));
167     SkASSERT(rowBytes >= info.minRowBytes());
168
169     if (kIndex_8_SkColorType != info.fColorType) {
170         ctable = NULL;
171     }
172
173     fStorage = storage;
174     fCTable = ctable;
175     fRB = rowBytes;
176     SkSafeRef(ctable);
177
178     this->setPreLocked(fStorage, rowBytes, fCTable);
179 }
180
181
182 SkMallocPixelRef::~SkMallocPixelRef() {
183     SkSafeUnref(fCTable);
184     if (fReleaseProc != NULL) {
185         fReleaseProc(fStorage, fReleaseProcContext);
186     }
187 }
188
189 bool SkMallocPixelRef::onNewLockPixels(LockRec* rec) {
190     rec->fPixels = fStorage;
191     rec->fRowBytes = fRB;
192     rec->fColorTable = fCTable;
193     return true;
194 }
195
196 void SkMallocPixelRef::onUnlockPixels() {
197     // nothing to do
198 }
199
200 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
201     return this->info().getSafeSize(fRB);
202 }
203
204 void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
205     this->INHERITED::flatten(buffer);
206
207     buffer.write32(SkToU32(fRB));
208
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);
214     if (fCTable) {
215         fCTable->writeToBuffer(buffer);
216     }
217 }
218
219 SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
220     : INHERITED(buffer, NULL)
221     , fReleaseProc(sk_free_releaseproc)
222     , fReleaseProcContext(NULL)
223 {
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);
229     } else {
230         fStorage = NULL;
231     }
232
233     if (buffer.readBool()) {
234         fCTable = SkNEW_ARGS(SkColorTable, (buffer));
235     } else {
236         fCTable = NULL;
237     }
238
239     this->setPreLocked(fStorage, fRB, fCTable);
240 }
241
242 ///////////////////////////////////////////////////////////////////////////////
243
244 SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info,
245                                                 SkColorTable* ctable) {
246     return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable);
247 }