aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-09 15:48:24 +0000
committerGravatar scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-09 15:48:24 +0000
commit468142b2f50de055f00d5684515d962777da5131 (patch)
tree82d0e50b633746bcb2e46302dc8283b1551e558b
parentbc69ce982f8374742ca910587485f0d741350c2d (diff)
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
-rw-r--r--include/core/SkImageDecoder.h10
-rw-r--r--src/images/SkImageDecoder.cpp17
-rw-r--r--src/images/SkImageDecoder_libico.cpp14
-rw-r--r--src/ports/SkImageDecoder_empty.cpp2
4 files changed, 43 insertions, 0 deletions
diff --git a/include/core/SkImageDecoder.h b/include/core/SkImageDecoder.h
index 67c8257827..191fe53f4c 100644
--- a/include/core/SkImageDecoder.h
+++ b/include/core/SkImageDecoder.h
@@ -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
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 0aa752e38f..5d94bb1c2d 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -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;
}
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index 6335136fa0..b14e19614c 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -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
diff --git a/src/ports/SkImageDecoder_empty.cpp b/src/ports/SkImageDecoder_empty.cpp
index 94db139656..c225bb1998 100644
--- a/src/ports/SkImageDecoder_empty.cpp
+++ b/src/ports/SkImageDecoder_empty.cpp
@@ -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;