mapi32/tests: Cast-qual warnings fix.
[wine] / dlls / gdi32 / bitblt.c
1 /*
2  * GDI bit-blit operations
3  *
4  * Copyright 1993, 1994  Alexandre Julliard
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 <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "gdi_private.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
30
31
32 /***********************************************************************
33  *           PatBlt    (GDI32.@)
34  */
35 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
36                         INT width, INT height, DWORD rop)
37 {
38     DC * dc = DC_GetDCUpdate( hdc );
39     BOOL bRet = FALSE;
40
41     if (!dc) return FALSE;
42
43     if (dc->funcs->pPatBlt)
44     {
45         TRACE("%p %d,%d %dx%d %06x\n", hdc, left, top, width, height, rop );
46         bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
47     }
48     GDI_ReleaseObj( hdc );
49     return bRet;
50 }
51
52
53 /***********************************************************************
54  *           BitBlt    (GDI32.@)
55  */
56 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
57                     INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
58 {
59     BOOL ret = FALSE;
60     DC *dcDst, *dcSrc;
61
62     if ((dcDst = DC_GetDCUpdate( hdcDst )) && dcDst->funcs->pBitBlt)
63     {
64         GDI_ReleaseObj( hdcDst );
65         /* FIXME: there is a race condition here */
66         dcSrc = DC_GetDCUpdate( hdcSrc );
67         dcDst = DC_GetDCPtr( hdcDst );
68         TRACE("hdcSrc=%p %d,%d -> hdcDest=%p %d,%d %dx%d rop=%06x\n",
69               hdcSrc, xSrc, ySrc, hdcDst, xDst, yDst, width, height, rop);
70
71         ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
72                                      dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
73
74         GDI_ReleaseObj( hdcDst );
75         if (dcSrc) GDI_ReleaseObj( hdcSrc );
76     }
77     else if(dcDst && dcDst->funcs->pStretchDIBits)
78     {
79         BITMAP bm;
80         BITMAPINFOHEADER info_hdr;
81         HBITMAP hbm;
82         LPVOID bits;
83         INT lines;
84
85         GDI_ReleaseObj( hdcDst );
86
87         if(GetObjectType( hdcSrc ) != OBJ_MEMDC)
88         {
89             FIXME("hdcSrc isn't a memory dc.  Don't yet cope with this\n");
90             return FALSE;
91         }
92
93         GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
94  
95         info_hdr.biSize = sizeof(info_hdr);
96         info_hdr.biWidth = bm.bmWidth;
97         info_hdr.biHeight = bm.bmHeight;
98         info_hdr.biPlanes = 1;
99         info_hdr.biBitCount = 32;
100         info_hdr.biCompression = BI_RGB;
101         info_hdr.biSizeImage = 0;
102         info_hdr.biXPelsPerMeter = 0;
103         info_hdr.biYPelsPerMeter = 0;
104         info_hdr.biClrUsed = 0;
105         info_hdr.biClrImportant = 0;
106
107         if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
108             return FALSE;
109
110         /* Select out the src bitmap before calling GetDIBits */
111         hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
112         GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
113         SelectObject(hdcSrc, hbm);
114
115         lines = StretchDIBits(hdcDst, xDst, yDst, width, height, xSrc, bm.bmHeight - height - ySrc,
116                               width, height, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
117
118         HeapFree(GetProcessHeap(), 0, bits);
119         return (lines == height);
120     }
121     else if(dcDst)
122         GDI_ReleaseObj( hdcDst );
123
124     return ret;
125 }
126
127
128 /***********************************************************************
129  *           StretchBlt    (GDI32.@)
130  */
131 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
132                             INT widthDst, INT heightDst,
133                             HDC hdcSrc, INT xSrc, INT ySrc,
134                             INT widthSrc, INT heightSrc,
135                         DWORD rop )
136 {
137     BOOL ret = FALSE;
138     DC *dcDst, *dcSrc;
139
140     if ((dcDst = DC_GetDCUpdate( hdcDst )) && dcDst->funcs->pStretchBlt)
141     {
142         GDI_ReleaseObj( hdcDst );
143         /* FIXME: there is a race condition here */
144         if ((dcSrc = DC_GetDCUpdate( hdcSrc )))
145         {
146             dcDst = DC_GetDCPtr( hdcDst );
147
148             TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06x\n",
149                   hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
150                   hdcDst, xDst, yDst, widthDst, heightDst, rop );
151
152             ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
153                                              dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
154                                              rop );
155             GDI_ReleaseObj( hdcDst );
156             GDI_ReleaseObj( hdcSrc );
157         }
158     }
159     else if(dcDst && dcDst->funcs->pStretchDIBits)
160     {
161         BITMAP bm;
162         BITMAPINFOHEADER info_hdr;
163         HBITMAP hbm;
164         LPVOID bits;
165         INT lines;
166
167         GDI_ReleaseObj( hdcDst );
168
169         if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
170
171         GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
172  
173         info_hdr.biSize = sizeof(info_hdr);
174         info_hdr.biWidth = bm.bmWidth;
175         info_hdr.biHeight = bm.bmHeight;
176         info_hdr.biPlanes = 1;
177         info_hdr.biBitCount = 32;
178         info_hdr.biCompression = BI_RGB;
179         info_hdr.biSizeImage = 0;
180         info_hdr.biXPelsPerMeter = 0;
181         info_hdr.biYPelsPerMeter = 0;
182         info_hdr.biClrUsed = 0;
183         info_hdr.biClrImportant = 0;
184
185         if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
186             return FALSE;
187
188         /* Select out the src bitmap before calling GetDIBits */
189         hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
190         GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
191         SelectObject(hdcSrc, hbm);
192
193         lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, bm.bmHeight - heightSrc - ySrc,
194                               widthSrc, heightSrc, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
195
196         HeapFree(GetProcessHeap(), 0, bits);
197         return (lines == heightSrc);
198     }
199     else if(dcDst)
200         GDI_ReleaseObj( hdcDst );
201
202     return ret;
203 }
204
205 #define FRGND_ROP3(ROP4)        ((ROP4) & 0x00FFFFFF)
206 #define BKGND_ROP3(ROP4)        (ROP3Table[((ROP4)>>24) & 0xFF])
207
208 /***********************************************************************
209  *           MaskBlt [GDI32.@]
210  */
211 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
212                         INT nWidth, INT nHeight, HDC hdcSrc,
213                         INT nXSrc, INT nYSrc, HBITMAP hbmMask,
214                         INT xMask, INT yMask, DWORD dwRop)
215 {
216     HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
217     HDC hDC1, hDC2;
218     HBRUSH hbrMask, hbrDst, hbrTmp;
219
220     static const DWORD ROP3Table[256] = 
221     {
222         0x00000042, 0x00010289,
223         0x00020C89, 0x000300AA,
224         0x00040C88, 0x000500A9,
225         0x00060865, 0x000702C5,
226         0x00080F08, 0x00090245,
227         0x000A0329, 0x000B0B2A,
228         0x000C0324, 0x000D0B25,
229         0x000E08A5, 0x000F0001,
230         0x00100C85, 0x001100A6,
231         0x00120868, 0x001302C8,
232         0x00140869, 0x001502C9,
233         0x00165CCA, 0x00171D54,
234         0x00180D59, 0x00191CC8,
235         0x001A06C5, 0x001B0768,
236         0x001C06CA, 0x001D0766,
237         0x001E01A5, 0x001F0385,
238         0x00200F09, 0x00210248,
239         0x00220326, 0x00230B24,
240         0x00240D55, 0x00251CC5,
241         0x002606C8, 0x00271868,
242         0x00280369, 0x002916CA,
243         0x002A0CC9, 0x002B1D58,
244         0x002C0784, 0x002D060A,
245         0x002E064A, 0x002F0E2A,
246         0x0030032A, 0x00310B28,
247         0x00320688, 0x00330008,
248         0x003406C4, 0x00351864,
249         0x003601A8, 0x00370388,
250         0x0038078A, 0x00390604,
251         0x003A0644, 0x003B0E24,
252         0x003C004A, 0x003D18A4,
253         0x003E1B24, 0x003F00EA,
254         0x00400F0A, 0x00410249,
255         0x00420D5D, 0x00431CC4,
256         0x00440328, 0x00450B29,
257         0x004606C6, 0x0047076A,
258         0x00480368, 0x004916C5,
259         0x004A0789, 0x004B0605,
260         0x004C0CC8, 0x004D1954,
261         0x004E0645, 0x004F0E25,
262         0x00500325, 0x00510B26,
263         0x005206C9, 0x00530764,
264         0x005408A9, 0x00550009,
265         0x005601A9, 0x00570389,
266         0x00580785, 0x00590609,
267         0x005A0049, 0x005B18A9,
268         0x005C0649, 0x005D0E29,
269         0x005E1B29, 0x005F00E9,
270         0x00600365, 0x006116C6,
271         0x00620786, 0x00630608,
272         0x00640788, 0x00650606,
273         0x00660046, 0x006718A8,
274         0x006858A6, 0x00690145,
275         0x006A01E9, 0x006B178A,
276         0x006C01E8, 0x006D1785,
277         0x006E1E28, 0x006F0C65,
278         0x00700CC5, 0x00711D5C,
279         0x00720648, 0x00730E28,
280         0x00740646, 0x00750E26,
281         0x00761B28, 0x007700E6,
282         0x007801E5, 0x00791786,
283         0x007A1E29, 0x007B0C68,
284         0x007C1E24, 0x007D0C69,
285         0x007E0955, 0x007F03C9,
286         0x008003E9, 0x00810975,
287         0x00820C49, 0x00831E04,
288         0x00840C48, 0x00851E05,
289         0x008617A6, 0x008701C5,
290         0x008800C6, 0x00891B08,
291         0x008A0E06, 0x008B0666,
292         0x008C0E08, 0x008D0668,
293         0x008E1D7C, 0x008F0CE5,
294         0x00900C45, 0x00911E08,
295         0x009217A9, 0x009301C4,
296         0x009417AA, 0x009501C9,
297         0x00960169, 0x0097588A,
298         0x00981888, 0x00990066,
299         0x009A0709, 0x009B07A8,
300         0x009C0704, 0x009D07A6,
301         0x009E16E6, 0x009F0345,
302         0x00A000C9, 0x00A11B05,
303         0x00A20E09, 0x00A30669,
304         0x00A41885, 0x00A50065,
305         0x00A60706, 0x00A707A5,
306         0x00A803A9, 0x00A90189,
307         0x00AA0029, 0x00AB0889,
308         0x00AC0744, 0x00AD06E9,
309         0x00AE0B06, 0x00AF0229,
310         0x00B00E05, 0x00B10665,
311         0x00B21974, 0x00B30CE8,
312         0x00B4070A, 0x00B507A9,
313         0x00B616E9, 0x00B70348,
314         0x00B8074A, 0x00B906E6,
315         0x00BA0B09, 0x00BB0226,
316         0x00BC1CE4, 0x00BD0D7D,
317         0x00BE0269, 0x00BF08C9,
318         0x00C000CA, 0x00C11B04,
319         0x00C21884, 0x00C3006A,
320         0x00C40E04, 0x00C50664,
321         0x00C60708, 0x00C707AA,
322         0x00C803A8, 0x00C90184,
323         0x00CA0749, 0x00CB06E4,
324         0x00CC0020, 0x00CD0888,
325         0x00CE0B08, 0x00CF0224,
326         0x00D00E0A, 0x00D1066A,
327         0x00D20705, 0x00D307A4,
328         0x00D41D78, 0x00D50CE9,
329         0x00D616EA, 0x00D70349,
330         0x00D80745, 0x00D906E8,
331         0x00DA1CE9, 0x00DB0D75,
332         0x00DC0B04, 0x00DD0228,
333         0x00DE0268, 0x00DF08C8,
334         0x00E003A5, 0x00E10185,
335         0x00E20746, 0x00E306EA,
336         0x00E40748, 0x00E506E5,
337         0x00E61CE8, 0x00E70D79,
338         0x00E81D74, 0x00E95CE6,
339         0x00EA02E9, 0x00EB0849,
340         0x00EC02E8, 0x00ED0848,
341         0x00EE0086, 0x00EF0A08,
342         0x00F00021, 0x00F10885,
343         0x00F20B05, 0x00F3022A,
344         0x00F40B0A, 0x00F50225,
345         0x00F60265, 0x00F708C5,
346         0x00F802E5, 0x00F90845,
347         0x00FA0089, 0x00FB0A09,
348         0x00FC008A, 0x00FD0A0A,
349         0x00FE02A9, 0x00FF0062,
350     };
351
352     if (!hbmMask)
353         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
354
355     hbrMask = CreatePatternBrush(hbmMask);
356     hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
357
358     /* make bitmap */
359     hDC1 = CreateCompatibleDC(hdcDest);
360     hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
361     hOldBitmap1 = SelectObject(hDC1, hBitmap1);
362
363     /* draw using bkgnd rop */
364     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
365     hbrTmp = SelectObject(hDC1, hbrDst);
366     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
367     SelectObject(hDC1, hbrTmp);
368
369     /* make bitmap */
370     hDC2 = CreateCompatibleDC(hdcDest);
371     hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
372     hOldBitmap2 = SelectObject(hDC2, hBitmap2);
373
374     /* draw using foregnd rop */
375     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
376     hbrTmp = SelectObject(hDC2, hbrDst);
377     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
378
379     /* combine both using the mask as a pattern brush */
380     SelectObject(hDC2, hbrMask);
381     BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */ 
382     SelectObject(hDC2, hbrTmp);
383
384     /* blit to dst */
385     BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
386
387     /* restore all objects */
388     SelectObject(hdcDest, hbrDst);
389     SelectObject(hDC1, hOldBitmap1);
390     SelectObject(hDC2, hOldBitmap2);
391
392     /* delete all temp objects */
393     DeleteObject(hBitmap1);
394     DeleteObject(hBitmap2);
395     DeleteObject(hbrMask);
396
397     DeleteDC(hDC1);
398     DeleteDC(hDC2);
399
400     return TRUE;
401 }
402
403 /******************************************************************************
404  *           GdiTransparentBlt [GDI32.@]
405  */
406 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
407                             HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
408                             UINT crTransparent )
409 {
410     BOOL ret = FALSE;
411     HDC hdcWork;
412     HBITMAP bmpWork;
413     HGDIOBJ oldWork;
414     HDC hdcMask = NULL;
415     HBITMAP bmpMask = NULL;
416     HBITMAP oldMask = NULL;
417     COLORREF oldBackground;
418     COLORREF oldForeground;
419     int oldStretchMode;
420
421     if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
422         TRACE("Cannot mirror\n");
423         return FALSE;
424     }
425
426     oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
427     oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
428
429     /* Stretch bitmap */
430     oldStretchMode = GetStretchBltMode(hdcSrc);
431     if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
432         SetStretchBltMode(hdcSrc, COLORONCOLOR);
433     hdcWork = CreateCompatibleDC(hdcDest);
434     bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
435     oldWork = SelectObject(hdcWork, bmpWork);
436     if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
437         TRACE("Failed to stretch\n");
438         goto error;
439     }
440     SetBkColor(hdcWork, crTransparent);
441
442     /* Create mask */
443     hdcMask = CreateCompatibleDC(hdcDest);
444     bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
445     oldMask = SelectObject(hdcMask, bmpMask);
446     if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
447         TRACE("Failed to create mask\n");
448         goto error;
449     }
450
451     /* Replace transparent color with black */
452     SetBkColor(hdcWork, RGB(0,0,0));
453     SetTextColor(hdcWork, RGB(255,255,255));
454     if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
455         TRACE("Failed to mask out background\n");
456         goto error;
457     }
458
459     /* Replace non-transparent area on destination with black */
460     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
461         TRACE("Failed to clear destination area\n");
462         goto error;
463     }
464
465     /* Draw the image */
466     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
467         TRACE("Failed to paint image\n");
468         goto error;
469     }
470
471     ret = TRUE;
472 error:
473     SetStretchBltMode(hdcSrc, oldStretchMode);
474     SetBkColor(hdcDest, oldBackground);
475     SetTextColor(hdcDest, oldForeground);
476     if(hdcWork) {
477         SelectObject(hdcWork, oldWork);
478         DeleteDC(hdcWork);
479     }
480     if(bmpWork) DeleteObject(bmpWork);
481     if(hdcMask) {
482         SelectObject(hdcMask, oldMask);
483         DeleteDC(hdcMask);
484     }
485     if(bmpMask) DeleteObject(bmpMask);
486     return ret;
487 }
488
489 /******************************************************************************
490  *           GdiAlphaBlend [GDI32.@]
491  */
492 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
493                           HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
494                           BLENDFUNCTION blendFunction)
495 {
496     BOOL ret = FALSE;
497     DC *dcDst, *dcSrc;
498
499     if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
500     /* FIXME: there is a race condition here */
501     if ((dcDst = DC_GetDCUpdate( hdcDst )))
502     {
503         dcSrc = DC_GetDCPtr( hdcSrc );
504         TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
505               hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
506               hdcDst, xDst, yDst, widthDst, heightDst,
507               blendFunction.BlendOp, blendFunction.BlendFlags,
508               blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
509         if (dcDst->funcs->pAlphaBlend)
510             ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
511                                              dcSrc ? dcSrc->physDev : NULL,
512                                              xSrc, ySrc, widthSrc, heightSrc, blendFunction );
513         if (dcSrc) GDI_ReleaseObj( hdcSrc );
514         GDI_ReleaseObj( hdcDst );
515     }
516     return ret;
517 }
518
519 /*********************************************************************
520  *      PlgBlt [GDI32.@]
521  *
522  */
523 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
524                         HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
525                         INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
526 {
527     FIXME("PlgBlt, stub\n");
528         return 1;
529 }