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

Last change on this file since 8266 was 7800, checked in by sandervl, 24 years ago

minor loging update

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