6 #define INRECT(r, x, y) \
7 ( ( ((r).right > x)) && \
8 ( ((r).left <= x)) && \
9 ( ((r).bottom > y)) && \
12 #define OVERLAPPING_RGN 0
13 #define INVERTED_RGN 1
17 From tests, there are four results based on normalized coordinates.
18 If the rects are overlapping and normalized, it's OVERLAPPING_RGN.
19 If the rects are overlapping in anyway or same in dimension and one is inverted,
21 If the rects are same in dimension or NULL, it's SAME_RGN.
22 If the rects are overlapping and not normalized or displace in different areas,
27 ComplexityFromRects( PRECTL prc1
, PRECTL prc2
)
29 if ( prc2
->left
>= prc1
->left
)
31 if ( ( prc1
->right
>= prc2
->right
) &&
32 ( prc1
->top
<= prc2
->top
) &&
33 ( prc1
->bottom
>= prc2
->bottom
) )
36 if ( prc2
->left
> prc1
->left
)
38 if ( ( prc1
->left
>= prc2
->right
) ||
39 ( prc1
->right
<= prc2
->left
) ||
40 ( prc1
->top
>= prc2
->bottom
) ||
41 ( prc1
->bottom
<= prc2
->top
) )
46 if ( ( prc2
->right
< prc1
->right
) ||
47 ( prc2
->top
> prc1
->top
) ||
48 ( prc2
->bottom
< prc1
->bottom
) )
50 if ( ( prc1
->left
>= prc2
->right
) ||
51 ( prc1
->right
<= prc2
->left
) ||
52 ( prc1
->top
>= prc2
->bottom
) ||
53 ( prc1
->bottom
<= prc2
->top
) )
60 return OVERLAPPING_RGN
;
66 SortRects(PRECT pRect
, INT nCount
)
68 INT i
= 0, a
= 0, b
= 0, c
, s
;
73 i
= 1; // set index point
74 c
= nCount
; // set inverse count
77 s
= i
; // set sort count
84 if(pRect
[b
].top
!= pRect
[i
].bottom
) break;
85 if(pRect
[b
].left
< pRect
[a
].left
)
93 } while ( s
< nCount
);
101 * I thought it was okay to have this in DeleteObject but~ Speed. (jt)
105 DeleteRegion( HRGN hRgn
)
109 if ((GdiGetHandleUserData((HGDIOBJ
) hRgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
)) &&
110 ( Rgn_Attr
!= NULL
))
112 PTEB pTeb
= NtCurrentTeb();
113 if (pTeb
->Win32ThreadInfo
!= NULL
)
115 if ((pTeb
->GdiTebBatch
.Offset
+ sizeof(GDIBSOBJECT
)) <= GDIBATCHBUFSIZE
)
117 PGDIBSOBJECT pgO
= (PGDIBSOBJECT
)(&pTeb
->GdiTebBatch
.Buffer
[0] +
118 pTeb
->GdiTebBatch
.Offset
);
119 pgO
->gbHdr
.Cmd
= GdiBCDelRgn
;
120 pgO
->gbHdr
.Size
= sizeof(GDIBSOBJECT
);
121 pgO
->hgdiobj
= (HGDIOBJ
)hRgn
;
123 pTeb
->GdiTebBatch
.Offset
+= sizeof(GDIBSOBJECT
);
124 pTeb
->GdiBatchCount
++;
125 if (pTeb
->GdiBatchCount
>= GDI_BatchLimit
) NtGdiFlush();
130 return NtGdiDeleteObjectApp((HGDIOBJ
) hRgn
);
135 MirrorRgnByWidth(HRGN hRgn
, INT Width
, HRGN
*phRgn
)
137 INT cRgnDSize
, Ret
= 0;
140 cRgnDSize
= NtGdiGetRegionData(hRgn
, 0, NULL
);
144 pRgnData
= LocalAlloc(LMEM_FIXED
, cRgnDSize
* sizeof(LONG
));
147 if ( GetRegionData(hRgn
, cRgnDSize
, pRgnData
) )
151 INT SaveL
= pRgnData
->rdh
.rcBound
.left
;
152 pRgnData
->rdh
.rcBound
.left
= Width
- pRgnData
->rdh
.rcBound
.right
;
153 pRgnData
->rdh
.rcBound
.right
= Width
- SaveL
;
154 if (pRgnData
->rdh
.nCount
> 0)
156 PRECT pRect
= (PRECT
)&pRgnData
->Buffer
;
157 for (i
= 0; i
< pRgnData
->rdh
.nCount
; i
++)
159 SaveL
= pRect
[i
].left
;
160 pRect
[i
].left
= Width
- pRect
[i
].right
;
161 pRect
[i
].right
= Width
- SaveL
;
164 SortRects((PRECT
)&pRgnData
->Buffer
, pRgnData
->rdh
.nCount
);
165 hRgnex
= ExtCreateRegion(NULL
, cRgnDSize
, pRgnData
);
168 if (phRgn
) phRgn
= (HRGN
*)hRgnex
;
171 CombineRgn(hRgn
, hRgnex
, 0, RGN_COPY
);
172 DeleteObject(hRgnex
);
185 MirrorRgnDC(HDC hdc
, HRGN hRgn
, HRGN
*phRgn
)
187 if (!GdiIsHandleValid((HGDIOBJ
) hdc
) ||
188 (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)) return 0;
190 return MirrorRgnByWidth(hRgn
, NtGdiGetDeviceWidth(hdc
), phRgn
);
193 /* FUNCTIONS *****************************************************************/
200 CombineRgn(HRGN hDest
,
205 PRGN_ATTR pRgn_Attr_Dest
= NULL
;
206 PRGN_ATTR pRgn_Attr_Src1
= NULL
;
207 PRGN_ATTR pRgn_Attr_Src2
= NULL
;
211 Ret
= GdiGetHandleUserData((HGDIOBJ
) hDest
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr_Dest
);
212 Ret
= GdiGetHandleUserData((HGDIOBJ
) hSrc1
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr_Src1
);
217 pRgn_Attr_Src1
->Flags
> SIMPLEREGION
)
218 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
220 /* Handle COPY and use only src1. */
221 if ( CombineMode
== RGN_COPY
)
223 switch (pRgn_Attr_Src1
->Flags
)
226 Ret
= SetRectRgn( hDest
, 0, 0, 0, 0);
232 Ret
= SetRectRgn( hDest
,
233 pRgn_Attr_Src1
->Rect
.left
,
234 pRgn_Attr_Src1
->Rect
.top
,
235 pRgn_Attr_Src1
->Rect
.right
,
236 pRgn_Attr_Src1
->Rect
.bottom
);
243 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
247 Ret
= GdiGetHandleUserData((HGDIOBJ
) hSrc2
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr_Src2
);
250 pRgn_Attr_Src2
->Flags
> SIMPLEREGION
)
251 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
254 if ( CombineMode
!= RGN_AND
)
256 if ( CombineMode
<= RGN_AND
)
259 There might be some type of junk in the call, so go K.
260 If this becomes a problem, need to setup parameter check at the top.
262 DPRINT1("Might be junk! CombineMode %d\n",CombineMode
);
263 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
266 if ( CombineMode
> RGN_XOR
) /* Handle DIFF. */
268 if ( CombineMode
!= RGN_DIFF
)
269 { /* Filter check! Well, must be junk?, so go K. */
270 DPRINT1("RGN_COPY was handled! CombineMode %d\n",CombineMode
);
271 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
273 /* Now handle DIFF. */
274 if ( pRgn_Attr_Src1
->Flags
== NULLREGION
)
276 if (SetRectRgn( hDest
, 0, 0, 0, 0))
281 if ( pRgn_Attr_Src2
->Flags
!= NULLREGION
)
283 Complexity
= ComplexityFromRects( &pRgn_Attr_Src1
->Rect
, &pRgn_Attr_Src2
->Rect
);
285 if ( Complexity
!= DIFF_RGN
)
287 if ( Complexity
!= INVERTED_RGN
)
288 /* If same or overlapping and norm just go K. */
289 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
291 if (SetRectRgn( hDest
, 0, 0, 0, 0))
297 else /* Handle OR or XOR. */
299 if ( pRgn_Attr_Src1
->Flags
== NULLREGION
)
301 if ( pRgn_Attr_Src2
->Flags
!= NULLREGION
)
302 { /* Src1 null and not NULL, set from src2. */
303 Ret
= SetRectRgn( hDest
,
304 pRgn_Attr_Src2
->Rect
.left
,
305 pRgn_Attr_Src2
->Rect
.top
,
306 pRgn_Attr_Src2
->Rect
.right
,
307 pRgn_Attr_Src2
->Rect
.bottom
);
313 if (SetRectRgn( hDest
, 0, 0, 0, 0))
317 /* Src1 is not NULL. */
318 if ( pRgn_Attr_Src2
->Flags
!= NULLREGION
)
320 if ( CombineMode
!= RGN_OR
) /* Filter XOR, so go K. */
321 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
323 Complexity
= ComplexityFromRects( &pRgn_Attr_Src1
->Rect
, &pRgn_Attr_Src2
->Rect
);
324 /* If inverted use Src2. */
325 if ( Complexity
== INVERTED_RGN
)
327 Ret
= SetRectRgn( hDest
,
328 pRgn_Attr_Src2
->Rect
.left
,
329 pRgn_Attr_Src2
->Rect
.top
,
330 pRgn_Attr_Src2
->Rect
.right
,
331 pRgn_Attr_Src2
->Rect
.bottom
);
336 /* Not NULL or overlapping or differentiated, go to K. */
337 if ( Complexity
!= SAME_RGN
)
338 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
339 /* If same, just fall through. */
342 Ret
= SetRectRgn( hDest
,
343 pRgn_Attr_Src1
->Rect
.left
,
344 pRgn_Attr_Src1
->Rect
.top
,
345 pRgn_Attr_Src1
->Rect
.right
,
346 pRgn_Attr_Src1
->Rect
.bottom
);
353 if ( pRgn_Attr_Src1
->Flags
!= NULLREGION
&&
354 pRgn_Attr_Src2
->Flags
!= NULLREGION
)
356 Complexity
= ComplexityFromRects( &pRgn_Attr_Src1
->Rect
, &pRgn_Attr_Src2
->Rect
);
358 if ( Complexity
== DIFF_RGN
) /* Differentiated in anyway just NULL rgn. */
360 if (SetRectRgn( hDest
, 0, 0, 0, 0))
365 if ( Complexity
!= INVERTED_RGN
) /* Not inverted and overlapping. */
367 if ( Complexity
!= SAME_RGN
) /* Must be norm and overlapping. */
368 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
369 /* Merge from src2. */
370 Ret
= SetRectRgn( hDest
,
371 pRgn_Attr_Src2
->Rect
.left
,
372 pRgn_Attr_Src2
->Rect
.top
,
373 pRgn_Attr_Src2
->Rect
.right
,
374 pRgn_Attr_Src2
->Rect
.bottom
);
379 /* Inverted so merge from src1. */
380 Ret
= SetRectRgn( hDest
,
381 pRgn_Attr_Src1
->Rect
.left
,
382 pRgn_Attr_Src1
->Rect
.top
,
383 pRgn_Attr_Src1
->Rect
.right
,
384 pRgn_Attr_Src1
->Rect
.bottom
);
391 if (SetRectRgn( hDest
, 0, 0, 0, 0))
395 /* Even on error the flag is set dirty and force server side to redraw. */
396 pRgn_Attr_Dest
->AttrFlags
|= ATTR_RGN_DIRTY
;
405 CreateEllipticRgnIndirect(
409 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
410 return NtGdiCreateEllipticRgn(prc
->left
, prc
->top
, prc
->right
, prc
->bottom
);
419 CreatePolygonRgn( const POINT
* lppt
, int cPoints
, int fnPolyFillMode
)
421 return (HRGN
) NtGdiPolyPolyDraw( (HDC
) fnPolyFillMode
, (PPOINT
) lppt
, (PULONG
) &cPoints
, 1, GdiPolyPolyRgn
);
429 CreatePolyPolygonRgn( const POINT
* lppt
,
430 const INT
* lpPolyCounts
,
434 return (HRGN
) NtGdiPolyPolyDraw( (HDC
) fnPolyFillMode
, (PPOINT
) lppt
, (PULONG
) lpPolyCounts
, (ULONG
) nCount
, GdiPolyPolyRgn
);
442 CreateRectRgn(int x1
, int y1
, int x2
, int y2
)
448 /* Normalize points */
462 /* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/
463 if ( x1
< -(1<<27) ||
468 SetLastError(ERROR_INVALID_PARAMETER
);
472 hrgn
= hGetPEBHandle(hctRegionHandle
, 0);
475 hrgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
480 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
482 DPRINT1("No Attr for Region handle!!!\n");
487 if (( x1
== x2
) || (y1
== y2
))
489 pRgn_Attr
->Flags
= NULLREGION
;
490 pRgn_Attr
->Rect
.left
= pRgn_Attr
->Rect
.top
=
491 pRgn_Attr
->Rect
.right
= pRgn_Attr
->Rect
.bottom
= 0;
495 pRgn_Attr
->Flags
= SIMPLEREGION
;
496 pRgn_Attr
->Rect
.left
= x1
;
497 pRgn_Attr
->Rect
.top
= y1
;
498 pRgn_Attr
->Rect
.right
= x2
;
499 pRgn_Attr
->Rect
.bottom
= y2
;
502 pRgn_Attr
->AttrFlags
= (ATTR_RGN_DIRTY
|ATTR_RGN_VALID
);
512 CreateRectRgnIndirect(
516 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
517 return CreateRectRgn(prc
->left
, prc
->top
, prc
->right
, prc
->bottom
);
526 ExcludeClipRect(IN HDC hdc
, IN INT xLeft
, IN INT yTop
, IN INT xRight
, IN INT yBottom
)
529 // Handle something other than a normal dc object.
530 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
532 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
533 return MFDRV_ExcludeClipRect( hdc
, xLeft
, yTop
, xRight
, yBottom
);
536 PLDC pLDC
= GdiGetLDC(hdc
);
539 if (pLDC
->iType
!= LDC_EMFLDC
|| EMFDRV_ExcludeClipRect( hdc
, xLeft
, yTop
, xRight
, yBottom
))
540 return NtGdiExcludeClipRect(hdc
, xLeft
, yTop
, xRight
, yBottom
);
543 SetLastError(ERROR_INVALID_HANDLE
);
548 return NtGdiExcludeClipRect(hdc
, xLeft
, yTop
, xRight
, yBottom
);
557 CONST XFORM
* lpXform
,
559 CONST RGNDATA
* lpRgnData
564 if ((!lpXform
) && (lpRgnData
->rdh
.nCount
== 1))
566 PRECT pRect
= (PRECT
)&lpRgnData
->Buffer
[0];
567 return CreateRectRgn(pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
569 return NtGdiExtCreateRegion((LPXFORM
) lpXform
, nCount
,(LPRGNDATA
) lpRgnData
);
571 SetLastError(ERROR_INVALID_PARAMETER
);
580 ExtSelectClipRgn( IN HDC hdc
, IN HRGN hrgn
, IN INT iMode
)
586 // Handle something other than a normal dc object.
587 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
589 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
590 return MFDRV_ExtSelectClipRgn( hdc
, );
593 PLDC pLDC
= GdiGetLDC(hdc
);
596 if (pLDC
->iType
!= LDC_EMFLDC
|| EMFDRV_ExtSelectClipRgn( hdc
, ))
597 return NtGdiExtSelectClipRgn(hdc
, );
600 SetLastError(ERROR_INVALID_HANDLE
);
608 if ( GetLayout(hdc
) & LAYOUT_RTL
)
610 if ( MirrorRgnDC(hdc
, hrgn
, &NewRgn
) )
612 if ( NewRgn
) hrgn
= NewRgn
;
617 /* Batch handles RGN_COPY only! */
618 if (iMode
== RGN_COPY
)
622 PRGN_ATTR pRgn_Attr
= NULL
;
624 /* hrgn can be NULL unless the RGN_COPY mode is specified. */
626 GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
);
628 if ( GdiGetHandleUserData((HGDIOBJ
) hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) &pDc_Attr
) &&
631 PGDI_TABLE_ENTRY pEntry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hdc
);
632 PTEB pTeb
= NtCurrentTeb();
634 if ( pTeb
->Win32ThreadInfo
!= NULL
&&
635 pTeb
->GdiTebBatch
.HDC
== hdc
&&
636 !(pDc_Attr
->ulDirty_
& DC_DIBSECTION
) &&
637 !(pEntry
->Flags
& GDI_ENTRY_VALIDATE_VIS
) )
640 (hrgn
&& pRgn_Attr
&& pRgn_Attr
->Flags
<= SIMPLEREGION
) )
642 if ((pTeb
->GdiTebBatch
.Offset
+ sizeof(GDIBSEXTSELCLPRGN
)) <= GDIBATCHBUFSIZE
)
644 PGDIBSEXTSELCLPRGN pgO
= (PGDIBSEXTSELCLPRGN
)(&pTeb
->GdiTebBatch
.Buffer
[0] +
645 pTeb
->GdiTebBatch
.Offset
);
646 pgO
->gbHdr
.Cmd
= GdiBCExtSelClipRgn
;
647 pgO
->gbHdr
.Size
= sizeof(GDIBSEXTSELCLPRGN
);
650 if ( hrgn
&& pRgn_Attr
)
652 Ret
= pRgn_Attr
->Flags
;
654 if ( pDc_Attr
->VisRectRegion
.Rect
.left
>= pRgn_Attr
->Rect
.right
||
655 pDc_Attr
->VisRectRegion
.Rect
.top
>= pRgn_Attr
->Rect
.bottom
||
656 pDc_Attr
->VisRectRegion
.Rect
.right
<= pRgn_Attr
->Rect
.left
||
657 pDc_Attr
->VisRectRegion
.Rect
.bottom
<= pRgn_Attr
->Rect
.top
)
660 pgO
->left
= pRgn_Attr
->Rect
.left
;
661 pgO
->top
= pRgn_Attr
->Rect
.top
;
662 pgO
->right
= pRgn_Attr
->Rect
.right
;
663 pgO
->bottom
= pRgn_Attr
->Rect
.bottom
;
667 Ret
= pDc_Attr
->VisRectRegion
.Flags
;
668 pgO
->fnMode
|= 0x80000000; // Set no hrgn mode.
670 pTeb
->GdiTebBatch
.Offset
+= sizeof(GDIBSEXTSELCLPRGN
);
671 pTeb
->GdiBatchCount
++;
672 if (pTeb
->GdiBatchCount
>= GDI_BatchLimit
) NtGdiFlush();
673 if ( NewRgn
) DeleteObject(NewRgn
);
681 Ret
= NtGdiExtSelectClipRgn(hdc
, hrgn
, iMode
);
683 if ( NewRgn
) DeleteObject(NewRgn
);
698 INT Ret
= NtGdiGetRandomRgn(hdc
, hrgn
, CLIPRGN
);
701 // if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
714 return NtGdiGetRandomRgn(hdc
, hrgn
, METARGN
);
723 GetRegionData(HRGN hrgn
,
732 return NtGdiGetRegionData(hrgn
,nCount
,lpRgnData
);
746 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
))
747 return NtGdiGetRgnBox(hrgn
, prcOut
);
749 if (Rgn_Attr
->Flags
== NULLREGION
)
758 if (Rgn_Attr
->Flags
!= SIMPLEREGION
)
759 return NtGdiGetRgnBox(hrgn
, prcOut
);
760 /* WARNING! prcOut is never checked newbies! */
761 RtlCopyMemory( prcOut
, &Rgn_Attr
->Rect
, sizeof(RECT
));
763 return Rgn_Attr
->Flags
;
771 IntersectClipRect(HDC hdc
,
778 // Handle something other than a normal dc object.
779 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
781 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
782 return MFDRV_IntersectClipRect( hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
785 PLDC pLDC
= GdiGetLDC(hdc
);
788 if (pLDC
->iType
!= LDC_EMFLDC
|| EMFDRV_IntersectClipRect( hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
))
789 return NtGdiIntersectClipRect(hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
792 SetLastError(ERROR_INVALID_HANDLE
);
797 return NtGdiIntersectClipRect(hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
805 MirrorRgn(HWND hwnd
, HRGN hrgn
)
808 GetWindowRect(hwnd
, &Rect
);
809 return MirrorRgnByWidth(hrgn
, Rect
.right
- Rect
.left
, NULL
);
817 OffsetClipRgn(HDC hdc
,
822 // Handle something other than a normal dc object.
823 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
825 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
826 return MFDRV_OffsetClipRgn( hdc
, nXOffset
, nYOffset
);
829 PLDC pLDC
= GdiGetLDC(hdc
);
832 SetLastError(ERROR_INVALID_HANDLE
);
835 if (pLDC
->iType
== LDC_EMFLDC
&& !EMFDRV_OffsetClipRgn( hdc
, nXOffset
, nYOffset
))
837 return NtGdiOffsetClipRgn( hdc
, nXOffset
, nYOffset
);
841 return NtGdiOffsetClipRgn( hdc
, nXOffset
, nYOffset
);
850 OffsetRgn( HRGN hrgn
,
855 int nLeftRect
, nTopRect
, nRightRect
, nBottomRect
;
857 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
858 return NtGdiOffsetRgn(hrgn
,nXOffset
,nYOffset
);
860 if ( pRgn_Attr
->Flags
== NULLREGION
)
861 return pRgn_Attr
->Flags
;
863 if ( pRgn_Attr
->Flags
!= SIMPLEREGION
)
864 return NtGdiOffsetRgn(hrgn
,nXOffset
,nYOffset
);
866 nLeftRect
= pRgn_Attr
->Rect
.left
;
867 nTopRect
= pRgn_Attr
->Rect
.top
;
868 nRightRect
= pRgn_Attr
->Rect
.right
;
869 nBottomRect
= pRgn_Attr
->Rect
.bottom
;
871 if (nLeftRect
< nRightRect
)
873 if (nTopRect
< nBottomRect
)
875 nLeftRect
= nXOffset
+ nLeftRect
;
876 nTopRect
= nYOffset
+ nTopRect
;
877 nRightRect
= nXOffset
+ nRightRect
;
878 nBottomRect
= nYOffset
+ nBottomRect
;
880 /* Check 28 bit limit. Chp 9 Areas, pg 560. */
881 if ( nLeftRect
< -(1<<27) ||
882 nTopRect
< -(1<<27) ||
883 nRightRect
> (1<<27)-1 ||
884 nBottomRect
> (1<<27)-1 )
889 pRgn_Attr
->Rect
.top
= nTopRect
;
890 pRgn_Attr
->Rect
.left
= nLeftRect
;
891 pRgn_Attr
->Rect
.right
= nRightRect
;
892 pRgn_Attr
->Rect
.bottom
= nBottomRect
;
893 pRgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
896 return pRgn_Attr
->Flags
;
904 PtInRegion(IN HRGN hrgn
,
910 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
911 return NtGdiPtInRegion(hrgn
,x
,y
);
913 if ( pRgn_Attr
->Flags
== NULLREGION
)
916 if ( pRgn_Attr
->Flags
!= SIMPLEREGION
)
917 return NtGdiPtInRegion(hrgn
,x
,y
);
919 return INRECT( pRgn_Attr
->Rect
, x
, y
);
927 RectInRegion(HRGN hrgn
,
933 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
934 return NtGdiRectInRegion(hrgn
, (LPRECT
) prcl
);
936 if ( pRgn_Attr
->Flags
== NULLREGION
)
939 if ( pRgn_Attr
->Flags
!= SIMPLEREGION
)
940 return NtGdiRectInRegion(hrgn
, (LPRECT
) prcl
);
942 /* swap the coordinates to make right >= left and bottom >= top */
943 /* (region building rectangles are normalized the same way) */
944 if ( prcl
->top
> prcl
->bottom
)
946 rc
.top
= prcl
->bottom
;
947 rc
.bottom
= prcl
->top
;
952 rc
.bottom
= prcl
->bottom
;
954 if ( prcl
->right
< prcl
->left
)
956 rc
.right
= prcl
->left
;
957 rc
.left
= prcl
->right
;
961 rc
.right
= prcl
->right
;
962 rc
.left
= prcl
->left
;
965 if ( ComplexityFromRects( &pRgn_Attr
->Rect
, &rc
) != DIFF_RGN
)
980 return ExtSelectClipRgn(hdc
, hrgn
, RGN_COPY
);
988 SetRectRgn(HRGN hrgn
,
996 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
))
997 return NtGdiSetRectRgn(hrgn
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
999 if ((nLeftRect
== nRightRect
) || (nTopRect
== nBottomRect
))
1001 Rgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
1002 Rgn_Attr
->Flags
= NULLREGION
;
1003 Rgn_Attr
->Rect
.left
= Rgn_Attr
->Rect
.top
=
1004 Rgn_Attr
->Rect
.right
= Rgn_Attr
->Rect
.bottom
= 0;
1008 Rgn_Attr
->Rect
.left
= nLeftRect
;
1009 Rgn_Attr
->Rect
.top
= nTopRect
;
1010 Rgn_Attr
->Rect
.right
= nRightRect
;
1011 Rgn_Attr
->Rect
.bottom
= nBottomRect
;
1013 if(nLeftRect
> nRightRect
)
1015 Rgn_Attr
->Rect
.left
= nRightRect
;
1016 Rgn_Attr
->Rect
.right
= nLeftRect
;
1018 if(nTopRect
> nBottomRect
)
1020 Rgn_Attr
->Rect
.top
= nBottomRect
;
1021 Rgn_Attr
->Rect
.bottom
= nTopRect
;
1024 Rgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
1025 Rgn_Attr
->Flags
= SIMPLEREGION
;
1034 SetMetaRgn( HDC hDC
)
1036 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_DC
)
1037 return NtGdiSetMetaRgn(hDC
);
1039 PLDC pLDC
= GdiGetLDC(hDC
);
1040 if ( pLDC
&& GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_METADC
)
1042 if (pLDC
->iType
== LDC_EMFLDC
|| EMFDRV_SetMetaRgn(hDC
))
1044 return NtGdiSetMetaRgn(hDC
);
1047 SetLastError(ERROR_INVALID_HANDLE
);