2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
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.
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.
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
22 #include "gdi_private.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
28 /***********************************************************************
31 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
32 INT width, INT height, DWORD rop)
34 DC * dc = DC_GetDCUpdate( hdc );
37 if (!dc) return FALSE;
39 if (dc->funcs->pPatBlt)
41 TRACE("%p %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
42 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
44 GDI_ReleaseObj( hdc );
49 /***********************************************************************
52 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
53 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
58 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
59 /* FIXME: there is a race condition here */
60 if ((dcDst = DC_GetDCUpdate( hdcDst )))
62 dcSrc = DC_GetDCPtr( hdcSrc );
63 TRACE("hdcSrc=%p %d,%d -> hdcDest=%p %d,%d %dx%d rop=%06lx\n",
64 hdcSrc, xSrc, ySrc, hdcDst, xDst, yDst, width, height, 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 );
75 /***********************************************************************
76 * StretchBlt (GDI32.@)
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,
87 if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
88 /* FIXME: there is a race condition here */
89 if ((dcDst = DC_GetDCUpdate( hdcDst )))
91 dcSrc = DC_GetDCPtr( hdcSrc );
93 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06lx\n",
94 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
95 hdcDst, xDst, yDst, widthDst, heightDst, rop );
98 if (dcDst->funcs->pStretchBlt)
99 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
100 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
102 GDI_ReleaseObj( hdcSrc );
104 GDI_ReleaseObj( hdcDst );
109 static inline BYTE SwapROP3_SrcDst(BYTE bRop3)
111 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
114 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
115 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
116 #define DSTCOPY 0x00AA0029
117 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
119 /***********************************************************************
122 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
123 INT nWidth, INT nHeight, HDC hdcSrc,
124 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
125 INT xMask, INT yMask, DWORD dwRop)
127 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
128 HDC hDCMask, hDC1, hDC2;
129 static const DWORD ROP3Table[256] =
131 0x00000042, 0x00010289,
132 0x00020C89, 0x000300AA,
133 0x00040C88, 0x000500A9,
134 0x00060865, 0x000702C5,
135 0x00080F08, 0x00090245,
136 0x000A0329, 0x000B0B2A,
137 0x000C0324, 0x000D0B25,
138 0x000E08A5, 0x000F0001,
139 0x00100C85, 0x001100A6,
140 0x00120868, 0x001302C8,
141 0x00140869, 0x001502C9,
142 0x00165CCA, 0x00171D54,
143 0x00180D59, 0x00191CC8,
144 0x001A06C5, 0x001B0768,
145 0x001C06CA, 0x001D0766,
146 0x001E01A5, 0x001F0385,
147 0x00200F09, 0x00210248,
148 0x00220326, 0x00230B24,
149 0x00240D55, 0x00251CC5,
150 0x002606C8, 0x00271868,
151 0x00280369, 0x002916CA,
152 0x002A0CC9, 0x002B1D58,
153 0x002C0784, 0x002D060A,
154 0x002E064A, 0x002F0E2A,
155 0x0030032A, 0x00310B28,
156 0x00320688, 0x00330008,
157 0x003406C4, 0x00351864,
158 0x003601A8, 0x00370388,
159 0x0038078A, 0x00390604,
160 0x003A0644, 0x003B0E24,
161 0x003C004A, 0x003D18A4,
162 0x003E1B24, 0x003F00EA,
163 0x00400F0A, 0x00410249,
164 0x00420D5D, 0x00431CC4,
165 0x00440328, 0x00450B29,
166 0x004606C6, 0x0047076A,
167 0x00480368, 0x004916C5,
168 0x004A0789, 0x004B0605,
169 0x004C0CC8, 0x004D1954,
170 0x004E0645, 0x004F0E25,
171 0x00500325, 0x00510B26,
172 0x005206C9, 0x00530764,
173 0x005408A9, 0x00550009,
174 0x005601A9, 0x00570389,
175 0x00580785, 0x00590609,
176 0x005A0049, 0x005B18A9,
177 0x005C0649, 0x005D0E29,
178 0x005E1B29, 0x005F00E9,
179 0x00600365, 0x006116C6,
180 0x00620786, 0x00630608,
181 0x00640788, 0x00650606,
182 0x00660046, 0x006718A8,
183 0x006858A6, 0x00690145,
184 0x006A01E9, 0x006B178A,
185 0x006C01E8, 0x006D1785,
186 0x006E1E28, 0x006F0C65,
187 0x00700CC5, 0x00711D5C,
188 0x00720648, 0x00730E28,
189 0x00740646, 0x00750E26,
190 0x00761B28, 0x007700E6,
191 0x007801E5, 0x00791786,
192 0x007A1E29, 0x007B0C68,
193 0x007C1E24, 0x007D0C69,
194 0x007E0955, 0x007F03C9,
195 0x008003E9, 0x00810975,
196 0x00820C49, 0x00831E04,
197 0x00840C48, 0x00851E05,
198 0x008617A6, 0x008701C5,
199 0x008800C6, 0x00891B08,
200 0x008A0E06, 0x008B0666,
201 0x008C0E08, 0x008D0668,
202 0x008E1D7C, 0x008F0CE5,
203 0x00900C45, 0x00911E08,
204 0x009217A9, 0x009301C4,
205 0x009417AA, 0x009501C9,
206 0x00960169, 0x0097588A,
207 0x00981888, 0x00990066,
208 0x009A0709, 0x009B07A8,
209 0x009C0704, 0x009D07A6,
210 0x009E16E6, 0x009F0345,
211 0x00A000C9, 0x00A11B05,
212 0x00A20E09, 0x00A30669,
213 0x00A41885, 0x00A50065,
214 0x00A60706, 0x00A707A5,
215 0x00A803A9, 0x00A90189,
216 0x00AA0029, 0x00AB0889,
217 0x00AC0744, 0x00AD06E9,
218 0x00AE0B06, 0x00AF0229,
219 0x00B00E05, 0x00B10665,
220 0x00B21974, 0x00B30CE8,
221 0x00B4070A, 0x00B507A9,
222 0x00B616E9, 0x00B70348,
223 0x00B8074A, 0x00B906E6,
224 0x00BA0B09, 0x00BB0226,
225 0x00BC1CE4, 0x00BD0D7D,
226 0x00BE0269, 0x00BF08C9,
227 0x00C000CA, 0x00C11B04,
228 0x00C21884, 0x00C3006A,
229 0x00C40E04, 0x00C50664,
230 0x00C60708, 0x00C707AA,
231 0x00C803A8, 0x00C90184,
232 0x00CA0749, 0x00CB06E4,
233 0x00CC0020, 0x00CD0888,
234 0x00CE0B08, 0x00CF0224,
235 0x00D00E0A, 0x00D1066A,
236 0x00D20705, 0x00D307A4,
237 0x00D41D78, 0x00D50CE9,
238 0x00D616EA, 0x00D70349,
239 0x00D80745, 0x00D906E8,
240 0x00DA1CE9, 0x00DB0D75,
241 0x00DC0B04, 0x00DD0228,
242 0x00DE0268, 0x00DF08C8,
243 0x00E003A5, 0x00E10185,
244 0x00E20746, 0x00E306EA,
245 0x00E40748, 0x00E506E5,
246 0x00E61CE8, 0x00E70D79,
247 0x00E81D74, 0x00E95CE6,
248 0x00EA02E9, 0x00EB0849,
249 0x00EC02E8, 0x00ED0848,
250 0x00EE0086, 0x00EF0A08,
251 0x00F00021, 0x00F10885,
252 0x00F20B05, 0x00F3022A,
253 0x00F40B0A, 0x00F50225,
254 0x00F60265, 0x00F708C5,
255 0x00F802E5, 0x00F90845,
256 0x00FA0089, 0x00FB0A09,
257 0x00FC008A, 0x00FD0A0A,
258 0x00FE02A9, 0x00FF0062,
262 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
264 /* 1. make mask bitmap's dc */
265 hDCMask = CreateCompatibleDC(hdcDest);
266 hOldMaskBitmap = (HBITMAP)SelectObject(hDCMask, hbmMask);
268 /* 2. make masked Background bitmap */
270 /* 2.1 make bitmap */
271 hDC1 = CreateCompatibleDC(hdcDest);
272 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
273 hOldBitmap2 = (HBITMAP)SelectObject(hDC1, hBitmap2);
275 /* 2.2 draw dest bitmap and mask */
276 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
277 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop));
278 BitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE);
280 /* 3. make masked Foreground bitmap */
282 /* 3.1 make bitmap */
283 hDC2 = CreateCompatibleDC(hdcDest);
284 hBitmap3 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
285 hOldBitmap3 = (HBITMAP)SelectObject(hDC2, hBitmap3);
287 /* 3.2 draw src bitmap and mask */
288 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
289 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
290 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND);
292 /* 4. combine two bitmap and copy it to hdcDest */
293 BitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT);
294 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY);
296 /* 5. restore all object */
297 SelectObject(hDCMask, hOldMaskBitmap);
298 SelectObject(hDC1, hOldBitmap2);
299 SelectObject(hDC2, hOldBitmap3);
301 /* 6. delete all temp object */
302 DeleteObject(hBitmap2);
303 DeleteObject(hBitmap3);
312 /******************************************************************************
313 * GdiTransparentBlt [GDI32.@]
315 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
316 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
324 HBITMAP bmpMask = NULL;
325 HBITMAP oldMask = NULL;
326 COLORREF oldBackground;
327 COLORREF oldForeground;
330 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
331 TRACE("Can not mirror\n");
335 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
336 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
339 oldStretchMode = GetStretchBltMode(hdcSrc);
340 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
341 SetStretchBltMode(hdcSrc, COLORONCOLOR);
342 hdcWork = CreateCompatibleDC(hdcDest);
343 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
344 oldWork = SelectObject(hdcWork, bmpWork);
345 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
346 TRACE("Failed to stretch\n");
349 SetBkColor(hdcWork, crTransparent);
352 hdcMask = CreateCompatibleDC(hdcDest);
353 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
354 oldMask = SelectObject(hdcMask, bmpMask);
355 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
356 TRACE("Failed to create mask\n");
360 /* Replace transparent color with black */
361 SetBkColor(hdcWork, RGB(0,0,0));
362 SetTextColor(hdcWork, RGB(255,255,255));
363 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
364 TRACE("Failed to mask out background\n");
368 /* Replace non-transparent area on destination with black */
369 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
370 TRACE("Failed to clear destination area\n");
375 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
376 TRACE("Failed to paint image\n");
382 SetStretchBltMode(hdcSrc, oldStretchMode);
383 SetBkColor(hdcDest, oldBackground);
384 SetTextColor(hdcDest, oldForeground);
386 SelectObject(hdcWork, oldWork);
389 if(bmpWork) DeleteObject(bmpWork);
391 SelectObject(hdcMask, oldMask);
394 if(bmpMask) DeleteObject(bmpMask);
398 /******************************************************************************
399 * GdiAlphaBlend [GDI32.@]
401 BOOL WINAPI GdiAlphaBlend(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
402 HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
403 BLENDFUNCTION blendFunction)
405 FIXME("partial stub - using StretchBlt\n");
406 return StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
407 hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
411 /*********************************************************************
415 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
416 HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
417 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
419 FIXME("PlgBlt, stub\n");