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