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

Last change on this file since 9388 was 9388, checked in by sandervl, 23 years ago

PF: FillRgn fix for DIB sections:

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