ReactOS 0.4.15-dev-7788-g1ad9096
region.c File Reference
#include <win32k.h>
#include <suppress.h>
#include <debug.h>
Include dependency graph for region.c:

Go to the source code of this file.

Classes

struct  BRESINFO
 
struct  _EDGE_TABLE_ENTRY
 
struct  _SCANLINE_LIST
 
struct  EDGE_TABLE
 
struct  _SCANLINE_LISTBLOCK
 
struct  _POINTBLOCK
 

Macros

#define NDEBUG
 
#define COPY_RECTS(dest, src, nRects)
 
#define EMPTY_REGION(pReg)
 
#define REGION_NOT_EMPTY(pReg)   pReg->rdh.nCount
 
#define INRECT(r, x, y)
 
#define EXTENTCHECK(r1, r2)
 
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2)
 
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2)
 
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres)
 
#define BRESINCRPGONSTRUCT(bres)    BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
 
#define CLOCKWISE   1
 
#define COUNTERCLOCKWISE   -1
 
#define SLLSPERBLOCK   25
 
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
 
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
 
#define LARGE_COORDINATE   INT_MAX
 
#define SMALL_COORDINATE   INT_MIN
 
#define NUMPTSTOBUFFER   200
 
#define RGN_DEFAULT_RECTS   2
 

Typedefs

typedef struct _EDGE_TABLE_ENTRY EDGE_TABLE_ENTRY
 
typedef struct _SCANLINE_LIST SCANLINE_LIST
 
typedef struct _SCANLINE_LISTBLOCK SCANLINE_LISTBLOCK
 
typedef BOOL(FASTCALLoverlapProcp) (PREGION, PRECT, PRECT, PRECT, PRECT, INT, INT)
 
typedef BOOL(FASTCALLnonOverlapProcp) (PREGION, PRECT, PRECT, INT, INT)
 
typedef struct _POINTBLOCK POINTBLOCK
 

Functions

static BOOL REGION_bGrowBufferSize (_Inout_ PREGION prgn, _In_ UINT cRects)
 
static __inline BOOL REGION_bEnsureBufferSize (_Inout_ PREGION prgn, _In_ UINT cRects)
 
FORCEINLINE VOID REGION_vAddRect (_Inout_ PREGION prgn, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
 
static __inline BOOL REGION_bAddRect (_Inout_ PREGION prgn, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
 
INT FASTCALL REGION_Complexity (PREGION prgn)
 
static BOOL FASTCALL REGION_CopyRegion (PREGION dst, PREGION src)
 
static VOID FASTCALL REGION_SetExtents (PREGION pReg)
 
INT FASTCALL REGION_CropRegion (PREGION rgnDst, PREGION rgnSrc, const RECTL *rect)
 
static INT FASTCALL REGION_Coalesce (PREGION pReg, INT prevStart, INT curStart)
 
static BOOL FASTCALL REGION_RegionOp (PREGION newReg, PREGION reg1, PREGION reg2, overlapProcp overlapFunc, nonOverlapProcp nonOverlap1Func, nonOverlapProcp nonOverlap2Func)
 
static BOOL FASTCALL REGION_IntersectO (PREGION pReg, PRECTL r1, PRECTL r1End, PRECTL r2, PRECTL r2End, INT top, INT bottom)
 
static BOOL FASTCALL REGION_IntersectRegion (PREGION newReg, PREGION reg1, PREGION reg2)
 
static BOOL FASTCALL REGION_UnionNonO (PREGION pReg, PRECTL r, PRECTL rEnd, INT top, INT bottom)
 
static __inline BOOL REGION_bMergeRect (_Inout_ PREGION prgn, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
 
static BOOL FASTCALL REGION_UnionO (PREGION pReg, PRECTL r1, PRECTL r1End, PRECTL r2, PRECTL r2End, INT top, INT bottom)
 
static BOOL FASTCALL REGION_UnionRegion (PREGION newReg, PREGION reg1, PREGION reg2)
 
static BOOL FASTCALL REGION_SubtractNonO1 (PREGION pReg, PRECTL r, PRECTL rEnd, INT top, INT bottom)
 
static BOOL FASTCALL REGION_SubtractO (PREGION pReg, PRECTL r1, PRECTL r1End, PRECTL r2, PRECTL r2End, INT top, INT bottom)
 
static BOOL FASTCALL REGION_SubtractRegion (PREGION regD, PREGION regM, PREGION regS)
 
static BOOL FASTCALL REGION_XorRegion (PREGION dr, PREGION sra, PREGION srb)
 
BOOL FASTCALL REGION_UnionRectWithRgn (PREGION rgn, const RECTL *rect)
 
INT FASTCALL REGION_SubtractRectFromRgn (PREGION prgnDest, PREGION prgnSrc, const RECTL *prcl)
 
BOOL FASTCALL REGION_bCopy (PREGION dst, PREGION src)
 
BOOL FASTCALL REGION_bIntersectRegion (PREGION newReg, PREGION reg1, PREGION reg2)
 
static BOOL REGION_bMakeSimpleFrameRgn (_Inout_ PREGION prgn, _In_ PRECTL prclSrc, _In_ INT cx, _In_ INT cy)
 
static BOOL REGION_bMakeFrameRegion (_Inout_ PREGION prgnDest, _Inout_ PREGION prgnSrc, _In_ INT cx, _In_ INT cy)
 
HRGN FASTCALL GreCreateFrameRgn (HRGN hrgn, INT cx, INT cy)
 
BOOL FASTCALL REGION_bXformRgn (_Inout_ PREGION prgn, _In_ PMATRIX pmx)
 
PREGION FASTCALL REGION_AllocRgnWithHandle (INT nReg)
 
BOOL NTAPI REGION_bAllocRgnAttr (PREGION prgn)
 
PREGION FASTCALL REGION_AllocUserRgnWithHandle (INT nRgn)
 
static VOID REGION_vSyncRegion (_In_ PREGION prgn)
 
PREGION FASTCALL REGION_LockRgn (_In_ HRGN hrgn)
 
VOID FASTCALL REGION_UnlockRgn (_In_ PREGION prgn)
 
PREGION FASTCALL IntSysCreateRectpRgn (INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
 
VOID NTAPI REGION_vCleanup (PVOID ObjectBody)
 
VOID FASTCALL REGION_Delete (PREGION pRgn)
 
BOOL FASTCALL IntGdiSetRegionOwner (HRGN hRgn, DWORD OwnerMask)
 
INT FASTCALL IntGdiCombineRgn (PREGION prgnDest, PREGION prgnSrc1, PREGION prgnSrc2, INT iCombineMode)
 
INT FASTCALL REGION_GetRgnBox (PREGION Rgn, PRECTL pRect)
 
INT APIENTRY IntGdiGetRgnBox (HRGN hRgn, PRECTL pRect)
 
BOOL FASTCALL REGION_PtInRegion (PREGION prgn, INT X, INT Y)
 
BOOL FASTCALL REGION_RectInRegion (PREGION Rgn, const RECTL *rect)
 
VOID FASTCALL REGION_SetRectRgn (PREGION rgn, INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
 
BOOL FASTCALL REGION_bOffsetRgn (_Inout_ PREGION prgn, _In_ INT cx, _In_ INT cy)
 
static VOID FASTCALL REGION_InsertEdgeInET (EDGE_TABLE *ET, EDGE_TABLE_ENTRY *ETE, INT scanline, SCANLINE_LISTBLOCK **SLLBlock, INT *iSLLBlock)
 
static VOID FASTCALL REGION_loadAET (EDGE_TABLE_ENTRY *AET, EDGE_TABLE_ENTRY *ETEs)
 
static VOID FASTCALL REGION_computeWAET (EDGE_TABLE_ENTRY *AET)
 
static BOOL FASTCALL REGION_InsertionSort (EDGE_TABLE_ENTRY *AET)
 
static VOID FASTCALL REGION_FreeStorage (SCANLINE_LISTBLOCK *pSLLBlock)
 
static INT FASTCALL REGION_PtsToRegion (INT numFullPtBlocks, INT iCurPtBlock, POINTBLOCK *FirstPtBlock, PREGION reg)
 
static VOID FASTCALL REGION_CreateETandAET (const ULONG *Count, INT nbpolygons, const POINT *pts, EDGE_TABLE *ET, EDGE_TABLE_ENTRY *AET, EDGE_TABLE_ENTRY *pETEs, SCANLINE_LISTBLOCK *pSLLBlock)
 
BOOL FASTCALL REGION_SetPolyPolygonRgn (_Inout_ PREGION prgn, _In_ const POINT *ppt, _In_ const ULONG *pcPoints, _In_ ULONG cPolygons, _In_ INT iMode)
 
HRGN NTAPI GreCreatePolyPolygonRgn (_In_ const POINT *ppt, _In_ const ULONG *pcPoints, _In_ ULONG cPolygons, _In_ INT iMode)
 
BOOL FASTCALL IntRectInRegion (HRGN hRgn, LPRECTL rc)
 
INT APIENTRY NtGdiCombineRgn (IN HRGN hrgnDst, IN HRGN hrgnSrc1, IN HRGN hrgnSrc2, IN INT iMode)
 
HRGN APIENTRY NtGdiCreateEllipticRgn (INT Left, INT Top, INT Right, INT Bottom)
 
HRGN APIENTRY NtGdiCreateRectRgn (INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
 
HRGN APIENTRY NtGdiCreateRoundRectRgn (INT left, INT top, INT right, INT bottom, INT ellipse_width, INT ellipse_height)
 
BOOL APIENTRY NtGdiEqualRgn (HRGN hSrcRgn1, HRGN hSrcRgn2)
 
HRGN APIENTRY NtGdiExtCreateRegion (OPTIONAL LPXFORM Xform, DWORD Count, LPRGNDATA RgnData)
 
INT APIENTRY NtGdiGetRgnBox (HRGN hRgn, PRECTL pRect)
 
INT APIENTRY NtGdiOffsetRgn (_In_ HRGN hrgn, _In_ INT cx, _In_ INT cy)
 
BOOL APIENTRY NtGdiPtInRegion (_In_ HRGN hrgn, _In_ INT x, _In_ INT y)
 
__kernel_entry BOOL APIENTRY NtGdiRectInRegion (_In_ HRGN hrgn, _Inout_ LPRECT prclUnsafe)
 
BOOL APIENTRY NtGdiSetRectRgn (_In_ HRGN hrgn, _In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
 
 _Success_ (return!=0)
 

Variables

PREGION prgnDefault = NULL
 
HRGN hrgnDefault = NULL
 

Macro Definition Documentation

◆ BRESINCRPGON

#define BRESINCRPGON (   d,
  minval,
  m,
  m1,
  incr1,
  incr2 
)
Value:
{ \
if (m1 > 0) { \
if (d > 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} else {\
if (d >= 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} \
}
const GLfloat * m
Definition: glext.h:10848
#define d
Definition: ke_i.h:81

Definition at line 214 of file region.c.

◆ BRESINCRPGONSTRUCT

#define BRESINCRPGONSTRUCT (   bres)     BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)

Definition at line 255 of file region.c.

◆ BRESINITPGON

#define BRESINITPGON (   dy,
  x1,
  x2,
  xStart,
  d,
  m,
  m1,
  incr1,
  incr2 
)
Value:
{ \
int dx; /* Local storage */ \
\
/* \
* If the edge is horizontal, then it is ignored \
* and assumed not to be processed. Otherwise, do this stuff. \
*/ \
if ((dy) != 0) { \
xStart = (x1); \
dx = (x2) - xStart; \
if (dx < 0) { \
m = dx / (dy); \
m1 = m - 1; \
incr1 = -2 * dx + 2 * (dy) * m1; \
incr2 = -2 * dx + 2 * (dy) * m; \
d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
} else { \
m = dx / (dy); \
m1 = m + 1; \
incr1 = 2 * dx - 2 * (dy) * m1; \
incr2 = 2 * dx - 2 * (dy) * m; \
d = -2 * m * (dy) + 2 * dx; \
} \
} \
}
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708

Definition at line 191 of file region.c.

◆ BRESINITPGONSTRUCT

#define BRESINITPGONSTRUCT (   dmaj,
  min1,
  min2,
  bres 
)
Value:
BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
bres.m, bres.m1, bres.incr1, bres.incr2)
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2)
Definition: region.c:191

Definition at line 251 of file region.c.

◆ CLOCKWISE

#define CLOCKWISE   1

Definition at line 307 of file region.c.

◆ COPY_RECTS

#define COPY_RECTS (   dest,
  src,
  nRects 
)
Value:
do { \
PRECTL xDest = (dest); \
PRECTL xSrc = (src); \
UINT xRects = (nRects); \
while (xRects-- > 0) { \
*(xDest++) = *(xSrc++); \
} \
} while (0)
GLenum src
Definition: glext.h:6340
static char * dest
Definition: rtl.c:135
unsigned int UINT
Definition: ndis.h:50

Definition at line 135 of file region.c.

◆ COUNTERCLOCKWISE

#define COUNTERCLOCKWISE   -1

Definition at line 308 of file region.c.

◆ EMPTY_REGION

#define EMPTY_REGION (   pReg)
Value:
{ \
(pReg)->rdh.nCount = 0; \
(pReg)->rdh.rcBound.left = (pReg)->rdh.rcBound.top = 0; \
(pReg)->rdh.rcBound.right = (pReg)->rdh.rcBound.bottom = 0; \
(pReg)->rdh.iType = RDH_RECTANGLES; \
}
#define RDH_RECTANGLES
Definition: wingdi.h:669

Definition at line 148 of file region.c.

◆ EVALUATEEDGEEVENODD

#define EVALUATEEDGEEVENODD (   pAET,
  pPrevAET,
  y 
)
Value:
{ \
if (pAET->ymax == y) { /* Leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548

Definition at line 381 of file region.c.

◆ EVALUATEEDGEWINDING

#define EVALUATEEDGEWINDING (   pAET,
  pPrevAET,
  y,
  fixWAET 
)
Value:
{ \
if (pAET->ymax == y) { /* Leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
fixWAET = 1; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}

Definition at line 359 of file region.c.

◆ EXTENTCHECK

#define EXTENTCHECK (   r1,
  r2 
)
Value:
((r1)->right > (r2)->left && \
(r1)->left < (r2)->right && \
(r1)->bottom > (r2)->top && \
(r1)->top < (r2)->bottom)
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLdouble GLdouble right
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
GLint GLint bottom
Definition: glext.h:7726
static DNS_RECORDW r1
Definition: record.c:37
static DNS_RECORDW r2
Definition: record.c:38

Definition at line 166 of file region.c.

◆ INRECT

#define INRECT (   r,
  x,
  y 
)
Value:
( ( ((r).right > x)) && \
( ((r).left <= x)) && \
( ((r).bottom > y)) && \
( ((r).top <= y)) )
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble GLdouble GLdouble r
Definition: gl.h:2055

Definition at line 157 of file region.c.

◆ LARGE_COORDINATE

#define LARGE_COORDINATE   INT_MAX

Definition at line 401 of file region.c.

◆ NDEBUG

#define NDEBUG

Definition at line 126 of file region.c.

◆ NUMPTSTOBUFFER

#define NUMPTSTOBUFFER   200

Definition at line 512 of file region.c.

◆ REGION_NOT_EMPTY

#define REGION_NOT_EMPTY (   pReg)    pReg->rdh.nCount

Definition at line 155 of file region.c.

◆ RGN_DEFAULT_RECTS

#define RGN_DEFAULT_RECTS   2

Definition at line 514 of file region.c.

◆ SLLSPERBLOCK

#define SLLSPERBLOCK   25

Definition at line 339 of file region.c.

◆ SMALL_COORDINATE

#define SMALL_COORDINATE   INT_MIN

Definition at line 402 of file region.c.

Typedef Documentation

◆ EDGE_TABLE_ENTRY

◆ nonOverlapProcp

typedef BOOL(FASTCALL * nonOverlapProcp) (PREGION, PRECT, PRECT, INT, INT)

Definition at line 509 of file region.c.

◆ overlapProcp

typedef BOOL(FASTCALL * overlapProcp) (PREGION, PRECT, PRECT, PRECT, PRECT, INT, INT)

Definition at line 508 of file region.c.

◆ POINTBLOCK

◆ SCANLINE_LIST

◆ SCANLINE_LISTBLOCK

Function Documentation

◆ _Success_()

_Success_ ( return!  = 0)

MSDN: GetRegionData, Return Values:

"If the function succeeds and dwCount specifies an adequate number of bytes, the return value is always dwCount. If dwCount is too small or the function fails, the return value is 0. If lpRgnData is NULL, the return value is the required number of bytes. If the function fails, the return value is zero."

Definition at line 4082 of file region.c.

4093{
4094 ULONG cjRects, cjSize;
4095 PREGION prgn;
4096
4097 /* Lock the region */
4098 prgn = REGION_LockRgn(hrgn);
4099 if (prgn == NULL)
4100 {
4102 return 0;
4103 }
4104
4105 /* Calculate the region sizes */
4106 cjRects = prgn->rdh.nCount * sizeof(RECT);
4107 cjSize = cjRects + sizeof(RGNDATAHEADER);
4108
4109 /* Check if region data is requested */
4110 if (lpRgnData)
4111 {
4112 /* Check if the buffer is large enough */
4113 if (cjBuffer >= cjSize)
4114 {
4115 /* Probe the buffer and copy the data */
4116 _SEH2_TRY
4117 {
4118 ProbeForWrite(lpRgnData, cjSize, sizeof(ULONG));
4119 RtlCopyMemory(lpRgnData, &prgn->rdh, sizeof(RGNDATAHEADER));
4120 RtlCopyMemory(lpRgnData->Buffer, prgn->Buffer, cjRects);
4121 lpRgnData->rdh.iType = RDH_RECTANGLES;
4122 lpRgnData->rdh.nRgnSize = cjRects;
4123 }
4125 {
4127 cjSize = 0;
4128 }
4129 _SEH2_END;
4130 }
4131 else
4132 {
4133 /* Buffer is too small */
4135 cjSize = 0;
4136 }
4137 }
4138
4139 /* Unlock the region and return the size */
static HRGN hrgn
struct _RGNDATAHEADER RGNDATAHEADER
#define NULL
Definition: types.h:112
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_In_ ULONG cjBuffer
Definition: ntgdi.h:2860
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
Definition: region.h:8
RECTL * Buffer
Definition: region.h:16
RGNDATAHEADER rdh
Definition: region.h:15
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define RECT
Definition: precomp.h:26
PREGION FASTCALL REGION_LockRgn(_In_ HRGN hrgn)
Definition: region.c:2358
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
_In_ ULONG cjSize
Definition: winddi.h:3634

◆ GreCreateFrameRgn()

HRGN FASTCALL GreCreateFrameRgn ( HRGN  hrgn,
INT  cx,
INT  cy 
)

Definition at line 2025 of file region.c.

2032{
2033 PREGION prgnFrame, prgnSrc;
2034 HRGN hrgnFrame;
2035
2036 /* Allocate a new region */
2037 prgnFrame = REGION_AllocUserRgnWithHandle(1);
2038 if (prgnFrame == NULL)
2039 {
2041 return NULL;
2042 }
2043
2044 /* Lock the source region */
2045 prgnSrc = REGION_LockRgn(hrgn);
2046 if (prgnSrc == NULL)
2047 {
2048 REGION_Delete(prgnFrame);
2049 return FALSE;
2050 }
2051
2052 if (REGION_bMakeFrameRegion(prgnFrame, prgnSrc, cx, cy))
2053 {
2054 hrgnFrame = prgnFrame->BaseObject.hHmgr;
2055 REGION_UnlockRgn(prgnFrame);
2056 }
2057 else
2058 {
2059 REGION_Delete(prgnFrame);
2060 hrgnFrame = NULL;
2061 }
2062
HGDIOBJ hHmgr(VOID)
Definition: baseobj.hpp:95
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define FALSE
Definition: types.h:117
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
BASEOBJECT BaseObject
Definition: region.h:11
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2449
VOID FASTCALL REGION_UnlockRgn(_In_ PREGION prgn)
Definition: region.c:2373
PREGION FASTCALL REGION_AllocUserRgnWithHandle(INT nRgn)
Definition: region.c:2294
static BOOL REGION_bMakeFrameRegion(_Inout_ PREGION prgnDest, _Inout_ PREGION prgnSrc, _In_ INT cx, _In_ INT cy)
Definition: region.c:1940

Referenced by NtGdiFrameRgn().

◆ GreCreatePolyPolygonRgn()

HRGN NTAPI GreCreatePolyPolygonRgn ( _In_ const POINT ppt,
_In_ const ULONG pcPoints,
_In_ ULONG  cPolygons,
_In_ INT  iMode 
)

Definition at line 3452 of file region.c.

3460{
3461 PREGION prgn;
3462 HRGN hrgn;
3463
3464 /* Allocate a new region */
3466 if (prgn == NULL)
3467 {
3469 return NULL;
3470 }
3471
3472 /* Call the internal function and check for success */
3473 if (REGION_SetPolyPolygonRgn(prgn, ppt, pcPoints, cPolygons, iMode))
3474 {
3475 /* Success, get the handle and unlock the region */
3476 hrgn = prgn->BaseObject.hHmgr;
3477 REGION_UnlockRgn(prgn);
3478 }
3479 else
3480 {
3481 /* Failure, delete the region */
3482 REGION_Delete(prgn);
3483 hrgn = NULL;
3484 }
BOOL FASTCALL REGION_SetPolyPolygonRgn(_Inout_ PREGION prgn, _In_ const POINT *ppt, _In_ const ULONG *pcPoints, _In_ ULONG cPolygons, _In_ INT iMode)
Definition: region.c:3254
_In_ ULONG iMode
Definition: winddi.h:3520

Referenced by NtGdiPolyPolyDraw().

◆ IntGdiCombineRgn()

INT FASTCALL IntGdiCombineRgn ( PREGION  prgnDest,
PREGION  prgnSrc1,
PREGION  prgnSrc2,
INT  iCombineMode 
)

Definition at line 2487 of file region.c.

2495{
2496 BOOL Ret = TRUE;
2497
2498 if (prgnDest == NULL)
2499 {
2500 DPRINT("IntGdiCombineRgn: hDest unavailable\n");
2501 return ERROR;
2502 }
2503
2504 if (prgnSrc1 == NULL)
2505 {
2506 DPRINT("IntGdiCombineRgn: hSrc1 unavailable\n");
2507 return ERROR;
2508 }
2509
2510 if (iCombineMode == RGN_COPY)
2511 {
2512 if (!REGION_CopyRegion(prgnDest, prgnSrc1))
2513 return ERROR;
2514
2515 return REGION_Complexity(prgnDest);
2516 }
2517
2518 if (prgnSrc2 == NULL)
2519 {
2520 DPRINT1("IntGdiCombineRgn requires hSrc2 != NULL for combine mode %d!\n", iCombineMode);
2521 ASSERT(FALSE);
2522 return ERROR;
2523 }
2524
2525 switch (iCombineMode)
2526 {
2527 case RGN_AND:
2528 Ret = REGION_IntersectRegion(prgnDest, prgnSrc1, prgnSrc2);
2529 break;
2530 case RGN_OR:
2531 Ret = REGION_UnionRegion(prgnDest, prgnSrc1, prgnSrc2);
2532 break;
2533 case RGN_XOR:
2534 Ret = REGION_XorRegion(prgnDest, prgnSrc1, prgnSrc2);
2535 break;
2536 case RGN_DIFF:
2537 Ret = REGION_SubtractRegion(prgnDest, prgnSrc1, prgnSrc2);
2538 break;
2539 }
#define DPRINT1
Definition: precomp.h:8
#define TRUE
Definition: types.h:120
#define ERROR(name)
Definition: error_private.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ASSERT(a)
Definition: mode.c:44
#define DPRINT
Definition: sndvol32.h:71
INT FASTCALL REGION_Complexity(PREGION prgn)
Definition: region.c:554
static BOOL FASTCALL REGION_UnionRegion(PREGION newReg, PREGION reg1, PREGION reg2)
Definition: region.c:1464
static BOOL FASTCALL REGION_XorRegion(PREGION dr, PREGION sra, PREGION srb)
Definition: region.c:1753
static BOOL FASTCALL REGION_IntersectRegion(PREGION newReg, PREGION reg1, PREGION reg2)
Definition: region.c:1292
static BOOL FASTCALL REGION_SubtractRegion(PREGION regD, PREGION regM, PREGION regS)
Definition: region.c:1717
static BOOL FASTCALL REGION_CopyRegion(PREGION dst, PREGION src)
Definition: region.c:574
#define RGN_DIFF
Definition: wingdi.h:358
#define RGN_COPY
Definition: wingdi.h:357
#define RGN_AND
Definition: wingdi.h:356
#define RGN_XOR
Definition: wingdi.h:360
#define RGN_OR
Definition: wingdi.h:359

Referenced by _Success_(), co_IntGetUpdateRgn(), co_UserRedrawWindow(), co_VIS_WindowLayoutChanged(), co_WinPosSetWindowPos(), DC_vCopyState(), DceUpdateVisRgn(), ForceNCPaintErase(), IntGdiBitBltRgn(), IntGdiFillRgn(), IntInvalidateWindows(), IntScrollWindowEx(), IntValidateParents(), NtGdiCombineRgn(), NtGdiGetRandomRgn(), REGION_LPTODP(), UserScrollDC(), and VIS_ComputeVisibleRegion().

◆ IntGdiGetRgnBox()

INT APIENTRY IntGdiGetRgnBox ( HRGN  hRgn,
PRECTL  pRect 
)

Definition at line 2561 of file region.c.

2567{
2568 PREGION Rgn;
2569 DWORD ret;
2570
2571 Rgn = REGION_LockRgn(hRgn);
2572 if (Rgn == NULL)
2573 {
2574 return ERROR;
2575 }
2576
2577 ret = REGION_GetRgnBox(Rgn, pRect);
2578 REGION_UnlockRgn(Rgn);
unsigned long DWORD
Definition: ntddk_ex.h:95
static HRGN hRgn
Definition: mapping.c:33
int ret
INT FASTCALL REGION_GetRgnBox(PREGION Rgn, PRECTL pRect)
Definition: region.c:2543

Referenced by co_UserGetUpdateRect(), and IntGetNCUpdateRgn().

◆ IntGdiSetRegionOwner()

BOOL FASTCALL IntGdiSetRegionOwner ( HRGN  hRgn,
DWORD  OwnerMask 
)

Definition at line 2459 of file region.c.

2463{
2464 PREGION prgn;
2465 PRGN_ATTR prgnattr;
2466 PPROCESSINFO ppi;
2467
2468 prgn = REGION_LockRgn(hRgn);
2469 if (prgn == NULL)
2470 {
2471 return FALSE;
2472 }
2473
2474 prgnattr = prgn->prgnattr;
2475 if (prgnattr != &prgn->rgnattr)
2476 {
2478 prgn->prgnattr = &prgn->rgnattr;
2480 GdiPoolFree(ppi->pPoolRgnAttr, prgnattr);
2481 }
2482
2483 REGION_UnlockRgn(prgn);
VOID NTAPI GdiPoolFree(PGDI_POOL pPool, PVOID pvAlloc)
Definition: gdipool.c:233
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
struct _GDI_POOL * pPoolRgnAttr
Definition: win32.h:293
RGN_ATTR rgnattr
Definition: region.h:13
_Notnull_ PRGN_ATTR prgnattr
Definition: region.h:12
VOID NTAPI GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr)
Definition: gdiobj.c:1096

Referenced by co_UserFreeWindow(), ForceNCPaintErase(), IntBeginPaint(), IntGetNCUpdateRgn(), IntInvalidateWindows(), SelectWindowRgn(), and UserUpdateMonitorSize().

◆ IntRectInRegion()

BOOL FASTCALL IntRectInRegion ( HRGN  hRgn,
LPRECTL  rc 
)

Definition at line 3488 of file region.c.

3494{
3495 PREGION Rgn;
3496 BOOL Ret;
3497
3498 Rgn = REGION_LockRgn(hRgn);
3499 if (Rgn == NULL)
3500 {
3501 return ERROR;
3502 }
3503
3504 Ret = REGION_RectInRegion(Rgn, rc);
BOOL FASTCALL REGION_RectInRegion(PREGION Rgn, const RECTL *rect)
Definition: region.c:2605

Referenced by NtGdiRectInRegion().

◆ IntSysCreateRectpRgn()

PREGION FASTCALL IntSysCreateRectpRgn ( INT  LeftRect,
INT  TopRect,
INT  RightRect,
INT  BottomRect 
)

Definition at line 2407 of file region.c.

2415{
2416 PREGION prgn;
2417
2418 /* Allocate a region, without a handle */
2420 if (prgn == NULL)
2421 {
2422 return NULL;
2423 }
2424
2425 /* Initialize it */
2426 prgn->Buffer = &prgn->rdh.rcBound;
2427 prgn->prgnattr = &prgn->rgnattr;
2429 REGION_SetRectRgn(prgn, LeftRect, TopRect, RightRect, BottomRect);
@ BASEFLAG_LOOKASIDE
Definition: gdiobj.h:58
#define ATTR_RGN_VALID
Definition: ntgdihdl.h:195
@ GDIObjType_RGN_TYPE
Definition: ntgdityp.h:124
struct _REGION * PREGION
ULONG AttrFlags
Definition: ntgdihdl.h:256
POBJ NTAPI GDIOBJ_AllocateObject(UCHAR objt, ULONG cjSize, FLONG fl)
Definition: gdiobj.c:562
VOID FASTCALL REGION_SetRectRgn(PREGION rgn, INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
Definition: region.c:2665

Referenced by _Success_(), CLIPPING_UpdateGCRegion(), co_UserRedrawWindow(), co_VIS_WindowLayoutChanged(), co_WinPosSetWindowPos(), DC_InitHack(), DC_vCopyState(), DC_vInitDc(), DC_vUpdateDC(), DceGetVisRgn(), DceUpdateVisRgn(), IntGdiBitBltRgn(), IntGdiFillRgn(), IntGdiSetMetaRgn(), IntInvalidateWindows(), IntScrollWindowEx(), IntSetDefaultRegion(), NtGdiSelectClipPath(), and PATH_FillPathEx().

◆ NtGdiCombineRgn()

INT APIENTRY NtGdiCombineRgn ( IN HRGN  hrgnDst,
IN HRGN  hrgnSrc1,
IN HRGN  hrgnSrc2,
IN INT  iMode 
)

Definition at line 3511 of file region.c.

3519{
3520 HRGN ahrgn[3];
3521 PREGION aprgn[3];
3522 INT iResult;
3523
3524 /* Validate the combine mode */
3525 if ((iMode < RGN_AND) || (iMode > RGN_COPY))
3526 {
3527 return ERROR;
3528 }
3529
3530 /* Validate that we have the required regions */
3531 if ((hrgnDst == NULL) ||
3532 (hrgnSrc1 == NULL) ||
3533 ((iMode != RGN_COPY) && (hrgnSrc2 == NULL)))
3534 {
3535 DPRINT1("NtGdiCombineRgn invalid parameters: %p, %p, %p, %d\n",
3536 hrgnDst, hrgnSrc1, hrgnSrc2, iMode);
3538 return ERROR;
3539 }
3540
3541 /* Lock all regions */
3542 ahrgn[0] = hrgnDst;
3543 ahrgn[1] = hrgnSrc1;
3544 ahrgn[2] = iMode != RGN_COPY ? hrgnSrc2 : NULL;
3546 {
3547 DPRINT1("NtGdiCombineRgn failed to lock regions: %p, %p, %p, %d\n",
3548 hrgnDst, hrgnSrc1, hrgnSrc2, iMode);
3549 return ERROR;
3550 }
3551
3552 /* HACK: Sync usermode attributes */
3553 REGION_vSyncRegion(aprgn[0]);
3554 if (aprgn[1] != aprgn[0])
3555 REGION_vSyncRegion(aprgn[1]);
3556 if ((aprgn[2] != NULL) && (aprgn[2] != aprgn[0]) && (aprgn[2] != aprgn[1]))
3557 REGION_vSyncRegion(aprgn[2]);
3558
3559 /* Call the internal function */
3560 iResult = IntGdiCombineRgn(aprgn[0], aprgn[1], aprgn[2], iMode);
3561
3562 /* Unlock and return */
3563 REGION_UnlockRgn(aprgn[0]);
3564 REGION_UnlockRgn(aprgn[1]);
3565 if (aprgn[2] != NULL)
3566 REGION_UnlockRgn(aprgn[2]);
int32_t INT
Definition: typedefs.h:58
BOOL NTAPI GDIOBJ_bLockMultipleObjects(IN ULONG ulCount, IN HGDIOBJ *ahObj, OUT PGDIOBJ *apObj, IN UCHAR objt)
Definition: gdiobj.c:1031
static VOID REGION_vSyncRegion(_In_ PREGION prgn)
Definition: region.c:2315
INT FASTCALL IntGdiCombineRgn(PREGION prgnDest, PREGION prgnSrc1, PREGION prgnSrc2, INT iCombineMode)
Definition: region.c:2487
_In_ HANDLE hrgnSrc1
Definition: winddi.h:4295
_In_ HANDLE _In_ HANDLE hrgnSrc2
Definition: winddi.h:4296

◆ NtGdiCreateEllipticRgn()

HRGN APIENTRY NtGdiCreateEllipticRgn ( INT  Left,
INT  Top,
INT  Right,
INT  Bottom 
)

Definition at line 3570 of file region.c.

3578{
3579 return NtGdiCreateRoundRectRgn(Left,
3580 Top,
3581 Right, Bottom,
static LPHIST_ENTRY Bottom
Definition: history.c:54
static LPHIST_ENTRY Top
Definition: history.c:53
HRGN APIENTRY NtGdiCreateRoundRectRgn(INT left, INT top, INT right, INT bottom, INT ellipse_width, INT ellipse_height)
Definition: region.c:3614

◆ NtGdiCreateRectRgn()

HRGN APIENTRY NtGdiCreateRectRgn ( INT  LeftRect,
INT  TopRect,
INT  RightRect,
INT  BottomRect 
)

Definition at line 3585 of file region.c.

3593{
3594 PREGION pRgn;
3595 HRGN hRgn;
3596
3597 /* Allocate region data structure with space for 1 RECTL */
3599 if (pRgn == NULL)
3600 {
3602 return NULL;
3603 }
3604
3605 hRgn = pRgn->BaseObject.hHmgr;
3606
3607 REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect);
3608 REGION_UnlockRgn(pRgn);
3609
3610 DPRINT("Returning %p.\n", hRgn);

◆ NtGdiCreateRoundRectRgn()

HRGN APIENTRY NtGdiCreateRoundRectRgn ( INT  left,
INT  top,
INT  right,
INT  bottom,
INT  ellipse_width,
INT  ellipse_height 
)

Definition at line 3614 of file region.c.

3624{
3625 PREGION obj;
3626 HRGN hrgn;
3627 int a, b, i, x, y;
3628 INT64 asq, bsq, dx, dy, err;
3629 RECT *rects;
3630
3631 /* Make the dimensions sensible */
3632 if (left > right)
3633 {
3634 INT tmp = left;
3635 left = right;
3636 right = tmp;
3637 }
3638
3639 if (top > bottom)
3640 {
3641 INT tmp = top;
3642 top = bottom;
3643 bottom = tmp;
3644 }
3645
3646 /* the region is for the rectangle interior, but only at right and bottom for some reason */
3647 right--;
3648 bottom--;
3649
3650 ellipse_width = min( right - left, abs( ellipse_width ));
3651 ellipse_height = min( bottom - top, abs( ellipse_height ));
3652
3653 /* Check if we can do a normal rectangle instead */
3654
3655 if ((ellipse_width < 2) || (ellipse_height < 2))
3657
3658 obj = REGION_AllocUserRgnWithHandle( ellipse_height );
3659 if (obj == NULL)
3660 return 0;
3661
3662 hrgn = obj->BaseObject.hHmgr;
3663
3664 obj->rdh.rcBound.left = left;
3665 obj->rdh.rcBound.top = top;
3666 obj->rdh.rcBound.right = right;
3667 obj->rdh.rcBound.bottom = bottom;
3668 rects = obj->Buffer;
3669
3670 /* based on an algorithm by Alois Zingl */
3671
3672 a = ellipse_width - 1;
3673 b = ellipse_height - 1;
3674 asq = (INT64)8 * a * a;
3675 bsq = (INT64)8 * b * b;
3676 dx = (INT64)4 * b * b * (1 - a);
3677 dy = (INT64)4 * a * a * (1 + (b % 2));
3678 err = dx + dy + a * a * (b % 2);
3679
3680 x = 0;
3681 y = ellipse_height / 2;
3682
3683 rects[y].left = left;
3684 rects[y].right = right;
3685
3686 while (x <= ellipse_width / 2)
3687 {
3688 INT64 e2 = 2 * err;
3689 if (e2 >= dx)
3690 {
3691 x++;
3692 err += dx += bsq;
3693 }
3694 if (e2 <= dy)
3695 {
3696 y++;
3697 err += dy += asq;
3698 rects[y].left = left + x;
3699 rects[y].right = right - x;
3700 }
3701 }
3702 for (i = 0; i < ellipse_height / 2; i++)
3703 {
3704 rects[i].left = rects[b - i].left;
3705 rects[i].right = rects[b - i].right;
3706 rects[i].top = top + i;
3707 rects[i].bottom = rects[i].top + 1;
3708 }
3709 for (; i < ellipse_height; i++)
3710 {
3711 rects[i].top = bottom - ellipse_height + i;
3712 rects[i].bottom = rects[i].top + 1;
3713 }
3714 rects[ellipse_height / 2].top = top + ellipse_height / 2; /* extend to top of rectangle */
3715
signed long long INT64
#define abs(i)
Definition: fconv.c:206
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define min(a, b)
Definition: monoChain.cc:55
__kernel_entry W32KAPI HRGN APIENTRY NtGdiCreateRectRgn(_In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
#define err(...)
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306

Referenced by NtGdiCreateEllipticRgn().

◆ NtGdiEqualRgn()

BOOL APIENTRY NtGdiEqualRgn ( HRGN  hSrcRgn1,
HRGN  hSrcRgn2 
)

Definition at line 3719 of file region.c.

3725{
3726 HRGN ahrgn[2];
3727 PREGION aprgn[2];
3728 PREGION rgn1, rgn2;
3729 PRECTL tRect1, tRect2;
3730 ULONG i;
3731 BOOL bRet = FALSE;
3732
3733 /* Check if we got 2 regions */
3734 if ((hSrcRgn1 == NULL) || (hSrcRgn2 == NULL))
3735 {
3736 return FALSE;
3737 }
3738
3739 /* Check if these are the same regions */
3740 if (hSrcRgn1 == hSrcRgn2)
3741 {
3742 /* Make sure this region is valid */
3744 GreIsHandleValid(hSrcRgn1))
3745 {
3746 return TRUE;
3747 }
3748 return FALSE;
3749 }
3750
3751 /* Lock both regions */
3752 ahrgn[0] = hSrcRgn1;
3753 ahrgn[1] = hSrcRgn2;
3755 {
3756 DPRINT1("NtGdiEqualRgn failed to lock regions: %p, %p\n",
3757 hSrcRgn1, hSrcRgn2);
3758 return FALSE;
3759 }
3760
3761 REGION_vSyncRegion(aprgn[0]);
3762 REGION_vSyncRegion(aprgn[1]);
3763
3764 rgn1 = aprgn[0];
3765 rgn2 = aprgn[1];
3766
3767 if (rgn1->rdh.nCount != rgn2->rdh.nCount)
3768 goto exit;
3769
3770 if (rgn1->rdh.nCount == 0)
3771 {
3772 bRet = TRUE;
3773 goto exit;
3774 }
3775
3776 if ((rgn1->rdh.rcBound.left != rgn2->rdh.rcBound.left) ||
3777 (rgn1->rdh.rcBound.right != rgn2->rdh.rcBound.right) ||
3778 (rgn1->rdh.rcBound.top != rgn2->rdh.rcBound.top) ||
3779 (rgn1->rdh.rcBound.bottom != rgn2->rdh.rcBound.bottom))
3780 goto exit;
3781
3782 tRect1 = rgn1->Buffer;
3783 tRect2 = rgn2->Buffer;
3784
3785 if ((tRect1 == NULL) || (tRect2 == NULL))
3786 goto exit;
3787
3788 for (i=0; i < rgn1->rdh.nCount; i++)
3789 {
3790 if ((tRect1[i].left != tRect2[i].left) ||
3791 (tRect1[i].right != tRect2[i].right) ||
3792 (tRect1[i].top != tRect2[i].top) ||
3793 (tRect1[i].bottom != tRect2[i].bottom))
3794 goto exit;
3795 }
3796
3797 bRet = TRUE;
3798
3799exit:
3800 REGION_UnlockRgn(rgn1);
#define GDI_HANDLE_GET_TYPE(h)
Definition: gdi.h:31
@ GDILoObjType_LO_REGION_TYPE
Definition: gdi_private.h:38
#define exit(n)
Definition: config.h:202
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1146

◆ NtGdiExtCreateRegion()

HRGN APIENTRY NtGdiExtCreateRegion ( OPTIONAL LPXFORM  Xform,
DWORD  Count,
LPRGNDATA  RgnData 
)

Definition at line 3804 of file region.c.

3811{
3812 HRGN hRgn;
3814 DWORD nCount = 0;
3815 DWORD iType = 0;
3816 DWORD dwSize = 0;
3817 UINT i;
3818 RECT* rects;
3820 MATRIX matrix;
3821 XFORMOBJ xo;
3822
3823 DPRINT("NtGdiExtCreateRegion\n");
3824 _SEH2_TRY
3825 {
3826 ProbeForRead(RgnData, Count, 1);
3827 nCount = RgnData->rdh.nCount;
3828 iType = RgnData->rdh.iType;
3829 dwSize = RgnData->rdh.dwSize;
3830 rects = (RECT*)RgnData->Buffer;
3831 }
3833 {
3835 }
3836 _SEH2_END;
3837
3838 if (!NT_SUCCESS(Status))
3839 {
3841 return NULL;
3842 }
3843
3844 /* Check parameters, but don't set last error here */
3845 if ((Count < sizeof(RGNDATAHEADER) + nCount * sizeof(RECT)) ||
3846 (iType != RDH_RECTANGLES) ||
3847 (dwSize != sizeof(RGNDATAHEADER)))
3848 {
3849 return NULL;
3850 }
3851
3853
3854 if (Region == NULL)
3855 {
3857 return FALSE;
3858 }
3859 hRgn = Region->BaseObject.hHmgr;
3860
3861 _SEH2_TRY
3862 {
3863 /* Insert the rectangles one by one */
3864 for(i=0; i<nCount; i++)
3865 {
3866 if ( rects[i].left < rects[i].right && rects[i].top < rects[i].bottom )
3867 {
3868 if (!REGION_UnionRectWithRgn(Region, &rects[i]))
3869 {
3872 hRgn = NULL;
3874 }
3875 }
3876 }
3877
3878 if (Xform != NULL)
3879 {
3880 ULONG ret;
3881
3882 /* Init the XFORMOBJ from the Xform struct */
3884 XFORMOBJ_vInit(&xo, &matrix);
3885 ret = XFORMOBJ_iSetXform(&xo, (XFORML*)Xform);
3886
3887 /* Check for error */
3888 if (ret != DDI_ERROR)
3889 {
3890 /* Apply the coordinate transformation on the rects */
3891 if (XFORMOBJ_bApplyXform(&xo,
3892 XF_LTOL,
3893 Region->rdh.nCount * 2,
3894 Region->Buffer,
3895 Region->Buffer))
3896 {
3898 }
3899 }
3900 }
3901 }
3903 {
3905 }
3906 _SEH2_END;
3907 if (!NT_SUCCESS(Status))
3908 {
3912 return NULL;
3913 }
3914
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define _SEH2_LEAVE
Definition: filesup.c:20
Status
Definition: gdiplustypes.h:25
GLuint GLenum matrix
Definition: glext.h:9407
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
int Count
Definition: noreturn.cpp:7
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: matrix.h:44
RGNDATAHEADER rdh
Definition: axextend.idl:399
char Buffer[1]
Definition: axextend.idl:400
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
BOOL FASTCALL REGION_UnionRectWithRgn(PREGION rgn, const RECTL *rect)
Definition: region.c:1796
#define XF_LTOL
Definition: winddi.h:3109
#define DDI_ERROR
Definition: winddi.h:154
_In_ ULONG iType
Definition: winddi.h:3748
#define XFORMOBJ_iSetXform
Definition: xformobj.h:14
#define XFORMOBJ_vInit
Definition: xformobj.h:12
#define XFORMOBJ_bApplyXform
Definition: xformobj.h:11

◆ NtGdiGetRgnBox()

INT APIENTRY NtGdiGetRgnBox ( HRGN  hRgn,
PRECTL  pRect 
)

Definition at line 3919 of file region.c.

3925{
3926 PREGION Rgn;
3927 RECTL SafeRect;
3928 DWORD ret;
3930
3931 Rgn = REGION_LockRgn(hRgn);
3932 if (Rgn == NULL)
3933 {
3934 return ERROR;
3935 }
3936
3937 ret = REGION_GetRgnBox(Rgn, &SafeRect);
3938 REGION_UnlockRgn(Rgn);
3939 if (ret == ERROR)
3940 {
3941 return ret;
3942 }
3943
3944 _SEH2_TRY
3945 {
3946 ProbeForWrite(pRect, sizeof(RECT), 1);
3947 *pRect = SafeRect;
3948 }
3950 {
3952 }
3953 _SEH2_END;
3954 if (!NT_SUCCESS(Status))
3955 {
3956 return ERROR;
3957 }

Referenced by emfdrv_stroke_and_fill_path(), and GetRgnBox().

◆ NtGdiOffsetRgn()

INT APIENTRY NtGdiOffsetRgn ( _In_ HRGN  hrgn,
_In_ INT  cx,
_In_ INT  cy 
)

Definition at line 3961 of file region.c.

3968{
3969 PREGION prgn;
3970 INT iResult;
3971
3972 DPRINT("NtGdiOffsetRgn: hrgn %p cx %d cy %d\n", hrgn, cx, cy);
3973
3974 /* Lock the region */
3975 prgn = REGION_LockRgn(hrgn);
3976 if (prgn == NULL)
3977 {
3978 DPRINT1("NtGdiOffsetRgn: failed to lock region %p\n", hrgn);
3979 return ERROR;
3980 }
3981
3982 /* Call the internal function */
3983 if (!REGION_bOffsetRgn(prgn, cx, cy))
3984 {
3985 iResult = ERROR;
3986 }
3987 else
3988 {
3989 iResult = REGION_Complexity(prgn);
3990 }
3991
3992 /* Unlock and return the result */
BOOL FASTCALL REGION_bOffsetRgn(_Inout_ PREGION prgn, _In_ INT cx, _In_ INT cy)
Definition: region.c:2707

Referenced by co_UserExcludeUpdateRgn(), co_UserGetUpdateRgn(), co_WinPosSetWindowPos(), DceResetActiveDCEs(), IntCalcWindowRgn(), and OffsetRgn().

◆ NtGdiPtInRegion()

BOOL APIENTRY NtGdiPtInRegion ( _In_ HRGN  hrgn,
_In_ INT  x,
_In_ INT  y 
)

Definition at line 3996 of file region.c.

4003{
4004 PREGION prgn;
4005 BOOL bResult;
4006
4007 /* Lock the region */
4008 prgn = REGION_LockRgn(hrgn);
4009 if (prgn == NULL)
4010 {
4011 DPRINT1("NtGdiPtInRegion: hrgn error\n");
4012 return FALSE;
4013 }
4014
4015 /* Call the internal function */
4016 bResult = REGION_PtInRegion(prgn, x, y);
4017
4018 /* Unlock and return the result */
BOOL FASTCALL REGION_PtInRegion(PREGION prgn, INT X, INT Y)
Definition: region.c:2582

Referenced by IntPtInWindow(), and PtInRegion().

◆ NtGdiRectInRegion()

__kernel_entry BOOL APIENTRY NtGdiRectInRegion ( _In_ HRGN  hrgn,
_Inout_ LPRECT  prclUnsafe 
)

Definition at line 4023 of file region.c.

4029{
4030 RECTL rcTemp;
4031
4032 /* Probe and copy the rect */
4033 _SEH2_TRY
4034 {
4035 ProbeForRead(prclUnsafe, sizeof(RECT), 1);
4036 rcTemp = *prclUnsafe;
4037 }
4039 {
4040 DPRINT1("NtGdiRectInRegion: Exception accessing the rect\n");
4041 return FALSE;
4042 }
4043 _SEH2_END;
4044

Referenced by RectInRegion().

◆ NtGdiSetRectRgn()

BOOL APIENTRY NtGdiSetRectRgn ( _In_ HRGN  hrgn,
_In_ INT  xLeft,
_In_ INT  yTop,
_In_ INT  xRight,
_In_ INT  yBottom 
)

Definition at line 4048 of file region.c.

4057{
4058 PREGION prgn;
4059
4060 /* Lock the region */
4061 prgn = REGION_LockRgn(hrgn);
4062 if (prgn == NULL)
4063 {
4064 return FALSE;
4065 }
4066
4067 /* Call the internal API */
4068 REGION_SetRectRgn(prgn, xLeft, yTop, xRight, yBottom);
4069
4070 /* Unlock the region and return success */

Referenced by co_UserGetUpdateRgn(), and SetRectRgn().

◆ REGION_AllocRgnWithHandle()

PREGION FASTCALL REGION_AllocRgnWithHandle ( INT  nReg)

Definition at line 2201 of file region.c.

2206{
2207 //HRGN hReg;
2208 PREGION pReg;
2209
2211 sizeof(REGION),
2213 if (pReg == NULL)
2214 {
2215 DPRINT1("Could not allocate a palette.\n");
2216 return NULL;
2217 }
2218
2219 //hReg = pReg->BaseObject.hHmgr;
2220
2221 if ((nReg == 0) || (nReg == 1))
2222 {
2223 /* Testing shows that > 95% of all regions have only 1 rect.
2224 Including that here saves us from having to do another allocation */
2225 pReg->Buffer = &pReg->rdh.rcBound;
2226 }
2227 else
2228 {
2230 nReg * sizeof(RECT),
2231 TAG_REGION);
2232 if (pReg->Buffer == NULL)
2233 {
2234 DPRINT1("Could not allocate region buffer\n");
2236 return NULL;
2237 }
2238 }
2239
2240 EMPTY_REGION(pReg);
2241 pReg->rdh.dwSize = sizeof(RGNDATAHEADER);
2242 pReg->rdh.nCount = nReg;
2243 pReg->rdh.nRgnSize = nReg * sizeof(RECT);
2244 pReg->prgnattr = &pReg->rgnattr;
2245
2246 /* Initialize the region attribute */
2247 pReg->rgnattr.AttrFlags = 0;
2249 pReg->rgnattr.Rect = pReg->rdh.rcBound;
2250
2251 /* Finally insert the region into the handle table */
2253 {
2254 DPRINT1("Could not insert palette into handle table.\n");
2256 return NULL;
2257 }
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
ULONG iComplexity
Definition: ntgdihdl.h:257
RECTL Rect
Definition: ntgdihdl.h:258
VOID NTAPI GDIOBJ_vFreeObject(POBJ pobj)
Definition: gdiobj.c:596
HGDIOBJ NTAPI GDIOBJ_hInsertObject(POBJ pobj, ULONG ulOwner)
Definition: gdiobj.c:912
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1111
#define EMPTY_REGION(pReg)
Definition: region.c:148
#define TAG_REGION
Definition: tags.h:22
#define SIMPLEREGION
Definition: wingdi.h:362

Referenced by REGION_AllocUserRgnWithHandle(), and REGION_XorRegion().

◆ REGION_AllocUserRgnWithHandle()

PREGION FASTCALL REGION_AllocUserRgnWithHandle ( INT  nRgn)

Definition at line 2294 of file region.c.

2299{
2300 PREGION prgn;
2301
2302 prgn = REGION_AllocRgnWithHandle(nRgn);
2303 if (prgn == NULL)
2304 {
2305 return NULL;
2306 }
2307
2308 if (!REGION_bAllocRgnAttr(prgn))
2309 {
2310 ASSERT(FALSE);
2311 }
BOOL NTAPI REGION_bAllocRgnAttr(PREGION prgn)
Definition: region.c:2261
PREGION FASTCALL REGION_AllocRgnWithHandle(INT nReg)
Definition: region.c:2201

Referenced by GreCreateFrameRgn(), GreCreatePolyPolygonRgn(), NtGdiCreateRectRgn(), NtGdiCreateRoundRectRgn(), NtGdiExtCreateRegion(), and NtGdiPathToRegion().

◆ REGION_bAddRect()

static __inline BOOL REGION_bAddRect ( _Inout_ PREGION  prgn,
_In_ LONG  left,
_In_ LONG  top,
_In_ LONG  right,
_In_ LONG  bottom 
)
static

Definition at line 492 of file region.c.

501{
502 if (!REGION_bEnsureBufferSize(prgn, prgn->rdh.nCount + 1))
503 {
504 return FALSE;
505 }
506
static __inline BOOL REGION_bEnsureBufferSize(_Inout_ PREGION prgn, _In_ UINT cRects)
Definition: region.c:456

Referenced by REGION_bMergeRect(), REGION_IntersectO(), and REGION_SubtractO().

◆ REGION_bAllocRgnAttr()

BOOL NTAPI REGION_bAllocRgnAttr ( PREGION  prgn)

Definition at line 2261 of file region.c.

2266{
2267 PPROCESSINFO ppi;
2268 PRGN_ATTR prgnattr;
2269
2270 NT_ASSERT(prgn->prgnattr == &prgn->rgnattr);
2271
2273 ASSERT(ppi);
2274
2275 prgnattr = GdiPoolAllocate(ppi->pPoolRgnAttr);
2276 if (prgnattr == NULL)
2277 {
2278 DPRINT1("Could not allocate RGN attr\n");
2279 return FALSE;
2280 }
2281
2282 /* Copy the current region attribute */
2283 *prgnattr = prgn->rgnattr;
2284
2285 /* Set the object attribute in the handle table */
2286 prgn->prgnattr = prgnattr;
2287 GDIOBJ_vSetObjectAttr(&prgn->BaseObject, prgnattr);
PVOID NTAPI GdiPoolAllocate(PGDI_POOL pPool)
Definition: gdipool.c:122
#define NT_ASSERT
Definition: rtlfuncs.h:3310

Referenced by REGION_AllocUserRgnWithHandle().

◆ REGION_bCopy()

BOOL FASTCALL REGION_bCopy ( PREGION  dst,
PREGION  src 
)

Definition at line 1828 of file region.c.

1834{

Referenced by _Success_(), CLIPPING_UpdateGCRegion(), and GdiSelectVisRgn().

◆ REGION_bEnsureBufferSize()

static __inline BOOL REGION_bEnsureBufferSize ( _Inout_ PREGION  prgn,
_In_ UINT  cRects 
)
static

Definition at line 456 of file region.c.

462{
463 /* Check if the current region size is too small */
464 if (cRects > prgn->rdh.nRgnSize / sizeof(RECTL))
465 {
466 /* Allocate a new buffer */
467 return REGION_bGrowBufferSize(prgn, cRects);
468 }
static BOOL REGION_bGrowBufferSize(_Inout_ PREGION prgn, _In_ UINT cRects)
Definition: region.c:406

Referenced by REGION_bAddRect(), REGION_SubtractNonO1(), REGION_SubtractO(), and REGION_UnionNonO().

◆ REGION_bGrowBufferSize()

static BOOL REGION_bGrowBufferSize ( _Inout_ PREGION  prgn,
_In_ UINT  cRects 
)
static

Definition at line 406 of file region.c.

412{
413 ULONG cjNewSize;
414 PVOID pvBuffer;
415 NT_ASSERT(cRects > 0);
416
417 /* Make sure we don't overflow */
418 if (cRects > MAXULONG / sizeof(RECTL))
419 {
420 return FALSE;
421 }
422
423 /* Calculate new buffer size */
424 cjNewSize = cRects * sizeof(RECTL);
425
426 /* Avoid allocating too often, by duplicating the old buffer size
427 Note: we don't do an overflow check, since the old size will never
428 get that large before running out of memory. */
429 if (2 * prgn->rdh.nRgnSize > cjNewSize)
430 {
431 cjNewSize = 2 * prgn->rdh.nRgnSize;
432 }
433
434 /* Allocate the new buffer */
435 pvBuffer = ExAllocatePoolWithTag(PagedPool, cjNewSize, TAG_REGION);
436 if (pvBuffer == NULL)
437 {
438 return FALSE;
439 }
440
441 /* Copy the rects into the new buffer */
442 COPY_RECTS(pvBuffer, prgn->Buffer, prgn->rdh.nCount);
443
444 /* Free the old buffer */
445 if (prgn->Buffer != &prgn->rdh.rcBound)
446 {
447 ExFreePoolWithTag(prgn->Buffer, TAG_REGION);
448 }
449
450 /* Set the new buffer */
451 prgn->Buffer = pvBuffer;
452 prgn->rdh.nRgnSize = cjNewSize;
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define MAXULONG
Definition: typedefs.h:251
#define COPY_RECTS(dest, src, nRects)
Definition: region.c:135

Referenced by REGION_bEnsureBufferSize().

◆ REGION_bIntersectRegion()

BOOL FASTCALL REGION_bIntersectRegion ( PREGION  newReg,
PREGION  reg1,
PREGION  reg2 
)

Definition at line 1838 of file region.c.

1845{

Referenced by CLIPPING_UpdateGCRegion(), and IntGdiSetMetaRgn().

◆ REGION_bMakeFrameRegion()

static BOOL REGION_bMakeFrameRegion ( _Inout_ PREGION  prgnDest,
_Inout_ PREGION  prgnSrc,
_In_ INT  cx,
_In_ INT  cy 
)
static

Definition at line 1940 of file region.c.

1948{
1949 /* Handle negative cx / cy */
1950 cx = abs(cx);
1951 cy = abs(cy);
1952
1953 /* Check border size (the cast is necessary to catch cx/cy == INT_MIN!) */
1954 if (((UINT)cx > MAX_COORD) || ((UINT)cy > MAX_COORD))
1955 {
1956 return FALSE;
1957 }
1958
1959 /* Fail on empty source region */
1960 if (!REGION_NOT_EMPTY(prgnSrc))
1961 {
1962 return FALSE;
1963 }
1964
1965 /* Handle trivial case */
1966 if ((cx == 0) && (cy == 0))
1967 {
1968 EMPTY_REGION(prgnDest);
1969 return TRUE;
1970 }
1971
1972 /* Handle simple source region */
1973 if (REGION_Complexity(prgnSrc) == SIMPLEREGION)
1974 {
1975 return REGION_bMakeSimpleFrameRgn(prgnDest, &prgnSrc->rdh.rcBound, cx, cy);
1976 }
1977
1978 /* Check if we can move the region to create the frame region */
1979 if ((prgnSrc->rdh.rcBound.left < (MIN_COORD + cx)) ||
1980 (prgnSrc->rdh.rcBound.top < (MIN_COORD + cy)) ||
1981 (prgnSrc->rdh.rcBound.right > (MAX_COORD - cx)) ||
1982 (prgnSrc->rdh.rcBound.bottom > (MAX_COORD - cy)))
1983 {
1984 return FALSE;
1985 }
1986
1987 /* Copy the source region */
1988 if (!REGION_CopyRegion(prgnDest, prgnSrc))
1989 {
1990 return FALSE;
1991 }
1992
1993 /* Move the source region to the bottom-right */
1994 NT_VERIFY(REGION_bOffsetRgn(prgnSrc, cx, cy));
1995
1996 /* Intersect with the source region (this crops the top-left frame) */
1997 REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
1998
1999 /* Move the source region to the bottom-left */
2000 NT_VERIFY(REGION_bOffsetRgn(prgnSrc, -2 * cx, 0));
2001
2002 /* Intersect with the source region (this crops the top-right frame) */
2003 REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
2004
2005 /* Move the source region to the top-left */
2006 NT_VERIFY(REGION_bOffsetRgn(prgnSrc, 0, -2 * cy));
2007
2008 /* Intersect with the source region (this crops the bottom-right frame) */
2009 REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
2010
2011 /* Move the source region to the top-right */
2012 NT_VERIFY(REGION_bOffsetRgn(prgnSrc, 2 * cx, 0));
2013
2014 /* Intersect with the source region (this crops the bottom-left frame) */
2015 REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
2016
2017 /* Move the source region back to the original position */
2018 NT_VERIFY(REGION_bOffsetRgn(prgnSrc, -cx, cy));
2019
2020 /* Finally subtract the cropped region from the source */
2021 REGION_SubtractRegion(prgnDest, prgnSrc, prgnDest);
#define MAX_COORD
Definition: region.c:12
#define MIN_COORD
Definition: region.c:11
static BOOL REGION_bMakeSimpleFrameRgn(_Inout_ PREGION prgn, _In_ PRECTL prclSrc, _In_ INT cx, _In_ INT cy)
Definition: region.c:1849
#define REGION_NOT_EMPTY(pReg)
Definition: region.c:155
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3287

Referenced by GreCreateFrameRgn().

◆ REGION_bMakeSimpleFrameRgn()

static BOOL REGION_bMakeSimpleFrameRgn ( _Inout_ PREGION  prgn,
_In_ PRECTL  prclSrc,
_In_ INT  cx,
_In_ INT  cy 
)
static

Definition at line 1849 of file region.c.

1857{
1858 RECTL arcl[4];
1859 UINT i;
1860
1861 NT_ASSERT((cx >= 0) && (cy >= 0));
1862 NT_ASSERT((prclSrc->bottom > prclSrc->top) &&
1863 (prclSrc->right > prclSrc->left));
1864
1865 /* Start with an empty region */
1866 EMPTY_REGION(prgn);
1867
1868 /* Check for the case where the frame covers the whole rect */
1869 if (((prclSrc->bottom - prclSrc->top) <= cy * 2) ||
1870 ((prclSrc->right - prclSrc->left) <= cx * 2))
1871 {
1872 prgn->rdh.rcBound = *prclSrc;
1873 prgn->Buffer[0] = *prclSrc;
1874 prgn->rdh.nCount = 1;
1875 return TRUE;
1876 }
1877
1878 i = 0;
1879
1880 if (cy != 0)
1881 {
1882 /* Top rectangle */
1883 arcl[i].left = prclSrc->left;
1884 arcl[i].top = prclSrc->top;
1885 arcl[i].right = prclSrc->right;
1886 arcl[i].bottom = prclSrc->top + cy;
1887 i++;
1888 }
1889
1890 if (cx != 0)
1891 {
1892 /* Left rectangle */
1893 arcl[i].left = prclSrc->left;
1894 arcl[i].top = prclSrc->top + cy;
1895 arcl[i].right = prclSrc->left + cx;
1896 arcl[i].bottom = prclSrc->bottom - cy;
1897 i++;
1898
1899 /* Right rectangle */
1900 arcl[i].left = prclSrc->right - cx;
1901 arcl[i].top = prclSrc->top + cy;
1902 arcl[i].right = prclSrc->right;
1903 arcl[i].bottom = prclSrc->bottom - cy;
1904 i++;
1905 }
1906
1907 if (cy != 0)
1908 {
1909 /* Bottom rectangle */
1910 arcl[i].left = prclSrc->left;
1911 arcl[i].top = prclSrc->bottom - cy;
1912 arcl[i].right = prclSrc->right;
1913 arcl[i].bottom = prclSrc->bottom;
1914 i++;
1915 }
1916
1917 if (i != 0)
1918 {
1919 /* The frame results in a complex region. rcBounds remains
1920 the same, though. */
1921 prgn->rdh.nCount = i;
1922 NT_ASSERT(prgn->rdh.nCount > 1);
1923 prgn->rdh.nRgnSize = prgn->rdh.nCount * sizeof(RECT);
1924 NT_ASSERT(prgn->Buffer == &prgn->rdh.rcBound);
1925 prgn->Buffer = ExAllocatePoolWithTag(PagedPool,
1926 prgn->rdh.nRgnSize,
1927 TAG_REGION);
1928 if (prgn->Buffer == NULL)
1929 {
1930 prgn->rdh.nRgnSize = 0;
1931 return FALSE;
1932 }
1933
1935 COPY_RECTS(prgn->Buffer, arcl, prgn->rdh.nCount);
1936 }
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
#define _PRAGMA_WARNING_SUPPRESS(x)
Definition: suppress.h:28
#define __WARNING_MAYBE_UNINIT_VAR
Definition: suppress.h:598
_In_ SURFOBJ _In_ CLIPOBJ _In_opt_ XLATEOBJ _In_ RECTL _In_ RECTL * prclSrc
Definition: winddi.h:3418

Referenced by REGION_bMakeFrameRegion().

◆ REGION_bMergeRect()

static __inline BOOL REGION_bMergeRect ( _Inout_ PREGION  prgn,
_In_ LONG  left,
_In_ LONG  top,
_In_ LONG  right,
_In_ LONG  bottom 
)
static

Definition at line 1371 of file region.c.

1380{
1381 if ((prgn->rdh.nCount != 0) &&
1382 (prgn->Buffer[prgn->rdh.nCount - 1].top == top) &&
1383 (prgn->Buffer[prgn->rdh.nCount - 1].bottom == bottom) &&
1384 (prgn->Buffer[prgn->rdh.nCount - 1].right >= left))
1385 {
1386 if (prgn->Buffer[prgn->rdh.nCount - 1].right < right)
1387 {
1388 prgn->Buffer[prgn->rdh.nCount - 1].right = right;
1389 }
1390 }
1391 else
1392 {
1393 if (!REGION_bAddRect(prgn, left, top, right, bottom))
1394 {
1395 return FALSE;
1396 }
1397 }
static __inline BOOL REGION_bAddRect(_Inout_ PREGION prgn, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
Definition: region.c:492

Referenced by REGION_UnionO().

◆ REGION_bOffsetRgn()

BOOL FASTCALL REGION_bOffsetRgn ( _Inout_ PREGION  prgn,
_In_ INT  cx,
_In_ INT  cy 
)

Definition at line 2707 of file region.c.

2714{
2715 PRECTL prcl;
2716 UINT i;
2717
2718 NT_ASSERT(prgn != NULL);
2719
2720 /* Check for trivial case */
2721 if ((cx == 0) && (cy == 0))
2722 {
2723 return TRUE;
2724 }
2725
2726 /* Check for empty regions, we ignore the offset values here */
2727 if (prgn->rdh.nCount == 0)
2728 {
2729 return TRUE;
2730 }
2731
2732 /* Make sure the offset is within the legal range */
2733 if ((cx > MAX_COORD) || (cx < MIN_COORD) ||
2734 (cy > MAX_COORD) || (cy < MIN_COORD))
2735 {
2736 return FALSE;
2737 }
2738
2739 /* Are we moving right? */
2740 if (cx > 0)
2741 {
2742 /* Check if we stay inside the bounds on the right side */
2743 if (prgn->rdh.rcBound.right > (MAX_COORD - cx))
2744 {
2745 return FALSE;
2746 }
2747 }
2748 else
2749 {
2750 /* Check if we stay inside the bounds on the left side */
2751 if (prgn->rdh.rcBound.left < (MIN_COORD - cx))
2752 {
2753 return FALSE;
2754 }
2755 }
2756
2757 /* Are we moving down? */
2758 if (cy > 0)
2759 {
2760 /* Check if we stay inside the bounds on the right side */
2761 if (prgn->rdh.rcBound.bottom > (MAX_COORD - cy))
2762 {
2763 return FALSE;
2764 }
2765 }
2766 else
2767 {
2768 /* Check if we stay inside the bounds on the left side */
2769 if (prgn->rdh.rcBound.top < (MIN_COORD - cy))
2770 {
2771 return FALSE;
2772 }
2773 }
2774
2775 /* Loop to move the rects */
2776 prcl = prgn->Buffer;
2777 for (i = 0; i < prgn->rdh.nCount; i++)
2778 {
2779 prcl[i].left += cx;
2780 prcl[i].right += cx;
2781 prcl[i].top += cy;
2782 prcl[i].bottom += cy;
2783 }
2784
2785 /* Finally update the bounds rect */
2786 if (prgn->Buffer != &prgn->rdh.rcBound)
2787 {
2788 prgn->rdh.rcBound.left += cx;
2789 prgn->rdh.rcBound.right += cx;
2790 prgn->rdh.rcBound.top += cy;
2791 prgn->rdh.rcBound.bottom += cy;
2792 }
_In_ ULONG _In_ CLIPOBJ _In_ RECTL * prcl
Definition: winddi.h:3531

Referenced by CLIPPING_UpdateGCRegion(), co_IntGetUpdateRgn(), co_UserRedrawWindow(), co_VIS_WindowLayoutChanged(), co_WinPosSetWindowPos(), DceResetActiveDCEs(), GdiSelectVisRgn(), IntGdiBitBltRgn(), IntGdiFillRgn(), IntInvalidateWindows(), IntScrollWindowEx(), NtGdiGetRandomRgn(), NtGdiOffsetClipRgn(), NtGdiOffsetRgn(), REGION_bMakeFrameRegion(), REGION_bXformRgn(), UserScrollDC(), and VIS_ComputeVisibleRegion().

◆ REGION_bXformRgn()

BOOL FASTCALL REGION_bXformRgn ( _Inout_ PREGION  prgn,
_In_ PMATRIX  pmx 
)

Definition at line 2066 of file region.c.

2072{
2073 XFORMOBJ xo;
2074 ULONG i, cjSize;
2075 PPOINT ppt;
2076 PULONG pcPoints;
2077 RECT rect;
2078 BOOL bResult;
2079
2080 /* Check for zero rectangles and return TRUE for translation only matrices */
2081 if (prgn->rdh.nCount < 1)
2082 return (pmx->flAccel & XFORM_UNITY) != 0;
2083
2084 /* Check if this is a scaling only matrix (off-diagonal elements are 0 */
2085 if (pmx->flAccel & XFORM_SCALE)
2086 {
2087 /* Check if this is a translation only matrix */
2088 if (pmx->flAccel & XFORM_UNITY)
2089 {
2090 /* Just offset the region */
2091 return REGION_bOffsetRgn(prgn, (pmx->fxDx + 8) / 16, (pmx->fxDy + 8) / 16);
2092 }
2093 else
2094 {
2095 /* Initialize the xform object */
2096 XFORMOBJ_vInit(&xo, pmx);
2097
2098 /* Scaling can move the rects out of the coordinate space, so
2099 * we first need to check whether we can apply the transformation
2100 * on the bounds rect without modifying the region */
2101 if (!XFORMOBJ_bApplyXform(&xo, XF_LTOL, 2, &prgn->rdh.rcBound, &rect))
2102 {
2103 return FALSE;
2104 }
2105
2106 /* Apply the xform to the rects in the region */
2107 if (!XFORMOBJ_bApplyXform(&xo,
2108 XF_LTOL,
2109 prgn->rdh.nCount * 2,
2110 prgn->Buffer,
2111 prgn->Buffer))
2112 {
2113 /* This can not happen, since we already checked the bounds! */
2115 }
2116
2117 /* Reset bounds */
2118 RECTL_vSetEmptyRect(&prgn->rdh.rcBound);
2119
2120 /* Loop all rects in the region */
2121 for (i = 0; i < prgn->rdh.nCount; i++)
2122 {
2123 /* Make sure the rect is well-ordered after the xform */
2124 RECTL_vMakeWellOrdered(&prgn->Buffer[i]);
2125
2126 /* Update bounds */
2127 if (!RECTL_bUnionRect(&prgn->rdh.rcBound,
2128 &prgn->rdh.rcBound,
2129 &prgn->Buffer[i]))
2130 {
2131 DPRINT1("NULL Set in Union Rects\n");
2132 return FALSE;
2133 }
2134 }
2135
2136 /* Loop all rects in the region */
2137 for (i = 0; i < prgn->rdh.nCount - 1; i++)
2138 {
2139 NT_ASSERT(prgn->Buffer[i].top <= prgn->Buffer[i].bottom);
2140 NT_ASSERT(prgn->Buffer[i + 1].top >= prgn->Buffer[i].top);
2141 }
2142
2143 return TRUE;
2144 }
2145 }
2146 else
2147 {
2148 /* Allocate a buffer for the polygons */
2149 cjSize = prgn->rdh.nCount * (4 * sizeof(POINT) + sizeof(ULONG));
2151 if (ppt == NULL)
2152 {
2153 return FALSE;
2154 }
2155
2156 /* Fill the buffer with the rects */
2157 pcPoints = (PULONG)&ppt[4 * prgn->rdh.nCount];
2158 for (i = 0; i < prgn->rdh.nCount; i++)
2159 {
2160 /* Make sure the rect is within the legal range */
2161 pcPoints[i] = 4;
2162 ppt[4 * i + 0].x = prgn->Buffer[i].left;
2163 ppt[4 * i + 0].y = prgn->Buffer[i].top;
2164 ppt[4 * i + 1].x = prgn->Buffer[i].right;
2165 ppt[4 * i + 1].y = prgn->Buffer[i].top;
2166 ppt[4 * i + 2].x = prgn->Buffer[i].right;
2167 ppt[4 * i + 2].y = prgn->Buffer[i].bottom;
2168 ppt[4 * i + 3].x = prgn->Buffer[i].left;
2169 ppt[4 * i + 3].y = prgn->Buffer[i].bottom;
2170 }
2171
2172 /* Initialize the xform object */
2173 XFORMOBJ_vInit(&xo, pmx);
2174
2175 /* Apply the xform to the rects in the buffer */
2176 if (!XFORMOBJ_bApplyXform(&xo,
2177 XF_LTOL,
2178 prgn->rdh.nCount * 2,
2179 ppt,
2180 ppt))
2181 {
2182 /* This means, there were coordinates that would go outside of
2183 the coordinate space after the transformation */
2185 return FALSE;
2186 }
2187
2188 /* Now use the polygons to create a polygon region */
2189 bResult = REGION_SetPolyPolygonRgn(prgn,
2190 ppt,
2191 pcPoints,
2192 prgn->rdh.nCount,
2193 WINDING);
2194
2195 /* Free the polygon buffer */
2197
#define WINDING
Definition: constants.h:279
#define for
Definition: utility.h:88
@ XFORM_SCALE
Definition: ntgdityp.h:106
@ XFORM_UNITY
Definition: ntgdityp.h:107
& rect
Definition: startmenu.cpp:1413
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
uint32_t * PULONG
Definition: typedefs.h:59
#define POINT
Definition: precomp.h:30
VOID FASTCALL RECTL_vMakeWellOrdered(_Inout_ RECTL *prcl)
Definition: rect.c:81
BOOL FASTCALL RECTL_bUnionRect(_Out_ RECTL *prclDst, _In_ const RECTL *prcl1, _In_ const RECTL *prcl2)
Definition: rect.c:18
FORCEINLINE VOID RECTL_vSetEmptyRect(_Out_ RECTL *prcl)
Definition: rect.h:20
#define GDITAG_REGION
Definition: tags.h:158

Referenced by REGION_LPTODP().

◆ REGION_Coalesce()

static INT FASTCALL REGION_Coalesce ( PREGION  pReg,
INT  prevStart,
INT  curStart 
)
static
 Attempt to merge the rects in the current band with those in the
 previous one. Used only by REGION_RegionOp.

Results: The new index for the previous band.

Note
Side Effects: If coalescing takes place:
  • rectangles in the previous band will have their bottom fields altered.
  • pReg->numRects will be decreased.

Definition at line 808 of file region.c.

815{
816 RECTL *pPrevRect; /* Current rect in previous band */
817 RECTL *pCurRect; /* Current rect in current band */
818 RECTL *pRegEnd; /* End of region */
819 INT curNumRects; /* Number of rectangles in current band */
820 INT prevNumRects; /* Number of rectangles in previous band */
821 INT bandtop; /* Top coordinate for current band */
822
823 pRegEnd = pReg->Buffer + pReg->rdh.nCount;
824 pPrevRect = pReg->Buffer + prevStart;
825 prevNumRects = curStart - prevStart;
826
827 /* Figure out how many rectangles are in the current band. Have to do
828 * this because multiple bands could have been added in REGION_RegionOp
829 * at the end when one region has been exhausted. */
830 pCurRect = pReg->Buffer + curStart;
831 bandtop = pCurRect->top;
832 for (curNumRects = 0;
833 (pCurRect != pRegEnd) && (pCurRect->top == bandtop);
834 curNumRects++)
835 {
836 pCurRect++;
837 }
838
839 if (pCurRect != pRegEnd)
840 {
841 /* If more than one band was added, we have to find the start
842 * of the last band added so the next coalescing job can start
843 * at the right place... (given when multiple bands are added,
844 * this may be pointless -- see above). */
845 pRegEnd--;
846 while ((pRegEnd-1)->top == pRegEnd->top)
847 {
848 pRegEnd--;
849 }
850
851 curStart = pRegEnd - pReg->Buffer;
852 pRegEnd = pReg->Buffer + pReg->rdh.nCount;
853 }
854
855 if ((curNumRects == prevNumRects) && (curNumRects != 0))
856 {
857 pCurRect -= curNumRects;
858
859 /* The bands may only be coalesced if the bottom of the previous
860 * matches the top scanline of the current. */
861 if (pPrevRect->bottom == pCurRect->top)
862 {
863 /* Make sure the bands have rects in the same places. This
864 * assumes that rects have been added in such a way that they
865 * cover the most area possible. I.e. two rects in a band must
866 * have some horizontal space between them. */
867 do
868 {
869 if ((pPrevRect->left != pCurRect->left) ||
870 (pPrevRect->right != pCurRect->right))
871 {
872 /* The bands don't line up so they can't be coalesced. */
873 return (curStart);
874 }
875
876 pPrevRect++;
877 pCurRect++;
878 prevNumRects -= 1;
879 }
880 while (prevNumRects != 0);
881
882 pReg->rdh.nCount -= curNumRects;
883 pCurRect -= curNumRects;
884 pPrevRect -= curNumRects;
885
886 /* The bands may be merged, so set the bottom of each rect
887 * in the previous band to that of the corresponding rect in
888 * the current band. */
889 do
890 {
891 pPrevRect->bottom = pCurRect->bottom;
892 pPrevRect++;
893 pCurRect++;
894 curNumRects -= 1;
895 }
896 while (curNumRects != 0);
897
898 /* If only one band was added to the region, we have to backup
899 * curStart to the start of the previous band.
900 *
901 * If more than one band was added to the region, copy the
902 * other bands down. The assumption here is that the other bands
903 * came from the same region as the current one and no further
904 * coalescing can be done on them since it's all been done
905 * already... curStart is already in the right place. */
906 if (pCurRect == pRegEnd)
907 {
908 curStart = prevStart;
909 }
910 else
911 {
912 do
913 {
914 *pPrevRect++ = *pCurRect++;
915 }
916 while (pCurRect != pRegEnd);
917 }
918 }
919 }

Referenced by REGION_RegionOp().

◆ REGION_Complexity()

INT FASTCALL REGION_Complexity ( PREGION  prgn)

Definition at line 554 of file region.c.

558{
559 if (prgn == NULL)
560 return NULLREGION;
561
562 DPRINT("Region Complexity: %lu\n", prgn->rdh.nCount);
563 switch (prgn->rdh.nCount)
564 {
565 case 0:
566 return NULLREGION;
567 case 1:
568 return SIMPLEREGION;
569 default:
#define NULLREGION
Definition: wingdi.h:361

Referenced by _Success_(), co_WinPosSetWindowPos(), DxEngGetDCState(), IntGdiCombineRgn(), IntGdiSetMetaRgn(), NtGdiOffsetClipRgn(), NtGdiOffsetRgn(), REGION_bMakeFrameRegion(), REGION_CropRegion(), REGION_GetRgnBox(), REGION_SubtractRectFromRgn(), and REGION_UnlockRgn().

◆ REGION_computeWAET()

static VOID FASTCALL REGION_computeWAET ( EDGE_TABLE_ENTRY AET)
static

Definition at line 2937 of file region.c.

2942{
2943 register EDGE_TABLE_ENTRY *pWETE;
2944 register INT inside = 1;
2945 register INT isInside = 0;
2946
2947 AET->nextWETE = (EDGE_TABLE_ENTRY *)NULL;
2948 pWETE = AET;
2949 AET = AET->next;
2950 while (AET)
2951 {
2952 if (AET->ClockWise)
2953 isInside++;
2954 else
2955 isInside--;
2956
2957 if ((!inside && !isInside) ||
2958 ( inside && isInside))
2959 {
2960 pWETE->nextWETE = AET;
2961 pWETE = AET;
2962 inside = !inside;
2963 }
2964 AET = AET->next;
2965 }
Definition: region.c:311
struct _EDGE_TABLE_ENTRY * nextWETE
Definition: region.c:316
INT ClockWise
Definition: region.c:317
struct _EDGE_TABLE_ENTRY * next
Definition: region.c:314

Referenced by REGION_SetPolyPolygonRgn().

◆ REGION_CopyRegion()

static BOOL FASTCALL REGION_CopyRegion ( PREGION  dst,
PREGION  src 
)
static

Definition at line 574 of file region.c.

580{
581 /* Only copy if source and dest are not equal */
582 if (dst != src)
583 {
584 /* Check if we need to increase our buffer */
585 if (dst->rdh.nRgnSize < src->rdh.nCount * sizeof(RECT))
586 {
587 PRECTL temp;
588
589 /* Allocate a new buffer */
591 src->rdh.nCount * sizeof(RECT),
592 TAG_REGION);
593 if (temp == NULL)
594 return FALSE;
595
596 /* Free the old buffer */
597 if ((dst->Buffer != NULL) && (dst->Buffer != &dst->rdh.rcBound))
599
600 /* Set the new buffer and the size */
601 dst->Buffer = temp;
602 dst->rdh.nRgnSize = src->rdh.nCount * sizeof(RECT);
603 }
604
605 dst->rdh.nCount = src->rdh.nCount;
606 dst->rdh.rcBound.left = src->rdh.rcBound.left;
607 dst->rdh.rcBound.top = src->rdh.rcBound.top;
608 dst->rdh.rcBound.right = src->rdh.rcBound.right;
609 dst->rdh.rcBound.bottom = src->rdh.rcBound.bottom;
610 dst->rdh.iType = src->rdh.iType;
611 COPY_RECTS(dst->Buffer, src->Buffer, src->rdh.nCount);
612 }
GLenum GLenum dst
Definition: glext.h:6340
static calc_node_t temp
Definition: rpn_ieee.c:38

Referenced by IntGdiCombineRgn(), REGION_bCopy(), REGION_bMakeFrameRegion(), REGION_SubtractRegion(), and REGION_UnionRegion().

◆ REGION_CreateETandAET()

static VOID FASTCALL REGION_CreateETandAET ( const ULONG Count,
INT  nbpolygons,
const POINT pts,
EDGE_TABLE ET,
EDGE_TABLE_ENTRY AET,
EDGE_TABLE_ENTRY pETEs,
SCANLINE_LISTBLOCK pSLLBlock 
)
static

Definition at line 3168 of file region.c.

3179{
3180 const POINT *top, *bottom;
3181 const POINT *PrevPt, *CurrPt, *EndPt;
3182 INT poly, count;
3183 INT iSLLBlock = 0;
3184 INT dy;
3185
3186 /* Initialize the Active Edge Table */
3187 AET->next = (EDGE_TABLE_ENTRY *)NULL;
3188 AET->back = (EDGE_TABLE_ENTRY *)NULL;
3189 AET->nextWETE = (EDGE_TABLE_ENTRY *)NULL;
3191
3192 /* Initialize the Edge Table. */
3193 ET->scanlines.next = (SCANLINE_LIST *)NULL;
3194 ET->ymax = SMALL_COORDINATE;
3195 ET->ymin = LARGE_COORDINATE;
3196 pSLLBlock->next = (SCANLINE_LISTBLOCK *)NULL;
3197
3198 EndPt = pts - 1;
3199 for (poly = 0; poly < nbpolygons; poly++)
3200 {
3201 count = Count[poly];
3202 EndPt += count;
3203 if (count < 2)
3204 continue;
3205
3206 PrevPt = EndPt;
3207
3208 /* For each vertex in the array of points.
3209 * In this loop we are dealing with two vertices at
3210 * a time -- these make up one edge of the polygon. */
3211 while (count--)
3212 {
3213 CurrPt = pts++;
3214
3215 /* Find out which point is above and which is below. */
3216 if (PrevPt->y > CurrPt->y)
3217 {
3218 bottom = PrevPt, top = CurrPt;
3219 pETEs->ClockWise = 0;
3220 }
3221 else
3222 {
3223 bottom = CurrPt, top = PrevPt;
3224 pETEs->ClockWise = 1;
3225 }
3226
3227 /* Don't add horizontal edges to the Edge table. */
3228 if (bottom->y != top->y)
3229 {
3230 /* -1 so we don't get last scanline */
3231 pETEs->ymax = bottom->y - 1;
3232
3233 /* Initialize integer edge algorithm */
3234 dy = bottom->y - top->y;
3235 BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
3236
3238 pETEs,
3239 top->y,
3240 &pSLLBlock,
3241 &iSLLBlock);
3242
3243 if (PrevPt->y > ET->ymax)
3244 ET->ymax = PrevPt->y;
3245 if (PrevPt->y < ET->ymin)
3246 ET->ymin = PrevPt->y;
3247 pETEs++;
3248 }
3249
3250 PrevPt = CurrPt;
GLuint GLuint GLsizei count
Definition: gl.h:1545
@ ET
Definition: bidi.c:79
INT minor_axis
Definition: region.c:245
BRESINFO bres
Definition: region.c:313
INT ymax
Definition: region.c:312
struct _EDGE_TABLE_ENTRY * back
Definition: region.c:315
struct _SCANLINE_LISTBLOCK * next
Definition: region.c:344
#define SMALL_COORDINATE
Definition: region.c:402
#define LARGE_COORDINATE
Definition: region.c:401
static VOID FASTCALL REGION_InsertEdgeInET(EDGE_TABLE *ET, EDGE_TABLE_ENTRY *ETE, INT scanline, SCANLINE_LISTBLOCK **SLLBlock, INT *iSLLBlock)
Definition: region.c:2806
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres)
Definition: region.c:251

Referenced by REGION_SetPolyPolygonRgn().

◆ REGION_CropRegion()

INT FASTCALL REGION_CropRegion ( PREGION  rgnDst,
PREGION  rgnSrc,
const RECTL rect 
)

Definition at line 665 of file region.c.

672{
673 PRECTL lpr, rpr;
674 ULONG i, j, clipa, clipb, nRgnSize;
675 INT left = MAXLONG;
676 INT right = MINLONG;
677 INT top = MAXLONG;
679
680 if ((rect->left >= rect->right) ||
681 (rect->top >= rect->bottom) ||
682 (EXTENTCHECK(rect, &rgnSrc->rdh.rcBound) == 0))
683 {
684 goto empty;
685 }
686
687 /* Skip all rects that are completely above our intersect rect */
688 for (clipa = 0; clipa < rgnSrc->rdh.nCount; clipa++)
689 {
690 /* bottom is exclusive, so break when we go above it */
691 if (rgnSrc->Buffer[clipa].bottom > rect->top) break;
692 }
693
694 /* Bail out, if there is nothing left */
695 if (clipa == rgnSrc->rdh.nCount) goto empty;
696
697 /* Find the last rect that is still within the intersect rect (exclusive) */
698 for (clipb = clipa; clipb < rgnSrc->rdh.nCount; clipb++)
699 {
700 /* bottom is exclusive, so stop, when we start at that y pos */
701 if (rgnSrc->Buffer[clipb].top >= rect->bottom) break;
702 }
703
704 /* Bail out, if there is nothing left */
705 if (clipb == clipa) goto empty;
706
707 // clipa - index of the first rect in the first intersecting band
708 // clipb - index of the last rect in the last intersecting band plus 1
709
710 /* Check if the buffer in the dest region is large enough,
711 otherwise allocate a new one */
712 nRgnSize = (clipb - clipa) * sizeof(RECT);
713 if ((rgnDst != rgnSrc) && (rgnDst->rdh.nRgnSize < nRgnSize))
714 {
715 PRECTL temp;
717 if (temp == NULL)
718 return ERROR;
719
720 /* Free the old buffer */
721 if (rgnDst->Buffer && (rgnDst->Buffer != &rgnDst->rdh.rcBound))
723
724 rgnDst->Buffer = temp;
725 rgnDst->rdh.nCount = 0;
726 rgnDst->rdh.nRgnSize = nRgnSize;
727 rgnDst->rdh.iType = RDH_RECTANGLES;
728 }
729
730 /* Loop all rects within the intersect rect from the y perspective */
731 for (i = clipa, j = 0; i < clipb ; i++)
732 {
733 /* i - src index, j - dst index, j is always <= i for obvious reasons */
734
735 lpr = &rgnSrc->Buffer[i];
736
737 /* Make sure the source rect is not retarded */
738 ASSERT(lpr->bottom > lpr->top);
739 ASSERT(lpr->right > lpr->left);
740
741 /* We already checked above, this should hold true */
742 ASSERT(lpr->bottom > rect->top);
743 ASSERT(lpr->top < rect->bottom);
744
745 /* Check if this rect is really inside the intersect rect */
746 if ((lpr->left < rect->right) && (lpr->right > rect->left))
747 {
748 rpr = &rgnDst->Buffer[j];
749
750 /* Crop the rect with the intersect rect */
751 rpr->top = max(lpr->top, rect->top);
752 rpr->bottom = min(lpr->bottom, rect->bottom);
753 rpr->left = max(lpr->left, rect->left);
754 rpr->right = min(lpr->right, rect->right);
755
756 /* Make sure the resulting rect is not retarded */
757 ASSERT(rpr->bottom > rpr->top);
758 ASSERT(rpr->right > rpr->left);
759
760 /* Track new bounds */
761 if (rpr->left < left) left = rpr->left;
762 if (rpr->right > right) right = rpr->right;
763 if (rpr->top < top) top = rpr->top;
764 if (rpr->bottom > bottom) bottom = rpr->bottom;
765
766 /* Next target rect */
767 j++;
768 }
769 }
770
771 if (j == 0) goto empty;
772
773 /* Update the bounds rect */
774 rgnDst->rdh.rcBound.left = left;
775 rgnDst->rdh.rcBound.right = right;
776 rgnDst->rdh.rcBound.top = top;
777 rgnDst->rdh.rcBound.bottom = bottom;
778
779 /* Set new rect count */
780 rgnDst->rdh.nCount = j;
781
782 return REGION_Complexity(rgnDst);
783
784empty:
785 if (rgnDst->Buffer == NULL)
786 {
787 rgnDst->Buffer = &rgnDst->rdh.rcBound;
788 }
789
static const WCHAR empty[]
Definition: main.c:47
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define max(a, b)
Definition: svc.c:63
#define MAXLONG
Definition: umtypes.h:116
#define MINLONG
Definition: umtypes.h:115
#define EXTENTCHECK(r1, r2)
Definition: region.c:166

◆ REGION_Delete()

◆ REGION_FreeStorage()

static VOID FASTCALL REGION_FreeStorage ( SCANLINE_LISTBLOCK pSLLBlock)
static

Definition at line 3021 of file region.c.

3026{
3027 SCANLINE_LISTBLOCK *tmpSLLBlock;
3028
3029 while (pSLLBlock)
3030 {
3031 tmpSLLBlock = pSLLBlock->next;
3032 ExFreePoolWithTag(pSLLBlock, TAG_REGION);

Referenced by REGION_SetPolyPolygonRgn().

◆ REGION_GetRgnBox()

INT FASTCALL REGION_GetRgnBox ( PREGION  Rgn,
PRECTL  pRect 
)

◆ REGION_InsertEdgeInET()

static VOID FASTCALL REGION_InsertEdgeInET ( EDGE_TABLE ET,
EDGE_TABLE_ENTRY ETE,
INT  scanline,
SCANLINE_LISTBLOCK **  SLLBlock,
INT iSLLBlock 
)
static

Definition at line 2806 of file region.c.

2815{
2816 EDGE_TABLE_ENTRY *start, *prev;
2817 SCANLINE_LIST *pSLL, *pPrevSLL;
2818 SCANLINE_LISTBLOCK *tmpSLLBlock;
2819
2820 /* Find the right bucket to put the edge into */
2821 pPrevSLL = &ET->scanlines;
2822 pSLL = pPrevSLL->next;
2823 while (pSLL && (pSLL->scanline < scanline))
2824 {
2825 pPrevSLL = pSLL;
2826 pSLL = pSLL->next;
2827 }
2828
2829 /* Reassign pSLL (pointer to SCANLINE_LIST) if necessary */
2830 if ((!pSLL) || (pSLL->scanline > scanline))
2831 {
2832 if (*iSLLBlock > SLLSPERBLOCK-1)
2833 {
2834 tmpSLLBlock = ExAllocatePoolWithTag(PagedPool,
2835 sizeof(SCANLINE_LISTBLOCK),
2836 TAG_REGION);
2837 if (tmpSLLBlock == NULL)
2838 {
2839 DPRINT1("REGION_InsertEdgeInETL(): Can't alloc SLLB\n");
2840 /* FIXME: Free resources? */
2841 return;
2842 }
2843
2844 (*SLLBlock)->next = tmpSLLBlock;
2845 tmpSLLBlock->next = (SCANLINE_LISTBLOCK *)NULL;
2846 *SLLBlock = tmpSLLBlock;
2847 *iSLLBlock = 0;
2848 }
2849
2850 pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
2851
2852 pSLL->next = pPrevSLL->next;
2853 pSLL->edgelist = (EDGE_TABLE_ENTRY *)NULL;
2854 pPrevSLL->next = pSLL;
2855 }
2856
2857 pSLL->scanline = scanline;
2858
2859 /* Now insert the edge in the right bucket */
2860 prev = (EDGE_TABLE_ENTRY *)NULL;
2861 start = pSLL->edgelist;
2862 while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
2863 {
2864 prev = start;
2865 start = start->next;
2866 }
2867
2868 ETE->next = start;
2869
2870 if (prev)
2871 prev->next = ETE;
GLuint start
Definition: gl.h:1545
struct _SCANLINE_LIST * next
Definition: region.c:324
EDGE_TABLE_ENTRY * edgelist
Definition: region.c:323
INT scanline
Definition: region.c:322
#define SLLSPERBLOCK
Definition: region.c:339

Referenced by REGION_CreateETandAET().

◆ REGION_InsertionSort()

static BOOL FASTCALL REGION_InsertionSort ( EDGE_TABLE_ENTRY AET)
static

Definition at line 2978 of file region.c.

2983{
2984 EDGE_TABLE_ENTRY *pETEchase;
2985 EDGE_TABLE_ENTRY *pETEinsert;
2986 EDGE_TABLE_ENTRY *pETEchaseBackTMP;
2987 BOOL changed = FALSE;
2988
2989 AET = AET->next;
2990 while (AET)
2991 {
2992 pETEinsert = AET;
2993 pETEchase = AET;
2994 while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
2995 pETEchase = pETEchase->back;
2996
2997 AET = AET->next;
2998 if (pETEchase != pETEinsert)
2999 {
3000 pETEchaseBackTMP = pETEchase->back;
3001 pETEinsert->back->next = AET;
3002 if (AET)
3003 AET->back = pETEinsert->back;
3004
3005 pETEinsert->next = pETEchase;
3006 pETEchase->back->next = pETEinsert;
3007 pETEchase->back = pETEinsert;
3008 pETEinsert->back = pETEchaseBackTMP;
3009 changed = TRUE;
3010 }
3011 }

Referenced by REGION_SetPolyPolygonRgn().

◆ REGION_IntersectO()

static BOOL FASTCALL REGION_IntersectO ( PREGION  pReg,
PRECTL  r1,
PRECTL  r1End,
PRECTL  r2,
PRECTL  r2End,
INT  top,
INT  bottom 
)
static

Handle an overlapping band for REGION_Intersect.

Results: None.

Note
Side Effects: Rectangles may be added to the region.

Definition at line 1236 of file region.c.

1247{
1248 INT left, right;
1249
1250 while ((r1 != r1End) && (r2 != r2End))
1251 {
1252 left = max(r1->left, r2->left);
1253 right = min(r1->right, r2->right);
1254
1255 /* If there's any overlap between the two rectangles, add that
1256 * overlap to the new region.
1257 * There's no need to check for subsumption because the only way
1258 * such a need could arise is if some region has two rectangles
1259 * right next to each other. Since that should never happen... */
1260 if (left < right)
1261 {
1262 if (!REGION_bAddRect(pReg, left, top, right, bottom))
1263 {
1264 return FALSE;
1265 }
1266 }
1267
1268 /* Need to advance the pointers. Shift the one that extends
1269 * to the right the least, since the other still has a chance to
1270 * overlap with that region's next rectangle, if you see what I mean. */
1271 if (r1->right < r2->right)
1272 {
1273 r1++;
1274 }
1275 else if (r2->right < r1->right)
1276 {
1277 r2++;
1278 }
1279 else
1280 {
1281 r1++;
1282 r2++;
1283 }
1284 }

Referenced by REGION_IntersectRegion().

◆ REGION_IntersectRegion()

static BOOL FASTCALL REGION_IntersectRegion ( PREGION  newReg,
PREGION  reg1,
PREGION  reg2 
)
static

Definition at line 1292 of file region.c.

1299{
1300 /* Check for trivial reject */
1301 if ((reg1->rdh.nCount == 0) ||
1302 (reg2->rdh.nCount == 0) ||
1303 (EXTENTCHECK(&reg1->rdh.rcBound, &reg2->rdh.rcBound) == 0))
1304 {
1305 newReg->rdh.nCount = 0;
1306 }
1307 else
1308 {
1309 if (!REGION_RegionOp(newReg,
1310 reg1,
1311 reg2,
1313 NULL,
1314 NULL))
1315 return FALSE;
1316 }
1317
1318 /* Can't alter newReg's extents before we call miRegionOp because
1319 * it might be one of the source regions and miRegionOp depends
1320 * on the extents of those regions being the same. Besides, this
1321 * way there's no checking against rectangles that will be nuked
1322 * due to coalescing, so we have to examine fewer rectangles. */
static BOOL FASTCALL REGION_IntersectO(PREGION pReg, PRECTL r1, PRECTL r1End, PRECTL r2, PRECTL r2End, INT top, INT bottom)
Definition: region.c:1236
static BOOL FASTCALL REGION_RegionOp(PREGION newReg, PREGION reg1, PREGION reg2, overlapProcp overlapFunc, nonOverlapProcp nonOverlap1Func, nonOverlapProcp nonOverlap2Func)
Definition: region.c:946

Referenced by IntGdiCombineRgn(), REGION_bIntersectRegion(), and REGION_bMakeFrameRegion().

◆ REGION_loadAET()

static VOID FASTCALL REGION_loadAET ( EDGE_TABLE_ENTRY AET,
EDGE_TABLE_ENTRY ETEs 
)
static

Definition at line 2884 of file region.c.

2890{
2891 EDGE_TABLE_ENTRY *pPrevAET;
2892 EDGE_TABLE_ENTRY *tmp;
2893
2894 pPrevAET = AET;
2895 AET = AET->next;
2896 while (ETEs)
2897 {
2898 while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
2899 {
2900 pPrevAET = AET;
2901 AET = AET->next;
2902 }
2903
2904 tmp = ETEs->next;
2905 ETEs->next = AET;
2906 if (AET)
2907 AET->back = ETEs;
2908
2909 ETEs->back = pPrevAET;
2910 pPrevAET->next = ETEs;
2911 pPrevAET = ETEs;
2912

Referenced by REGION_SetPolyPolygonRgn().

◆ REGION_LockRgn()

◆ REGION_PtInRegion()

BOOL FASTCALL REGION_PtInRegion ( PREGION  prgn,
INT  X,
INT  Y 
)

Definition at line 2582 of file region.c.

2589{
2590 ULONG i;
2591 PRECT r;
2592
2593 if (prgn->rdh.nCount > 0 && INRECT(prgn->rdh.rcBound, X, Y))
2594 {
2595 r = prgn->Buffer;
2596 for (i = 0; i < prgn->rdh.nCount; i++)
2597 {
2598 if (INRECT(r[i], X, Y))
2599 return TRUE;
2600 }
2601 }
#define Y(I)
#define INRECT(r, x, y)
Definition: region.c:14

Referenced by NtGdiExtFloodFill(), NtGdiPtInRegion(), and NtGdiPtVisible().

◆ REGION_PtsToRegion()

static INT FASTCALL REGION_PtsToRegion ( INT  numFullPtBlocks,
INT  iCurPtBlock,
POINTBLOCK FirstPtBlock,
PREGION  reg 
)
static

Definition at line 3042 of file region.c.

3050{
3051 RECTL *rects;
3052 POINT *pts;
3053 POINTBLOCK *CurPtBlock;
3054 INT i;
3055 RECTL *extents, *temp;
3056 INT numRects;
3057
3058 extents = &reg->rdh.rcBound;
3059
3060 numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
3061
3062 /* Make sure, we have at least one rect */
3063 if (numRects == 0)
3064 {
3065 numRects = 1;
3066 }
3067
3068 temp = ExAllocatePoolWithTag(PagedPool, numRects * sizeof(RECT), TAG_REGION);
3069 if (temp == NULL)
3070 {
3071 return 0;
3072 }
3073
3074 if (reg->Buffer != NULL)
3075 {
3076 COPY_RECTS(temp, reg->Buffer, reg->rdh.nCount);
3077 if (reg->Buffer != &reg->rdh.rcBound)
3079 }
3080 reg->Buffer = temp;
3081
3082 reg->rdh.nCount = numRects;
3083 CurPtBlock = FirstPtBlock;
3084 rects = reg->Buffer - 1;
3085 numRects = 0;
3086 extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE;
3087
3088 for ( ; numFullPtBlocks >= 0; numFullPtBlocks--)
3089 {
3090 /* The loop uses 2 points per iteration */
3091 i = NUMPTSTOBUFFER >> 1;
3092 if (numFullPtBlocks == 0)
3093 i = iCurPtBlock >> 1;
3094
3095 for (pts = CurPtBlock->pts; i--; pts += 2)
3096 {
3097 if (pts->x == pts[1].x)
3098 continue;
3099
3100 if ((numRects && pts->x == rects->left) &&
3101 (pts->y == rects->bottom) &&
3102 (pts[1].x == rects->right) &&
3103 ((numRects == 1) || (rects[-1].top != rects->top)) &&
3104 (i && pts[2].y > pts[1].y))
3105 {
3106 rects->bottom = pts[1].y + 1;
3107 continue;
3108 }
3109
3110 numRects++;
3111 rects++;
3112 rects->left = pts->x;
3113 rects->top = pts->y;
3114 rects->right = pts[1].x;
3115 rects->bottom = pts[1].y + 1;
3116
3117 if (rects->left < extents->left)
3118 extents->left = rects->left;
3119 if (rects->right > extents->right)
3120 extents->right = rects->right;
3121 }
3122
3123 CurPtBlock = CurPtBlock->next;
3124 }
3125
3126 if (numRects)
3127 {
3128 extents->top = reg->Buffer->top;
3129 extents->bottom = rects->bottom;
3130 }
3131 else
3132 {
3133 extents->left = 0;
3134 extents->top = 0;
3135 extents->right = 0;
3136 extents->bottom = 0;
3137 }
3138
3139 reg->rdh.nCount = numRects;
static int reg
Definition: i386-dis.c:1290
struct _POINTBLOCK * next
Definition: region.c:520
POINT pts[NUMPTSTOBUFFER]
Definition: region.c:519
#define NUMPTSTOBUFFER
Definition: region.c:512

Referenced by REGION_SetPolyPolygonRgn().

◆ REGION_RectInRegion()

BOOL FASTCALL REGION_RectInRegion ( PREGION  Rgn,
const RECTL rect 
)

Definition at line 2605 of file region.c.

2611{
2612 PRECTL pCurRect, pRectEnd;
2613 RECT rc;
2614
2615 /* Swap the coordinates to make right >= left and bottom >= top */
2616 /* (region building rectangles are normalized the same way) */
2617 if (rect->top > rect->bottom)
2618 {
2619 rc.top = rect->bottom;
2620 rc.bottom = rect->top;
2621 }
2622 else
2623 {
2624 rc.top = rect->top;
2625 rc.bottom = rect->bottom;
2626 }
2627
2628 if (rect->right < rect->left)
2629 {
2630 rc.right = rect->left;
2631 rc.left = rect->right;
2632 }
2633 else
2634 {
2635 rc.right = rect->right;
2636 rc.left = rect->left;
2637 }
2638
2639 /* This is (just) a useful optimization */
2640 if ((Rgn->rdh.nCount > 0) && EXTENTCHECK(&Rgn->rdh.rcBound, &rc))
2641 {
2642 for (pCurRect = Rgn->Buffer, pRectEnd = pCurRect +
2643 Rgn->rdh.nCount; pCurRect < pRectEnd; pCurRect++)
2644 {
2645 if (pCurRect->bottom <= rc.top)
2646 continue; /* Not far enough down yet */
2647
2648 if (pCurRect->top >= rc.bottom)
2649 break; /* Too far down */
2650
2651 if (pCurRect->right <= rc.left)
2652 continue; /* Not far enough over yet */
2653
2654 if (pCurRect->left >= rc.right)
2655 {
2656 continue;
2657 }
2658
2659 return TRUE;
2660 }
2661 }

Referenced by IntRectInRegion(), and NtGdiRectVisible().

◆ REGION_RegionOp()

static BOOL FASTCALL REGION_RegionOp ( PREGION  newReg,
PREGION  reg1,
PREGION  reg2,
overlapProcp  overlapFunc,
nonOverlapProcp  nonOverlap1Func,
nonOverlapProcp  nonOverlap2Func 
)
static
  Apply an operation to two regions. Called by REGION_Union,
  REGION_Inverse, REGION_Subtract, REGION_Intersect...

Results: None.

Side Effects: The new region is overwritten.

Note
The idea behind this function is to view the two regions as sets. Together they cover a rectangle of area that this function divides into horizontal bands where points are covered only by one region or by both. For the first case, the nonOverlapFunc is called with each the band and the band's upper and lower extents. For the second, the overlapFunc is called to process the entire band. It is responsible for clipping the rectangles in the band, though this function provides the boundaries. At the end of each band, the new region is coalesced, if possible, to reduce the number of rectangles in the region.

Definition at line 946 of file region.c.

956{
957 RECTL *r1; /* Pointer into first region */
958 RECTL *r2; /* Pointer into 2d region */
959 RECTL *r1End; /* End of 1st region */
960 RECTL *r2End; /* End of 2d region */
961 INT ybot; /* Bottom of intersection */
962 INT ytop; /* Top of intersection */
963 RECTL *oldRects; /* Old rects for newReg */
964 ULONG prevBand; /* Index of start of
965 * Previous band in newReg */
966 ULONG curBand; /* Index of start of current band in newReg */
967 RECTL *r1BandEnd; /* End of current band in r1 */
968 RECTL *r2BandEnd; /* End of current band in r2 */
969 ULONG top; /* Top of non-overlapping band */
970 ULONG bot; /* Bottom of non-overlapping band */
971
972 /* Initialization:
973 * set r1, r2, r1End and r2End appropriately, preserve the important
974 * parts of the destination region until the end in case it's one of
975 * the two source regions, then mark the "new" region empty, allocating
976 * another array of rectangles for it to use. */
977 r1 = reg1->Buffer;
978 r2 = reg2->Buffer;
979 r1End = r1 + reg1->rdh.nCount;
980 r2End = r2 + reg2->rdh.nCount;
981
982 /* newReg may be one of the src regions so we can't empty it. We keep a
983 * note of its rects pointer (so that we can free them later), preserve its
984 * extents and simply set numRects to zero. */
985 oldRects = newReg->Buffer;
986 newReg->rdh.nCount = 0;
987
988 /* Allocate a reasonable number of rectangles for the new region. The idea
989 * is to allocate enough so the individual functions don't need to
990 * reallocate and copy the array, which is time consuming, yet we don't
991 * have to worry about using too much memory. I hope to be able to
992 * nuke the Xrealloc() at the end of this function eventually. */
993 newReg->rdh.nRgnSize = max(reg1->rdh.nCount + 1, reg2->rdh.nCount) * 2 * sizeof(RECT);
994
996 newReg->rdh.nRgnSize,
997 TAG_REGION);
998 if (newReg->Buffer == NULL)
999 {
1000 newReg->rdh.nRgnSize = 0;
1001 return FALSE;
1002 }
1003
1004 /* Initialize ybot and ytop.
1005 * In the upcoming loop, ybot and ytop serve different functions depending
1006 * on whether the band being handled is an overlapping or non-overlapping
1007 * band.
1008 * In the case of a non-overlapping band (only one of the regions
1009 * has points in the band), ybot is the bottom of the most recent
1010 * intersection and thus clips the top of the rectangles in that band.
1011 * ytop is the top of the next intersection between the two regions and
1012 * serves to clip the bottom of the rectangles in the current band.
1013 * For an overlapping band (where the two regions intersect), ytop clips
1014 * the top of the rectangles of both regions and ybot clips the bottoms. */
1015 if (reg1->rdh.rcBound.top < reg2->rdh.rcBound.top)
1016 ybot = reg1->rdh.rcBound.top;
1017 else
1018 ybot = reg2->rdh.rcBound.top;
1019
1020 /* prevBand serves to mark the start of the previous band so rectangles
1021 * can be coalesced into larger rectangles. qv. miCoalesce, above.
1022 * In the beginning, there is no previous band, so prevBand == curBand
1023 * (curBand is set later on, of course, but the first band will always
1024 * start at index 0). prevBand and curBand must be indices because of
1025 * the possible expansion, and resultant moving, of the new region's
1026 * array of rectangles. */
1027 prevBand = 0;
1028 do
1029 {
1030 curBand = newReg->rdh.nCount;
1031
1032 /* This algorithm proceeds one source-band (as opposed to a
1033 * destination band, which is determined by where the two regions
1034 * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
1035 * rectangle after the last one in the current band for their
1036 * respective regions. */
1037 r1BandEnd = r1;
1038 while ((r1BandEnd != r1End) && (r1BandEnd->top == r1->top))
1039 {
1040 r1BandEnd++;
1041 }
1042
1043 r2BandEnd = r2;
1044 while ((r2BandEnd != r2End) && (r2BandEnd->top == r2->top))
1045 {
1046 r2BandEnd++;
1047 }
1048
1049 /* First handle the band that doesn't intersect, if any.
1050 *
1051 * Note that attention is restricted to one band in the
1052 * non-intersecting region at once, so if a region has n
1053 * bands between the current position and the next place it overlaps
1054 * the other, this entire loop will be passed through n times. */
1055 if (r1->top < r2->top)
1056 {
1057 top = max(r1->top,ybot);
1058 bot = min(r1->bottom,r2->top);
1059
1060 if ((top != bot) && (nonOverlap1Func != NULL))
1061 {
1062 if (!(*nonOverlap1Func)(newReg, r1, r1BandEnd, top, bot)) return FALSE;
1063 }
1064
1065 ytop = r2->top;
1066 }
1067 else if (r2->top < r1->top)
1068 {
1069 top = max(r2->top,ybot);
1070 bot = min(r2->bottom,r1->top);
1071
1072 if ((top != bot) && (nonOverlap2Func != NULL))
1073 {
1074 if (!(*nonOverlap2Func)(newReg, r2, r2BandEnd, top, bot) ) return FALSE;
1075 }
1076
1077 ytop = r1->top;
1078 }
1079 else
1080 {
1081 ytop = r1->top;
1082 }
1083
1084 /* If any rectangles got added to the region, try and coalesce them
1085 * with rectangles from the previous band. Note we could just do
1086 * this test in miCoalesce, but some machines incur a not
1087 * inconsiderable cost for function calls, so... */
1088 if (newReg->rdh.nCount != curBand)
1089 {
1090 prevBand = REGION_Coalesce(newReg, prevBand, curBand);
1091 }
1092
1093 /* Now see if we've hit an intersecting band. The two bands only
1094 * intersect if ybot > ytop */
1095 ybot = min(r1->bottom, r2->bottom);
1096 curBand = newReg->rdh.nCount;
1097 if (ybot > ytop)
1098 {
1099 if (!(*overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot)) return FALSE;
1100 }
1101
1102 if (newReg->rdh.nCount != curBand)
1103 {
1104 prevBand = REGION_Coalesce(newReg, prevBand, curBand);
1105 }
1106
1107 /* If we've finished with a band (bottom == ybot) we skip forward
1108 * in the region to the next band. */
1109 if (r1->bottom == ybot)
1110 {
1111 r1 = r1BandEnd;
1112 }
1113 if (r2->bottom == ybot)
1114 {
1115 r2 = r2BandEnd;
1116 }
1117 }
1118 while ((r1 != r1End) && (r2 != r2End));
1119
1120 /* Deal with whichever region still has rectangles left. */
1121 curBand = newReg->rdh.nCount;
1122 if (r1 != r1End)
1123 {
1124 if (nonOverlap1Func != NULL)
1125 {
1126 do
1127 {
1128 r1BandEnd = r1;
1129 while ((r1BandEnd < r1End) && (r1BandEnd->top == r1->top))
1130 {
1131 r1BandEnd++;
1132 }
1133
1134 if (!(*nonOverlap1Func)(newReg,
1135 r1,
1136 r1BandEnd,
1137 max(r1->top,ybot),
1138 r1->bottom))
1139 return FALSE;
1140 r1 = r1BandEnd;
1141 }
1142 while (r1 != r1End);
1143 }
1144 }
1145 else if ((r2 != r2End) && (nonOverlap2Func != NULL))
1146 {
1147 do
1148 {
1149 r2BandEnd = r2;
1150 while ((r2BandEnd < r2End) && (r2BandEnd->top == r2->top))
1151 {
1152 r2BandEnd++;
1153 }
1154
1155 if (!(*nonOverlap2Func)(newReg,
1156 r2,
1157 r2BandEnd,
1158 max(r2->top,ybot),
1159 r2->bottom))
1160 return FALSE;
1161 r2 = r2BandEnd;
1162 }
1163 while (r2 != r2End);
1164 }
1165
1166 if (newReg->rdh.nCount != curBand)
1167 {
1168 (VOID)REGION_Coalesce(newReg, prevBand, curBand);
1169 }
1170
1171 /* A bit of cleanup. To keep regions from growing without bound,
1172 * we shrink the array of rectangles to match the new number of
1173 * rectangles in the region. This never goes to 0, however...
1174 *
1175 * Only do this stuff if the number of rectangles allocated is more than
1176 * twice the number of rectangles in the region (a simple optimization...). */
1177 if ((newReg->rdh.nRgnSize > (2 * newReg->rdh.nCount * sizeof(RECT))) &&
1178 (newReg->rdh.nCount > 2))
1179 {
1180 if (REGION_NOT_EMPTY(newReg))
1181 {
1182 RECTL *prev_rects = newReg->Buffer;
1184 newReg->rdh.nCount * sizeof(RECT),
1185 TAG_REGION);
1186
1187 if (newReg->Buffer == NULL)
1188 {
1189 newReg->Buffer = prev_rects;
1190 }
1191 else
1192 {
1193 newReg->rdh.nRgnSize = newReg->rdh.nCount*sizeof(RECT);
1194 COPY_RECTS(newReg->Buffer, prev_rects, newReg->rdh.nCount);
1195 if (prev_rects != &newReg->rdh.rcBound)
1196 ExFreePoolWithTag(prev_rects, TAG_REGION);
1197 }
1198 }
1199 else
1200 {
1201 /* No point in doing the extra work involved in an Xrealloc if
1202 * the region is empty */
1203 newReg->rdh.nRgnSize = sizeof(RECT);
1204 if (newReg->Buffer != &newReg->rdh.rcBound)
1206
1208 sizeof(RECT),
1209 TAG_REGION);
1210 ASSERT(newReg->Buffer);
1211 }
1212 }
1213
1214 newReg->rdh.iType = RDH_RECTANGLES;
1215
1216 if (oldRects != &newReg->rdh.rcBound)
#define VOID
Definition: acefi.h:82
static INT FASTCALL REGION_Coalesce(PREGION pReg, INT prevStart, INT curStart)
Definition: region.c:808

Referenced by REGION_IntersectRegion(), REGION_SubtractRegion(), and REGION_UnionRegion().

◆ REGION_SetExtents()

static VOID FASTCALL REGION_SetExtents ( PREGION  pReg)
static

Definition at line 617 of file region.c.

622{
623 RECTL *pRect, *pRectEnd, *pExtents;
624
625 /* Quick check for NULLREGION */
626 if (pReg->rdh.nCount == 0)
627 {
628 pReg->rdh.rcBound.left = 0;
629 pReg->rdh.rcBound.top = 0;
630 pReg->rdh.rcBound.right = 0;
631 pReg->rdh.rcBound.bottom = 0;
632 pReg->rdh.iType = RDH_RECTANGLES;
633 return;
634 }
635
636 pExtents = &pReg->rdh.rcBound;
637 pRect = pReg->Buffer;
638 pRectEnd = pReg->Buffer + pReg->rdh.nCount - 1;
639
640 /* Since pRect is the first rectangle in the region, it must have the
641 * smallest top and since pRectEnd is the last rectangle in the region,
642 * it must have the largest bottom, because of banding. Initialize left and
643 * right from pRect and pRectEnd, resp., as good things to initialize them
644 * to... */
645 pExtents->left = pRect->left;
646 pExtents->top = pRect->top;
647 pExtents->right = pRectEnd->right;
648 pExtents->bottom = pRectEnd->bottom;
649
650 while (pRect <= pRectEnd)
651 {
652 if (pRect->left < pExtents->left)
653 pExtents->left = pRect->left;
654 if (pRect->right > pExtents->right)
655 pExtents->right = pRect->right;
656 pRect++;
657 }

Referenced by REGION_IntersectRegion(), and REGION_SubtractRegion().

◆ REGION_SetPolyPolygonRgn()

BOOL FASTCALL REGION_SetPolyPolygonRgn ( _Inout_ PREGION  prgn,
_In_ const POINT ppt,
_In_ const ULONG pcPoints,
_In_ ULONG  cPolygons,
_In_ INT  iMode 
)

Definition at line 3254 of file region.c.

3263{
3264 EDGE_TABLE_ENTRY *pAET; /* Active Edge Table */
3265 INT y; /* Current scanline */
3266 INT iPts = 0; /* Number of pts in buffer */
3267 EDGE_TABLE_ENTRY *pWETE; /* Winding Edge Table Entry */
3268 SCANLINE_LIST *pSLL; /* Current SCANLINE_LIST */
3269 POINT *pts; /* Output buffer */
3270 EDGE_TABLE_ENTRY *pPrevAET; /* Pointer to previous AET */
3271 EDGE_TABLE ET; /* Header node for ET */
3272 EDGE_TABLE_ENTRY AET; /* Header node for AET */
3273 EDGE_TABLE_ENTRY *pETEs; /* EDGE_TABLEEntries pool */
3274 SCANLINE_LISTBLOCK SLLBlock; /* Header for SCANLINE_LIST */
3275 INT fixWAET = FALSE;
3276 POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */
3277 POINTBLOCK *tmpPtBlock;
3278 UINT numFullPtBlocks = 0;
3279 UINT poly, total;
3280 BOOL bResult = FALSE;
3281
3282 /* Check if iMode is valid */
3283 if ((iMode != ALTERNATE) && (iMode != WINDING))
3284 {
3285 DPRINT1("Invalid iMode: %lu\n", iMode);
3286 return FALSE;
3287 }
3288
3289 /* Special case a rectangle */
3290 if (((cPolygons == 1) && ((pcPoints[0] == 4) ||
3291 ((pcPoints[0] == 5) && (ppt[4].x == ppt[0].x) && (ppt[4].y == ppt[0].y)))) &&
3292 (((ppt[0].y == ppt[1].y) &&
3293 (ppt[1].x == ppt[2].x) &&
3294 (ppt[2].y == ppt[3].y) &&
3295 (ppt[3].x == ppt[0].x)) ||
3296 ((ppt[0].x == ppt[1].x) &&
3297 (ppt[1].y == ppt[2].y) &&
3298 (ppt[2].x == ppt[3].x) &&
3299 (ppt[3].y == ppt[0].y))))
3300 {
3301 REGION_SetRectRgn(prgn,
3302 min(ppt[0].x, ppt[2].x),
3303 min(ppt[0].y, ppt[2].y),
3304 max(ppt[0].x, ppt[2].x),
3305 max(ppt[0].y, ppt[2].y));
3306 return TRUE;
3307 }
3308
3309 for (poly = total = 0; poly < cPolygons; poly++)
3310 total += pcPoints[poly];
3311
3313 sizeof(EDGE_TABLE_ENTRY) * total,
3314 TAG_REGION);
3315 if (pETEs == NULL)
3316 {
3317 DPRINT1("Failed to allocate %lu edge entries\n", total);
3318 return FALSE;
3319 }
3320
3321 pts = FirstPtBlock.pts;
3322 REGION_CreateETandAET(pcPoints, cPolygons, ppt, &ET, &AET, pETEs, &SLLBlock);
3323 pSLL = ET.scanlines.next;
3324 curPtBlock = &FirstPtBlock;
3325
3326 if (iMode != WINDING)
3327 {
3328 /* For each scanline */
3329 for (y = ET.ymin; y < ET.ymax; y++)
3330 {
3331 /* Add a new edge to the active edge table when we
3332 * get to the next edge. */
3333 if (pSLL != NULL && y == pSLL->scanline)
3334 {
3335 REGION_loadAET(&AET, pSLL->edgelist);
3336 pSLL = pSLL->next;
3337 }
3338 pPrevAET = &AET;
3339 pAET = AET.next;
3340
3341 /* For each active edge */
3342 while (pAET)
3343 {
3344 pts->x = pAET->bres.minor_axis, pts->y = y;
3345 pts++, iPts++;
3346
3347 /* Send out the buffer */
3348 if (iPts == NUMPTSTOBUFFER)
3349 {
3350 tmpPtBlock = ExAllocatePoolWithTag(PagedPool,
3351 sizeof(POINTBLOCK),
3352 TAG_REGION);
3353 if (tmpPtBlock == NULL)
3354 {
3355 DPRINT1("Can't alloc tmpPtBlock\n");
3356 goto Cleanup;
3357 }
3358
3359 curPtBlock->next = tmpPtBlock;
3360 curPtBlock = tmpPtBlock;
3361 pts = curPtBlock->pts;
3362 numFullPtBlocks++;
3363 iPts = 0;
3364 }
3365
3366 EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
3367 }
3368
3370 }
3371 }
3372 else
3373 {
3374 /* For each scanline */
3375 for (y = ET.ymin; y < ET.ymax; y++)
3376 {
3377 /* Add a new edge to the active edge table when we
3378 * get to the next edge. */
3379 if (pSLL != NULL && y == pSLL->scanline)
3380 {
3381 REGION_loadAET(&AET, pSLL->edgelist);
3382 REGION_computeWAET(&AET);
3383 pSLL = pSLL->next;
3384 }
3385
3386 pPrevAET = &AET;
3387 pAET = AET.next;
3388 pWETE = pAET;
3389
3390 /* For each active edge */
3391 while (pAET)
3392 {
3393 /* Add to the buffer only those edges that
3394 * are in the Winding active edge table. */
3395 if (pWETE == pAET)
3396 {
3397 pts->x = pAET->bres.minor_axis;
3398 pts->y = y;
3399 pts++;
3400 iPts++;
3401
3402 /* Send out the buffer */
3403 if (iPts == NUMPTSTOBUFFER)
3404 {
3405 tmpPtBlock = ExAllocatePoolWithTag(PagedPool,
3406 sizeof(POINTBLOCK),
3407 TAG_REGION);
3408 if (tmpPtBlock == NULL)
3409 {
3410 DPRINT1("Can't alloc tPB\n");
3411 goto Cleanup;
3412 }
3413 curPtBlock->next = tmpPtBlock;
3414 curPtBlock = tmpPtBlock;
3415 pts = curPtBlock->pts;
3416 numFullPtBlocks++;
3417 iPts = 0;
3418 }
3419
3420 pWETE = pWETE->nextWETE;
3421 }
3422
3423 EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
3424 }
3425
3426 /* Recompute the winding active edge table if
3427 * we just resorted or have exited an edge. */
3428 if (REGION_InsertionSort(&AET) || fixWAET)
3429 {
3430 REGION_computeWAET(&AET);
3431 fixWAET = FALSE;
3432 }
3433 }
3434 }
3435
3436 REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, prgn);
3437 bResult = TRUE;
3438
3439Cleanup:
3440 REGION_FreeStorage(SLLBlock.next);
3441
3442 for (curPtBlock = FirstPtBlock.next; numFullPtBlocks-- > 0;)
3443 {
3444 tmpPtBlock = curPtBlock->next;
3445 ExFreePoolWithTag(curPtBlock, TAG_REGION);
3446 curPtBlock = tmpPtBlock;
3447 }
3448
#define ALTERNATE
Definition: constants.h:278
static const WCHAR Cleanup[]
Definition: register.c:80
size_t total
static VOID FASTCALL REGION_CreateETandAET(const ULONG *Count, INT nbpolygons, const POINT *pts, EDGE_TABLE *ET, EDGE_TABLE_ENTRY *AET, EDGE_TABLE_ENTRY *pETEs, SCANLINE_LISTBLOCK *pSLLBlock)
Definition: region.c:3168
static INT FASTCALL REGION_PtsToRegion(INT numFullPtBlocks, INT iCurPtBlock, POINTBLOCK *FirstPtBlock, PREGION reg)
Definition: region.c:3042
static VOID FASTCALL REGION_FreeStorage(SCANLINE_LISTBLOCK *pSLLBlock)
Definition: region.c:3021
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
Definition: region.c:381
static VOID FASTCALL REGION_loadAET(EDGE_TABLE_ENTRY *AET, EDGE_TABLE_ENTRY *ETEs)
Definition: region.c:2884
static VOID FASTCALL REGION_computeWAET(EDGE_TABLE_ENTRY *AET)
Definition: region.c:2937
static BOOL FASTCALL REGION_InsertionSort(EDGE_TABLE_ENTRY *AET)
Definition: region.c:2978
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
Definition: region.c:359

Referenced by GreCreatePolyPolygonRgn(), PATH_PathToRegion(), and REGION_bXformRgn().

◆ REGION_SetRectRgn()

VOID FASTCALL REGION_SetRectRgn ( PREGION  rgn,
INT  LeftRect,
INT  TopRect,
INT  RightRect,
INT  BottomRect 
)

Definition at line 2665 of file region.c.

2674{
2675 PRECTL firstRect;
2676
2677 if (LeftRect > RightRect)
2678 {
2679 INT tmp = LeftRect;
2680 LeftRect = RightRect;
2681 RightRect = tmp;
2682 }
2683
2684 if (TopRect > BottomRect)
2685 {
2686 INT tmp = TopRect;
2687 TopRect = BottomRect;
2688 BottomRect = tmp;
2689 }
2690
2691 if ((LeftRect != RightRect) && (TopRect != BottomRect))
2692 {
2693 firstRect = rgn->Buffer;
2694 ASSERT(firstRect);
2695 firstRect->left = rgn->rdh.rcBound.left = LeftRect;
2696 firstRect->top = rgn->rdh.rcBound.top = TopRect;
2697 firstRect->right = rgn->rdh.rcBound.right = RightRect;
2698 firstRect->bottom = rgn->rdh.rcBound.bottom = BottomRect;
2699 rgn->rdh.nCount = 1;
2700 rgn->rdh.iType = RDH_RECTANGLES;
2701 }
2702 else
2703 {

Referenced by co_IntGetUpdateRgn(), IntSetDefaultRegion(), IntSysCreateRectpRgn(), NtGdiCreateRectRgn(), NtGdiSelectBitmap(), NtGdiSetRectRgn(), REGION_SetPolyPolygonRgn(), REGION_vSyncRegion(), and UserScrollDC().

◆ REGION_SubtractNonO1()

static BOOL FASTCALL REGION_SubtractNonO1 ( PREGION  pReg,
PRECTL  r,
PRECTL  rEnd,
INT  top,
INT  bottom 
)
static
 Deal with non-overlapping band for subtraction. Any parts from
 region 2 we discard. Anything from region 1 we add to the region.

Results: None.

Note
Side Effects: pReg may be affected.

Definition at line 1561 of file region.c.

1570{
1571 if (r != rEnd)
1572 {
1573 if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (rEnd - r)))
1574 {
1575 return FALSE;
1576 }
1577
1578 do
1579 {
1580 REGION_vAddRect(pReg, r->left, top, r->right, bottom);
1581 r++;
1582 }
1583 while (r != rEnd);
1584 }
FORCEINLINE VOID REGION_vAddRect(_Inout_ PREGION prgn, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
Definition: region.c:472

Referenced by REGION_SubtractRegion().

◆ REGION_SubtractO()

static BOOL FASTCALL REGION_SubtractO ( PREGION  pReg,
PRECTL  r1,
PRECTL  r1End,
PRECTL  r2,
PRECTL  r2End,
INT  top,
INT  bottom 
)
static
 Overlapping band subtraction. x1 is the left-most point not yet
 checked.

Results: None.

Note
Side Effects: pReg may have rectangles added to it.

Definition at line 1600 of file region.c.

1611{
1612 INT left;
1613
1614 left = r1->left;
1615
1616 while ((r1 != r1End) && (r2 != r2End))
1617 {
1618 if (r2->right <= left)
1619 {
1620 /* Subtrahend missed the boat: go to next subtrahend. */
1621 r2++;
1622 }
1623 else if (r2->left <= left)
1624 {
1625 /* Subtrahend preceeds minuend: nuke left edge of minuend. */
1626 left = r2->right;
1627 if (left >= r1->right)
1628 {
1629 /* Minuend completely covered: advance to next minuend and
1630 * reset left fence to edge of new minuend. */
1631 r1++;
1632 if (r1 != r1End)
1633 left = r1->left;
1634 }
1635 else
1636 {
1637 /* Subtrahend now used up since it doesn't extend beyond
1638 * minuend */
1639 r2++;
1640 }
1641 }
1642 else if (r2->left < r1->right)
1643 {
1644 /* Left part of subtrahend covers part of minuend: add uncovered
1645 * part of minuend to region and skip to next subtrahend. */
1646 if (!REGION_bAddRect(pReg, left, top, r2->left, bottom))
1647 {
1648 return FALSE;
1649 }
1650
1651 left = r2->right;
1652 if (left >= r1->right)
1653 {
1654 /* Minuend used up: advance to new... */
1655 r1++;
1656 if (r1 != r1End)
1657 left = r1->left;
1658 }
1659 else
1660 {
1661 /* Subtrahend used up */
1662 r2++;
1663 }
1664 }
1665 else
1666 {
1667 /* Minuend used up: add any remaining piece before advancing. */
1668 if (r1->right > left)
1669 {
1670 if (!REGION_bAddRect(pReg, left, top, r1->right, bottom))
1671 {
1672 return FALSE;
1673 }
1674 }
1675
1676 r1++;
1677 if (r1 != r1End)
1678 left = r1->left;
1679 }
1680 }
1681
1682 /* Make sure the buffer is large enough for all remaining operations */
1683 if (r1 != r1End)
1684 {
1685 if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (r1End - r1)))
1686 {
1687 return FALSE;
1688 }
1689
1690 /* Add remaining minuend rectangles to region. */
1691 do
1692 {
1693 REGION_vAddRect(pReg, left, top, r1->right, bottom);
1694 r1++;
1695 if (r1 != r1End)
1696 {
1697 left = r1->left;
1698 }
1699 }
1700 while (r1 != r1End);
1701 }

Referenced by REGION_SubtractRegion().

◆ REGION_SubtractRectFromRgn()

INT FASTCALL REGION_SubtractRectFromRgn ( PREGION  prgnDest,
PREGION  prgnSrc,
const RECTL prcl 
)

Definition at line 1811 of file region.c.

1818{
1819 REGION rgnLocal;
1820
1821 rgnLocal.Buffer = &rgnLocal.rdh.rcBound;
1822 rgnLocal.rdh.nCount = 1;
1823 rgnLocal.rdh.nRgnSize = sizeof(RECT);
1824 rgnLocal.rdh.rcBound = *prcl;

◆ REGION_SubtractRegion()

static BOOL FASTCALL REGION_SubtractRegion ( PREGION  regD,
PREGION  regM,
PREGION  regS 
)
static
 Subtract regS from regM and leave the result in regD.
 S stands for subtrahend, M for minuend and D for difference.

Results: TRUE.

Note
Side Effects: regD is overwritten.

Definition at line 1717 of file region.c.

1724{
1725 /* Check for trivial reject */
1726 if ((regM->rdh.nCount == 0) ||
1727 (regS->rdh.nCount == 0) ||
1728 (EXTENTCHECK(&regM->rdh.rcBound, &regS->rdh.rcBound) == 0))
1729 {
1730 return REGION_CopyRegion(regD, regM);
1731 }
1732
1733 if (!REGION_RegionOp(regD,
1734 regM,
1735 regS,
1738 NULL))
1739 return FALSE;
1740
1741 /* Can't alter newReg's extents before we call miRegionOp because
1742 * it might be one of the source regions and miRegionOp depends
1743 * on the extents of those regions being the unaltered. Besides, this
1744 * way there's no checking against rectangles that will be nuked
1745 * due to coalescing, so we have to examine fewer rectangles. */
static BOOL FASTCALL REGION_SubtractO(PREGION pReg, PRECTL r1, PRECTL r1End, PRECTL r2, PRECTL r2End, INT top, INT bottom)
Definition: region.c:1600
static BOOL FASTCALL REGION_SubtractNonO1(PREGION pReg, PRECTL r, PRECTL rEnd, INT top, INT bottom)
Definition: region.c:1561

Referenced by IntGdiCombineRgn(), REGION_bMakeFrameRegion(), REGION_SubtractRectFromRgn(), and REGION_XorRegion().

◆ REGION_UnionNonO()

static BOOL FASTCALL REGION_UnionNonO ( PREGION  pReg,
PRECTL  r,
PRECTL  rEnd,
INT  top,
INT  bottom 
)
static
 Handle a non-overlapping band for the union operation. Just
 Adds the rectangles into the region. Doesn't have to check for
 subsumption or anything.

Results: None.

Note
Side Effects: pReg->numRects is incremented and the final rectangles overwritten with the rectangles we're passed.

Definition at line 1344 of file region.c.

1353{
1354 if (r != rEnd)
1355 {
1356 if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (rEnd - r)))
1357 {
1358 return FALSE;
1359 }
1360
1361 do
1362 {
1363 REGION_vAddRect(pReg, r->left, top, r->right, bottom);
1364 r++;
1365 }
1366 while (r != rEnd);
1367 }

Referenced by REGION_UnionRegion().

◆ REGION_UnionO()

static BOOL FASTCALL REGION_UnionO ( PREGION  pReg,
PRECTL  r1,
PRECTL  r1End,
PRECTL  r2,
PRECTL  r2End,
INT  top,
INT  bottom 
)
static
 Handle an overlapping band for the union operation. Picks the
 left-most rectangle each time and merges it into the region.

Results: None.

Note
Side Effects: Rectangles are overwritten in pReg->rects and pReg->numRects will be changed.

Definition at line 1414 of file region.c.

1425{
1426 while ((r1 != r1End) && (r2 != r2End))
1427 {
1428 if (r1->left < r2->left)
1429 {
1430 if (!REGION_bMergeRect(pReg, r1->left, top, r1->right, bottom)) return FALSE;
1431 r1++;
1432 }
1433 else
1434 {
1435 if (!REGION_bMergeRect(pReg, r2->left, top, r2->right, bottom)) return FALSE;
1436 r2++;
1437 }
1438 }
1439
1440 if (r1 != r1End)
1441 {
1442 do
1443 {
1444 if (!REGION_bMergeRect(pReg, r1->left, top, r1->right, bottom)) return FALSE;
1445 r1++;
1446 }
1447 while (r1 != r1End);
1448 }
1449 else
1450 {
1451 while (r2 != r2End)
1452 {
1453 if (!REGION_bMergeRect(pReg, r2->left, top, r2->right, bottom)) return FALSE;
1454 r2++;
1455 }
1456 }
static __inline BOOL REGION_bMergeRect(_Inout_ PREGION prgn, _In_ LONG left, _In_ LONG top, _In_ LONG right, _In_ LONG bottom)
Definition: region.c:1371

Referenced by REGION_UnionRegion().

◆ REGION_UnionRectWithRgn()

BOOL FASTCALL REGION_UnionRectWithRgn ( PREGION  rgn,
const RECTL rect 
)

Adds a rectangle to a REGION

Definition at line 1796 of file region.c.

1802{
1803 REGION region;
1804
1805 region.Buffer = &region.rdh.rcBound;
1806 region.rdh.nCount = 1;
1807 region.rdh.nRgnSize = sizeof(RECT);

Referenced by NtGdiExtCreateRegion().

◆ REGION_UnionRegion()

static BOOL FASTCALL REGION_UnionRegion ( PREGION  newReg,
PREGION  reg1,
PREGION  reg2 
)
static

Definition at line 1464 of file region.c.

1471{
1472 BOOL ret = TRUE;
1473
1474 /* Checks all the simple cases
1475 * Region 1 and 2 are the same or region 1 is empty */
1476 if ((reg1 == reg2) || (reg1->rdh.nCount == 0) ||
1477 (reg1->rdh.rcBound.right <= reg1->rdh.rcBound.left) ||
1478 (reg1->rdh.rcBound.bottom <= reg1->rdh.rcBound.top))
1479 {
1480 if (newReg != reg2)
1481 {
1482 ret = REGION_CopyRegion(newReg, reg2);
1483 }
1484
1485 return ret;
1486 }
1487
1488 /* If nothing to union (region 2 empty) */
1489 if ((reg2->rdh.nCount == 0) ||
1490 (reg2->rdh.rcBound.right <= reg2->rdh.rcBound.left) ||
1491 (reg2->rdh.rcBound.bottom <= reg2->rdh.rcBound.top))
1492 {
1493 if (newReg != reg1)
1494 {
1495 ret = REGION_CopyRegion(newReg, reg1);
1496 }
1497
1498 return ret;
1499 }
1500
1501 /* Region 1 completely subsumes region 2 */
1502 if ((reg1->rdh.nCount == 1) &&
1503 (reg1->rdh.rcBound.left <= reg2->rdh.rcBound.left) &&
1504 (reg1->rdh.rcBound.top <= reg2->rdh.rcBound.top) &&
1505 (reg2->rdh.rcBound.right <= reg1->rdh.rcBound.right) &&
1506 (reg2->rdh.rcBound.bottom <= reg1->rdh.rcBound.bottom))
1507 {
1508 if (newReg != reg1)
1509 {
1510 ret = REGION_CopyRegion(newReg, reg1);
1511 }
1512
1513 return ret;
1514 }
1515
1516 /* Region 2 completely subsumes region 1 */
1517 if ((reg2->rdh.nCount == 1) &&
1518 (reg2->rdh.rcBound.left <= reg1->rdh.rcBound.left) &&
1519 (reg2->rdh.rcBound.top <= reg1->rdh.rcBound.top) &&
1520 (reg1->rdh.rcBound.right <= reg2->rdh.rcBound.right) &&
1521 (reg1->rdh.rcBound.bottom <= reg2->rdh.rcBound.bottom))
1522 {
1523 if (newReg != reg2)
1524 {
1525 ret = REGION_CopyRegion(newReg, reg2);
1526 }
1527
1528 return ret;
1529 }
1530
1531 if ((ret = REGION_RegionOp(newReg,
1532 reg1,
1533 reg2,
1537 {
1538 newReg->rdh.rcBound.left = min(reg1->rdh.rcBound.left, reg2->rdh.rcBound.left);
1539 newReg->rdh.rcBound.top = min(reg1->rdh.rcBound.top, reg2->rdh.rcBound.top);
1540 newReg->rdh.rcBound.right = max(reg1->rdh.rcBound.right, reg2->rdh.rcBound.right);
1541 newReg->rdh.rcBound.bottom = max(reg1->rdh.rcBound.bottom, reg2->rdh.rcBound.bottom);
static BOOL FASTCALL REGION_UnionO(PREGION pReg, PRECTL r1, PRECTL r1End, PRECTL r2, PRECTL r2End, INT top, INT bottom)
Definition: region.c:1414
static BOOL FASTCALL REGION_UnionNonO(PREGION pReg, PRECTL r, PRECTL rEnd, INT top, INT bottom)
Definition: region.c:1344

Referenced by IntGdiCombineRgn(), and REGION_XorRegion().

◆ REGION_UnlockRgn()

VOID FASTCALL REGION_UnlockRgn ( _In_ PREGION  prgn)

Definition at line 2373 of file region.c.

2378{
2379 PRGN_ATTR prgnattr;
2380
2381 NT_ASSERT(prgn != NULL);
2382 NT_ASSERT(prgn->prgnattr != NULL);
2383
2384 /* Get the region attribute and check if it's user mode */
2385 prgnattr = prgn->prgnattr;
2386 if (prgnattr != &prgn->rgnattr)
2387 {
2388 NT_ASSERT(GreGetObjectOwner(prgn->BaseObject.hHmgr) == GDI_OBJ_HMGR_POWNED);
2389 prgnattr->iComplexity = REGION_Complexity(prgn);
2390 prgnattr->Rect.left = prgn->rdh.rcBound.left;
2391 prgnattr->Rect.top = prgn->rdh.rcBound.top;
2392 prgnattr->Rect.right = prgn->rdh.rcBound.right;
2393 prgnattr->Rect.bottom = prgn->rdh.rcBound.bottom;
2394 prgnattr->AttrFlags |= ATTR_RGN_VALID;
2395 }
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1192

Referenced by co_IntGetUpdateRgn(), co_WinPosSetWindowPos(), DceUpdateVisRgn(), ForceNCPaintErase(), GreCreateFrameRgn(), GreCreatePolyPolygonRgn(), IntDefWindowProc(), IntGdiGetRgnBox(), IntGdiSetRegionOwner(), IntInvalidateWindows(), IntRectInRegion(), IntScrollWindowEx(), IntValidateParents(), NtGdiCombineRgn(), NtGdiCreateRectRgn(), NtGdiCreateRoundRectRgn(), NtGdiEqualRgn(), NtGdiExtCreateRegion(), NtGdiExtSelectClipRgn(), NtGdiFillRgn(), NtGdiGetRandomRgn(), NtGdiGetRgnBox(), NtGdiInvertRgn(), NtGdiOffsetRgn(), NtGdiPathToRegion(), NtGdiPtInRegion(), NtGdiSetRectRgn(), NtUserCallHwndParamLock(), NtUserRedrawWindow(), PaintSuspendedWindow(), REGION_XorRegion(), UserScrollDC(), and VIS_ComputeVisibleRegion().

◆ REGION_vAddRect()

FORCEINLINE VOID REGION_vAddRect ( _Inout_ PREGION  prgn,
_In_ LONG  left,
_In_ LONG  top,
_In_ LONG  right,
_In_ LONG  bottom 
)

Definition at line 472 of file region.c.

481{
482 PRECTL prcl;
483 NT_ASSERT((prgn->rdh.nCount + 1) * sizeof(RECT) <= prgn->rdh.nRgnSize);
484
485 prcl = &prgn->Buffer[prgn->rdh.nCount];
486 prcl->left = left;
487 prcl->top = top;
488 prcl->right = right;

Referenced by REGION_bAddRect(), REGION_SubtractNonO1(), REGION_SubtractO(), and REGION_UnionNonO().

◆ REGION_vCleanup()

VOID NTAPI REGION_vCleanup ( PVOID  ObjectBody)

Definition at line 2433 of file region.c.

2437{
2438 PREGION pRgn = (PREGION)ObjectBody;
2440 ASSERT(ppi);
2441
2442 ASSERT(pRgn->prgnattr);
2443 if (pRgn->prgnattr != &pRgn->rgnattr)
2444 GdiPoolFree(ppi->pPoolRgnAttr, pRgn->prgnattr);
2445

◆ REGION_vSyncRegion()

static VOID REGION_vSyncRegion ( _In_ PREGION  prgn)
static

Definition at line 2315 of file region.c.

2320{
2321 PRGN_ATTR prgnattr;
2322
2323 NT_ASSERT(prgn != NULL);
2324 NT_ASSERT(prgn->prgnattr != NULL);
2325 NT_ASSERT((prgn->prgnattr == &prgn->rgnattr) ||
2326 (prgn->prgnattr->AttrFlags & ATTR_RGN_VALID));
2327
2328 /* Get the region attribute and check if it's dirty (modified) */
2329 prgnattr = prgn->prgnattr;
2330 if (prgnattr->AttrFlags & ATTR_RGN_DIRTY)
2331 {
2332 NT_ASSERT(GreGetObjectOwner(prgn->BaseObject.hHmgr) == GDI_OBJ_HMGR_POWNED);
2333 NT_ASSERT(prgnattr != &prgn->rgnattr);
2334
2335 if (prgnattr->iComplexity == NULLREGION)
2336 {
2337 EMPTY_REGION(prgn);
2338 }
2339 else if (prgnattr->iComplexity == SIMPLEREGION)
2340 {
2341 REGION_SetRectRgn(prgn,
2342 prgnattr->Rect.left,
2343 prgnattr->Rect.top,
2344 prgnattr->Rect.right,
2345 prgnattr->Rect.bottom);
2346 }
2347 else
2348 {
2349 /* Should not happen, region attribute is corrupted! */
2350 DPRINT1("Region attribute is corrupted, ignoring\n");
2352 }
2353 }
2354
#define ATTR_RGN_DIRTY
Definition: ntgdihdl.h:196

Referenced by NtGdiCombineRgn(), NtGdiEqualRgn(), and REGION_LockRgn().

◆ REGION_XorRegion()

static BOOL FASTCALL REGION_XorRegion ( PREGION  dr,
PREGION  sra,
PREGION  srb 
)
static

Definition at line 1753 of file region.c.

1760{
1761 HRGN htra, htrb;
1762 PREGION tra, trb;
1763 BOOL ret;
1764
1765 // FIXME: Don't use a handle
1766 tra = REGION_AllocRgnWithHandle(sra->rdh.nCount + 1);
1767 if (tra == NULL)
1768 {
1769 return FALSE;
1770 }
1771 htra = tra->BaseObject.hHmgr;
1772
1773 // FIXME: Don't use a handle
1774 trb = REGION_AllocRgnWithHandle(srb->rdh.nCount + 1);
1775 if (trb == NULL)
1776 {
1777 REGION_UnlockRgn(tra);
1778 GreDeleteObject(htra);
1779 return FALSE;
1780 }
1781 htrb = trb->BaseObject.hHmgr;
1782
1783 ret = REGION_SubtractRegion(tra, sra, srb) &&
1784 REGION_SubtractRegion(trb, srb, sra) &&
1785 REGION_UnionRegion(dr, tra, trb);
1786 REGION_UnlockRgn(tra);
1787 REGION_UnlockRgn(trb);
1788
1789 GreDeleteObject(htra);

Referenced by IntGdiCombineRgn().

Variable Documentation

◆ hrgnDefault

HRGN hrgnDefault = NULL

Definition at line 130 of file region.c.

◆ prgnDefault

PREGION prgnDefault = NULL

Definition at line 129 of file region.c.

Referenced by DC_InitHack(), IntGdiReleaseVisRgn(), IntSetDefaultRegion(), and REGION_Delete().