Allow ico decoder to decode PNG sub-images.

Since Windows Vista, PNG can be embedded in an ICO file. Update
our decoder to support this.

BUG=https://code.google.com/p/skia/issues/detail?id=1398
R=djsollen@google.com

Review URL: https://codereview.chromium.org/18655007

git-svn-id: http://skia.googlecode.com/svn/trunk@9932 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
scroggo@google.com 2013-07-09 15:48:24 +00:00
parent bc69ce982f
commit 468142b2f5
4 changed files with 43 additions and 0 deletions

View File

@ -404,7 +404,17 @@ protected:
int dstX, int dstY, int width, int height,
int srcX, int srcY);
/**
* Copy all fields on this decoder to the other decoder. Used by subclasses
* to decode a subimage using a different decoder, but with the same settings.
*/
void copyFieldsToOther(SkImageDecoder* other);
/**
* Return the default preference being used by the current or latest call to
* decode.
*/
SkBitmap::Config getDefaultPref() { return fDefaultPref; }
/** Can be queried from within onDecode, to see if the user (possibly in
a different thread) has requested the decode to cancel. If this returns

View File

@ -50,6 +50,23 @@ SkImageDecoder::~SkImageDecoder() {
SkSafeUnref(fAllocator);
}
void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
if (NULL == other) {
return;
}
other->setPeeker(fPeeker);
other->setChooser(fChooser);
other->setAllocator(fAllocator);
other->setSampleSize(fSampleSize);
if (fUsePrefTable) {
other->setPrefConfigTable(fPrefTable);
} else {
other->fDefaultPref = fDefaultPref;
}
other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
}
SkImageDecoder::Format SkImageDecoder::getFormat() const {
return kUnknown_Format;
}

View File

@ -152,6 +152,20 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
int offset = read4Bytes(buf, 18 + choice*16);
if ((size_t)(offset + size) > length)
return false;
// Check to see if this is a PNG image inside the ICO
{
SkMemoryStream subStream(buf + offset, size, false);
SkAutoTDelete<SkImageDecoder> otherDecoder(SkImageDecoder::Factory(&subStream));
if (otherDecoder.get() != NULL) {
// Set fields on the other decoder to be the same as this one.
this->copyFieldsToOther(otherDecoder.get());
if(otherDecoder->decode(&subStream, bm, this->getDefaultPref(), mode)) {
return true;
}
}
}
//int infoSize = read4Bytes(buf, offset); //40
//int width = read4Bytes(buf, offset+4); //should == w
//int height = read4Bytes(buf, offset+8); //should == 2*h

View File

@ -22,6 +22,8 @@ SkImageDecoder* SkImageDecoder::Factory(SkStream*) {
return NULL;
}
void SkImageDecoder::copyFieldsToOther(SkImageDecoder* ) {}
bool SkImageDecoder::DecodeFile(const char[], SkBitmap*, SkBitmap::Config,
SkImageDecoder::Mode, SkImageDecoder::Format*) {
return false;