From 0dd638f20e7a1b974960f57a7e660099bd778115 Mon Sep 17 00:00:00 2001 From: "paper%animecity.nu" Date: Tue, 8 Mar 2005 03:44:28 +0000 Subject: [PATCH] Bug 274244: Display more broken GIFs. r=stuart sr=tor --- gfx/idl/gfxIImageFrame.idl | 7 ++++++- gfx/public/nsIImage.h | 7 +++++++ gfx/src/beos/nsImageBeOS.cpp | 10 ++++++++++ gfx/src/beos/nsImageBeOS.h | 1 + gfx/src/cairo/nsCairoImage.cpp | 7 +++++++ gfx/src/cairo/nsCairoImage.h | 1 + gfx/src/gtk/nsImageGTK.cpp | 10 ++++++++++ gfx/src/gtk/nsImageGTK.h | 1 + gfx/src/mac/nsImageMac.cpp | 9 +++++++++ gfx/src/mac/nsImageMac.h | 1 + gfx/src/os2/nsImageOS2.cpp | 11 +++++++++++ gfx/src/os2/nsImageOS2.h | 1 + gfx/src/photon/nsImagePh.cpp | 10 ++++++++++ gfx/src/photon/nsImagePh.h | 1 + gfx/src/qt/nsImageQt.cpp | 10 ++++++++++ gfx/src/qt/nsImageQt.h | 1 + gfx/src/shared/gfxImageFrame.cpp | 13 +++++++++++++ gfx/src/windows/nsImageWin.cpp | 14 ++++++++++++-- gfx/src/windows/nsImageWin.h | 1 + gfx/src/xlib/nsImageXlib.cpp | 10 ++++++++++ gfx/src/xlib/nsImageXlib.h | 1 + layout/base/nsCSSRendering.cpp | 7 +------ modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp | 8 ++------ 23 files changed, 127 insertions(+), 15 deletions(-) diff --git a/gfx/idl/gfxIImageFrame.idl b/gfx/idl/gfxIImageFrame.idl index 9d7aeaf30863..f6ca88a05545 100644 --- a/gfx/idl/gfxIImageFrame.idl +++ b/gfx/idl/gfxIImageFrame.idl @@ -57,7 +57,7 @@ native nsRectRef(nsIntRect &); * @author Stuart Parmenter * @version 0.1 */ -[scriptable, uuid(20caf74f-2c35-450f-9f87-c3ecc213553c)] +[scriptable, uuid(f6d00ee7-defc-4101-b2dc-e72cf4c37c3c)] interface gfxIImageFrame : nsISupports { /** @@ -116,6 +116,11 @@ interface gfxIImageFrame : nsISupports */ readonly attribute gfx_format format; + /** + * returns whether the image requires the background to be painted + */ + readonly attribute boolean needsBackground; + /* data accessors */ readonly attribute unsigned long imageBytesPerRow; diff --git a/gfx/public/nsIImage.h b/gfx/public/nsIImage.h index 4f5714964caf..adbcdbea4e61 100644 --- a/gfx/public/nsIImage.h +++ b/gfx/public/nsIImage.h @@ -164,6 +164,13 @@ public: * @param aUpdateRect The rectangle to update */ virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsIntRect *aUpdateRect) = 0; + + /** + * Get whether this image's region is completely filled with data. + * @return PR_TRUE if image is complete, PR_FALSE if image is not yet + * complete or broken + */ + virtual PRBool GetIsImageComplete() = 0; /** * Converted this pixelmap to an optimized pixelmap for the device diff --git a/gfx/src/beos/nsImageBeOS.cpp b/gfx/src/beos/nsImageBeOS.cpp index 552fb5fe5654..b46fdd253886 100644 --- a/gfx/src/beos/nsImageBeOS.cpp +++ b/gfx/src/beos/nsImageBeOS.cpp @@ -154,6 +154,16 @@ void nsImageBeOS::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRec mDecodedX2 = aUpdateRect->XMost(); } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageBeOS::GetIsImageComplete() { + return mDecodedX1 == 0 && + mDecodedY1 == 0 && + mDecodedX2 == mWidth && + mDecodedY2 == mHeight; +} + // Draw the bitmap, this method has a source and destination coordinates NS_IMETHODIMP nsImageBeOS::Draw(nsIRenderingContext &aContext, nsIDrawingSurface* aSurface, PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, diff --git a/gfx/src/beos/nsImageBeOS.h b/gfx/src/beos/nsImageBeOS.h index 2d0cc60389dc..e65954bde2b5 100644 --- a/gfx/src/beos/nsImageBeOS.h +++ b/gfx/src/beos/nsImageBeOS.h @@ -78,6 +78,7 @@ public: virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements); diff --git a/gfx/src/cairo/nsCairoImage.cpp b/gfx/src/cairo/nsCairoImage.cpp index 4aa30eb569e6..dff7dca7df4a 100644 --- a/gfx/src/cairo/nsCairoImage.cpp +++ b/gfx/src/cairo/nsCairoImage.cpp @@ -163,6 +163,13 @@ nsCairoImage::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *a { } +PRBool +nsCairoImage::GetIsImageComplete() +{ + /* TODO: nsCairoImage needs to store coords of decoded data */ + return PR_TRUE; +} + nsresult nsCairoImage::Optimize(nsIDeviceContext* aContext) { diff --git a/gfx/src/cairo/nsCairoImage.h b/gfx/src/cairo/nsCairoImage.h index c80279d77639..f299148f5f8a 100644 --- a/gfx/src/cairo/nsCairoImage.h +++ b/gfx/src/cairo/nsCairoImage.h @@ -63,6 +63,7 @@ public: virtual PRBool GetHasAlphaMask(); virtual PRUint8 * GetAlphaBits(); virtual PRInt32 GetAlphaLineStride(); + virtual PRBool GetIsImageComplete(); virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); virtual nsresult Optimize(nsIDeviceContext* aContext); virtual nsColorMap * GetColorMap(); diff --git a/gfx/src/gtk/nsImageGTK.cpp b/gfx/src/gtk/nsImageGTK.cpp index 67c63a96995e..46100c329c12 100644 --- a/gfx/src/gtk/nsImageGTK.cpp +++ b/gfx/src/gtk/nsImageGTK.cpp @@ -309,6 +309,16 @@ void nsImageGTK::ImageUpdated(nsIDeviceContext *aContext, mDecodedX2 = aUpdateRect->XMost(); } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageGTK::GetIsImageComplete() { + return mDecodedX1 == 0 && + mDecodedY1 == 0 && + mDecodedX2 == mWidth && + mDecodedY2 == mHeight; +} + void nsImageGTK::UpdateCachedImage() { #ifdef TRACE_IMAGE_ALLOCATION diff --git a/gfx/src/gtk/nsImageGTK.h b/gfx/src/gtk/nsImageGTK.h index b95d6ca0dd32..06ae0ade303a 100644 --- a/gfx/src/gtk/nsImageGTK.h +++ b/gfx/src/gtk/nsImageGTK.h @@ -98,6 +98,7 @@ public: void UpdateCachedImage(); virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements); diff --git a/gfx/src/mac/nsImageMac.cpp b/gfx/src/mac/nsImageMac.cpp index 4d7ce74a9c31..71234dfd613e 100644 --- a/gfx/src/mac/nsImageMac.cpp +++ b/gfx/src/mac/nsImageMac.cpp @@ -193,6 +193,15 @@ nsImageMac::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, mDecodedX2 = aUpdateRect->XMost(); } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageMac::GetIsImageComplete() { + return mDecodedX1 == 0 && + mDecodedY1 == 0 && + mDecodedX2 == mWidth && + mDecodedY2 == mHeight; +} void DataProviderReleaseFunc(void *info, const void *data, size_t size) { diff --git a/gfx/src/mac/nsImageMac.h b/gfx/src/mac/nsImageMac.h index 0e89883595e9..a3dcca181321 100644 --- a/gfx/src/mac/nsImageMac.h +++ b/gfx/src/mac/nsImageMac.h @@ -70,6 +70,7 @@ public: // mAlphaBits). 'aFlags' is ignored. virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); // Optimizes memory usage for object. virtual nsresult Optimize(nsIDeviceContext* aContext); diff --git a/gfx/src/os2/nsImageOS2.cpp b/gfx/src/os2/nsImageOS2.cpp index f8eedbdd61b4..102a2126f09c 100644 --- a/gfx/src/os2/nsImageOS2.cpp +++ b/gfx/src/os2/nsImageOS2.cpp @@ -248,6 +248,17 @@ void nsImageOS2::ImageUpdated( nsIDeviceContext *aContext, } } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageOS2::GetIsImageComplete() { + return mInfo && + mDecodedRect.x == 0 && + mDecodedRect.y == 0 && + mDecodedRect.width == mInfo->cx && + mDecodedRect.height == mInfo->cy; +} + void nsImageOS2::BuildBlenderLookup (void) { for (int y = 0 ; y < 256 ; y++) diff --git a/gfx/src/os2/nsImageOS2.h b/gfx/src/os2/nsImageOS2.h index 1229ac82698a..a12b78457d7d 100644 --- a/gfx/src/os2/nsImageOS2.h +++ b/gfx/src/os2/nsImageOS2.h @@ -75,6 +75,7 @@ public: PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight); virtual nsColorMap* GetColorMap() {return mColorMap;} virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements); virtual nsresult Optimize(nsIDeviceContext* aContext); virtual PRUint8* GetAlphaBits() { return mAlphaBits; } diff --git a/gfx/src/photon/nsImagePh.cpp b/gfx/src/photon/nsImagePh.cpp index f42a96c4ff7f..76a996701e09 100644 --- a/gfx/src/photon/nsImagePh.cpp +++ b/gfx/src/photon/nsImagePh.cpp @@ -243,6 +243,16 @@ nsresult nsImagePh :: Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth,nsMas return NS_OK; } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImagePh::GetIsImageComplete() { + return mDecodedX1 == 0 && + mDecodedY1 == 0 && + mDecodedX2 == mWidth && + mDecodedY2 == mHeight; +} + /** ---------------------------------------------------------------- * Draw the bitmap, this method has a source and destination coordinates * @update dc - 11/20/98 diff --git a/gfx/src/photon/nsImagePh.h b/gfx/src/photon/nsImagePh.h index 33034ca206c1..a51169b64064 100644 --- a/gfx/src/photon/nsImagePh.h +++ b/gfx/src/photon/nsImagePh.h @@ -106,6 +106,7 @@ public: mDirtyFlags = aFlags; mPhImage.size.h = mDecodedY2; } + virtual PRBool GetIsImageComplete(); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements); // virtual PRBool IsOptimized() { return mIsOptimized; } diff --git a/gfx/src/qt/nsImageQt.cpp b/gfx/src/qt/nsImageQt.cpp index 6cf0441cc93c..448419dfacb2 100644 --- a/gfx/src/qt/nsImageQt.cpp +++ b/gfx/src/qt/nsImageQt.cpp @@ -214,6 +214,16 @@ void nsImageQt::ImageUpdated(nsIDeviceContext *aContext, mDecodedRect.UnionRect(mDecodedRect, *aUpdateRect); } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageQt::GetIsImageComplete() { + return mDecodedRect.x == 0 && + mDecodedRect.y == 0 && + mDecodedRect.width == mWidth && + mDecodedRect.height == mHeight; +} + // Draw the bitmap, this method has a source and destination coordinates NS_IMETHODIMP nsImageQt::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, diff --git a/gfx/src/qt/nsImageQt.h b/gfx/src/qt/nsImageQt.h index 29d91391d87f..a1f15531bb53 100644 --- a/gfx/src/qt/nsImageQt.h +++ b/gfx/src/qt/nsImageQt.h @@ -74,6 +74,7 @@ public: virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags,nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); virtual nsresult Optimize(nsIDeviceContext *aContext); diff --git a/gfx/src/shared/gfxImageFrame.cpp b/gfx/src/shared/gfxImageFrame.cpp index 5d3c706c54c9..7f94c9f4b628 100644 --- a/gfx/src/shared/gfxImageFrame.cpp +++ b/gfx/src/shared/gfxImageFrame.cpp @@ -232,6 +232,19 @@ NS_IMETHODIMP gfxImageFrame::GetFormat(gfx_format *aFormat) return NS_OK; } +/* readonly attribute boolean needsBackground; */ +NS_IMETHODIMP gfxImageFrame::GetNeedsBackground(PRBool *aNeedsBackground) +{ + if (!mInitalized) + return NS_ERROR_NOT_INITIALIZED; + + *aNeedsBackground = (mFormat != gfxIFormats::RGB && + mFormat != gfxIFormats::BGR) || + !mImage->GetIsImageComplete(); + return NS_OK; +} + + /* readonly attribute unsigned long imageBytesPerRow; */ NS_IMETHODIMP gfxImageFrame::GetImageBytesPerRow(PRUint32 *aBytesPerRow) { diff --git a/gfx/src/windows/nsImageWin.cpp b/gfx/src/windows/nsImageWin.cpp index 545228c858ac..0987c54844b7 100644 --- a/gfx/src/windows/nsImageWin.cpp +++ b/gfx/src/windows/nsImageWin.cpp @@ -259,6 +259,17 @@ nsImageWin :: ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *a mDecodedX2 = aUpdateRect->XMost(); } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageWin::GetIsImageComplete() { + return mInitialized && + mDecodedX1 == 0 && + mDecodedY1 == 0 && + mDecodedX2 == mBHead->biWidth && + mDecodedY2 == mBHead->biHeight; +} + //------------------------------------------------------------ struct MONOBITMAPINFO { @@ -1088,8 +1099,7 @@ nsImageWin::ProgressiveDoubleBlit(nsIDeviceContext *aContext, return PR_FALSE; } } - mTmpHBitmap = ::CreateCompatibleBitmap(theHDC, mBHead->biWidth, - mBHead->biHeight); + mTmpHBitmap = ::CreateCompatibleBitmap(theHDC, mDecodedX2, mDecodedY2); if (!mTmpHBitmap) { ::DeleteDC(imgDC); if (maskDC) { diff --git a/gfx/src/windows/nsImageWin.h b/gfx/src/windows/nsImageWin.h index 473526355ed6..90ac3082d018 100644 --- a/gfx/src/windows/nsImageWin.h +++ b/gfx/src/windows/nsImageWin.h @@ -101,6 +101,7 @@ public: nscoord aDWidth, nscoord aDHeight); virtual nsColorMap* GetColorMap() {return mColorMap;} virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements); virtual nsresult Optimize(nsIDeviceContext* aContext); virtual PRUint8* GetAlphaBits() { return mAlphaBits; } diff --git a/gfx/src/xlib/nsImageXlib.cpp b/gfx/src/xlib/nsImageXlib.cpp index 5a5b3386f70e..77cdaa1a790b 100644 --- a/gfx/src/xlib/nsImageXlib.cpp +++ b/gfx/src/xlib/nsImageXlib.cpp @@ -265,6 +265,16 @@ void nsImageXlib::ImageUpdated(nsIDeviceContext *aContext, mDecodedX2 = aUpdateRect->XMost(); } +/** --------------------------------------------------- + * See documentation in nsIImage.h + */ +PRBool nsImageXlib::GetIsImageComplete() { + return mDecodedX1 == 0 && + mDecodedY1 == 0 && + mDecodedX2 == mWidth && + mDecodedY2 == mHeight; +} + void nsImageXlib::UpdateCachedImage() { nsRegionRectIterator ri(mUpdateRegion); diff --git a/gfx/src/xlib/nsImageXlib.h b/gfx/src/xlib/nsImageXlib.h index 7b6f079e5207..2012d08014b7 100644 --- a/gfx/src/xlib/nsImageXlib.h +++ b/gfx/src/xlib/nsImageXlib.h @@ -83,6 +83,7 @@ public: void UpdateCachedImage(); virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); + virtual PRBool GetIsImageComplete(); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements); diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index fb41bb45b50c..dcd6e83d1268 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2936,12 +2936,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, nsCOMPtr gfxImgFrame; image->GetCurrentFrame(getter_AddRefs(gfxImgFrame)); if (gfxImgFrame) { - gfx_format frameFormat; - gfxImgFrame->GetFormat(&frameFormat); - NS_ASSERTION(frameFormat >= 0 && frameFormat <= 7, - "Unknown gfxIFormats value"); - needBackgroundColor = frameFormat != gfxIFormats::RGB && - frameFormat != gfxIFormats::BGR; + gfxImgFrame->GetNeedsBackground(&needBackgroundColor); /* check for tiling of a image where frame smaller than container */ nsSize iSize; diff --git a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp index 3ecbdc37420a..06008787bbf2 100644 --- a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp +++ b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp @@ -239,7 +239,7 @@ NS_IMETHODIMP nsGIFDecoder2::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR PRUint32 numFrames = 0; if (mImageContainer) mImageContainer->GetNumFrames(&numFrames); - if (numFrames <= 1) + if (numFrames <= 0) return NS_ERROR_FAILURE; } @@ -359,11 +359,7 @@ int nsGIFDecoder2::EndImageFrame( } decoder->mImageContainer->EndFrameDecode(aFrameNumber, aDelayTimeout); - // if the gif is corrupt don't mark the frame as complete, as nsCSSRendering - // will happily try using it to draw a background - if (decoder->mObserver && - decoder->mImageFrame && - decoder->mGIFStruct->state != gif_error) { + if (decoder->mObserver && decoder->mImageFrame) { decoder->FlushImageData(); if (aFrameNumber == 1) {