зеркало из https://github.com/mozilla/pjs.git
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
This commit is contained in:
Родитель
0a483b237a
Коммит
260b595874
|
@ -58,6 +58,7 @@ REQUIRES = \
|
|||
imglib2 \
|
||||
browsercomps \
|
||||
gfx \
|
||||
thebes \
|
||||
widget \
|
||||
pref \
|
||||
layout \
|
||||
|
|
|
@ -50,6 +50,7 @@ REQUIRES = xpcom \
|
|||
string \
|
||||
dom \
|
||||
gfx \
|
||||
thebes \
|
||||
layout \
|
||||
widget \
|
||||
view \
|
||||
|
|
|
@ -60,6 +60,7 @@ REQUIRES = xpcom \
|
|||
necko \
|
||||
pref \
|
||||
gfx \
|
||||
thebes \
|
||||
widget \
|
||||
view \
|
||||
webshell \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -58,6 +58,7 @@ REQUIRES= \
|
|||
necko \
|
||||
dom \
|
||||
locale \
|
||||
thebes \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<gfxPattern> pat = new gfxPattern(ThebesSurface());
|
||||
pat->SetMatrix(mat);
|
||||
|
||||
ctx->NewPath();
|
||||
ctx->SetPattern(pat);
|
||||
ctx->Rectangle(dr, doSnap);
|
||||
ctx->Rectangle(destRect, doSnap);
|
||||
ctx->Fill();
|
||||
|
||||
if (doSnap)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -975,91 +975,8 @@ nsThebesRenderingContext::DrawImage(imgIContainer *aImage,
|
|||
mThebes->CurrentMatrix().GetTranslation().x, mThebes->CurrentMatrix().GetTranslation().y);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<gfxIImageFrame> imgFrame;
|
||||
aImage->GetCurrentFrame(getter_AddRefs(imgFrame));
|
||||
if (!imgFrame) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIImage> 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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<gfxIImageFrame> imgFrame;
|
||||
aImage->GetCurrentFrame(getter_AddRefs(imgFrame));
|
||||
if (!imgFrame) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIImage> 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<nsIDeviceContext> 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
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Boris Zbarsky <bzbarsky@mit.edu> (original author)
|
||||
* L. David Baron <dbaron@dbaron.org>, 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__
|
||||
|
|
|
@ -51,6 +51,7 @@ REQUIRES = xpcom \
|
|||
locale \
|
||||
content \
|
||||
gfx \
|
||||
thebes \
|
||||
widget \
|
||||
view \
|
||||
dom \
|
||||
|
|
|
@ -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<imgIContainer> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, 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<imgIContainer> 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)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, 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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -53,6 +53,7 @@ REQUIRES = xpcom \
|
|||
content \
|
||||
xul \
|
||||
gfx \
|
||||
thebes \
|
||||
widget \
|
||||
view \
|
||||
docshell \
|
||||
|
|
|
@ -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<imgIContainer> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ LIBXUL_LIBRARY = 1
|
|||
REQUIRES = xpcom \
|
||||
string \
|
||||
gfx \
|
||||
thebes \
|
||||
imglib2 \
|
||||
$(JPEG_REQUIRES) \
|
||||
$(NULL)
|
||||
|
|
Загрузка…
Ссылка в новой задаче