From e81955cfa2888a04627751128cc022328686f360 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Tue, 20 Mar 2007 00:58:20 +0000 Subject: [PATCH] When drawing images, track full source and dest regions (unclipped) or use floats, to avoid rounding problems with advanced image resizing algorithms. b=371434 r=vlad r+sr=roc git-svn-id: svn://10.0.0.236/trunk@222053 18797224-902f-48f8-a5cc-f745e15eee43 --- .../browser/components/shell/src/Makefile.in | 1 + mozilla/content/base/src/Makefile.in | 1 + mozilla/editor/libeditor/html/Makefile.in | 1 + mozilla/gfx/public/nsIImage.h | 40 ++--- mozilla/gfx/src/nsRenderingContextImpl.h | 2 + mozilla/gfx/src/shared/Makefile.in | 1 + .../gfx/src/shared/nsRenderingContextImpl.cpp | 2 + mozilla/gfx/src/thebes/nsThebesImage.cpp | 57 +++---- mozilla/gfx/src/thebes/nsThebesImage.h | 8 +- .../src/thebes/nsThebesRenderingContext.cpp | 87 +--------- mozilla/layout/base/nsCSSRendering.cpp | 2 +- mozilla/layout/base/nsLayoutUtils.cpp | 159 ++++++++++++++++++ mozilla/layout/base/nsLayoutUtils.h | 24 +++ mozilla/layout/forms/Makefile.in | 1 + mozilla/layout/generic/nsBulletFrame.cpp | 15 +- mozilla/layout/generic/nsBulletFrame.h | 3 +- mozilla/layout/generic/nsImageFrame.cpp | 151 ++++++----------- mozilla/layout/generic/nsImageFrame.h | 22 ++- .../reftests/pixel-rounding/reftest.list | 28 +-- mozilla/layout/xul/base/src/Makefile.in | 1 + .../layout/xul/base/src/nsImageBoxFrame.cpp | 29 +--- .../xul/base/src/tree/src/nsTreeBodyFrame.cpp | 20 +-- .../modules/libpr0n/decoders/jpeg/Makefile.in | 1 + 23 files changed, 335 insertions(+), 321 deletions(-) diff --git a/mozilla/browser/components/shell/src/Makefile.in b/mozilla/browser/components/shell/src/Makefile.in index 38ee852f214..170eb724692 100644 --- a/mozilla/browser/components/shell/src/Makefile.in +++ b/mozilla/browser/components/shell/src/Makefile.in @@ -58,6 +58,7 @@ REQUIRES = \ imglib2 \ browsercomps \ gfx \ + thebes \ widget \ pref \ layout \ diff --git a/mozilla/content/base/src/Makefile.in b/mozilla/content/base/src/Makefile.in index b66e4f6c3d0..a88535f5f72 100644 --- a/mozilla/content/base/src/Makefile.in +++ b/mozilla/content/base/src/Makefile.in @@ -50,6 +50,7 @@ REQUIRES = xpcom \ string \ dom \ gfx \ + thebes \ layout \ widget \ view \ diff --git a/mozilla/editor/libeditor/html/Makefile.in b/mozilla/editor/libeditor/html/Makefile.in index bc31e830187..9f476dd76b2 100644 --- a/mozilla/editor/libeditor/html/Makefile.in +++ b/mozilla/editor/libeditor/html/Makefile.in @@ -60,6 +60,7 @@ REQUIRES = xpcom \ necko \ pref \ gfx \ + thebes \ widget \ view \ webshell \ diff --git a/mozilla/gfx/public/nsIImage.h b/mozilla/gfx/public/nsIImage.h index 02e0c3462c9..9d7ed05938b 100644 --- a/mozilla/gfx/public/nsIImage.h +++ b/mozilla/gfx/public/nsIImage.h @@ -41,6 +41,7 @@ #include "nsISupports.h" #include "nsIRenderingContext.h" #include "nsRect.h" +#include "gfxRect.h" #ifdef MOZ_CAIRO_GFX class gfxASurface; @@ -79,9 +80,10 @@ typedef enum { #endif // IID for the nsIImage interface -#define NS_IIMAGE_IID \ - { 0xce91c93f, 0x532d, 0x470d, \ - { 0xbf, 0xa3, 0xc9, 0x6e, 0x56, 0x01, 0x52, 0xa4 } } +// ab6af421-9552-4d18-a3f4-a2bf9d2e44f7 +#define NS_IIMAGE_IID \ +{ 0xab6af421, 0x9552, 0x4d18, \ + { 0xa3, 0xf4, 0xa2, 0xbf, 0x9d, 0x2e, 0x44, 0xf7 } } // Interface to Images class nsIImage : public nsISupports @@ -193,36 +195,14 @@ public: */ virtual nsColorMap * GetColorMap() = 0; - /** - * BitBlit the nsIImage to a device, the source can be scaled to the dest - * @update - dwc 2/1/99 - * @param aSurface the surface to blit to - * @param aX The destination horizontal location - * @param aY The destination vertical location - * @param aWidth The destination width of the pixelmap - * @param aHeight The destination height of the pixelmap - * @return if TRUE, no errors - */ - NS_IMETHOD Draw(nsIRenderingContext &aContext, nsIDrawingSurface* aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) = 0; - /** * BitBlit the nsIImage to a device, the source and dest can be scaled - * @update - dwc 2/1/99 - * @param aSurface the surface to blit to - * @param aSX The source width of the pixelmap - * @param aSY The source vertical location - * @param aSWidth The source width of the pixelmap - * @param aSHeight The source height of the pixelmap - * @param aDX The destination horizontal location - * @param aDY The destination vertical location - * @param aDWidth The destination width of the pixelmap - * @param aDHeight The destination height of the pixelmap - * @return if TRUE, no errors + * @param aSourceRect source rectangle, in image pixels + * @param aDestRect destination rectangle, in device pixels */ - NS_IMETHOD Draw(nsIRenderingContext &aContext, nsIDrawingSurface* aSurface, - PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, - PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight) = 0; - + NS_IMETHOD Draw(nsIRenderingContext &aContext, + const gfxRect &aSourceRect, + const gfxRect &aDestRect) = 0; NS_IMETHOD DrawTile(nsIRenderingContext &aContext, nsIDrawingSurface* aSurface, diff --git a/mozilla/gfx/src/nsRenderingContextImpl.h b/mozilla/gfx/src/nsRenderingContextImpl.h index 99499e2ab38..2374bc94b77 100644 --- a/mozilla/gfx/src/nsRenderingContextImpl.h +++ b/mozilla/gfx/src/nsRenderingContextImpl.h @@ -116,7 +116,9 @@ public: NS_IMETHOD SetRightToLeftText(PRBool aIsRTL); NS_IMETHOD GetRightToLeftText(PRBool* aIsRTL); +#ifndef MOZ_CAIRO_GFX NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect & aSrcRect, const nsRect & aDestRect); +#endif NS_IMETHOD DrawTile(imgIContainer *aImage, nscoord aXOffset, nscoord aYOffset, const nsRect * aTargetRect); NS_IMETHOD GetClusterInfo(const PRUnichar *aText, diff --git a/mozilla/gfx/src/shared/Makefile.in b/mozilla/gfx/src/shared/Makefile.in index a11e887c32f..a61d5760a05 100644 --- a/mozilla/gfx/src/shared/Makefile.in +++ b/mozilla/gfx/src/shared/Makefile.in @@ -58,6 +58,7 @@ REQUIRES= \ necko \ dom \ locale \ + thebes \ $(NULL) CPPSRCS = \ diff --git a/mozilla/gfx/src/shared/nsRenderingContextImpl.cpp b/mozilla/gfx/src/shared/nsRenderingContextImpl.cpp index 04a3576c145..268398acbfa 100644 --- a/mozilla/gfx/src/shared/nsRenderingContextImpl.cpp +++ b/mozilla/gfx/src/shared/nsRenderingContextImpl.cpp @@ -306,6 +306,7 @@ nsRenderingContextImpl::GetRightToLeftText(PRBool* aIsRTL) #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" +#ifndef MOZ_CAIRO_GFX NS_IMETHODIMP nsRenderingContextImpl::DrawImage(imgIContainer *aImage, const nsRect & aSrcRect, const nsRect & aDestRect) { nsRect dr = aDestRect; @@ -395,6 +396,7 @@ NS_IMETHODIMP nsRenderingContextImpl::DrawImage(imgIContainer *aImage, const nsR return img->Draw(*this, surface, sr.x, sr.y, sr.width, sr.height, dr.x, dr.y, dr.width, dr.height); } +#endif /* [noscript] void drawTile (in imgIContainer aImage, in nscoord aXImageStart, in nscoord aYImageStart, [const] in nsRect aTargetRect); */ NS_IMETHODIMP diff --git a/mozilla/gfx/src/thebes/nsThebesImage.cpp b/mozilla/gfx/src/thebes/nsThebesImage.cpp index 7fa1afda623..538b7c46d2e 100644 --- a/mozilla/gfx/src/thebes/nsThebesImage.cpp +++ b/mozilla/gfx/src/thebes/nsThebesImage.cpp @@ -310,20 +310,11 @@ nsThebesImage::UnlockImagePixels(PRBool aMaskPixels) /* NB: These are pixels, not twips. */ NS_IMETHODIMP -nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, - PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) +nsThebesImage::Draw(nsIRenderingContext &aContext, + const gfxRect &aSourceRect, + const gfxRect &aDestRect) { - return Draw(aContext, aSurface, 0, 0, mWidth, mHeight, aX, aY, aWidth, aHeight); -} - -/* NB: These are pixels, not twips. */ -/* BUT nsRenderingContextImpl's DrawImage calls this with twips. */ -NS_IMETHODIMP -nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, - PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, - PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight) -{ - if (NS_UNLIKELY(aDWidth == 0 || aDHeight == 0)) { + if (NS_UNLIKELY(aDestRect.IsEmpty())) { NS_ERROR("nsThebesImage::Draw zero dest size - please fix caller."); return NS_OK; } @@ -333,7 +324,7 @@ nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, #if 0 fprintf (stderr, "nsThebesImage::Draw src [%d %d %d %d] dest [%d %d %d %d] tx [%f %f] dec [%d %d %d %d]\n", - aSX, aSY, aSWidth, aSHeight, aDX, aDY, aDWidth, aDHeight, + aSourceRect.pos.x, aSourceRect.pos.y, aSWidth, aSHeight, aDX, aDY, aDWidth, aDHeight, ctx->CurrentMatrix().GetTranslation().x, ctx->CurrentMatrix().GetTranslation().y, mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height); #endif @@ -349,7 +340,7 @@ nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, // otherwise ctx->SetColor(mSinglePixelColor); ctx->NewPath(); - ctx->Rectangle(gfxRect(aDX, aDY, aDWidth, aDHeight), PR_TRUE); + ctx->Rectangle(aDestRect, PR_TRUE); ctx->Fill(); return NS_OK; } @@ -362,49 +353,47 @@ nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, ctx->SetMatrix(roundedCTM); } - gfxFloat xscale = gfxFloat(aDWidth) / aSWidth; - gfxFloat yscale = gfxFloat(aDHeight) / aSHeight; + gfxFloat xscale = aDestRect.size.width / aSourceRect.size.width; + gfxFloat yscale = aDestRect.size.height / aSourceRect.size.height; + + gfxRect srcRect(aSourceRect); + gfxRect destRect(aDestRect); if (!GetIsImageComplete()) { - nsRect srcRect(aSX, aSY, aSWidth, aSHeight); - srcRect.IntersectRect(srcRect, mDecoded); + srcRect.Intersect(gfxRect(mDecoded.x, mDecoded.y, + mDecoded.width, mDecoded.height)); // This happens when mDecoded.width or height is zero. bug 368427. - if (NS_UNLIKELY(srcRect.width == 0 || srcRect.height == 0)) + if (NS_UNLIKELY(srcRect.size.width == 0 || srcRect.size.height == 0)) return NS_OK; - aDX += (PRInt32)((srcRect.x - aSX)*xscale); - aDY += (PRInt32)((srcRect.y - aSY)*yscale); + destRect.pos.x += (srcRect.pos.x - aSourceRect.pos.x)*xscale; + destRect.pos.y += (srcRect.pos.y - aSourceRect.pos.y)*yscale; // use '+ 1 - *scale' to get rid of rounding errors - aDWidth = (PRInt32)((srcRect.width)*xscale + 1 - xscale); - aDHeight = (PRInt32)((srcRect.height)*yscale + 1 - yscale); - - aSX = srcRect.x; - aSY = srcRect.y; + destRect.size.width = (srcRect.size.width)*xscale + 1 - xscale; + destRect.size.height = (srcRect.size.height)*yscale + 1 - yscale; } // Reject over-wide or over-tall images. - if (!AllowedImageSize(aDWidth, aDHeight)) + if (!AllowedImageSize(destRect.size.width, destRect.size.height)) return NS_ERROR_FAILURE; - gfxRect dr(aDX, aDY, aDWidth, aDHeight); - gfxMatrix mat; - mat.Translate(gfxPoint(aSX, aSY)); + mat.Translate(srcRect.pos); mat.Scale(1.0/xscale, 1.0/yscale); - /* Translate the start point of the image (the aSX,aSY point) + /* Translate the start point of the image (srcRect.pos) * to coincide with the destination rectangle origin */ - mat.Translate(gfxPoint(-aDX, -aDY)); + mat.Translate(-destRect.pos); nsRefPtr pat = new gfxPattern(ThebesSurface()); pat->SetMatrix(mat); ctx->NewPath(); ctx->SetPattern(pat); - ctx->Rectangle(dr, doSnap); + ctx->Rectangle(destRect, doSnap); ctx->Fill(); if (doSnap) diff --git a/mozilla/gfx/src/thebes/nsThebesImage.h b/mozilla/gfx/src/thebes/nsThebesImage.h index 55ded046a59..663810c74e2 100644 --- a/mozilla/gfx/src/thebes/nsThebesImage.h +++ b/mozilla/gfx/src/thebes/nsThebesImage.h @@ -73,12 +73,8 @@ public: virtual nsColorMap *GetColorMap(); NS_IMETHOD Draw(nsIRenderingContext &aContext, - nsIDrawingSurface *aSurface, - PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight); - NS_IMETHOD Draw(nsIRenderingContext &aContext, - nsIDrawingSurface *aSurface, - PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, - PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight); + const gfxRect &aSourceRect, + const gfxRect &aDestRect); NS_IMETHOD DrawTile(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, diff --git a/mozilla/gfx/src/thebes/nsThebesRenderingContext.cpp b/mozilla/gfx/src/thebes/nsThebesRenderingContext.cpp index a8166eebd98..8310f51ac11 100644 --- a/mozilla/gfx/src/thebes/nsThebesRenderingContext.cpp +++ b/mozilla/gfx/src/thebes/nsThebesRenderingContext.cpp @@ -975,91 +975,8 @@ nsThebesRenderingContext::DrawImage(imgIContainer *aImage, mThebes->CurrentMatrix().GetTranslation().x, mThebes->CurrentMatrix().GetTranslation().y); #endif - nsCOMPtr imgFrame; - aImage->GetCurrentFrame(getter_AddRefs(imgFrame)); - if (!imgFrame) return NS_ERROR_FAILURE; - - nsCOMPtr img(do_GetInterface(imgFrame)); - if (!img) return NS_ERROR_FAILURE; - - // For Bug 87819 - // imgFrame may want image to start at different position, so adjust - nsIntRect pxImgFrameRect; - imgFrame->GetRect(pxImgFrameRect); - - // twSrcRect is always in appunits (twips), - // and has nothing to do with the current transform (it's a region - // of the image) - double p2a = nsIDeviceContext::AppUnitsPerCSSPixel(); - nsIntRect pxSr; - pxSr.x = NSAppUnitsToIntPixels(twSrcRect.x, p2a); - pxSr.y = NSAppUnitsToIntPixels(twSrcRect.y, p2a); - pxSr.width = NSAppUnitsToIntPixels(twSrcRect.XMost(), p2a) - pxSr.x; - pxSr.height = NSAppUnitsToIntPixels(twSrcRect.YMost(), p2a) - pxSr.y; - - // the dest rect is affected by the current transform; that'll be - // handled by Image::Draw(), when we actually set up the rectangle. - nsIntRect pxDr; - pxDr.x = FROM_TWIPS_INT(twDestRect.x); - pxDr.y = FROM_TWIPS_INT(twDestRect.y); - pxDr.width = FROM_TWIPS_INT(twDestRect.XMost()) - pxDr.x; - pxDr.height = FROM_TWIPS_INT(twDestRect.YMost()) - pxDr.y; - - // If we were asked to draw a 0-width or 0-height image, - // as either the src or dst, just bail; we can't do anything - // useful with this. - if (pxSr.width == 0 || pxSr.height == 0 || - pxDr.width == 0 || pxDr.height == 0) - { - return NS_OK; - } - - if (pxImgFrameRect.x > 0) { - pxSr.x -= pxImgFrameRect.x; - - nscoord scaled_x = pxSr.x; - if (pxDr.width != pxSr.width) { - PRFloat64 scale_ratio = PRFloat64(pxDr.width) / PRFloat64(pxSr.width); - scaled_x = NSToCoordRound(scaled_x * scale_ratio); - } - - if (pxSr.x < 0) { - pxDr.x -= scaled_x; - pxSr.width += pxSr.x; - pxDr.width += scaled_x; - if (pxSr.width <= 0 || pxDr.width <= 0) - return NS_OK; - pxSr.x = 0; - } else if (pxSr.x > pxImgFrameRect.width) { - return NS_OK; - } - } - - if (pxImgFrameRect.y > 0) { - pxSr.y -= pxImgFrameRect.y; - - nscoord scaled_y = pxSr.y; - if (pxDr.height != pxSr.height) { - PRFloat64 scale_ratio = PRFloat64(pxDr.height) / PRFloat64(pxSr.height); - scaled_y = NSToCoordRound(scaled_y * scale_ratio); - } - - if (pxSr.y < 0) { - pxDr.y -= scaled_y; - pxSr.height += pxSr.y; - pxDr.height += scaled_y; - if (pxSr.height <= 0 || pxDr.height <= 0) - return NS_OK; - pxSr.y = 0; - } else if (pxSr.y > pxImgFrameRect.height) { - return NS_OK; - } - } - - return img->Draw(*this, mDrawingSurface, - pxSr.x, pxSr.y, - pxSr.width, pxSr.height, - pxDr.x, pxDr.y, pxDr.width, pxDr.height); + NS_NOTREACHED("DrawImage should no longer be called with thebes"); + return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP diff --git a/mozilla/layout/base/nsCSSRendering.cpp b/mozilla/layout/base/nsCSSRendering.cpp index 5a32b5a3e13..941bececf2f 100644 --- a/mozilla/layout/base/nsCSSRendering.cpp +++ b/mozilla/layout/base/nsCSSRendering.cpp @@ -3197,7 +3197,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, if (sourceRect.XMost() <= tileWidth && sourceRect.YMost() <= tileHeight) { // The entire drawRect is contained inside a single tile; just // draw the corresponding part of the image once. - aRenderingContext.DrawImage(image, sourceRect, drawRect); + nsLayoutUtils::DrawImage(&aRenderingContext, image, absTileRect, drawRect); } else { aRenderingContext.DrawTile(image, absTileRect.x, absTileRect.y, &drawRect); } diff --git a/mozilla/layout/base/nsLayoutUtils.cpp b/mozilla/layout/base/nsLayoutUtils.cpp index aa5b8262c5f..69a267a3f3d 100644 --- a/mozilla/layout/base/nsLayoutUtils.cpp +++ b/mozilla/layout/base/nsLayoutUtils.cpp @@ -60,6 +60,11 @@ #include "nsFrameManager.h" #include "nsBlockFrame.h" #include "nsBidiPresUtils.h" +#include "gfxIImageFrame.h" +#include "imgIContainer.h" +#include "gfxRect.h" +#include "nsIImage.h" +#include "nsIInterfaceRequestorUtils.h" #ifdef MOZ_SVG_FOREIGNOBJECT #include "nsSVGForeignObjectFrame.h" @@ -1853,3 +1858,157 @@ nsLayoutUtils::GetClosestLayer(nsIFrame* aFrame) return layer; return aFrame->GetPresContext()->PresShell()->FrameManager()->GetRootFrame(); } + +/* static */ nsresult +nsLayoutUtils::DrawImage(nsIRenderingContext* aRenderingContext, + imgIContainer* aImage, + const nsRect& aDestRect, + const nsRect& aDirtyRect, + const nsRect* aSourceRect) +{ +#ifdef MOZ_CAIRO_GFX + nsRect dirtyRect; + dirtyRect.IntersectRect(aDirtyRect, aDestRect); + if (dirtyRect.IsEmpty()) + return NS_OK; + + nsCOMPtr imgFrame; + aImage->GetCurrentFrame(getter_AddRefs(imgFrame)); + if (!imgFrame) return NS_ERROR_FAILURE; + + nsCOMPtr img(do_GetInterface(imgFrame)); + if (!img) return NS_ERROR_FAILURE; + + // twSrcRect is always in appunits (twips), + // and has nothing to do with the current transform (it's a region + // of the image) + gfxRect pxSrc; + if (aSourceRect) { + PRInt32 p2a = nsIDeviceContext::AppUnitsPerCSSPixel(); + pxSrc.pos.x = NSAppUnitsToFloatPixels(aSourceRect->x, p2a); + pxSrc.pos.y = NSAppUnitsToFloatPixels(aSourceRect->y, p2a); + pxSrc.size.width = NSAppUnitsToFloatPixels(aSourceRect->width, p2a); + pxSrc.size.height = NSAppUnitsToFloatPixels(aSourceRect->height, p2a); + } else { + pxSrc.pos.x = pxSrc.pos.y = 0.0; + PRInt32 w = 0, h = 0; + aImage->GetWidth(&w); + aImage->GetHeight(&h); + pxSrc.size.width = gfxFloat(w); + pxSrc.size.height = gfxFloat(h); + } + + nsCOMPtr dc; + aRenderingContext->GetDeviceContext(*getter_AddRefs(dc)); + PRInt32 d2a = dc->AppUnitsPerDevPixel(); + + // the dest rect is affected by the current transform; that'll be + // handled by Image::Draw(), when we actually set up the rectangle. + + // Snap the edges of where layout wants the image to the nearest + // pixel, but then convert back to gfxFloats for the rest of the math. + gfxRect pxDest; + { + nsIntRect r; + r.x = NSAppUnitsToIntPixels(aDestRect.x, d2a); + r.y = NSAppUnitsToIntPixels(aDestRect.y, d2a); + r.width = NSAppUnitsToIntPixels(aDestRect.XMost(), d2a) - r.x; + r.height = NSAppUnitsToIntPixels(aDestRect.YMost(), d2a) - r.y; + pxDest.pos.x = gfxFloat(r.x); + pxDest.pos.y = gfxFloat(r.y); + pxDest.size.width = gfxFloat(r.width); + pxDest.size.height = gfxFloat(r.height); + } + + // And likewise for the dirty rect. (Is should be OK to round to + // nearest rather than outwards, since any dirty rects coming from the + // OS should be on pixel boundaries; the rest is other things it's + // been intersected with, and we should be rounding those consistently.) + gfxRect pxDirty; + { + nsIntRect r; + r.x = NSAppUnitsToIntPixels(aDirtyRect.x, d2a); + r.y = NSAppUnitsToIntPixels(aDirtyRect.y, d2a); + r.width = NSAppUnitsToIntPixels(aDirtyRect.XMost(), d2a) - r.x; + r.height = NSAppUnitsToIntPixels(aDirtyRect.YMost(), d2a) - r.y; + pxDirty.pos.x = gfxFloat(r.x); + pxDirty.pos.y = gfxFloat(r.y); + pxDirty.size.width = gfxFloat(r.width); + pxDirty.size.height = gfxFloat(r.height); + } + + // Reduce the src rect to what's needed for the dirty rect. + if (pxDirty.size.width != pxDest.size.width) { + const gfxFloat ratio = pxSrc.size.width / pxDest.size.width; + pxSrc.pos.x += (pxDirty.pos.x - pxDest.pos.x) * ratio; + pxSrc.size.width = pxDirty.size.width * ratio; + } + if (pxDirty.size.height != pxDest.size.height) { + const gfxFloat ratio = pxSrc.size.height / pxDest.size.height; + pxSrc.pos.y += (pxDirty.pos.y - pxDest.pos.y) * ratio; + pxSrc.size.height = pxDirty.size.height * ratio; + } + + // If we were asked to draw a 0-width or 0-height image, + // as either the src or dst, just bail; we can't do anything + // useful with this. + if (pxSrc.IsEmpty() || pxDirty.IsEmpty()) + { + return NS_OK; + } + + // For Bug 87819 + // imgFrame may want image to start at different position, so adjust + nsIntRect pxImgFrameRect; + imgFrame->GetRect(pxImgFrameRect); + + if (pxImgFrameRect.x > 0) { + pxSrc.pos.x -= gfxFloat(pxImgFrameRect.x); + + gfxFloat scaled_x = pxSrc.pos.x; + if (pxDirty.size.width != pxSrc.size.width) { + scaled_x = scaled_x * (pxDirty.size.width / pxSrc.size.width); + } + + if (pxSrc.pos.x < 0.0) { + pxDirty.pos.x -= scaled_x; + pxSrc.size.width += pxSrc.pos.x; + pxDirty.size.width += scaled_x; + if (pxSrc.size.width <= 0.0 || pxDirty.size.width <= 0.0) + return NS_OK; + pxSrc.pos.x = 0.0; + } + } + if (pxSrc.pos.x > gfxFloat(pxImgFrameRect.width)) { + return NS_OK; + } + + if (pxImgFrameRect.y > 0) { + pxSrc.pos.y -= gfxFloat(pxImgFrameRect.y); + + gfxFloat scaled_y = pxSrc.pos.y; + if (pxDirty.size.height != pxSrc.size.height) { + scaled_y = scaled_y * (pxDirty.size.height / pxSrc.size.height); + } + + if (pxSrc.pos.y < 0.0) { + pxDirty.pos.y -= scaled_y; + pxSrc.size.height += pxSrc.pos.y; + pxDirty.size.height += scaled_y; + if (pxSrc.size.height <= 0.0 || pxDirty.size.height <= 0.0) + return NS_OK; + pxSrc.pos.y = 0.0; + } + } + if (pxSrc.pos.y > gfxFloat(pxImgFrameRect.height)) { + return NS_OK; + } + + return img->Draw(*aRenderingContext, pxSrc, pxDirty); +#else + /* + * If somebody wants non-cairo GFX to work again, they could write + * appropriate code to call nsIRenderingContext::DrawImage here + */ +#endif +} diff --git a/mozilla/layout/base/nsLayoutUtils.h b/mozilla/layout/base/nsLayoutUtils.h index 73074b0909f..63a25750e68 100644 --- a/mozilla/layout/base/nsLayoutUtils.h +++ b/mozilla/layout/base/nsLayoutUtils.h @@ -20,6 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Boris Zbarsky (original author) + * L. David Baron , Mozilla Corporation * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -584,6 +586,28 @@ public: * going away, so this is a cleaner definition. */ static nsIFrame* GetClosestLayer(nsIFrame* aFrame); + + /** + * Draw a single image. + * @param aImage The image. + * @param aRenderingContext Where to draw the image, set up with an + * appropriate scale and transform for drawing in + * app units (aDestRect). + * @param aDestRect Where to draw the image (app units). + * @param aDirtyRect Draw only within this region (rounded to the + * nearest pixel); the intersection of + * invalidation and clipping. + * @param aSourceRect If null, draw the entire image so it fits in + * aDestRect. If non-null, the subregion of the + * image that should be drawn (in app units, such + * that converting it to CSS pixels yields image + * pixels). + */ + static nsresult DrawImage(nsIRenderingContext* aRenderingContext, + imgIContainer* aImage, + const nsRect& aDestRect, + const nsRect& aDirtyRect, + const nsRect* aSourceRect = nsnull); }; #endif // nsLayoutUtils_h__ diff --git a/mozilla/layout/forms/Makefile.in b/mozilla/layout/forms/Makefile.in index 31a0ef470aa..38ae2f59552 100644 --- a/mozilla/layout/forms/Makefile.in +++ b/mozilla/layout/forms/Makefile.in @@ -51,6 +51,7 @@ REQUIRES = xpcom \ locale \ content \ gfx \ + thebes \ widget \ view \ dom \ diff --git a/mozilla/layout/generic/nsBulletFrame.cpp b/mozilla/layout/generic/nsBulletFrame.cpp index 80f02c2b02f..3867ce228e4 100644 --- a/mozilla/layout/generic/nsBulletFrame.cpp +++ b/mozilla/layout/generic/nsBulletFrame.cpp @@ -195,7 +195,7 @@ void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect) { NS_STATIC_CAST(nsBulletFrame*, mFrame)-> - PaintBullet(*aCtx, aBuilder->ToReferenceFrame(mFrame)); + PaintBullet(*aCtx, aBuilder->ToReferenceFrame(mFrame), aDirtyRect); } NS_IMETHODIMP @@ -212,7 +212,8 @@ nsBulletFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } void -nsBulletFrame::PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt) +nsBulletFrame::PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt, + const nsRect& aDirtyRect) { const nsStyleList* myList = GetStyleList(); PRUint8 listStyleType = myList->mListStyleType; @@ -225,11 +226,11 @@ nsBulletFrame::PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt) nsCOMPtr imageCon; mImageRequest->GetImage(getter_AddRefs(imageCon)); if (imageCon) { - nsRect innerArea(0, 0, - mRect.width - (mPadding.left + mPadding.right), - mRect.height - (mPadding.top + mPadding.bottom)); - nsRect dest(mPadding.left, mPadding.top, innerArea.width, innerArea.height); - aRenderingContext.DrawImage(imageCon, innerArea, dest + aPt); + nsRect dest(mPadding.left, mPadding.top, + mRect.width - (mPadding.left + mPadding.right), + mRect.height - (mPadding.top + mPadding.bottom)); + nsLayoutUtils::DrawImage(&aRenderingContext, imageCon, + dest + aPt, aDirtyRect); return; } } diff --git a/mozilla/layout/generic/nsBulletFrame.h b/mozilla/layout/generic/nsBulletFrame.h index cda1d2e8249..947a8f89ff6 100644 --- a/mozilla/layout/generic/nsBulletFrame.h +++ b/mozilla/layout/generic/nsBulletFrame.h @@ -99,7 +99,8 @@ public: PRBool GetListItemText(const nsStyleList& aStyleList, nsString& aResult); - void PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt); + void PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt, + const nsRect& aDirtyRect); protected: void GetDesiredSize(nsPresContext* aPresContext, diff --git a/mozilla/layout/generic/nsImageFrame.cpp b/mozilla/layout/generic/nsImageFrame.cpp index c90c9165e88..3db68eee280 100644 --- a/mozilla/layout/generic/nsImageFrame.cpp +++ b/mozilla/layout/generic/nsImageFrame.cpp @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * L. David Baron , Mozilla Corporation * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -308,8 +309,10 @@ nsImageFrame::Init(nsIContent* aContent, } PRBool -nsImageFrame::RecalculateTransform(imgIContainer* aImage) +nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage) { + NS_PRECONDITION(aImage, "null image"); + PRBool intrinsicSizeChanged = PR_FALSE; if (aImage) { @@ -324,6 +327,12 @@ nsImageFrame::RecalculateTransform(imgIContainer* aImage) } } + return intrinsicSizeChanged; +} + +void +nsImageFrame::RecalculateTransform() +{ // In any case, we need to translate this over appropriately. Set // translation _before_ setting scaling so that it does not get // scaled! @@ -331,8 +340,9 @@ nsImageFrame::RecalculateTransform(imgIContainer* aImage) // XXXbz does this introduce rounding errors because of the cast to // float? Should we just manually add that stuff in every time // instead? - mTransform.SetToTranslate(float(mBorderPadding.left), - float(mBorderPadding.top - GetContinuationOffset())); + nsRect innerArea = GetInnerArea(); + mTransform.SetToTranslate(float(innerArea.x), + float(innerArea.y - GetContinuationOffset())); // Set the scale factors if (mIntrinsicSize.width != 0 && mIntrinsicSize.height != 0 && @@ -340,8 +350,6 @@ nsImageFrame::RecalculateTransform(imgIContainer* aImage) mTransform.AddScale(float(mComputedSize.width) / float(mIntrinsicSize.width), float(mComputedSize.height) / float(mIntrinsicSize.height)); } - - return intrinsicSizeChanged; } /* @@ -518,7 +526,7 @@ nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage) return NS_OK; } - RecalculateTransform(aImage); + UpdateIntrinsicSize(aImage); // Now we need to reflow if we have an unconstrained size and have // already gotten the initial reflow @@ -577,6 +585,8 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest, } } + // XXX We really need to round this out, now that we're doing better + // image scaling! nsRect r = SourceRectToDest(*aRect); #ifdef DEBUG_decode printf("Source rect (%d,%d,%d,%d) -> invalidate dest rect (%d,%d,%d,%d)\n", @@ -620,7 +630,7 @@ nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsCOMPtr imageContainer; aRequest->GetImage(getter_AddRefs(imageContainer)); NS_ASSERTION(imageContainer, "Successful load with no container?"); - intrinsicSizeChanged = RecalculateTransform(imageContainer); + intrinsicSizeChanged = UpdateIntrinsicSize(imageContainer); } else { // Have to size to 0,0 so that GetDesiredSize recalculates the size @@ -686,7 +696,7 @@ nsImageFrame::EnsureIntrinsicSize(nsPresContext* aPresContext) } if (currentContainer) { - RecalculateTransform(currentContainer); + UpdateIntrinsicSize(currentContainer); } else { // image request is null or image size not known, probably an // invalid image specified @@ -698,7 +708,6 @@ nsImageFrame::EnsureIntrinsicSize(nsPresContext* aPresContext) mIntrinsicSize.SizeTo(nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH))), nsPresContext::CSSPixelsToAppUnits(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH)))); } - RecalculateTransform(nsnull); } } } @@ -721,36 +730,18 @@ nsImageFrame::ComputeSize(nsIRenderingContext *aRenderingContext, nsRect nsImageFrame::GetInnerArea() const { - nsRect r; - r.x = mBorderPadding.left; - r.y = GetPrevInFlow() ? 0 : mBorderPadding.top; - r.width = mRect.width - mBorderPadding.left - mBorderPadding.right; - r.height = mRect.height - - (GetPrevInFlow() ? 0 : mBorderPadding.top) - - (GetNextInFlow() ? 0 : mBorderPadding.bottom); - return r; + return GetContentRect() - GetPosition(); } // get the offset into the content area of the image where aImg starts if it is a continuation. nscoord -nsImageFrame::GetContinuationOffset(nscoord* aWidth) const +nsImageFrame::GetContinuationOffset() const { nscoord offset = 0; - if (aWidth) { - *aWidth = 0; - } - - if (GetPrevInFlow()) { - for (nsIFrame* prevInFlow = GetPrevInFlow() ; prevInFlow; prevInFlow = prevInFlow->GetPrevInFlow()) { - nsRect rect = prevInFlow->GetRect(); - if (aWidth) { - *aWidth = rect.width; - } - offset += rect.height; - } - offset -= mBorderPadding.top; - offset = PR_MAX(0, offset); + for (nsIFrame *f = GetPrevInFlow(); f; f = f->GetPrevInFlow()) { + offset += f->GetContentRect().height; } + NS_ASSERTION(offset >= 0, "bogus GetContentRect"); return offset; } @@ -810,26 +801,21 @@ nsImageFrame::Reflow(nsPresContext* aPresContext, mState |= IMAGE_GOTINITIALREFLOW; } - // Set our borderpadding so that if GetDesiredSize has to recalc the - // transform it can. - mBorderPadding = aReflowState.mComputedBorderPadding; - - nsSize newSize(aReflowState.ComputedWidth(), aReflowState.mComputedHeight); - if (mComputedSize != newSize) { - mComputedSize = newSize; - RecalculateTransform(nsnull); - } + mComputedSize = + nsSize(aReflowState.ComputedWidth(), aReflowState.mComputedHeight); + RecalculateTransform(); aMetrics.width = mComputedSize.width; aMetrics.height = mComputedSize.height; // add borders and padding - aMetrics.width += mBorderPadding.left + mBorderPadding.right; - aMetrics.height += mBorderPadding.top + mBorderPadding.bottom; + aMetrics.width += aReflowState.mComputedBorderPadding.LeftRight(); + aMetrics.height += aReflowState.mComputedBorderPadding.TopBottom(); if (GetPrevInFlow()) { - nscoord y = GetContinuationOffset(&aMetrics.width); - aMetrics.height -= y + mBorderPadding.top; + aMetrics.width = GetPrevInFlow()->GetSize().width; + nscoord y = GetContinuationOffset(); + aMetrics.height -= y + aReflowState.mComputedBorderPadding.top; aMetrics.height = PR_MAX(0, aMetrics.height); } @@ -1028,6 +1014,7 @@ struct nsRecessedBorder : public nsStyleBorder { void nsImageFrame::DisplayAltFeedback(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, imgIRequest* aRequest, nsPoint aPt) { @@ -1084,11 +1071,10 @@ nsImageFrame::DisplayAltFeedback(nsIRenderingContext& aRenderingContext, } if (imgCon) { // draw it - nsRect source(0,0,size,size); nsRect dest((vis->mDirection == NS_STYLE_DIRECTION_RTL) ? inner.XMost() - size : inner.x, inner.y, size, size); - aRenderingContext.DrawImage(imgCon, source, dest); + nsLayoutUtils::DrawImage(&aRenderingContext, imgCon, dest, aDirtyRect); iconUsed = PR_TRUE; } } @@ -1134,6 +1120,7 @@ static void PaintAltFeedback(nsIFrame* aFrame, nsIRenderingContext* aCtx, { nsImageFrame* f = NS_STATIC_CAST(nsImageFrame*, aFrame); f->DisplayAltFeedback(*aCtx, + aDirtyRect, IMAGE_OK(f->GetContent()->IntrinsicState(), PR_TRUE) ? nsImageFrame::gIconLoad->mLoadingImage : nsImageFrame::gIconLoad->mBrokenImage, @@ -1190,64 +1177,19 @@ nsImageFrame::PaintImage(nsIRenderingContext& aRenderingContext, nsPoint aPt, { // Render the image into our content area (the area inside // the borders and padding) + NS_ASSERTION(GetInnerArea().width == mComputedSize.width, "bad width"); nsRect inner = GetInnerArea() + aPt; - nsRect paintArea(inner); + nsRect clip; + clip.IntersectRect(inner, aDirtyRect); - nscoord offsetY = 0; + nsRect dest(inner.TopLeft(), mComputedSize); + dest.y -= GetContinuationOffset(); - // if the image is split account for y-offset - if (GetPrevInFlow()) { - offsetY = GetContinuationOffset(); - } - - if (mIntrinsicSize == mComputedSize) { - // Find the actual rect to be painted to in the rendering context - paintArea.IntersectRect(paintArea, aDirtyRect); - - // Rect in the image to paint - nsRect r(paintArea.x - inner.x, - paintArea.y - inner.y + offsetY, - paintArea.width, - paintArea.height); - - aRenderingContext.DrawImage(aImage, r, paintArea); - } else { - // The computed size is the total size of all the continuations, - // including ourselves. Note that we're basically inverting - // mTransform here (would it too much to ask for - // nsTransform2D::Invert?), since we need to convert from - // rendering context coords to image coords... - nsTransform2D trans; - trans.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)), - (float(mIntrinsicSize.height) / float(mComputedSize.height))); - - // XXXbz it looks like we should take - // IntersectRect(paintArea, aDirtyRect) here too, but things - // get very weird if I do that .... - // paintArea.IntersectRect(paintArea, aDirtyRect); - - // dirty rect in image our coord size... - nsRect r(paintArea.x - inner.x, - paintArea.y - inner.y + offsetY, - paintArea.width, - paintArea.height); - - // Transform that to image coords - trans.TransformCoord(&r.x, &r.y, &r.width, &r.height); - -#ifdef DEBUG_decode - printf("IF draw src (%d,%d,%d,%d) -> dst (%d,%d,%d,%d)\n", - r.x, r.y, r.width, r.height, paintArea.x, paintArea.y, - paintArea.width, paintArea.height); -#endif - - aRenderingContext.DrawImage(aImage, r, paintArea); - } + nsLayoutUtils::DrawImage(&aRenderingContext, aImage, dest, clip); nsPresContext* presContext = GetPresContext(); nsImageMap* map = GetImageMap(presContext); if (nsnull != map) { - nsRect inner = GetInnerArea() + aPt; aRenderingContext.PushState(); aRenderingContext.SetColor(NS_RGB(0, 0, 0)); aRenderingContext.SetLineStyle(nsLineStyle_kDotted); @@ -1693,6 +1635,19 @@ mRect.height); } #endif +PRIntn +nsImageFrame::GetSkipSides() const +{ + PRIntn skip = 0; + if (nsnull != GetPrevInFlow()) { + skip |= 1 << NS_SIDE_TOP; + } + if (nsnull != GetNextInFlow()) { + skip |= 1 << NS_SIDE_BOTTOM; + } + return skip; +} + NS_IMETHODIMP nsImageFrame::GetIntrinsicImageSize(nsSize& aSize) { diff --git a/mozilla/layout/generic/nsImageFrame.h b/mozilla/layout/generic/nsImageFrame.h index a402c366a6c..fa07fda14cb 100644 --- a/mozilla/layout/generic/nsImageFrame.h +++ b/mozilla/layout/generic/nsImageFrame.h @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * L. David Baron , Mozilla Corporation * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -140,6 +141,8 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; #endif + virtual PRIntn GetSkipSides() const; + NS_IMETHOD GetImageMap(nsPresContext *aPresContext, nsIImageMap **aImageMap); NS_IMETHOD GetIntrinsicImageSize(nsSize& aSize); @@ -161,6 +164,7 @@ public: nsStyleContext* aStyleContext); void DisplayAltFeedback(nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, imgIRequest* aRequest, nsPoint aPt); @@ -238,19 +242,21 @@ private: inline void GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup); - nscoord GetContinuationOffset(nscoord* aWidth = 0) const; + nscoord GetContinuationOffset() const; void GetDocumentCharacterSet(nsACString& aCharset) const; /** - * This function will recalculate mTransform. If a non-null image - * is passed in, mIntrinsicSize will be recalculated from the image - * size. Otherwise, mIntrinsicSize will not be touched. + * Recalculate mIntrinsicSize from the image. * - * @return PR_TRUE if aImage is non-null and its size did _not_ + * @return whether aImage's size did _not_ * match our previous intrinsic size - * @return PR_FALSE otherwise */ - PRBool RecalculateTransform(imgIContainer* aImage); + PRBool UpdateIntrinsicSize(imgIContainer* aImage); + + /** + * This function will recalculate mTransform. + */ + void RecalculateTransform(); /** * Helper functions to check whether the request or image container @@ -274,8 +280,6 @@ private: nsSize mIntrinsicSize; nsTransform2D mTransform; - nsMargin mBorderPadding; - static nsIIOService* sIOService; /* loading / broken image icon support */ diff --git a/mozilla/layout/reftests/pixel-rounding/reftest.list b/mozilla/layout/reftests/pixel-rounding/reftest.list index b1cd8751eed..d6effa816b9 100644 --- a/mozilla/layout/reftests/pixel-rounding/reftest.list +++ b/mozilla/layout/reftests/pixel-rounding/reftest.list @@ -51,33 +51,33 @@ fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == border-top-6.html border-top-10-ref.htm != background-image-base.html background-image-height-10-ref.html -fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == background-image-height-4.html background-image-base.html # bug 371316 + bug 371434 -fails-if(MOZ_WIDGET_TOOLKIT!="cocoa") == background-image-height-5.html background-image-height-10-ref.html # bug 371316 + bug 371434 +== background-image-height-4.html background-image-base.html +== background-image-height-5.html background-image-height-10-ref.html == background-image-height-6.html background-image-height-10-ref.html != background-image-base.html background-image-top-10-ref.html == background-image-top-4.html background-image-base.html == background-image-top-5.html background-image-top-10-ref.html == background-image-top-6.html background-image-top-10-ref.html != background-image-base.html background-image-width-10-ref.html -fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == background-image-width-4.html background-image-base.html # bug 371316 + bug 371434 -fails-if(MOZ_WIDGET_TOOLKIT!="cocoa") == background-image-width-5.html background-image-width-10-ref.html # bug 371316 + bug 371434 +== background-image-width-4.html background-image-base.html +== background-image-width-5.html background-image-width-10-ref.html == background-image-width-6.html background-image-width-10-ref.html != background-image-base.html background-image-left-10-ref.html == background-image-left-4.html background-image-base.html == background-image-left-5.html background-image-left-10-ref.html == background-image-left-6.html background-image-left-10-ref.html -fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == background-image-top-height-4.html background-image-height-4.html # bug 371316 + bug 371434 -random-if(MOZ_WIDGET_TOOLKIT=="gtk2") fails-if(MOZ_WIDGET_TOOLKIT=="windows") == background-image-top-height-5.html background-image-height-5.html # bug 371316 + bug 371434 +== background-image-top-height-4.html background-image-height-4.html +== background-image-top-height-5.html background-image-height-5.html == background-image-top-height-6.html background-image-height-6.html -fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == background-image-left-width-4.html background-image-width-4.html # bug 371316 + bug 371434 -random-if(MOZ_WIDGET_TOOLKIT=="gtk2") fails-if(MOZ_WIDGET_TOOLKIT=="windows") == background-image-left-width-5.html background-image-width-5.html # bug 371316 + bug 371434 +== background-image-left-width-4.html background-image-width-4.html +== background-image-left-width-5.html background-image-width-5.html == background-image-left-width-6.html background-image-width-6.html -fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == background-image-height-top-4.html background-image-height-4.html # bug 371316 + bug 371434 -random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == background-image-height-top-5.html background-image-height-5.html # bug 371316 + bug 371434 -random-if(MOZ_WIDGET_TOOLKIT=="gtk2") fails-if(MOZ_WIDGET_TOOLKIT=="windows") == background-image-height-top-6.html background-image-height-6.html # bug 371316 + bug 371434 -fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == background-image-width-left-4.html background-image-width-4.html # bug 371316 + bug 371434 -random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == background-image-width-left-5.html background-image-width-5.html # bug 371316 + bug 371434 -random-if(MOZ_WIDGET_TOOLKIT=="gtk2") fails-if(MOZ_WIDGET_TOOLKIT=="windows") == background-image-width-left-6.html background-image-width-6.html # bug 371316 + bug 371434 +== background-image-height-top-4.html background-image-height-4.html +== background-image-height-top-5.html background-image-height-5.html +== background-image-height-top-6.html background-image-height-6.html +== background-image-width-left-4.html background-image-width-4.html +== background-image-width-left-5.html background-image-width-5.html +== background-image-width-left-6.html background-image-width-6.html # These all fail due to bug 155955, and maybe also bug 371180, plus a diff --git a/mozilla/layout/xul/base/src/Makefile.in b/mozilla/layout/xul/base/src/Makefile.in index dd08ed1a805..b42d2a73f86 100644 --- a/mozilla/layout/xul/base/src/Makefile.in +++ b/mozilla/layout/xul/base/src/Makefile.in @@ -53,6 +53,7 @@ REQUIRES = xpcom \ content \ xul \ gfx \ + thebes \ widget \ view \ docshell \ diff --git a/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp b/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp index a7b420516dd..964c95be721 100644 --- a/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp +++ b/mozilla/layout/xul/base/src/nsImageBoxFrame.cpp @@ -370,7 +370,8 @@ nsImageBoxFrame::PaintImage(nsIRenderingContext& aRenderingContext, return; // don't draw if the image is not dirty - if (!aDirtyRect.Intersects(rect)) + nsRect dirty; + if (!dirty.IntersectRect(aDirtyRect, rect)) return; nsCOMPtr imgCon; @@ -378,30 +379,8 @@ nsImageBoxFrame::PaintImage(nsIRenderingContext& aRenderingContext, if (imgCon) { PRBool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0); - PRBool sizeMatch = hasSubRect ? - mSubRect.width == rect.width && mSubRect.height == rect.height : - mImageSize.width == rect.width && mImageSize.height == rect.height; - - if (sizeMatch) { - nsRect dest(rect); - - if (hasSubRect) - rect = mSubRect; - else { - rect.x = 0; - rect.y = 0; - } - - // XXXdwh do dirty rect intersection like the HTML image frame does, - // so that we don't always repaint the entire image! - aRenderingContext.DrawImage(imgCon, rect, dest); - } - else { - nsRect src(0, 0, mImageSize.width, mImageSize.height); - if (hasSubRect) - src = mSubRect; - aRenderingContext.DrawImage(imgCon, src, rect); - } + nsLayoutUtils::DrawImage(&aRenderingContext, imgCon, + rect, dirty, hasSubRect ? &mSubRect : nsnull); } } diff --git a/mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp b/mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp index 46175e8321f..e2a356a7718 100644 --- a/mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/mozilla/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -3218,7 +3218,8 @@ nsTreeBodyFrame::PaintTwisty(PRInt32 aRowIndex, } // Paint the image. - aRenderingContext.DrawImage(image, imageSize, r); + nsLayoutUtils::DrawImage(&aRenderingContext, image, + r, aDirtyRect, &imageSize); } } } @@ -3339,15 +3340,11 @@ nsTreeBodyFrame::PaintImage(PRInt32 aRowIndex, // Essentially, we are scaling the image as dictated by the CSS destination // height and width, and we are then clipping the scaled image by the cell // width and height. - if (destRect.width != imageDestSize.width) { - sourceRect.width = sourceRect.width * destRect.width / imageDestSize.width; - } - if (destRect.height != imageDestSize.height) { - sourceRect.height = sourceRect.height * destRect.height / imageDestSize.height; - } - - // Finally we can paint the image. - aRenderingContext.DrawImage(image, sourceRect, destRect); + nsRect clip; + clip.IntersectRect(aDirtyRect, destRect); + nsLayoutUtils::DrawImage(&aRenderingContext, image, + nsRect(destRect.TopLeft(), imageDestSize), + clip, &sourceRect); } // Update the aRemainingWidth and aCurrX values. @@ -3506,7 +3503,8 @@ nsTreeBodyFrame::PaintCheckbox(PRInt32 aRowIndex, } // Paint the image. - aRenderingContext.DrawImage(image, imageSize, r); + nsLayoutUtils::DrawImage(&aRenderingContext, image, + r, aDirtyRect, &imageSize); } } diff --git a/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in b/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in index 3db8517e404..ad9bde91326 100644 --- a/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in +++ b/mozilla/modules/libpr0n/decoders/jpeg/Makefile.in @@ -51,6 +51,7 @@ LIBXUL_LIBRARY = 1 REQUIRES = xpcom \ string \ gfx \ + thebes \ imglib2 \ $(JPEG_REQUIRES) \ $(NULL)