Index: Source/platform/image-decoders/bmp/BMPImageReader.cpp |
diff --git a/Source/platform/image-decoders/bmp/BMPImageReader.cpp b/Source/platform/image-decoders/bmp/BMPImageReader.cpp |
index 5463802947861377c44c116d9f1ec5b95e3f49c2..c2186fd8c72ce0e75baa04b6737e0303cce71c79 100644 |
--- a/Source/platform/image-decoders/bmp/BMPImageReader.cpp |
+++ b/Source/platform/image-decoders/bmp/BMPImageReader.cpp |
@@ -66,7 +66,7 @@ const uint8_t nBitTo8BitlookupTable[] = { |
namespace WebCore { |
-BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask) |
+BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool isInICO) |
: m_parent(parent) |
, m_buffer(0) |
, m_decodedOffset(decodedAndHeaderOffset) |
@@ -79,7 +79,8 @@ BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffs |
, m_needToProcessColorTable(false) |
, m_seenNonZeroAlphaPixel(false) |
, m_seenZeroAlphaPixel(false) |
- , m_andMaskState(usesAndMask ? NotYetDecoded : None) |
+ , m_isInICO(isInICO) |
+ , m_decodingAndMask(false) |
{ |
// Clue-in decodeBMP() that we need to detect the correct info header size. |
memset(&m_infoHeader, 0, sizeof(m_infoHeader)); |
@@ -126,7 +127,7 @@ bool BMPImageReader::decodeBMP(bool onlySize) |
} |
// Decode the data. |
- if ((m_andMaskState != Decoding) && !pastEndOfImage(0)) { |
+ if (!m_decodingAndMask && !pastEndOfImage(0)) { |
if ((m_infoHeader.biCompression != RLE4) && (m_infoHeader.biCompression != RLE8) && (m_infoHeader.biCompression != RLE24)) { |
const ProcessingResult result = processNonRLEData(false, 0); |
if (result != Success) |
@@ -137,7 +138,7 @@ bool BMPImageReader::decodeBMP(bool onlySize) |
// If the image has an AND mask and there was no alpha data, process the |
// mask. |
- if ((m_andMaskState == NotYetDecoded) && !m_buffer->hasAlpha()) { |
+ if (m_isInICO && !m_decodingAndMask && !m_buffer->hasAlpha()) { |
// Reset decoding coordinates to start of image. |
m_coord.setX(0); |
m_coord.setY(m_isTopDown ? 0 : (m_parent->size().height() - 1)); |
@@ -145,9 +146,9 @@ bool BMPImageReader::decodeBMP(bool onlySize) |
// The AND mask is stored as 1-bit data. |
m_infoHeader.biBitCount = 1; |
- m_andMaskState = Decoding; |
+ m_decodingAndMask = true; |
} |
- if (m_andMaskState == Decoding) { |
+ if (m_decodingAndMask) { |
const ProcessingResult result = processNonRLEData(false, 0); |
if (result != Success) |
return (result == Failure) ? m_parent->setFailed() : false; |
@@ -241,14 +242,14 @@ bool BMPImageReader::readInfoHeader() |
if (m_isOS21x) { |
m_infoHeader.biWidth = readUint16(4); |
m_infoHeader.biHeight = readUint16(6); |
- ASSERT(m_andMaskState == None); // ICO is a Windows format, not OS/2! |
+ ASSERT(!m_isInICO); // ICO is a Windows format, not OS/2! |
m_infoHeader.biBitCount = readUint16(10); |
return true; |
} |
m_infoHeader.biWidth = readUint32(4); |
m_infoHeader.biHeight = readUint32(8); |
- if (m_andMaskState != None) |
+ if (m_isInICO) |
m_infoHeader.biHeight /= 2; |
m_infoHeader.biBitCount = readUint16(14); |
@@ -440,7 +441,8 @@ bool BMPImageReader::processBitmasks() |
// |
// To complicate things, Windows V3 BMPs, which lack this mask, can specify |
// 32bpp format, which to any sane reader would imply an 8-bit alpha |
- // channel -- and indeed, there exist BMPs in this format which clearly |
+ // channel -- and for BMPs-in-ICOs, that's precisely what's intended to |
+ // happen. There also exist standalone BMPs in this format which clearly |
// expect the alpha channel to be respected. However, there are many other |
// BMPs which, for example, fill this channel with all 0s, yet clearly |
// expect to not be displayed as a fully-transparent rectangle. |
@@ -460,9 +462,10 @@ bool BMPImageReader::processBitmasks() |
// |
// So it's impossible to display every BMP in the way its creators intended, |
// and we have to choose what to break. Given the paragraph above, we match |
- // other browsers and ignore alpha in Windows V3 BMPs. |
+ // other browsers and ignore alpha in Windows V3 BMPs except inside ICO |
+ // files. |
if (!isWindowsV4Plus()) |
- m_bitMasks[3] = 0; |
+ m_bitMasks[3] = (m_isInICO && (m_infoHeader.biCompression != BITFIELDS) && (m_infoHeader.biBitCount == 32)) ? static_cast<uint32_t>(0xff000000) : 0; |
// We've now decoded all the non-image data we care about. Skip anything |
// else before the actual raster data. |
@@ -726,7 +729,7 @@ BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, i |
uint8_t pixelData = m_data->data()[m_decodedOffset + byte]; |
for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) { |
const size_t colorIndex = (pixelData >> (8 - m_infoHeader.biBitCount)) & mask; |
- if (m_andMaskState == Decoding) { |
+ if (m_decodingAndMask) { |
// There's no way to accurately represent an AND + XOR |
// operation as an RGBA image, so where the AND values |
// are 1, we simply set the framebuffer pixels to fully |