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    fFactory->safeUnref();
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
60SkImageDecoderFactory* SkImageRef::setDecoderFactory(
61                                                SkImageDecoderFactory* fact) {
62    SkRefCnt_SafeAssign(fFactory, fact);
63    return fact;
64}
65
66///////////////////////////////////////////////////////////////////////////////
67
68bool SkImageRef::onDecode(SkImageDecoder* codec, SkStream* stream,
69                          SkBitmap* bitmap, SkBitmap::Config config,
70                          SkImageDecoder::Mode mode) {
71    return codec->decode(stream, bitmap, config, mode);
72}
73
74bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) {
75    SkASSERT(&gImageRefMutex == this->mutex());
76
77    if (fErrorInDecoding) {
78        return false;
79    }
80
81    /*  As soon as we really know our config, we record it, so that on
82        subsequent calls to the codec, we are sure we will always get the same
83        result.
84    */
85    if (SkBitmap::kNo_Config != fBitmap.config()) {
86        fConfig = fBitmap.config();
87    }
88
89    if (NULL != fBitmap.getPixels() ||
90            (SkBitmap::kNo_Config != fBitmap.config() &&
91             SkImageDecoder::kDecodeBounds_Mode == mode)) {
92        return true;
93    }
94
95    SkASSERT(fBitmap.getPixels() == NULL);
96
97    fStream->rewind();
98
99    SkImageDecoder* codec;
100    if (fFactory) {
101        codec = fFactory->newDecoder(fStream);
102    } else {
103        codec = SkImageDecoder::Factory(fStream);
104    }
105
106    if (codec) {
107        SkAutoTDelete<SkImageDecoder> ad(codec);
108
109        codec->setSampleSize(fSampleSize);
110        codec->setDitherImage(fDoDither);
111        if (this->onDecode(codec, fStream, &fBitmap, fConfig, mode)) {
112            return true;
113        }
114    }
115
116#ifdef DUMP_IMAGEREF_LIFECYCLE
117    if (NULL == codec) {
118        SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI());
119    } else {
120        SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n",
121                 this->getURI(), mode);
122    }
123#endif
124    fErrorInDecoding = true;
125    fBitmap.reset();
126    return false;
127}
128
129void* SkImageRef::onLockPixels(SkColorTable** ct) {
130    SkASSERT(&gImageRefMutex == this->mutex());
131
132    if (NULL == fBitmap.getPixels()) {
133        (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode);
134    }
135
136    if (ct) {
137        *ct = fBitmap.getColorTable();
138    }
139    return fBitmap.getPixels();
140}
141
142void SkImageRef::onUnlockPixels() {
143    // we're already have the mutex locked
144    SkASSERT(&gImageRefMutex == this->mutex());
145}
146
147size_t SkImageRef::ramUsed() const {
148    size_t size = 0;
149
150    if (fBitmap.getPixels()) {
151        size = fBitmap.getSize();
152        if (fBitmap.getColorTable()) {
153            size += fBitmap.getColorTable()->count() * sizeof(SkPMColor);
154        }
155    }
156    return size;
157}
158
159///////////////////////////////////////////////////////////////////////////////
160
161SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer)
162        : INHERITED(buffer, &gImageRefMutex), fErrorInDecoding(false) {
163    fConfig = (SkBitmap::Config)buffer.readU8();
164    fSampleSize = buffer.readU8();
165    fDoDither = buffer.readBool();
166
167    size_t length = buffer.readU32();
168    fStream = SkNEW_ARGS(SkMemoryStream, (length));
169    buffer.read((void*)fStream->getMemoryBase(), length);
170
171    fPrev = fNext = NULL;
172    fFactory = NULL;
173}
174
175void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const {
176    this->INHERITED::flatten(buffer);
177
178    buffer.write8(fConfig);
179    buffer.write8(fSampleSize);
180    buffer.writeBool(fDoDither);
181    size_t length = fStream->getLength();
182    buffer.write32(length);
183    fStream->rewind();
184    buffer.readFromStream(fStream, length);
185}
186
187