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
33 #include "gdi_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
39 /***********************************************************************
42 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top,
43 INT width, INT height, DWORD rop)
45 DC * dc = get_dc_ptr( hdc );
48 if (!dc) return FALSE;
50 if (dc->funcs->pPatBlt)
52 TRACE("%p %d,%d %dx%d %06x\n", hdc, left, top, width, height, rop );
54 bRet = dc->funcs->pPatBlt( dc->physDev, left, top, width, height, rop );
61 /***********************************************************************
64 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
65 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
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 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
75 if (dcDst->funcs->pBitBlt)
78 dcSrc = get_dc_ptr( hdcSrc );
79 if (dcSrc) update_dc( dcSrc );
81 ret = dcDst->funcs->pBitBlt( dcDst->physDev, xDst, yDst, width, height,
82 dcSrc ? dcSrc->physDev : NULL, xSrc, ySrc, rop );
84 release_dc_ptr( dcDst );
85 if (dcSrc) release_dc_ptr( dcSrc );
87 else if (dcDst->funcs->pStretchDIBits)
90 BITMAPINFOHEADER info_hdr;
95 release_dc_ptr( dcDst );
97 if(GetObjectType( hdcSrc ) != OBJ_MEMDC)
99 FIXME("hdcSrc isn't a memory dc. Don't yet cope with this\n");
103 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
105 info_hdr.biSize = sizeof(info_hdr);
106 info_hdr.biWidth = bm.bmWidth;
107 info_hdr.biHeight = bm.bmHeight;
108 info_hdr.biPlanes = 1;
109 info_hdr.biBitCount = 32;
110 info_hdr.biCompression = BI_RGB;
111 info_hdr.biSizeImage = 0;
112 info_hdr.biXPelsPerMeter = 0;
113 info_hdr.biYPelsPerMeter = 0;
114 info_hdr.biClrUsed = 0;
115 info_hdr.biClrImportant = 0;
117 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
120 /* Select out the src bitmap before calling GetDIBits */
121 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
122 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
123 SelectObject(hdcSrc, hbm);
125 lines = StretchDIBits(hdcDst, xDst, yDst, width, height, xSrc, bm.bmHeight - height - ySrc,
126 width, height, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
128 HeapFree(GetProcessHeap(), 0, bits);
129 return (lines == height);
131 else release_dc_ptr( dcDst );
137 /***********************************************************************
138 * StretchBlt (GDI32.@)
140 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
141 INT widthDst, INT heightDst,
142 HDC hdcSrc, INT xSrc, INT ySrc,
143 INT widthSrc, INT heightSrc,
149 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d rop=%06x\n",
150 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
151 hdcDst, xDst, yDst, widthDst, heightDst, rop );
154 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
156 if (dcDst->funcs->pStretchBlt)
158 if ((dcSrc = get_dc_ptr( hdcSrc )))
163 ret = dcDst->funcs->pStretchBlt( dcDst->physDev, xDst, yDst, widthDst, heightDst,
164 dcSrc->physDev, xSrc, ySrc, widthSrc, heightSrc,
166 release_dc_ptr( dcDst );
167 release_dc_ptr( dcSrc );
170 else if (dcDst->funcs->pStretchDIBits)
173 BITMAPINFOHEADER info_hdr;
178 release_dc_ptr( dcDst );
180 if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
182 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
184 info_hdr.biSize = sizeof(info_hdr);
185 info_hdr.biWidth = bm.bmWidth;
186 info_hdr.biHeight = bm.bmHeight;
187 info_hdr.biPlanes = 1;
188 info_hdr.biBitCount = 32;
189 info_hdr.biCompression = BI_RGB;
190 info_hdr.biSizeImage = 0;
191 info_hdr.biXPelsPerMeter = 0;
192 info_hdr.biYPelsPerMeter = 0;
193 info_hdr.biClrUsed = 0;
194 info_hdr.biClrImportant = 0;
196 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
199 /* Select out the src bitmap before calling GetDIBits */
200 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
201 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
202 SelectObject(hdcSrc, hbm);
204 lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, bm.bmHeight - heightSrc - ySrc,
205 widthSrc, heightSrc, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
207 HeapFree(GetProcessHeap(), 0, bits);
208 return (lines == heightSrc);
210 else release_dc_ptr( dcDst );
215 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
216 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
218 /***********************************************************************
221 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
222 INT nWidth, INT nHeight, HDC hdcSrc,
223 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
224 INT xMask, INT yMask, DWORD dwRop)
226 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
228 HBRUSH hbrMask, hbrDst, hbrTmp;
230 static const DWORD ROP3Table[256] =
232 0x00000042, 0x00010289,
233 0x00020C89, 0x000300AA,
234 0x00040C88, 0x000500A9,
235 0x00060865, 0x000702C5,
236 0x00080F08, 0x00090245,
237 0x000A0329, 0x000B0B2A,
238 0x000C0324, 0x000D0B25,
239 0x000E08A5, 0x000F0001,
240 0x00100C85, 0x001100A6,
241 0x00120868, 0x001302C8,
242 0x00140869, 0x001502C9,
243 0x00165CCA, 0x00171D54,
244 0x00180D59, 0x00191CC8,
245 0x001A06C5, 0x001B0768,
246 0x001C06CA, 0x001D0766,
247 0x001E01A5, 0x001F0385,
248 0x00200F09, 0x00210248,
249 0x00220326, 0x00230B24,
250 0x00240D55, 0x00251CC5,
251 0x002606C8, 0x00271868,
252 0x00280369, 0x002916CA,
253 0x002A0CC9, 0x002B1D58,
254 0x002C0784, 0x002D060A,
255 0x002E064A, 0x002F0E2A,
256 0x0030032A, 0x00310B28,
257 0x00320688, 0x00330008,
258 0x003406C4, 0x00351864,
259 0x003601A8, 0x00370388,
260 0x0038078A, 0x00390604,
261 0x003A0644, 0x003B0E24,
262 0x003C004A, 0x003D18A4,
263 0x003E1B24, 0x003F00EA,
264 0x00400F0A, 0x00410249,
265 0x00420D5D, 0x00431CC4,
266 0x00440328, 0x00450B29,
267 0x004606C6, 0x0047076A,
268 0x00480368, 0x004916C5,
269 0x004A0789, 0x004B0605,
270 0x004C0CC8, 0x004D1954,
271 0x004E0645, 0x004F0E25,
272 0x00500325, 0x00510B26,
273 0x005206C9, 0x00530764,
274 0x005408A9, 0x00550009,
275 0x005601A9, 0x00570389,
276 0x00580785, 0x00590609,
277 0x005A0049, 0x005B18A9,
278 0x005C0649, 0x005D0E29,
279 0x005E1B29, 0x005F00E9,
280 0x00600365, 0x006116C6,
281 0x00620786, 0x00630608,
282 0x00640788, 0x00650606,
283 0x00660046, 0x006718A8,
284 0x006858A6, 0x00690145,
285 0x006A01E9, 0x006B178A,
286 0x006C01E8, 0x006D1785,
287 0x006E1E28, 0x006F0C65,
288 0x00700CC5, 0x00711D5C,
289 0x00720648, 0x00730E28,
290 0x00740646, 0x00750E26,
291 0x00761B28, 0x007700E6,
292 0x007801E5, 0x00791786,
293 0x007A1E29, 0x007B0C68,
294 0x007C1E24, 0x007D0C69,
295 0x007E0955, 0x007F03C9,
296 0x008003E9, 0x00810975,
297 0x00820C49, 0x00831E04,
298 0x00840C48, 0x00851E05,
299 0x008617A6, 0x008701C5,
300 0x008800C6, 0x00891B08,
301 0x008A0E06, 0x008B0666,
302 0x008C0E08, 0x008D0668,
303 0x008E1D7C, 0x008F0CE5,
304 0x00900C45, 0x00911E08,
305 0x009217A9, 0x009301C4,
306 0x009417AA, 0x009501C9,
307 0x00960169, 0x0097588A,
308 0x00981888, 0x00990066,
309 0x009A0709, 0x009B07A8,
310 0x009C0704, 0x009D07A6,
311 0x009E16E6, 0x009F0345,
312 0x00A000C9, 0x00A11B05,
313 0x00A20E09, 0x00A30669,
314 0x00A41885, 0x00A50065,
315 0x00A60706, 0x00A707A5,
316 0x00A803A9, 0x00A90189,
317 0x00AA0029, 0x00AB0889,
318 0x00AC0744, 0x00AD06E9,
319 0x00AE0B06, 0x00AF0229,
320 0x00B00E05, 0x00B10665,
321 0x00B21974, 0x00B30CE8,
322 0x00B4070A, 0x00B507A9,
323 0x00B616E9, 0x00B70348,
324 0x00B8074A, 0x00B906E6,
325 0x00BA0B09, 0x00BB0226,
326 0x00BC1CE4, 0x00BD0D7D,
327 0x00BE0269, 0x00BF08C9,
328 0x00C000CA, 0x00C11B04,
329 0x00C21884, 0x00C3006A,
330 0x00C40E04, 0x00C50664,
331 0x00C60708, 0x00C707AA,
332 0x00C803A8, 0x00C90184,
333 0x00CA0749, 0x00CB06E4,
334 0x00CC0020, 0x00CD0888,
335 0x00CE0B08, 0x00CF0224,
336 0x00D00E0A, 0x00D1066A,
337 0x00D20705, 0x00D307A4,
338 0x00D41D78, 0x00D50CE9,
339 0x00D616EA, 0x00D70349,
340 0x00D80745, 0x00D906E8,
341 0x00DA1CE9, 0x00DB0D75,
342 0x00DC0B04, 0x00DD0228,
343 0x00DE0268, 0x00DF08C8,
344 0x00E003A5, 0x00E10185,
345 0x00E20746, 0x00E306EA,
346 0x00E40748, 0x00E506E5,
347 0x00E61CE8, 0x00E70D79,
348 0x00E81D74, 0x00E95CE6,
349 0x00EA02E9, 0x00EB0849,
350 0x00EC02E8, 0x00ED0848,
351 0x00EE0086, 0x00EF0A08,
352 0x00F00021, 0x00F10885,
353 0x00F20B05, 0x00F3022A,
354 0x00F40B0A, 0x00F50225,
355 0x00F60265, 0x00F708C5,
356 0x00F802E5, 0x00F90845,
357 0x00FA0089, 0x00FB0A09,
358 0x00FC008A, 0x00FD0A0A,
359 0x00FE02A9, 0x00FF0062,
363 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
365 hbrMask = CreatePatternBrush(hbmMask);
366 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
369 hDC1 = CreateCompatibleDC(hdcDest);
370 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
371 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
373 /* draw using bkgnd rop */
374 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
375 hbrTmp = SelectObject(hDC1, hbrDst);
376 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
377 SelectObject(hDC1, hbrTmp);
380 hDC2 = CreateCompatibleDC(hdcDest);
381 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
382 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
384 /* draw using foregnd rop */
385 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
386 hbrTmp = SelectObject(hDC2, hbrDst);
387 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
389 /* combine both using the mask as a pattern brush */
390 SelectObject(hDC2, hbrMask);
391 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
392 SelectObject(hDC2, hbrTmp);
395 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
397 /* restore all objects */
398 SelectObject(hdcDest, hbrDst);
399 SelectObject(hDC1, hOldBitmap1);
400 SelectObject(hDC2, hOldBitmap2);
402 /* delete all temp objects */
403 DeleteObject(hBitmap1);
404 DeleteObject(hBitmap2);
405 DeleteObject(hbrMask);
413 /******************************************************************************
414 * GdiTransparentBlt [GDI32.@]
416 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
417 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
425 HBITMAP bmpMask = NULL;
426 HBITMAP oldMask = NULL;
427 COLORREF oldBackground;
428 COLORREF oldForeground;
431 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
432 TRACE("Cannot mirror\n");
436 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
437 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
440 oldStretchMode = GetStretchBltMode(hdcSrc);
441 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
442 SetStretchBltMode(hdcSrc, COLORONCOLOR);
443 hdcWork = CreateCompatibleDC(hdcDest);
444 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
445 oldWork = SelectObject(hdcWork, bmpWork);
446 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
447 TRACE("Failed to stretch\n");
450 SetBkColor(hdcWork, crTransparent);
453 hdcMask = CreateCompatibleDC(hdcDest);
454 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
455 oldMask = SelectObject(hdcMask, bmpMask);
456 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
457 TRACE("Failed to create mask\n");
461 /* Replace transparent color with black */
462 SetBkColor(hdcWork, RGB(0,0,0));
463 SetTextColor(hdcWork, RGB(255,255,255));
464 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
465 TRACE("Failed to mask out background\n");
469 /* Replace non-transparent area on destination with black */
470 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
471 TRACE("Failed to clear destination area\n");
476 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
477 TRACE("Failed to paint image\n");
483 SetStretchBltMode(hdcSrc, oldStretchMode);
484 SetBkColor(hdcDest, oldBackground);
485 SetTextColor(hdcDest, oldForeground);
487 SelectObject(hdcWork, oldWork);
490 if(bmpWork) DeleteObject(bmpWork);
492 SelectObject(hdcMask, oldMask);
495 if(bmpMask) DeleteObject(bmpMask);
499 /******************************************************************************
500 * GdiAlphaBlend [GDI32.@]
502 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
503 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
504 BLENDFUNCTION blendFunction)
509 dcSrc = get_dc_ptr( hdcSrc );
510 if ((dcDst = get_dc_ptr( hdcDst )))
512 if (dcSrc) update_dc( dcSrc );
514 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
515 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
516 hdcDst, xDst, yDst, widthDst, heightDst,
517 blendFunction.BlendOp, blendFunction.BlendFlags,
518 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
519 if (dcDst->funcs->pAlphaBlend)
520 ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
521 dcSrc ? dcSrc->physDev : NULL,
522 xSrc, ySrc, widthSrc, heightSrc, blendFunction );
523 release_dc_ptr( dcDst );
525 if (dcSrc) release_dc_ptr( dcSrc );
529 /*********************************************************************
533 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
534 HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
535 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
538 /* parallelogram coords */
547 /* save actual mode, set GM_ADVANCED */
548 oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
552 memcpy(plg,lpPoint,sizeof(POINT)*3);
555 rect[1].x = nXSrc + nWidth;
558 rect[2].y = nYSrc + nHeight;
559 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
561 det = rect[1].x*(rect[2].y - rect[0].y) - rect[2].x*(rect[1].y - rect[0].y) - rect[0].x*(rect[2].y - rect[1].y);
563 if (fabs(det) < 1e-5)
565 SetGraphicsMode(hdcDest,oldgMode);
569 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
570 hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
573 xf.eM11 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det;
574 xf.eM21 = (rect[1].x*(plg[2].x - plg[0].x) - rect[2].x*(plg[1].x - plg[0].x) - rect[0].x*(plg[2].x - plg[1].x)) / det;
575 xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
576 rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
577 rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
581 xf.eM12 = (plg[1].y*(rect[2].y - rect[0].y) - plg[2].y*(rect[1].y - rect[0].y) - plg[0].y*(rect[2].y - rect[1].y)) / det;
582 xf.eM22 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det;
583 xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
584 rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
585 rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
588 GetWorldTransform(hdcSrc,&SrcXf);
589 CombineTransform(&xf,&xf,&SrcXf);
591 /* save actual dest transform */
592 GetWorldTransform(hdcDest,&oldDestXf);
594 SetWorldTransform(hdcDest,&xf);
595 /* now destination and source DCs use same coords */
596 MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
600 /* restore dest DC */
601 SetWorldTransform(hdcDest,&oldDestXf);
602 SetGraphicsMode(hdcDest,oldgMode);