[gdi32]
[reactos.git] / reactos / dll / win32 / gdi32 / objects / region.c
1 #include "precomp.h"
2
3 static
4 VOID
5 FASTCALL
6 SortRects(PRECT pRect, INT nCount)
7 {
8 INT i = 0, a = 0, b = 0, c, s;
9 RECT sRect;
10
11 if (nCount > 0)
12 {
13 i = 1; // set index point
14 c = nCount; // set inverse count
15 do
16 {
17 s = i; // set sort count
18 if ( i < nCount )
19 {
20 a = i - 1;
21 b = i;
22 do
23 {
24 if(pRect[b].top != pRect[i].bottom) break;
25 if(pRect[b].left < pRect[a].left)
26 {
27 sRect = pRect[a];
28 pRect[a] = pRect[b];
29 pRect[b] = sRect;
30 }
31 ++s;
32 ++b;
33 } while ( s < nCount );
34 }
35 ++i;
36 } while ( c-- != 1 );
37 }
38 }
39
40 /*
41 * I thought it was okay to have this in DeleteObject but~ Speed. (jt)
42 */
43 BOOL
44 FASTCALL
45 DeleteRegion( HRGN hRgn )
46 {
47 #if 0
48 PRGN_ATTR Rgn_Attr;
49
50 if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
51 ( Rgn_Attr != NULL ))
52 {
53 PTEB pTeb = NtCurrentTeb();
54 if (pTeb->Win32ThreadInfo != NULL)
55 {
56 if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
57 {
58 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
59 pTeb->GdiTebBatch.Offset);
60 pgO->gbHdr.Cmd = GdiBCDelRgn;
61 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
62 pgO->hgdiobj = (HGDIOBJ)hRgn;
63
64 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
65 pTeb->GdiBatchCount++;
66 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
67 return TRUE;
68 }
69 }
70 }
71 #endif
72 return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
73 }
74
75 INT
76 FASTCALL
77 MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn)
78 {
79 INT cRgnDSize, Ret = 0;
80 PRGNDATA pRgnData;
81
82 cRgnDSize = NtGdiGetRegionData(hRgn, 0, NULL);
83
84 if (cRgnDSize)
85 {
86 pRgnData = LocalAlloc(LMEM_FIXED, cRgnDSize * sizeof(LONG));
87 if (pRgnData)
88 {
89 if ( GetRegionData(hRgn, cRgnDSize, pRgnData) )
90 {
91 HRGN hRgnex;
92 UINT i;
93 INT SaveL = pRgnData->rdh.rcBound.left;
94 pRgnData->rdh.rcBound.left = Width - pRgnData->rdh.rcBound.right;
95 pRgnData->rdh.rcBound.right = Width - SaveL;
96 if (pRgnData->rdh.nCount > 0)
97 {
98 PRECT pRect = (PRECT)&pRgnData->Buffer;
99 for (i = 0; i < pRgnData->rdh.nCount; i++)
100 {
101 SaveL = pRect[i].left;
102 pRect[i].left = Width - pRect[i].right;
103 pRect[i].right = Width - SaveL;
104 }
105 }
106 SortRects((PRECT)&pRgnData->Buffer, pRgnData->rdh.nCount);
107 hRgnex = ExtCreateRegion(NULL, cRgnDSize , pRgnData);
108 if (hRgnex)
109 {
110 if (phRgn) phRgn = (HRGN *)hRgnex;
111 else
112 {
113 CombineRgn(hRgn, hRgnex, 0, RGN_COPY);
114 DeleteObject(hRgnex);
115 }
116 Ret = 1;
117 }
118 }
119 LocalFree(pRgnData);
120 }
121 }
122 return Ret;
123 }
124
125 INT
126 WINAPI
127 MirrorRgnDC(HDC hdc, HRGN hRgn, HRGN *phRgn)
128 {
129 if (!GdiIsHandleValid((HGDIOBJ) hdc) ||
130 (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)) return 0;
131
132 return MirrorRgnByWidth(hRgn, NtGdiGetDeviceWidth(hdc), phRgn);
133 }
134
135 /* FUNCTIONS *****************************************************************/
136
137 /*
138 * @unimplemented
139 */
140 INT
141 WINAPI
142 CombineRgn(HRGN hDest,
143 HRGN hSrc1,
144 HRGN hSrc2,
145 INT CombineMode)
146 {
147 /* FIXME some part should be done in user mode */
148 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
149 }
150
151 /*
152 * @implemented
153 */
154 HRGN
155 WINAPI
156 CreatePolygonRgn( const POINT * lppt, int cPoints, int fnPolyFillMode)
157 {
158 return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) &cPoints, 1, GdiPolyPolyRgn);
159 }
160
161 /*
162 * @implemented
163 */
164 HRGN
165 WINAPI
166 CreatePolyPolygonRgn( const POINT* lppt,
167 const INT* lpPolyCounts,
168 int nCount,
169 int fnPolyFillMode)
170 {
171 return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) lpPolyCounts, (ULONG) nCount, GdiPolyPolyRgn );
172 }
173
174 /*
175 * @implemented
176 */
177 HRGN
178 WINAPI
179 CreateEllipticRgnIndirect(
180 const RECT *prc
181 )
182 {
183 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
184 return NtGdiCreateEllipticRgn(prc->left, prc->top, prc->right, prc->bottom);
185
186 }
187
188 /*
189 * @implemented
190 */
191 HRGN
192 WINAPI
193 CreateRectRgn(int x1, int y1, int x2,int y2)
194 {
195 /* FIXME Some part need be done in user mode */
196 return NtGdiCreateRectRgn(x1,y1,x2,y2);
197 }
198
199 /*
200 * @implemented
201 */
202 HRGN
203 WINAPI
204 CreateRectRgnIndirect(
205 const RECT *prc
206 )
207 {
208 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
209 return CreateRectRgn(prc->left, prc->top, prc->right, prc->bottom);
210
211 }
212
213 /*
214 * @implemented
215 */
216 INT
217 WINAPI
218 ExcludeClipRect(IN HDC hdc, IN INT xLeft, IN INT yTop, IN INT xRight, IN INT yBottom)
219 {
220 /* FIXME some part need be done on user mode size */
221 return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom);
222 }
223
224 /*
225 * @implemented
226 */
227 HRGN
228 WINAPI
229 ExtCreateRegion(
230 CONST XFORM * lpXform,
231 DWORD nCount,
232 CONST RGNDATA * lpRgnData
233 )
234 {
235 if (lpRgnData)
236 {
237 if ((!lpXform) && (lpRgnData->rdh.nCount == 1))
238 {
239 PRECT pRect = (PRECT)&lpRgnData->Buffer[0];
240 return CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
241 }
242 return NtGdiExtCreateRegion((LPXFORM) lpXform, nCount,(LPRGNDATA) lpRgnData);
243 }
244 SetLastError(ERROR_INVALID_PARAMETER);
245 return NULL;
246 }
247
248 /*
249 * @implemented
250 */
251 INT
252 WINAPI
253 ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode)
254 {
255 /* FIXME some part need be done on user mode size */
256 return NtGdiExtSelectClipRgn(hdc,hrgn, iMode);
257 }
258
259 /*
260 * @implemented
261 */
262 int
263 WINAPI
264 GetClipRgn(
265 HDC hdc,
266 HRGN hrgn
267 )
268 {
269 INT Ret = NtGdiGetRandomRgn(hdc, hrgn, CLIPRGN);
270 // if (Ret)
271 // {
272 // if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
273 // }
274 return Ret;
275 }
276
277 /*
278 * @implemented
279 */
280 int
281 WINAPI
282 GetMetaRgn(HDC hdc,
283 HRGN hrgn)
284 {
285 return NtGdiGetRandomRgn(hdc, hrgn, METARGN);
286 }
287
288 /*
289 * @implemented
290 *
291 */
292 INT
293 WINAPI
294 GetRgnBox(HRGN hrgn,
295 LPRECT prcOut)
296 {
297 #if 0
298 PRGN_ATTR Rgn_Attr;
299 if (!GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
300 return NtGdiGetRgnBox(hrgn, prcOut);
301 if (Rgn_Attr->Flags == NULLREGION)
302 {
303 prcOut->left = 0;
304 prcOut->top = 0;
305 prcOut->right = 0;
306 prcOut->bottom = 0;
307 }
308 else
309 {
310 if (Rgn_Attr->Flags != SIMPLEREGION) return NtGdiGetRgnBox(hrgn, prcOut);
311 *prcOut = Rgn_Attr->Rect;
312 }
313 return Rgn_Attr->Flags;
314 #endif
315 return NtGdiGetRgnBox(hrgn, prcOut);
316 }
317
318 /*
319 * @implemented
320 */
321 INT
322 WINAPI
323 IntersectClipRect(HDC hdc,
324 int nLeftRect,
325 int nTopRect,
326 int nRightRect,
327 int nBottomRect)
328 {
329 #if 0
330 // Handle something other than a normal dc object.
331 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
332 {
333 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
334 return MFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
335 else
336 {
337 PLDC pLDC = GdiGetLDC(hdc);
338 if ( pLDC )
339 {
340 if (pLDC->iType != LDC_EMFLDC || EMFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect))
341 return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
342 }
343 else
344 SetLastError(ERROR_INVALID_HANDLE);
345 return 0;
346 }
347 }
348 #endif
349 return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
350 }
351
352 /*
353 * @implemented
354 */
355 BOOL
356 WINAPI
357 MirrorRgn(HWND hwnd, HRGN hrgn)
358 {
359 RECT Rect;
360 GetWindowRect(hwnd, &Rect);
361 return MirrorRgnByWidth(hrgn, Rect.right - Rect.left, NULL);
362 }
363
364 /*
365 * @implemented
366 */
367 INT
368 WINAPI
369 OffsetClipRgn(HDC hdc,
370 int nXOffset,
371 int nYOffset)
372 {
373 #if 0
374 // Handle something other than a normal dc object.
375 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
376 {
377 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
378 return MFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset );
379 else
380 {
381 PLDC pLDC = GdiGetLDC(hdc);
382 if ( !pLDC )
383 {
384 SetLastError(ERROR_INVALID_HANDLE);
385 return 0;
386 }
387 if (pLDC->iType == LDC_EMFLDC && !EMFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset ))
388 return 0;
389 return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset);
390 }
391 }
392 #endif
393 return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset);
394 }
395
396 /*
397 * @implemented
398 *
399 */
400 INT
401 WINAPI
402 OffsetRgn( HRGN hrgn,
403 int nXOffset,
404 int nYOffset)
405 {
406 /* FIXME some part are done in user mode */
407 return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);
408 }
409
410 /*
411 * @unimplemented
412 */
413 BOOL
414 WINAPI
415 PtInRegion(IN HRGN hrgn,
416 int x,
417 int y)
418 {
419 /* FIXME some stuff at user mode need be fixed */
420 return NtGdiPtInRegion(hrgn,x,y);
421 }
422
423 /*
424 * @unimplemented
425 */
426 BOOL
427 WINAPI
428 RectInRegion(HRGN hrgn,
429 LPCRECT prcl)
430 {
431 /* FIXME some stuff at user mode need be fixed */
432 return NtGdiRectInRegion(hrgn, (LPRECT) prcl);
433 }
434
435 /*
436 * @implemented
437 */
438 int WINAPI
439 SelectClipRgn(
440 HDC hdc,
441 HRGN hrgn
442 )
443 {
444 return ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
445 }
446
447 /*
448 * @implemented
449 */
450 BOOL
451 WINAPI
452 SetRectRgn(HRGN hrgn,
453 int nLeftRect,
454 int nTopRect,
455 int nRightRect,
456 int nBottomRect)
457 {
458 PRGN_ATTR Rgn_Attr;
459
460 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
461 return NtGdiSetRectRgn(hrgn, nLeftRect, nTopRect, nRightRect, nBottomRect);
462
463 if ((nLeftRect == nRightRect) || (nTopRect == nBottomRect))
464 {
465 Rgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
466 Rgn_Attr->Flags = NULLREGION;
467 Rgn_Attr->Rect.left = Rgn_Attr->Rect.top =
468 Rgn_Attr->Rect.right = Rgn_Attr->Rect.bottom = 0;
469 return TRUE;
470 }
471
472 Rgn_Attr->Rect.left = nLeftRect;
473 Rgn_Attr->Rect.top = nTopRect;
474 Rgn_Attr->Rect.right = nRightRect;
475 Rgn_Attr->Rect.bottom = nBottomRect;
476
477 if(nLeftRect > nRightRect)
478 {
479 Rgn_Attr->Rect.left = nRightRect;
480 Rgn_Attr->Rect.right = nLeftRect;
481 }
482 if(nTopRect > nBottomRect)
483 {
484 Rgn_Attr->Rect.top = nBottomRect;
485 Rgn_Attr->Rect.bottom = nTopRect;
486 }
487
488 Rgn_Attr->AttrFlags |= ATTR_RGN_DIRTY ;
489 Rgn_Attr->Flags = SIMPLEREGION;
490 return TRUE;
491 }
492
493 /*
494 * @implemented
495 */
496 int
497 WINAPI
498 SetMetaRgn( HDC hDC )
499 {
500 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC)
501 return NtGdiSetMetaRgn(hDC);
502 #if 0
503 PLDC pLDC = GdiGetLDC(hDC);
504 if ( pLDC && GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC )
505 {
506 if (pLDC->iType == LDC_EMFLDC || EMFDRV_SetMetaRgn(hDC))
507 {
508 return NtGdiSetMetaRgn(hDC);
509 }
510 else
511 SetLastError(ERROR_INVALID_HANDLE);
512 }
513 #endif
514 return 0;
515 }
516
517