msvcrt/tests: Test _dup2 for failure when second arg is negative.
[wine] / dlls / wineps.drv / clipping.c
1 /*
2  *      PostScript clipping functions
3  *
4  *      Copyright 1999  Luc Tourangau
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "psdrv.h"
22 #include "wine/debug.h"
23 #include "winbase.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
26
27 /***********************************************************************
28  *           PSDRV_SetDeviceClipping
29  */
30 void CDECL PSDRV_SetDeviceClipping( PSDRV_PDEVICE *physDev, HRGN vis_rgn, HRGN clip_rgn )
31 {
32     /* We could set a dirty flag here to speed up PSDRV_SetClip */
33     return;
34 }
35
36 /***********************************************************************
37  *           PSDRV_SetClip
38  *
39  * The idea here is that every graphics operation should bracket
40  * output in PSDRV_SetClip/ResetClip calls.  The clip path outside
41  * these calls will be empty; the reason for this is that it is
42  * impossible in PostScript to cleanly make the clip path larger than
43  * the current one.  Also Photoshop assumes that despite having set a
44  * small clip area in the printer dc that it can still write raw
45  * PostScript to the driver and expect this code not to be clipped.
46  */
47 void PSDRV_SetClip( PSDRV_PDEVICE *physDev )
48 {
49     CHAR szArrayName[] = "clippath";
50     DWORD size;
51     RGNDATA *rgndata = NULL;
52     HRGN hrgn = CreateRectRgn(0,0,0,0);
53     BOOL empty;
54
55     TRACE("hdc=%p\n", physDev->hdc);
56
57     if(physDev->pathdepth) {
58         TRACE("inside a path, so not clipping\n");
59         goto end;
60     }
61
62     empty = !GetClipRgn(physDev->hdc, hrgn);
63
64     if(!empty) {
65         size = GetRegionData(hrgn, 0, NULL);
66         if(!size) {
67             ERR("Invalid region\n");
68             goto end;
69         }
70
71         rgndata = HeapAlloc( GetProcessHeap(), 0, size );
72         if(!rgndata) {
73             ERR("Can't allocate buffer\n");
74             goto end;
75         }
76
77         GetRegionData(hrgn, size, rgndata);
78
79         PSDRV_WriteGSave(physDev);
80
81         /* check for NULL region */
82         if (rgndata->rdh.nCount == 0)
83         {
84             /* set an empty clip path. */
85             PSDRV_WriteRectClip(physDev, 0, 0, 0, 0);
86         }
87         /* optimize when it is a simple region */
88         else if (rgndata->rdh.nCount == 1)
89         {
90             RECT *pRect = (RECT *)rgndata->Buffer;
91
92             PSDRV_WriteRectClip(physDev, pRect->left, pRect->top,
93                                 pRect->right - pRect->left,
94                                 pRect->bottom - pRect->top);
95         }
96         else
97         {
98             UINT i;
99             RECT *pRect = (RECT *)rgndata->Buffer;
100
101             PSDRV_WriteArrayDef(physDev, szArrayName, rgndata->rdh.nCount * 4);
102
103             for (i = 0; i < rgndata->rdh.nCount; i++, pRect++)
104             {
105                 PSDRV_WriteArrayPut(physDev, szArrayName, i * 4,
106                                     pRect->left);
107                 PSDRV_WriteArrayPut(physDev, szArrayName, i * 4 + 1,
108                                     pRect->top);
109                 PSDRV_WriteArrayPut(physDev, szArrayName, i * 4 + 2,
110                                     pRect->right - pRect->left);
111                 PSDRV_WriteArrayPut(physDev, szArrayName, i * 4 + 3,
112                                     pRect->bottom - pRect->top);
113             }
114             PSDRV_WriteRectClip2(physDev, szArrayName);
115         }
116     }
117 end:
118     HeapFree( GetProcessHeap(), 0, rgndata );
119     DeleteObject(hrgn);
120 }
121
122
123 /***********************************************************************
124  *           PSDRV_ResetClip
125  */
126 void PSDRV_ResetClip( PSDRV_PDEVICE *physDev )
127 {
128     HRGN hrgn = CreateRectRgn(0,0,0,0);
129     BOOL empty;
130
131     empty = !GetClipRgn(physDev->hdc, hrgn);
132     if(!empty && !physDev->pathdepth)
133         PSDRV_WriteGRestore(physDev);
134     DeleteObject(hrgn);
135 }