diff --git a/mozilla/gfx/public/nsIRenderingContext.h b/mozilla/gfx/public/nsIRenderingContext.h index aed5c9688b4..6766b172746 100644 --- a/mozilla/gfx/public/nsIRenderingContext.h +++ b/mozilla/gfx/public/nsIRenderingContext.h @@ -717,6 +717,17 @@ public: //~~~ NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd) = 0; + /** + * Copy an image to the RenderingContext in a tiled manner + * @param aImage image to copy + * @param aSrcXOffset x offset inside the source image to begin tiling from + * @param aSrcYOffset y offset inside the source image to begin tiling from + * @param aTileRect area to tile + */ + NS_IMETHOD DrawTile(nsIImage *aImage, nscoord aSrcXOffset, + nscoord aSrcYOffset, const nsRect &aTileRect) = 0; + + #ifdef MOZ_MATHML /** * Returns bounding metrics (in app units) of an 8-bit character string diff --git a/mozilla/gfx/public/nsRenderingContextImpl.h b/mozilla/gfx/public/nsRenderingContextImpl.h index 9b7a9ec3c6a..cd8b843e9c4 100644 --- a/mozilla/gfx/public/nsRenderingContextImpl.h +++ b/mozilla/gfx/public/nsRenderingContextImpl.h @@ -55,8 +55,10 @@ public: * See documentation in nsIRenderingContext.h * @update 03/29/00 dwc */ - NS_IMETHOD DrawTile(nsIImage *aImage,nscoord aX0,nscoord aY0,nscoord aX1,nscoord aY1,nscoord aWidth,nscoord aHeight); - + NS_IMETHOD DrawTile(nsIImage *aImage,nscoord aX0,nscoord aY0,nscoord aX1,nscoord aY1, + nscoord aWidth,nscoord aHeight); + NS_IMETHOD DrawTile(nsIImage *aImage, nscoord aSrcXOffset, + nscoord aSrcYOffset, const nsRect &aTileRect); /** --------------------------------------------------- * See documentation in nsIRenderingContext.h * @update 03/29/00 dwc diff --git a/mozilla/gfx/src/gtk/nsDrawingSurfaceGTK.h b/mozilla/gfx/src/gtk/nsDrawingSurfaceGTK.h index 05126430411..b2e4df3ebdc 100644 --- a/mozilla/gfx/src/gtk/nsDrawingSurfaceGTK.h +++ b/mozilla/gfx/src/gtk/nsDrawingSurfaceGTK.h @@ -64,6 +64,7 @@ public: void GetSize(PRUint32 *aWidth, PRUint32 *aHeight) { *aWidth = mWidth; *aHeight = mHeight; } + PRInt32 GetDepth() { return mDepth; } protected: PRUint8 ConvertMaskToCount(unsigned long val); diff --git a/mozilla/gfx/src/gtk/nsImageGTK.cpp b/mozilla/gfx/src/gtk/nsImageGTK.cpp index 6267fc4e0d0..41491efaa23 100644 --- a/mozilla/gfx/src/gtk/nsImageGTK.cpp +++ b/mozilla/gfx/src/gtk/nsImageGTK.cpp @@ -669,7 +669,7 @@ nsImageGTK::DrawComposited(nsIRenderingContext &aContext, readX = aX; readY = aY; destX = 0; destY = 0; - if ((readY>=surfaceHeight) || (readX>=surfaceWidth)) { + if ((readY>=(int)surfaceHeight) || (readX>=(int)surfaceWidth)) { // This should never happen if the layout engine is sane, // but pavlov says he saw it. Bulletproof gfx for now... return; @@ -1001,7 +1001,9 @@ nsImageGTK::Draw(nsIRenderingContext &aContext, } /* inline */ -void nsImageGTK::TilePixmap(GdkPixmap *src, GdkPixmap *dest, const nsRect &destRect, +void nsImageGTK::TilePixmap(GdkPixmap *src, GdkPixmap *dest, + PRInt32 aSXOffset, PRInt32 aSYOffset, + const nsRect &destRect, const nsRect &clipRect, PRBool useClip) { GdkGC *gc; @@ -1010,8 +1012,8 @@ void nsImageGTK::TilePixmap(GdkPixmap *src, GdkPixmap *dest, const nsRect &destR memset(&values, 0, sizeof(GdkGCValues)); values.fill = GDK_TILED; values.tile = src; - values.ts_x_origin = destRect.x; - values.ts_y_origin = destRect.y; + values.ts_x_origin = destRect.x - aSXOffset; + values.ts_y_origin = destRect.y - aSYOffset; valuesMask = GdkGCValuesMask(GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN); gc = gdk_gc_new_with_values(src, &values, valuesMask); @@ -1060,7 +1062,12 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, aTileRect.width, aTileRect.height, this); #endif - if (mAlphaDepth == 8) { + nsDrawingSurfaceGTK *drawing = (nsDrawingSurfaceGTK*)aSurface; + + if ((drawing->GetDepth() == 8) || (mAlphaDepth == 8)) { +#ifdef DEBUG_TILING + printf("Warning: using slow tiling\n"); +#endif PRInt32 aY0 = aTileRect.y, aX0 = aTileRect.x, aY1 = aTileRect.y + aTileRect.height, @@ -1073,8 +1080,6 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, return NS_OK; } - nsDrawingSurfaceGTK *drawing = (nsDrawingSurfaceGTK*)aSurface; - PRInt32 validX = 0, validY = 0, @@ -1112,12 +1117,12 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, nsRect tmpRect(0,0,aTileRect.width, aTileRect.height); tileImg = gdk_pixmap_new(mImagePixmap, aTileRect.width, aTileRect.height, mDepth); - TilePixmap(mImagePixmap, tileImg, tmpRect, tmpRect, PR_FALSE); + TilePixmap(mImagePixmap, tileImg, 0, 0, tmpRect, tmpRect, PR_FALSE); // tile alpha mask tileMask = gdk_pixmap_new(mAlphaPixmap, aTileRect.width, aTileRect.height, mAlphaDepth); - TilePixmap(mAlphaPixmap, tileMask, tmpRect, tmpRect, PR_FALSE); + TilePixmap(mAlphaPixmap, tileMask, 0, 0, tmpRect, tmpRect, PR_FALSE); GdkGC *fgc = gdk_gc_new(drawing->GetDrawable()); gdk_gc_set_clip_mask(fgc, (GdkBitmap*)tileMask); @@ -1140,12 +1145,129 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, PRBool isValid; aContext.GetClipRect(clipRect, isValid); - TilePixmap(mImagePixmap, drawing->GetDrawable(), aTileRect, clipRect, PR_TRUE); + TilePixmap(mImagePixmap, drawing->GetDrawable(), aTileRect.x, aTileRect.y, aTileRect, clipRect, PR_TRUE); } return NS_OK; } + + +NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext, + nsDrawingSurface aSurface, + PRInt32 aSXOffset, PRInt32 aSYOffset, + const nsRect &aTileRect) +{ +#ifdef DEBUG_TILING + printf("nsImageGTK::DrawTile: mWidth=%d, mHeight=%d\n", mWidth, mHeight); + printf("nsImageGTK::DrawTile((src: %d, %d), (tile: %d,%d, %d, %d) %p\n", aSXOffset, aSYOffset, + aTileRect.x, aTileRect.y, + aTileRect.width, aTileRect.height, this); +#endif + + nsDrawingSurfaceGTK *drawing = (nsDrawingSurfaceGTK*)aSurface; + + PRInt32 + validX = 0, + validY = 0, + validWidth = mWidth, + validHeight = mHeight; + + // limit the image rectangle to the size of the image data which + // has been validated. + if ((mDecodedY2 < mHeight)) { + validHeight = mDecodedY2 - mDecodedY1; + } + if ((mDecodedX2 < mWidth)) { + validWidth = mDecodedX2 - mDecodedX1; + } + if ((mDecodedY1 > 0)) { + validHeight -= mDecodedY1; + validY = mDecodedY1; + } + if ((mDecodedX1 > 0)) { + validWidth -= mDecodedX1; + validX = mDecodedX1; + } + + if (mAlphaDepth == 8) { +#ifdef DEBUG_TILING + printf("Warning: using slow tiling\n"); +#endif + PRInt32 aY0 = aTileRect.y - aSYOffset, + aX0 = aTileRect.x - aSXOffset, + aY1 = aTileRect.y + aTileRect.height, + aX1 = aTileRect.x + aTileRect.width; + + // Set up clipping and call Draw(). + PRBool clipState; + aContext.PushState(); + aContext.SetClipRect(aTileRect, nsClipCombine_kIntersect, + clipState); + + for (PRInt32 y = aY0; y < aY1; y+=validHeight) + for (PRInt32 x = aX0; x < aX1; x+=validWidth) + Draw(aContext,aSurface,x,y,validWidth,validHeight); + + aContext.PopState(clipState); + + return NS_OK; + } + + // draw the tile offscreen + CreateOffscreenPixmap(validWidth, validHeight); + DrawImageOffscreen(validX, validY, validWidth, validHeight); + + if (mAlphaDepth == 1) { + GdkPixmap *tileImg; + GdkPixmap *tileMask; + + CreateAlphaBitmap(validWidth, validHeight); + + nsRect tmpRect(0,0,aTileRect.width, aTileRect.height); + + tileImg = gdk_pixmap_new(mImagePixmap, aTileRect.width, + aTileRect.height, drawing->GetDepth()); + TilePixmap(mImagePixmap, tileImg, aSXOffset, aSYOffset, tmpRect, + tmpRect, PR_FALSE); + + + // tile alpha mask + tileMask = gdk_pixmap_new(mAlphaPixmap, aTileRect.width, aTileRect.height, mAlphaDepth); + TilePixmap(mAlphaPixmap, tileMask, aSXOffset, aSYOffset, tmpRect, + tmpRect, PR_FALSE); + + GdkGC *fgc = gdk_gc_new(drawing->GetDrawable()); + gdk_gc_set_clip_mask(fgc, (GdkBitmap*)tileMask); + gdk_gc_set_clip_origin(fgc, aTileRect.x, aTileRect.y); + + // and copy it back + gdk_window_copy_area(drawing->GetDrawable(), fgc, aTileRect.x, + aTileRect.y, tileImg, 0, 0, + aTileRect.width, aTileRect.height); + gdk_gc_unref(fgc); + + gdk_pixmap_unref(tileImg); + gdk_pixmap_unref(tileMask); + + } else { + + // In the non-alpha case, gdk can tile for us + + nsRect clipRect; + PRBool isValid; + aContext.GetClipRect(clipRect, isValid); + + TilePixmap(mImagePixmap, drawing->GetDrawable(), aSXOffset, aSYOffset, + aTileRect, clipRect, PR_FALSE); + } + + mFlags = 0; + return NS_OK; +} + + + //------------------------------------------------------------ nsresult nsImageGTK::Optimize(nsIDeviceContext* aContext) diff --git a/mozilla/gfx/src/gtk/nsImageGTK.h b/mozilla/gfx/src/gtk/nsImageGTK.h index 985d3f676c8..fe060815b52 100644 --- a/mozilla/gfx/src/gtk/nsImageGTK.h +++ b/mozilla/gfx/src/gtk/nsImageGTK.h @@ -72,6 +72,11 @@ public: nsRect &aSrcRect, nsRect &aTileRect); + NS_IMETHOD DrawTile(nsIRenderingContext &aContext, + nsDrawingSurface aSurface, + PRInt32 aSXOffset, PRInt32 aSYOffset, + const nsRect &aTileRect); + virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect); virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, @@ -135,7 +140,8 @@ private: PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight); - inline void TilePixmap(GdkPixmap *src, GdkPixmap *dest, const nsRect &destRect, const nsRect &clipRect, PRBool useClip); + inline void TilePixmap(GdkPixmap *src, GdkPixmap *dest, PRInt32 aSXOffset, PRInt32 aSYOffset, + const nsRect &destRect, const nsRect &clipRect, PRBool useClip); inline void CreateAlphaBitmap(PRInt32 aWidth, PRInt32 aHeight); inline void CreateOffscreenPixmap(PRInt32 aWidth, PRInt32 aHeight); inline void DrawImageOffscreen(PRInt32 validX, PRInt32 validY, PRInt32 validWidth, PRInt32 validHeight); diff --git a/mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp b/mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp index d0eacd76c32..c6f5237ea2f 100644 --- a/mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp +++ b/mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp @@ -1531,6 +1531,29 @@ nsRenderingContextGTK::DrawTile(nsIImage *aImage, return NS_OK; } + +NS_IMETHODIMP +nsRenderingContextGTK::DrawTile(nsIImage *aImage, + nscoord aSrcXOffset, nscoord aSrcYOffset, + const nsRect &aTileRect) +{ + nsImageGTK* image = (nsImageGTK*) aImage; + + nsRect tileRect(aTileRect); + nsRect srcRect(0, 0, aSrcXOffset, aSrcYOffset); + mTranMatrix->TransformCoord(&srcRect.x, &srcRect.y, &srcRect.width, + &srcRect.height); + mTranMatrix->TransformCoord(&tileRect.x, &tileRect.y, + &tileRect.width, &tileRect.height); + + if((tileRect.width > 0) && (tileRect.height > 0)) + image->DrawTile(*this, mSurface, srcRect.width, srcRect.height, + tileRect); + + return NS_OK; +} + + #endif diff --git a/mozilla/gfx/src/gtk/nsRenderingContextGTK.h b/mozilla/gfx/src/gtk/nsRenderingContextGTK.h index c85158c5df4..009c191f7d4 100644 --- a/mozilla/gfx/src/gtk/nsRenderingContextGTK.h +++ b/mozilla/gfx/src/gtk/nsRenderingContextGTK.h @@ -42,7 +42,7 @@ #include -//#define USE_NATIVE_TILING 1 +#define USE_NATIVE_TILING 1 class nsRenderingContextGTK : public nsRenderingContextImpl { @@ -160,7 +160,9 @@ public: NS_IMETHOD DrawImage(nsIImage *aImage, const nsRect& aSRect, const nsRect& aDRect); #ifdef USE_NATIVE_TILING NS_IMETHOD DrawTile(nsIImage *aImage,nscoord aX0,nscoord aY0,nscoord aX1,nscoord aY1, - nscoord aWidth,nscoord aHeight); + nscoord aWidth, nscoord aHeight); + NS_IMETHOD DrawTile(nsIImage *aImage, nscoord aSrcXOffset, + nscoord aSrcYOffset, const nsRect &aTileRect); #endif NS_IMETHOD CopyOffScreenBits(nsDrawingSurface aSrcSurf, PRInt32 aSrcX, PRInt32 aSrcY, const nsRect &aDestBounds, PRUint32 aCopyFlags); diff --git a/mozilla/layout/base/nsCSSRendering.cpp b/mozilla/layout/base/nsCSSRendering.cpp index 4cd7957f622..5ac75681a7a 100644 --- a/mozilla/layout/base/nsCSSRendering.cpp +++ b/mozilla/layout/base/nsCSSRendering.cpp @@ -2273,12 +2273,14 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } } +#ifndef XP_UNIX // Setup clipping so that rendering doesn't leak out of the computed // dirty rect PRBool clipState; aRenderingContext.PushState(); aRenderingContext.SetClipRect(dirtyRect, nsClipCombine_kIntersect, clipState); +#endif // Compute the x and y starting points and limits for tiling nscoord x0, x1; @@ -2353,8 +2355,19 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } } +#ifdef XP_UNIX + // Take the intersection again to paint only the required area + nsRect tileRect(x0,y0,(x1-x0),(y1-y0)); + nsRect drawRect; + if (drawRect.IntersectRect(tileRect, dirtyRect)) { + PRInt32 xOffset = drawRect.x - x0, + yOffset = drawRect.y - y0; + aRenderingContext.DrawTile(image,xOffset,yOffset,drawRect); + } +#else + aRenderingContext.DrawTile(image,x0,y0,x1,y1,tileWidth,tileHeight); +#endif - aRenderingContext.DrawTile(image,x0,y0,x1,y1,tileWidth,tileHeight); #ifdef DOTILE nsIDrawingSurface *theSurface,*ts=nsnull; @@ -2458,8 +2471,10 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } #endif +#ifndef XP_UNIX // Restore clipping aRenderingContext.PopState(clipState); +#endif NS_IF_RELEASE(image); } else { // See if there's a background color specified. The background color diff --git a/mozilla/layout/html/style/src/nsCSSRendering.cpp b/mozilla/layout/html/style/src/nsCSSRendering.cpp index 4cd7957f622..5ac75681a7a 100644 --- a/mozilla/layout/html/style/src/nsCSSRendering.cpp +++ b/mozilla/layout/html/style/src/nsCSSRendering.cpp @@ -2273,12 +2273,14 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } } +#ifndef XP_UNIX // Setup clipping so that rendering doesn't leak out of the computed // dirty rect PRBool clipState; aRenderingContext.PushState(); aRenderingContext.SetClipRect(dirtyRect, nsClipCombine_kIntersect, clipState); +#endif // Compute the x and y starting points and limits for tiling nscoord x0, x1; @@ -2353,8 +2355,19 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } } +#ifdef XP_UNIX + // Take the intersection again to paint only the required area + nsRect tileRect(x0,y0,(x1-x0),(y1-y0)); + nsRect drawRect; + if (drawRect.IntersectRect(tileRect, dirtyRect)) { + PRInt32 xOffset = drawRect.x - x0, + yOffset = drawRect.y - y0; + aRenderingContext.DrawTile(image,xOffset,yOffset,drawRect); + } +#else + aRenderingContext.DrawTile(image,x0,y0,x1,y1,tileWidth,tileHeight); +#endif - aRenderingContext.DrawTile(image,x0,y0,x1,y1,tileWidth,tileHeight); #ifdef DOTILE nsIDrawingSurface *theSurface,*ts=nsnull; @@ -2458,8 +2471,10 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, } #endif +#ifndef XP_UNIX // Restore clipping aRenderingContext.PopState(clipState); +#endif NS_IF_RELEASE(image); } else { // See if there's a background color specified. The background color