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