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
12SkMutex gImageRefMutex;
13
14///////////////////////////////////////////////////////////////////////////////
15
16SkImageRef::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
34SkImageRef::~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    SkSafeUnref(fFactory);
44}
45
46bool 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
60bool 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
70SkImageDecoderFactory* SkImageRef::setDecoderFactory(
71                                                SkImageDecoderFactory* fact) {
72    SkRefCnt_SafeAssign(fFactory, fact);
73    return fact;
74}
75
76///////////////////////////////////////////////////////////////////////////////
77
78bool 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
84bool 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
139void* 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
152void SkImageRef::onUnlockPixels() {
153    // we're already have the mutex locked
154    SkASSERT(&gImageRefMutex == this->mutex());
155}
156
157size_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
171SkImageRef::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
185void 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