1 #include "SkImageRef.h"
2 #include "SkBitmap.h"
3 #include "SkFlattenable.h"
4 #include "SkImageDecoder.h"
5 #include "SkStream.h"
6 #include "SkTemplates.h"
7 #include "SkThread.h"
8
9 //#define DUMP_IMAGEREF_LIFECYCLE
10
11 // can't be static, as SkImageRef_Pool needs to see it
12 SkMutex gImageRefMutex;
13
14 ///////////////////////////////////////////////////////////////////////////////
15
SkImageRef(SkStream * stream,SkBitmap::Config config,int sampleSize)16 SkImageRef::SkImageRef(SkStream* stream, SkBitmap::Config config,
17 int sampleSize)
18 : SkPixelRef(&gImageRefMutex), fErrorInDecoding(false) {
19 SkASSERT(stream);
20 stream->ref();
21 fStream = stream;
22 fConfig = config;
23 fSampleSize = sampleSize;
24 fDoDither = true;
25 fPrev = fNext = NULL;
26 fFactory = NULL;
27
28 #ifdef DUMP_IMAGEREF_LIFECYCLE
29 SkDebugf("add ImageRef %p [%d] data=%d\n",
30 this, config, (int)stream->getLength());
31 #endif
32 }
33
~SkImageRef()34 SkImageRef::~SkImageRef() {
35 SkASSERT(&gImageRefMutex == this->mutex());
36
37 #ifdef DUMP_IMAGEREF_LIFECYCLE
38 SkDebugf("delete ImageRef %p [%d] data=%d\n",
39 this, fConfig, (int)fStream->getLength());
40 #endif
41
42 fStream->unref();
43 fFactory->safeUnref();
44 }
45
getInfo(SkBitmap * bitmap)46 bool SkImageRef::getInfo(SkBitmap* bitmap) {
47 SkAutoMutexAcquire ac(gImageRefMutex);
48
49 if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) {
50 return false;
51 }
52
53 SkASSERT(SkBitmap::kNo_Config != fBitmap.config());
54 if (bitmap) {
55 bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height());
56 }
57 return true;
58 }
59
isOpaque(SkBitmap * bitmap)60 bool SkImageRef::isOpaque(SkBitmap* bitmap) {
61 if (bitmap && bitmap->pixelRef() == this) {
62 bitmap->lockPixels();
63 bitmap->setIsOpaque(fBitmap.isOpaque());
64 bitmap->unlockPixels();
65 return true;
66 }
67 return false;
68 }
69
setDecoderFactory(SkImageDecoderFactory * fact)70 SkImageDecoderFactory* SkImageRef::setDecoderFactory(
71 SkImageDecoderFactory* fact) {
72 SkRefCnt_SafeAssign(fFactory, fact);
73 return fact;
74 }
75
76 ///////////////////////////////////////////////////////////////////////////////
77
onDecode(SkImageDecoder * codec,SkStream * stream,SkBitmap * bitmap,SkBitmap::Config config,SkImageDecoder::Mode mode)78 bool SkImageRef::onDecode(SkImageDecoder* codec, SkStream* stream,
79 SkBitmap* bitmap, SkBitmap::Config config,
80 SkImageDecoder::Mode mode) {
81 return codec->decode(stream, bitmap, config, mode);
82 }
83
prepareBitmap(SkImageDecoder::Mode mode)84 bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
85 SkASSERT(&gImageRefMutex == this->mutex());
86
87 if (fErrorInDecoding) {
88 return false;
89 }
90
91 /* As soon as we really know our config, we record it, so that on
92 subsequent calls to the codec, we are sure we will always get the same
93 result.
94 */
95 if (SkBitmap::kNo_Config != fBitmap.config()) {
96 fConfig = fBitmap.config();
97 }
98
99 if (NULL != fBitmap.getPixels() ||
100 (SkBitmap::kNo_Config != fBitmap.config() &&
101 SkImageDecoder::kDecodeBounds_Mode == mode)) {
102 return true;
103 }
104
105 SkASSERT(fBitmap.getPixels() == NULL);
106
107 fStream->rewind();
108
109 SkImageDecoder* codec;
110 if (fFactory) {
111 codec = fFactory->newDecoder(fStream);
112 } else {
113 codec = SkImageDecoder::Factory(fStream);
114 }
115
116 if (codec) {
117 SkAutoTDelete<SkImageDecoder> ad(codec);
118
119 codec->setSampleSize(fSampleSize);
120 codec->setDitherImage(fDoDither);
121 if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) {
122 return true;
123 }
124 }
125
126 #ifdef DUMP_IMAGEREF_LIFECYCLE
127 if (NULL == codec) {
128 SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
129 } else {
130 SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
131 this->getURI(), mode);
132 }
133 #endif
134 fErrorInDecoding = true;
135 fBitmap.reset();
136 return false;
137 }
138
onLockPixels(SkColorTable ** ct)139 void* SkImageRef::onLockPixels(SkColorTable** ct) {
140 SkASSERT(&gImageRefMutex == this->mutex());
141
142 if (NULL == fBitmap.getPixels()) {
143 (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
144 }
145
146 if (ct) {
147 *ct = fBitmap.getColorTable();
148 }
149 return fBitmap.getPixels();
150 }
151
onUnlockPixels()152 void SkImageRef::onUnlockPixels() {
153 // we're already have the mutex locked
154 SkASSERT(&gImageRefMutex == this->mutex());
155 }
156
ramUsed() const157 size_t SkImageRef::ramUsed() const {
158 size_t size = 0;
159
160 if (fBitmap.getPixels()) {
161 size = fBitmap.getSize();
162 if (fBitmap.getColorTable()) {
163 size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
164 }
165 }
166 return size;
167 }
168
169 ///////////////////////////////////////////////////////////////////////////////
170
SkImageRef(SkFlattenableReadBuffer & buffer)171 SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer)
172 : INHERITED(buffer, &gImageRefMutex), fErrorInDecoding(false) {
173 fConfig = (SkBitmap::Config)buffer.readU8();
174 fSampleSize = buffer.readU8();
175 fDoDither = buffer.readBool();
176
177 size_t length = buffer.readU32();
178 fStream = SkNEW_ARGS(SkMemoryStream, (length));
179 buffer.read((void*)fStream->getMemoryBase(), length);
180
181 fPrev = fNext = NULL;
182 fFactory = NULL;
183 }
184
flatten(SkFlattenableWriteBuffer & buffer) const185 void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
186 this->INHERITED::flatten(buffer);
187
188 buffer.write8(fConfig);
189 buffer.write8(fSampleSize);
190 buffer.writeBool(fDoDither);
191 size_t length = fStream->getLength();
192 buffer.write32(length);
193 fStream->rewind();
194 buffer.readFromStream(fStream, length);
195 }
196
197