gdi32: Mirror the clip region when the DC is mirrored, with tests.

This commit is contained in:
Alexandre Julliard 2010-07-29 13:36:43 +02:00
parent 31da90fd9d
commit 7d776a866e
4 changed files with 170 additions and 20 deletions

View File

@ -42,6 +42,29 @@ static inline HRGN get_clip_region( DC * dc )
}
/***********************************************************************
* get_clip_rect
*
* Compute a clip rectangle from its logical coordinates.
*/
static inline RECT get_clip_rect( DC * dc, int left, int top, int right, int bottom )
{
RECT rect;
rect.left = left;
rect.top = top;
rect.right = right;
rect.bottom = bottom;
LPtoDP( dc->hSelf, (POINT *)&rect, 2 );
if (dc->layout & LAYOUT_RTL)
{
int tmp = rect.left;
rect.left = rect.right + 1;
rect.right = tmp + 1;
}
return rect;
}
/***********************************************************************
* CLIPPING_UpdateGCRegion
*
@ -140,6 +163,19 @@ INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
}
else
{
HRGN mirrored = 0;
if (dc->layout & LAYOUT_RTL)
{
if (!(mirrored = CreateRectRgn( 0, 0, 0, 0 )))
{
release_dc_ptr( dc );
return ERROR;
}
mirror_region( mirrored, hrgn, dc->vis_rect.right - dc->vis_rect.left );
hrgn = mirrored;
}
if (!dc->hClipRgn)
create_default_clip_region( dc );
@ -147,6 +183,8 @@ INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
else
CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
if (mirrored) DeleteObject( mirrored );
}
CLIPPING_UpdateGCRegion( dc );
@ -196,8 +234,10 @@ INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
/* FIXME: ret is just a success flag, we should return a proper value */
}
else if (dc->hClipRgn) {
ret = OffsetRgn( dc->hClipRgn, MulDiv( x, dc->vportExtX, dc->wndExtX ),
MulDiv( y, dc->vportExtY, dc->wndExtY ) );
x = MulDiv( x, dc->vportExtX, dc->wndExtX );
y = MulDiv( y, dc->vportExtY, dc->wndExtY );
if (dc->layout & LAYOUT_RTL) x = -x;
ret = OffsetRgn( dc->hClipRgn, x, y );
CLIPPING_UpdateGCRegion( dc );
}
release_dc_ptr( dc );
@ -226,14 +266,9 @@ INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
}
else
{
POINT pt[2];
RECT rect = get_clip_rect( dc, left, top, right, bottom );
pt[0].x = left;
pt[0].y = top;
pt[1].x = right;
pt[1].y = bottom;
LPtoDP( hdc, pt, 2 );
if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
if (!(newRgn = CreateRectRgnIndirect( &rect ))) ret = ERROR;
else
{
if (!dc->hClipRgn)
@ -267,25 +302,18 @@ INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom
}
else
{
POINT pt[2];
pt[0].x = left;
pt[0].y = top;
pt[1].x = right;
pt[1].y = bottom;
LPtoDP( hdc, pt, 2 );
RECT rect = get_clip_rect( dc, left, top, right, bottom );
if (!dc->hClipRgn)
{
dc->hClipRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y );
dc->hClipRgn = CreateRectRgnIndirect( &rect );
ret = SIMPLEREGION;
}
else
{
HRGN newRgn;
if (!(newRgn = CreateRectRgn( pt[0].x, pt[0].y, pt[1].x, pt[1].y ))) ret = ERROR;
if (!(newRgn = CreateRectRgnIndirect( &rect ))) ret = ERROR;
else
{
ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
@ -388,7 +416,12 @@ INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
{
if( dc->hClipRgn )
{
if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR )
{
ret = 1;
if (dc->layout & LAYOUT_RTL)
mirror_region( hRgn, hRgn, dc->vis_rect.right - dc->vis_rect.left );
}
}
else ret = 0;
release_dc_ptr( dc );
@ -408,7 +441,11 @@ INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
if (dc)
{
if (dc->hMetaRgn && CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY ) != ERROR)
{
ret = 1;
if (dc->layout & LAYOUT_RTL)
mirror_region( hRgn, hRgn, dc->vis_rect.right - dc->vis_rect.left );
}
release_dc_ptr( dc );
}
return ret;

View File

@ -490,6 +490,7 @@ extern UINT WINAPI GDIRealizePalette( HDC hdc );
extern HPALETTE PALETTE_Init(void) DECLSPEC_HIDDEN;
/* region.c */
extern INT mirror_region( HRGN dst, HRGN src, INT width ) DECLSPEC_HIDDEN;
extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y ) DECLSPEC_HIDDEN;
/* Undocumented value for DIB's iUsage: Indicates a mono DIB w/o pal entries */

View File

@ -1458,6 +1458,63 @@ static BOOL REGION_CopyRegion(WINEREGION *dst, WINEREGION *src)
return TRUE;
}
/***********************************************************************
* REGION_MirrorRegion
*/
static BOOL REGION_MirrorRegion( WINEREGION *dst, WINEREGION *src, int width )
{
int i, start, end;
RECT extents;
RECT *rects = HeapAlloc( GetProcessHeap(), 0, src->numRects * sizeof(RECT) );
if (!rects) return FALSE;
extents.left = width - src->extents.right;
extents.right = width - src->extents.left;
extents.top = src->extents.top;
extents.bottom = src->extents.bottom;
for (start = 0; start < src->numRects; start = end)
{
/* find the end of the current band */
for (end = start + 1; end < src->numRects; end++)
if (src->rects[end].top != src->rects[end - 1].top) break;
for (i = 0; i < end - start; i++)
{
rects[start + i].left = width - src->rects[end - i - 1].right;
rects[start + i].right = width - src->rects[end - i - 1].left;
rects[start + i].top = src->rects[end - i - 1].top;
rects[start + i].bottom = src->rects[end - i - 1].bottom;
}
}
HeapFree( GetProcessHeap(), 0, dst->rects );
dst->rects = rects;
dst->size = src->numRects;
dst->numRects = src->numRects;
dst->extents = extents;
return TRUE;
}
/***********************************************************************
* mirror_region
*/
INT mirror_region( HRGN dst, HRGN src, INT width )
{
RGNOBJ *src_rgn, *dst_rgn;
INT ret = ERROR;
if (!(src_rgn = GDI_GetObjPtr( src, OBJ_REGION ))) return ERROR;
if ((dst_rgn = GDI_GetObjPtr( dst, OBJ_REGION )))
{
if (REGION_MirrorRegion( &dst_rgn->rgn, &src_rgn->rgn, width )) ret = get_region_type( dst_rgn );
GDI_ReleaseObj( dst_rgn );
}
GDI_ReleaseObj( src_rgn );
return ret;
}
/***********************************************************************
* REGION_Coalesce
*

View File

@ -31,6 +31,7 @@
static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
static DWORD (WINAPI *pGetLayout)(HDC hdc);
static INT (WINAPI *pGetRandomRgn)(HDC hDC, HRGN hRgn, INT iCode);
static BOOL (WINAPI *pGetTransform)(HDC, DWORD, XFORM *);
static DWORD (WINAPI *pSetVirtualResolution)(HDC, DWORD, DWORD, DWORD, DWORD);
@ -228,7 +229,9 @@ static void test_dc_layout(void)
SIZE size;
POINT pt;
HBITMAP bitmap;
RECT rc, ret_rc;
HDC hdc;
HRGN hrgn;
if (!pGetLayout || !pSetLayout)
{
@ -287,6 +290,57 @@ static void test_dc_layout(void)
ok( xform.eDy == 0.0, "got %f\n", xform.eDy );
}
SetRect( &rc, 10, 10, 20, 20 );
IntersectClipRect( hdc, 10, 10, 20, 20 );
hrgn = CreateRectRgn( 0, 0, 0, 0 );
GetClipRgn( hdc, hrgn );
GetRgnBox( hrgn, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
pSetLayout( hdc, LAYOUT_LTR );
SetRect( &rc, 80, 10, 90, 20 );
GetClipRgn( hdc, hrgn );
GetRgnBox( hrgn, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
GetClipBox( hdc, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
IntersectClipRect( hdc, 80, 10, 85, 20 );
pSetLayout( hdc, LAYOUT_RTL );
SetRect( &rc, 15, 10, 20, 20 );
GetClipRgn( hdc, hrgn );
GetRgnBox( hrgn, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
SetRectRgn( hrgn, 60, 10, 80, 20 );
pSetLayout( hdc, LAYOUT_LTR );
ExtSelectClipRgn( hdc, hrgn, RGN_OR );
pSetLayout( hdc, LAYOUT_RTL );
SetRect( &rc, 15, 10, 40, 20 );
GetClipRgn( hdc, hrgn );
GetRgnBox( hrgn, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
/* OffsetClipRgn mirrors too */
OffsetClipRgn( hdc, 5, 5 );
OffsetRect( &rc, 5, 5 );
GetClipRgn( hdc, hrgn );
GetRgnBox( hrgn, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
/* GetRandomRgn returns the raw region */
if (pGetRandomRgn)
{
SetRect( &rc, 55, 15, 80, 25 );
pGetRandomRgn( hdc, hrgn, 1 );
GetRgnBox( hrgn, &ret_rc );
ok( EqualRect( &rc, &ret_rc ), "wrong clip box %d,%d - %d,%d\n",
ret_rc.left, ret_rc.top, ret_rc.right, ret_rc.bottom );
}
SetMapMode(hdc, MM_LOMETRIC);
ret = GetMapMode( hdc );
ok(ret == MM_ANISOTROPIC, "expected MM_ANISOTROPIC, got %d\n", ret);
@ -656,6 +710,7 @@ START_TEST(mapping)
HMODULE mod = GetModuleHandleA("gdi32.dll");
pGetLayout = (void *)GetProcAddress( mod, "GetLayout" );
pSetLayout = (void *)GetProcAddress( mod, "SetLayout" );
pGetRandomRgn = (void *)GetProcAddress( mod, "GetRandomRgn" );
pGetTransform = (void *)GetProcAddress( mod, "GetTransform" );
pSetVirtualResolution = (void *)GetProcAddress( mod, "SetVirtualResolution" );