mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-13 11:38:16 +00:00
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:
parent
3bb8acf4c3
commit
e5c3adbd79
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user