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