Bug 113561 - handle tiling of images where the frame is smaller

than the container.  r=pavlov, sr=bryner
This commit is contained in:
tor%cs.brown.edu 2004-01-16 23:28:51 +00:00
Родитель 758ec01164
Коммит 6e0bbb9e6a
15 изменённых файлов: 76 добавлений и 30 удалений

Просмотреть файл

@ -209,6 +209,7 @@ public:
NS_IMETHOD DrawTile(nsIRenderingContext &aContext,
nsDrawingSurface aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset,
PRInt32 aPadX, PRInt32 aPadY,
const nsRect &aTileRect) = 0;
/**

Просмотреть файл

@ -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));

Просмотреть файл

@ -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();

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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,

Просмотреть файл

@ -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),

Просмотреть файл

@ -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,

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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<nsIDeviceContext> 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;y<y1;y+=ScaledTileHeight) {
for (x=x0;x<x1;x+=ScaledTileWidth) {
for (y=y0;y<y1;y+=ScaledTileHeight+aPadY*scale) {
for (x=x0;x<x1;x+=ScaledTileWidth+aPadX*scale) {
Draw(aContext, aSurface,
0, 0, PR_MIN(validWidth, x1-x), PR_MIN(validHeight, y1-y),
x, y, PR_MIN(destScaledWidth, x1-x), PR_MIN(destScaledHeight, y1-y));

Просмотреть файл

@ -106,6 +106,7 @@ public:
NS_IMETHOD DrawTile(nsIRenderingContext &aContext,
nsDrawingSurface aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset,
PRInt32 aPadX, PRInt32 aPadY,
const nsRect &aTileRect);
/**

Просмотреть файл

@ -1332,6 +1332,7 @@ void nsImageXlib::TilePixmap(Pixmap src, Pixmap dest, PRInt32 aSXOffset,
NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext,
nsDrawingSurface aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset,
PRInt32 aPadX, PRInt32 aPadY,
const nsRect &aTileRect)
{
if (mPendingUpdate)
@ -1382,7 +1383,7 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext,
return NS_OK;
}
if (partial || ((mAlphaDepth == 8) && mAlphaValid)) {
if (partial || ((mAlphaDepth == 8) && mAlphaValid) || (aPadX || aPadY)) {
PRInt32 aY0 = aTileRect.y - aSYOffset,
aX0 = aTileRect.x - aSXOffset,
aY1 = aTileRect.y + aTileRect.height,
@ -1394,8 +1395,8 @@ NS_IMETHODIMP nsImageXlib::DrawTile(nsIRenderingContext &aContext,
((nsRenderingContextXlib&)aContext).SetClipRectInPixels(
aTileRect, nsClipCombine_kIntersect, clipState);
((nsRenderingContextXlib&)aContext).UpdateGC();
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));

Просмотреть файл

@ -78,6 +78,7 @@ public:
NS_IMETHOD DrawTile(nsIRenderingContext &aContext,
nsDrawingSurface aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset,
PRInt32 aPadX, PRInt32 aPadY,
const nsRect &aTileRect);
void UpdateCachedImage();

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;