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
is_valid(const SkImageInfo & info,SkColorTable * ctable)12 static bool is_valid(const SkImageInfo& info, SkColorTable* ctable) {
13 if (info.fWidth < 0 ||
14 info.fHeight < 0 ||
15 (unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType ||
16 (unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType)
17 {
18 return false;
19 }
20
21 // these seem like good checks, but currently we have (at least) tests
22 // that expect the pixelref to succeed even when there is a mismatch
23 // with colortables. fix?
24 #if 0
25 if (kIndex8_SkColorType == info.fColorType && NULL == ctable) {
26 return false;
27 }
28 if (kIndex8_SkColorType != info.fColorType && NULL != ctable) {
29 return false;
30 }
31 #endif
32 return true;
33 }
34
NewDirect(const SkImageInfo & info,void * addr,size_t rowBytes,SkColorTable * ctable)35 SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
36 void* addr,
37 size_t rowBytes,
38 SkColorTable* ctable) {
39 if (!is_valid(info, ctable)) {
40 return NULL;
41 }
42 return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, false));
43 }
44
NewAllocate(const SkImageInfo & info,size_t requestedRowBytes,SkColorTable * ctable)45 SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
46 size_t requestedRowBytes,
47 SkColorTable* ctable) {
48 if (!is_valid(info, ctable)) {
49 return NULL;
50 }
51
52 int32_t minRB = info.minRowBytes();
53 if (minRB < 0) {
54 return NULL; // allocation will be too large
55 }
56 if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
57 return NULL; // cannot meet requested rowbytes
58 }
59
60 int32_t rowBytes;
61 if (requestedRowBytes) {
62 rowBytes = requestedRowBytes;
63 } else {
64 rowBytes = minRB;
65 }
66
67 Sk64 bigSize;
68 bigSize.setMul(info.fHeight, rowBytes);
69 if (!bigSize.is32()) {
70 return NULL;
71 }
72
73 size_t size = bigSize.get32();
74 void* addr = sk_malloc_flags(size, 0);
75 if (NULL == addr) {
76 return NULL;
77 }
78
79 return SkNEW_ARGS(SkMallocPixelRef, (info, addr, rowBytes, ctable, true));
80 }
81
82 ///////////////////////////////////////////////////////////////////////////////
83
SkMallocPixelRef(const SkImageInfo & info,void * storage,size_t rowBytes,SkColorTable * ctable,bool ownsPixels)84 SkMallocPixelRef::SkMallocPixelRef(const SkImageInfo& info, void* storage,
85 size_t rowBytes, SkColorTable* ctable,
86 bool ownsPixels)
87 : INHERITED(info)
88 , fOwnPixels(ownsPixels)
89 {
90 SkASSERT(is_valid(info, ctable));
91 SkASSERT(rowBytes >= info.minRowBytes());
92
93 if (kIndex_8_SkColorType != info.fColorType) {
94 ctable = NULL;
95 }
96
97 fStorage = storage;
98 fCTable = ctable;
99 fRB = rowBytes;
100 SkSafeRef(ctable);
101
102 this->setPreLocked(fStorage, fCTable);
103 }
104
~SkMallocPixelRef()105 SkMallocPixelRef::~SkMallocPixelRef() {
106 SkSafeUnref(fCTable);
107 if (fOwnPixels) {
108 sk_free(fStorage);
109 }
110 }
111
onLockPixels(SkColorTable ** ctable)112 void* SkMallocPixelRef::onLockPixels(SkColorTable** ctable) {
113 *ctable = fCTable;
114 return fStorage;
115 }
116
onUnlockPixels()117 void SkMallocPixelRef::onUnlockPixels() {
118 // nothing to do
119 }
120
getAllocatedSizeInBytes() const121 size_t SkMallocPixelRef::getAllocatedSizeInBytes() const {
122 return this->info().getSafeSize(fRB);
123 }
124
flatten(SkFlattenableWriteBuffer & buffer) const125 void SkMallocPixelRef::flatten(SkFlattenableWriteBuffer& buffer) const {
126 this->INHERITED::flatten(buffer);
127
128 buffer.write32(fRB);
129
130 // TODO: replace this bulk write with a chunky one that can trim off any
131 // trailing bytes on each scanline (in case rowbytes > width*size)
132 size_t size = this->info().getSafeSize(fRB);
133 buffer.writeByteArray(fStorage, size);
134 buffer.writeBool(fCTable != NULL);
135 if (fCTable) {
136 fCTable->writeToBuffer(buffer);
137 }
138 }
139
SkMallocPixelRef(SkFlattenableReadBuffer & buffer)140 SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer)
141 : INHERITED(buffer, NULL)
142 , fOwnPixels(true)
143 {
144 fRB = buffer.read32();
145 size_t size = buffer.isValid() ? this->info().getSafeSize(fRB) : 0;
146 fStorage = sk_malloc_throw(size);
147 buffer.readByteArray(fStorage, size);
148 if (buffer.readBool()) {
149 fCTable = SkNEW_ARGS(SkColorTable, (buffer));
150 } else {
151 fCTable = NULL;
152 }
153
154 this->setPreLocked(fStorage, fCTable);
155 }
156