
Sat Aug 23 00:05:23 1997 Andreas Mohr <100.30936@germany.net> * [if1632/kernel.spec] [if1632/mmsystem.spec] Added some stubs. * [include/neexe.h] [loader/module.c] Added warning for OS/2 executables. * [multimedia/midi.c] Shortened MIDIOUT driver version string to be less than 31 chars. * [objects/gdiobj.c] Fixed DeleteObject32() to react properly when called with stock object. Fri Aug 22 18:03:26 1997 Dimitrie O. Paun <dimi@cs.toronto.edu> * [controls/updown.c] [include/updown.h] First attempt at implementiong the UpDown class. * [controls/widgets.c] Added the UpDown class to be initialized by InitCommonControls(). Wed Aug 20 18:01:33 1997 Doug Ridgway <ridgway@routh.UCSD.EDU> * [graphics/*] [objects/*] [include/gdi.h] Made all GDI objects (except DCs) moveable. Mon Aug 18 03:25:30 1997 Alex Korobka <alex@trantor.pharm.sunysb.edu> * [windows/event.c] [misc/winsock.c] [misc/winsock_dns.c] Removed IPC communication to speed up winsock services (tested only with 16-bit netscape 3.03). * [graphics/x11drv/xfont.c] [documentation/fonts] Miscellaneous improvements. Updated docs. Sun Aug 17 20:39:55 1997 Ingo Schneider <schneidi@informatik.tu-muenchen.de> * [misc/comm.c] A couple of bug fixes. Sun Aug 17 19:29:22 1997 Alexandre Julliard <julliard@lrc.epfl.ch> * [debugger/dbg.y] Display next instruction after stepi/nexti. * [if1632/relay.c] [include/callback.h] [tools/build.c] Replaced CallTo32_LargeStack with the CALL_LARGE_STACK macro for better Winelib support. * [include/sigcontext.h] Renamed to sig_context.h to avoid conflicts with libc. * [*/*] All API functions are now prefixed with WINAPI in prevision of future Winelib integration. * [loader/signal.c] [memory/ldt.c] Fixed assembly code to be -fPIC compatible. Thu Aug 14 14:38:15 1997 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de> * [if1632/crtdll.spec][win32/except.c] _global_unwind, _local_unwind stub added. * [objects/dib.c] Don't read memory you don't even need for the target bitmap (fixes one 'lazy' program). * [if1632/relay.c][if1632/thunk.c][if1632/kernel32.spec] [win32/ordinals.c][memory/selector.c][memory/global.c] [include/callback.h] Added/moved some more win95 ordinal stuff. Implemented QT_Thunk (not 100% correct yet) and some friends. * [loader/pe_image.c] Add possibility to break at the DLL entrypoint. * [controls/static.c][misc/commdlg.c][scheduler/thread.c] Misc bugfixes and additions. * [misc/registry.c] The registry seems to be case-preserving but case-insensitive. * [memory/global.c] Adapted to new /proc/meminfo format. * [objects/font.c][graphics/x11drv/xfont.c] FONT_SelectObject and GetTextMetrics* get passed ranges in logical and not device points (thanks to Marion Reyzl for pointing this out). * [windows/caret.c] Use the windows own DC if present (The caret coordinates are logical coordinates based on it). Fixes another AMIPRO problem. Wed Aug 6 18:22:22 1997 Morten Welinder <terra@diku.dk> * [controls/menu.c] General clean-up and Win32 work: split item_flags into fType and fState; split item_id into wID and hSubMenu. Improved debug-printing. Implemented InsertMenuItem32[AW], SetMenuDefaultItem32, and SetMenuItemInfo32[AW]. Fixed GetMenuItemInfo32[AW]. * [if1632/user32.spec] Define above new functions. * [include/windows.h] Define MF_DEFAULT and MF_RIGHTJUSTIFY. Prototype above functions. * [include/menu.h] Don't prototype now-static MENU_InitSysMenuPopup. * [include/comm.h] Reduce MAX_PORTS to 9 (which the profile code can handle). Tue Aug 5 20:16:22 1997 Victor Schneider <vischne@ibm.net> * [library/winestub.c] [libtest/expand.c] These patches let people porting Windows apps compile them using the same conventions regarding global _argc and _argv as those on Windows C/C++ compilers.
765 lines
22 KiB
C
765 lines
22 KiB
C
/*
|
|
* GDI region objects
|
|
*
|
|
* Copyright 1993, 1994, 1995 Alexandre Julliard
|
|
*
|
|
* RGNOBJ is documented in the Dr. Dobbs Journal March 1993.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "region.h"
|
|
#include "stddebug.h"
|
|
#include "debug.h"
|
|
|
|
|
|
/***********************************************************************
|
|
* REGION_DeleteObject
|
|
*/
|
|
BOOL32 REGION_DeleteObject( HRGN32 hrgn, RGNOBJ * obj )
|
|
{
|
|
dprintf_region(stddeb, "DeleteRegion: %04x\n", hrgn );
|
|
if (obj->xrgn) XDestroyRegion( obj->xrgn );
|
|
return GDI_FreeObject( hrgn );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* OffsetRgn16 (GDI.101)
|
|
*/
|
|
INT16 WINAPI OffsetRgn16( HRGN16 hrgn, INT16 x, INT16 y )
|
|
{
|
|
return OffsetRgn32( hrgn, x, y );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* OffsetRgn32 (GDI32.256)
|
|
*/
|
|
INT32 WINAPI OffsetRgn32( HRGN32 hrgn, INT32 x, INT32 y )
|
|
{
|
|
RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
|
|
if (!obj) return ERROR;
|
|
dprintf_region(stddeb, "OffsetRgn: %04x %d,%d\n", hrgn, x, y );
|
|
if (!obj->xrgn)
|
|
{
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return NULLREGION;
|
|
}
|
|
XOffsetRegion( obj->xrgn, x, y );
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return COMPLEXREGION;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetRgnBox16 (GDI.134)
|
|
*/
|
|
INT16 WINAPI GetRgnBox16( HRGN16 hrgn, LPRECT16 rect )
|
|
{
|
|
RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
|
|
if (!obj) return ERROR;
|
|
dprintf_region(stddeb, "GetRgnBox: %04x\n", hrgn );
|
|
if (!obj->xrgn)
|
|
{
|
|
SetRectEmpty16( rect );
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return NULLREGION;
|
|
}
|
|
else
|
|
{
|
|
XRectangle xrect;
|
|
XClipBox( obj->xrgn, &xrect );
|
|
GDI_HEAP_UNLOCK(hrgn);
|
|
SetRect16( rect, xrect.x, xrect.y,
|
|
xrect.x + xrect.width, xrect.y + xrect.height);
|
|
return COMPLEXREGION;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* GetRgnBox32 (GDI32.219)
|
|
*/
|
|
INT32 WINAPI GetRgnBox32( HRGN32 hrgn, LPRECT32 rect )
|
|
{
|
|
RECT16 r;
|
|
INT16 ret = GetRgnBox16( hrgn, &r );
|
|
CONV_RECT16TO32( &r, rect );
|
|
return ret;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateRectRgn16 (GDI.64)
|
|
*/
|
|
HRGN16 WINAPI CreateRectRgn16(INT16 left, INT16 top, INT16 right, INT16 bottom)
|
|
{
|
|
return (HRGN16)CreateRectRgn32( left, top, right, bottom );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateRectRgn32 (GDI32.59)
|
|
*/
|
|
HRGN32 WINAPI CreateRectRgn32(INT32 left, INT32 top, INT32 right, INT32 bottom)
|
|
{
|
|
HRGN32 hrgn;
|
|
RGNOBJ *obj;
|
|
|
|
if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
|
|
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
|
|
if ((right > left) && (bottom > top))
|
|
{
|
|
XRectangle rect = { left, top, right - left, bottom - top };
|
|
if (!(obj->xrgn = XCreateRegion()))
|
|
{
|
|
GDI_FreeObject( hrgn );
|
|
return 0;
|
|
}
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
}
|
|
else obj->xrgn = 0;
|
|
dprintf_region( stddeb, "CreateRectRgn(%d,%d-%d,%d): returning %04x\n",
|
|
left, top, right, bottom, hrgn );
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return hrgn;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateRectRgnIndirect16 (GDI.65)
|
|
*/
|
|
HRGN16 WINAPI CreateRectRgnIndirect16( const RECT16* rect )
|
|
{
|
|
return CreateRectRgn32( rect->left, rect->top, rect->right, rect->bottom );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateRectRgnIndirect32 (GDI32.60)
|
|
*/
|
|
HRGN32 WINAPI CreateRectRgnIndirect32( const RECT32* rect )
|
|
{
|
|
return CreateRectRgn32( rect->left, rect->top, rect->right, rect->bottom );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetRectRgn16 (GDI.172)
|
|
*/
|
|
VOID WINAPI SetRectRgn16( HRGN16 hrgn, INT16 left, INT16 top,
|
|
INT16 right, INT16 bottom )
|
|
{
|
|
SetRectRgn32( hrgn, left, top, right, bottom );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetRectRgn32 (GDI32.332)
|
|
*/
|
|
VOID WINAPI SetRectRgn32( HRGN32 hrgn, INT32 left, INT32 top,
|
|
INT32 right, INT32 bottom )
|
|
{
|
|
RGNOBJ * obj;
|
|
|
|
dprintf_region(stddeb, "SetRectRgn: %04x %d,%d-%d,%d\n",
|
|
hrgn, left, top, right, bottom );
|
|
|
|
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return;
|
|
if (obj->xrgn) XDestroyRegion( obj->xrgn );
|
|
if ((right > left) && (bottom > top))
|
|
{
|
|
XRectangle rect = { left, top, right - left, bottom - top };
|
|
if ((obj->xrgn = XCreateRegion()) != 0)
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
}
|
|
else obj->xrgn = 0;
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateRoundRectRgn16 (GDI.444)
|
|
*/
|
|
HRGN16 WINAPI CreateRoundRectRgn16( INT16 left, INT16 top,
|
|
INT16 right, INT16 bottom,
|
|
INT16 ellipse_width, INT16 ellipse_height )
|
|
{
|
|
return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
|
|
ellipse_width, ellipse_height );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateRoundRectRgn32 (GDI32.61)
|
|
*/
|
|
HRGN32 WINAPI CreateRoundRectRgn32( INT32 left, INT32 top,
|
|
INT32 right, INT32 bottom,
|
|
INT32 ellipse_width, INT32 ellipse_height )
|
|
{
|
|
RGNOBJ * obj;
|
|
HRGN32 hrgn;
|
|
XRectangle rect;
|
|
int asq, bsq, d, xd, yd;
|
|
|
|
/* Check if we can do a normal rectangle instead */
|
|
|
|
if ((right <= left) || (bottom <= top) ||
|
|
(ellipse_width <= 0) || (ellipse_height <= 0))
|
|
return CreateRectRgn32( left, top, right, bottom );
|
|
|
|
/* Create region */
|
|
|
|
if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
|
|
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
|
|
obj->xrgn = XCreateRegion();
|
|
dprintf_region(stddeb,"CreateRoundRectRgn(%d,%d-%d,%d %dx%d): return=%04x\n",
|
|
left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
|
|
|
|
/* Check parameters */
|
|
|
|
if (ellipse_width > right-left) ellipse_width = right-left;
|
|
if (ellipse_height > bottom-top) ellipse_height = bottom-top;
|
|
|
|
/* Ellipse algorithm, based on an article by K. Porter */
|
|
/* in DDJ Graphics Programming Column, 8/89 */
|
|
|
|
asq = ellipse_width * ellipse_width / 4; /* a^2 */
|
|
bsq = ellipse_height * ellipse_height / 4; /* b^2 */
|
|
d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
|
|
xd = 0;
|
|
yd = asq * ellipse_height; /* 2a^2b */
|
|
|
|
rect.x = left + ellipse_width / 2;
|
|
rect.width = right - left - ellipse_width;
|
|
rect.height = 1;
|
|
|
|
/* Loop to draw first half of quadrant */
|
|
|
|
while (xd < yd)
|
|
{
|
|
if (d > 0) /* if nearest pixel is toward the center */
|
|
{
|
|
/* move toward center */
|
|
rect.y = top++;
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
rect.y = --bottom;
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
yd -= 2*asq;
|
|
d -= yd;
|
|
}
|
|
rect.x--; /* next horiz point */
|
|
rect.width += 2;
|
|
xd += 2*bsq;
|
|
d += bsq + xd;
|
|
}
|
|
|
|
/* Loop to draw second half of quadrant */
|
|
|
|
d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
|
|
while (yd >= 0)
|
|
{
|
|
/* next vertical point */
|
|
rect.y = top++;
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
rect.y = --bottom;
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
if (d < 0) /* if nearest pixel is outside ellipse */
|
|
{
|
|
rect.x--; /* move away from center */
|
|
rect.width += 2;
|
|
xd += 2*bsq;
|
|
d += xd;
|
|
}
|
|
yd -= 2*asq;
|
|
d += asq - yd;
|
|
}
|
|
|
|
/* Add the inside rectangle */
|
|
|
|
if (top <= bottom)
|
|
{
|
|
rect.y = top;
|
|
rect.height = bottom - top + 1;
|
|
XUnionRectWithRegion( &rect, obj->xrgn, obj->xrgn );
|
|
}
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return hrgn;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateEllipticRgn16 (GDI.54)
|
|
*/
|
|
HRGN16 WINAPI CreateEllipticRgn16( INT16 left, INT16 top,
|
|
INT16 right, INT16 bottom )
|
|
{
|
|
return (HRGN16)CreateRoundRectRgn32( left, top, right, bottom,
|
|
right-left, bottom-top );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateEllipticRgn32 (GDI32.39)
|
|
*/
|
|
HRGN32 WINAPI CreateEllipticRgn32( INT32 left, INT32 top,
|
|
INT32 right, INT32 bottom )
|
|
{
|
|
return CreateRoundRectRgn32( left, top, right, bottom,
|
|
right-left, bottom-top );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateEllipticRgnIndirect16 (GDI.55)
|
|
*/
|
|
HRGN16 WINAPI CreateEllipticRgnIndirect16( const RECT16 *rect )
|
|
{
|
|
return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
|
|
rect->bottom, rect->right - rect->left,
|
|
rect->bottom - rect->top );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreateEllipticRgnIndirect32 (GDI32.40)
|
|
*/
|
|
HRGN32 WINAPI CreateEllipticRgnIndirect32( const RECT32 *rect )
|
|
{
|
|
return CreateRoundRectRgn32( rect->left, rect->top, rect->right,
|
|
rect->bottom, rect->right - rect->left,
|
|
rect->bottom - rect->top );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreatePolygonRgn16 (GDI.63)
|
|
*/
|
|
HRGN16 WINAPI CreatePolygonRgn16( const POINT16 * points, INT16 count,
|
|
INT16 mode )
|
|
{
|
|
return CreatePolyPolygonRgn16( points, &count, 1, mode );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreatePolyPolygonRgn16 (GDI.451)
|
|
*/
|
|
HRGN16 WINAPI CreatePolyPolygonRgn16( const POINT16 * points,
|
|
const INT16 * count,
|
|
INT16 nbpolygons, INT16 mode )
|
|
{
|
|
int i,nrofpts;
|
|
LPINT32 count32;
|
|
LPPOINT32 points32;
|
|
HRGN32 ret;
|
|
|
|
nrofpts=0;
|
|
for (i=nbpolygons;i--;)
|
|
nrofpts+=count[i];
|
|
points32 = (LPPOINT32)HeapAlloc( GetProcessHeap(), 0,
|
|
nrofpts*sizeof(POINT32) );
|
|
for (i=nrofpts;i--;)
|
|
CONV_POINT16TO32( &(points[i]), &(points32[i]) );
|
|
count32 = (LPINT32)HeapAlloc( GetProcessHeap(), 0,
|
|
sizeof(INT32)*nbpolygons );
|
|
for (i=nbpolygons;i--;)
|
|
count32[i]=count[i];
|
|
ret = CreatePolyPolygonRgn32(points32,count32,nbpolygons,mode);
|
|
HeapFree( GetProcessHeap(), 0, count32 );
|
|
HeapFree( GetProcessHeap(), 0, points32 );
|
|
return ret;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreatePolygonRgn32 (GDI32.58)
|
|
*/
|
|
HRGN32 WINAPI CreatePolygonRgn32( const POINT32 *points, INT32 count,
|
|
INT32 mode )
|
|
{
|
|
return CreatePolyPolygonRgn32( points, &count, 1, mode );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CreatePolyPolygonRgn32 (GDI32.57)
|
|
*/
|
|
HRGN32 WINAPI CreatePolyPolygonRgn32( const POINT32 * points,
|
|
const INT32 * count,
|
|
INT32 nbpolygons, INT32 mode )
|
|
{
|
|
RGNOBJ * obj;
|
|
HRGN32 hrgn;
|
|
int i, j, maxPoints;
|
|
XPoint *xpoints, *pt;
|
|
Region xrgn;
|
|
|
|
/* Allocate points array */
|
|
|
|
if (!nbpolygons) return 0;
|
|
for (i = maxPoints = 0; i < nbpolygons; i++)
|
|
if (maxPoints < count[i]) maxPoints = count[i];
|
|
if (!maxPoints) return 0;
|
|
if (!(xpoints = (XPoint *)HeapAlloc( GetProcessHeap(), 0,
|
|
sizeof(XPoint) * maxPoints )))
|
|
return 0;
|
|
|
|
/* Allocate region */
|
|
|
|
if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
|
|
{
|
|
HeapFree( GetProcessHeap(), 0, xpoints );
|
|
return 0;
|
|
}
|
|
obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
|
|
obj->xrgn = 0;
|
|
dprintf_region(stddeb, "CreatePolyPolygonRgn: %d polygons, returning %04x\n",
|
|
nbpolygons, hrgn );
|
|
|
|
/* Create X region */
|
|
|
|
for (i = 0; i < nbpolygons; i++, count++)
|
|
{
|
|
for (j = *count, pt = xpoints; j > 0; j--, points++, pt++)
|
|
{
|
|
pt->x = points->x;
|
|
pt->y = points->y;
|
|
}
|
|
xrgn = XPolygonRegion( xpoints, *count,
|
|
(mode == WINDING) ? WindingRule : EvenOddRule );
|
|
if (!xrgn)
|
|
{
|
|
if (obj->xrgn) XDestroyRegion( obj->xrgn );
|
|
HeapFree( GetProcessHeap(), 0, xpoints );
|
|
GDI_FreeObject( hrgn );
|
|
return 0;
|
|
}
|
|
if (i > 0)
|
|
{
|
|
Region tmprgn = XCreateRegion();
|
|
if (mode == WINDING) XUnionRegion( xrgn, obj->xrgn, tmprgn );
|
|
else XXorRegion( xrgn, obj->xrgn, tmprgn );
|
|
XDestroyRegion( obj->xrgn );
|
|
obj->xrgn = tmprgn;
|
|
}
|
|
else obj->xrgn = xrgn;
|
|
}
|
|
|
|
HeapFree( GetProcessHeap(), 0, xpoints );
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return hrgn;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* PtInRegion16 (GDI.161)
|
|
*/
|
|
BOOL16 WINAPI PtInRegion16( HRGN16 hrgn, INT16 x, INT16 y )
|
|
{
|
|
return PtInRegion32( hrgn, x, y );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* PtInRegion32 (GDI32.278)
|
|
*/
|
|
BOOL32 WINAPI PtInRegion32( HRGN32 hrgn, INT32 x, INT32 y )
|
|
{
|
|
RGNOBJ * obj;
|
|
BOOL32 result;
|
|
|
|
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
|
|
if (!obj->xrgn) result = FALSE;
|
|
else result = XPointInRegion( obj->xrgn, x, y );
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* RectInRegion16 (GDI.181)
|
|
*/
|
|
BOOL16 WINAPI RectInRegion16( HRGN16 hrgn, const RECT16 *rect )
|
|
{
|
|
RGNOBJ * obj;
|
|
BOOL16 result;
|
|
|
|
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
|
|
if (!obj->xrgn) result = FALSE;
|
|
else result = (XRectInRegion( obj->xrgn, rect->left, rect->top,
|
|
rect->right-rect->left,
|
|
rect->bottom-rect->top ) != RectangleOut);
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* RectInRegion32 (GDI32.281)
|
|
*/
|
|
BOOL32 WINAPI RectInRegion32( HRGN32 hrgn, const RECT32 *rect )
|
|
{
|
|
RGNOBJ * obj;
|
|
BOOL32 result;
|
|
|
|
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
|
|
if (!obj->xrgn) result = FALSE;
|
|
else result = (XRectInRegion( obj->xrgn, rect->left, rect->top,
|
|
rect->right-rect->left,
|
|
rect->bottom-rect->top ) != RectangleOut);
|
|
GDI_HEAP_UNLOCK( hrgn );
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* EqualRgn16 (GDI.72)
|
|
*/
|
|
BOOL16 WINAPI EqualRgn16( HRGN16 rgn1, HRGN16 rgn2 )
|
|
{
|
|
return EqualRgn32( rgn1, rgn2 );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* EqualRgn32 (GDI32.90)
|
|
*/
|
|
BOOL32 WINAPI EqualRgn32( HRGN32 rgn1, HRGN32 rgn2 )
|
|
{
|
|
RGNOBJ *obj1, *obj2;
|
|
BOOL32 result;
|
|
|
|
if (!(obj1 = (RGNOBJ *) GDI_GetObjPtr( rgn1, REGION_MAGIC ))) return FALSE;
|
|
if (!(obj2 = (RGNOBJ *) GDI_GetObjPtr( rgn2, REGION_MAGIC )))
|
|
{
|
|
GDI_HEAP_UNLOCK( rgn1 );
|
|
return FALSE;
|
|
}
|
|
if (!obj1->xrgn || !obj2->xrgn) result = (!obj1->xrgn && !obj2->xrgn);
|
|
else result = XEqualRegion( obj1->xrgn, obj2->xrgn );
|
|
GDI_HEAP_UNLOCK( rgn1 );
|
|
GDI_HEAP_UNLOCK( rgn2 );
|
|
return result;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* REGION_CopyRegion
|
|
*
|
|
* Copy region src into dest.
|
|
*/
|
|
static INT32 REGION_CopyRegion( RGNOBJ *src, RGNOBJ *dest )
|
|
{
|
|
Region tmprgn;
|
|
if (src->xrgn)
|
|
{
|
|
if (src->xrgn == dest->xrgn) return COMPLEXREGION;
|
|
tmprgn = XCreateRegion();
|
|
if (!dest->xrgn) dest->xrgn = XCreateRegion();
|
|
XUnionRegion( tmprgn, src->xrgn, dest->xrgn );
|
|
XDestroyRegion( tmprgn );
|
|
return COMPLEXREGION;
|
|
}
|
|
else
|
|
{
|
|
if (dest->xrgn) XDestroyRegion( dest->xrgn );
|
|
dest->xrgn = 0;
|
|
return NULLREGION;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* REGION_UnionRectWithRgn
|
|
*
|
|
* Add rectangle to region
|
|
*/
|
|
BOOL32 REGION_UnionRectWithRgn( HRGN32 hRgn, const RECT32 *rc )
|
|
{
|
|
RGNOBJ *rgnObj = (RGNOBJ*) GDI_GetObjPtr( hRgn, REGION_MAGIC );
|
|
XRectangle rect = { rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top };
|
|
BOOL32 ret = FALSE;
|
|
|
|
if( rgnObj )
|
|
{
|
|
if( !rgnObj->xrgn )
|
|
{
|
|
if (!(rgnObj->xrgn = XCreateRegion()))
|
|
{
|
|
GDI_FreeObject( hRgn );
|
|
return 0;
|
|
}
|
|
ret = SIMPLEREGION;
|
|
}
|
|
else
|
|
ret = COMPLEXREGION;
|
|
XUnionRectWithRegion( &rect, rgnObj->xrgn, rgnObj->xrgn );
|
|
GDI_HEAP_UNLOCK( hRgn );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* REGION_CreateFrameRgn
|
|
*
|
|
* Create a region that is a frame around another region
|
|
*/
|
|
BOOL32 REGION_FrameRgn( HRGN32 hDest, HRGN32 hSrc, INT32 x, INT32 y )
|
|
{
|
|
RGNOBJ *destObj,*srcObj;
|
|
Region result;
|
|
|
|
destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC );
|
|
srcObj = (RGNOBJ*) GDI_GetObjPtr( hSrc, REGION_MAGIC );
|
|
if (!srcObj->xrgn)
|
|
{
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc );
|
|
return FALSE;
|
|
}
|
|
REGION_CopyRegion( srcObj, destObj );
|
|
XShrinkRegion( destObj->xrgn, -x, -y );
|
|
result = XCreateRegion();
|
|
XSubtractRegion( destObj->xrgn, srcObj->xrgn, result );
|
|
XDestroyRegion( destObj->xrgn );
|
|
destObj->xrgn = result;
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CombineRgn16 (GDI.451)
|
|
*/
|
|
INT16 WINAPI CombineRgn16(HRGN16 hDest, HRGN16 hSrc1, HRGN16 hSrc2, INT16 mode)
|
|
{
|
|
return (INT16)CombineRgn32( hDest, hSrc1, hSrc2, mode );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CombineRgn32 (GDI32.19)
|
|
*
|
|
* Note: The behavior is correct even if src and dest regions are the same.
|
|
*/
|
|
INT32 WINAPI CombineRgn32(HRGN32 hDest, HRGN32 hSrc1, HRGN32 hSrc2, INT32 mode)
|
|
{
|
|
RGNOBJ *destObj, *src1Obj, *src2Obj;
|
|
Region destrgn;
|
|
INT32 result;
|
|
|
|
dprintf_region(stddeb, "CombineRgn: %04x,%04x -> %04x mode=%x\n",
|
|
hSrc1, hSrc2, hDest, mode );
|
|
|
|
if (!(destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC )))
|
|
return ERROR;
|
|
if (!(src1Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc1, REGION_MAGIC )))
|
|
{
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
return ERROR;
|
|
}
|
|
if (mode == RGN_COPY)
|
|
{
|
|
result = REGION_CopyRegion( src1Obj, destObj );
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
return result;
|
|
}
|
|
|
|
if (!(src2Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc2, REGION_MAGIC )))
|
|
{
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
return ERROR;
|
|
}
|
|
/* Some optimizations for null regions */
|
|
|
|
if (!src1Obj->xrgn || !src2Obj->xrgn)
|
|
{
|
|
switch(mode)
|
|
{
|
|
case RGN_DIFF:
|
|
if (src1Obj->xrgn)
|
|
{
|
|
result = REGION_CopyRegion( src1Obj, destObj );
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return result;
|
|
}
|
|
/* else fall through */
|
|
case RGN_AND:
|
|
if (destObj->xrgn) XDestroyRegion( destObj->xrgn );
|
|
destObj->xrgn = 0;
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return NULLREGION;
|
|
case RGN_OR:
|
|
case RGN_XOR:
|
|
if (src1Obj->xrgn)
|
|
result = REGION_CopyRegion( src1Obj, destObj );
|
|
else
|
|
result = REGION_CopyRegion( src2Obj, destObj );
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return result;
|
|
default:
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return ERROR;
|
|
}
|
|
}
|
|
|
|
/* Perform the operation with the two X regions */
|
|
|
|
if (!(destrgn = XCreateRegion()))
|
|
{
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return ERROR;
|
|
}
|
|
switch(mode)
|
|
{
|
|
case RGN_AND:
|
|
XIntersectRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
|
|
break;
|
|
case RGN_OR:
|
|
XUnionRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
|
|
break;
|
|
case RGN_XOR:
|
|
XXorRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
|
|
break;
|
|
case RGN_DIFF:
|
|
XSubtractRegion( src1Obj->xrgn, src2Obj->xrgn, destrgn );
|
|
break;
|
|
default:
|
|
XDestroyRegion( destrgn );
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return ERROR;
|
|
}
|
|
if (destObj->xrgn) XDestroyRegion( destObj->xrgn );
|
|
destObj->xrgn = destrgn;
|
|
if (XEmptyRegion(destObj->xrgn))
|
|
{
|
|
XDestroyRegion( destObj->xrgn );
|
|
destObj->xrgn = 0;
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return NULLREGION;
|
|
}
|
|
GDI_HEAP_UNLOCK( hDest );
|
|
GDI_HEAP_UNLOCK( hSrc1 );
|
|
GDI_HEAP_UNLOCK( hSrc2 );
|
|
return COMPLEXREGION;
|
|
}
|