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