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

Last change on this file since 3709 was 3709, checked in by sandervl, 25 years ago

GetClipBox bugfix

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