source: trunk/src/gdi32/region.cpp@ 7029

Last change on this file since 7029 was 7003, checked in by phaller, 24 years ago

disabled profiling

File size: 52.6 KB
Line 
1/* $Id: region.cpp,v 1.23 2001-10-10 22:20:22 phaller Exp $ */
2
3/*
4 * GDI32 region code
5 *
6 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 *
9 * TODO: Metafile recording
10 * TODO: Do we need to translate & set the last error for Gpi operations?
11 *
12 * Project Odin Software License can be found in LICENSE.TXT
13 *
14 */
15
16// Note: profiling currently not supported for this file
17#undef PROFILE
18#include <odinwrap.h>
19
20#define INCL_GPI
21#define INCL_WIN
22#include <os2wrap.h> //need odin wrappers
23
24#include <win32type.h>
25#include <win32api.h>
26#include <winconst.h>
27#include <stdlib.h>
28#include <stdarg.h>
29#include <string.h>
30#include <misc.h>
31#include <objhandle.h>
32#include <dcdata.h>
33#include <winuser32.h>
34#include "oslibgpi.h"
35
36#define DBG_LOCALLOG DBG_region
37#include "dbglocal.h"
38
39
40ODINDEBUGCHANNEL(GDI32-REGION)
41
42
43typedef enum
44{
45 AS_DEVICE,
46 AS_WORLD
47} InterpMode;
48
49#define MEM_HPS_MAX 768
50
51static void convertDeviceRect(HWND hwnd, pDCData pHps, PRECTL pRectl, ULONG count);
52
53#define convertWinDeviceRectToPMDeviceRect(arg1, arg2, arg3) convertDeviceRect(arg1, arg2, arg3)
54#define convertPMDeviceRectToWinDeviceRect(arg1, arg2, arg3) convertDeviceRect(arg1, arg2, arg3)
55
56inline void convertDeviceRect(pDCData pHps, PRECTL pRectl, ULONG count)
57{
58 convertDeviceRect(0, pHps, pRectl, count);
59}
60inline void convertDeviceRect(HWND hwnd, PRECTL pRectl, ULONG count)
61{
62 convertDeviceRect(hwnd, 0, pRectl, count);
63}
64
65HPS hpsRegion = 0;
66
67//******************************************************************************
68//******************************************************************************
69BOOL InitRegionSpace()
70{
71 hpsRegion = WinGetScreenPS(HWND_DESKTOP);
72 return hpsRegion != 0;
73}
74//******************************************************************************
75//******************************************************************************
76LONG hdcHeight(HWND hwnd, pDCData pHps)
77{
78 if(hwnd == 0 && pHps != 0)
79 hwnd = pHps->hwnd;
80
81 if(hwnd != 0 || pHps == 0)
82 {
83 RECT rect;
84 RECTL rectl;
85 LONG y = 0;
86
87 if(pHps == 0 || pHps->isClient) //client area
88 {
89 if(GetClientRect(OS2ToWin32Handle(hwnd), &rect) == TRUE) {
90 y = rect.bottom - rect.top;
91 }
92 }
93 else
94 if(WinQueryWindowRect(hwnd, &rectl)) //whole window
95 y = rectl.yTop;
96
97 return y;
98 }
99 else
100 if(pHps->bitmapHandle)
101 {
102 return pHps->bitmapHeight;
103 }
104 else
105 if(pHps->isMetaPS)
106 {
107 return 0;
108 }
109 else
110 if(pHps->isPrinter)
111 {
112 return pHps->printPageHeight;
113 }
114 else
115 {
116 return MEM_HPS_MAX;
117 }
118}
119//******************************************************************************
120//******************************************************************************
121LONG hdcWidth(HWND hwnd, pDCData pHps)
122{
123 if(hwnd == 0 && pHps != 0)
124 hwnd = pHps->hwnd;
125
126 if(hwnd != 0 || pHps == 0)
127 {
128 RECT rect;
129 RECTL rectl;
130 LONG x = 0;
131
132 if(pHps == 0 || pHps->isClient) //client area
133 {
134 if(GetClientRect(OS2ToWin32Handle(hwnd), &rect) == TRUE) {
135 x = rect.right - rect.left;
136 }
137 }
138 else
139 if(WinQueryWindowRect(hwnd, &rectl)) //whole window
140 x = rectl.xRight;
141
142 return x;
143 }
144// else
145// DebugInt3();
146 return 0;
147}
148//******************************************************************************
149//******************************************************************************
150static void convertWinWorldRectToPMDeviceRect(pDCData pHps_Hdc, PRECTL pRects, UINT count = 1)
151{
152 PRECTL pRectl;
153 for (int x=0; x < count; x++)
154 {
155 pRectl = &pRects[x];
156
157 if(pRectl->yTop < pRectl->yBottom) {
158 ULONG temp = pRectl->yBottom;
159 pRectl->yBottom = pRectl->yTop;
160 pRectl->yTop = temp;
161 }
162 BOOL success = GpiConvert( pHps_Hdc->hps, CVTC_WORLD, CVTC_DEVICE, 2, (PPOINTL)pRectl);
163 if(!success)
164 {
165 break;
166 }
167 if(pRectl->yTop < pRectl->yBottom) {
168 ULONG temp = pRectl->yBottom;
169 pRectl->yBottom = pRectl->yTop;
170 pRectl->yTop = temp;
171 }
172 }
173}
174//******************************************************************************
175//******************************************************************************
176static void convertDeviceRect(HWND hwnd, pDCData pHps, PRECTL pRectl, ULONG count)
177{
178 long wHeight, wWidth;
179
180 if(hwnd == HWND_DESKTOP) {
181 wHeight = OSLibGetScreenHeight();
182 wWidth = OSLibGetScreenWidth();
183 }
184 else {
185 wHeight = hdcHeight(hwnd, pHps);
186 wWidth = hdcWidth(hwnd, pHps);
187 }
188
189 if(pHps)
190 {
191 wHeight += pHps->HPStoHDCInversionHeight;
192 }
193
194 if(hwnd || (pHps && pHps->hwnd)) {
195 for(int x=0; x < count; x++)
196 {
197 if(pRectl[x].xRight > wWidth) {
198 pRectl[x].xRight = wWidth;
199 }
200 if(pRectl[x].yTop > wHeight) {
201 pRectl[x].yTop = 0;
202 }
203 else pRectl[x].yTop = wHeight - pRectl[x].yTop;
204
205 pRectl[x].yBottom = wHeight - pRectl[x].yBottom;
206 }
207 }
208 else {
209 for(int x=0; x < count; x++)
210 {
211 pRectl[x].yTop = wHeight - pRectl[x].yTop;
212 pRectl[x].yBottom = wHeight - pRectl[x].yBottom;
213 }
214 }
215}
216//******************************************************************************
217//******************************************************************************
218static void convertPMDeviceRectToWinWorldRect(pDCData pHps_Hdc, PRECTL pRectl)
219{
220 GpiConvert(pHps_Hdc->hps, CVTC_DEVICE, CVTC_WORLD, 2, (PPOINTL)pRectl );
221}
222//******************************************************************************
223//******************************************************************************
224BOOL interpretRegionAs(pDCData pHps, HRGN hrgnDest, HRGN hrgnSrc, InterpMode mode)
225{
226 BOOL success = FALSE;
227 int x, i;
228 HPS hpsDest;
229
230 if(pHps)
231 {
232 if(!hrgnDest) {
233 hrgnDest = pHps->hrgnHDC;
234#ifdef DEBUG
235 if(hrgnDest == 0) {
236 DebugInt3();
237 }
238#endif
239 }
240 hpsDest = pHps->hps;
241 }
242 else {
243 DebugInt3();
244 return FALSE;
245 }
246
247 RGNRECT rgnRect;
248 rgnRect.ircStart = 1;
249 rgnRect.crc = 0;
250 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
251 success = GpiQueryRegionRects(hpsRegion, hrgnSrc, NULL, &rgnRect, NULL);
252 if(success)
253 {
254 if(rgnRect.crcReturned > 0)
255 {
256 rgnRect.crc = rgnRect.crcReturned;
257 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
258 success = GpiQueryRegionRects(hpsRegion, hrgnSrc, NULL, &rgnRect, pRectl);
259 if(success)
260 {
261 if(mode == AS_DEVICE)
262 {
263 ULONG temp;
264 for(x=0; x < rgnRect.crcReturned; x++)
265 {
266 temp = pRectl[x].yBottom;
267 pRectl[x].yBottom = pRectl[x].yTop;
268 pRectl[x].yTop = temp;
269 }
270 convertWinDeviceRectToPMDeviceRect(pHps, pRectl, rgnRect.crcReturned);
271 }
272 else
273 {
274 GpiConvert(pHps->hps, CVTC_WORLD, CVTC_DEVICE, rgnRect.crcReturned<<1, (PPOINTL)pRectl);
275
276 ULONG temp;
277 for(i=0; i < rgnRect.crcReturned; i++)
278 {
279 if(pRectl[i].yTop < pRectl[i].yBottom)
280 {
281 temp = pRectl[i].yBottom + 1;
282 pRectl[i].yBottom = pRectl[i].yTop + 1;
283 pRectl[i].yTop = temp;
284 }
285 else
286 {
287 pRectl[i].yTop++;
288 pRectl[i].yBottom++;
289 }
290 }
291 }
292 success = GpiSetRegion(hpsDest, hrgnDest, rgnRect.crcReturned, pRectl);
293 }
294 delete[] pRectl;
295 }
296 else
297 {
298 success = GpiSetRegion(hpsDest, hrgnDest, 0, NULL);
299 }
300 }
301 return success;
302}
303//******************************************************************************
304//exported (used by user32)
305//******************************************************************************
306BOOL WIN32API setWinDeviceRegionFromPMDeviceRegion(HRGN winHrgn, HRGN pmHrgn, pDCData pHpsPmHrgn, HWND hwndPmHrgn)
307{
308 BOOL success;
309 int x;
310 BOOL mustReleaseScreenPS = FALSE;
311 HPS hps;
312
313 if(pHpsPmHrgn || hwndPmHrgn)
314 {
315 if(pHpsPmHrgn)
316 hps = pHpsPmHrgn->hps;
317 else
318 {
319 hps = WinGetScreenPS(HWND_DESKTOP);
320 mustReleaseScreenPS = TRUE;
321 }
322
323 RGNRECT rgnRect;
324 rgnRect.ircStart = 1;
325 rgnRect.crc = 0;
326 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
327 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, NULL);
328 if(success )
329 {
330 if(rgnRect.crcReturned > 0)
331 {
332 rgnRect.crc = rgnRect.crcReturned;
333 PRECTL pRectl = new RECTL[rgnRect.crcReturned];
334 success = GpiQueryRegionRects(hps, pmHrgn, NULL, &rgnRect, pRectl);
335 if(success)
336 {
337 if(pHpsPmHrgn)
338 convertPMDeviceRectToWinDeviceRect(pHpsPmHrgn, pRectl, rgnRect.crcReturned);
339 else
340 convertPMDeviceRectToWinDeviceRect(hwndPmHrgn, pRectl, rgnRect.crcReturned);
341
342 for(x=0; x < rgnRect.crcReturned; x++)
343 {
344 ULONG temp = pRectl[x].yBottom;
345 pRectl[x].yBottom = pRectl[x].yTop;
346 pRectl[x].yTop = temp;
347 }
348
349 success = GpiSetRegion(hpsRegion, winHrgn, rgnRect.crcReturned, pRectl);
350 }
351 delete[] pRectl;
352 }
353 else
354 {
355 success = GpiSetRegion(hpsRegion, winHrgn, 0, NULL);
356 }
357 }
358 }
359 else
360 success = FALSE;
361
362 if(mustReleaseScreenPS)
363 WinReleasePS(hps);
364
365 return success;
366}
367//******************************************************************************
368int WIN32API GetRgnBox( HRGN hrgn, PRECT pRect);
369//******************************************************************************
370ODINFUNCTIONNODBG2(int, SelectClipRgn, HDC, hdc, HRGN, hrgn)
371{
372 LONG lComplexity = RGN_NULL;
373 HRGN hrgnNewClip;
374 HRGN hrgnOldClip;
375#ifdef DEBUG
376 HRGN hrgn1 = hrgn;
377#endif
378
379 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
380 if(!pHps)
381 {
382 dprintf(("WARNING: SelectClipRgn: invalid hdc!", hdc, hrgn));
383 SetLastError(ERROR_INVALID_HANDLE_W);
384 return ERROR_W;
385 }
386
387 dprintf(("SelectClipRgn: %x %x", hdc, hrgn));
388 if(hrgn)
389 {
390 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
391 if(hrgn == HANDLE_OBJ_ERROR) {
392 dprintf(("WARNING: SelectClipRgn: invalid region!", hdc, hrgn1));
393 SetLastError(ERROR_INVALID_HANDLE_W);
394 return ERROR_W;
395 }
396 }
397
398 if(hrgn)
399 {
400 RECTL rectl = {0,0,1,1};
401 hrgnNewClip = GpiCreateRegion(pHps->hps, 1, &rectl);
402 if(interpretRegionAs(pHps, hrgnNewClip, hrgn, AS_DEVICE) == 0)
403 {
404 lComplexity = RGN_ERROR;
405 }
406 }
407 else
408 hrgnNewClip = 0;
409
410 if(lComplexity != RGN_ERROR)
411 {
412 if(hrgnNewClip == 0) {
413 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
414 }
415 lComplexity = GpiSetClipRegion(pHps->hps, hrgnNewClip, &hrgnOldClip);
416 if (lComplexity != RGN_ERROR )
417 {
418 if(hrgnOldClip)
419 GpiDestroyRegion(pHps->hps, hrgnOldClip);
420
421 //todo: metafile recording
422 SetLastError(ERROR_SUCCESS_W);
423
424 //SvL: Must check if origin changed here. Sometimes happens when
425 // window looses focus. (don't know why....)
426 checkOrigin(pHps);
427 return lComplexity;
428 }
429 }
430
431 dprintf(("WARNING: SelectClipRgn: RGN_ERROR!", hdc, hrgn1));
432 if(hrgnNewClip)
433 GpiDestroyRegion(pHps->hps, hrgnNewClip);
434
435 SetLastError(ERROR_SUCCESS_W);
436 return lComplexity;
437}
438//******************************************************************************
439//******************************************************************************
440ODINFUNCTIONNODBG3(int, ExtSelectClipRgn, HDC, hdc, HRGN, hrgn, int, mode)
441{
442#ifdef DEBUG
443 HRGN hrgn1 = hrgn;
444#endif
445
446 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
447 if (!pHps)
448 {
449 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid hdc", hdc, hrgn, mode));
450 SetLastError(ERROR_INVALID_HANDLE_W);
451 return ERROR_W;
452 }
453
454 LONG lComplexity;
455 HRGN hrgnCurrent = NULLHANDLE;
456
457 if(!hrgn && mode != RGN_COPY_W)
458 {
459 SetLastError(ERROR_INVALID_PARAMETER_W);
460 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
461 return ERROR_W;
462 }
463
464 LONG lMode;
465 switch (mode)
466 {
467 case RGN_AND_W : lMode = CRGN_AND ; break;
468 case RGN_COPY_W : lMode = CRGN_COPY; break;
469 case RGN_DIFF_W : lMode = CRGN_DIFF; break;
470 case RGN_OR_W : lMode = CRGN_OR ; break;
471 case RGN_XOR_W : lMode = CRGN_XOR ; break;
472 default:
473 {
474 SetLastError(ERROR_INVALID_PARAMETER_W);
475 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid parameter", hdc, hrgn1, mode));
476 return ERROR_W;
477 }
478 }
479
480 if(hrgn)
481 {
482 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
483 if(hrgn == HANDLE_OBJ_ERROR) {
484 dprintf(("WARNING: ExtSelectRgn %x %x %d invalid region handle", hdc, hrgn1, mode));
485 SetLastError(ERROR_INVALID_HANDLE_W);
486 return 0;
487 }
488 }
489
490 dprintf(("ExtSelectRgn %x %x %d", hdc, hrgn1, mode));
491 //TODO: metafile recording
492 if(hrgn)
493 {
494 if(!interpretRegionAs(pHps, 0, hrgn, AS_DEVICE) )
495 {
496 return ERROR_W;
497 }
498 }
499 else
500 {
501 //remove clip region
502 GpiSetClipPath(pHps->hps, 0, SCP_RESET);
503 GpiSetClipRegion(pHps->hps, NULLHANDLE, &hrgnCurrent);
504
505 if(hrgnCurrent)
506 GpiDestroyRegion(pHps->hps, hrgnCurrent);
507
508 return NULLREGION_W;
509 }
510
511 GpiSetClipRegion(pHps->hps, NULLHANDLE, &hrgnCurrent);
512
513 if(hrgnCurrent == NULLHANDLE)
514 {
515 lMode = CRGN_COPY;
516 RECTL rectl = {0, 0, 1, 1};
517 hrgnCurrent = GpiCreateRegion(pHps->hps, 1, &rectl);
518 }
519
520 HRGN hrgnSrc1;
521 HRGN hrgnSrc2;
522 if(lMode != CRGN_COPY)
523 {
524 hrgnSrc1 = hrgnCurrent;
525 hrgnSrc2 = pHps->hrgnHDC;
526 }
527 else
528 {
529 hrgnSrc1 = pHps->hrgnHDC;
530 hrgnSrc2 = NULLHANDLE;
531 }
532
533 lComplexity = GpiCombineRegion(pHps->hps, hrgnCurrent, hrgnSrc1, hrgnSrc2, lMode);
534 if (lComplexity != RGN_ERROR)
535 {
536 HRGN hrgnOld;
537 lComplexity = GpiSetClipRegion(pHps->hps, hrgnCurrent, &hrgnOld);
538 SetLastError(ERROR_SUCCESS_W);
539
540 //SvL: Must check if origin changed here. Sometimes happens when
541 // window looses focus. (don't know why....)
542 checkOrigin(pHps);
543
544 if (lComplexity != RGN_ERROR)
545 return lComplexity;
546 }
547 SetLastError(ERROR_SUCCESS_W);
548 return ERROR_W;
549}
550//******************************************************************************
551//******************************************************************************
552ODINFUNCTIONNODBG2(int, GetClipBox, HDC, hdc, PRECT, lpRect)
553{
554 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
555 RECTL rectl;
556 LONG lComplexity;
557 int rc;
558
559 if(!hdc || !lpRect || !pHps) {
560 dprintf(("GDI32: GetClipBox %x %x ERROR_INVALID_PARAMETER", hdc, lpRect));
561 SetLastError(ERROR_INVALID_PARAMETER_W);
562 return ERROR_W;
563 }
564 if(pHps->isPrinter)
565 {
566 lpRect->left = 0;
567 lpRect->top = 0;
568 lpRect->right = GetDeviceCaps( hdc, HORZRES_W);
569 lpRect->bottom = GetDeviceCaps( hdc, VERTRES_W);
570 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
571 convertPMDeviceRectToWinWorldRect(pHps, &rectl);
572
573 rc = SIMPLEREGION_W;
574 }
575 else {
576 lComplexity = GpiQueryClipBox(pHps->hps, &rectl);
577 if(lComplexity == RGN_ERROR)
578 {
579 rc = ERROR_W;
580 }
581 else
582 if(lComplexity == RGN_NULL)
583 {
584 memset(lpRect, 0, sizeof(*lpRect));
585 rc = NULLREGION_W;
586 }
587 else {
588#ifndef INVERT
589 //Convert coordinates from PM to win32
590 if (pHps->yInvert > 0) {
591 LONG temp = pHps->yInvert - rectl.yBottom;
592 rectl.yBottom = pHps->yInvert - rectl.yTop;
593 rectl.yTop = temp;
594 }
595#endif
596 //Convert including/including to including/excluding
597 includeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
598
599 lpRect->left = rectl.xLeft;
600 lpRect->right = rectl.xRight;
601
602 if(rectl.yBottom > rectl.yTop) {
603 lpRect->top = rectl.yTop;
604 lpRect->bottom = rectl.yBottom;
605 }
606 else {
607 lpRect->top = rectl.yBottom;
608 lpRect->bottom = rectl.yTop;
609 }
610
611 rc = (lComplexity == RGN_RECT) ? SIMPLEREGION_W : COMPLEXREGION_W;
612 }
613 }
614// if(lpRect->left == 0 && lpRect->top == 0 && lpRect->right == 0 && lpRect->bottom == 0)
615// DebugInt3();
616 dprintf(("GDI32: GetClipBox of %X returned %d; (%d,%d)(%d,%d)", hdc, rc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
617 return rc;
618}
619//******************************************************************************
620//******************************************************************************
621ODINFUNCTIONNODBG2(int, GetClipRgn, HDC, hdc, HRGN, hrgn)
622{
623 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
624 BOOL success;
625 LONG lComplexity = RGN_RECT;
626 HRGN hrgnClip = NULL, hrgnTemp;
627#ifdef DEBUG
628 HRGN hrgn1 = hrgn;
629#endif
630
631 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
632 if(hrgn == HANDLE_OBJ_ERROR || !pHps) {
633 dprintf(("WARNING: GetClipRgn %x %x invalid handle", hdc, hrgn1));
634 SetLastError(ERROR_INVALID_HANDLE_W);
635 return 0;
636 }
637
638 if(GpiSetClipRegion(pHps->hps, NULL, &hrgnClip) == RGN_ERROR) {
639 dprintf(("WARNING: GetClipRgn GpiSetClipRegion failed! (%x)", WinGetLastError(0)));
640 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
641 return 0;
642 }
643 if(hrgnClip) {
644 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnClip, pHps, NULL)) {
645 dprintf(("WARNING: GetClipRgn setWinDeviceRegionFromPMDeviceRegion failed!"));
646 GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp);
647 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
648 return 0;
649 }
650 if(GpiSetClipRegion(pHps->hps, hrgnClip, &hrgnTemp) == RGN_ERROR )
651 {
652 dprintf(("WARNING: GetClipRgn GpiSetClipRegion failed %x!", WinGetLastError(0)));
653 SetLastError(ERROR_INVALID_PARAMETER_W); //todo right errror
654 return 0;
655 }
656 }
657 else lComplexity = RGN_NULL;
658
659 dprintf(("GetClipRgn %x %x returned %d", hdc, hrgn1, lComplexity != RGN_NULL));
660 SetLastError(ERROR_SUCCESS_W);
661 if(lComplexity == RGN_NULL)
662 return 0;
663 else return 1;
664}
665//******************************************************************************
666//******************************************************************************
667ODINFUNCTIONNODBG5(int, ExcludeClipRect, HDC, hdc, int, left, int, top, int, right, int, bottom)
668{
669 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
670 if(!pHps)
671 {
672 dprintf(("WARNING: ExcludeClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
673 SetLastError(ERROR_INVALID_HANDLE_W);
674 return ERROR_W;
675 }
676
677 LONG lComplexity;
678 RECTL rectl = { left, bottom, right, top };
679
680 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
681 if(rectl.yTop < rectl.yBottom) {
682 ULONG temp = rectl.yBottom;
683 rectl.yBottom = rectl.yTop;
684 rectl.yTop = temp;
685 }
686
687#ifndef INVERT
688 if (pHps->yInvert > 0) {
689 LONG temp = pHps->yInvert - rectl.yBottom;
690 rectl.yBottom = pHps->yInvert - rectl.yTop;
691 rectl.yTop = temp;
692 }
693#endif
694
695 dprintf(("ExcludeClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
696 lComplexity = GpiExcludeClipRectangle(pHps->hps, &rectl);
697 if (lComplexity == RGN_ERROR) {
698 SetLastError(ERROR_INVALID_PARAMETER_W); //TODO: wrong error
699 return ERROR_W;
700 }
701
702 //todo metafile recording
703
704 SetLastError(ERROR_SUCCESS_W);
705 return lComplexity;
706}
707//******************************************************************************
708//******************************************************************************
709ODINFUNCTIONNODBG5(int, IntersectClipRect, HDC, hdc, int, left, int, top, int, right, int, bottom)
710{
711 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
712 LONG lComplexity;
713 BOOL success;
714
715 if(!pHps) {
716 dprintf(("WARNING: IntersectClipRgn %x (%d,%d)(%d,%d) invalid hdc", hdc, left, top, right, bottom));
717 SetLastError(ERROR_INVALID_HANDLE_W);
718 return ERROR_W;
719 }
720 RECTL rectl = { left, bottom, right, top };
721
722 excludeBottomRightPoint(pHps, (PPOINTLOS2)&rectl);
723 if(rectl.yTop < rectl.yBottom) {
724 ULONG temp = rectl.yBottom;
725 rectl.yBottom = rectl.yTop;
726 rectl.yTop = temp;
727 }
728
729#ifndef INVERT
730 //Convert coordinates from PM to win32
731 if (pHps->yInvert > 0) {
732 LONG temp = pHps->yInvert - rectl.yBottom;
733 rectl.yBottom = pHps->yInvert - rectl.yTop;
734 rectl.yTop = temp;
735 }
736#endif
737
738 dprintf(("IntersectClipRgn %x (%d,%d)(%d,%d)", hdc, left, top, right, bottom));
739 lComplexity = GpiIntersectClipRectangle(pHps->hps, &rectl);
740
741 //todo metafile recording
742
743 SetLastError(ERROR_SUCCESS_W);
744 return lComplexity;
745}
746//******************************************************************************
747//******************************************************************************
748ODINFUNCTIONNODBG3(int, OffsetClipRgn, HDC, hdc, int, nXOffset, int, nYOffset )
749{
750 BOOL success;
751 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
752 LONG lComplexity;
753
754 if(!pHps) {
755 dprintf(("OffsetClipRgn %x (%d,%d) invalid hdc", hdc, nXOffset, nYOffset));
756 SetLastError(ERROR_INVALID_HANDLE_W);
757 return ERROR_W;
758 }
759
760 dprintf(("OffsetClipRgn %x (%d,%d)", hdc, nXOffset, nYOffset));
761 POINTL pointl = { nXOffset, nYOffset };
762#ifndef INVERT
763 if (pHps->yInvert > 0) {
764 pointl.y = pHps->yInvert - pointl.y;
765 }
766#endif
767
768 lComplexity = GpiOffsetClipRegion(pHps->hps, &pointl);
769
770 //todo metafile recording
771
772 SetLastError(ERROR_SUCCESS_W);
773 return lComplexity;
774}
775//******************************************************************************
776//******************************************************************************
777ODINFUNCTIONNODBG4(HRGN, CreatePolyPolygonRgn, const POINT * , lppt, const int *, pPolyCount, int, nCount, int, fnPolyFillMode)
778{
779 LONG flMode;
780
781 switch(fnPolyFillMode)
782 {
783 case ALTERNATE_W:
784 flMode = POLYGON_ALTERNATE;
785 break;
786 case WINDING_W:
787 flMode = POLYGON_WINDING;
788 break;
789 default:
790 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
791 SetLastError(ERROR_INVALID_PARAMETER_W);
792 return 0;
793 }
794
795 if(nCount < 1)
796 {
797 dprintf(("WARNING: CreatePolyPolygonRgn %x %x %d %d invalid parameter", lppt, pPolyCount, nCount, fnPolyFillMode));
798 SetLastError(ERROR_INVALID_PARAMETER_W);
799 return 0;
800 }
801
802 PPOLYGON pPolygon = new POLYGON[nCount];
803 if(!pPolygon) {
804 dprintf(("ERROR: CreatePolyPolygonRgn: out of memory!!"));
805 SetLastError(ERROR_OUTOFMEMORY_W);
806 return 0;
807 }
808 dprintf(("CreatePolyPolygonRgn %x %x %d %d", lppt, pPolyCount, nCount, fnPolyFillMode));
809
810 PPOINTL pPointl = (PPOINTL)lppt+1; // skip first point
811 for (int x=0; x < nCount; x++) {
812 pPolygon[x].ulPoints = (x == 0) ? pPolyCount[x] - 1 : pPolyCount[x];
813 pPolygon[x].aPointl = pPointl;
814 pPointl += pPolygon[x].ulPoints;
815 }
816 GpiMove(hpsRegion, (PPOINTL)lppt);
817 HRGN hrgn = GpiCreatePolygonRegion(hpsRegion, nCount, pPolygon, POLYGON_BOUNDARY | flMode);
818
819 delete[] pPolygon;
820
821 if(!hrgn) {
822 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
823 return 0;
824 }
825
826 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
827 SetLastError(ERROR_OUTOFMEMORY_W);
828 return 0;
829 }
830 SetLastError(ERROR_SUCCESS_W);
831 return hrgn;
832}
833//******************************************************************************
834//******************************************************************************
835ODINFUNCTIONNODBG4(HRGN, CreateRectRgn, int, left, int, top, int, right, int, bottom)
836{
837 HRGN hrgn;
838 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
839
840 hrgn = GpiCreateRegion(hpsRegion, 1, &rectl);
841 if(!hrgn) {
842 dprintf(("WARNING: CreateRectRgn: GpiCreateRectRegion failed! %x", WinGetLastError(0)));
843 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
844 return 0;
845 }
846
847 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
848 SetLastError(ERROR_OUTOFMEMORY_W);
849 return 0;
850 }
851 dprintf(("CreateRectRegion (%d,%d)(%d,%d) returned %x", left, top, right, bottom, hrgn));
852 SetLastError(ERROR_SUCCESS_W);
853 return hrgn;
854}
855//******************************************************************************
856//******************************************************************************
857ODINFUNCTIONNODBG1(HRGN, CreateRectRgnIndirect, const RECT *, lprc)
858{
859 return CreateRectRgn(lprc->left, lprc->top, lprc->right, lprc->bottom);
860}
861//******************************************************************************
862//******************************************************************************
863ODINFUNCTIONNODBG6(HRGN, CreateRoundRectRgn, int, left, int, top, int, right, int, bottom, int, nWidthEllipse, int, nHeightEllipse)
864{
865 HRGN hrgn;
866 RECTL rectl = { left, top < bottom ? top : bottom, right, top < bottom ? bottom : top };
867
868 PPOINTL pPointl = (PPOINTL)&rectl;
869
870 GpiMove(hpsRegion, &pPointl[0]);
871 hrgn = GpiCreateRoundRectRegion(hpsRegion, &pPointl[1], labs(nWidthEllipse), labs(nHeightEllipse));
872
873 if(!hrgn) {
874 SetLastError(ERROR_INVALID_PARAMETER_W); //todo: not right
875 dprintf(("WARNING: CreateRoundRectRgn: GpiCreateRoundRectRegion failed! %x", WinGetLastError(0)));
876 return 0;
877 }
878
879 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
880 SetLastError(ERROR_OUTOFMEMORY_W);
881 return 0;
882 }
883 dprintf(("CreateRoundRectRegion (%d,%d)(%d,%d) (%d,%d) returned %x", left, top, right, bottom, nWidthEllipse, nHeightEllipse, hrgn));
884 SetLastError(ERROR_SUCCESS_W);
885 return hrgn;
886}
887//******************************************************************************
888//******************************************************************************
889ODINFUNCTIONNODBG3(HRGN, ExtCreateRegion, const XFORM_W *, pXform, DWORD, count, const RGNDATA *, pData)
890{
891 HRGN hrgn;
892
893 if(!pData || count < (sizeof(RGNDATAHEADER) + pData->rdh.nCount * sizeof(RECT))) {
894 dprintf(("WARNING: ExtCreateRegion %x %d %x; invalid parameter", pXform, count, pData));
895 SetLastError(ERROR_INVALID_PARAMETER_W);
896 return 0;
897 }
898
899 PRECTL pRectl = new RECTL[pData->rdh.nCount];
900 PRECT pDataRects = (PRECT)pData->Buffer;
901 for(int i=0; i < pData->rdh.nCount; i++) {
902 MapWin32ToOS2Rect(pDataRects[i], pRectl[i]);
903 }
904
905 BOOL doShear = pXform && (pXform->eM12 || pXform->eM21);
906 HPS hpsTemp = NULLHANDLE;
907
908 dprintf(("ExtCreateRegion %x %d %x", pXform, count, pData));
909 if(doShear) {
910 hpsTemp = WinGetPS(HWND_DESKTOP);
911 GpiBeginPath(hpsTemp, 1);
912
913 MATRIXLF matrixlf;
914 matrixlf.fxM11 = pXform->eM11 * (float)0x10000;
915 matrixlf.fxM12 = pXform->eM12 * (float)0x10000;
916 matrixlf.lM13 = 0;
917 matrixlf.fxM21 = pXform->eM21 * (float)0x10000;
918 matrixlf.fxM22 = pXform->eM22 * (float)0x10000;
919 matrixlf.lM23 = 0;
920 matrixlf.lM31 = pXform->eDx;
921 matrixlf.lM32 = pXform->eDy;
922 matrixlf.lM33 = 1;
923
924 GpiSetModelTransformMatrix(hpsTemp, 9, &matrixlf, TRANSFORM_REPLACE);
925 }
926
927 for(i=0; i < pData->rdh.nCount; i++)
928 {
929 LONG temp = pRectl[i].yTop;
930 pRectl[i].yTop = pRectl[i].yBottom;
931 pRectl[i].yBottom = temp;
932
933 if(pXform)
934 {
935 PPOINTL pPointl = ((PPOINTL)&pRectl[i]);
936
937 if (doShear) {
938 GpiMove(hpsTemp, pPointl);
939 GpiBox(hpsTemp, DRO_OUTLINE, pPointl+1, 0, 0);
940 }
941 else
942 {
943 for(int j=0; j < 2; j++) {
944 pPointl[j].x = (pXform->eM11 * (float)pPointl[j].x) + (pXform->eM12 * (float)pPointl[j].y) + pXform->eDx;
945 pPointl[j].y = (pXform->eM21 * (float)pPointl[j].x) + (pXform->eM22 * (float)pPointl[j].y) + pXform->eDy;
946 }
947
948 PRECTL pRectlT = (PRECTL)pPointl;
949 if (pRectlT->xLeft > pRectlT->xRight) {
950 LONG temp = pRectlT->xLeft;
951 pRectlT->xLeft = pRectlT->xRight;
952 pRectlT->xRight = temp;
953 }
954 if (pRectlT->yBottom > pRectlT->yTop) {
955 LONG temp = pRectlT->yBottom;
956 pRectlT->yBottom = pRectlT->yTop;
957 pRectlT->yTop = temp;
958 }
959 }
960 }
961 }
962
963 if(doShear) {
964 GpiEndPath(hpsTemp);
965 hrgn = GpiPathToRegion(hpsTemp, 1, FPATH_WINDING);
966
967 if(pRectl)
968 delete[] pRectl;
969
970 if(hrgn == 0) {
971 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
972 SetLastError(ERROR_INVALID_PARAMETER_W);
973 return 0;
974 }
975 WinReleasePS(hpsTemp);
976 }
977 else {
978 hrgn = GpiCreateRegion(hpsRegion, pData->rdh.nCount, pRectl);
979 if(pRectl)
980 delete[] pRectl;
981
982 if(hrgn == 0) {
983 dprintf(("WARNING: ExtCreateRegion GpiCreateRegion failed! (%x)", WinGetLastError(0)));
984 SetLastError(ERROR_INVALID_PARAMETER_W);
985 return 0;
986 }
987 }
988
989 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
990 SetLastError(ERROR_OUTOFMEMORY_W);
991 return 0;
992 }
993 SetLastError(ERROR_SUCCESS_W);
994 return hrgn;
995}
996//******************************************************************************
997//******************************************************************************
998ODINFUNCTIONNODBG4(HRGN, CreateEllipticRgn, int, left, int, top, int, right, int, bottom)
999{
1000 HRGN hrgn;
1001
1002 RECTL rectl = { left,
1003 top < bottom ? top : bottom,
1004 right,
1005 top < bottom ? bottom : top };
1006
1007 dprintf(("CreateEllipticRgn (%d,%d)(%d,%d)", left, top, right, bottom));
1008 hrgn = GpiCreateEllipticRegion(hpsRegion, &rectl);
1009
1010 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
1011 SetLastError(ERROR_OUTOFMEMORY_W);
1012 return 0;
1013 }
1014 SetLastError(ERROR_SUCCESS_W);
1015 return hrgn;
1016}
1017//******************************************************************************
1018//******************************************************************************
1019ODINFUNCTIONNODBG1(HRGN, CreateEllipticRgnIndirect, const RECT *, pRect)
1020{
1021 return CreateEllipticRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);
1022}
1023//******************************************************************************
1024//******************************************************************************
1025ODINFUNCTIONNODBG3(HRGN, CreatePolygonRgn, const POINT *, lppt, int, cPoints, int, fnPolyFillMode)
1026{
1027 HRGN hrgn;
1028 LONG flMode;
1029
1030 if(!lppt || cPoints < 2) {
1031 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1032 SetLastError(ERROR_INVALID_PARAMETER_W);
1033 return 0;
1034 }
1035
1036 switch (fnPolyFillMode)
1037 {
1038 case ALTERNATE_W :
1039 flMode = POLYGON_ALTERNATE;
1040 break;
1041 case WINDING_W :
1042 flMode = POLYGON_WINDING;
1043 break;
1044 default:
1045 dprintf(("WARNING: CreatePolygonRgn %x %d %d invalid parameter", lppt, cPoints, fnPolyFillMode));
1046 SetLastError(ERROR_INVALID_PARAMETER_W);
1047 return 0;
1048 }
1049
1050 dprintf(("CreatePolygonRgn %x %d %d", lppt, cPoints, fnPolyFillMode));
1051
1052
1053 POLYGON polygon;
1054 polygon.ulPoints = cPoints - 1;
1055 polygon.aPointl = (PPOINTL)(lppt + 1);
1056
1057 GpiMove(hpsRegion, (PPOINTL)lppt);
1058 hrgn = GpiCreatePolygonRegion(hpsRegion, 1, &polygon, POLYGON_BOUNDARY | flMode);
1059
1060 if(ObjAllocateHandle(&hrgn, hrgn, GDIOBJ_REGION) == FALSE) {
1061 SetLastError(ERROR_OUTOFMEMORY_W);
1062 return 0;
1063 }
1064 SetLastError(ERROR_SUCCESS_W);
1065 return hrgn;
1066}
1067//******************************************************************************
1068//******************************************************************************
1069ODINFUNCTIONNODBG4(int, CombineRgn, HRGN, hrgnDest, HRGN, hrgnSrc1, HRGN, hrgnSrc2, int, combineMode)
1070{
1071 ULONG lComplexity;
1072 LONG mode;
1073#ifdef DEBUG
1074 HRGN hrgn1 = hrgnDest;
1075 HRGN hrgn2 = hrgnSrc1;
1076 HRGN hrgn3 = hrgnSrc2;
1077#endif
1078
1079 switch(combineMode) {
1080 case RGN_AND_W:
1081 mode = CRGN_AND;
1082 break;
1083 case RGN_COPY_W:
1084 mode = CRGN_COPY;
1085 break;
1086 case RGN_DIFF_W:
1087 mode = CRGN_DIFF;
1088 break;
1089 case RGN_OR_W:
1090 mode = CRGN_OR;
1091 break;
1092 case RGN_XOR_W:
1093 mode = CRGN_XOR;
1094 break;
1095 default:
1096 dprintf(("WARNING: CombineRgn %x %x %x %d; invalid mode!", hrgnDest, hrgnSrc1, hrgnSrc2, combineMode));
1097 SetLastError(ERROR_INVALID_PARAMETER_W);
1098 return ERROR_W;
1099 }
1100
1101 hrgnDest = ObjGetHandleData(hrgnDest, GDIOBJ_REGION);
1102 hrgnSrc1 = ObjGetHandleData(hrgnSrc1, GDIOBJ_REGION);
1103 hrgnSrc2 = ObjGetHandleData(hrgnSrc2, GDIOBJ_REGION);
1104 if(hrgnDest == HANDLE_OBJ_ERROR || hrgnSrc1 == HANDLE_OBJ_ERROR || (hrgnSrc2 == HANDLE_OBJ_ERROR && combineMode != RGN_COPY_W)) {
1105 dprintf(("WARNING: CombineRgn %x %x %x %d invalid region", hrgn1, hrgn2, hrgn3, combineMode));
1106 SetLastError(ERROR_INVALID_HANDLE_W);
1107 return ERROR_W;
1108 }
1109
1110 lComplexity = GpiCombineRegion(hpsRegion, hrgnDest, hrgnSrc1, hrgnSrc2, mode);
1111 if(lComplexity == RGN_ERROR) {
1112 dprintf(("WARNING: CombineRgn %x %x %x %d GpiCombineRegion failed (%x)", hrgn1, hrgn2, hrgn3, mode, WinGetLastError(0)));
1113 SetLastError(ERROR_INVALID_HANDLE_W);
1114 return ERROR_W;
1115 }
1116 dprintf(("CombineRgn %x %x %x %d", hrgn1, hrgn2, hrgn3, mode));
1117 SetLastError(ERROR_SUCCESS_W);
1118 return lComplexity;
1119}
1120//******************************************************************************
1121//******************************************************************************
1122ODINFUNCTIONNODBG2(BOOL, EqualRgn, HRGN, hrgn1, HRGN, hrgn2)
1123{
1124 LONG lEquality;
1125#ifdef DEBUG
1126 HRGN hrgnt1 = hrgn1;
1127 HRGN hrgnt2 = hrgn2;
1128#endif
1129
1130 hrgn1 = ObjGetHandleData(hrgn1, GDIOBJ_REGION);
1131 hrgn2 = ObjGetHandleData(hrgn2, GDIOBJ_REGION);
1132 if(hrgn1 == HANDLE_OBJ_ERROR || hrgn2 == HANDLE_OBJ_ERROR) {
1133 dprintf(("WARNING: EqualRgn %x %x invalid region", hrgnt1, hrgnt2));
1134 SetLastError(ERROR_INVALID_HANDLE_W);
1135 return FALSE;
1136 }
1137 lEquality = GpiEqualRegion(hpsRegion, hrgn1, hrgn2);
1138
1139 dprintf(("EqualRgn %x %x = %d", hrgnt1, hrgnt2, lEquality));
1140 SetLastError(ERROR_SUCCESS_W);
1141
1142 if(lEquality == EQRGN_EQUAL)
1143 return TRUE;
1144 else
1145 if(lEquality == EQRGN_NOTEQUAL)
1146 return FALSE;
1147 else {
1148 return FALSE;
1149 }
1150}
1151//******************************************************************************
1152//******************************************************************************
1153ODINFUNCTIONNODBG5(BOOL, SetRectRgn, HRGN, hrgn, int, left, int, top, int, right, int, bottom)
1154{
1155 BOOL result = FALSE;
1156#ifdef DEBUG
1157 HRGN hrgn1 = hrgn;
1158#endif
1159
1160 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1161 if(hrgn == HANDLE_OBJ_ERROR) {
1162 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) invalid region handle", hrgn1, left, top, right, bottom));
1163 SetLastError(ERROR_INVALID_HANDLE_W);
1164 return 0;
1165 }
1166 RECTL rectl = { left, top, right, bottom }; //reversed y coordinates
1167 if(GpiSetRegion(hpsRegion, hrgn, 1, &rectl)) {
1168 dprintf(("SetRectRgn %x (%d,%d)(%d,%d)", hrgn1, left, top, right, bottom));
1169 return TRUE;
1170 }
1171 dprintf(("WARNING: SetRectRgn %x (%d,%d)(%d,%d) GpiSetRegion failed %x", hrgn1, left, top, right, bottom, WinGetLastError(0)));
1172 return FALSE;
1173}
1174//******************************************************************************
1175//NOTE: depends on hps inversion
1176//******************************************************************************
1177ODINFUNCTIONNODBG3(ULONG, GetRegionData, HRGN, hrgn, ULONG, count, PRGNDATA, pData)
1178{
1179#ifdef DEBUG
1180 HRGN hrgn1 = hrgn;
1181#endif
1182
1183 if(!count && pData)
1184 {
1185 dprintf(("WARNING: GetRegionData %x %d %x; invalid parameter", hrgn1, count, pData));
1186 SetLastError(ERROR_INVALID_PARAMETER_W);
1187 return 0;
1188 }
1189 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1190 if(hrgn == HANDLE_OBJ_ERROR) {
1191 dprintf(("WARNING: GetRegionData %x %d %x; invalid region handle", hrgn1, count, pData));
1192 SetLastError(ERROR_INVALID_HANDLE_W);
1193 return 0;
1194 }
1195 RGNRECT rgnRect;
1196 rgnRect.ircStart = 1;
1197 rgnRect.crc = 0;
1198 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT;
1199 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, NULL))
1200 {
1201 dprintf(("WARNING: GetRegionData %x %d %x: GpiQueryRegionRects failed! (%x)", hrgn1, count, pData, WinGetLastError(0)));
1202 return 0;
1203 }
1204
1205 dprintf(("GetRegionData %x %d %x", hrgn1, count, pData));
1206
1207 ULONG bufSizeNeeded = rgnRect.crcReturned * sizeof(RECT) + sizeof (RGNDATAHEADER);
1208
1209 if(pData && (count >= (sizeof(RGNDATAHEADER) + rgnRect.crcReturned * sizeof(RECT))))
1210 {
1211 //we actually need to flip the top & bottom values, but as the layout of the PM RECTL and
1212 //Win32 RECT have exactly those two members reversed, we don't do this for the returned
1213 //rectangles (more efficient)
1214 PRECTL pRectl = (PRECTL)pData->Buffer;
1215 rgnRect.crc = rgnRect.crcReturned;
1216 if(!GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, pRectl))
1217 {
1218 dprintf(("WARNING: GetRegionData: GpiQueryRegionRects failed! (%x)", WinGetLastError(0)));
1219 return 0;
1220 }
1221
1222 RECTL boundRect;
1223 GpiQueryRegionBox(hpsRegion, hrgn, &boundRect); // no need to check rc
1224
1225 pData->rdh.dwSize = sizeof(pData->rdh);
1226 pData->rdh.iType = RDH_RECTANGLES_W; // one and only possible value
1227 pData->rdh.nCount = rgnRect.crcReturned;
1228 pData->rdh.nRgnSize = rgnRect.crcReturned * sizeof(RECT);
1229
1230 //flip top & bottom for bounding rectangle (not really necessary; but cleaner coding)
1231 LONG temp = boundRect.yTop;
1232 boundRect.yTop = boundRect.yBottom;
1233 boundRect.yBottom = temp;
1234 MapOS2ToWin32Rect(boundRect, pData->rdh.rcBound);
1235 }
1236
1237 //return size needed
1238 return bufSizeNeeded;
1239}
1240//******************************************************************************
1241//******************************************************************************
1242ODINFUNCTIONNODBG2(int, GetRgnBox, HRGN, hrgn, PRECT, pRect)
1243{
1244 BOOL success;
1245 LONG lComplexity;
1246#ifdef DEBUG
1247 HRGN hrgn1 = hrgn;
1248#endif
1249
1250 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1251 if(hrgn == HANDLE_OBJ_ERROR) {
1252 dprintf(("WARNING: GetRgnBox %x %x invalid region!", hrgn1, pRect));
1253 SetLastError(ERROR_INVALID_HANDLE_W);
1254 return FALSE;
1255 }
1256
1257 RECTL rectl;
1258 lComplexity = GpiQueryRegionBox(hpsRegion, hrgn, &rectl);
1259 if(lComplexity != RGN_ERROR)
1260 {
1261 //no conversion required, just flip top & bottom
1262 ULONG temp = rectl.yBottom;
1263 rectl.yBottom = rectl.yTop;
1264 rectl.yTop = temp;
1265
1266 MapOS2ToWin32Rect(rectl, *pRect);
1267 }
1268 else {
1269 lComplexity = ERROR_W;
1270 dprintf(("WARNING: GetRgnBox error in region!"));
1271 }
1272 dprintf(("GetRgnBox %x (%d,%d)(%d,%d)", hrgn1, pRect->left, pRect->bottom, pRect->right, pRect->top));
1273
1274 SetLastError(ERROR_SUCCESS_W);
1275 return lComplexity;
1276}
1277//******************************************************************************
1278//******************************************************************************
1279ODINFUNCTIONNODBG2(BOOL, InvertRgn, HDC, hdc, HRGN, hrgn)
1280{
1281#ifdef DEBUG
1282 HRGN hrgn1 = hrgn;
1283#endif
1284 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1285
1286 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1287 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1288 dprintf(("WARNING: InvertRgn %x %x invalid handle!", hdc, hrgn));
1289 SetLastError(ERROR_INVALID_HANDLE_W);
1290 return FALSE;
1291 }
1292 //todo metafile recording
1293
1294 dprintf(("InvertRgn %x %x", hdc, hrgn1));
1295
1296 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1297
1298 LONG lHits = GPI_ERROR;
1299 HRGN hrgnOld;
1300 LONG lComplexity ;
1301 RECTL boundingRect; // this gets a rectangle in world cordinates!
1302
1303 lComplexity = GpiQueryRegionBox(pHps->hps, pHps->hrgnHDC, &boundingRect);
1304 if(lComplexity != RGN_ERROR)
1305 {
1306 lComplexity = GpiSetClipRegion(pHps->hps, pHps->hrgnHDC, &hrgnOld);
1307 if(lComplexity != RGN_ERROR)
1308 {
1309 RECTL rectls[2];
1310 rectls[0] = boundingRect;
1311 rectls[1] = boundingRect;
1312 lHits = GpiBitBlt(pHps->hps, NULL, 3, (PPOINTL)rectls,
1313 ROP_DSTINVERT, 0);
1314
1315 /* Restore the old region */
1316 GpiSetClipRegion(pHps->hps, hrgnOld, &hrgnOld);
1317 }
1318 }
1319
1320 if(lHits == GPI_ERROR || lComplexity == RGN_ERROR)
1321 {
1322 dprintf(("WARNING: InvertRgn error during Gpi operation (%x) (%d,%d)", WinGetLastError(0), lHits, lComplexity));
1323 return FALSE;
1324 }
1325
1326 return TRUE;
1327}
1328//******************************************************************************
1329//******************************************************************************
1330ODINFUNCTIONNODBG3(int, OffsetRgn, HRGN, hrgn, int, xOffset, int, yOffset)
1331{
1332 LONG lComplexity;
1333#ifdef DEBUG
1334 HRGN hrgn1 = hrgn;
1335#endif
1336
1337 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1338 if(hrgn == HANDLE_OBJ_ERROR) {
1339 dprintf(("WARNING: OffsetRgn %x %d %d invalid handle!", hrgn, xOffset, yOffset));
1340 SetLastError(ERROR_INVALID_HANDLE_W);
1341 return ERROR_W;
1342 }
1343 dprintf(("OffsetRgn %x %d %d", hrgn1, xOffset, yOffset));
1344
1345 POINTL ptlOffset = {xOffset, yOffset};
1346 GpiOffsetRegion(hpsRegion, hrgn, &ptlOffset);
1347
1348 RECTL rectl[8];
1349 RGNRECT rgnRect;
1350 rgnRect.ircStart = 1;
1351 rgnRect.crc = 8;
1352 rgnRect.ulDirection = RECTDIR_LFRT_TOPBOT; // doesn't make a difference
1353 if(GpiQueryRegionRects(hpsRegion, hrgn, NULL, &rgnRect, &rectl[0]))
1354 {
1355 switch (rgnRect.crcReturned) {
1356 case 0:
1357 lComplexity = NULLREGION_W;
1358 break;
1359 case 1:
1360 lComplexity = SIMPLEREGION_W;
1361 break;
1362 default:
1363 lComplexity = COMPLEXREGION_W;
1364 break;
1365 }
1366 }
1367 else {
1368 lComplexity = ERROR_W;
1369 dprintf(("WARNING: OffsetRgn error in region! (%x)", WinGetLastError(0)));
1370 }
1371
1372 SetLastError(ERROR_SUCCESS_W);
1373
1374 return lComplexity;
1375}
1376//******************************************************************************
1377//******************************************************************************
1378ODINFUNCTIONNODBG5(BOOL, FrameRgn, HDC, hdc, HRGN, hrgn, HBRUSH, hBrush, int, width, int, height)
1379{
1380 HBRUSH hbrushRestore = 0;
1381#ifdef DEBUG
1382 HRGN hrgn1 = hrgn;
1383#endif
1384 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1385
1386 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1387 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1388 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid handle!", hdc, hrgn, hBrush, width, height));
1389 SetLastError(ERROR_INVALID_HANDLE_W);
1390 return FALSE;
1391 }
1392
1393 width = abs(width);
1394 height = abs(height);
1395
1396 if(pHps->lastBrushKey != (UINT)hBrush)
1397 {
1398 hbrushRestore = SelectObject(hdc, hBrush);
1399 if(!hbrushRestore)
1400 {
1401 dprintf(("WARNING: FrameRgn %x %x %x (%d,%d) invalid brush!", hdc, hrgn, hBrush, width, height));
1402 SetLastError(ERROR_INVALID_HANDLE_W);
1403 return FALSE;
1404 }
1405 }
1406 dprintf(("FrameRgn %x %x %x (%d,%d)", hdc, hrgn1, hBrush, width, height));
1407 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1408
1409 SIZEL thickness = { width, height };
1410 LONG lHits = GpiFrameRegion(pHps->hps, pHps->hrgnHDC, &thickness);
1411
1412 SetLastError(ERROR_SUCCESS_W);
1413
1414 // Restore the brush if necessary
1415 if(hbrushRestore)
1416 SelectObject(hdc, hbrushRestore);
1417
1418 //todo metafile recording
1419 return (lHits != GPI_ERROR);
1420}
1421//******************************************************************************
1422//******************************************************************************
1423ODINFUNCTIONNODBG3(BOOL, FillRgn, HDC, hdc, HRGN, hrgn, HBRUSH, hBrush)
1424{
1425 BOOL success;
1426 HBRUSH hbrushRestore = 0;
1427#ifdef DEBUG
1428 HRGN hrgn1 = hrgn;
1429#endif
1430
1431 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1432
1433 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1434 if(!pHps || hrgn == HANDLE_OBJ_ERROR) {
1435 dprintf(("WARNING: FillRgn %x %x %x invalid handle!", hdc, hrgn1, hBrush));
1436 SetLastError(ERROR_INVALID_HANDLE_W);
1437 return FALSE;
1438 }
1439
1440 if(pHps->lastBrushKey != (UINT)hBrush)
1441 {
1442 hbrushRestore = SelectObject(hdc, hBrush);
1443 if (!hbrushRestore)
1444 {
1445 dprintf(("WARNING: FillRgn %x %x %x invalid brush!", hdc, hrgn1, hBrush));
1446 SetLastError(ERROR_INVALID_HANDLE_W);
1447 return FALSE;
1448 }
1449 }
1450 dprintf(("FillRgn %x %x %x", hdc, hrgn1, hBrush));
1451
1452 interpretRegionAs(pHps, NULL, hrgn, AS_WORLD);
1453
1454 success = GpiPaintRegion(pHps->hps, pHps->hrgnHDC);
1455
1456 //todo metafile recording
1457
1458 /* Restore the brush if necessary */
1459 if(hbrushRestore)
1460 SelectObject(hdc, hbrushRestore);
1461
1462 return(success);
1463}
1464//******************************************************************************
1465//******************************************************************************
1466ODINFUNCTIONNODBG2(BOOL, PaintRgn, HDC, hdc, HRGN, hrgn)
1467{
1468 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1469 if(!pHps)
1470 {
1471 SetLastError(ERROR_INVALID_HANDLE_W);
1472 return FALSE;
1473 }
1474
1475 return FillRgn(hdc, hrgn, (HBRUSH) pHps->lastBrushKey);
1476}
1477//******************************************************************************
1478//******************************************************************************
1479ODINFUNCTIONNODBG3(BOOL, PtInRegion, HRGN, hrgn, int, x, int, y)
1480{
1481 BOOL success;
1482 LONG lInside;
1483#ifdef DEBUG
1484 HRGN hrgn1 = hrgn;
1485#endif
1486
1487 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1488 if(hrgn == HANDLE_OBJ_ERROR) {
1489 dprintf(("WARNING: PtInRgn %x (%d,%d) invalid region!", hrgn1, x, y));
1490 SetLastError(ERROR_INVALID_HANDLE_W);
1491 return FALSE;
1492 }
1493
1494 POINTL pointl = {x,y};
1495 lInside = GpiPtInRegion(hpsRegion, hrgn, &pointl);
1496 if(lInside == PRGN_ERROR) {
1497 success = FALSE;
1498 }
1499 else success = TRUE;
1500
1501 SetLastError(ERROR_SUCCESS_W);
1502
1503 dprintf(("PtInRgn %x (%d,%d) returned %d", hrgn1, x, y, (success && lInside == PRGN_INSIDE) ? 1 : 0));
1504
1505 if(success && lInside == PRGN_INSIDE)
1506 return TRUE;
1507 else
1508 return FALSE;
1509}
1510//******************************************************************************
1511//******************************************************************************
1512ODINFUNCTIONNODBG2(BOOL, RectInRegion, HRGN, hrgn, const RECT *, pRect)
1513{
1514 BOOL success;
1515 LONG lInside;
1516#ifdef DEBUG
1517 HRGN hrgn1 = hrgn;
1518#endif
1519
1520 if(!pRect) {
1521 dprintf(("WARNING: RectInRgn %x %x invalid parameter!", hrgn1, pRect));
1522 SetLastError(ERROR_INVALID_PARAMETER_W);
1523 return FALSE;
1524 }
1525 hrgn = ObjGetHandleData(hrgn, GDIOBJ_REGION);
1526 if(hrgn == HANDLE_OBJ_ERROR) {
1527 dprintf(("WARNING: RectInRgn %x %x invalid region", hrgn1, pRect));
1528 SetLastError(ERROR_INVALID_HANDLE_W);
1529 return FALSE;
1530 }
1531
1532 RECTL rectl;
1533 MapWin32ToOS2Rect(*pRect, rectl);
1534 //switch bottom & top
1535 UINT temp = rectl.yBottom;
1536 rectl.yBottom = rectl.yTop;
1537 rectl.yTop = temp;
1538
1539 lInside = GpiRectInRegion(hpsRegion, hrgn, &rectl);
1540 if(lInside == RRGN_ERROR) {
1541 success = FALSE;
1542 }
1543 else success = TRUE;
1544
1545 SetLastError(ERROR_SUCCESS_W);
1546
1547 dprintf(("RectInRgn %x %x returned %d", hrgn1, pRect, (success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL)) ? 1 : 0));
1548
1549 if(success && (lInside == RRGN_INSIDE || lInside == RRGN_PARTIAL))
1550 return TRUE;
1551 else
1552 return FALSE;
1553}
1554//******************************************************************************
1555//Returned region in device coordinates (undocumented behaviour)
1556//******************************************************************************
1557ODINFUNCTIONNODBG1(HRGN, PathToRegion, HDC, hdc)
1558{
1559 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
1560 if(!pHps)
1561 {
1562 dprintf(("WARNING: PathToRegion %x; invalid hdc!", hdc));
1563 SetLastError(ERROR_INVALID_HANDLE_W);
1564 return NULLHANDLE;
1565 }
1566
1567 HRGN hrgn, hrgnTemp, hrgnwin;
1568
1569 dprintf(("GDI32: PathToRegion %x", hdc));
1570
1571 hrgnTemp = GpiPathToRegion(pHps->hps, 1, (pHps->polyFillMode == ALTERNATE_W) ? FPATH_ALTERNATE : FPATH_WINDING);
1572 if(hrgnTemp == NULLHANDLE)
1573 goto error;
1574
1575 hrgnwin = CreateRectRgn(1, 1, 2, 2);
1576 hrgn = ObjGetHandleData(hrgnwin, GDIOBJ_REGION);
1577 if(hrgn == HANDLE_OBJ_ERROR) {
1578 dprintf(("WARNING: PathToRegion invalid region", hrgnwin));
1579 SetLastError(ERROR_INVALID_HANDLE_W);
1580 return NULLHANDLE;
1581 }
1582
1583 if(!setWinDeviceRegionFromPMDeviceRegion(hrgn, hrgnTemp, pHps, NULL))
1584 goto error;
1585
1586 GpiDestroyRegion(pHps->hps, hrgnTemp);
1587
1588 return hrgnwin;
1589
1590error:
1591 if(hrgnwin)
1592 DeleteObject(hrgnwin);
1593
1594 SetLastError(ERROR_INVALID_HANDLE_W); //todo right error
1595 return NULLHANDLE;
1596}
1597//******************************************************************************
1598//Needs wrapper as this file includes os2.h!!
1599//******************************************************************************
1600ODINFUNCTIONNODBG1(BOOL, OSLibDeleteRegion, HANDLE, hRegion)
1601{
1602 if(GpiDestroyRegion(hpsRegion, hRegion) == FALSE) {
1603 dprintf(("WARNING: OSLibDeleteRegion %x; GpiDestroyRegion failed (%x)", hRegion, WinGetLastError(0)));
1604 }
1605 return (0);
1606}
1607/*****************************************************************************
1608 * Name : int GetMetaRgn
1609 * Purpose : The GetMetaRgn function retrieves the current metaregion for
1610 * the specified device context.
1611 * Parameters: HDC hdc handle of device context
1612 * HRGN hrgn handle of region
1613 * Variables :
1614 * Result : 0 / 1
1615 * Remark :
1616 * Status : UNTESTED STUB
1617 *
1618 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1619 *****************************************************************************/
1620
1621ODINFUNCTIONNODBG2(int, GetMetaRgn, HDC, hdc, HRGN, hrgn)
1622{
1623 dprintf(("GDI32: GetMetaRgn(%08xh, %08xh) not implemented.\n",
1624 hdc,
1625 hrgn));
1626
1627 SetLastError(ERROR_SUCCESS_W);
1628 return (0);
1629}
1630/*****************************************************************************
1631 * Name : int SetMetaRgn
1632 * Purpose : The SetMetaRgn function intersects the current clipping region
1633 * for the specified device context with the current metaregion
1634 * and saves the combined region as the new metaregion for the
1635 * specified device context. The clipping region is reset to a null region.
1636 * Parameters: HDC hdc handle of device context
1637 * Variables :
1638 * Result : TRUE / FALSE
1639 * Remark :
1640 * Status : UNTESTED STUB
1641 *
1642 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1643 *****************************************************************************/
1644
1645ODINFUNCTIONNODBG1(BOOL, SetMetaRgn, HDC, hdc)
1646{
1647 dprintf(("GDI32: SetMetaRgn(%08xh) not implemented.\n",
1648 hdc));
1649
1650 SetLastError(ERROR_SUCCESS_W);
1651 return (NULLREGION_W);
1652}
1653//******************************************************************************
1654//******************************************************************************
Note: See TracBrowser for help on using the repository browser.