gdi32: Allow the PutImage entry point to optionally support stretching.
[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_SetClip
29  *
30  * The idea here is that every graphics operation should bracket
31  * output in PSDRV_SetClip/ResetClip calls.  The clip path outside
32  * these calls will be empty; the reason for this is that it is
33  * impossible in PostScript to cleanly make the clip path larger than
34  * the current one.  Also Photoshop assumes that despite having set a
35  * small clip area in the printer dc that it can still write raw
36  * PostScript to the driver and expect this code not to be clipped.
37  */
38 void PSDRV_SetClip( PHYSDEV dev )
39 {
40     PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
41     CHAR szArrayName[] = "clippath";
42     DWORD size;
43     RGNDATA *rgndata = NULL;
44     HRGN hrgn = CreateRectRgn(0,0,0,0);
45     BOOL empty;
46
47     TRACE("hdc=%p\n", dev->hdc);
48
49     if(physDev->pathdepth) {
50         TRACE("inside a path, so not clipping\n");
51         goto end;
52     }
53
54     empty = !GetClipRgn(dev->hdc, hrgn);
55
56     if(!empty) {
57         size = GetRegionData(hrgn, 0, NULL);
58         if(!size) {
59             ERR("Invalid region\n");
60             goto end;
61         }
62
63         rgndata = HeapAlloc( GetProcessHeap(), 0, size );
64         if(!rgndata) {
65             ERR("Can't allocate buffer\n");
66             goto end;
67         }
68
69         GetRegionData(hrgn, size, rgndata);
70
71         PSDRV_WriteGSave(dev);
72
73         /* check for NULL region */
74         if (rgndata->rdh.nCount == 0)
75         {
76             /* set an empty clip path. */
77             PSDRV_WriteRectClip(dev, 0, 0, 0, 0);
78         }
79         /* optimize when it is a simple region */
80         else if (rgndata->rdh.nCount == 1)
81         {
82             RECT *pRect = (RECT *)rgndata->Buffer;
83
84             PSDRV_WriteRectClip(dev, pRect->left, pRect->top,
85                                 pRect->right - pRect->left,
86                                 pRect->bottom - pRect->top);
87         }
88         else
89         {
90             UINT i;
91             RECT *pRect = (RECT *)rgndata->Buffer;
92
93             PSDRV_WriteArrayDef(dev, szArrayName, rgndata->rdh.nCount * 4);
94
95             for (i = 0; i < rgndata->rdh.nCount; i++, pRect++)
96             {
97                 PSDRV_WriteArrayPut(dev, szArrayName, i * 4,
98                                     pRect->left);
99                 PSDRV_WriteArrayPut(dev, szArrayName, i * 4 + 1,
100                                     pRect->top);
101                 PSDRV_WriteArrayPut(dev, szArrayName, i * 4 + 2,
102                                     pRect->right - pRect->left);
103                 PSDRV_WriteArrayPut(dev, szArrayName, i * 4 + 3,
104                                     pRect->bottom - pRect->top);
105             }
106             PSDRV_WriteRectClip2(dev, szArrayName);
107         }
108     }
109 end:
110     HeapFree( GetProcessHeap(), 0, rgndata );
111     DeleteObject(hrgn);
112 }
113
114
115 /***********************************************************************
116  *           PSDRV_ResetClip
117  */
118 void PSDRV_ResetClip( PHYSDEV dev )
119 {
120     PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
121     HRGN hrgn = CreateRectRgn(0,0,0,0);
122     BOOL empty;
123
124     empty = !GetClipRgn(dev->hdc, hrgn);
125     if(!empty && !physDev->pathdepth)
126         PSDRV_WriteGRestore(dev);
127     DeleteObject(hrgn);
128 }