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