Merge freeldr from amd64 branch:
[reactos.git] / reactos / dll / win32 / gdi32 / objects / region.c
1 #include "precomp.h"
2
3
4 static
5 VOID
6 FASTCALL
7 SortRects(PRECT pRect, INT nCount)
8 {
9 INT i = 0, a = 0, b = 0, c, s;
10 RECT sRect;
11
12 if (nCount > 0)
13 {
14 i = 1; // set index point
15 c = nCount; // set inverse count
16 do
17 {
18 s = i; // set sort count
19 if ( i < nCount )
20 {
21 a = i - 1;
22 b = i;
23 do
24 {
25 if(pRect[b].top != pRect[i].bottom) break;
26 if(pRect[b].left < pRect[a].left)
27 {
28 sRect = pRect[a];
29 pRect[a] = pRect[b];
30 pRect[b] = sRect;
31 }
32 ++s;
33 ++b;
34 } while ( s < nCount );
35 }
36 ++i;
37 } while ( c-- != 1 );
38 }
39 }
40
41 /*
42 * I thought it was okay to have this in DeleteObject but~ Speed. (jt)
43 */
44 BOOL
45 FASTCALL
46 DeleteRegion( HRGN hRgn )
47 {
48 #if 0
49 PRGN_ATTR Rgn_Attr;
50
51 if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
52 ( Rgn_Attr != NULL ))
53 {
54 PTEB pTeb = NtCurrentTeb();
55 if (pTeb->Win32ThreadInfo != NULL)
56 {
57 if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
58 {
59 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
60 pTeb->GdiTebBatch.Offset);
61 pgO->gbHdr.Cmd = GdiBCDelRgn;
62 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
63 pgO->hgdiobj = (HGDIOBJ)hRgn;
64
65 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
66 pTeb->GdiBatchCount++;
67 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
68 return TRUE;
69 }
70 }
71 }
72 #endif
73 return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
74 }
75
76 INT
77 FASTCALL
78 MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn)
79 {
80 INT cRgnDSize, Ret = 0;
81 PRGNDATA pRgnData;
82
83 cRgnDSize = NtGdiGetRegionData(hRgn, 0, NULL);
84
85 if (cRgnDSize)
86 {
87 pRgnData = LocalAlloc(LMEM_FIXED, cRgnDSize * sizeof(LONG));
88 if (pRgnData)
89 {
90 if ( GetRegionData(hRgn, cRgnDSize, pRgnData) )
91 {
92 HRGN hRgnex;
93 UINT i;
94 INT SaveL = pRgnData->rdh.rcBound.left;
95 pRgnData->rdh.rcBound.left = Width - pRgnData->rdh.rcBound.right;
96 pRgnData->rdh.rcBound.right = Width - SaveL;
97 if (pRgnData->rdh.nCount > 0)
98 {
99 PRECT pRect = (PRECT)&pRgnData->Buffer;
100 for (i = 0; i < pRgnData->rdh.nCount; i++)
101 {
102 SaveL = pRect[i].left;
103 pRect[i].left = Width - pRect[i].right;
104 pRect[i].right = Width - SaveL;
105 }
106 }
107 SortRects((PRECT)&pRgnData->Buffer, pRgnData->rdh.nCount);
108 hRgnex = ExtCreateRegion(NULL, cRgnDSize , pRgnData);
109 if (hRgnex)
110 {
111 if (phRgn) phRgn = (HRGN *)hRgnex;
112 else
113 {
114 CombineRgn(hRgn, hRgnex, *phRgn, RGN_COPY);
115 DeleteObject(hRgnex);
116 }
117 Ret = 1;
118 }
119 }
120 LocalFree(pRgnData);
121 }
122 }
123 return Ret;
124 }
125
126 INT
127 WINAPI
128 MirrorRgnDC(HDC hdc, HRGN hRgn, HRGN *phRgn)
129 {
130 if (!GdiIsHandleValid((HGDIOBJ) hdc) ||
131 (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)) return 0;
132
133 return MirrorRgnByWidth(hRgn, NtGdiGetDeviceWidth(hdc), phRgn);
134 }
135
136 /* FUNCTIONS *****************************************************************/
137
138 /*
139 * @implemented
140 */
141 HRGN
142 WINAPI
143 CreatePolygonRgn( const POINT * lppt, int cPoints, int fnPolyFillMode)
144 {
145 return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) &cPoints, 1, GdiPolyPolyRgn);
146 }
147
148
149 /*
150 * @implemented
151 */
152 HRGN
153 WINAPI
154 CreatePolyPolygonRgn( const POINT* lppt,
155 const INT* lpPolyCounts,
156 int nCount,
157 int fnPolyFillMode)
158 {
159 return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) lpPolyCounts, (ULONG) nCount, GdiPolyPolyRgn );
160 }
161
162
163 /*
164 * @implemented
165 */
166 HRGN
167 WINAPI
168 CreateEllipticRgnIndirect(
169 const RECT *prc
170 )
171 {
172 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
173 return NtGdiCreateEllipticRgn(prc->left, prc->top, prc->right, prc->bottom);
174
175 }
176
177 /*
178 * @implemented
179 */
180 HRGN
181 WINAPI
182 CreateRectRgn(int x1, int y1, int x2,int y2)
183 {
184 /* FIXME Some part need be done in user mode */
185 return NtGdiCreateRectRgn(x1,y1,x2,y2);
186 }
187
188 /*
189 * @implemented
190 */
191 HRGN
192 WINAPI
193 CreateRectRgnIndirect(
194 const RECT *prc
195 )
196 {
197 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
198 return CreateRectRgn(prc->left, prc->top, prc->right, prc->bottom);
199
200 }
201
202 /*
203 * @implemented
204 */
205 HRGN
206 WINAPI
207 ExtCreateRegion(
208 CONST XFORM * lpXform,
209 DWORD nCount,
210 CONST RGNDATA * lpRgnData
211 )
212 {
213 if (lpRgnData)
214 {
215 if ((!lpXform) && (lpRgnData->rdh.nCount == 1))
216 {
217 PRECT pRect = (PRECT)&lpRgnData->Buffer[0];
218 return CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
219 }
220 return NtGdiExtCreateRegion((LPXFORM) lpXform, nCount,(LPRGNDATA) lpRgnData);
221 }
222 SetLastError(ERROR_INVALID_PARAMETER);
223 return NULL;
224 }
225
226 /*
227 * @implemented
228 */
229 int
230 WINAPI
231 GetClipRgn(
232 HDC hdc,
233 HRGN hrgn
234 )
235 {
236 INT Ret = NtGdiGetRandomRgn(hdc, hrgn, CLIPRGN);
237 // if (Ret)
238 // {
239 // if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
240 // }
241 return Ret;
242 }
243
244 /*
245 * @implemented
246 */
247 int
248 WINAPI
249 GetMetaRgn(HDC hdc,
250 HRGN hrgn)
251 {
252 return NtGdiGetRandomRgn(hdc, hrgn, METARGN);
253 }
254
255 /*
256 * @implemented
257 */
258 BOOL
259 WINAPI
260 MirrorRgn(HWND hwnd, HRGN hrgn)
261 {
262 RECT Rect;
263 GetWindowRect(hwnd, &Rect);
264 return MirrorRgnByWidth(hrgn, Rect.right - Rect.left, NULL);
265 }
266
267 /*
268 * @implemented
269 */
270 int WINAPI
271 SelectClipRgn(
272 HDC hdc,
273 HRGN hrgn
274 )
275 {
276 return ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
277 }
278
279 /*
280 * @implemented
281 */
282 BOOL
283 WINAPI
284 SetRectRgn(HRGN hrgn,
285 int nLeftRect,
286 int nTopRect,
287 int nRightRect,
288 int nBottomRect)
289 {
290 #if 0
291 PRGN_ATTR Rgn_Attr;
292
293 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
294 #endif
295 return NtGdiSetRectRgn(hrgn, nLeftRect, nTopRect, nRightRect, nBottomRect);
296 #if 0
297 if ((nLeftRect == nRightRect) || (nTopRect == nBottomRect))
298 {
299 Rgn_Attr->flFlags |= DIRTY_RGNATTR;
300 Rgn_Attr->dwType = RGNATTR_INIT;
301 Rgn_Attr->rcBound.left = Rgn_Attr->rcBound.top =
302 Rgn_Attr->rcBound.right = Rgn_Attr->rcBound.bottom = 0;
303 return TRUE;
304 }
305
306 Rgn_Attr->rcBound.left = nLeftRect;
307 Rgn_Attr->rcBound.top = nTopRect;
308 Rgn_Attr->rcBound.right = nRightRect;
309 Rgn_Attr->rcBound.bottom = nBottomRect;
310
311 if(nLeftRect > nRightRect)
312 {
313 Rgn_Attr->rcBound.left = nRightRect;
314 Rgn_Attr->rcBound.right = nLeftRect;
315 }
316 if(nTopRect > nBottomRect)
317 {
318 Rgn_Attr->rcBound.top = nBottomRect;
319 Rgn_Attr->rcBound.bottom = nTopRect;
320 }
321
322 Rgn_Attr->flFlags |= DIRTY_RGNATTR;
323 Rgn_Attr->dwType = RGNATTR_SET;
324 return TRUE;
325 #endif
326 }
327
328 /*
329 * @implemented
330 */
331 int
332 WINAPI
333 SetMetaRgn( HDC hDC )
334 {
335 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC)
336 return NtGdiSetMetaRgn(hDC);
337 #if 0
338 PLDC pLDC = GdiGetLDC(hDC);
339 if ( pLDC && GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC )
340 {
341 if (pLDC->iType == LDC_EMFLDC || EMFDRV_SetMetaRgn(hDC))
342 {
343 return NtGdiSetMetaRgn(hDC);
344 }
345 else
346 SetLastError(ERROR_INVALID_HANDLE);
347 }
348 #endif
349 return 0;
350 }
351
352