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