• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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