New and improved background tiling code for GTK. We take an offset into

the image as a parameter so we avoid drawing the whole tile if it's not
all needed.  Also, we can avoid setting any clip regions at all this
way, and avoid trips to the X server.  Fixes several background rendering
problems.  Also fix a signedness problem in the compositing code
(r=tor).  r=pavlov.
This commit is contained in:
bryner%uiuc.edu 2000-05-12 06:29:37 +00:00
parent 3bb8acf4c3
commit e5c3adbd79
9 changed files with 214 additions and 17 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,7 +42,7 @@
#include <gtk/gtk.h>
//#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);

View File

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

View File

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