winex11: Add bounds rectangle tracking to all graphics entry points.

This commit is contained in:
Alexandre Julliard 2012-04-16 17:49:05 +02:00
parent bb62ddeba7
commit 4a87722144
7 changed files with 183 additions and 39 deletions

View File

@ -391,7 +391,7 @@ static void test_device_caps( HDC hdc, HDC ref_dc, const char *descr )
SetMapMode( hdc, MM_TEXT ); SetMapMode( hdc, MM_TEXT );
Rectangle( hdc, 2, 2, 4, 4 ); Rectangle( hdc, 2, 2, 4, 4 );
type = GetBoundsRect( hdc, &rect, DCB_RESET ); type = GetBoundsRect( hdc, &rect, DCB_RESET );
if (GetObjectType( hdc ) != OBJ_MEMDC || GetDeviceCaps( hdc, TECHNOLOGY ) == DT_RASDISPLAY) if (GetObjectType( hdc ) == OBJ_ENHMETADC)
todo_wine todo_wine
ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET, ok( rect.left == 2 && rect.top == 2 && rect.right == 4 && rect.bottom == 4 && type == DCB_SET,
"GetBoundsRect returned %d,%d,%d,%d type %x for %s\n", "GetBoundsRect returned %d,%d,%d,%d type %x for %s\n",
@ -890,10 +890,8 @@ static void test_boundsrect(void)
MoveToEx( hdc, 10, 10, NULL ); MoveToEx( hdc, 10, 10, NULL );
LineTo( hdc, 20, 20 ); LineTo( hdc, 20, 20 );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
todo_wine
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 10, 10, 21, 21 ); SetRect( &expect, 10, 10, 21, 21 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
SetRect( &rect, 8, 8, 23, 23 ); SetRect( &rect, 8, 8, 23, 23 );
expect = rect; expect = rect;
@ -907,32 +905,27 @@ static void test_boundsrect(void)
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 8, 8, 31, 26 ); SetRect( &expect, 8, 8, 31, 26 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
SetBoundsRect( hdc, NULL, DCB_DISABLE ); SetBoundsRect( hdc, NULL, DCB_DISABLE );
LineTo( hdc, 40, 40 ); LineTo( hdc, 40, 40 );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 8, 8, 31, 26 ); SetRect( &expect, 8, 8, 31, 26 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
SetRect( &rect, 6, 6, 30, 30 ); SetRect( &rect, 6, 6, 30, 30 );
SetBoundsRect( hdc, &rect, DCB_ACCUMULATE ); SetBoundsRect( hdc, &rect, DCB_ACCUMULATE );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 6, 6, 31, 30 ); SetRect( &expect, 6, 6, 31, 30 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
RestoreDC( hdc, level ); RestoreDC( hdc, level );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
LineTo( hdc, 40, 40 ); LineTo( hdc, 40, 40 );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
SelectObject( hdc, old ); SelectObject( hdc, old );
@ -947,14 +940,12 @@ static void test_boundsrect(void)
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 6, 6, 51, 41 ); SetRect( &expect, 6, 6, 51, 41 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
SelectObject( hdc, GetStockObject( NULL_PEN )); SelectObject( hdc, GetStockObject( NULL_PEN ));
LineTo( hdc, 50, 50 ); LineTo( hdc, 50, 50 );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 6, 6, 51, 51 ); SetRect( &expect, 6, 6, 51, 51 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
memset( buffer, 0, sizeof(buffer) ); memset( buffer, 0, sizeof(buffer) );
@ -970,7 +961,6 @@ static void test_boundsrect(void)
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );
ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret ); ok( ret == DCB_SET, "GetBoundsRect returned %x\n", ret );
SetRect( &expect, 6, 6, 51, 51 ); SetRect( &expect, 6, 6, 51, 51 );
todo_wine
ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom ); ok( EqualRect(&rect, &expect), "Got (%d,%d)-(%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom );
LineTo( hdc, 55, 30 ); LineTo( hdc, 55, 30 );
ret = GetBoundsRect( hdc, &rect, 0 ); ret = GetBoundsRect( hdc, &rect, 0 );

View File

@ -749,6 +749,7 @@ void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT
XFreePixmap( gdi_display, pixmaps[DST] ); XFreePixmap( gdi_display, pixmaps[DST] );
if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] ); if (pixmaps[TMP]) XFreePixmap( gdi_display, pixmaps[TMP] );
wine_tsx11_unlock(); wine_tsx11_unlock();
add_device_bounds( physdev, visrect );
} }
/*********************************************************************** /***********************************************************************
@ -800,6 +801,7 @@ BOOL X11DRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
dst->visrect.right - dst->visrect.left, dst->visrect.right - dst->visrect.left,
dst->visrect.bottom - dst->visrect.top ); dst->visrect.bottom - dst->visrect.top );
wine_tsx11_unlock(); wine_tsx11_unlock();
add_device_bounds( physDev, &dst->visrect );
return TRUE; return TRUE;
} }
@ -830,6 +832,8 @@ BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
height = dst->visrect.bottom - dst->visrect.top; height = dst->visrect.bottom - dst->visrect.top;
opcode = BITBLT_Opcodes[(rop >> 16) & 0xff]; opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
add_device_bounds( physDevDst, &dst->visrect );
/* a few optimizations for single-op ROPs */ /* a few optimizations for single-op ROPs */
if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST)) if (!opcode[1] && OP_SRCDST(opcode[0]) == OP_ARGS(SRC,DST))
{ {
@ -1302,6 +1306,7 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info
} }
if (restore_region) restore_clipping_region( physdev ); if (restore_region) restore_clipping_region( physdev );
add_device_bounds( physdev, &dst->visrect );
} }
image->data = NULL; image->data = NULL;
} }

View File

@ -104,6 +104,42 @@ static RECT get_device_rect( HDC hdc, int left, int top, int right, int bottom )
return rect; return rect;
} }
static void add_pen_device_bounds( X11DRV_PDEVICE *dev, const POINT *points, int count )
{
RECT bounds, rect;
int width = 0;
reset_bounds( &bounds );
if (dev->pen.type & PS_GEOMETRIC || dev->pen.width > 1)
{
/* Windows uses some heuristics to estimate the distance from the point that will be painted */
width = dev->pen.width + 2;
if (dev->pen.linejoin == PS_JOIN_MITER)
{
width *= 5;
if (dev->pen.endcap == PS_ENDCAP_SQUARE) width = (width * 3 + 1) / 2;
}
else
{
if (dev->pen.endcap == PS_ENDCAP_SQUARE) width -= width / 4;
else width = (width + 1) / 2;
}
}
while (count-- > 0)
{
rect.left = points->x - width;
rect.top = points->y - width;
rect.right = points->x + width + 1;
rect.bottom = points->y + width + 1;
add_bounds_rect( &bounds, &rect );
points++;
}
add_device_bounds( dev, &bounds );
}
/*********************************************************************** /***********************************************************************
* X11DRV_GetRegionData * X11DRV_GetRegionData
* *
@ -506,12 +542,14 @@ BOOL X11DRV_LineTo( PHYSDEV dev, INT x, INT y )
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
POINT pt[2]; POINT pt[2];
if (X11DRV_SetupGCForPen( physDev )) { GetCurrentPositionEx( dev->hdc, &pt[0] );
GetCurrentPositionEx( dev->hdc, &pt[0] ); pt[1].x = x;
pt[1].x = x; pt[1].y = y;
pt[1].y = y; LPtoDP( dev->hdc, pt, 2 );
LPtoDP( dev->hdc, pt, 2 ); add_pen_device_bounds( physDev, pt, 2 );
if (X11DRV_SetupGCForPen( physDev ))
{
wine_tsx11_lock(); wine_tsx11_lock();
XDrawLine(gdi_display, physDev->drawable, physDev->gc, XDrawLine(gdi_display, physDev->drawable, physDev->gc,
physDev->dc_rect.left + pt[0].x, physDev->dc_rect.top + pt[0].y, physDev->dc_rect.left + pt[0].x, physDev->dc_rect.top + pt[0].y,
@ -670,6 +708,7 @@ static BOOL X11DRV_DrawArc( PHYSDEV dev, INT left, INT top, INT right, INT botto
} }
physDev->pen.width = oldwidth; physDev->pen.width = oldwidth;
add_pen_device_bounds( physDev, (POINT *)&rc, 2 );
return TRUE; return TRUE;
} }
@ -748,6 +787,7 @@ BOOL X11DRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
} }
physDev->pen.width = oldwidth; physDev->pen.width = oldwidth;
add_pen_device_bounds( physDev, (POINT *)&rc, 2 );
return TRUE; return TRUE;
} }
@ -784,7 +824,9 @@ BOOL X11DRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
if(physDev->pen.type != PS_GEOMETRIC) if(physDev->pen.type != PS_GEOMETRIC)
physDev->pen.linejoin = PS_JOIN_MITER; physDev->pen.linejoin = PS_JOIN_MITER;
if ((rc.right > rc.left + width) && (rc.bottom > rc.top + width)) rc.right--;
rc.bottom--;
if ((rc.right >= rc.left + width) && (rc.bottom >= rc.top + width))
{ {
if (X11DRV_SetupGCForBrush( physDev )) if (X11DRV_SetupGCForBrush( physDev ))
{ {
@ -792,7 +834,7 @@ BOOL X11DRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
XFillRectangle( gdi_display, physDev->drawable, physDev->gc, XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->dc_rect.left + rc.left + (width + 1) / 2, physDev->dc_rect.left + rc.left + (width + 1) / 2,
physDev->dc_rect.top + rc.top + (width + 1) / 2, physDev->dc_rect.top + rc.top + (width + 1) / 2,
rc.right-rc.left-width-1, rc.bottom-rc.top-width-1); rc.right-rc.left-width, rc.bottom-rc.top-width);
wine_tsx11_unlock(); wine_tsx11_unlock();
} }
} }
@ -801,12 +843,13 @@ BOOL X11DRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
wine_tsx11_lock(); wine_tsx11_lock();
XDrawRectangle( gdi_display, physDev->drawable, physDev->gc, XDrawRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top, physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.top,
rc.right-rc.left-1, rc.bottom-rc.top-1 ); rc.right-rc.left, rc.bottom-rc.top );
wine_tsx11_unlock(); wine_tsx11_unlock();
} }
physDev->pen.width = oldwidth; physDev->pen.width = oldwidth;
physDev->pen.linejoin = oldjoinstyle; physDev->pen.linejoin = oldjoinstyle;
add_pen_device_bounds( physDev, (POINT *)&rc, 2 );
return TRUE; return TRUE;
} }
@ -1000,6 +1043,7 @@ BOOL X11DRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
physDev->pen.width = oldwidth; physDev->pen.width = oldwidth;
physDev->pen.endcap = oldendcap; physDev->pen.endcap = oldendcap;
add_pen_device_bounds( physDev, (POINT *)&rc, 2 );
return TRUE; return TRUE;
} }
@ -1012,6 +1056,7 @@ COLORREF X11DRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
unsigned long pixel; unsigned long pixel;
POINT pt; POINT pt;
RECT rect;
pt.x = x; pt.x = x;
pt.y = y; pt.y = y;
@ -1025,6 +1070,8 @@ COLORREF X11DRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
physDev->dc_rect.left + pt.x, physDev->dc_rect.top + pt.y ); physDev->dc_rect.left + pt.x, physDev->dc_rect.top + pt.y );
wine_tsx11_unlock(); wine_tsx11_unlock();
SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 );
add_device_bounds( physDev, &rect );
return X11DRV_PALETTE_ToLogical(physDev, pixel); return X11DRV_PALETTE_ToLogical(physDev, pixel);
} }
@ -1035,6 +1082,7 @@ COLORREF X11DRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
BOOL X11DRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) BOOL X11DRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
{ {
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
RECT rc;
if (X11DRV_SetupGCForBrush( physDev )) if (X11DRV_SetupGCForBrush( physDev ))
{ {
@ -1055,6 +1103,11 @@ BOOL X11DRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
wine_tsx11_unlock(); wine_tsx11_unlock();
HeapFree( GetProcessHeap(), 0, data ); HeapFree( GetProcessHeap(), 0, data );
} }
if (GetRgnBox( hrgn, &rc ))
{
LPtoDP( dev->hdc, (POINT *)&rc, 2 );
add_device_bounds( physDev, &rc );
}
return TRUE; return TRUE;
} }
@ -1072,6 +1125,7 @@ BOOL X11DRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
if (!points) return FALSE; if (!points) return FALSE;
memcpy( points, pt, count * sizeof(*pt) ); memcpy( points, pt, count * sizeof(*pt) );
LPtoDP( dev->hdc, points, count ); LPtoDP( dev->hdc, points, count );
add_pen_device_bounds( physDev, points, count );
if (!(xpoints = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) ))) if (!(xpoints = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (count+1) )))
{ {
@ -1127,6 +1181,7 @@ BOOL X11DRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT p
if (!points) return FALSE; if (!points) return FALSE;
memcpy( points, pt, total * sizeof(*pt) ); memcpy( points, pt, total * sizeof(*pt) );
LPtoDP( dev->hdc, points, total ); LPtoDP( dev->hdc, points, total );
add_pen_device_bounds( physDev, points, total );
if (X11DRV_SetupGCForBrush( physDev )) if (X11DRV_SetupGCForBrush( physDev ))
{ {
@ -1197,6 +1252,7 @@ BOOL X11DRV_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO
if (!points) return FALSE; if (!points) return FALSE;
memcpy( points, pt, total * sizeof(*pt) ); memcpy( points, pt, total * sizeof(*pt) );
LPtoDP( dev->hdc, points, total ); LPtoDP( dev->hdc, points, total );
add_pen_device_bounds( physDev, points, total );
if (X11DRV_SetupGCForPen ( physDev )) if (X11DRV_SetupGCForPen ( physDev ))
{ {
@ -1235,7 +1291,7 @@ BOOL X11DRV_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO
static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev, static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev,
int x, int y, int x, int y,
int xOrg, int yOrg, int xOrg, int yOrg,
unsigned long pixel, WORD fillType ) unsigned long pixel, WORD fillType, RECT *bounds )
{ {
int left, right; int left, right;
@ -1250,6 +1306,10 @@ static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev,
left = right = x; left = right = x;
while ((left > 0) && TO_FLOOD( left-1, y )) left--; while ((left > 0) && TO_FLOOD( left-1, y )) left--;
while ((right < image->width) && TO_FLOOD( right, y )) right++; while ((right < image->width) && TO_FLOOD( right, y )) right++;
bounds->left = min( bounds->left, left );
bounds->top = min( bounds->top, y );
bounds->right = max( bounds->right, right );
bounds->bottom = max( bounds->bottom, y + 1 );
XFillRectangle( gdi_display, physDev->drawable, physDev->gc, XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
xOrg + left, yOrg + y, right-left, 1 ); xOrg + left, yOrg + y, right-left, 1 );
@ -1272,7 +1332,7 @@ static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev,
if (x >= right) break; if (x >= right) break;
while ((x < right) && TO_FLOOD(x,y)) x++; while ((x < right) && TO_FLOOD(x,y)) x++;
X11DRV_InternalFloodFill(image, physDev, x-1, y, X11DRV_InternalFloodFill(image, physDev, x-1, y,
xOrg, yOrg, pixel, fillType ); xOrg, yOrg, pixel, fillType, bounds );
} }
} }
@ -1287,7 +1347,7 @@ static void X11DRV_InternalFloodFill(XImage *image, X11DRV_PDEVICE *physDev,
if (x >= right) break; if (x >= right) break;
while ((x < right) && TO_FLOOD(x,y)) x++; while ((x < right) && TO_FLOOD(x,y)) x++;
X11DRV_InternalFloodFill(image, physDev, x-1, y, X11DRV_InternalFloodFill(image, physDev, x-1, y,
xOrg, yOrg, pixel, fillType ); xOrg, yOrg, pixel, fillType, bounds );
} }
} }
#undef TO_FLOOD #undef TO_FLOOD
@ -1306,7 +1366,7 @@ BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillTy
{ {
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
XImage *image; XImage *image;
RECT rect; RECT rect, bounds;
POINT pt; POINT pt;
TRACE("X11DRV_ExtFloodFill %d,%d %06x %d\n", x, y, color, fillType ); TRACE("X11DRV_ExtFloodFill %d,%d %06x %d\n", x, y, color, fillType );
@ -1345,14 +1405,19 @@ BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillTy
{ {
unsigned long pixel = X11DRV_PALETTE_ToPhysical( physDev, color ); unsigned long pixel = X11DRV_PALETTE_ToPhysical( physDev, color );
reset_bounds( &bounds );
wine_tsx11_lock(); wine_tsx11_lock();
X11DRV_InternalFloodFill(image, physDev, X11DRV_InternalFloodFill(image, physDev,
pt.x - rect.left, pt.x - rect.left,
pt.y - rect.top, pt.y - rect.top,
physDev->dc_rect.left + rect.left, physDev->dc_rect.left + rect.left,
physDev->dc_rect.top + rect.top, physDev->dc_rect.top + rect.top,
pixel, fillType ); pixel, fillType, &bounds );
wine_tsx11_unlock(); wine_tsx11_unlock();
OffsetRect( &bounds, rect.left, rect.top );
add_device_bounds( physDev, &bounds );
} }
wine_tsx11_lock(); wine_tsx11_lock();
@ -1371,6 +1436,7 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
const GRADIENT_RECT *rect = grad_array; const GRADIENT_RECT *rect = grad_array;
TRIVERTEX v[2]; TRIVERTEX v[2];
POINT pt[2]; POINT pt[2];
RECT rc, bounds;
unsigned int i; unsigned int i;
XGCValues val; XGCValues val;
@ -1389,10 +1455,11 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
XChangeGC( gdi_display, physdev->gc, XChangeGC( gdi_display, physdev->gc,
GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val ); GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val );
wine_tsx11_unlock(); wine_tsx11_unlock();
reset_bounds( &bounds );
for (i = 0; i < ngrad; i++, rect++) for (i = 0; i < ngrad; i++, rect++)
{ {
int pos, x, dx; int x, dx;
v[0] = vert_array[rect->UpperLeft]; v[0] = vert_array[rect->UpperLeft];
v[1] = vert_array[rect->LowerRight]; v[1] = vert_array[rect->LowerRight];
@ -1409,7 +1476,12 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
v[1] = vert_array[rect->UpperLeft]; v[1] = vert_array[rect->UpperLeft];
dx = -dx; dx = -dx;
} }
for (x = 0, pos = min( pt[0].x, pt[1].x ); x < dx; x++, pos++) rc.left = min( pt[0].x, pt[1].x );
rc.top = min( pt[0].y, pt[1].y );
rc.right = max( pt[0].x, pt[1].x );
rc.bottom = max( pt[0].y, pt[1].y );
add_bounds_rect( &bounds, &rc );
for (x = 0; x < dx; x++)
{ {
int color = X11DRV_PALETTE_ToPhysical( physdev, int color = X11DRV_PALETTE_ToPhysical( physdev,
RGB( (v[0].Red * (dx - x) + v[1].Red * x) / dx / 256, RGB( (v[0].Red * (dx - x) + v[1].Red * x) / dx / 256,
@ -1419,11 +1491,12 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
wine_tsx11_lock(); wine_tsx11_lock();
XSetForeground( gdi_display, physdev->gc, color ); XSetForeground( gdi_display, physdev->gc, color );
XDrawLine( gdi_display, physdev->drawable, physdev->gc, XDrawLine( gdi_display, physdev->drawable, physdev->gc,
physdev->dc_rect.left + pos, physdev->dc_rect.top + pt[0].y, physdev->dc_rect.left + rc.left + x, physdev->dc_rect.top + rc.top,
physdev->dc_rect.left + pos, physdev->dc_rect.top + pt[1].y ); physdev->dc_rect.left + rc.left + x, physdev->dc_rect.top + rc.bottom );
wine_tsx11_unlock(); wine_tsx11_unlock();
} }
} }
add_device_bounds( physdev, &bounds );
return TRUE; return TRUE;
case GRADIENT_FILL_RECT_V: case GRADIENT_FILL_RECT_V:
@ -1436,10 +1509,11 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
XChangeGC( gdi_display, physdev->gc, XChangeGC( gdi_display, physdev->gc,
GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val ); GCFunction | GCLineWidth | GCLineStyle | GCCapStyle | GCFillStyle, &val );
wine_tsx11_unlock(); wine_tsx11_unlock();
reset_bounds( &bounds );
for (i = 0; i < ngrad; i++, rect++) for (i = 0; i < ngrad; i++, rect++)
{ {
int pos, y, dy; int y, dy;
v[0] = vert_array[rect->UpperLeft]; v[0] = vert_array[rect->UpperLeft];
v[1] = vert_array[rect->LowerRight]; v[1] = vert_array[rect->LowerRight];
@ -1456,7 +1530,12 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
v[1] = vert_array[rect->UpperLeft]; v[1] = vert_array[rect->UpperLeft];
dy = -dy; dy = -dy;
} }
for (y = 0, pos = min( pt[0].y, pt[1].y ); y < dy; y++, pos++) rc.left = min( pt[0].x, pt[1].x );
rc.top = min( pt[0].y, pt[1].y );
rc.right = max( pt[0].x, pt[1].x );
rc.bottom = max( pt[0].y, pt[1].y );
add_bounds_rect( &bounds, &rc );
for (y = 0; y < dy; y++)
{ {
int color = X11DRV_PALETTE_ToPhysical( physdev, int color = X11DRV_PALETTE_ToPhysical( physdev,
RGB( (v[0].Red * (dy - y) + v[1].Red * y) / dy / 256, RGB( (v[0].Red * (dy - y) + v[1].Red * y) / dy / 256,
@ -1466,11 +1545,12 @@ BOOL X11DRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
wine_tsx11_lock(); wine_tsx11_lock();
XSetForeground( gdi_display, physdev->gc, color ); XSetForeground( gdi_display, physdev->gc, color );
XDrawLine( gdi_display, physdev->drawable, physdev->gc, XDrawLine( gdi_display, physdev->drawable, physdev->gc,
physdev->dc_rect.left + pt[0].x, physdev->dc_rect.top + pos, physdev->dc_rect.left + rc.left, physdev->dc_rect.top + rc.top + y,
physdev->dc_rect.left + pt[1].x, physdev->dc_rect.top + pos ); physdev->dc_rect.left + rc.right, physdev->dc_rect.top + rc.top + y );
wine_tsx11_unlock(); wine_tsx11_unlock();
} }
} }
add_device_bounds( physdev, &bounds );
return TRUE; return TRUE;
} }

View File

@ -118,6 +118,7 @@ static X11DRV_PDEVICE *create_x11_physdev( Drawable drawable )
if (!(physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) ))) return NULL; if (!(physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev) ))) return NULL;
reset_bounds( &physDev->bounds );
wine_tsx11_lock(); wine_tsx11_lock();
physDev->drawable = drawable; physDev->drawable = drawable;
physDev->gc = XCreateGC( gdi_display, drawable, 0, NULL ); physDev->gc = XCreateGC( gdi_display, drawable, 0, NULL );
@ -187,6 +188,31 @@ static BOOL X11DRV_DeleteDC( PHYSDEV dev )
} }
void add_device_bounds( X11DRV_PDEVICE *dev, const RECT *rect )
{
RECT rc;
if (dev->region && GetRgnBox( dev->region, &rc ))
{
if (IntersectRect( &rc, &rc, rect )) add_bounds_rect( &dev->bounds, &rc );
}
else add_bounds_rect( &dev->bounds, rect );
}
/***********************************************************************
* dibdrv_GetBoundsRect
*/
static UINT X11DRV_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
{
X11DRV_PDEVICE *pdev = get_x11drv_dev( dev );
if (IsRectEmpty( &pdev->bounds )) return DCB_RESET;
if (rect) *rect = pdev->bounds;
if (flags & DCB_RESET) reset_bounds( &pdev->bounds );
return DCB_SET;
}
/*********************************************************************** /***********************************************************************
* GetDeviceCaps (X11DRV.@) * GetDeviceCaps (X11DRV.@)
*/ */
@ -477,7 +503,7 @@ static const struct gdi_dc_funcs x11drv_funcs =
NULL, /* pFrameRgn */ NULL, /* pFrameRgn */
NULL, /* pGdiComment */ NULL, /* pGdiComment */
NULL, /* pGdiRealizationInfo */ NULL, /* pGdiRealizationInfo */
NULL, /* pGetBoundsRect */ X11DRV_GetBoundsRect, /* pGetBoundsRect */
NULL, /* pGetCharABCWidths */ NULL, /* pGetCharABCWidths */
NULL, /* pGetCharABCWidthsI */ NULL, /* pGetCharABCWidthsI */
NULL, /* pGetCharWidth */ NULL, /* pGetCharWidth */

View File

@ -2256,6 +2256,7 @@ static void WINAPI X11DRV_wglGetIntegerv(GLenum pname, GLint* params)
void flush_gl_drawable(X11DRV_PDEVICE *physDev) void flush_gl_drawable(X11DRV_PDEVICE *physDev)
{ {
int w, h; int w, h;
RECT rect;
if (!physDev->gl_copy || !physDev->current_pf) if (!physDev->gl_copy || !physDev->current_pf)
return; return;
@ -2275,6 +2276,8 @@ void flush_gl_drawable(X11DRV_PDEVICE *physDev)
XCopyArea(gdi_display, src, physDev->drawable, physDev->gc, 0, 0, w, h, XCopyArea(gdi_display, src, physDev->drawable, physDev->gc, 0, 0, w, h,
physDev->dc_rect.left, physDev->dc_rect.top); physDev->dc_rect.left, physDev->dc_rect.top);
wine_tsx11_unlock(); wine_tsx11_unlock();
SetRect( &rect, 0, 0, w, h );
add_device_bounds( physDev, &rect );
} }
} }

View File

@ -26,6 +26,7 @@
# error You must include config.h to use this header # error You must include config.h to use this header
#endif #endif
#include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xresource.h> #include <X11/Xresource.h>
@ -122,6 +123,7 @@ typedef struct
Drawable drawable; Drawable drawable;
RECT dc_rect; /* DC rectangle relative to drawable */ RECT dc_rect; /* DC rectangle relative to drawable */
RECT drawable_rect; /* Drawable rectangle relative to screen */ RECT drawable_rect; /* Drawable rectangle relative to screen */
RECT bounds; /* Graphics bounds */
HRGN region; /* Device region (visible region & clip region) */ HRGN region; /* Device region (visible region & clip region) */
X_PHYSPEN pen; X_PHYSPEN pen;
X_PHYSBRUSH brush; X_PHYSBRUSH brush;
@ -140,6 +142,21 @@ static inline X11DRV_PDEVICE *get_x11drv_dev( PHYSDEV dev )
return (X11DRV_PDEVICE *)dev; return (X11DRV_PDEVICE *)dev;
} }
static inline void reset_bounds( RECT *bounds )
{
bounds->left = bounds->top = INT_MAX;
bounds->right = bounds->bottom = INT_MIN;
}
static inline void add_bounds_rect( RECT *bounds, const RECT *rect )
{
if (rect->left >= rect->right || rect->top >= rect->bottom) return;
bounds->left = min( bounds->left, rect->left );
bounds->top = min( bounds->top, rect->top );
bounds->right = max( bounds->right, rect->right );
bounds->bottom = max( bounds->bottom, rect->bottom );
}
extern X_PHYSBITMAP BITMAP_stock_phys_bitmap DECLSPEC_HIDDEN; /* phys bitmap for the default stock bitmap */ extern X_PHYSBITMAP BITMAP_stock_phys_bitmap DECLSPEC_HIDDEN; /* phys bitmap for the default stock bitmap */
/* Retrieve the GC used for bitmap operations */ /* Retrieve the GC used for bitmap operations */
@ -234,6 +251,7 @@ extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,
extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN; extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN;
extern BOOL add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN; extern BOOL add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN;
extern void restore_clipping_region( X11DRV_PDEVICE *dev ) DECLSPEC_HIDDEN; extern void restore_clipping_region( X11DRV_PDEVICE *dev ) DECLSPEC_HIDDEN;
extern void add_device_bounds( X11DRV_PDEVICE *dev, const RECT *rect ) DECLSPEC_HIDDEN;
extern void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop ) DECLSPEC_HIDDEN; extern void execute_rop( X11DRV_PDEVICE *physdev, Pixmap src_pixmap, GC gc, const RECT *visrect, DWORD rop ) DECLSPEC_HIDDEN;

View File

@ -1680,6 +1680,7 @@ static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
POINT offset, desired, current; POINT offset, desired, current;
int render_op = PictOpOver; int render_op = PictOpOver;
XRenderColor col; XRenderColor col;
RECT rect, bounds;
get_xrender_color( physdev, GetTextColor( physdev->dev.hdc ), &col ); get_xrender_color( physdev, GetTextColor( physdev->dev.hdc ), &col );
pict = get_xrender_picture( physdev, 0, (flags & ETO_CLIPPED) ? lprect : NULL ); pict = get_xrender_picture( physdev, 0, (flags & ETO_CLIPPED) ? lprect : NULL );
@ -1702,6 +1703,7 @@ static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
lprect->right - lprect->left, lprect->right - lprect->left,
lprect->bottom - lprect->top ); lprect->bottom - lprect->top );
wine_tsx11_unlock(); wine_tsx11_unlock();
add_device_bounds( physdev->x11dev, lprect );
} }
if(count == 0) return TRUE; if(count == 0) return TRUE;
@ -1750,6 +1752,7 @@ static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
if (physdev->format == WXR_FORMAT_MONO && col.red == 0 && col.green == 0 && col.blue == 0) if (physdev->format == WXR_FORMAT_MONO && col.red == 0 && col.green == 0 && col.blue == 0)
render_op = PictOpOutReverse; /* This gives us 'black' text */ render_op = PictOpOutReverse; /* This gives us 'black' text */
reset_bounds( &bounds );
for(idx = 0; idx < count; idx++) for(idx = 0; idx < count; idx++)
{ {
elts[idx].glyphset = formatEntry->glyphset; elts[idx].glyphset = formatEntry->glyphset;
@ -1761,6 +1764,12 @@ static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff); current.x += (elts[idx].xOff + formatEntry->gis[wstr[idx]].xOff);
current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff); current.y += (elts[idx].yOff + formatEntry->gis[wstr[idx]].yOff);
rect.left = desired.x - physdev->x11dev->dc_rect.left - formatEntry->gis[wstr[idx]].x;
rect.top = desired.y - physdev->x11dev->dc_rect.top - formatEntry->gis[wstr[idx]].y;
rect.right = rect.left + formatEntry->gis[wstr[idx]].width;
rect.bottom = rect.top + formatEntry->gis[wstr[idx]].height;
add_bounds_rect( &bounds, &rect );
if(!lpDx) if(!lpDx)
{ {
desired.x += formatEntry->gis[wstr[idx]].xOff; desired.x += formatEntry->gis[wstr[idx]].xOff;
@ -1792,6 +1801,7 @@ static BOOL xrenderdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
HeapFree(GetProcessHeap(), 0, elts); HeapFree(GetProcessHeap(), 0, elts);
LeaveCriticalSection(&xrender_cs); LeaveCriticalSection(&xrender_cs);
add_device_bounds( physdev->x11dev, &bounds );
return TRUE; return TRUE;
} }
@ -2170,6 +2180,7 @@ static BOOL xrenderdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
} }
else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst ); else xrender_stretch_blit( physdev_src, physdev_dst, 0, src, dst );
add_device_bounds( physdev_dst->x11dev, &dst->visrect );
return TRUE; return TRUE;
x11drv_fallback: x11drv_fallback:
@ -2272,6 +2283,8 @@ static DWORD xrenderdrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMA
} }
else xrender_put_image( src_pixmap, src_pict, mask_pict, clip, else xrender_put_image( src_pixmap, src_pict, mask_pict, clip,
physdev->pict_format, physdev, 0, src, dst, use_repeat ); physdev->pict_format, physdev, 0, src, dst, use_repeat );
add_device_bounds( physdev->x11dev, &dst->visrect );
} }
wine_tsx11_lock(); wine_tsx11_lock();
@ -2354,6 +2367,7 @@ static DWORD xrenderdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct
wine_tsx11_unlock(); wine_tsx11_unlock();
LeaveCriticalSection( &xrender_cs ); LeaveCriticalSection( &xrender_cs );
add_device_bounds( physdev->x11dev, &dst->visrect );
} }
return ret; return ret;
@ -2459,6 +2473,7 @@ static BOOL xrenderdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
wine_tsx11_unlock(); wine_tsx11_unlock();
LeaveCriticalSection( &xrender_cs ); LeaveCriticalSection( &xrender_cs );
add_device_bounds( physdev_dst->x11dev, &dst->visrect );
return TRUE; return TRUE;
} }
@ -2476,6 +2491,7 @@ static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG n
Picture src_pict, dst_pict; Picture src_pict, dst_pict;
unsigned int i; unsigned int i;
const GRADIENT_RECT *rect = grad_array; const GRADIENT_RECT *rect = grad_array;
RECT rc;
POINT pt[2]; POINT pt[2];
if (!pXRenderCreateLinearGradient) goto fallback; if (!pXRenderCreateLinearGradient) goto fallback;
@ -2535,8 +2551,13 @@ static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG n
} }
} }
TRACE( "%u gradient %d,%d - %d,%d colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n", rc.left = min( pt[0].x, pt[1].x );
mode, pt[0].x, pt[0].y, pt[1].x, pt[1].y, rc.top = min( pt[0].y, pt[1].y );
rc.right = max( pt[0].x, pt[1].x );
rc.bottom = max( pt[0].y, pt[1].y );
TRACE( "%u gradient %s colors %04x,%04x,%04x,%04x -> %04x,%04x,%04x,%04x\n",
mode, wine_dbgstr_rect( &rc ),
colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha, colors[0].red, colors[0].green, colors[0].blue, colors[0].alpha,
colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha ); colors[1].red, colors[1].green, colors[1].blue, colors[1].alpha );
@ -2545,12 +2566,13 @@ static BOOL xrenderdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG n
wine_tsx11_lock(); wine_tsx11_lock();
src_pict = pXRenderCreateLinearGradient( gdi_display, &gradient, stops, colors, 2 ); src_pict = pXRenderCreateLinearGradient( gdi_display, &gradient, stops, colors, 2 );
xrender_blit( PictOpSrc, src_pict, 0, dst_pict, xrender_blit( PictOpSrc, src_pict, 0, dst_pict,
0, 0, abs(pt[1].x - pt[0].x), abs(pt[1].y - pt[0].y), 0, 0, rc.right - rc.left, rc.bottom - rc.top,
physdev->x11dev->dc_rect.left + min( pt[0].x, pt[1].x ), physdev->x11dev->dc_rect.left + rc.left,
physdev->x11dev->dc_rect.top + min( pt[0].y, pt[1].y ), physdev->x11dev->dc_rect.top + rc.top,
abs(pt[1].x - pt[0].x), abs(pt[1].y - pt[0].y), 1, 1 ); rc.right - rc.left, rc.bottom - rc.top, 1, 1 );
pXRenderFreePicture( gdi_display, src_pict ); pXRenderFreePicture( gdi_display, src_pict );
wine_tsx11_unlock(); wine_tsx11_unlock();
add_device_bounds( physdev->x11dev, &rc );
} }
return TRUE; return TRUE;
} }