diff --git a/gfx/public/nsIImage.h b/gfx/public/nsIImage.h index d48cdb0af9ed..5b89413162e5 100644 --- a/gfx/public/nsIImage.h +++ b/gfx/public/nsIImage.h @@ -209,6 +209,7 @@ public: NS_IMETHOD DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect) = 0; /** diff --git a/gfx/src/gtk/nsImageGTK.cpp b/gfx/src/gtk/nsImageGTK.cpp index d9ad2d5b2389..41c39c713f1d 100644 --- a/gfx/src/gtk/nsImageGTK.cpp +++ b/gfx/src/gtk/nsImageGTK.cpp @@ -1663,6 +1663,7 @@ void nsImageGTK::TilePixmap(GdkPixmap *src, GdkPixmap *dest, NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect) { #ifdef DEBUG_TILING @@ -1715,7 +1716,7 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, return NS_OK; } - if (partial || (mAlphaDepth == 8)) { + if (partial || (mAlphaDepth == 8) || (aPadX || aPadY)) { PRInt32 aY0 = aTileRect.y - aSYOffset, aX0 = aTileRect.x - aSXOffset, aY1 = aTileRect.y + aTileRect.height, @@ -1737,8 +1738,8 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, #ifdef DEBUG_TILING printf("Warning: using slow tiling\n"); #endif - for (PRInt32 y = aY0; y < aY1; y += mHeight) - for (PRInt32 x = aX0; x < aX1; x += mWidth) + for (PRInt32 y = aY0; y < aY1; y += mHeight + aPadY) + for (PRInt32 x = aX0; x < aX1; x += mWidth + aPadX) Draw(aContext,aSurface, x,y, PR_MIN(validWidth, aX1-x), PR_MIN(validHeight, aY1-y)); diff --git a/gfx/src/gtk/nsImageGTK.h b/gfx/src/gtk/nsImageGTK.h index cdbc50fbf524..175374c362f9 100644 --- a/gfx/src/gtk/nsImageGTK.h +++ b/gfx/src/gtk/nsImageGTK.h @@ -84,6 +84,7 @@ public: NS_IMETHOD DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect); void UpdateCachedImage(); diff --git a/gfx/src/mac/nsImageMac.cpp b/gfx/src/mac/nsImageMac.cpp index a370a7536da3..cc6a7221e32e 100644 --- a/gfx/src/mac/nsImageMac.cpp +++ b/gfx/src/mac/nsImageMac.cpp @@ -1490,6 +1490,7 @@ nsImageMac::MakeIconType(PRInt32 aHeight, PRInt32 aDepth, PRBool aMask) nsresult nsImageMac::SlowTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect) { if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1) @@ -1523,8 +1524,8 @@ nsresult nsImageMac::SlowTile(nsIRenderingContext &aContext, aY1 = aTileRect.y + aTileRect.height, aX1 = aTileRect.x + aTileRect.width; - for (PRInt32 y = aY0; y < aY1; y += mHeight) - for (PRInt32 x = aX0; x < aX1; x += mWidth) + for (PRInt32 y = aY0; y < aY1; y += mHeight + aPadY) + for (PRInt32 x = aX0; x < aX1; x += mWidth + aPadX) { Draw(aContext, aSurface, 0, 0, PR_MIN(validWidth, aX1-x), PR_MIN(validHeight, aY1-y), // src coords @@ -1820,15 +1821,17 @@ nsresult nsImageMac::DrawTileQuickly(nsIRenderingContext &aContext, NS_IMETHODIMP nsImageMac::DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect) { nsresult rv = NS_ERROR_FAILURE; + PRBool padded = (aPadX || aPadY); - if (!RenderingToPrinter(aContext)) + if (!RenderingToPrinter(aContext) && !padded) rv = DrawTileQuickly(aContext, aSurface, aSXOffset, aSYOffset, aTileRect); if (NS_FAILED(rv)) - rv = SlowTile(aContext, aSurface, aSXOffset, aSYOffset, aTileRect); + rv = SlowTile(aContext, aSurface, aSXOffset, aSYOffset, aPadX, aPadY, aTileRect); return rv; } diff --git a/gfx/src/mac/nsImageMac.h b/gfx/src/mac/nsImageMac.h index 749fba7cfd60..6df80c7add96 100644 --- a/gfx/src/mac/nsImageMac.h +++ b/gfx/src/mac/nsImageMac.h @@ -82,6 +82,7 @@ public: NS_IMETHOD DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect); @@ -130,6 +131,7 @@ protected: nsresult SlowTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect); nsresult DrawTileQuickly(nsIRenderingContext &aContext, diff --git a/gfx/src/os2/nsImageOS2.cpp b/gfx/src/os2/nsImageOS2.cpp index 3466fd916e86..a63df5bf1f8a 100644 --- a/gfx/src/os2/nsImageOS2.cpp +++ b/gfx/src/os2/nsImageOS2.cpp @@ -695,6 +695,7 @@ nsImageOS2::BuildTile (HPS hpsTile, PRUint8* pImageBits, PBITMAPINFO2 pBitmapInf NS_IMETHODIMP nsImageOS2::DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect) { if (aTileRect.IsEmpty ()) @@ -703,6 +704,7 @@ NS_IMETHODIMP nsImageOS2::DrawTile(nsIRenderingContext &aContext, PRBool didTile = PR_FALSE; PRInt32 ImageWidth = mInfo->cx; PRInt32 ImageHeight = mInfo->cy; + PRBool padded = (aPadX || aPadY); // Get the scale - if greater than 1 then do slow tile which nsIDeviceContext *theDeviceContext; @@ -724,7 +726,8 @@ NS_IMETHODIMP nsImageOS2::DrawTile(nsIRenderingContext &aContext, // Can't tile with 8bit alpha masks because need access destination bitmap values if ((ImageWidth < DrawRect.width / 2 || ImageHeight < DrawRect.height / 2) && (ImageWidth <= MAX_BUFFER_WIDTH) && (ImageHeight <= MAX_BUFFER_HEIGHT) && - mAlphaDepth <= 1) + mAlphaDepth <= 1 && + !padded) { nsDrawingSurfaceOS2 *surf = (nsDrawingSurfaceOS2*) aSurface; @@ -845,9 +848,9 @@ NS_IMETHODIMP nsImageOS2::DrawTile(nsIRenderingContext &aContext, nscoord ScaledTileWidth = PR_MAX(PRInt32(ImageWidth*scale), 1); nscoord ScaledTileHeight = PR_MAX(PRInt32(ImageHeight*scale), 1); - for (PRInt32 y = y0; y < y1; y += ScaledTileHeight) + for (PRInt32 y = y0; y < y1; y += ScaledTileHeight + aPadY * scale) { - for (PRInt32 x = x0; x < x1; x += ScaledTileWidth) + for (PRInt32 x = x0; x < x1; x += ScaledTileWidth + aPadX * scale) { Draw(aContext, aSurface, 0, 0, PR_MIN(ValidRect.width, x1 - x), PR_MIN(ValidRect.height, y1 - y), diff --git a/gfx/src/os2/nsImageOS2.h b/gfx/src/os2/nsImageOS2.h index 1edd60b385bb..3231e0a6cda5 100644 --- a/gfx/src/os2/nsImageOS2.h +++ b/gfx/src/os2/nsImageOS2.h @@ -73,6 +73,7 @@ public: NS_IMETHOD DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect); NS_IMETHOD DrawToImage(nsIImage* aDstImage, nscoord aDX, nscoord aDY, diff --git a/gfx/src/shared/gfxImageFrame.cpp b/gfx/src/shared/gfxImageFrame.cpp index c5a3f74a853e..1bd4ba6606ef 100644 --- a/gfx/src/shared/gfxImageFrame.cpp +++ b/gfx/src/shared/gfxImageFrame.cpp @@ -24,17 +24,6 @@ #include "gfxImageFrame.h" #include "nsIServiceManager.h" - -/* Limit the width and height of images to (2^15 - 1) to avoid any overflows. - We know that (width * height * alpha) needs to be under 2^32. - In the event of padding being needed, we do -1 to save some extra space. - - therefore, the maxium image buffer imagelib will create is: - ((2^15 - 1) * (2^15 - 1) * 4) == 4294705156 - This is less than 2^32 so we're safe. - */ -#define SIZE_LIMIT 32767 - NS_IMPL_ISUPPORTS2(gfxImageFrame, gfxIImageFrame, nsIInterfaceRequestor) gfxImageFrame::gfxImageFrame() : @@ -64,7 +53,16 @@ NS_IMETHODIMP gfxImageFrame::Init(nscoord aX, nscoord aY, nscoord aWidth, nscoor return NS_ERROR_FAILURE; } - if (aWidth > SIZE_LIMIT || aHeight > SIZE_LIMIT) { + /* check to make sure we don't overflow a 32-bit */ + nscoord tmp = aWidth * aHeight; + if (tmp / aHeight != aWidth) { + fprintf(stderr, "erp\n"); + NS_ASSERTION(0, "width or height too large\n"); + return NS_ERROR_FAILURE; + } + tmp = tmp * 4; + if (tmp / 4 != aWidth * aHeight) { + fprintf(stderr, "erp2\n"); NS_ASSERTION(0, "width or height too large\n"); return NS_ERROR_FAILURE; } diff --git a/gfx/src/shared/nsRenderingContextImpl.cpp b/gfx/src/shared/nsRenderingContextImpl.cpp index 310641e5a4ca..c4bbb5a2e997 100644 --- a/gfx/src/shared/nsRenderingContextImpl.cpp +++ b/gfx/src/shared/nsRenderingContextImpl.cpp @@ -911,7 +911,16 @@ nsRenderingContextImpl::DrawTile(imgIContainer *aImage, GetDrawingSurface((void**)&surface); if (!surface) return NS_ERROR_FAILURE; - return img->DrawTile(*this, surface, xOffset, yOffset, dr); + /* bug 113561 - frame can be smaller than container */ + nsRect iframeRect; + iframe->GetRect(iframeRect); + PRInt32 padx = width - iframeRect.width; + PRInt32 pady = height - iframeRect.height; + + return img->DrawTile(*this, surface, + xOffset - iframeRect.x, yOffset - iframeRect.y, + padx, pady, + dr); } NS_IMETHODIMP diff --git a/gfx/src/windows/nsImageWin.cpp b/gfx/src/windows/nsImageWin.cpp index ac8d26532f5a..a3a42447b591 100644 --- a/gfx/src/windows/nsImageWin.cpp +++ b/gfx/src/windows/nsImageWin.cpp @@ -797,6 +797,7 @@ NS_IMETHODIMP nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, + PRInt32 aPadX, PRInt32 aPadY, const nsRect &aDestRect) { if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1) @@ -810,13 +811,14 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext, nsCOMPtr theDeviceContext; HDC theHDC; nscoord ScaledTileWidth,ScaledTileHeight; + PRBool padded = (aPadX || aPadY); ((nsDrawingSurfaceWin *)aSurface)->GetTECHNOLOGY(&canRaster); // We can Progressive Double Blit if we aren't printing to a printer, and // we aren't in 256 color mode, and we don't have an unoptimized 8 bit alpha. if ((canRaster != DT_RASPRINTER) && (256 != mNumPaletteColors) && - !(mAlphaDepth == 8 && !mIsOptimized)) + !(mAlphaDepth == 8 && !mIsOptimized) && !padded) if (ProgressiveDoubleBlit(aSurface, aSXOffset, aSYOffset, aDestRect)) return NS_OK; @@ -865,7 +867,7 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext, ScaledTileHeight = PR_MAX(PRInt32(mBHead->biHeight*scale), 1); // do alpha depth equal to 8 here.. this needs some special attention - if (mAlphaDepth == 8 && !mIsOptimized) { + if (mAlphaDepth == 8 && !mIsOptimized && !padded) { unsigned char *screenBits=nsnull,*adjAlpha,*adjImage,*adjScreen; HDC memDC=nsnull; HBITMAP tmpBitmap=nsnull,oldBitmap; @@ -961,8 +963,8 @@ NS_IMETHODIMP nsImageWin::DrawTile(nsIRenderingContext &aContext, // if we got to this point.. everything else failed.. and the slow blit backstop // will finish this tiling - for (y=y0;yGetWidth(&iSize.width); + image->GetHeight(&iSize.height); + nsRect iframeRect; + gfxImgFrame->GetRect(iframeRect); + if (iSize.width != iframeRect.width || + iSize.height != iframeRect.height) { + needBackgroundColor = PR_TRUE; + } } } break; diff --git a/layout/html/style/src/nsCSSRendering.cpp b/layout/html/style/src/nsCSSRendering.cpp index b909ed13b429..13448530d757 100644 --- a/layout/html/style/src/nsCSSRendering.cpp +++ b/layout/html/style/src/nsCSSRendering.cpp @@ -3020,6 +3020,17 @@ nsCSSRendering::PaintBackgroundWithSC(nsIPresContext* aPresContext, "Unknown gfxIFormats value"); needBackgroundColor = frameFormat != gfxIFormats::RGB && frameFormat != gfxIFormats::BGR; + + /* check for tiling of a image where frame smaller than container */ + nsSize iSize; + image->GetWidth(&iSize.width); + image->GetHeight(&iSize.height); + nsRect iframeRect; + gfxImgFrame->GetRect(iframeRect); + if (iSize.width != iframeRect.width || + iSize.height != iframeRect.height) { + needBackgroundColor = PR_TRUE; + } } } break;