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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "gdi_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
32 /***********************************************************************
35 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
36 INT width, INT height, DWORD rop)
38 DC * dc = get_dc_ptr( hdc );
41 if (!dc) return FALSE;
43 if (dc->funcs->pPatBlt)
45 TRACE("%p %d,%d %dx%d %06x\n", hdc, left, top, width, height, rop );
47 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
54 /***********************************************************************
57 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
58 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
63 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
65 if (dcDst->funcs->pBitBlt)
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);
73 ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
74 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
76 release_dc_ptr( dcDst );
77 if (dcSrc) release_dc_ptr( dcSrc );
79 else if (dcDst->funcs->pStretchDIBits)
82 BITMAPINFOHEADER info_hdr;
87 release_dc_ptr( dcDst );
89 if(GetObjectType( hdcSrc ) != OBJ_MEMDC)
91 FIXME("hdcSrc isn't a memory dc. Don't yet cope with this\n");
95 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
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;
109 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
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);
117 lines = StretchDIBits(hdcDst, xDst, yDst, width, height, xSrc, bm.bmHeight - height - ySrc,
118 width, height, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
120 HeapFree(GetProcessHeap(), 0, bits);
121 return (lines == height);
123 else release_dc_ptr( dcDst );
129 /***********************************************************************
130 * StretchBlt (GDI32.@)
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,
141 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
143 if (dcDst->funcs->pStretchBlt)
145 if ((dcSrc = get_dc_ptr( hdcSrc )))
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 );
154 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
155 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
157 release_dc_ptr( dcDst );
158 release_dc_ptr( dcSrc );
161 else if (dcDst->funcs->pStretchDIBits)
164 BITMAPINFOHEADER info_hdr;
169 release_dc_ptr( dcDst );
171 if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
173 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
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;
187 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
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);
195 lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, bm.bmHeight - heightSrc - ySrc,
196 widthSrc, heightSrc, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
198 HeapFree(GetProcessHeap(), 0, bits);
199 return (lines == heightSrc);
201 else release_dc_ptr( dcDst );
206 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
207 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
209 /***********************************************************************
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)
217 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
219 HBRUSH hbrMask, hbrDst, hbrTmp;
221 static const DWORD ROP3Table[256] =
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,
354 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
356 hbrMask = CreatePatternBrush(hbmMask);
357 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
360 hDC1 = CreateCompatibleDC(hdcDest);
361 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
362 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
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);
371 hDC2 = CreateCompatibleDC(hdcDest);
372 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
373 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
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));
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);
386 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
388 /* restore all objects */
389 SelectObject(hdcDest, hbrDst);
390 SelectObject(hDC1, hOldBitmap1);
391 SelectObject(hDC2, hOldBitmap2);
393 /* delete all temp objects */
394 DeleteObject(hBitmap1);
395 DeleteObject(hBitmap2);
396 DeleteObject(hbrMask);
404 /******************************************************************************
405 * GdiTransparentBlt [GDI32.@]
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,
416 HBITMAP bmpMask = NULL;
417 HBITMAP oldMask = NULL;
418 COLORREF oldBackground;
419 COLORREF oldForeground;
422 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
423 TRACE("Cannot mirror\n");
427 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
428 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
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");
441 SetBkColor(hdcWork, crTransparent);
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");
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");
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");
467 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
468 TRACE("Failed to paint image\n");
474 SetStretchBltMode(hdcSrc, oldStretchMode);
475 SetBkColor(hdcDest, oldBackground);
476 SetTextColor(hdcDest, oldForeground);
478 SelectObject(hdcWork, oldWork);
481 if(bmpWork) DeleteObject(bmpWork);
483 SelectObject(hdcMask, oldMask);
486 if(bmpMask) DeleteObject(bmpMask);
490 /******************************************************************************
491 * GdiAlphaBlend [GDI32.@]
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)
500 dcSrc = get_dc_ptr( hdcSrc );
501 if ((dcDst = get_dc_ptr( hdcDst )))
503 if (dcSrc) update_dc( dcSrc );
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 );
516 if (dcSrc) release_dc_ptr( dcSrc );
520 /*********************************************************************
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)
528 FIXME("PlgBlt, stub\n");