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);
38 static inline BOOL rop_uses_src( DWORD rop )
40 return ((rop >> 2) & 0x330000) != (rop & 0x330000);
43 static inline void swap_ints( int *i, int *j )
50 static BOOL get_vis_rectangles( DC *dc_dst, struct bitblt_coords *dst,
51 DC *dc_src, struct bitblt_coords *src )
55 /* get the destination visible rectangle */
57 rect.left = dst->log_x;
58 rect.top = dst->log_y;
59 rect.right = dst->log_x + dst->log_width;
60 rect.bottom = dst->log_y + dst->log_height;
61 LPtoDP( dc_dst->hSelf, (POINT *)&rect, 2 );
64 dst->width = rect.right - rect.left;
65 dst->height = rect.bottom - rect.top;
66 if (dst->layout & LAYOUT_RTL && dst->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
68 swap_ints( &rect.left, &rect.right );
70 dst->width = rect.right - rect.left;
72 if (rect.left > rect.right) { swap_ints( &rect.left, &rect.right ); rect.left++; rect.right++; }
73 if (rect.top > rect.bottom) { swap_ints( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
75 if (get_clip_box( dc_dst, &clip ))
76 intersect_rect( &dst->visrect, &rect, &clip );
80 /* get the source visible rectangle */
82 if (!src) return !is_rect_empty( &dst->visrect );
84 rect.left = src->log_x;
85 rect.top = src->log_y;
86 rect.right = src->log_x + src->log_width;
87 rect.bottom = src->log_y + src->log_height;
88 LPtoDP( dc_src->hSelf, (POINT *)&rect, 2 );
91 src->width = rect.right - rect.left;
92 src->height = rect.bottom - rect.top;
93 if (src->layout & LAYOUT_RTL && src->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
95 swap_ints( &rect.left, &rect.right );
97 src->width = rect.right - rect.left;
99 if (rect.left > rect.right) { swap_ints( &rect.left, &rect.right ); rect.left++; rect.right++; }
100 if (rect.top > rect.bottom) { swap_ints( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
102 /* source is not clipped */
103 if (dc_src->header.type == OBJ_MEMDC)
104 intersect_rect( &src->visrect, &rect, &dc_src->vis_rect );
106 src->visrect = rect; /* FIXME: clip to device size */
108 if (is_rect_empty( &src->visrect )) return FALSE;
109 if (is_rect_empty( &dst->visrect )) return FALSE;
111 /* intersect the rectangles */
113 if ((src->width == dst->width) && (src->height == dst->height)) /* no stretching */
115 offset_rect( &src->visrect, dst->x - src->x, dst->y - src->y );
116 intersect_rect( &rect, &src->visrect, &dst->visrect );
117 src->visrect = dst->visrect = rect;
118 offset_rect( &src->visrect, src->x - dst->x, src->y - dst->y );
120 else /* stretching */
122 /* map source rectangle into destination coordinates */
123 rect.left = dst->x + (src->visrect.left - src->x)*dst->width/src->width;
124 rect.top = dst->y + (src->visrect.top - src->y)*dst->height/src->height;
125 rect.right = dst->x + (src->visrect.right - src->x)*dst->width/src->width;
126 rect.bottom = dst->y + (src->visrect.bottom - src->y)*dst->height/src->height;
127 if (rect.left > rect.right) swap_ints( &rect.left, &rect.right );
128 if (rect.top > rect.bottom) swap_ints( &rect.top, &rect.bottom );
130 /* avoid rounding errors */
135 if (!intersect_rect( &dst->visrect, &rect, &dst->visrect )) return FALSE;
137 /* map destination rectangle back to source coordinates */
138 rect.left = src->x + (dst->visrect.left - dst->x)*src->width/dst->width;
139 rect.top = src->y + (dst->visrect.top - dst->y)*src->height/dst->height;
140 rect.right = src->x + (dst->visrect.right - dst->x)*src->width/dst->width;
141 rect.bottom = src->y + (dst->visrect.bottom - dst->y)*src->height/dst->height;
142 if (rect.left > rect.right) swap_ints( &rect.left, &rect.right );
143 if (rect.top > rect.bottom) swap_ints( &rect.top, &rect.bottom );
145 /* avoid rounding errors */
150 if (!intersect_rect( &src->visrect, &rect, &src->visrect )) return FALSE;
155 void free_heap_bits( struct gdi_image_bits *bits )
157 HeapFree( GetProcessHeap(), 0, bits->ptr );
160 /* nulldrv fallback implementation using StretchDIBits */
161 BOOL nulldrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
162 PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
164 DC *dc_src, *dc_dst = get_nulldrv_dc( dst_dev );
165 char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
166 char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
167 BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
168 BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
170 struct gdi_image_bits bits;
173 if (!(dc_src = get_dc_ptr( src_dev->hdc ))) return FALSE;
174 src_dev = GET_DC_PHYSDEV( dc_src, pGetImage );
175 err = src_dev->funcs->pGetImage( src_dev, 0, src_info, &bits, src );
176 release_dc_ptr( dc_src );
177 if (err) return FALSE;
179 dst_dev = GET_DC_PHYSDEV( dc_dst, pPutImage );
180 memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
181 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, dst_info, &bits, src, dst, rop );
182 if (err == ERROR_BAD_FORMAT)
184 /* 1-bpp source without a color table uses the destination DC colors */
185 if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
187 COLORREF color = GetTextColor( dst_dev->hdc );
188 src_info->bmiColors[0].rgbRed = GetRValue( color );
189 src_info->bmiColors[0].rgbGreen = GetGValue( color );
190 src_info->bmiColors[0].rgbBlue = GetBValue( color );
191 src_info->bmiColors[0].rgbReserved = 0;
192 color = GetBkColor( dst_dev->hdc );
193 src_info->bmiColors[1].rgbRed = GetRValue( color );
194 src_info->bmiColors[1].rgbGreen = GetGValue( color );
195 src_info->bmiColors[1].rgbBlue = GetBValue( color );
196 src_info->bmiColors[1].rgbReserved = 0;
197 src_info->bmiHeader.biClrUsed = 2;
200 /* 1-bpp destination without a color table requires a fake 1-entry table
201 * that contains only the background color */
202 if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
204 COLORREF color = GetBkColor( src_dev->hdc );
205 dst_info->bmiColors[0].rgbRed = GetRValue( color );
206 dst_info->bmiColors[0].rgbGreen = GetGValue( color );
207 dst_info->bmiColors[0].rgbBlue = GetBValue( color );
208 dst_info->bmiColors[0].rgbReserved = 0;
209 dst_info->bmiHeader.biClrUsed = 1;
212 dst_info->bmiHeader.biWidth = src->visrect.right - src->visrect.left;
213 if ((ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ))))
215 err = convert_bitmapinfo( src_info, bits.ptr, src, dst_info, ptr );
216 if (bits.free) bits.free( &bits );
219 bits.free = free_heap_bits;
222 /* get rid of the fake 1-bpp table */
223 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
224 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, dst_info, &bits, src, dst, rop );
227 else err = ERROR_OUTOFMEMORY;
230 if (err == ERROR_TRANSFORM_NOT_SUPPORTED &&
231 ((src->width != dst->width) || (src->height != dst->height)))
233 FIXME( "should stretch %dx%d -> %dx%d\n",
234 src->width, src->height, dst->width, dst->height );
237 if (bits.free) bits.free( &bits );
241 /***********************************************************************
244 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop)
249 if (rop_uses_src( rop )) return FALSE;
250 if ((dc = get_dc_ptr( hdc )))
252 struct bitblt_coords dst;
253 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPatBlt );
259 dst.log_width = width;
260 dst.log_height = height;
261 dst.layout = dc->layout;
262 if (rop & NOMIRRORBITMAP)
264 dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
265 rop &= ~NOMIRRORBITMAP;
267 ret = !get_vis_rectangles( dc, &dst, NULL, NULL );
269 TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s rop=%06x\n",
270 hdc, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
271 dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
273 if (!ret) ret = physdev->funcs->pPatBlt( physdev, &dst, rop );
275 release_dc_ptr( dc );
281 /***********************************************************************
284 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
285 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
287 if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, width, height, rop );
288 else return StretchBlt( hdcDst, xDst, yDst, width, height,
289 hdcSrc, xSrc, ySrc, width, height, rop );
293 /***********************************************************************
294 * StretchBlt (GDI32.@)
296 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
297 HDC hdcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop )
302 if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, widthDst, heightDst, rop );
304 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
306 if ((dcSrc = get_dc_ptr( hdcSrc )))
308 struct bitblt_coords src, dst;
309 PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pStretchBlt );
310 PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pStretchBlt );
317 src.log_width = widthSrc;
318 src.log_height = heightSrc;
319 src.layout = dcSrc->layout;
322 dst.log_width = widthDst;
323 dst.log_height = heightDst;
324 dst.layout = dcDst->layout;
325 if (rop & NOMIRRORBITMAP)
327 src.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
328 dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
329 rop &= ~NOMIRRORBITMAP;
331 ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
333 TRACE("src %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s rop=%06x\n",
334 hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
335 src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
336 hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
337 dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
339 if (!ret) ret = dst_dev->funcs->pStretchBlt( dst_dev, &dst, src_dev, &src, rop );
340 release_dc_ptr( dcSrc );
342 release_dc_ptr( dcDst );
346 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
347 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
349 /***********************************************************************
352 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
353 INT nWidth, INT nHeight, HDC hdcSrc,
354 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
355 INT xMask, INT yMask, DWORD dwRop)
357 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
359 HBRUSH hbrMask, hbrDst, hbrTmp;
361 static const DWORD ROP3Table[256] =
363 0x00000042, 0x00010289,
364 0x00020C89, 0x000300AA,
365 0x00040C88, 0x000500A9,
366 0x00060865, 0x000702C5,
367 0x00080F08, 0x00090245,
368 0x000A0329, 0x000B0B2A,
369 0x000C0324, 0x000D0B25,
370 0x000E08A5, 0x000F0001,
371 0x00100C85, 0x001100A6,
372 0x00120868, 0x001302C8,
373 0x00140869, 0x001502C9,
374 0x00165CCA, 0x00171D54,
375 0x00180D59, 0x00191CC8,
376 0x001A06C5, 0x001B0768,
377 0x001C06CA, 0x001D0766,
378 0x001E01A5, 0x001F0385,
379 0x00200F09, 0x00210248,
380 0x00220326, 0x00230B24,
381 0x00240D55, 0x00251CC5,
382 0x002606C8, 0x00271868,
383 0x00280369, 0x002916CA,
384 0x002A0CC9, 0x002B1D58,
385 0x002C0784, 0x002D060A,
386 0x002E064A, 0x002F0E2A,
387 0x0030032A, 0x00310B28,
388 0x00320688, 0x00330008,
389 0x003406C4, 0x00351864,
390 0x003601A8, 0x00370388,
391 0x0038078A, 0x00390604,
392 0x003A0644, 0x003B0E24,
393 0x003C004A, 0x003D18A4,
394 0x003E1B24, 0x003F00EA,
395 0x00400F0A, 0x00410249,
396 0x00420D5D, 0x00431CC4,
397 0x00440328, 0x00450B29,
398 0x004606C6, 0x0047076A,
399 0x00480368, 0x004916C5,
400 0x004A0789, 0x004B0605,
401 0x004C0CC8, 0x004D1954,
402 0x004E0645, 0x004F0E25,
403 0x00500325, 0x00510B26,
404 0x005206C9, 0x00530764,
405 0x005408A9, 0x00550009,
406 0x005601A9, 0x00570389,
407 0x00580785, 0x00590609,
408 0x005A0049, 0x005B18A9,
409 0x005C0649, 0x005D0E29,
410 0x005E1B29, 0x005F00E9,
411 0x00600365, 0x006116C6,
412 0x00620786, 0x00630608,
413 0x00640788, 0x00650606,
414 0x00660046, 0x006718A8,
415 0x006858A6, 0x00690145,
416 0x006A01E9, 0x006B178A,
417 0x006C01E8, 0x006D1785,
418 0x006E1E28, 0x006F0C65,
419 0x00700CC5, 0x00711D5C,
420 0x00720648, 0x00730E28,
421 0x00740646, 0x00750E26,
422 0x00761B28, 0x007700E6,
423 0x007801E5, 0x00791786,
424 0x007A1E29, 0x007B0C68,
425 0x007C1E24, 0x007D0C69,
426 0x007E0955, 0x007F03C9,
427 0x008003E9, 0x00810975,
428 0x00820C49, 0x00831E04,
429 0x00840C48, 0x00851E05,
430 0x008617A6, 0x008701C5,
431 0x008800C6, 0x00891B08,
432 0x008A0E06, 0x008B0666,
433 0x008C0E08, 0x008D0668,
434 0x008E1D7C, 0x008F0CE5,
435 0x00900C45, 0x00911E08,
436 0x009217A9, 0x009301C4,
437 0x009417AA, 0x009501C9,
438 0x00960169, 0x0097588A,
439 0x00981888, 0x00990066,
440 0x009A0709, 0x009B07A8,
441 0x009C0704, 0x009D07A6,
442 0x009E16E6, 0x009F0345,
443 0x00A000C9, 0x00A11B05,
444 0x00A20E09, 0x00A30669,
445 0x00A41885, 0x00A50065,
446 0x00A60706, 0x00A707A5,
447 0x00A803A9, 0x00A90189,
448 0x00AA0029, 0x00AB0889,
449 0x00AC0744, 0x00AD06E9,
450 0x00AE0B06, 0x00AF0229,
451 0x00B00E05, 0x00B10665,
452 0x00B21974, 0x00B30CE8,
453 0x00B4070A, 0x00B507A9,
454 0x00B616E9, 0x00B70348,
455 0x00B8074A, 0x00B906E6,
456 0x00BA0B09, 0x00BB0226,
457 0x00BC1CE4, 0x00BD0D7D,
458 0x00BE0269, 0x00BF08C9,
459 0x00C000CA, 0x00C11B04,
460 0x00C21884, 0x00C3006A,
461 0x00C40E04, 0x00C50664,
462 0x00C60708, 0x00C707AA,
463 0x00C803A8, 0x00C90184,
464 0x00CA0749, 0x00CB06E4,
465 0x00CC0020, 0x00CD0888,
466 0x00CE0B08, 0x00CF0224,
467 0x00D00E0A, 0x00D1066A,
468 0x00D20705, 0x00D307A4,
469 0x00D41D78, 0x00D50CE9,
470 0x00D616EA, 0x00D70349,
471 0x00D80745, 0x00D906E8,
472 0x00DA1CE9, 0x00DB0D75,
473 0x00DC0B04, 0x00DD0228,
474 0x00DE0268, 0x00DF08C8,
475 0x00E003A5, 0x00E10185,
476 0x00E20746, 0x00E306EA,
477 0x00E40748, 0x00E506E5,
478 0x00E61CE8, 0x00E70D79,
479 0x00E81D74, 0x00E95CE6,
480 0x00EA02E9, 0x00EB0849,
481 0x00EC02E8, 0x00ED0848,
482 0x00EE0086, 0x00EF0A08,
483 0x00F00021, 0x00F10885,
484 0x00F20B05, 0x00F3022A,
485 0x00F40B0A, 0x00F50225,
486 0x00F60265, 0x00F708C5,
487 0x00F802E5, 0x00F90845,
488 0x00FA0089, 0x00FB0A09,
489 0x00FC008A, 0x00FD0A0A,
490 0x00FE02A9, 0x00FF0062,
494 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
496 hbrMask = CreatePatternBrush(hbmMask);
497 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
500 hDC1 = CreateCompatibleDC(hdcDest);
501 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
502 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
504 /* draw using bkgnd rop */
505 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
506 hbrTmp = SelectObject(hDC1, hbrDst);
507 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
508 SelectObject(hDC1, hbrTmp);
511 hDC2 = CreateCompatibleDC(hdcDest);
512 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
513 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
515 /* draw using foregnd rop */
516 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
517 hbrTmp = SelectObject(hDC2, hbrDst);
518 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
520 /* combine both using the mask as a pattern brush */
521 SelectObject(hDC2, hbrMask);
522 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
523 SelectObject(hDC2, hbrTmp);
526 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
528 /* restore all objects */
529 SelectObject(hdcDest, hbrDst);
530 SelectObject(hDC1, hOldBitmap1);
531 SelectObject(hDC2, hOldBitmap2);
533 /* delete all temp objects */
534 DeleteObject(hBitmap1);
535 DeleteObject(hBitmap2);
536 DeleteObject(hbrMask);
544 /******************************************************************************
545 * GdiTransparentBlt [GDI32.@]
547 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
548 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
556 HBITMAP bmpMask = NULL;
557 HBITMAP oldMask = NULL;
558 COLORREF oldBackground;
559 COLORREF oldForeground;
562 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
563 TRACE("Cannot mirror\n");
567 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
568 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
571 oldStretchMode = GetStretchBltMode(hdcSrc);
572 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
573 SetStretchBltMode(hdcSrc, COLORONCOLOR);
574 hdcWork = CreateCompatibleDC(hdcDest);
575 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
576 oldWork = SelectObject(hdcWork, bmpWork);
577 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
578 TRACE("Failed to stretch\n");
581 SetBkColor(hdcWork, crTransparent);
584 hdcMask = CreateCompatibleDC(hdcDest);
585 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
586 oldMask = SelectObject(hdcMask, bmpMask);
587 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
588 TRACE("Failed to create mask\n");
592 /* Replace transparent color with black */
593 SetBkColor(hdcWork, RGB(0,0,0));
594 SetTextColor(hdcWork, RGB(255,255,255));
595 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
596 TRACE("Failed to mask out background\n");
600 /* Replace non-transparent area on destination with black */
601 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
602 TRACE("Failed to clear destination area\n");
607 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
608 TRACE("Failed to paint image\n");
614 SetStretchBltMode(hdcSrc, oldStretchMode);
615 SetBkColor(hdcDest, oldBackground);
616 SetTextColor(hdcDest, oldForeground);
618 SelectObject(hdcWork, oldWork);
621 if(bmpWork) DeleteObject(bmpWork);
623 SelectObject(hdcMask, oldMask);
626 if(bmpMask) DeleteObject(bmpMask);
630 /******************************************************************************
631 * GdiAlphaBlend [GDI32.@]
633 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
634 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
635 BLENDFUNCTION blendFunction)
640 dcSrc = get_dc_ptr( hdcSrc );
641 if (!dcSrc) return FALSE;
643 if ((dcDst = get_dc_ptr( hdcDst )))
645 struct bitblt_coords src, dst;
646 PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pAlphaBlend );
647 PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pAlphaBlend );
654 src.log_width = widthSrc;
655 src.log_height = heightSrc;
656 src.layout = GetLayout( src_dev->hdc );
659 dst.log_width = widthDst;
660 dst.log_height = heightDst;
661 dst.layout = GetLayout( dst_dev->hdc );
662 ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
664 TRACE("src %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s blend=%02x/%02x/%02x/%02x\n",
665 hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
666 src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
667 hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
668 dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect),
669 blendFunction.BlendOp, blendFunction.BlendFlags,
670 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
672 if (!ret) ret = dst_dev->funcs->pAlphaBlend( dst_dev, &dst, src_dev, &src, blendFunction );
673 release_dc_ptr( dcDst );
675 release_dc_ptr( dcSrc );
679 /*********************************************************************
683 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
684 HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
685 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
688 /* parallelogram coords */
697 /* save actual mode, set GM_ADVANCED */
698 oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
702 memcpy(plg,lpPoint,sizeof(POINT)*3);
705 rect[1].x = nXSrc + nWidth;
708 rect[2].y = nYSrc + nHeight;
709 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
711 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);
713 if (fabs(det) < 1e-5)
715 SetGraphicsMode(hdcDest,oldgMode);
719 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
720 hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
723 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;
724 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;
725 xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
726 rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
727 rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
731 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;
732 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;
733 xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
734 rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
735 rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
738 GetWorldTransform(hdcSrc,&SrcXf);
739 CombineTransform(&xf,&xf,&SrcXf);
741 /* save actual dest transform */
742 GetWorldTransform(hdcDest,&oldDestXf);
744 SetWorldTransform(hdcDest,&xf);
745 /* now destination and source DCs use same coords */
746 MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
750 /* restore dest DC */
751 SetWorldTransform(hdcDest,&oldDestXf);
752 SetGraphicsMode(hdcDest,oldgMode);