gdi32: Mirror the clip region when the DC is mirrored, with tests.
This commit is contained in:
parent
31da90fd9d
commit
7d776a866e
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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" );
|
||||
|
||||
|
|
Loading…
Reference in New Issue