Commit 2fef61b6 authored by pkasting@chromium.org's avatar pkasting@chromium.org

2009-06-19 Peter Kasting <pkasting@google.com>

        Reviewed by Eric Seidel.

        https://bugs.webkit.org/show_bug.cgi?id=26460 part three
        Make BMPImageReader a standalone class that is used by ICOImageDecoder
        and BMPImageDecoder to decode individual BMPs within a file.  These
        decoders now inherit directly from ImageDecoder.
        
        This also makes these decoders decode on-demand in isSizeAvailable() and
        frameBufferAtIndex(), like the other decoders, instead of when setData()
        is called, like before.  This should provide a speedup on pages
        containing BMPs that aren't immediately onscreen.

        * platform/image-decoders/bmp/BMPImageDecoder.cpp:
        (WebCore::BMPImageDecoder::BMPImageDecoder):
        (WebCore::BMPImageDecoder::setData):
        (WebCore::BMPImageDecoder::isSizeAvailable):
        (WebCore::BMPImageDecoder::frameBufferAtIndex):
        (WebCore::BMPImageDecoder::decodeWithCheckForDataEnded):
        (WebCore::BMPImageDecoder::decode):
        (WebCore::BMPImageDecoder::processFileHeader):
        * platform/image-decoders/bmp/BMPImageDecoder.h:
        (WebCore::BMPImageDecoder::readUint32):
        * platform/image-decoders/bmp/BMPImageReader.cpp:
        (WebCore::BMPImageReader::BMPImageReader):
        (WebCore::BMPImageReader::decodeBMP):
        (WebCore::BMPImageReader::readInfoHeaderSize):
        (WebCore::BMPImageReader::processInfoHeader):
        (WebCore::BMPImageReader::readInfoHeader):
        (WebCore::BMPImageReader::processBitmasks):
        (WebCore::BMPImageReader::processColorTable):
        (WebCore::BMPImageReader::processRLEData):
        (WebCore::BMPImageReader::processNonRLEData):
        (WebCore::BMPImageReader::setFailed):
        * platform/image-decoders/bmp/BMPImageReader.h:
        (WebCore::BMPImageReader::readUint16):
        (WebCore::BMPImageReader::readUint32):
        (WebCore::BMPImageReader::setBuffer):
        (WebCore::BMPImageReader::setData):
        (WebCore::BMPImageReader::):
        (WebCore::BMPImageReader::pastEndOfImage):
        (WebCore::BMPImageReader::readCurrentPixel):
        (WebCore::BMPImageReader::setRGBA):
        * platform/image-decoders/ico/ICOImageDecoder.cpp:
        (WebCore::ICOImageDecoder::ICOImageDecoder):
        (WebCore::ICOImageDecoder::setData):
        (WebCore::ICOImageDecoder::isSizeAvailable):
        (WebCore::ICOImageDecoder::size):
        (WebCore::ICOImageDecoder::frameBufferAtIndex):
        (WebCore::ICOImageDecoder::decodeWithCheckForDataEnded):
        (WebCore::ICOImageDecoder::decode):
        (WebCore::ICOImageDecoder::processDirectory):
        (WebCore::ICOImageDecoder::processDirectoryEntries):
        (WebCore::ICOImageDecoder::readDirectoryEntry):
        (WebCore::ICOImageDecoder::processImageType):
        * platform/image-decoders/ico/ICOImageDecoder.h:
        (WebCore::ICOImageDecoder::readUint16):
        (WebCore::ICOImageDecoder::readUint32):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@44874 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 23260caa
2009-06-19 Peter Kasting <pkasting@google.com>
Reviewed by Eric Seidel.
https://bugs.webkit.org/show_bug.cgi?id=26460 part three
Make BMPImageReader a standalone class that is used by ICOImageDecoder
and BMPImageDecoder to decode individual BMPs within a file. These
decoders now inherit directly from ImageDecoder.
This also makes these decoders decode on-demand in isSizeAvailable() and
frameBufferAtIndex(), like the other decoders, instead of when setData()
is called, like before. This should provide a speedup on pages
containing BMPs that aren't immediately onscreen.
* platform/image-decoders/bmp/BMPImageDecoder.cpp:
(WebCore::BMPImageDecoder::BMPImageDecoder):
(WebCore::BMPImageDecoder::setData):
(WebCore::BMPImageDecoder::isSizeAvailable):
(WebCore::BMPImageDecoder::frameBufferAtIndex):
(WebCore::BMPImageDecoder::decodeWithCheckForDataEnded):
(WebCore::BMPImageDecoder::decode):
(WebCore::BMPImageDecoder::processFileHeader):
* platform/image-decoders/bmp/BMPImageDecoder.h:
(WebCore::BMPImageDecoder::readUint32):
* platform/image-decoders/bmp/BMPImageReader.cpp:
(WebCore::BMPImageReader::BMPImageReader):
(WebCore::BMPImageReader::decodeBMP):
(WebCore::BMPImageReader::readInfoHeaderSize):
(WebCore::BMPImageReader::processInfoHeader):
(WebCore::BMPImageReader::readInfoHeader):
(WebCore::BMPImageReader::processBitmasks):
(WebCore::BMPImageReader::processColorTable):
(WebCore::BMPImageReader::processRLEData):
(WebCore::BMPImageReader::processNonRLEData):
(WebCore::BMPImageReader::setFailed):
* platform/image-decoders/bmp/BMPImageReader.h:
(WebCore::BMPImageReader::readUint16):
(WebCore::BMPImageReader::readUint32):
(WebCore::BMPImageReader::setBuffer):
(WebCore::BMPImageReader::setData):
(WebCore::BMPImageReader::):
(WebCore::BMPImageReader::pastEndOfImage):
(WebCore::BMPImageReader::readCurrentPixel):
(WebCore::BMPImageReader::setRGBA):
* platform/image-decoders/ico/ICOImageDecoder.cpp:
(WebCore::ICOImageDecoder::ICOImageDecoder):
(WebCore::ICOImageDecoder::setData):
(WebCore::ICOImageDecoder::isSizeAvailable):
(WebCore::ICOImageDecoder::size):
(WebCore::ICOImageDecoder::frameBufferAtIndex):
(WebCore::ICOImageDecoder::decodeWithCheckForDataEnded):
(WebCore::ICOImageDecoder::decode):
(WebCore::ICOImageDecoder::processDirectory):
(WebCore::ICOImageDecoder::processDirectoryEntries):
(WebCore::ICOImageDecoder::readDirectoryEntry):
(WebCore::ICOImageDecoder::processImageType):
* platform/image-decoders/ico/ICOImageDecoder.h:
(WebCore::ICOImageDecoder::readUint16):
(WebCore::ICOImageDecoder::readUint32):
2009-06-19 Adam Barth <abarth@webkit.org>
Reviewed by Dimitri Glazkov.
......
......@@ -31,6 +31,8 @@
#include "config.h"
#include "BMPImageDecoder.h"
#include "BMPImageReader.h"
namespace WebCore {
// Number of bits in .BMP used to store the file header (doesn't match
......@@ -39,30 +41,87 @@ namespace WebCore {
static const size_t sizeOfFileHeader = 14;
BMPImageDecoder::BMPImageDecoder()
: BMPImageReader()
: ImageDecoder()
, m_allDataReceived(false)
, m_decodedOffset(0)
{
}
void BMPImageDecoder::decodeImage(SharedBuffer* data)
void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
{
// Read and process file header.
if ((m_decodedOffset < sizeOfFileHeader) && !processFileHeader(data))
if (failed())
return;
// Decode BMP.
decodeBMP(data);
ImageDecoder::setData(data, allDataReceived);
m_allDataReceived = allDataReceived;
if (m_reader)
m_reader->setData(data);
}
bool BMPImageDecoder::processFileHeader(SharedBuffer* data)
bool BMPImageDecoder::isSizeAvailable()
{
if (!ImageDecoder::isSizeAvailable() && !failed())
decodeWithCheckForDataEnded(true);
return ImageDecoder::isSizeAvailable();
}
RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index)
{
if (index)
return 0;
if (m_frameBufferCache.isEmpty())
m_frameBufferCache.resize(1);
RGBA32Buffer* buffer = &m_frameBufferCache.first();
if (buffer->status() != RGBA32Buffer::FrameComplete && !failed())
decodeWithCheckForDataEnded(false);
return buffer;
}
void BMPImageDecoder::decodeWithCheckForDataEnded(bool onlySize)
{
if (failed())
return;
// If we couldn't decode the image but we've received all the data, decoding
// has failed.
if (!decode(onlySize) && m_allDataReceived)
setFailed();
}
bool BMPImageDecoder::decode(bool onlySize)
{
size_t imgDataOffset = 0;
if ((m_decodedOffset < sizeOfFileHeader)
&& !processFileHeader(&imgDataOffset))
return false;
if (!m_reader) {
m_reader.set(new BMPImageReader(this, m_decodedOffset, imgDataOffset,
false));
m_reader->setData(m_data.get());
}
if (!m_frameBufferCache.isEmpty())
m_reader->setBuffer(&m_frameBufferCache.first());
return m_reader->decodeBMP(onlySize);
}
bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset)
{
ASSERT(imgDataOffset);
// Read file header.
ASSERT(!m_decodedOffset);
if (data->size() < sizeOfFileHeader)
if (m_data->size() < sizeOfFileHeader)
return false;
const uint16_t fileType =
(data->data()[0] << 8) | static_cast<uint8_t>(data->data()[1]);
m_imgDataOffset = readUint32(data, 10);
m_decodedOffset = m_headerOffset = sizeOfFileHeader;
(m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]);
*imgDataOffset = readUint32(10);
m_decodedOffset = sizeOfFileHeader;
// See if this is a bitmap filetype we understand.
enum {
......
......@@ -32,28 +32,54 @@
#define BMPImageDecoder_h
#include "BMPImageReader.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
// This class decodes the BMP image format.
class BMPImageDecoder : public BMPImageReader {
class BMPImageDecoder : public ImageDecoder {
public:
BMPImageDecoder();
// ImageDecoder
virtual String filenameExtension() const { return "bmp"; }
// BMPImageReader
virtual void decodeImage(SharedBuffer*);
virtual void setData(SharedBuffer*, bool allDataReceived);
virtual bool isSizeAvailable();
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
private:
inline uint32_t readUint32(SharedBuffer* data, int offset) const
inline uint32_t readUint32(int offset) const
{
return readUint32Helper(data, m_decodedOffset + offset);
return BMPImageReader::readUint32(m_data.get(),
m_decodedOffset + offset);
}
// Processes the file header at the beginning of the data. Returns true if
// the file header could be decoded.
bool processFileHeader(SharedBuffer*);
// Decodes the image. If |onlySize| is true, stops decoding after
// calculating the image size. If decoding fails but there is no more
// data coming, sets the "decode failure" flag.
void decodeWithCheckForDataEnded(bool onlySize);
// Decodes the image. If |onlySize| is true, stops decoding after
// calculating the image size. Returns whether decoding succeeded.
// NOTE: Used internally by decodeWithCheckForDataEnded(). Other people
// should not call this.
bool decode(bool onlySize);
// Processes the file header at the beginning of the data. Sets
// |*imgDataOffset| based on the header contents. Returns true if the
// file header could be decoded.
bool processFileHeader(size_t* imgDataOffset);
// True if we've seen all the data.
bool m_allDataReceived;
// An index into |m_data| representing how much we've already decoded.
// Note that this only tracks data _this_ class decodes; once the
// BMPImageReader takes over this will not be updated further.
size_t m_decodedOffset;
// The reader used to do most of the BMP decoding.
OwnPtr<BMPImageReader> m_reader;
};
} // namespace WebCore
......
......@@ -36,23 +36,13 @@
namespace WebCore {
// This class decodes a BMP image. It is used as a base for the BMP and ICO
// decoders, which wrap it in the appropriate code to read file headers, etc.
class BMPImageReader : public ImageDecoder {
// This class decodes a BMP image. It is used in the BMP and ICO decoders,
// which wrap it in the appropriate code to read file headers, etc.
class BMPImageReader {
public:
BMPImageReader();
// Does the actual decoding. |data| starts at the beginning of the file,
// but may be incomplete.
virtual void decodeImage(SharedBuffer* data) = 0;
// ImageDecoder
virtual void setData(SharedBuffer* data, bool allDataReceived);
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
// Read a value from |data[offset]|, converting from little to native
// endianness.
static inline uint16_t readUint16Helper(SharedBuffer* data, int offset)
static inline uint16_t readUint16(SharedBuffer* data, int offset)
{
uint16_t result;
memcpy(&result, &data->data()[offset], 2);
......@@ -62,7 +52,7 @@ namespace WebCore {
return result;
}
static inline uint32_t readUint32Helper(SharedBuffer* data, int offset)
static inline uint32_t readUint32(SharedBuffer* data, int offset)
{
uint32_t result;
memcpy(&result, &data->data()[offset], 4);
......@@ -73,33 +63,22 @@ namespace WebCore {
return result;
}
protected:
enum AndMaskState {
None,
NotYetDecoded,
Decoding,
};
// Does the actual decoding. Returns whether decoding succeeded.
bool decodeBMP(SharedBuffer* data);
// An index into |m_data| representing how much we've already decoded.
size_t m_decodedOffset;
// The file offset at which the BMP info header starts.
size_t m_headerOffset;
// |parent| is the decoder that owns us.
// |startOffset| points to the start of the BMP within the file.
// |buffer| points at an empty RGBA32Buffer that we'll initialize and
// fill with decoded data.
BMPImageReader(ImageDecoder* parent,
size_t decodedAndHeaderOffset,
size_t imgDataOffset,
bool usesAndMask);
// The file offset at which the actual image bits start. When decoding
// ICO files, this is set to 0, since it's not stored anywhere in a
// header; the reader functions expect the image data to start
// immediately after the header and (if necessary) color table.
size_t m_imgDataOffset;
void setBuffer(RGBA32Buffer* buffer) { m_buffer = buffer; }
void setData(SharedBuffer* data) { m_data = data; }
// ICOs store a 1bpp "mask" immediately after the main bitmap image data
// (and, confusingly, add its height to the biHeight value in the info
// header, thus doubling it). This variable tracks whether we have such
// a mask and if we've started decoding it yet.
AndMaskState m_andMaskState;
// Does the actual decoding. If |onlySize| is true, decoding only
// progresses as far as necessary to get the image size. Returns
// whether decoding succeeded.
bool decodeBMP(bool onlySize);
private:
// The various BMP compression types. We don't currently decode all
......@@ -117,6 +96,11 @@ namespace WebCore {
HUFFMAN1D, // Stored in file as 3
RLE24, // Stored in file as 4
};
enum AndMaskState {
None,
NotYetDecoded,
Decoding,
};
// These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE
// structs, but with unnecessary entries removed.
......@@ -134,27 +118,27 @@ namespace WebCore {
uint8_t rgbRed;
};
inline uint16_t readUint16(SharedBuffer* data, int offset) const
inline uint16_t readUint16(int offset) const
{
return readUint16Helper(data, m_decodedOffset + offset);
return readUint16(m_data.get(), m_decodedOffset + offset);
}
inline uint32_t readUint32(SharedBuffer* data, int offset) const
inline uint32_t readUint32(int offset) const
{
return readUint32Helper(data, m_decodedOffset + offset);
return readUint32(m_data.get(), m_decodedOffset + offset);
}
// Determines the size of the BMP info header. Returns true if the size
// is valid.
bool getInfoHeaderSize(SharedBuffer* data);
bool readInfoHeaderSize();
// Processes the BMP info header. Returns true if the info header could
// be decoded.
bool processInfoHeader(SharedBuffer* data);
bool processInfoHeader();
// Helper function for processInfoHeader() which does the actual reading
// of header values from the byte stream. Returns false on error.
bool readInfoHeader(SharedBuffer* data);
bool readInfoHeader();
// Returns true if this is a Windows V4+ BMP.
inline bool isWindowsV4Plus() const
......@@ -169,15 +153,15 @@ namespace WebCore {
// For BI_BITFIELDS images, initializes the m_bitMasks[] and
// m_bitOffsets[] arrays. processInfoHeader() will initialize these for
// other compression types where needed.
bool processBitmasks(SharedBuffer* data);
bool processBitmasks();
// For paletted images, allocates and initializes the m_colorTable[]
// array.
bool processColorTable(SharedBuffer* data);
bool processColorTable();
// Processes an RLE-encoded image. Returns true if the entire image was
// decoded.
bool processRLEData(SharedBuffer* data);
bool processRLEData();
// Processes a set of non-RLE-compressed pixels. Two cases:
// * inRLE = true: the data is inside an RLE-encoded bitmap. Tries to
......@@ -188,7 +172,7 @@ namespace WebCore {
// beginning of the next row to be decoded. Tries to process as
// many complete rows as possible. Returns true if the whole image
// was decoded.
bool processNonRLEData(SharedBuffer* data, bool inRLE, int numPixels);
bool processNonRLEData(bool inRLE, int numPixels);
// Returns true if the current y-coordinate plus |numRows| would be past
// the end of the image. Here "plus" means "toward the end of the
......@@ -196,7 +180,7 @@ namespace WebCore {
inline bool pastEndOfImage(int numRows)
{
return m_isTopDown
? ((m_coord.y() + numRows) >= size().height())
? ((m_coord.y() + numRows) >= m_parent->size().height())
: ((m_coord.y() - numRows) < 0);
}
......@@ -205,20 +189,19 @@ namespace WebCore {
// row.
// NOTE: Only as many bytes of the return value as are needed to hold
// the pixel data will actually be set.
inline uint32_t readCurrentPixel(SharedBuffer* data, int bytesPerPixel) const
inline uint32_t readCurrentPixel(int bytesPerPixel) const
{
const int additionalOffset = m_coord.x() * bytesPerPixel;
const int offset = m_coord.x() * bytesPerPixel;
switch (bytesPerPixel) {
case 2:
return readUint16(data, additionalOffset);
return readUint16(offset);
case 3: {
// It doesn't matter that we never set the most significant byte
// of the return value here in little-endian mode, the caller
// won't read it.
uint32_t pixel;
memcpy(&pixel,
&data->data()[m_decodedOffset + additionalOffset], 3);
memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3);
#if PLATFORM(BIG_ENDIAN)
pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) |
((pixel & 0xff000000) >> 24);
......@@ -227,7 +210,7 @@ namespace WebCore {
}
case 4:
return readUint32(data, additionalOffset);
return readUint32(offset);
default:
ASSERT_NOT_REACHED();
......@@ -268,7 +251,8 @@ namespace WebCore {
unsigned blue,
unsigned alpha)
{
m_frameBufferCache.first().setRGBA(m_coord.x(), m_coord.y(), red, green, blue, alpha);
m_buffer->setRGBA(m_coord.x(), m_coord.y(), red, green, blue,
alpha);
m_coord.move(1, 0);
}
......@@ -291,6 +275,32 @@ namespace WebCore {
// depending on the value of |m_isTopDown|.
void moveBufferToNextRow();
// Sets the "decode failure" flag and clears any local storage. For
// caller convenience (since so many callers want to return false after
// calling this), returns false to enable easy tailcalling.
bool setFailed();
// The decoder that owns us.
ImageDecoder* m_parent;
// The destination for the pixel data.
RGBA32Buffer* m_buffer;
// The file to decode.
RefPtr<SharedBuffer> m_data;
// An index into |m_data| representing how much we've already decoded.
size_t m_decodedOffset;
// The file offset at which the BMP info header starts.
size_t m_headerOffset;
// The file offset at which the actual image bits start. When decoding
// ICO files, this is set to 0, since it's not stored anywhere in a
// header; the reader functions expect the image data to start
// immediately after the header and (if necessary) color table.
size_t m_imgDataOffset;
// The BMP info header.
BitmapInfoHeader m_infoHeader;
......@@ -341,6 +351,12 @@ namespace WebCore {
// these are used.
bool m_seenNonZeroAlphaPixel;
bool m_seenZeroAlphaPixel;
// ICOs store a 1bpp "mask" immediately after the main bitmap image data
// (and, confusingly, add its height to the biHeight value in the info
// header, thus doubling it). This variable tracks whether we have such
// a mask and if we've started decoding it yet.
AndMaskState m_andMaskState;
};
} // namespace WebCore
......
......@@ -31,6 +31,9 @@
#include "config.h"
#include "ICOImageDecoder.h"
#include "BMPImageReader.h"
#include "PNGImageDecoder.h"
namespace WebCore {
// Number of bits in .ICO/.CUR used to store the directory and its entries,
......@@ -40,44 +43,105 @@ static const size_t sizeOfDirectory = 6;
static const size_t sizeOfDirEntry = 16;
ICOImageDecoder::ICOImageDecoder(const IntSize& preferredIconSize)
: BMPImageReader()
: ImageDecoder()
, m_allDataReceived(false)
, m_decodedOffset(0)
, m_preferredIconSize(preferredIconSize)
, m_imageType(Unknown)
{
m_andMaskState = NotYetDecoded;
}
void ICOImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
{
if (failed())
return;
ImageDecoder::setData(data, allDataReceived);
m_allDataReceived = allDataReceived;
if (m_bmpReader)
m_bmpReader->setData(data);
if (m_pngDecoder) {
// Copy out PNG data to a separate vector and send to the PNG decoder.
// FIXME: Save this copy by making the PNG decoder able to take an
// optional offset.
RefPtr<SharedBuffer> pngData(
SharedBuffer::create(&m_data->data()[m_dirEntry.dwImageOffset],
m_data->size() - m_dirEntry.dwImageOffset));
m_pngDecoder->setData(pngData.get(), m_allDataReceived);
}
}
bool ICOImageDecoder::isSizeAvailable()
{
if (!ImageDecoder::isSizeAvailable() && !failed())
decodeWithCheckForDataEnded(true);
return (m_imageType == PNG) ?
m_pngDecoder.isSizeAvailable() : BMPImageReader::isSizeAvailable();
m_pngDecoder->isSizeAvailable() : ImageDecoder::isSizeAvailable();
}
IntSize ICOImageDecoder::size() const
{
return (m_imageType == PNG) ? m_pngDecoder.size() : BMPImageReader::size();
return (m_imageType == PNG) ? m_pngDecoder->size() : ImageDecoder::size();
}
void ICOImageDecoder::decodeImage(SharedBuffer* data)
RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index)
{
// Read and process directory.
if ((m_decodedOffset < sizeOfDirectory) && !processDirectory(data))
if (index)
return 0;
if (m_imageType == Unknown)
decodeWithCheckForDataEnded(true);
if (m_imageType == PNG) {
m_frameBufferCache.clear();
return m_pngDecoder->frameBufferAtIndex(index);
}
if (m_frameBufferCache.isEmpty())
m_frameBufferCache.resize(1);
RGBA32Buffer* buffer = &m_frameBufferCache.first();
if (buffer->status() != RGBA32Buffer::FrameComplete && (m_imageType == BMP)
&& !failed())
decodeWithCheckForDataEnded(false);
return buffer;
}
void ICOImageDecoder::decodeWithCheckForDataEnded(bool onlySize)
{
if (failed())
return;
// If we couldn't decode the image but we've received all the data, decoding
// has failed.
if (!decode(onlySize) && m_allDataReceived)
setFailed();
}
bool ICOImageDecoder::decode(bool onlySize)
{
// Read and process directory.
if ((m_decodedOffset < sizeOfDirectory) && !processDirectory())
return false;
// Read and process directory entries.
if ((m_decodedOffset <
(sizeOfDirectory + (m_directory.idCount * sizeOfDirEntry)))
&& !processDirectoryEntries(data))
return;
&& !processDirectoryEntries())
return false;
// Get the image type.
if ((m_imageType == Unknown) && !processImageType(data))
return;
if ((m_imageType == Unknown) && !processImageType())
return false;
// Create the appropriate image decoder if need be.
if ((m_imageType == PNG) ? !m_pngDecoder : !m_bmpReader) {
if (m_imageType == PNG)
m_pngDecoder.set(new PNGImageDecoder());
else
m_bmpReader.set(new BMPImageReader(this, m_decodedOffset, 0, true));
// Decode selected entry.
if (m_imageType == PNG)
decodePNG(data);
else {
// Note that we don't try to limit the bytes we give to the decoder to
// just the size specified in the icon directory. If the size given in
// the directory is insufficient to decode the whole image, the image is
......@@ -85,24 +149,28 @@ void ICOImageDecoder::decodeImage(SharedBuffer* data)
// (which we do here) is to simply aggressively consume bytes until we
// run out of bytes, finish decoding, or hit a sequence that makes the
// decoder fail.
decodeBMP(data);