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
)
103 * I thought it was okay to have this in DeleteObject but~ Speed. (jt)
113 if ((GdiGetHandleUserData(hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
)) &&
114 ( Rgn_Attr
!= NULL
))
118 pgO
= GdiAllocBatchCommand(NULL
, GdiBCDelRgn
);
126 return NtGdiDeleteObjectApp(hrgn
);
136 INT cRgnDSize
, Ret
= 0;
139 cRgnDSize
= NtGdiGetRegionData(hrgn
, 0, NULL
);
143 pRgnData
= LocalAlloc(LMEM_FIXED
, cRgnDSize
* sizeof(LONG
));
146 if ( GetRegionData(hrgn
, cRgnDSize
, pRgnData
) )
150 INT SaveL
= pRgnData
->rdh
.rcBound
.left
;
151 pRgnData
->rdh
.rcBound
.left
= Width
- pRgnData
->rdh
.rcBound
.right
;
152 pRgnData
->rdh
.rcBound
.right
= Width
- SaveL
;
153 if (pRgnData
->rdh
.nCount
> 0)
155 PRECT pRect
= (PRECT
)&pRgnData
->Buffer
;
156 for (i
= 0; i
< pRgnData
->rdh
.nCount
; i
++)
158 SaveL
= pRect
[i
].left
;
159 pRect
[i
].left
= Width
- pRect
[i
].right
;
160 pRect
[i
].right
= Width
- SaveL
;
163 SortRects((PRECT
)&pRgnData
->Buffer
, pRgnData
->rdh
.nCount
);
164 hRgnex
= ExtCreateRegion(NULL
, cRgnDSize
, pRgnData
);
167 if (phrgn
) phrgn
= (HRGN
*)hRgnex
;
170 CombineRgn(hrgn
, hRgnex
, 0, RGN_COPY
);
171 DeleteObject(hRgnex
);
189 if (!GdiValidateHandle((HGDIOBJ
) hdc
) ||
190 (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
))
193 return MirrorRgnByWidth(hrgn
, NtGdiGetDeviceWidth(hdc
), phrn
);
196 /* FUNCTIONS *****************************************************************/
201 _Inout_ PRGN_ATTR prgnattr
)
203 prgnattr
->iComplexity
= NULLREGION
;
204 prgnattr
->AttrFlags
|= ATTR_RGN_DIRTY
;
211 _Inout_ PRGN_ATTR prgnattr
,
217 ASSERT(xLeft
<= xRight
);
218 ASSERT(yTop
<= yBottom
);
220 if ((xLeft
== xRight
) || (yTop
== yBottom
))
221 return IntSetNullRgn(prgnattr
);
223 prgnattr
->iComplexity
= SIMPLEREGION
;
224 prgnattr
->Rect
.left
= xLeft
;
225 prgnattr
->Rect
.top
= yTop
;
226 prgnattr
->Rect
.right
= xRight
;
227 prgnattr
->Rect
.bottom
= yBottom
;
228 prgnattr
->AttrFlags
|= ATTR_RGN_DIRTY
;
241 _In_ INT iCombineMode
)
243 PRGN_ATTR prngattrDest
= NULL
;
244 PRGN_ATTR prngattrSrc1
= NULL
;
245 PRGN_ATTR prngattrSrc2
= NULL
;
248 /* Get the region attribute for dest and source 1 */
249 prngattrDest
= GdiGetRgnAttr(hrgnDest
);
250 prngattrSrc1
= GdiGetRgnAttr(hrgnSrc1
);
252 /* If that failed or if the source 1 region is complex, go to win32k */
253 if ((prngattrDest
== NULL
) || (prngattrSrc1
== NULL
) ||
254 (prngattrSrc1
->iComplexity
> SIMPLEREGION
))
256 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
259 /* Handle RGN_COPY first, it needs only hrgnSrc1 */
260 if (iCombineMode
== RGN_COPY
)
262 /* Check if the source region is a NULLREGION */
263 if (prngattrSrc1
->iComplexity
== NULLREGION
)
265 /* The dest region is a NULLREGION, too */
266 return IntSetNullRgn(prngattrDest
);
269 /* We already know that the source region cannot be complex, so
270 create a rect region from the bounds of the source rect */
271 return IntSetRectRgn(prngattrDest
,
272 prngattrSrc1
->Rect
.left
,
273 prngattrSrc1
->Rect
.top
,
274 prngattrSrc1
->Rect
.right
,
275 prngattrSrc1
->Rect
.bottom
);
278 /* For all other operations we need hrgnSrc2 */
279 prngattrSrc2
= GdiGetRgnAttr(hrgnSrc2
);
281 /* If we got no attribute or the region is complex, go to win32k */
282 if ((prngattrSrc2
== NULL
) || (prngattrSrc2
->iComplexity
> SIMPLEREGION
))
284 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
288 if (iCombineMode
== RGN_AND
)
290 /* Check if either of the regions is a NULLREGION */
291 if ((prngattrSrc1
->iComplexity
== NULLREGION
) ||
292 (prngattrSrc2
->iComplexity
== NULLREGION
))
294 /* Result is also a NULLREGION */
295 return IntSetNullRgn(prngattrDest
);
298 /* Get the intersection of the 2 rects */
299 if (!IntersectRect(&rcTemp
, &prngattrSrc1
->Rect
, &prngattrSrc2
->Rect
))
301 /* The rects do not intersect, result is a NULLREGION */
302 return IntSetNullRgn(prngattrDest
);
305 /* Use the intersection of the rects */
306 return IntSetRectRgn(prngattrDest
,
313 /* Handle RGN_DIFF */
314 if (iCombineMode
== RGN_DIFF
)
316 /* Check if source 1 is a NULLREGION */
317 if (prngattrSrc1
->iComplexity
== NULLREGION
)
319 /* The result is a NULLREGION as well */
320 return IntSetNullRgn(prngattrDest
);
323 /* Get the intersection of the 2 rects */
324 if ((prngattrSrc2
->iComplexity
== NULLREGION
) ||
325 !IntersectRect(&rcTemp
, &prngattrSrc1
->Rect
, &prngattrSrc2
->Rect
))
327 /* The rects do not intersect, dest equals source 1 */
328 return IntSetRectRgn(prngattrDest
,
329 prngattrSrc1
->Rect
.left
,
330 prngattrSrc1
->Rect
.top
,
331 prngattrSrc1
->Rect
.right
,
332 prngattrSrc1
->Rect
.bottom
);
335 /* We need to check is whether we can subtract the rects. For that
336 we call SubtractRect, which will give us the bounding box of the
337 subtraction. The function returns FALSE if the resulting rect is
339 if (!SubtractRect(&rcTemp
, &prngattrSrc1
->Rect
, &rcTemp
))
341 /* The result is a NULLREGION */
342 return IntSetNullRgn(prngattrDest
);
345 /* Now check if the result of SubtractRect matches the source 1 rect.
346 Since we already know that the rects intersect, the result can
347 only match the source 1 rect, if it could not be "cut" on either
348 side, but the overlapping was on a corner, so the new bounding box
349 equals the previous rect */
350 if (!EqualRect(&rcTemp
, &prngattrSrc1
->Rect
))
352 /* We got a properly subtracted rect, so use it. */
353 return IntSetRectRgn(prngattrDest
,
360 /* The result would be a complex region, go to win32k */
361 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
364 /* Handle OR and XOR */
365 if ((iCombineMode
== RGN_OR
) || (iCombineMode
== RGN_XOR
))
367 /* Check if source 1 is a NULLREGION */
368 if (prngattrSrc1
->iComplexity
== NULLREGION
)
370 /* Check if source 2 is also a NULLREGION */
371 if (prngattrSrc2
->iComplexity
== NULLREGION
)
373 /* Both are NULLREGIONs, result is also a NULLREGION */
374 return IntSetNullRgn(prngattrDest
);
377 /* The result is equal to source 2 */
378 return IntSetRectRgn(prngattrDest
,
379 prngattrSrc2
->Rect
.left
,
380 prngattrSrc2
->Rect
.top
,
381 prngattrSrc2
->Rect
.right
,
382 prngattrSrc2
->Rect
.bottom
);
385 /* Check if only source 2 is a NULLREGION */
386 if (prngattrSrc2
->iComplexity
== NULLREGION
)
388 /* The result is equal to source 1 */
389 return IntSetRectRgn(prngattrDest
,
390 prngattrSrc1
->Rect
.left
,
391 prngattrSrc1
->Rect
.top
,
392 prngattrSrc1
->Rect
.right
,
393 prngattrSrc1
->Rect
.bottom
);
396 /* Do the rects have the same x extent */
397 if ((prngattrSrc1
->Rect
.left
== prngattrSrc2
->Rect
.left
) &&
398 (prngattrSrc1
->Rect
.right
== prngattrSrc2
->Rect
.right
))
400 /* Do the rects also have the same y extent */
401 if ((prngattrSrc1
->Rect
.top
== prngattrSrc2
->Rect
.top
) &&
402 (prngattrSrc1
->Rect
.bottom
== prngattrSrc2
->Rect
.bottom
))
404 /* Rects are equal, if this is RGN_OR, the result is source 1 */
405 if (iCombineMode
== RGN_OR
)
407 /* The result is equal to source 1 */
408 return IntSetRectRgn(prngattrDest
,
409 prngattrSrc1
->Rect
.left
,
410 prngattrSrc1
->Rect
.top
,
411 prngattrSrc1
->Rect
.right
,
412 prngattrSrc1
->Rect
.bottom
);
416 /* XORing with itself yields an empty region */
417 return IntSetNullRgn(prngattrDest
);
421 /* Check if the rects are disjoint */
422 if ((prngattrSrc2
->Rect
.bottom
< prngattrSrc1
->Rect
.top
) ||
423 (prngattrSrc2
->Rect
.top
> prngattrSrc1
->Rect
.bottom
))
425 /* The result would be a complex region, go to win32k */
426 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
429 /* Check if this is OR */
430 if (iCombineMode
== RGN_OR
)
432 /* Use the maximum extent of both rects combined */
433 return IntSetRectRgn(prngattrDest
,
434 prngattrSrc1
->Rect
.left
,
435 min(prngattrSrc1
->Rect
.top
, prngattrSrc2
->Rect
.top
),
436 prngattrSrc1
->Rect
.right
,
437 max(prngattrSrc1
->Rect
.bottom
, prngattrSrc2
->Rect
.bottom
));
440 /* Check if the rects are adjacent */
441 if (prngattrSrc2
->Rect
.bottom
== prngattrSrc1
->Rect
.top
)
443 /* The result is the combined rects */
444 return IntSetRectRgn(prngattrDest
,
445 prngattrSrc1
->Rect
.left
,
446 prngattrSrc2
->Rect
.top
,
447 prngattrSrc1
->Rect
.right
,
448 prngattrSrc1
->Rect
.bottom
);
450 else if (prngattrSrc2
->Rect
.top
== prngattrSrc1
->Rect
.bottom
)
452 /* The result is the combined rects */
453 return IntSetRectRgn(prngattrDest
,
454 prngattrSrc1
->Rect
.left
,
455 prngattrSrc1
->Rect
.top
,
456 prngattrSrc1
->Rect
.right
,
457 prngattrSrc2
->Rect
.bottom
);
460 /* When we are here, this is RGN_XOR and the rects overlap */
461 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
464 /* Do the rects have the same y extent */
465 if ((prngattrSrc1
->Rect
.top
== prngattrSrc2
->Rect
.top
) &&
466 (prngattrSrc1
->Rect
.bottom
== prngattrSrc2
->Rect
.bottom
))
468 /* Check if the rects are disjoint */
469 if ((prngattrSrc2
->Rect
.right
< prngattrSrc1
->Rect
.left
) ||
470 (prngattrSrc2
->Rect
.left
> prngattrSrc1
->Rect
.right
))
472 /* The result would be a complex region, go to win32k */
473 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
476 /* Check if this is OR */
477 if (iCombineMode
== RGN_OR
)
479 /* Use the maximum extent of both rects combined */
480 return IntSetRectRgn(prngattrDest
,
481 min(prngattrSrc1
->Rect
.left
, prngattrSrc2
->Rect
.left
),
482 prngattrSrc1
->Rect
.top
,
483 max(prngattrSrc1
->Rect
.right
, prngattrSrc2
->Rect
.right
),
484 prngattrSrc1
->Rect
.bottom
);
487 /* Check if the rects are adjacent */
488 if (prngattrSrc2
->Rect
.right
== prngattrSrc1
->Rect
.left
)
490 /* The result is the combined rects */
491 return IntSetRectRgn(prngattrDest
,
492 prngattrSrc2
->Rect
.left
,
493 prngattrSrc1
->Rect
.top
,
494 prngattrSrc1
->Rect
.right
,
495 prngattrSrc1
->Rect
.bottom
);
497 else if (prngattrSrc2
->Rect
.left
== prngattrSrc1
->Rect
.right
)
499 /* The result is the combined rects */
500 return IntSetRectRgn(prngattrDest
,
501 prngattrSrc1
->Rect
.left
,
502 prngattrSrc1
->Rect
.top
,
503 prngattrSrc2
->Rect
.right
,
504 prngattrSrc1
->Rect
.bottom
);
507 /* When we are here, this is RGN_XOR and the rects overlap */
508 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
511 /* Last case: RGN_OR and one rect is completely within the other */
512 if (iCombineMode
== RGN_OR
)
514 /* Check if rect 1 can contain rect 2 */
515 if (prngattrSrc1
->Rect
.left
<= prngattrSrc2
->Rect
.left
)
517 /* rect 1 might be the outer one, check of that is true */
518 if ((prngattrSrc1
->Rect
.right
>= prngattrSrc2
->Rect
.right
) &&
519 (prngattrSrc1
->Rect
.top
<= prngattrSrc2
->Rect
.top
) &&
520 (prngattrSrc1
->Rect
.bottom
>= prngattrSrc2
->Rect
.bottom
))
522 /* Rect 1 contains rect 2, use it */
523 return IntSetRectRgn(prngattrDest
,
524 prngattrSrc1
->Rect
.left
,
525 prngattrSrc1
->Rect
.top
,
526 prngattrSrc1
->Rect
.right
,
527 prngattrSrc1
->Rect
.bottom
);
532 /* rect 2 might be the outer one, check of that is true */
533 if ((prngattrSrc2
->Rect
.right
>= prngattrSrc1
->Rect
.right
) &&
534 (prngattrSrc2
->Rect
.top
<= prngattrSrc1
->Rect
.top
) &&
535 (prngattrSrc2
->Rect
.bottom
>= prngattrSrc1
->Rect
.bottom
))
537 /* Rect 2 contains rect 1, use it */
538 return IntSetRectRgn(prngattrDest
,
539 prngattrSrc2
->Rect
.left
,
540 prngattrSrc2
->Rect
.top
,
541 prngattrSrc2
->Rect
.right
,
542 prngattrSrc2
->Rect
.bottom
);
547 /* We couldn't handle the operation, go to win32k */
548 return NtGdiCombineRgn(hrgnDest
, hrgnSrc1
, hrgnSrc2
, iCombineMode
);
551 DPRINT1("Invalid iCombineMode %d\n", iCombineMode
);
552 SetLastError(ERROR_INVALID_PARAMETER
);
562 CreateEllipticRgnIndirect(
566 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
567 return NtGdiCreateEllipticRgn(prc
->left
, prc
->top
, prc
->right
, prc
->bottom
);
576 CreatePolygonRgn( const POINT
* lppt
, int cPoints
, int fnPolyFillMode
)
578 return (HRGN
) NtGdiPolyPolyDraw( (HDC
) fnPolyFillMode
, (PPOINT
) lppt
, (PULONG
) &cPoints
, 1, GdiPolyPolyRgn
);
586 CreatePolyPolygonRgn( const POINT
* lppt
,
587 const INT
* lpPolyCounts
,
591 return (HRGN
) NtGdiPolyPolyDraw( (HDC
) fnPolyFillMode
, (PPOINT
) lppt
, (PULONG
) lpPolyCounts
, (ULONG
) nCount
, GdiPolyPolyRgn
);
599 CreateRectRgn(int x1
, int y1
, int x2
, int y2
)
606 //// Remove when Brush/Pen/Rgn Attr is ready!
607 return NtGdiCreateRectRgn(x1
,y1
,x2
,y2
);
610 /* Normalize points */
624 /* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/
625 if ( x1
< -(1<<27) ||
630 SetLastError(ERROR_INVALID_PARAMETER
);
634 hrgn
= hGetPEBHandle(hctRegionHandle
, 0);
637 hrgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
642 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
644 DPRINT1("No Attr for Region handle!!!\n");
649 if (( x1
== x2
) || (y1
== y2
))
651 pRgn_Attr
->iComplexity
= NULLREGION
;
652 pRgn_Attr
->Rect
.left
= pRgn_Attr
->Rect
.top
=
653 pRgn_Attr
->Rect
.right
= pRgn_Attr
->Rect
.bottom
= 0;
657 pRgn_Attr
->iComplexity
= SIMPLEREGION
;
658 pRgn_Attr
->Rect
.left
= x1
;
659 pRgn_Attr
->Rect
.top
= y1
;
660 pRgn_Attr
->Rect
.right
= x2
;
661 pRgn_Attr
->Rect
.bottom
= y2
;
664 pRgn_Attr
->AttrFlags
= (ATTR_RGN_DIRTY
|ATTR_RGN_VALID
);
674 CreateRectRgnIndirect(
678 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
679 return CreateRectRgn(prc
->left
, prc
->top
, prc
->right
, prc
->bottom
);
695 HANDLE_METADC(INT
, ExcludeClipRect
, ERROR
, hdc
, xLeft
, yTop
, xRight
, yBottom
);
697 return NtGdiExcludeClipRect(hdc
, xLeft
, yTop
, xRight
, yBottom
);
706 CONST XFORM
* lpXform
,
708 CONST RGNDATA
* lpRgnData
713 if ((!lpXform
) && (lpRgnData
->rdh
.nCount
== 1))
715 PRECT pRect
= (PRECT
)&lpRgnData
->Buffer
[0];
716 return CreateRectRgn(pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
718 return NtGdiExtCreateRegion((LPXFORM
) lpXform
, nCount
,(LPRGNDATA
) lpRgnData
);
720 SetLastError(ERROR_INVALID_PARAMETER
);
737 HANDLE_METADC(INT
, ExtSelectClipRgn
, 0, hdc
, hrgn
, iMode
);
742 if ( GetLayout(hdc
) & LAYOUT_RTL
)
744 if ( MirrorRgnDC(hdc
, hrgn
, &NewRgn
) )
746 if ( NewRgn
) hrgn
= NewRgn
;
751 /* Batch handles RGN_COPY only! */
752 if (iMode
== RGN_COPY
)
756 PRGN_ATTR pRgn_Attr
= NULL
;
758 /* hrgn can be NULL unless the RGN_COPY mode is specified. */
760 GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
);
762 if ( GdiGetHandleUserData((HGDIOBJ
) hdc
, GDI_OBJECT_TYPE_DC
, (PVOID
) &pDc_Attr
) &&
765 PGDI_TABLE_ENTRY pEntry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hdc
);
766 PTEB pTeb
= NtCurrentTeb();
768 if ( pTeb
->Win32ThreadInfo
!= NULL
&&
769 pTeb
->GdiTebBatch
.HDC
== hdc
&&
770 !(pDc_Attr
->ulDirty_
& DC_DIBSECTION
) &&
771 !(pEntry
->Flags
& GDI_ENTRY_VALIDATE_VIS
) )
774 (hrgn
&& pRgn_Attr
&& pRgn_Attr
->iComplexity
<= SIMPLEREGION
) )
776 if ((pTeb
->GdiTebBatch
.Offset
+ sizeof(GDIBSEXTSELCLPRGN
)) <= GDIBATCHBUFSIZE
)
778 // FIXME: This is broken, use GdiAllocBatchCommand!
779 PGDIBSEXTSELCLPRGN pgO
= (PGDIBSEXTSELCLPRGN
)(&pTeb
->GdiTebBatch
.Buffer
[0] +
780 pTeb
->GdiTebBatch
.Offset
);
781 pgO
->gbHdr
.Cmd
= GdiBCExtSelClipRgn
;
782 pgO
->gbHdr
.Size
= sizeof(GDIBSEXTSELCLPRGN
);
785 if ( hrgn
&& pRgn_Attr
)
787 Ret
= pRgn_Attr
->iComplexity
;
789 if ( pDc_Attr
->VisRectRegion
.Rect
.left
>= pRgn_Attr
->Rect
.right
||
790 pDc_Attr
->VisRectRegion
.Rect
.top
>= pRgn_Attr
->Rect
.bottom
||
791 pDc_Attr
->VisRectRegion
.Rect
.right
<= pRgn_Attr
->Rect
.left
||
792 pDc_Attr
->VisRectRegion
.Rect
.bottom
<= pRgn_Attr
->Rect
.top
)
795 pgO
->left
= pRgn_Attr
->Rect
.left
;
796 pgO
->top
= pRgn_Attr
->Rect
.top
;
797 pgO
->right
= pRgn_Attr
->Rect
.right
;
798 pgO
->bottom
= pRgn_Attr
->Rect
.bottom
;
802 Ret
= pDc_Attr
->VisRectRegion
.Flags
;
803 pgO
->fnMode
|= 0x80000000; // Set no hrgn mode.
805 pTeb
->GdiTebBatch
.Offset
+= sizeof(GDIBSEXTSELCLPRGN
);
806 pTeb
->GdiBatchCount
++;
807 if (pTeb
->GdiBatchCount
>= GDI_BatchLimit
) NtGdiFlush();
808 if ( NewRgn
) DeleteObject(NewRgn
);
816 Ret
= NtGdiExtSelectClipRgn(hdc
, hrgn
, iMode
);
818 if ( NewRgn
) DeleteObject(NewRgn
);
835 /* Check if DC handle is valid */
836 if (!GdiGetDcAttr(hdc
))
838 /* Last error code differs from what NtGdiGetRandomRgn returns */
839 SetLastError(ERROR_INVALID_PARAMETER
);
843 Ret
= NtGdiGetRandomRgn(hdc
, hrgn
, CLIPRGN
);
847 // if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
860 return NtGdiGetRandomRgn(hdc
, hrgn
, METARGN
);
869 GetRegionData(HRGN hrgn
,
878 return NtGdiGetRegionData(hrgn
,nCount
,lpRgnData
);
892 //if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
893 return NtGdiGetRgnBox(hrgn
, prcOut
);
895 if (Rgn_Attr
->iComplexity
== NULLREGION
)
904 if (Rgn_Attr
->iComplexity
!= SIMPLEREGION
)
905 return NtGdiGetRgnBox(hrgn
, prcOut
);
906 /* WARNING! prcOut is never checked newbies! */
907 RtlCopyMemory( prcOut
, &Rgn_Attr
->Rect
, sizeof(RECT
));
909 return Rgn_Attr
->iComplexity
;
924 HANDLE_METADC(INT
, IntersectClipRect
, ERROR
, hdc
, nLeft
, nTop
, nRight
, nBottom
);
925 return NtGdiIntersectClipRect(hdc
, nLeft
, nTop
, nRight
, nBottom
);
933 MirrorRgn(HWND hwnd
, HRGN hrgn
)
936 GetWindowRect(hwnd
, &Rect
);
937 return MirrorRgnByWidth(hrgn
, Rect
.right
- Rect
.left
, NULL
);
950 HANDLE_METADC(INT
, OffsetClipRgn
, ERROR
, hdc
, nXOffset
, nYOffset
);
951 return NtGdiOffsetClipRgn(hdc
, nXOffset
, nYOffset
);
960 OffsetRgn( HRGN hrgn
,
965 int nLeftRect
, nTopRect
, nRightRect
, nBottomRect
;
968 // if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
969 return NtGdiOffsetRgn(hrgn
,nXOffset
,nYOffset
);
971 if ( pRgn_Attr
->iComplexity
== NULLREGION
)
972 return pRgn_Attr
->iComplexity
;
974 if ( pRgn_Attr
->iComplexity
!= SIMPLEREGION
)
975 return NtGdiOffsetRgn(hrgn
,nXOffset
,nYOffset
);
977 nLeftRect
= pRgn_Attr
->Rect
.left
;
978 nTopRect
= pRgn_Attr
->Rect
.top
;
979 nRightRect
= pRgn_Attr
->Rect
.right
;
980 nBottomRect
= pRgn_Attr
->Rect
.bottom
;
982 if (nLeftRect
< nRightRect
)
984 if (nTopRect
< nBottomRect
)
986 nLeftRect
= nXOffset
+ nLeftRect
;
987 nTopRect
= nYOffset
+ nTopRect
;
988 nRightRect
= nXOffset
+ nRightRect
;
989 nBottomRect
= nYOffset
+ nBottomRect
;
991 /* Check 28 bit limit. Chp 9 Areas, pg 560. */
992 if ( nLeftRect
< -(1<<27) ||
993 nTopRect
< -(1<<27) ||
994 nRightRect
> (1<<27)-1 ||
995 nBottomRect
> (1<<27)-1 )
1000 pRgn_Attr
->Rect
.top
= nTopRect
;
1001 pRgn_Attr
->Rect
.left
= nLeftRect
;
1002 pRgn_Attr
->Rect
.right
= nRightRect
;
1003 pRgn_Attr
->Rect
.bottom
= nBottomRect
;
1004 pRgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
1007 return pRgn_Attr
->iComplexity
;
1015 PtInRegion(IN HRGN hrgn
,
1019 PRGN_ATTR pRgn_Attr
;
1022 //if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
1023 return NtGdiPtInRegion(hrgn
,x
,y
);
1025 if ( pRgn_Attr
->iComplexity
== NULLREGION
)
1028 if ( pRgn_Attr
->iComplexity
!= SIMPLEREGION
)
1029 return NtGdiPtInRegion(hrgn
,x
,y
);
1031 return INRECT( pRgn_Attr
->Rect
, x
, y
);
1039 RectInRegion(HRGN hrgn
,
1042 PRGN_ATTR pRgn_Attr
;
1046 //if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
1047 return NtGdiRectInRegion(hrgn
, (LPRECT
) prcl
);
1049 if ( pRgn_Attr
->iComplexity
== NULLREGION
)
1052 if ( pRgn_Attr
->iComplexity
!= SIMPLEREGION
)
1053 return NtGdiRectInRegion(hrgn
, (LPRECT
) prcl
);
1055 /* swap the coordinates to make right >= left and bottom >= top */
1056 /* (region building rectangles are normalized the same way) */
1057 if ( prcl
->top
> prcl
->bottom
)
1059 rc
.top
= prcl
->bottom
;
1060 rc
.bottom
= prcl
->top
;
1065 rc
.bottom
= prcl
->bottom
;
1067 if ( prcl
->right
< prcl
->left
)
1069 rc
.right
= prcl
->left
;
1070 rc
.left
= prcl
->right
;
1074 rc
.right
= prcl
->right
;
1075 rc
.left
= prcl
->left
;
1078 if ( ComplexityFromRects( &pRgn_Attr
->Rect
, &rc
) != DIFF_RGN
)
1093 return ExtSelectClipRgn(hdc
, hrgn
, RGN_COPY
);
1110 /* Try to get the region attribute */
1111 prngattr
= GdiGetRgnAttr(hrgn
);
1112 if (prngattr
== NULL
)
1114 return NtGdiSetRectRgn(hrgn
, xLeft
, yTop
, xRight
, yBottom
);
1117 /* check for NULL region */
1118 if ((xLeft
== xRight
) || (yTop
== yBottom
))
1120 IntSetNullRgn(prngattr
);
1126 prngattr
->Rect
.left
= xRight
;
1127 prngattr
->Rect
.right
= xLeft
;
1131 prngattr
->Rect
.left
= xLeft
;
1132 prngattr
->Rect
.right
= xRight
;
1137 prngattr
->Rect
.top
= yBottom
;
1138 prngattr
->Rect
.bottom
= yTop
;
1142 prngattr
->Rect
.top
= yTop
;
1143 prngattr
->Rect
.bottom
= yBottom
;
1146 prngattr
->AttrFlags
|= ATTR_RGN_DIRTY
;
1147 prngattr
->iComplexity
= SIMPLEREGION
;
1159 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_DC
)
1160 return NtGdiSetMetaRgn(hDC
);
1162 PLDC pLDC
= GdiGetLDC(hDC
);
1163 if ( pLDC
&& GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_METADC
)
1165 if (pLDC
->iType
== LDC_EMFLDC
|| EMFDRV_SetMetaRgn(hDC
))
1167 return NtGdiSetMetaRgn(hDC
);
1170 SetLastError(ERROR_INVALID_HANDLE
);