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