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;
181 pts[1].x = xSrc + widthSrc;
182 pts[1].y = ySrc + heightSrc;
183 LPtoDP(hdcSrc, pts, 2);
186 widthSrc = pts[1].x - pts[0].x;
187 heightSrc = pts[1].y - pts[0].y;
189 release_dc_ptr( dcDst );
191 if(GetObjectType( hdcSrc ) != OBJ_MEMDC) return FALSE;
193 GetObjectW(GetCurrentObject(hdcSrc, OBJ_BITMAP), sizeof(bm), &bm);
195 info_hdr.biSize = sizeof(info_hdr);
196 info_hdr.biWidth = bm.bmWidth;
197 info_hdr.biHeight = bm.bmHeight;
198 info_hdr.biPlanes = 1;
199 info_hdr.biBitCount = 32;
200 info_hdr.biCompression = BI_RGB;
201 info_hdr.biSizeImage = 0;
202 info_hdr.biXPelsPerMeter = 0;
203 info_hdr.biYPelsPerMeter = 0;
204 info_hdr.biClrUsed = 0;
205 info_hdr.biClrImportant = 0;
207 if(!(bits = HeapAlloc(GetProcessHeap(), 0, bm.bmHeight * bm.bmWidth * 4)))
210 /* Select out the src bitmap before calling GetDIBits */
211 hbm = SelectObject(hdcSrc, GetStockObject(DEFAULT_BITMAP));
212 GetDIBits(hdcSrc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS);
213 SelectObject(hdcSrc, hbm);
215 lines = StretchDIBits(hdcDst, xDst, yDst, widthDst, heightDst, xSrc, bm.bmHeight - heightSrc - ySrc,
216 widthSrc, heightSrc, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop);
218 HeapFree(GetProcessHeap(), 0, bits);
219 return (lines == heightSrc);
221 else release_dc_ptr( dcDst );
226 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
227 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
229 /***********************************************************************
232 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
233 INT nWidth, INT nHeight, HDC hdcSrc,
234 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
235 INT xMask, INT yMask, DWORD dwRop)
237 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
239 HBRUSH hbrMask, hbrDst, hbrTmp;
241 static const DWORD ROP3Table[256] =
243 0x00000042, 0x00010289,
244 0x00020C89, 0x000300AA,
245 0x00040C88, 0x000500A9,
246 0x00060865, 0x000702C5,
247 0x00080F08, 0x00090245,
248 0x000A0329, 0x000B0B2A,
249 0x000C0324, 0x000D0B25,
250 0x000E08A5, 0x000F0001,
251 0x00100C85, 0x001100A6,
252 0x00120868, 0x001302C8,
253 0x00140869, 0x001502C9,
254 0x00165CCA, 0x00171D54,
255 0x00180D59, 0x00191CC8,
256 0x001A06C5, 0x001B0768,
257 0x001C06CA, 0x001D0766,
258 0x001E01A5, 0x001F0385,
259 0x00200F09, 0x00210248,
260 0x00220326, 0x00230B24,
261 0x00240D55, 0x00251CC5,
262 0x002606C8, 0x00271868,
263 0x00280369, 0x002916CA,
264 0x002A0CC9, 0x002B1D58,
265 0x002C0784, 0x002D060A,
266 0x002E064A, 0x002F0E2A,
267 0x0030032A, 0x00310B28,
268 0x00320688, 0x00330008,
269 0x003406C4, 0x00351864,
270 0x003601A8, 0x00370388,
271 0x0038078A, 0x00390604,
272 0x003A0644, 0x003B0E24,
273 0x003C004A, 0x003D18A4,
274 0x003E1B24, 0x003F00EA,
275 0x00400F0A, 0x00410249,
276 0x00420D5D, 0x00431CC4,
277 0x00440328, 0x00450B29,
278 0x004606C6, 0x0047076A,
279 0x00480368, 0x004916C5,
280 0x004A0789, 0x004B0605,
281 0x004C0CC8, 0x004D1954,
282 0x004E0645, 0x004F0E25,
283 0x00500325, 0x00510B26,
284 0x005206C9, 0x00530764,
285 0x005408A9, 0x00550009,
286 0x005601A9, 0x00570389,
287 0x00580785, 0x00590609,
288 0x005A0049, 0x005B18A9,
289 0x005C0649, 0x005D0E29,
290 0x005E1B29, 0x005F00E9,
291 0x00600365, 0x006116C6,
292 0x00620786, 0x00630608,
293 0x00640788, 0x00650606,
294 0x00660046, 0x006718A8,
295 0x006858A6, 0x00690145,
296 0x006A01E9, 0x006B178A,
297 0x006C01E8, 0x006D1785,
298 0x006E1E28, 0x006F0C65,
299 0x00700CC5, 0x00711D5C,
300 0x00720648, 0x00730E28,
301 0x00740646, 0x00750E26,
302 0x00761B28, 0x007700E6,
303 0x007801E5, 0x00791786,
304 0x007A1E29, 0x007B0C68,
305 0x007C1E24, 0x007D0C69,
306 0x007E0955, 0x007F03C9,
307 0x008003E9, 0x00810975,
308 0x00820C49, 0x00831E04,
309 0x00840C48, 0x00851E05,
310 0x008617A6, 0x008701C5,
311 0x008800C6, 0x00891B08,
312 0x008A0E06, 0x008B0666,
313 0x008C0E08, 0x008D0668,
314 0x008E1D7C, 0x008F0CE5,
315 0x00900C45, 0x00911E08,
316 0x009217A9, 0x009301C4,
317 0x009417AA, 0x009501C9,
318 0x00960169, 0x0097588A,
319 0x00981888, 0x00990066,
320 0x009A0709, 0x009B07A8,
321 0x009C0704, 0x009D07A6,
322 0x009E16E6, 0x009F0345,
323 0x00A000C9, 0x00A11B05,
324 0x00A20E09, 0x00A30669,
325 0x00A41885, 0x00A50065,
326 0x00A60706, 0x00A707A5,
327 0x00A803A9, 0x00A90189,
328 0x00AA0029, 0x00AB0889,
329 0x00AC0744, 0x00AD06E9,
330 0x00AE0B06, 0x00AF0229,
331 0x00B00E05, 0x00B10665,
332 0x00B21974, 0x00B30CE8,
333 0x00B4070A, 0x00B507A9,
334 0x00B616E9, 0x00B70348,
335 0x00B8074A, 0x00B906E6,
336 0x00BA0B09, 0x00BB0226,
337 0x00BC1CE4, 0x00BD0D7D,
338 0x00BE0269, 0x00BF08C9,
339 0x00C000CA, 0x00C11B04,
340 0x00C21884, 0x00C3006A,
341 0x00C40E04, 0x00C50664,
342 0x00C60708, 0x00C707AA,
343 0x00C803A8, 0x00C90184,
344 0x00CA0749, 0x00CB06E4,
345 0x00CC0020, 0x00CD0888,
346 0x00CE0B08, 0x00CF0224,
347 0x00D00E0A, 0x00D1066A,
348 0x00D20705, 0x00D307A4,
349 0x00D41D78, 0x00D50CE9,
350 0x00D616EA, 0x00D70349,
351 0x00D80745, 0x00D906E8,
352 0x00DA1CE9, 0x00DB0D75,
353 0x00DC0B04, 0x00DD0228,
354 0x00DE0268, 0x00DF08C8,
355 0x00E003A5, 0x00E10185,
356 0x00E20746, 0x00E306EA,
357 0x00E40748, 0x00E506E5,
358 0x00E61CE8, 0x00E70D79,
359 0x00E81D74, 0x00E95CE6,
360 0x00EA02E9, 0x00EB0849,
361 0x00EC02E8, 0x00ED0848,
362 0x00EE0086, 0x00EF0A08,
363 0x00F00021, 0x00F10885,
364 0x00F20B05, 0x00F3022A,
365 0x00F40B0A, 0x00F50225,
366 0x00F60265, 0x00F708C5,
367 0x00F802E5, 0x00F90845,
368 0x00FA0089, 0x00FB0A09,
369 0x00FC008A, 0x00FD0A0A,
370 0x00FE02A9, 0x00FF0062,
374 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
376 hbrMask = CreatePatternBrush(hbmMask);
377 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
380 hDC1 = CreateCompatibleDC(hdcDest);
381 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
382 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
384 /* draw using bkgnd rop */
385 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
386 hbrTmp = SelectObject(hDC1, hbrDst);
387 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
388 SelectObject(hDC1, hbrTmp);
391 hDC2 = CreateCompatibleDC(hdcDest);
392 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
393 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
395 /* draw using foregnd rop */
396 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
397 hbrTmp = SelectObject(hDC2, hbrDst);
398 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
400 /* combine both using the mask as a pattern brush */
401 SelectObject(hDC2, hbrMask);
402 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
403 SelectObject(hDC2, hbrTmp);
406 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
408 /* restore all objects */
409 SelectObject(hdcDest, hbrDst);
410 SelectObject(hDC1, hOldBitmap1);
411 SelectObject(hDC2, hOldBitmap2);
413 /* delete all temp objects */
414 DeleteObject(hBitmap1);
415 DeleteObject(hBitmap2);
416 DeleteObject(hbrMask);
424 /******************************************************************************
425 * GdiTransparentBlt [GDI32.@]
427 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
428 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
436 HBITMAP bmpMask = NULL;
437 HBITMAP oldMask = NULL;
438 COLORREF oldBackground;
439 COLORREF oldForeground;
442 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
443 TRACE("Cannot mirror\n");
447 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
448 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
451 oldStretchMode = GetStretchBltMode(hdcSrc);
452 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
453 SetStretchBltMode(hdcSrc, COLORONCOLOR);
454 hdcWork = CreateCompatibleDC(hdcDest);
455 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
456 oldWork = SelectObject(hdcWork, bmpWork);
457 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
458 TRACE("Failed to stretch\n");
461 SetBkColor(hdcWork, crTransparent);
464 hdcMask = CreateCompatibleDC(hdcDest);
465 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
466 oldMask = SelectObject(hdcMask, bmpMask);
467 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
468 TRACE("Failed to create mask\n");
472 /* Replace transparent color with black */
473 SetBkColor(hdcWork, RGB(0,0,0));
474 SetTextColor(hdcWork, RGB(255,255,255));
475 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
476 TRACE("Failed to mask out background\n");
480 /* Replace non-transparent area on destination with black */
481 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
482 TRACE("Failed to clear destination area\n");
487 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
488 TRACE("Failed to paint image\n");
494 SetStretchBltMode(hdcSrc, oldStretchMode);
495 SetBkColor(hdcDest, oldBackground);
496 SetTextColor(hdcDest, oldForeground);
498 SelectObject(hdcWork, oldWork);
501 if(bmpWork) DeleteObject(bmpWork);
503 SelectObject(hdcMask, oldMask);
506 if(bmpMask) DeleteObject(bmpMask);
510 /******************************************************************************
511 * GdiAlphaBlend [GDI32.@]
513 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
514 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
515 BLENDFUNCTION blendFunction)
520 dcSrc = get_dc_ptr( hdcSrc );
521 if ((dcDst = get_dc_ptr( hdcDst )))
523 if (dcSrc) update_dc( dcSrc );
525 TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
526 hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
527 hdcDst, xDst, yDst, widthDst, heightDst,
528 blendFunction.BlendOp, blendFunction.BlendFlags,
529 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat);
530 if (dcDst->funcs->pAlphaBlend)
531 ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
532 dcSrc ? dcSrc->physDev : NULL,
533 xSrc, ySrc, widthSrc, heightSrc, blendFunction );
534 release_dc_ptr( dcDst );
536 if (dcSrc) release_dc_ptr( dcSrc );
540 /*********************************************************************
544 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
545 HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
546 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
549 /* parallelogram coords */
558 /* save actual mode, set GM_ADVANCED */
559 oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
563 memcpy(plg,lpPoint,sizeof(POINT)*3);
566 rect[1].x = nXSrc + nWidth;
569 rect[2].y = nYSrc + nHeight;
570 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
572 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);
574 if (fabs(det) < 1e-5)
576 SetGraphicsMode(hdcDest,oldgMode);
580 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
581 hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
584 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;
585 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;
586 xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
587 rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
588 rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
592 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;
593 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;
594 xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
595 rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
596 rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
599 GetWorldTransform(hdcSrc,&SrcXf);
600 CombineTransform(&xf,&xf,&SrcXf);
602 /* save actual dest transform */
603 GetWorldTransform(hdcDest,&oldDestXf);
605 SetWorldTransform(hdcDest,&xf);
606 /* now destination and source DCs use same coords */
607 MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
611 /* restore dest DC */
612 SetWorldTransform(hdcDest,&oldDestXf);
613 SetGraphicsMode(hdcDest,oldgMode);