Implement MaskBlt using BitBlt (adapted by Dimitrie O. Paun).
[wine] / graphics / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "gdi.h"
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
25
26
27 /***********************************************************************
28  *           PatBlt    (GDI32.@)
29  */
30 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
31                         INT width, INT height, DWORD rop)
32 {
33     DC * dc = DC_GetDCUpdate( hdc );
34     BOOL bRet = FALSE;
35
36     if (!dc) return FALSE;
37
38     if (dc->funcs->pPatBlt)
39     {
40         TRACE("%p %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
41         bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
42     }
43     GDI_ReleaseObj( hdc );
44     return bRet;
45 }
46
47
48 /***********************************************************************
49  *           BitBlt    (GDI32.@)
50  */
51 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
52                     INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
53 {
54     BOOL ret = FALSE;
55     DC *dcDst, *dcSrc;
56
57     if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
58     /* FIXME: there is a race condition here */
59     if ((dcDst = DC_GetDCUpdate( hdcDst )))
60     {
61         dcSrc = DC_GetDCPtr( hdcSrc );
62         TRACE("hdcSrc=%p %d,%d %d bpp->hdcDest=%p %d,%d %dx%dx%d rop=%06lx\n",
63               hdcSrc, xSrc, ySrc, dcSrc ? dcSrc->bitsPerPixel : 0,
64               hdcDst, xDst, yDst, width, height, dcDst->bitsPerPixel, rop);
65         if (dcDst->funcs->pBitBlt)
66             ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
67                                          dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
68         if (dcSrc) GDI_ReleaseObj( hdcSrc );
69         GDI_ReleaseObj( hdcDst );
70     }
71     return ret;
72 }
73
74
75 /***********************************************************************
76  *           StretchBlt    (GDI32.@)
77  */
78 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
79                             INT widthDst, INT heightDst,
80                             HDC hdcSrc, INT xSrc, INT ySrc,
81                             INT widthSrc, INT heightSrc,
82                         DWORD rop )
83 {
84     BOOL ret = FALSE;
85     DC *dcDst, *dcSrc;
86
87     if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
88     /* FIXME: there is a race condition here */
89     if ((dcDst = DC_GetDCUpdate( hdcDst )))
90     {
91         dcSrc = DC_GetDCPtr( hdcSrc );
92
93         TRACE("%p %d,%d %dx%dx%d -> %p %d,%d %dx%dx%d rop=%06lx\n",
94               hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
95               dcSrc ? dcSrc->bitsPerPixel : 0, hdcDst, xDst, yDst,
96               widthDst, heightDst, dcDst->bitsPerPixel, rop );
97
98         if (dcSrc) {
99             if (dcDst->funcs->pStretchBlt)
100                 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
101                                                  dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
102                                                  rop );
103             GDI_ReleaseObj( hdcSrc );
104         }
105         GDI_ReleaseObj( hdcDst );
106     }
107     return ret;
108 }
109
110 static inline BYTE SwapROP3_SrcDst(BYTE bRop3)
111 {
112     return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
113 }
114
115 #define FRGND_ROP3(ROP4)        ((ROP4) & 0x00FFFFFF)
116 #define BKGND_ROP3(ROP4)        (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
117 #define DSTCOPY                 0x00AA0029
118 #define DSTERASE                0x00220326 /* dest = dest & (~src) : DSna */
119
120 /***********************************************************************
121  *           MaskBlt [GDI32.@]
122  */
123 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
124                         INT nWidth, INT nHeight, HDC hdcSrc,
125                         INT nXSrc, INT nYSrc, HBITMAP hbmMask,
126                         INT xMask, INT yMask, DWORD dwRop)
127 {
128     HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
129     HDC hDCMask, hDC1, hDC2;
130     static const DWORD ROP3Table[256] = 
131     {
132         0x00000042, 0x00010289,
133         0x00020C89, 0x000300AA,
134         0x00040C88, 0x000500A9,
135         0x00060865, 0x000702C5,
136         0x00080F08, 0x00090245,
137         0x000A0329, 0x000B0B2A,
138         0x000C0324, 0x000D0B25,
139         0x000E08A5, 0x000F0001,
140         0x00100C85, 0x001100A6,
141         0x00120868, 0x001302C8,
142         0x00140869, 0x001502C9,
143         0x00165CCA, 0x00171D54,
144         0x00180D59, 0x00191CC8,
145         0x001A06C5, 0x001B0768,
146         0x001C06CA, 0x001D0766,
147         0x001E01A5, 0x001F0385,
148         0x00200F09, 0x00210248,
149         0x00220326, 0x00230B24,
150         0x00240D55, 0x00251CC5,
151         0x002606C8, 0x00271868,
152         0x00280369, 0x002916CA,
153         0x002A0CC9, 0x002B1D58,
154         0x002C0784, 0x002D060A,
155         0x002E064A, 0x002F0E2A,
156         0x0030032A, 0x00310B28,
157         0x00320688, 0x00330008,
158         0x003406C4, 0x00351864,
159         0x003601A8, 0x00370388,
160         0x0038078A, 0x00390604,
161         0x003A0644, 0x003B0E24,
162         0x003C004A, 0x003D18A4,
163         0x003E1B24, 0x003F00EA,
164         0x00400F0A, 0x00410249,
165         0x00420D5D, 0x00431CC4,
166         0x00440328, 0x00450B29,
167         0x004606C6, 0x0047076A,
168         0x00480368, 0x004916C5,
169         0x004A0789, 0x004B0605,
170         0x004C0CC8, 0x004D1954,
171         0x004E0645, 0x004F0E25,
172         0x00500325, 0x00510B26,
173         0x005206C9, 0x00530764,
174         0x005408A9, 0x00550009,
175         0x005601A9, 0x00570389,
176         0x00580785, 0x00590609,
177         0x005A0049, 0x005B18A9,
178         0x005C0649, 0x005D0E29,
179         0x005E1B29, 0x005F00E9,
180         0x00600365, 0x006116C6,
181         0x00620786, 0x00630608,
182         0x00640788, 0x00650606,
183         0x00660046, 0x006718A8,
184         0x006858A6, 0x00690145,
185         0x006A01E9, 0x006B178A,
186         0x006C01E8, 0x006D1785,
187         0x006E1E28, 0x006F0C65,
188         0x00700CC5, 0x00711D5C,
189         0x00720648, 0x00730E28,
190         0x00740646, 0x00750E26,
191         0x00761B28, 0x007700E6,
192         0x007801E5, 0x00791786,
193         0x007A1E29, 0x007B0C68,
194         0x007C1E24, 0x007D0C69,
195         0x007E0955, 0x007F03C9,
196         0x008003E9, 0x00810975,
197         0x00820C49, 0x00831E04,
198         0x00840C48, 0x00851E05,
199         0x008617A6, 0x008701C5,
200         0x008800C6, 0x00891B08,
201         0x008A0E06, 0x008B0666,
202         0x008C0E08, 0x008D0668,
203         0x008E1D7C, 0x008F0CE5,
204         0x00900C45, 0x00911E08,
205         0x009217A9, 0x009301C4,
206         0x009417AA, 0x009501C9,
207         0x00960169, 0x0097588A,
208         0x00981888, 0x00990066,
209         0x009A0709, 0x009B07A8,
210         0x009C0704, 0x009D07A6,
211         0x009E16E6, 0x009F0345,
212         0x00A000C9, 0x00A11B05,
213         0x00A20E09, 0x00A30669,
214         0x00A41885, 0x00A50065,
215         0x00A60706, 0x00A707A5,
216         0x00A803A9, 0x00A90189,
217         0x00AA0029, 0x00AB0889,
218         0x00AC0744, 0x00AD06E9,
219         0x00AE0B06, 0x00AF0229,
220         0x00B00E05, 0x00B10665,
221         0x00B21974, 0x00B30CE8,
222         0x00B4070A, 0x00B507A9,
223         0x00B616E9, 0x00B70348,
224         0x00B8074A, 0x00B906E6,
225         0x00BA0B09, 0x00BB0226,
226         0x00BC1CE4, 0x00BD0D7D,
227         0x00BE0269, 0x00BF08C9,
228         0x00C000CA, 0x00C11B04,
229         0x00C21884, 0x00C3006A,
230         0x00C40E04, 0x00C50664,
231         0x00C60708, 0x00C707AA,
232         0x00C803A8, 0x00C90184,
233         0x00CA0749, 0x00CB06E4,
234         0x00CC0020, 0x00CD0888,
235         0x00CE0B08, 0x00CF0224,
236         0x00D00E0A, 0x00D1066A,
237         0x00D20705, 0x00D307A4,
238         0x00D41D78, 0x00D50CE9,
239         0x00D616EA, 0x00D70349,
240         0x00D80745, 0x00D906E8,
241         0x00DA1CE9, 0x00DB0D75,
242         0x00DC0B04, 0x00DD0228,
243         0x00DE0268, 0x00DF08C8,
244         0x00E003A5, 0x00E10185,
245         0x00E20746, 0x00E306EA,
246         0x00E40748, 0x00E506E5,
247         0x00E61CE8, 0x00E70D79,
248         0x00E81D74, 0x00E95CE6,
249         0x00EA02E9, 0x00EB0849,
250         0x00EC02E8, 0x00ED0848,
251         0x00EE0086, 0x00EF0A08,
252         0x00F00021, 0x00F10885,
253         0x00F20B05, 0x00F3022A,
254         0x00F40B0A, 0x00F50225,
255         0x00F60265, 0x00F708C5,
256         0x00F802E5, 0x00F90845,
257         0x00FA0089, 0x00FB0A09,
258         0x00FC008A, 0x00FD0A0A,
259         0x00FE02A9, 0x00FF0062,
260     };
261
262     if (!hbmMask)
263         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
264
265     /* 1. make mask bitmap's dc */
266     hDCMask = CreateCompatibleDC(hdcDest);
267     hOldMaskBitmap = (HBITMAP)SelectObject(hDCMask, hbmMask);
268
269     /* 2. make masked Background bitmap */
270
271     /* 2.1 make bitmap */
272     hDC1 = CreateCompatibleDC(hdcDest);
273     hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
274     hOldBitmap2 = (HBITMAP)SelectObject(hDC1, hBitmap2);
275
276     /* 2.2 draw dest bitmap and mask */
277     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
278     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop));
279     BitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE);
280
281     /* 3. make masked Foreground bitmap */
282
283     /* 3.1 make bitmap */
284     hDC2 = CreateCompatibleDC(hdcDest);
285     hBitmap3 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
286     hOldBitmap3 = (HBITMAP)SelectObject(hDC2, hBitmap3);
287
288     /* 3.2 draw src bitmap and mask */
289     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
290     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
291     BitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND);
292
293     /* 4. combine two bitmap and copy it to hdcDest */
294     BitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT);
295     BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY);
296
297     /* 5. restore all object */
298     SelectObject(hDCMask, hOldMaskBitmap);
299     SelectObject(hDC1, hOldBitmap2);
300     SelectObject(hDC2, hOldBitmap3);
301
302     /* 6. delete all temp object */
303     DeleteObject(hBitmap2);
304     DeleteObject(hBitmap3);
305
306     DeleteDC(hDC1);
307     DeleteDC(hDC2);
308     DeleteDC(hDCMask);
309
310     return TRUE;
311 }
312
313 /*********************************************************************
314  *      PlgBlt [GDI32.@]
315  *
316  */
317 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
318                         HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
319                         INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
320 {
321     FIXME("PlgBlt, stub\n");
322         return 1;
323 }