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

Last change on this file since 10140 was 10140, checked in by sandervl, 22 years ago

minor update

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