Sync to trunk (r44933)
[reactos.git] / reactos / dll / win32 / gdi32 / objects / region.c
1 #include "precomp.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 #define INRECT(r, x, y) \
7 ( ( ((r).right > x)) && \
8 ( ((r).left <= x)) && \
9 ( ((r).bottom > y)) && \
10 ( ((r).top <= y)) )
11
12 #define OVERLAPPING_RGN 0
13 #define INVERTED_RGN 1
14 #define SAME_RGN 2
15 #define DIFF_RGN 3
16 /*
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,
20 it's INVERTED_RGN.
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,
23 it's DIFF_RGN.
24 */
25 INT
26 FASTCALL
27 ComplexityFromRects( PRECTL prc1, PRECTL prc2)
28 {
29 if ( prc2->left >= prc1->left )
30 {
31 if ( ( prc1->right >= prc2->right) &&
32 ( prc1->top <= prc2->top ) &&
33 ( prc1->bottom >= prc2->bottom ) )
34 return SAME_RGN;
35
36 if ( prc2->left > prc1->left )
37 {
38 if ( ( prc1->left >= prc2->right ) ||
39 ( prc1->right <= prc2->left ) ||
40 ( prc1->top >= prc2->bottom ) ||
41 ( prc1->bottom <= prc2->top ) )
42 return DIFF_RGN;
43 }
44 }
45
46 if ( ( prc2->right < prc1->right ) ||
47 ( prc2->top > prc1->top ) ||
48 ( prc2->bottom < prc1->bottom ) )
49 {
50 if ( ( prc1->left >= prc2->right ) ||
51 ( prc1->right <= prc2->left ) ||
52 ( prc1->top >= prc2->bottom ) ||
53 ( prc1->bottom <= prc2->top ) )
54 return DIFF_RGN;
55 }
56 else
57 {
58 return INVERTED_RGN;
59 }
60 return OVERLAPPING_RGN;
61 }
62
63 static
64 VOID
65 FASTCALL
66 SortRects(PRECT pRect, INT nCount)
67 {
68 INT i = 0, a = 0, b = 0, c, s;
69 RECT sRect;
70
71 if (nCount > 0)
72 {
73 i = 1; // set index point
74 c = nCount; // set inverse count
75 do
76 {
77 s = i; // set sort count
78 if ( i < nCount )
79 {
80 a = i - 1;
81 b = i;
82 do
83 {
84 if(pRect[b].top != pRect[i].bottom) break;
85 if(pRect[b].left < pRect[a].left)
86 {
87 sRect = pRect[a];
88 pRect[a] = pRect[b];
89 pRect[b] = sRect;
90 }
91 ++s;
92 ++b;
93 } while ( s < nCount );
94 }
95 ++i;
96 } while ( c-- != 1 );
97 }
98 }
99
100 /*
101 * I thought it was okay to have this in DeleteObject but~ Speed. (jt)
102 */
103 BOOL
104 FASTCALL
105 DeleteRegion( HRGN hRgn )
106 {
107 #if 0
108 PRGN_ATTR Rgn_Attr;
109
110 if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
111 ( Rgn_Attr != NULL ))
112 {
113 PTEB pTeb = NtCurrentTeb();
114 if (pTeb->Win32ThreadInfo != NULL)
115 {
116 if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
117 {
118 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
119 pTeb->GdiTebBatch.Offset);
120 pgO->gbHdr.Cmd = GdiBCDelRgn;
121 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
122 pgO->hgdiobj = (HGDIOBJ)hRgn;
123
124 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
125 pTeb->GdiBatchCount++;
126 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
127 return TRUE;
128 }
129 }
130 }
131 #endif
132 return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
133 }
134
135 INT
136 FASTCALL
137 MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn)
138 {
139 INT cRgnDSize, Ret = 0;
140 PRGNDATA pRgnData;
141
142 cRgnDSize = NtGdiGetRegionData(hRgn, 0, NULL);
143
144 if (cRgnDSize)
145 {
146 pRgnData = LocalAlloc(LMEM_FIXED, cRgnDSize * sizeof(LONG));
147 if (pRgnData)
148 {
149 if ( GetRegionData(hRgn, cRgnDSize, pRgnData) )
150 {
151 HRGN hRgnex;
152 UINT i;
153 INT SaveL = pRgnData->rdh.rcBound.left;
154 pRgnData->rdh.rcBound.left = Width - pRgnData->rdh.rcBound.right;
155 pRgnData->rdh.rcBound.right = Width - SaveL;
156 if (pRgnData->rdh.nCount > 0)
157 {
158 PRECT pRect = (PRECT)&pRgnData->Buffer;
159 for (i = 0; i < pRgnData->rdh.nCount; i++)
160 {
161 SaveL = pRect[i].left;
162 pRect[i].left = Width - pRect[i].right;
163 pRect[i].right = Width - SaveL;
164 }
165 }
166 SortRects((PRECT)&pRgnData->Buffer, pRgnData->rdh.nCount);
167 hRgnex = ExtCreateRegion(NULL, cRgnDSize , pRgnData);
168 if (hRgnex)
169 {
170 if (phRgn) phRgn = (HRGN *)hRgnex;
171 else
172 {
173 CombineRgn(hRgn, hRgnex, 0, RGN_COPY);
174 DeleteObject(hRgnex);
175 }
176 Ret = 1;
177 }
178 }
179 LocalFree(pRgnData);
180 }
181 }
182 return Ret;
183 }
184
185 INT
186 WINAPI
187 MirrorRgnDC(HDC hdc, HRGN hRgn, HRGN *phRgn)
188 {
189 if (!GdiIsHandleValid((HGDIOBJ) hdc) ||
190 (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)) return 0;
191
192 return MirrorRgnByWidth(hRgn, NtGdiGetDeviceWidth(hdc), phRgn);
193 }
194
195 /* FUNCTIONS *****************************************************************/
196
197 /*
198 * @implemented
199 */
200 INT
201 WINAPI
202 CombineRgn(HRGN hDest,
203 HRGN hSrc1,
204 HRGN hSrc2,
205 INT CombineMode)
206 {
207 #if 0
208 PRGN_ATTR pRgn_Attr_Dest = NULL;
209 PRGN_ATTR pRgn_Attr_Src1 = NULL;
210 PRGN_ATTR pRgn_Attr_Src2 = NULL;
211 INT Complexity;
212 BOOL Ret;
213
214 Ret = GdiGetHandleUserData((HGDIOBJ) hDest, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Dest);
215 Ret = GdiGetHandleUserData((HGDIOBJ) hSrc1, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src1);
216
217 if ( !Ret ||
218 !pRgn_Attr_Dest ||
219 !pRgn_Attr_Src1 ||
220 pRgn_Attr_Src1->Flags > SIMPLEREGION )
221 #endif
222 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
223 #if 0
224 /* Handle COPY and use only src1. */
225 if ( CombineMode == RGN_COPY )
226 {
227 switch (pRgn_Attr_Src1->Flags)
228 {
229 case NULLREGION:
230 Ret = SetRectRgn( hDest, 0, 0, 0, 0);
231 if (Ret)
232 return NULLREGION;
233 goto ERROR_Exit;
234
235 case SIMPLEREGION:
236 Ret = SetRectRgn( hDest,
237 pRgn_Attr_Src1->Rect.left,
238 pRgn_Attr_Src1->Rect.top,
239 pRgn_Attr_Src1->Rect.right,
240 pRgn_Attr_Src1->Rect.bottom );
241 if (Ret)
242 return SIMPLEREGION;
243 goto ERROR_Exit;
244
245 case COMPLEXREGION:
246 default:
247 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
248 }
249 }
250
251 Ret = GdiGetHandleUserData((HGDIOBJ) hSrc2, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src2);
252 if ( !Ret ||
253 !pRgn_Attr_Src2 ||
254 pRgn_Attr_Src2->Flags > SIMPLEREGION )
255 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
256
257 /* All but AND. */
258 if ( CombineMode != RGN_AND)
259 {
260 if ( CombineMode <= RGN_AND)
261 {
262 /*
263 There might be some type of junk in the call, so go K.
264 If this becomes a problem, need to setup parameter check at the top.
265 */
266 DPRINT1("Might be junk! CombineMode %d\n",CombineMode);
267 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
268 }
269
270 if ( CombineMode > RGN_XOR) /* Handle DIFF. */
271 {
272 if ( CombineMode != RGN_DIFF)
273 { /* Filter check! Well, must be junk?, so go K. */
274 DPRINT1("RGN_COPY was handled! CombineMode %d\n",CombineMode);
275 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
276 }
277
278 if ( pRgn_Attr_Src1->Flags != NULLREGION &&
279 pRgn_Attr_Src2->Flags != NULLREGION )
280 {
281 Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
282 /* If same or overlapping and norm just go K. */
283 if (Complexity == SAME_RGN || Complexity == OVERLAPPING_RGN)
284 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
285 }
286 /* Just NULL rgn. */
287 if (SetRectRgn( hDest, 0, 0, 0, 0))
288 return NULLREGION;
289 goto ERROR_Exit;
290 }
291 else /* Handle OR or XOR. */
292 {
293 if ( pRgn_Attr_Src1->Flags == NULLREGION )
294 {
295 if ( pRgn_Attr_Src2->Flags != NULLREGION )
296 { /* Src1 null and not NULL, set from src2. */
297 Ret = SetRectRgn( hDest,
298 pRgn_Attr_Src2->Rect.left,
299 pRgn_Attr_Src2->Rect.top,
300 pRgn_Attr_Src2->Rect.right,
301 pRgn_Attr_Src2->Rect.bottom );
302 if (Ret)
303 return SIMPLEREGION;
304 goto ERROR_Exit;
305 }
306 /* Both are NULL. */
307 if (SetRectRgn( hDest, 0, 0, 0, 0))
308 return NULLREGION;
309 goto ERROR_Exit;
310 }
311 /* Src1 is not NULL. */
312 if ( pRgn_Attr_Src2->Flags != NULLREGION )
313 {
314 if ( CombineMode != RGN_OR ) /* Filter XOR, so go K. */
315 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
316
317 Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
318 /* If inverted use Src2. */
319 if ( Complexity == INVERTED_RGN)
320 {
321 Ret = SetRectRgn( hDest,
322 pRgn_Attr_Src2->Rect.left,
323 pRgn_Attr_Src2->Rect.top,
324 pRgn_Attr_Src2->Rect.right,
325 pRgn_Attr_Src2->Rect.bottom );
326 if (Ret)
327 return SIMPLEREGION;
328 goto ERROR_Exit;
329 }
330 /* Not NULL or overlapping or differentiated, go to K. */
331 if ( Complexity != SAME_RGN)
332 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
333 /* If same, just fall through. */
334 }
335 }
336 Ret = SetRectRgn( hDest,
337 pRgn_Attr_Src1->Rect.left,
338 pRgn_Attr_Src1->Rect.top,
339 pRgn_Attr_Src1->Rect.right,
340 pRgn_Attr_Src1->Rect.bottom );
341 if (Ret)
342 return SIMPLEREGION;
343 goto ERROR_Exit;
344 }
345
346 /* Handle AND. */
347 if ( pRgn_Attr_Src1->Flags != NULLREGION &&
348 pRgn_Attr_Src2->Flags != NULLREGION )
349 {
350 Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
351
352 if ( Complexity == DIFF_RGN ) /* Differentiated in anyway just NULL rgn. */
353 {
354 if (SetRectRgn( hDest, 0, 0, 0, 0))
355 return NULLREGION;
356 goto ERROR_Exit;
357 }
358
359 if ( Complexity != INVERTED_RGN) /* Not inverted and overlapping. */
360 {
361 if ( Complexity != SAME_RGN) /* Must be norm and overlapping. */
362 return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
363 /* Merge from src2. */
364 Ret = SetRectRgn( hDest,
365 pRgn_Attr_Src2->Rect.left,
366 pRgn_Attr_Src2->Rect.top,
367 pRgn_Attr_Src2->Rect.right,
368 pRgn_Attr_Src2->Rect.bottom );
369 if (Ret)
370 return SIMPLEREGION;
371 goto ERROR_Exit;
372 }
373 /* Inverted so merge from src1. */
374 Ret = SetRectRgn( hDest,
375 pRgn_Attr_Src1->Rect.left,
376 pRgn_Attr_Src1->Rect.top,
377 pRgn_Attr_Src1->Rect.right,
378 pRgn_Attr_Src1->Rect.bottom );
379 if (Ret)
380 return SIMPLEREGION;
381 goto ERROR_Exit;
382 }
383
384 /* It's all NULL! */
385 if (SetRectRgn( hDest, 0, 0, 0, 0))
386 return NULLREGION;
387
388 ERROR_Exit:
389 /* Even on error the flag is set dirty and force server side to redraw. */
390 pRgn_Attr_Dest->AttrFlags |= ATTR_RGN_DIRTY;
391 return ERROR;
392 #endif
393 }
394
395 /*
396 * @implemented
397 */
398 HRGN
399 WINAPI
400 CreateEllipticRgnIndirect(
401 const RECT *prc
402 )
403 {
404 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
405 return NtGdiCreateEllipticRgn(prc->left, prc->top, prc->right, prc->bottom);
406
407 }
408
409 /*
410 * @implemented
411 */
412 HRGN
413 WINAPI
414 CreatePolygonRgn( const POINT * lppt, int cPoints, int fnPolyFillMode)
415 {
416 return (HRGN) NtGdiPolyPolyDraw(ULongToHandle(fnPolyFillMode), (PPOINT) lppt, (PULONG) &cPoints, 1, GdiPolyPolyRgn);
417 }
418
419 /*
420 * @implemented
421 */
422 HRGN
423 WINAPI
424 CreatePolyPolygonRgn( const POINT* lppt,
425 const INT* lpPolyCounts,
426 int nCount,
427 int fnPolyFillMode)
428 {
429 return (HRGN) NtGdiPolyPolyDraw( (HDC) fnPolyFillMode, (PPOINT) lppt, (PULONG) lpPolyCounts, (ULONG) nCount, GdiPolyPolyRgn );
430 }
431
432 /*
433 * @implemented
434 */
435 HRGN
436 WINAPI
437 CreateRectRgn(int x1, int y1, int x2, int y2)
438 {
439 PRGN_ATTR pRgn_Attr;
440 HRGN hrgn;
441 int tmp;
442
443 /* Normalize points */
444 tmp = x1;
445 if ( x1 > x2 )
446 {
447 x1 = x2;
448 x2 = tmp;
449 }
450
451 tmp = y1;
452 if ( y1 > y2 )
453 {
454 y1 = y2;
455 y2 = tmp;
456 }
457 /* Check outside 24 bit limit for universal set. Chp 9 Areas, pg 560.*/
458 if ( x1 < -(1<<27) ||
459 y1 < -(1<<27) ||
460 x2 > (1<<27)-1 ||
461 y2 > (1<<27)-1 )
462 {
463 SetLastError(ERROR_INVALID_PARAMETER);
464 return NULL;
465 }
466
467 hrgn = hGetPEBHandle(hctRegionHandle, 0);
468
469 if (!hrgn)
470 hrgn = NtGdiCreateRectRgn(0, 0, 1, 1);
471
472 if (!hrgn)
473 return hrgn;
474
475 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
476 {
477 DPRINT1("No Attr for Region handle!!!\n");
478 DeleteRegion(hrgn);
479 return NULL;
480 }
481
482 if (( x1 == x2) || (y1 == y2))
483 {
484 pRgn_Attr->Flags = NULLREGION;
485 pRgn_Attr->Rect.left = pRgn_Attr->Rect.top =
486 pRgn_Attr->Rect.right = pRgn_Attr->Rect.bottom = 0;
487 }
488 else
489 {
490 pRgn_Attr->Flags = SIMPLEREGION;
491 pRgn_Attr->Rect.left = x1;
492 pRgn_Attr->Rect.top = y1;
493 pRgn_Attr->Rect.right = x2;
494 pRgn_Attr->Rect.bottom = y2;
495 }
496
497 pRgn_Attr->AttrFlags = (ATTR_RGN_DIRTY|ATTR_RGN_VALID);
498
499 return hrgn;
500 }
501
502 /*
503 * @implemented
504 */
505 HRGN
506 WINAPI
507 CreateRectRgnIndirect(
508 const RECT *prc
509 )
510 {
511 /* Notes if prc is NULL it will crash on All Windows NT I checked 2000/XP/VISTA */
512 return CreateRectRgn(prc->left, prc->top, prc->right, prc->bottom);
513
514 }
515
516 /*
517 * @implemented
518 */
519 INT
520 WINAPI
521 ExcludeClipRect(IN HDC hdc, IN INT xLeft, IN INT yTop, IN INT xRight, IN INT yBottom)
522 {
523 #if 0
524 // Handle something other than a normal dc object.
525 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
526 {
527 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
528 return MFDRV_ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom);
529 else
530 {
531 PLDC pLDC = GdiGetLDC(hdc);
532 if ( pLDC )
533 {
534 if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom))
535 return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom);
536 }
537 else
538 SetLastError(ERROR_INVALID_HANDLE);
539 return ERROR;
540 }
541 }
542 #endif
543 return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom);
544 }
545
546 /*
547 * @implemented
548 */
549 HRGN
550 WINAPI
551 ExtCreateRegion(
552 CONST XFORM * lpXform,
553 DWORD nCount,
554 CONST RGNDATA * lpRgnData
555 )
556 {
557 if (lpRgnData)
558 {
559 if ((!lpXform) && (lpRgnData->rdh.nCount == 1))
560 {
561 PRECT pRect = (PRECT)&lpRgnData->Buffer[0];
562 return CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
563 }
564 return NtGdiExtCreateRegion((LPXFORM) lpXform, nCount,(LPRGNDATA) lpRgnData);
565 }
566 SetLastError(ERROR_INVALID_PARAMETER);
567 return NULL;
568 }
569
570 /*
571 * @implemented
572 */
573 INT
574 WINAPI
575 ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode)
576 {
577 /* FIXME some part need be done on user mode size */
578 return NtGdiExtSelectClipRgn(hdc,hrgn, iMode);
579 }
580
581 /*
582 * @implemented
583 */
584 int
585 WINAPI
586 GetClipRgn(
587 HDC hdc,
588 HRGN hrgn
589 )
590 {
591 INT Ret = NtGdiGetRandomRgn(hdc, hrgn, CLIPRGN);
592 // if (Ret)
593 // {
594 // if(GetLayout(hdc) & LAYOUT_RTL) MirrorRgnDC(hdc,(HRGN)Ret, NULL);
595 // }
596 return Ret;
597 }
598
599 /*
600 * @implemented
601 */
602 int
603 WINAPI
604 GetMetaRgn(HDC hdc,
605 HRGN hrgn)
606 {
607 return NtGdiGetRandomRgn(hdc, hrgn, METARGN);
608 }
609
610 /*
611 * @implemented
612 *
613 */
614 DWORD
615 WINAPI
616 GetRegionData(HRGN hrgn,
617 DWORD nCount,
618 LPRGNDATA lpRgnData)
619 {
620 if (!lpRgnData)
621 {
622 nCount = 0;
623 }
624
625 return NtGdiGetRegionData(hrgn,nCount,lpRgnData);
626 }
627
628 /*
629 * @implemented
630 *
631 */
632 INT
633 WINAPI
634 GetRgnBox(HRGN hrgn,
635 LPRECT prcOut)
636 {
637 #if 0
638 PRGN_ATTR Rgn_Attr;
639
640 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
641 #endif
642 return NtGdiGetRgnBox(hrgn, prcOut);
643 #if 0
644 if (Rgn_Attr->Flags == NULLREGION)
645 {
646 prcOut->left = 0;
647 prcOut->top = 0;
648 prcOut->right = 0;
649 prcOut->bottom = 0;
650 }
651 else
652 {
653 if (Rgn_Attr->Flags != SIMPLEREGION)
654 return NtGdiGetRgnBox(hrgn, prcOut);
655 /* WARNING! prcOut is never checked newbies! */
656 RtlCopyMemory( prcOut, &Rgn_Attr->Rect, sizeof(RECT));
657 }
658 return Rgn_Attr->Flags;
659 #endif
660 }
661
662 /*
663 * @implemented
664 */
665 INT
666 WINAPI
667 IntersectClipRect(HDC hdc,
668 int nLeftRect,
669 int nTopRect,
670 int nRightRect,
671 int nBottomRect)
672 {
673 #if 0
674 // Handle something other than a normal dc object.
675 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
676 {
677 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
678 return MFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
679 else
680 {
681 PLDC pLDC = GdiGetLDC(hdc);
682 if ( pLDC )
683 {
684 if (pLDC->iType != LDC_EMFLDC || EMFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect))
685 return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
686 }
687 else
688 SetLastError(ERROR_INVALID_HANDLE);
689 return ERROR;
690 }
691 }
692 #endif
693 return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect);
694 }
695
696 /*
697 * @implemented
698 */
699 BOOL
700 WINAPI
701 MirrorRgn(HWND hwnd, HRGN hrgn)
702 {
703 RECT Rect;
704 GetWindowRect(hwnd, &Rect);
705 return MirrorRgnByWidth(hrgn, Rect.right - Rect.left, NULL);
706 }
707
708 /*
709 * @implemented
710 */
711 INT
712 WINAPI
713 OffsetClipRgn(HDC hdc,
714 int nXOffset,
715 int nYOffset)
716 {
717 #if 0
718 // Handle something other than a normal dc object.
719 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
720 {
721 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
722 return MFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset );
723 else
724 {
725 PLDC pLDC = GdiGetLDC(hdc);
726 if ( !pLDC )
727 {
728 SetLastError(ERROR_INVALID_HANDLE);
729 return ERROR;
730 }
731 if (pLDC->iType == LDC_EMFLDC && !EMFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset ))
732 return ERROR;
733 return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset);
734 }
735 }
736 #endif
737 return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset);
738 }
739
740 /*
741 * @implemented
742 *
743 */
744 INT
745 WINAPI
746 OffsetRgn( HRGN hrgn,
747 int nXOffset,
748 int nYOffset)
749 {
750 #if 0
751 PRGN_ATTR pRgn_Attr;
752 int nLeftRect, nTopRect, nRightRect, nBottomRect;
753
754 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
755 #endif
756 return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);
757 #if 0
758 if ( pRgn_Attr->Flags == NULLREGION)
759 return pRgn_Attr->Flags;
760
761 if ( pRgn_Attr->Flags != SIMPLEREGION)
762 return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);
763
764 nLeftRect = pRgn_Attr->Rect.left;
765 nTopRect = pRgn_Attr->Rect.top;
766 nRightRect = pRgn_Attr->Rect.right;
767 nBottomRect = pRgn_Attr->Rect.bottom;
768
769 if (nLeftRect < nRightRect)
770 {
771 if (nTopRect < nBottomRect)
772 {
773 nLeftRect = nXOffset + nLeftRect;
774 nTopRect = nYOffset + nTopRect;
775 nRightRect = nXOffset + nRightRect;
776 nBottomRect = nYOffset + nBottomRect;
777
778 /* Check 28 bit limit. Chp 9 Areas, pg 560. */
779 if ( nLeftRect < -(1<<27) ||
780 nTopRect < -(1<<27) ||
781 nRightRect > (1<<27)-1 ||
782 nBottomRect > (1<<27)-1 )
783 {
784 return ERROR;
785 }
786
787 pRgn_Attr->Rect.top = nTopRect;
788 pRgn_Attr->Rect.left = nLeftRect;
789 pRgn_Attr->Rect.right = nRightRect;
790 pRgn_Attr->Rect.bottom = nBottomRect;
791 pRgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
792 }
793 }
794 return pRgn_Attr->Flags;
795 #endif
796 }
797
798 /*
799 * @implemented
800 */
801 BOOL
802 WINAPI
803 PtInRegion(IN HRGN hrgn,
804 int x,
805 int y)
806 {
807 #if 0
808 PRGN_ATTR pRgn_Attr;
809
810 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
811 #endif
812 return NtGdiPtInRegion(hrgn,x,y);
813 #if 0
814 if ( pRgn_Attr->Flags == NULLREGION)
815 return FALSE;
816
817 if ( pRgn_Attr->Flags != SIMPLEREGION)
818 return NtGdiPtInRegion(hrgn,x,y);
819
820 return INRECT( pRgn_Attr->Rect, x, y);
821 #endif
822 }
823
824 /*
825 * @implemented
826 */
827 BOOL
828 WINAPI
829 RectInRegion(HRGN hrgn,
830 LPCRECT prcl)
831 {
832 #if 0
833 PRGN_ATTR pRgn_Attr;
834 RECTL rc;
835
836 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
837 #endif
838 return NtGdiRectInRegion(hrgn, (LPRECT) prcl);
839 #if 0
840 if ( pRgn_Attr->Flags == NULLREGION)
841 return FALSE;
842
843 if ( pRgn_Attr->Flags != SIMPLEREGION)
844 return NtGdiRectInRegion(hrgn, (LPRECT) prcl);
845
846 /* swap the coordinates to make right >= left and bottom >= top */
847 /* (region building rectangles are normalized the same way) */
848 if ( prcl->top > prcl->bottom)
849 {
850 rc.top = prcl->bottom;
851 rc.bottom = prcl->top;
852 }
853 else
854 {
855 rc.top = prcl->top;
856 rc.bottom = prcl->bottom;
857 }
858 if ( prcl->right < prcl->left)
859 {
860 rc.right = prcl->left;
861 rc.left = prcl->right;
862 }
863 else
864 {
865 rc.right = prcl->right;
866 rc.left = prcl->left;
867 }
868
869 if ( ComplexityFromRects( &pRgn_Attr->Rect, &rc) != DIFF_RGN )
870 return TRUE;
871
872 return FALSE;
873 #endif
874 }
875
876 /*
877 * @implemented
878 */
879 int WINAPI
880 SelectClipRgn(
881 HDC hdc,
882 HRGN hrgn
883 )
884 {
885 return ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
886 }
887
888 /*
889 * @implemented
890 */
891 BOOL
892 WINAPI
893 SetRectRgn(HRGN hrgn,
894 int nLeftRect,
895 int nTopRect,
896 int nRightRect,
897 int nBottomRect)
898 {
899 #if 0
900 PRGN_ATTR Rgn_Attr;
901
902 if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr))
903 #endif
904 return NtGdiSetRectRgn(hrgn, nLeftRect, nTopRect, nRightRect, nBottomRect);
905 #if 0
906 if ((nLeftRect == nRightRect) || (nTopRect == nBottomRect))
907 {
908 Rgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
909 Rgn_Attr->Flags = NULLREGION;
910 Rgn_Attr->Rect.left = Rgn_Attr->Rect.top =
911 Rgn_Attr->Rect.right = Rgn_Attr->Rect.bottom = 0;
912 return TRUE;
913 }
914
915 Rgn_Attr->Rect.left = nLeftRect;
916 Rgn_Attr->Rect.top = nTopRect;
917 Rgn_Attr->Rect.right = nRightRect;
918 Rgn_Attr->Rect.bottom = nBottomRect;
919
920 if(nLeftRect > nRightRect)
921 {
922 Rgn_Attr->Rect.left = nRightRect;
923 Rgn_Attr->Rect.right = nLeftRect;
924 }
925 if(nTopRect > nBottomRect)
926 {
927 Rgn_Attr->Rect.top = nBottomRect;
928 Rgn_Attr->Rect.bottom = nTopRect;
929 }
930
931 Rgn_Attr->AttrFlags |= ATTR_RGN_DIRTY ;
932 Rgn_Attr->Flags = SIMPLEREGION;
933 return TRUE;
934 #endif
935 }
936
937 /*
938 * @implemented
939 */
940 int
941 WINAPI
942 SetMetaRgn( HDC hDC )
943 {
944 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC)
945 return NtGdiSetMetaRgn(hDC);
946 #if 0
947 PLDC pLDC = GdiGetLDC(hDC);
948 if ( pLDC && GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC )
949 {
950 if (pLDC->iType == LDC_EMFLDC || EMFDRV_SetMetaRgn(hDC))
951 {
952 return NtGdiSetMetaRgn(hDC);
953 }
954 else
955 SetLastError(ERROR_INVALID_HANDLE);
956 }
957 #endif
958 return ERROR;
959 }
960