Index: Source/platform/image-decoders/gif/GIFImageReader.cpp |
diff --git a/Source/platform/image-decoders/gif/GIFImageReader.cpp b/Source/platform/image-decoders/gif/GIFImageReader.cpp |
index 42db80edb56dab57fb92fcea2f215a966c84b03b..1211907a2cb50097569f63db10008614d81296b4 100644 |
--- a/Source/platform/image-decoders/gif/GIFImageReader.cpp |
+++ b/Source/platform/image-decoders/gif/GIFImageReader.cpp |
@@ -434,17 +434,15 @@ bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder: |
} |
case GIFGlobalHeader: { |
- // This is the height and width of the "screen" or frame into which images are rendered. The |
- // individual images can be smaller than the screen size and located with an origin anywhere |
- // within the screen. |
+ // This is the height and width of the "screen" or frame into which |
+ // images are rendered. The individual images can be smaller than |
+ // the screen size and located with an origin anywhere within the |
+ // screen. |
+ // Note that we don't inform the client of the size yet, as it might |
+ // change after we read the first frame's image header. |
m_screenWidth = GETINT16(currentComponent); |
m_screenHeight = GETINT16(currentComponent + 2); |
- // CALLBACK: Inform the decoderplugin of our size. |
- // Note: A subsequent frame might have dimensions larger than the "screen" dimensions. |
- if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) |
- return false; |
- |
const size_t globalColorMapColors = 2 << (currentComponent[4] & 0x07); |
if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* global map */ |
@@ -632,29 +630,26 @@ bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder: |
width = GETINT16(currentComponent + 4); |
height = GETINT16(currentComponent + 6); |
- /* Work around broken GIF files where the logical screen |
- * size has weird width or height. We assume that GIF87a |
- * files don't contain animations. |
- */ |
- if (currentFrameIsFirstFrame() |
- && ((m_screenHeight < height) || (m_screenWidth < width) || (m_version == 87))) { |
- m_screenHeight = height; |
- m_screenWidth = width; |
- xOffset = 0; |
- yOffset = 0; |
- |
- // CALLBACK: Inform the decoderplugin of our size. |
- if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) |
- return false; |
+ // Some GIF files have frames that don't fit in the specified |
+ // overall image size. For the first frame, we can simply enlarge |
+ // the image size to allow the frame to be visible. We can't do |
+ // this on subsequent frames because the rest of the decoding |
+ // infrastructure assumes the image size won't change as we |
+ // continue decoding, so any subsequent frames that are even |
+ // larger will be cropped. |
+ // Luckily, handling just the first frame is sufficient to deal |
+ // with most cases, e.g. ones where the image size is erroneously |
+ // set to zero, since usually the first frame completely fills |
+ // the image. |
+ if (currentFrameIsFirstFrame()) { |
+ m_screenHeight = std::max(m_screenHeight, yOffset + height); |
+ m_screenWidth = std::max(m_screenWidth, xOffset + width); |
} |
- // Work around more broken GIF files that have zero image width or height |
- if (!height || !width) { |
- height = m_screenHeight; |
- width = m_screenWidth; |
- if (!height || !width) |
- return false; |
- } |
+ // Inform the client of the final size. |
+ if (!m_sentSizeToClient && m_client && !m_client->setSize(m_screenWidth, m_screenHeight)) |
+ return false; |
+ m_sentSizeToClient = true; |
if (query == GIFImageDecoder::GIFSizeQuery) { |
// The decoder needs to stop. Hand back the number of bytes we consumed from |
@@ -668,9 +663,16 @@ bool GIFImageReader::parseData(size_t dataPosition, size_t len, GIFImageDecoder: |
GIFFrameContext* currentFrame = m_frames.last().get(); |
currentFrame->setHeaderDefined(); |
+ |
+ // Work around more broken GIF files that have zero image width or |
+ // height. |
+ if (!height || !width) { |
+ height = m_screenHeight; |
+ width = m_screenWidth; |
+ if (!height || !width) |
+ return false; |
+ } |
currentFrame->setRect(xOffset, yOffset, width, height); |
- m_screenWidth = std::max(m_screenWidth, width); |
- m_screenHeight = std::max(m_screenHeight, height); |
currentFrame->setInterlaced(currentComponent[8] & 0x40); |
// Overlaying interlaced, transparent GIFs over |