Fixed a few more headers dependency issues.
[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 <assert.h>
22
23 #include "psdrv.h"
24 #include "winbase.h"
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
28
29
30 /* Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. */
31 inline static int get_dib_width_bytes( int width, int depth )
32 {
33     int words;
34
35     switch(depth)
36     {
37     case 1:  words = (width + 31) / 32; break;
38     case 4:  words = (width + 7) / 8; break;
39     case 8:  words = (width + 3) / 4; break;
40     case 15:
41     case 16: words = (width + 1) / 2; break;
42     case 24: words = (width * 3 + 3)/4; break;
43     default:
44         WARN("(%d): Unsupported depth\n", depth );
45         /* fall through */
46     case 32: words = width; break;
47     }
48     return 4 * words;
49 }
50
51 /* get the bitmap info from either an INFOHEADER or COREHEADER bitmap */
52 static BOOL get_bitmap_info( const void *ptr, LONG *width, LONG *height, WORD *bpp, WORD *compr )
53 {
54     const BITMAPINFOHEADER *header = ptr;
55
56     switch(header->biSize)
57     {
58     case sizeof(BITMAPCOREHEADER):
59         {
60             const BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
61             *width  = core->bcWidth;
62             *height = core->bcHeight;
63             *bpp    = core->bcBitCount;
64             *compr  = 0;
65         }
66         return TRUE;
67     case sizeof(BITMAPINFOHEADER):
68     case sizeof(BITMAPV4HEADER):
69     case sizeof(BITMAPV5HEADER):
70         /* V4 and V5 structures are a superset of the INFOHEADER structure */
71         *width  = header->biWidth;
72         *height = header->biHeight;
73         *bpp    = header->biBitCount;
74         *compr  = header->biCompression;
75         return TRUE;
76     default:
77         ERR("(%ld): unknown/wrong size for header\n", header->biSize );
78         return FALSE;
79     }
80 }
81
82
83 /***************************************************************************
84  *                PSDRV_WriteImageHeader
85  *
86  * Helper for PSDRV_StretchDIBits
87  *
88  * BUGS
89  *  Uses level 2 PostScript
90  */
91
92 static BOOL PSDRV_WriteImageHeader(PSDRV_PDEVICE *physDev, const BITMAPINFO *info, INT xDst,
93                                    INT yDst, INT widthDst, INT heightDst,
94                                    INT widthSrc, INT heightSrc)
95 {
96     COLORREF map[256];
97     int i;
98
99     switch(info->bmiHeader.biBitCount) {
100     case 8:
101         PSDRV_WriteIndexColorSpaceBegin(physDev, 255);
102         for(i = 0; i < 256; i++) {
103             map[i] =  info->bmiColors[i].rgbRed |
104               info->bmiColors[i].rgbGreen << 8 |
105               info->bmiColors[i].rgbBlue << 16;
106         }
107         PSDRV_WriteRGB(physDev, map, 256);
108         PSDRV_WriteIndexColorSpaceEnd(physDev);
109         break;
110
111     case 4:
112         PSDRV_WriteIndexColorSpaceBegin(physDev, 15);
113         for(i = 0; i < 16; i++) {
114             map[i] =  info->bmiColors[i].rgbRed |
115               info->bmiColors[i].rgbGreen << 8 |
116               info->bmiColors[i].rgbBlue << 16;
117         }
118         PSDRV_WriteRGB(physDev, map, 16);
119         PSDRV_WriteIndexColorSpaceEnd(physDev);
120         break;
121
122     case 1:
123         PSDRV_WriteIndexColorSpaceBegin(physDev, 1);
124         for(i = 0; i < 2; i++) {
125             map[i] =  info->bmiColors[i].rgbRed |
126               info->bmiColors[i].rgbGreen << 8 |
127               info->bmiColors[i].rgbBlue << 16;
128         }
129         PSDRV_WriteRGB(physDev, map, 2);
130         PSDRV_WriteIndexColorSpaceEnd(physDev);
131         break;
132
133     case 15:
134     case 16:
135     case 24:
136     case 32:
137       {
138         PSCOLOR pscol;
139         pscol.type = PSCOLOR_RGB;
140         pscol.value.rgb.r = pscol.value.rgb.g = pscol.value.rgb.b = 0.0;
141         PSDRV_WriteSetColor(physDev, &pscol);
142         break;
143       }
144
145     default:
146         FIXME("Not implemented yet\n");
147         return FALSE;
148         break;
149     }
150
151     PSDRV_WriteImageDict(physDev, info->bmiHeader.biBitCount, xDst, yDst,
152                           widthDst, heightDst, widthSrc, heightSrc, NULL, FALSE);
153     return TRUE;
154 }
155
156
157 /***************************************************************************
158  *                PSDRV_WriteImageMaskHeader
159  *
160  * Helper for PSDRV_StretchDIBits
161  *
162  * We use the imagemask operator for 1bpp bitmaps since the output
163  * takes much less time for the printer to render.
164  *
165  * BUGS
166  *  Uses level 2 PostScript
167  */
168
169 static BOOL PSDRV_WriteImageMaskHeader(PSDRV_PDEVICE *physDev, const BITMAPINFO *info, INT xDst,
170                                        INT yDst, INT widthDst, INT heightDst,
171                                        INT widthSrc, INT heightSrc)
172 {
173     COLORREF map[2];
174     PSCOLOR bkgnd, foregnd;
175     int i;
176
177     assert(info->bmiHeader.biBitCount == 1);
178
179     for(i = 0; i < 2; i++) {
180         map[i] =  info->bmiColors[i].rgbRed |
181             info->bmiColors[i].rgbGreen << 8 |
182             info->bmiColors[i].rgbBlue << 16;
183     }
184
185     /* We'll write the mask with -ve polarity so that 
186        the foregnd color corresponds to a bit equal to
187        0 in the bitmap.
188     */
189     PSDRV_CreateColor(physDev, &foregnd, map[0]);
190     PSDRV_CreateColor(physDev, &bkgnd, map[1]);
191
192     PSDRV_WriteGSave(physDev);
193     PSDRV_WriteNewPath(physDev);
194     PSDRV_WriteRectangle(physDev, xDst, yDst, widthDst, heightDst);
195     PSDRV_WriteSetColor(physDev, &bkgnd);
196     PSDRV_WriteFill(physDev);
197     PSDRV_WriteGRestore(physDev);
198
199     PSDRV_WriteSetColor(physDev, &foregnd);
200     PSDRV_WriteImageDict(physDev, 1, xDst, yDst, widthDst, heightDst,
201                          widthSrc, heightSrc, NULL, TRUE);
202
203     return TRUE;
204 }
205
206
207 /***************************************************************************
208  *
209  *      PSDRV_StretchDIBits
210  *
211  * BUGS
212  *  Doesn't work correctly if xSrc isn't byte aligned - this affects 1 and 4
213  *  bit depths.
214  *  Compression not implemented.
215  */
216 INT PSDRV_StretchDIBits( PSDRV_PDEVICE *physDev, INT xDst, INT yDst, INT widthDst,
217                          INT heightDst, INT xSrc, INT ySrc,
218                          INT widthSrc, INT heightSrc, const void *bits,
219                          const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
220 {
221     LONG fullSrcWidth, fullSrcHeight;
222     INT widthbytes;
223     WORD bpp, compression;
224     const char *ptr;
225     INT line;
226     POINT pt[2];
227
228     TRACE("%p (%d,%d %dx%d) -> (%d,%d %dx%d)\n", physDev->hdc,
229           xSrc, ySrc, widthSrc, heightSrc, xDst, yDst, widthDst, heightDst);
230
231     if (!get_bitmap_info( info, &fullSrcWidth, &fullSrcHeight, &bpp, &compression )) return FALSE;
232
233     widthbytes = get_dib_width_bytes(fullSrcWidth, bpp);
234
235     TRACE("full size=%ldx%ld bpp=%d compression=%d rop=%08lx\n", fullSrcWidth,
236           fullSrcHeight, bpp, compression, dwRop);
237
238
239     if(compression != BI_RGB) {
240         FIXME("Compression not supported\n");
241         return FALSE;
242     }
243
244     pt[0].x = xDst;
245     pt[0].y = yDst;
246     pt[1].x = xDst + widthDst;
247     pt[1].y = yDst + heightDst;
248     LPtoDP( physDev->hdc, pt, 2 );
249     xDst = pt[0].x;
250     yDst = pt[0].y;
251     widthDst = pt[1].x - pt[0].x;
252     heightDst = pt[1].y - pt[0].y;
253
254     switch(bpp) {
255
256     case 1:
257         PSDRV_SetClip(physDev);
258         PSDRV_WriteGSave(physDev);
259
260         /* Use imagemask rather than image */
261         PSDRV_WriteImageMaskHeader(physDev, info, xDst, yDst, widthDst, heightDst,
262                                    widthSrc, heightSrc);
263         ptr = bits;
264         ptr += (ySrc * widthbytes);
265         if(xSrc & 7)
266             FIXME("This won't work...\n");
267         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
268             PSDRV_WriteBytes(physDev, ptr + xSrc/8, (widthSrc+7)/8);
269         break;
270
271     case 4:
272         PSDRV_SetClip(physDev);
273         PSDRV_WriteGSave(physDev);
274         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
275                                widthSrc, heightSrc);
276         ptr = bits;
277         ptr += (ySrc * widthbytes);
278         if(xSrc & 1)
279             FIXME("This won't work...\n");
280         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
281             PSDRV_WriteBytes(physDev, ptr + xSrc/2, (widthSrc+1)/2);
282         break;
283
284     case 8:
285         PSDRV_SetClip(physDev);
286         PSDRV_WriteGSave(physDev);
287         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
288                                widthSrc, heightSrc);
289         ptr = bits;
290         ptr += (ySrc * widthbytes);
291         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
292             PSDRV_WriteBytes(physDev, ptr + xSrc, widthSrc);
293         break;
294
295     case 15:
296     case 16:
297         PSDRV_SetClip(physDev);
298         PSDRV_WriteGSave(physDev);
299         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
300                                widthSrc, heightSrc);
301
302         ptr = bits;
303         ptr += (ySrc * widthbytes);
304         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
305             PSDRV_WriteDIBits16(physDev, (WORD *)ptr + xSrc, widthSrc);
306         break;
307
308     case 24:
309         PSDRV_SetClip(physDev);
310         PSDRV_WriteGSave(physDev);
311         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
312                                widthSrc, heightSrc);
313
314         ptr = bits;
315         ptr += (ySrc * widthbytes);
316         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
317             PSDRV_WriteDIBits24(physDev, ptr + xSrc * 3, widthSrc);
318         break;
319
320     case 32:
321         PSDRV_SetClip(physDev);
322         PSDRV_WriteGSave(physDev);
323         PSDRV_WriteImageHeader(physDev, info, xDst, yDst, widthDst, heightDst,
324                                widthSrc, heightSrc);
325
326         ptr = bits;
327         ptr += (ySrc * widthbytes);
328         for(line = 0; line < heightSrc; line++, ptr += widthbytes)
329             PSDRV_WriteDIBits32(physDev, ptr + xSrc * 3, widthSrc);
330         break;
331
332     default:
333         FIXME("Unsupported depth\n");
334         return FALSE;
335
336     }
337     PSDRV_WriteSpool(physDev, ">\n", 2);  /* End-of-Data for /HexASCIIDecodeFilter */
338     PSDRV_WriteGRestore(physDev);
339     PSDRV_ResetClip(physDev);
340     return TRUE;
341 }