Implement ResetDC and PHYSICALOFFSET[X|Y] devcaps.
[wine] / dlls / wineps / bitmap.c
1 /*
2  *      PostScript driver bitmap functions
3  *
4  * Copyright 1998  Huw D M Davies
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "psdrv.h"
22 #include "winbase.h"
23 #include "wine/debug.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
26
27
28 /* Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. */
29 inline static int get_dib_width_bytes( int width, int depth )
30 {
31     int words;
32
33     switch(depth)
34     {
35     case 1:  words = (width + 31) / 32; break;
36     case 4:  words = (width + 7) / 8; break;
37     case 8:  words = (width + 3) / 4; break;
38     case 15:
39     case 16: words = (width + 1) / 2; break;
40     case 24: words = (width * 3 + 3)/4; break;
41     default:
42         WARN("(%d): Unsupported depth\n", depth );
43         /* fall through */
44     case 32: words = width; break;
45     }
46     return 4 * words;
47 }
48
49 /* get the bitmap info from either an INFOHEADER or COREHEADER bitmap */
50 static BOOL get_bitmap_info( const void *ptr, LONG *width, LONG *height, WORD *bpp, WORD *compr )
51 {
52     const BITMAPINFOHEADER *header = ptr;
53
54     switch(header->biSize)
55     {
56     case sizeof(BITMAPCOREHEADER):
57         {
58             const BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
59             *width  = core->bcWidth;
60             *height = core->bcHeight;
61             *bpp    = core->bcBitCount;
62             *compr  = 0;
63         }
64         return TRUE;
65     case sizeof(BITMAPINFOHEADER):
66     case sizeof(BITMAPV4HEADER):
67     case sizeof(BITMAPV5HEADER):
68         /* V4 and V5 structures are a superset of the INFOHEADER structure */
69         *width  = header->biWidth;
70         *height = header->biHeight;
71         *bpp    = header->biBitCount;
72         *compr  = header->biCompression;
73         return TRUE;
74     default:
75         ERR("(%ld): unknown/wrong size for header\n", header->biSize );
76         return FALSE;
77     }
78 }
79
80
81 /***************************************************************************
82  *                PSDRV_WriteImageHeader
83  *
84  * Helper for PSDRV_StretchDIBits
85  *
86  * BUGS
87  *  Uses level 2 PostScript
88  */
89
90 static BOOL PSDRV_WriteImageHeader(PSDRV_PDEVICE *physDev, const BITMAPINFO *info, INT xDst,
91                                    INT yDst, INT widthDst, INT heightDst,
92                                    INT widthSrc, INT heightSrc)
93 {
94     COLORREF map[256];
95     int i;
96
97     switch(info->bmiHeader.biBitCount) {
98     case 8:
99         PSDRV_WriteIndexColorSpaceBegin(physDev, 255);
100         for(i = 0; i < 256; i++) {
101             map[i] =  info->bmiColors[i].rgbRed |
102               info->bmiColors[i].rgbGreen << 8 |
103               info->bmiColors[i].rgbBlue << 16;
104         }
105         PSDRV_WriteRGB(physDev, map, 256);
106         PSDRV_WriteIndexColorSpaceEnd(physDev);
107         break;
108
109     case 4:
110         PSDRV_WriteIndexColorSpaceBegin(physDev, 15);
111         for(i = 0; i < 16; i++) {
112             map[i] =  info->bmiColors[i].rgbRed |
113               info->bmiColors[i].rgbGreen << 8 |
114               info->bmiColors[i].rgbBlue << 16;
115         }
116         PSDRV_WriteRGB(physDev, map, 16);
117         PSDRV_WriteIndexColorSpaceEnd(physDev);
118         break;
119
120     case 1:
121         PSDRV_WriteIndexColorSpaceBegin(physDev, 1);
122         for(i = 0; i < 2; i++) {
123             map[i] =  info->bmiColors[i].rgbRed |
124               info->bmiColors[i].rgbGreen << 8 |
125               info->bmiColors[i].rgbBlue << 16;
126         }
127         PSDRV_WriteRGB(physDev, map, 2);
128         PSDRV_WriteIndexColorSpaceEnd(physDev);
129         break;
130
131     case 15:
132     case 16:
133     case 24:
134     case 32:
135       {
136         PSCOLOR pscol;
137         pscol.type = PSCOLOR_RGB;
138         pscol.value.rgb.r = pscol.value.rgb.g = pscol.value.rgb.b = 0.0;
139         PSDRV_WriteSetColor(physDev, &pscol);
140         break;
141       }
142
143     default:
144         FIXME("Not implemented yet\n");
145         return FALSE;
146         break;
147     }
148
149     PSDRV_WriteImageDict(physDev, info->bmiHeader.biBitCount, xDst, yDst,
150                           widthDst, heightDst, widthSrc, heightSrc, NULL);
151     return TRUE;
152 }
153
154
155 /***************************************************************************
156  *
157  *      PSDRV_StretchDIBits
158  *
159  * BUGS
160  *  Doesn't work correctly if xSrc isn't byte aligned - this affects 1 and 4
161  *  bit depths.
162  *  Compression not implemented.
163  */
164 INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDst,
165                          INT heightDst, INT xSrc, INT ySrc,
166                          INT widthSrc, INT heightSrc, const void *bits,
167                          const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
168 {
169     LONG fullSrcWidth, fullSrcHeight;
170     INT widthbytes;
171     WORD bpp, compression;
172     const char *ptr;
173     INT line;
174     DC *dc = physDev->dc;
175
176     TRACE("%08x (%d,%d %dx%d) -> (%d,%d %dx%d)\n", physDev->hdc,
177           xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst);
178
179     if (!get_bitmap_info( info, &fullSrcWidth, &fullSrcHeight, &bpp, &compression )) return FALSE;
180
181     widthbytes = get_dib_width_bytes(fullSrcWidth, bpp);
182
183     TRACE("full size=%ldx%ld bpp=%d compression=%d\n", fullSrcWidth,
184           fullSrcHeight, bpp, compression);
185
186
187     if(compression != BI_RGB) {
188         FIXME("Compression not supported\n");
189         return FALSE;
190     }
191
192     xDst = XLPTODP(dc, xDst);
193     yDst = YLPTODP(dc, yDst);
194     widthDst = XLSTODS(dc, widthDst);
195     heightDst = YLSTODS(dc, heightDst);
196
197     switch(bpp) {
198
199     case 1:
200         PSDRV_WriteGSave(physDev);
201         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
202                                widthSrc, heightSrc);
203         ptr = bits;
204         ptr += (ySrc * widthbytes);
205         if(xSrc & 7)
206             FIXME("This won't work...\n");
207         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
208             PSDRV_WriteBytes(physDev, ptr + xSrc/8, (widthSrc+7)/8);
209         break;
210
211     case 4:
212         PSDRV_WriteGSave(physDev);
213         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
214                                widthSrc, heightSrc);
215         ptr = bits;
216         ptr += (ySrc * widthbytes);
217         if(xSrc & 1)
218             FIXME("This won't work...\n");
219         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
220             PSDRV_WriteBytes(physDev, ptr + xSrc/2, (widthSrc+1)/2);
221         break;
222
223     case 8:
224         PSDRV_WriteGSave(physDev);
225         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
226                                widthSrc, heightSrc);
227         ptr = bits;
228         ptr += (ySrc * widthbytes);
229         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
230             PSDRV_WriteBytes(physDev, ptr + xSrc, widthSrc);
231         break;
232
233     case 15:
234     case 16:
235         PSDRV_WriteGSave(physDev);
236         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
237                                widthSrc, heightSrc);
238
239         ptr = bits;
240         ptr += (ySrc * widthbytes);
241         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
242             PSDRV_WriteDIBits16(physDev, (WORD *)ptr + xSrc, widthSrc);
243         break;
244
245     case 24:
246         PSDRV_WriteGSave(physDev);
247         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
248                                widthSrc, heightSrc);
249
250         ptr = bits;
251         ptr += (ySrc * widthbytes);
252         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
253             PSDRV_WriteDIBits24(physDev, ptr + xSrc * 3, widthSrc);
254         break;
255
256     case 32:
257         PSDRV_WriteGSave(physDev);
258         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
259                                widthSrc, heightSrc);
260
261         ptr = bits;
262         ptr += (ySrc * widthbytes);
263         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
264             PSDRV_WriteDIBits32(physDev, ptr + xSrc * 3, widthSrc);
265         break;
266
267     default:
268         FIXME("Unsupported depth\n");
269         return FALSE;
270
271     }
272     PSDRV_WriteSpool(physDev, ">\n", 2);  /* End-of-Data for /HexASCIIDecodeFilter */
273     PSDRV_WriteGRestore(physDev);
274     return TRUE;
275 }
276
277
278
279
280
281