3 #define INRECT(r, x, y) \
4 ( ( ((r).right > x)) && \
5 ( ((r).left <= x)) && \
6 ( ((r).bottom > y)) && \
12 ComplexityFromRects( PRECT prc1
, PRECT prc2
)
14 if ( prc2
->left
>= prc1
->left
)
16 if ( ( prc1
->right
>= prc2
->right
) &&
17 ( prc1
->top
<= prc2
->top
) &&
18 ( prc1
->bottom
<= prc2
->bottom
) )
21 if ( prc2
->left
> prc1
->left
)
23 if ( ( prc1
->left
>= prc2
->right
) ||
24 ( prc1
->right
<= prc2
->left
) ||
25 ( prc1
->top
>= prc2
->bottom
) ||
26 ( prc1
->bottom
<= prc2
->top
) )
31 if ( ( prc2
->right
< prc1
->right
) ||
32 ( prc2
->top
> prc1
->top
) ||
33 ( prc2
->bottom
< prc1
->bottom
) )
35 if ( ( prc1
->left
>= prc2
->right
) ||
36 ( prc1
->right
<= prc2
->left
) ||
37 ( prc1
->top
>= prc2
->bottom
) ||
38 ( prc1
->bottom
<= prc2
->top
) )
52 SortRects(PRECT pRect
, INT nCount
)
54 INT i
= 0, a
= 0, b
= 0, c
, s
;
59 i
= 1; // set index point
60 c
= nCount
; // set inverse count
63 s
= i
; // set sort count
70 if(pRect
[b
].top
!= pRect
[i
].bottom
) break;
71 if(pRect
[b
].left
< pRect
[a
].left
)
79 } while ( s
< nCount
);
87 * I thought it was okay to have this in DeleteObject but~ Speed. (jt)
91 DeleteRegion( HRGN hRgn
)
96 if ((GdiGetHandleUserData((HGDIOBJ
) hRgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
)) &&
99 PTEB pTeb
= NtCurrentTeb();
100 if (pTeb
->Win32ThreadInfo
!= NULL
)
102 if ((pTeb
->GdiTebBatch
.Offset
+ sizeof(GDIBSOBJECT
)) <= GDIBATCHBUFSIZE
)
104 PGDIBSOBJECT pgO
= (PGDIBSOBJECT
)(&pTeb
->GdiTebBatch
.Buffer
[0] +
105 pTeb
->GdiTebBatch
.Offset
);
106 pgO
->gbHdr
.Cmd
= GdiBCDelRgn
;
107 pgO
->gbHdr
.Size
= sizeof(GDIBSOBJECT
);
108 pgO
->hgdiobj
= (HGDIOBJ
)hRgn
;
110 pTeb
->GdiTebBatch
.Offset
+= sizeof(GDIBSOBJECT
);
111 pTeb
->GdiBatchCount
++;
112 if (pTeb
->GdiBatchCount
>= GDI_BatchLimit
) NtGdiFlush();
118 return NtGdiDeleteObjectApp((HGDIOBJ
) hRgn
);
123 MirrorRgnByWidth(HRGN hRgn
, INT Width
, HRGN
*phRgn
)
125 INT cRgnDSize
, Ret
= 0;
128 cRgnDSize
= NtGdiGetRegionData(hRgn
, 0, NULL
);
132 pRgnData
= LocalAlloc(LMEM_FIXED
, cRgnDSize
* sizeof(LONG
));
135 if ( GetRegionData(hRgn
, cRgnDSize
, pRgnData
) )
139 INT SaveL
= pRgnData
->rdh
.rcBound
.left
;
140 pRgnData
->rdh
.rcBound
.left
= Width
- pRgnData
->rdh
.rcBound
.right
;
141 pRgnData
->rdh
.rcBound
.right
= Width
- SaveL
;
142 if (pRgnData
->rdh
.nCount
> 0)
144 PRECT pRect
= (PRECT
)&pRgnData
->Buffer
;
145 for (i
= 0; i
< pRgnData
->rdh
.nCount
; i
++)
147 SaveL
= pRect
[i
].left
;
148 pRect
[i
].left
= Width
- pRect
[i
].right
;
149 pRect
[i
].right
= Width
- SaveL
;
152 SortRects((PRECT
)&pRgnData
->Buffer
, pRgnData
->rdh
.nCount
);
153 hRgnex
= ExtCreateRegion(NULL
, cRgnDSize
, pRgnData
);
156 if (phRgn
) phRgn
= (HRGN
*)hRgnex
;
159 CombineRgn(hRgn
, hRgnex
, 0, RGN_COPY
);
160 DeleteObject(hRgnex
);
173 MirrorRgnDC(HDC hdc
, HRGN hRgn
, HRGN
*phRgn
)
175 if (!GdiIsHandleValid((HGDIOBJ
) hdc
) ||
176 (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)) return 0;
178 return MirrorRgnByWidth(hRgn
, NtGdiGetDeviceWidth(hdc
), phRgn
);
181 /* FUNCTIONS *****************************************************************/
188 CombineRgn(HRGN hDest
,
193 /* FIXME some part should be done in user mode */
194 return NtGdiCombineRgn(hDest
, hSrc1
, hSrc2
, CombineMode
);
202 CreatePolygonRgn( const POINT
* lppt
, int cPoints
, int fnPolyFillMode
)
204 return (HRGN
) NtGdiPolyPolyDraw( (HDC
) fnPolyFillMode
, (PPOINT
) lppt
, (PULONG
) &cPoints
, 1, GdiPolyPolyRgn
);
212 CreatePolyPolygonRgn( const POINT
* lppt
,
213 const INT
* lpPolyCounts
,
217 return (HRGN
) NtGdiPolyPolyDraw( (HDC
) fnPolyFillMode
, (PPOINT
) lppt
, (PULONG
) lpPolyCounts
, (ULONG
) nCount
, GdiPolyPolyRgn
);
225 CreateEllipticRgnIndirect(
229 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
230 return NtGdiCreateEllipticRgn(prc
->left
, prc
->top
, prc
->right
, prc
->bottom
);
239 CreateRectRgn(int x1
, int y1
, int x2
, int y2
)
245 /* Normalize points */
260 if ( (UINT
)x1
< 0x80000000 ||
261 (UINT
)y1
< 0x80000000 ||
262 (UINT
)x2
> 0x7FFFFFFF ||
263 (UINT
)y2
> 0x7FFFFFFF )
265 SetLastError(ERROR_INVALID_PARAMETER
);
268 //// Remove when Brush/Pen/Rgn Attr is ready!
269 return NtGdiCreateRectRgn(x1
,y1
,x2
,y2
);
271 hrgn
= hGetPEBHandle(hctRegionHandle
, 0);
274 hrgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
279 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
285 if (( x1
== x2
) || (y1
== y2
))
287 pRgn_Attr
->Flags
= NULLREGION
;
288 pRgn_Attr
->Rect
.left
= pRgn_Attr
->Rect
.top
=
289 pRgn_Attr
->Rect
.right
= pRgn_Attr
->Rect
.bottom
= 0;
293 pRgn_Attr
->Flags
= SIMPLEREGION
;
294 pRgn_Attr
->Rect
.left
= x1
;
295 pRgn_Attr
->Rect
.top
= y1
;
296 pRgn_Attr
->Rect
.right
= x2
;
297 pRgn_Attr
->Rect
.bottom
= y2
;
300 pRgn_Attr
->AttrFlags
= (ATTR_RGN_DIRTY
|ATTR_RGN_VALID
);
310 CreateRectRgnIndirect(
314 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
315 return CreateRectRgn(prc
->left
, prc
->top
, prc
->right
, prc
->bottom
);
324 ExcludeClipRect(IN HDC hdc
, IN INT xLeft
, IN INT yTop
, IN INT xRight
, IN INT yBottom
)
327 // Handle something other than a normal dc object.
328 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
330 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
331 return MFDRV_ExcludeClipRect( hdc
, xLeft
, yTop
, xRight
, yBottom
);
334 PLDC pLDC
= GdiGetLDC(hdc
);
337 if (pLDC
->iType
!= LDC_EMFLDC
|| EMFDRV_ExcludeClipRect( hdc
, xLeft
, yTop
, xRight
, yBottom
))
338 return NtGdiExcludeClipRect(hdc
, xLeft
, yTop
, xRight
, yBottom
);
341 SetLastError(ERROR_INVALID_HANDLE
);
346 return NtGdiExcludeClipRect(hdc
, xLeft
, yTop
, xRight
, yBottom
);
355 CONST XFORM
* lpXform
,
357 CONST RGNDATA
* lpRgnData
362 if ((!lpXform
) && (lpRgnData
->rdh
.nCount
== 1))
364 PRECT pRect
= (PRECT
)&lpRgnData
->Buffer
[0];
365 return CreateRectRgn(pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
367 return NtGdiExtCreateRegion((LPXFORM
) lpXform
, nCount
,(LPRGNDATA
) lpRgnData
);
369 SetLastError(ERROR_INVALID_PARAMETER
);
378 ExtSelectClipRgn( IN HDC hdc
, IN HRGN hrgn
, IN INT iMode
)
380 /* FIXME some part need be done on user mode size */
381 return NtGdiExtSelectClipRgn(hdc
,hrgn
, iMode
);
394 INT Ret
= NtGdiGetRandomRgn(hdc
, hrgn
, CLIPRGN
);
397 // if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
410 return NtGdiGetRandomRgn(hdc
, hrgn
, METARGN
);
419 GetRegionData(HRGN hrgn
,
428 return NtGdiGetRegionData(hrgn
,nCount
,lpRgnData
);
442 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
))
443 return NtGdiGetRgnBox(hrgn
, prcOut
);
445 if (Rgn_Attr
->Flags
== NULLREGION
)
454 if (Rgn_Attr
->Flags
!= SIMPLEREGION
)
455 return NtGdiGetRgnBox(hrgn
, prcOut
);
456 /* WARNING! prcOut is never checked newbies! */
457 RtlCopyMemory( prcOut
, &Rgn_Attr
->Rect
, sizeof(RECT
));
459 return Rgn_Attr
->Flags
;
467 IntersectClipRect(HDC hdc
,
474 // Handle something other than a normal dc object.
475 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
477 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
478 return MFDRV_IntersectClipRect( hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
481 PLDC pLDC
= GdiGetLDC(hdc
);
484 if (pLDC
->iType
!= LDC_EMFLDC
|| EMFDRV_IntersectClipRect( hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
))
485 return NtGdiIntersectClipRect(hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
488 SetLastError(ERROR_INVALID_HANDLE
);
493 return NtGdiIntersectClipRect(hdc
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
501 MirrorRgn(HWND hwnd
, HRGN hrgn
)
504 GetWindowRect(hwnd
, &Rect
);
505 return MirrorRgnByWidth(hrgn
, Rect
.right
- Rect
.left
, NULL
);
513 OffsetClipRgn(HDC hdc
,
518 // Handle something other than a normal dc object.
519 if (GDI_HANDLE_GET_TYPE(hdc
) != GDI_OBJECT_TYPE_DC
)
521 if (GDI_HANDLE_GET_TYPE(hdc
) == GDI_OBJECT_TYPE_METADC
)
522 return MFDRV_OffsetClipRgn( hdc
, nXOffset
, nYOffset
);
525 PLDC pLDC
= GdiGetLDC(hdc
);
528 SetLastError(ERROR_INVALID_HANDLE
);
531 if (pLDC
->iType
== LDC_EMFLDC
&& !EMFDRV_OffsetClipRgn( hdc
, nXOffset
, nYOffset
))
533 return NtGdiOffsetClipRgn( hdc
, nXOffset
, nYOffset
);
537 return NtGdiOffsetClipRgn( hdc
, nXOffset
, nYOffset
);
546 OffsetRgn( HRGN hrgn
,
551 int nLeftRect
, nTopRect
, nRightRect
, nBottomRect
;
553 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
554 return NtGdiOffsetRgn(hrgn
,nXOffset
,nYOffset
);
556 if ( pRgn_Attr
->Flags
== NULLREGION
)
557 return pRgn_Attr
->Flags
;
559 if ( pRgn_Attr
->Flags
!= SIMPLEREGION
)
560 return NtGdiOffsetRgn(hrgn
,nXOffset
,nYOffset
);
562 nLeftRect
= pRgn_Attr
->Rect
.left
;
563 nTopRect
= pRgn_Attr
->Rect
.top
;
564 nRightRect
= pRgn_Attr
->Rect
.right
;
565 nBottomRect
= pRgn_Attr
->Rect
.bottom
;
567 if (nLeftRect
< nRightRect
)
569 if (nTopRect
< nBottomRect
)
571 nLeftRect
= nXOffset
+ nLeftRect
;
572 nTopRect
= nYOffset
+ nTopRect
;
573 nRightRect
= nXOffset
+ nRightRect
;
574 nBottomRect
= nYOffset
+ nBottomRect
;
576 /* Mask and bit test. */
577 if ( ( nLeftRect
& 0xF8000000 &&
578 (nLeftRect
& 0xF8000000) != 0x80000000 ) ||
579 ( nTopRect
& 0xF8000000 &&
580 (nTopRect
& 0xF8000000) != 0x80000000 ) ||
581 ( nRightRect
& 0xF8000000 &&
582 (nRightRect
& 0xF8000000) != 0x80000000 ) ||
583 ( nBottomRect
& 0xF8000000 &&
584 (nBottomRect
& 0xF8000000) != 0x80000000 ) )
590 pRgn_Attr
->Rect
.top
= nTopRect
;
591 pRgn_Attr
->Rect
.left
= nLeftRect
;
592 pRgn_Attr
->Rect
.right
= nRightRect
;
593 pRgn_Attr
->Rect
.bottom
= nBottomRect
;
594 pRgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
598 return pRgn_Attr
->Flags
;
606 PtInRegion(IN HRGN hrgn
,
612 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
613 return NtGdiPtInRegion(hrgn
,x
,y
);
615 if ( pRgn_Attr
->Flags
== NULLREGION
)
618 if ( pRgn_Attr
->Flags
!= SIMPLEREGION
)
619 return NtGdiPtInRegion(hrgn
,x
,y
);
621 return INRECT( pRgn_Attr
->Rect
, x
, y
);
629 RectInRegion(HRGN hrgn
,
635 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &pRgn_Attr
))
636 return NtGdiRectInRegion(hrgn
, (LPRECT
) prcl
);
638 if ( pRgn_Attr
->Flags
== NULLREGION
)
641 if ( pRgn_Attr
->Flags
!= SIMPLEREGION
)
642 return NtGdiRectInRegion(hrgn
, (LPRECT
) prcl
);
644 /* swap the coordinates to make right >= left and bottom >= top */
645 /* (region building rectangles are normalized the same way) */
646 if ( prcl
->top
> prcl
->bottom
)
648 rc
.top
= prcl
->bottom
;
649 rc
.bottom
= prcl
->top
;
654 rc
.bottom
= prcl
->bottom
;
656 if ( prcl
->right
< prcl
->left
)
658 rc
.right
= prcl
->left
;
659 rc
.left
= prcl
->right
;
663 rc
.right
= prcl
->right
;
664 rc
.left
= prcl
->left
;
667 if ( ComplexityFromRects( (PRECT
)&pRgn_Attr
->Rect
, &rc
) != COMPLEXREGION
)
682 return ExtSelectClipRgn(hdc
, hrgn
, RGN_COPY
);
690 SetRectRgn(HRGN hrgn
,
698 if (!GdiGetHandleUserData((HGDIOBJ
) hrgn
, GDI_OBJECT_TYPE_REGION
, (PVOID
) &Rgn_Attr
))
699 return NtGdiSetRectRgn(hrgn
, nLeftRect
, nTopRect
, nRightRect
, nBottomRect
);
701 if ((nLeftRect
== nRightRect
) || (nTopRect
== nBottomRect
))
703 Rgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
704 Rgn_Attr
->Flags
= NULLREGION
;
705 Rgn_Attr
->Rect
.left
= Rgn_Attr
->Rect
.top
=
706 Rgn_Attr
->Rect
.right
= Rgn_Attr
->Rect
.bottom
= 0;
710 Rgn_Attr
->Rect
.left
= nLeftRect
;
711 Rgn_Attr
->Rect
.top
= nTopRect
;
712 Rgn_Attr
->Rect
.right
= nRightRect
;
713 Rgn_Attr
->Rect
.bottom
= nBottomRect
;
715 if(nLeftRect
> nRightRect
)
717 Rgn_Attr
->Rect
.left
= nRightRect
;
718 Rgn_Attr
->Rect
.right
= nLeftRect
;
720 if(nTopRect
> nBottomRect
)
722 Rgn_Attr
->Rect
.top
= nBottomRect
;
723 Rgn_Attr
->Rect
.bottom
= nTopRect
;
726 Rgn_Attr
->AttrFlags
|= ATTR_RGN_DIRTY
;
727 Rgn_Attr
->Flags
= SIMPLEREGION
;
736 SetMetaRgn( HDC hDC
)
738 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_DC
)
739 return NtGdiSetMetaRgn(hDC
);
741 PLDC pLDC
= GdiGetLDC(hDC
);
742 if ( pLDC
&& GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_METADC
)
744 if (pLDC
->iType
== LDC_EMFLDC
|| EMFDRV_SetMetaRgn(hDC
))
746 return NtGdiSetMetaRgn(hDC
);
749 SetLastError(ERROR_INVALID_HANDLE
);