diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c index e8676703e18..7c4e0d588d2 100644 --- a/dlls/winex11.drv/graphics.c +++ b/dlls/winex11.drv/graphics.c @@ -185,27 +185,62 @@ RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) } -/*********************************************************************** - * X11DRV_SetDeviceClipping - */ -void X11DRV_SetDeviceClipping( PHYSDEV dev, HRGN vis_rgn, HRGN clip_rgn ) +static void update_x11_clipping( X11DRV_PDEVICE *physDev ) { - X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); RGNDATA *data; - CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY ); if (!(data = X11DRV_GetRegionData( physDev->region, 0 ))) return; - wine_tsx11_lock(); XSetClipRectangles( gdi_display, physDev->gc, physDev->dc_rect.left, physDev->dc_rect.top, (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded ); wine_tsx11_unlock(); if (physDev->xrender) X11DRV_XRender_SetDeviceClipping(physDev, data); - HeapFree( GetProcessHeap(), 0, data ); } +/*********************************************************************** + * add_extra_clipping_region + * + * Temporarily add a region to the current clipping region. + * The returned region must be restored with restore_clipping_region. + */ +HRGN add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) +{ + HRGN ret, clip; + + if (!(clip = CreateRectRgn( 0, 0, 0, 0 ))) return 0; + CombineRgn( clip, dev->region, rgn, RGN_AND ); + ret = dev->region; + dev->region = clip; + update_x11_clipping( dev ); + return ret; +} + + +/*********************************************************************** + * restore_clipping_region + */ +void restore_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) +{ + if (!rgn) return; + DeleteObject( dev->region ); + dev->region = rgn; + update_x11_clipping( dev ); +} + + +/*********************************************************************** + * X11DRV_SetDeviceClipping + */ +void X11DRV_SetDeviceClipping( PHYSDEV dev, HRGN vis_rgn, HRGN clip_rgn ) +{ + X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); + + CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY ); + update_x11_clipping( physDev ); +} + /*********************************************************************** * X11DRV_SetupGCForPatBlt diff --git a/dlls/winex11.drv/text.c b/dlls/winex11.drv/text.c index 89af8f6eca7..442a4c20e3d 100644 --- a/dlls/winex11.drv/text.c +++ b/dlls/winex11.drv/text.c @@ -85,13 +85,8 @@ BOOL X11DRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, if (flags & ETO_CLIPPED) { - HRGN clip_region; - - clip_region = CreateRectRgnIndirect( lprect ); - /* make a copy of the current device region */ - saved_region = CreateRectRgn( 0, 0, 0, 0 ); - CombineRgn( saved_region, physDev->region, 0, RGN_COPY ); - X11DRV_SetDeviceClipping( dev, saved_region, clip_region ); + HRGN clip_region = CreateRectRgnIndirect( lprect ); + saved_region = add_extra_clipping_region( physDev, clip_region ); DeleteObject( clip_region ); } @@ -177,12 +172,7 @@ BOOL X11DRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, } HeapFree( GetProcessHeap(), 0, str2b ); - if (flags & ETO_CLIPPED) - { - /* restore the device region */ - X11DRV_SetDeviceClipping( dev, saved_region, 0 ); - DeleteObject( saved_region ); - } + if (saved_region) restore_clipping_region( physDev, saved_region ); goto END; FAIL: diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 93d39818b51..deec898a3a2 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -289,6 +289,8 @@ extern X_PHYSBITMAP *X11DRV_init_phys_bitmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN; extern Pixmap X11DRV_get_pixmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN; extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp ) DECLSPEC_HIDDEN; +extern HRGN add_extra_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN; +extern void restore_clipping_region( X11DRV_PDEVICE *dev, HRGN rgn ) DECLSPEC_HIDDEN; extern BOOL X11DRV_SetupGCForPatBlt( X11DRV_PDEVICE *physDev, GC gc, BOOL fMapColors ) DECLSPEC_HIDDEN; extern BOOL X11DRV_SetupGCForBrush( X11DRV_PDEVICE *physDev ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c index dc603af237f..ad8e08bb3dd 100644 --- a/dlls/winex11.drv/xrender.c +++ b/dlls/winex11.drv/xrender.c @@ -1866,13 +1866,8 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag if (flags & ETO_CLIPPED) { - HRGN clip_region; - - clip_region = CreateRectRgnIndirect( lprect ); - /* make a copy of the current device region */ - saved_region = CreateRectRgn( 0, 0, 0, 0 ); - CombineRgn( saved_region, physDev->region, 0, RGN_COPY ); - X11DRV_SetDeviceClipping( &physDev->dev, saved_region, clip_region ); + HRGN clip_region = CreateRectRgnIndirect( lprect ); + saved_region = add_extra_clipping_region( physDev, clip_region ); DeleteObject( clip_region ); } @@ -2131,12 +2126,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag } LeaveCriticalSection(&xrender_cs); - if (flags & ETO_CLIPPED) - { - /* restore the device region */ - X11DRV_SetDeviceClipping( &physDev->dev, saved_region, 0 ); - DeleteObject( saved_region ); - } + if (saved_region) restore_clipping_region( physDev, saved_region ); retv = TRUE;