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 inline BOOL intersect_rect( RECT *dst, const RECT *src1, const RECT *src2 )
52 dst->left = max( src1->left, src2->left );
53 dst->top = max( src1->top, src2->top );
54 dst->right = min( src1->right, src2->right );
55 dst->bottom = min( src1->bottom, src2->bottom );
56 return (dst->left < dst->right && dst->top < dst->bottom);
59 static inline void offset_rect( RECT *rect, int offset_x, int offset_y )
61 rect->left += offset_x;
62 rect->top += offset_y;
63 rect->right += offset_x;
64 rect->bottom += offset_y;
67 static void get_vis_rectangles( DC *dc_dst, struct bitblt_coords *dst,
68 DC *dc_src, struct bitblt_coords *src )
72 /* get the destination visible rectangle */
74 rect.left = dst->log_x;
75 rect.top = dst->log_y;
76 rect.right = dst->log_x + dst->log_width;
77 rect.bottom = dst->log_y + dst->log_height;
78 LPtoDP( dc_dst->hSelf, (POINT *)&rect, 2 );
81 dst->width = rect.right - rect.left;
82 dst->height = rect.bottom - rect.top;
83 if (dst->layout & LAYOUT_RTL && dst->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
85 swap_ints( &rect.left, &rect.right );
87 dst->width = rect.right - rect.left;
89 if (rect.left > rect.right) { swap_ints( &rect.left, &rect.right ); rect.left++; rect.right++; }
90 if (rect.top > rect.bottom) { swap_ints( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
92 get_clip_box( dc_dst, &clip );
93 intersect_rect( &dst->visrect, &rect, &clip );
95 /* get the source visible rectangle */
99 rect.left = src->log_x;
100 rect.top = src->log_y;
101 rect.right = src->log_x + src->log_width;
102 rect.bottom = src->log_y + src->log_height;
103 LPtoDP( dc_src->hSelf, (POINT *)&rect, 2 );
106 src->width = rect.right - rect.left;
107 src->height = rect.bottom - rect.top;
108 if (src->layout & LAYOUT_RTL && src->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
110 swap_ints( &rect.left, &rect.right );
112 src->width = rect.right - rect.left;
114 if (rect.left > rect.right) { swap_ints( &rect.left, &rect.right ); rect.left++; rect.right++; }
115 if (rect.top > rect.bottom) { swap_ints( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
117 /* source is not clipped */
118 if (dc_src->header.type == OBJ_MEMDC)
119 intersect_rect( &src->visrect, &rect, &dc_src->vis_rect );
121 src->visrect = rect; /* FIXME: clip to device size */
123 /* intersect the rectangles */
125 if ((src->width == dst->width) && (src->height == dst->height)) /* no stretching */
127 offset_rect( &src->visrect, dst->x - src->x, dst->y - src->y );
128 intersect_rect( &rect, &src->visrect, &dst->visrect );
129 src->visrect = dst->visrect = rect;
130 offset_rect( &src->visrect, src->x - dst->x, src->y - dst->y );
132 else /* stretching */
134 /* map source rectangle into destination coordinates */
135 rect.left = dst->x + (src->visrect.left - src->x)*dst->width/src->width;
136 rect.top = dst->y + (src->visrect.top - src->y)*dst->height/src->height;
137 rect.right = dst->x + (src->visrect.right - src->x)*dst->width/src->width;
138 rect.bottom = dst->y + (src->visrect.bottom - src->y)*dst->height/src->height;
139 if (rect.left > rect.right) swap_ints( &rect.left, &rect.right );
140 if (rect.top > rect.bottom) swap_ints( &rect.top, &rect.bottom );
142 /* avoid rounding errors */
147 if (!intersect_rect( &dst->visrect, &rect, &dst->visrect )) return;
149 /* map destination rectangle back to source coordinates */
151 rect.left = src->x + (dst->visrect.left - dst->x)*src->width/dst->width;
152 rect.top = src->y + (dst->visrect.top - dst->y)*src->height/dst->height;
153 rect.right = src->x + (dst->visrect.right - dst->x)*src->width/dst->width;
154 rect.bottom = src->y + (dst->visrect.bottom - dst->y)*src->height/dst->height;
155 if (rect.left > rect.right) swap_ints( &rect.left, &rect.right );
156 if (rect.top > rect.bottom) swap_ints( &rect.top, &rect.bottom );
158 /* avoid rounding errors */
163 intersect_rect( &src->visrect, &rect, &src->visrect );
167 /* nulldrv fallback implementation using StretchDIBits */
168 BOOL CDECL nulldrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
169 PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
171 DC *dc = get_nulldrv_dc( dst_dev );
173 BITMAPINFOHEADER info_hdr;
178 /* make sure we have a real implementation for StretchDIBits */
179 if (GET_DC_PHYSDEV( dc, pStretchDIBits ) == dst_dev) return 0;
181 if (GetObjectType( src_dev->hdc ) != OBJ_MEMDC) return FALSE;
182 if (!GetObjectW( GetCurrentObject( src_dev->hdc, OBJ_BITMAP ), sizeof(bm), &bm )) return FALSE;
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( src_dev->hdc, GetStockObject(DEFAULT_BITMAP) );
201 lines = GetDIBits( src_dev->hdc, hbm, 0, bm.bmHeight, bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS );
202 SelectObject( src_dev->hdc, hbm );
204 if (lines) lines = StretchDIBits( dst_dev->hdc, dst->log_x, dst->log_y, dst->log_width, dst->log_height,
205 src->x, bm.bmHeight - src->height - src->y, src->width, src->height,
206 bits, (BITMAPINFO*)&info_hdr, DIB_RGB_COLORS, rop );
207 HeapFree( GetProcessHeap(), 0, bits );
208 return (lines == src->height);
211 /***********************************************************************
214 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop)
219 if (rop_uses_src( rop )) return FALSE;
220 if ((dc = get_dc_ptr( hdc )))
222 struct bitblt_coords dst;
223 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPatBlt );
229 dst.log_width = width;
230 dst.log_height = height;
231 dst.layout = dc->layout;
232 if (rop & NOMIRRORBITMAP)
234 dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
235 rop &= ~NOMIRRORBITMAP;
237 get_vis_rectangles( dc, &dst, NULL, NULL );
239 TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s rop=%06x\n",
240 hdc, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
241 dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
243 ret = physdev->funcs->pPatBlt( physdev, &dst, rop );
245 release_dc_ptr( dc );
251 /***********************************************************************
254 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
255 INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
257 if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, width, height, rop );
258 else return StretchBlt( hdcDst, xDst, yDst, width, height,
259 hdcSrc, xSrc, ySrc, width, height, rop );
263 /***********************************************************************
264 * StretchBlt (GDI32.@)
266 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
267 HDC hdcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop )
272 if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, widthDst, heightDst, rop );
274 if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
276 if ((dcSrc = get_dc_ptr( hdcSrc )))
278 struct bitblt_coords src, dst;
279 PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pStretchBlt );
280 PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pStretchBlt );
287 src.log_width = widthSrc;
288 src.log_height = heightSrc;
289 src.layout = dcSrc->layout;
292 dst.log_width = widthDst;
293 dst.log_height = heightDst;
294 dst.layout = dcDst->layout;
295 if (rop & NOMIRRORBITMAP)
297 src.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
298 dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
299 rop &= ~NOMIRRORBITMAP;
301 get_vis_rectangles( dcDst, &dst, dcSrc, &src );
303 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",
304 hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
305 src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
306 hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
307 dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
309 ret = dst_dev->funcs->pStretchBlt( dst_dev, &dst, src_dev, &src, rop );
310 release_dc_ptr( dcSrc );
312 release_dc_ptr( dcDst );
316 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
317 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
319 /***********************************************************************
322 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
323 INT nWidth, INT nHeight, HDC hdcSrc,
324 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
325 INT xMask, INT yMask, DWORD dwRop)
327 HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
329 HBRUSH hbrMask, hbrDst, hbrTmp;
331 static const DWORD ROP3Table[256] =
333 0x00000042, 0x00010289,
334 0x00020C89, 0x000300AA,
335 0x00040C88, 0x000500A9,
336 0x00060865, 0x000702C5,
337 0x00080F08, 0x00090245,
338 0x000A0329, 0x000B0B2A,
339 0x000C0324, 0x000D0B25,
340 0x000E08A5, 0x000F0001,
341 0x00100C85, 0x001100A6,
342 0x00120868, 0x001302C8,
343 0x00140869, 0x001502C9,
344 0x00165CCA, 0x00171D54,
345 0x00180D59, 0x00191CC8,
346 0x001A06C5, 0x001B0768,
347 0x001C06CA, 0x001D0766,
348 0x001E01A5, 0x001F0385,
349 0x00200F09, 0x00210248,
350 0x00220326, 0x00230B24,
351 0x00240D55, 0x00251CC5,
352 0x002606C8, 0x00271868,
353 0x00280369, 0x002916CA,
354 0x002A0CC9, 0x002B1D58,
355 0x002C0784, 0x002D060A,
356 0x002E064A, 0x002F0E2A,
357 0x0030032A, 0x00310B28,
358 0x00320688, 0x00330008,
359 0x003406C4, 0x00351864,
360 0x003601A8, 0x00370388,
361 0x0038078A, 0x00390604,
362 0x003A0644, 0x003B0E24,
363 0x003C004A, 0x003D18A4,
364 0x003E1B24, 0x003F00EA,
365 0x00400F0A, 0x00410249,
366 0x00420D5D, 0x00431CC4,
367 0x00440328, 0x00450B29,
368 0x004606C6, 0x0047076A,
369 0x00480368, 0x004916C5,
370 0x004A0789, 0x004B0605,
371 0x004C0CC8, 0x004D1954,
372 0x004E0645, 0x004F0E25,
373 0x00500325, 0x00510B26,
374 0x005206C9, 0x00530764,
375 0x005408A9, 0x00550009,
376 0x005601A9, 0x00570389,
377 0x00580785, 0x00590609,
378 0x005A0049, 0x005B18A9,
379 0x005C0649, 0x005D0E29,
380 0x005E1B29, 0x005F00E9,
381 0x00600365, 0x006116C6,
382 0x00620786, 0x00630608,
383 0x00640788, 0x00650606,
384 0x00660046, 0x006718A8,
385 0x006858A6, 0x00690145,
386 0x006A01E9, 0x006B178A,
387 0x006C01E8, 0x006D1785,
388 0x006E1E28, 0x006F0C65,
389 0x00700CC5, 0x00711D5C,
390 0x00720648, 0x00730E28,
391 0x00740646, 0x00750E26,
392 0x00761B28, 0x007700E6,
393 0x007801E5, 0x00791786,
394 0x007A1E29, 0x007B0C68,
395 0x007C1E24, 0x007D0C69,
396 0x007E0955, 0x007F03C9,
397 0x008003E9, 0x00810975,
398 0x00820C49, 0x00831E04,
399 0x00840C48, 0x00851E05,
400 0x008617A6, 0x008701C5,
401 0x008800C6, 0x00891B08,
402 0x008A0E06, 0x008B0666,
403 0x008C0E08, 0x008D0668,
404 0x008E1D7C, 0x008F0CE5,
405 0x00900C45, 0x00911E08,
406 0x009217A9, 0x009301C4,
407 0x009417AA, 0x009501C9,
408 0x00960169, 0x0097588A,
409 0x00981888, 0x00990066,
410 0x009A0709, 0x009B07A8,
411 0x009C0704, 0x009D07A6,
412 0x009E16E6, 0x009F0345,
413 0x00A000C9, 0x00A11B05,
414 0x00A20E09, 0x00A30669,
415 0x00A41885, 0x00A50065,
416 0x00A60706, 0x00A707A5,
417 0x00A803A9, 0x00A90189,
418 0x00AA0029, 0x00AB0889,
419 0x00AC0744, 0x00AD06E9,
420 0x00AE0B06, 0x00AF0229,
421 0x00B00E05, 0x00B10665,
422 0x00B21974, 0x00B30CE8,
423 0x00B4070A, 0x00B507A9,
424 0x00B616E9, 0x00B70348,
425 0x00B8074A, 0x00B906E6,
426 0x00BA0B09, 0x00BB0226,
427 0x00BC1CE4, 0x00BD0D7D,
428 0x00BE0269, 0x00BF08C9,
429 0x00C000CA, 0x00C11B04,
430 0x00C21884, 0x00C3006A,
431 0x00C40E04, 0x00C50664,
432 0x00C60708, 0x00C707AA,
433 0x00C803A8, 0x00C90184,
434 0x00CA0749, 0x00CB06E4,
435 0x00CC0020, 0x00CD0888,
436 0x00CE0B08, 0x00CF0224,
437 0x00D00E0A, 0x00D1066A,
438 0x00D20705, 0x00D307A4,
439 0x00D41D78, 0x00D50CE9,
440 0x00D616EA, 0x00D70349,
441 0x00D80745, 0x00D906E8,
442 0x00DA1CE9, 0x00DB0D75,
443 0x00DC0B04, 0x00DD0228,
444 0x00DE0268, 0x00DF08C8,
445 0x00E003A5, 0x00E10185,
446 0x00E20746, 0x00E306EA,
447 0x00E40748, 0x00E506E5,
448 0x00E61CE8, 0x00E70D79,
449 0x00E81D74, 0x00E95CE6,
450 0x00EA02E9, 0x00EB0849,
451 0x00EC02E8, 0x00ED0848,
452 0x00EE0086, 0x00EF0A08,
453 0x00F00021, 0x00F10885,
454 0x00F20B05, 0x00F3022A,
455 0x00F40B0A, 0x00F50225,
456 0x00F60265, 0x00F708C5,
457 0x00F802E5, 0x00F90845,
458 0x00FA0089, 0x00FB0A09,
459 0x00FC008A, 0x00FD0A0A,
460 0x00FE02A9, 0x00FF0062,
464 return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
466 hbrMask = CreatePatternBrush(hbmMask);
467 hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
470 hDC1 = CreateCompatibleDC(hdcDest);
471 hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
472 hOldBitmap1 = SelectObject(hDC1, hBitmap1);
474 /* draw using bkgnd rop */
475 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
476 hbrTmp = SelectObject(hDC1, hbrDst);
477 BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
478 SelectObject(hDC1, hbrTmp);
481 hDC2 = CreateCompatibleDC(hdcDest);
482 hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
483 hOldBitmap2 = SelectObject(hDC2, hBitmap2);
485 /* draw using foregnd rop */
486 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
487 hbrTmp = SelectObject(hDC2, hbrDst);
488 BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
490 /* combine both using the mask as a pattern brush */
491 SelectObject(hDC2, hbrMask);
492 BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
493 SelectObject(hDC2, hbrTmp);
496 BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
498 /* restore all objects */
499 SelectObject(hdcDest, hbrDst);
500 SelectObject(hDC1, hOldBitmap1);
501 SelectObject(hDC2, hOldBitmap2);
503 /* delete all temp objects */
504 DeleteObject(hBitmap1);
505 DeleteObject(hBitmap2);
506 DeleteObject(hbrMask);
514 /******************************************************************************
515 * GdiTransparentBlt [GDI32.@]
517 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
518 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
526 HBITMAP bmpMask = NULL;
527 HBITMAP oldMask = NULL;
528 COLORREF oldBackground;
529 COLORREF oldForeground;
532 if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
533 TRACE("Cannot mirror\n");
537 oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
538 oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
541 oldStretchMode = GetStretchBltMode(hdcSrc);
542 if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
543 SetStretchBltMode(hdcSrc, COLORONCOLOR);
544 hdcWork = CreateCompatibleDC(hdcDest);
545 bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
546 oldWork = SelectObject(hdcWork, bmpWork);
547 if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
548 TRACE("Failed to stretch\n");
551 SetBkColor(hdcWork, crTransparent);
554 hdcMask = CreateCompatibleDC(hdcDest);
555 bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
556 oldMask = SelectObject(hdcMask, bmpMask);
557 if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
558 TRACE("Failed to create mask\n");
562 /* Replace transparent color with black */
563 SetBkColor(hdcWork, RGB(0,0,0));
564 SetTextColor(hdcWork, RGB(255,255,255));
565 if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
566 TRACE("Failed to mask out background\n");
570 /* Replace non-transparent area on destination with black */
571 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
572 TRACE("Failed to clear destination area\n");
577 if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
578 TRACE("Failed to paint image\n");
584 SetStretchBltMode(hdcSrc, oldStretchMode);
585 SetBkColor(hdcDest, oldBackground);
586 SetTextColor(hdcDest, oldForeground);
588 SelectObject(hdcWork, oldWork);
591 if(bmpWork) DeleteObject(bmpWork);
593 SelectObject(hdcMask, oldMask);
596 if(bmpMask) DeleteObject(bmpMask);
600 /******************************************************************************
601 * GdiAlphaBlend [GDI32.@]
603 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
604 HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
605 BLENDFUNCTION blendFunction)
610 dcSrc = get_dc_ptr( hdcSrc );
611 if (!dcSrc) return FALSE;
613 if ((dcDst = get_dc_ptr( hdcDst )))
615 struct bitblt_coords src, dst;
616 PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pAlphaBlend );
617 PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pAlphaBlend );
624 src.log_width = widthSrc;
625 src.log_height = heightSrc;
626 src.layout = GetLayout( src_dev->hdc );
629 dst.log_width = widthDst;
630 dst.log_height = heightDst;
631 dst.layout = GetLayout( dst_dev->hdc );
632 get_vis_rectangles( dcDst, &dst, dcSrc, &src );
634 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",
635 hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
636 src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
637 hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
638 dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect),
639 blendFunction.BlendOp, blendFunction.BlendFlags,
640 blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
642 ret = dst_dev->funcs->pAlphaBlend( dst_dev, &dst, src_dev, &src, blendFunction );
643 release_dc_ptr( dcDst );
645 release_dc_ptr( dcSrc );
649 /*********************************************************************
653 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
654 HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
655 INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
658 /* parallelogram coords */
667 /* save actual mode, set GM_ADVANCED */
668 oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
672 memcpy(plg,lpPoint,sizeof(POINT)*3);
675 rect[1].x = nXSrc + nWidth;
678 rect[2].y = nYSrc + nHeight;
679 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
681 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);
683 if (fabs(det) < 1e-5)
685 SetGraphicsMode(hdcDest,oldgMode);
689 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
690 hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
693 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;
694 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;
695 xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
696 rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
697 rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
701 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;
702 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;
703 xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
704 rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
705 rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
708 GetWorldTransform(hdcSrc,&SrcXf);
709 CombineTransform(&xf,&xf,&SrcXf);
711 /* save actual dest transform */
712 GetWorldTransform(hdcDest,&oldDestXf);
714 SetWorldTransform(hdcDest,&xf);
715 /* now destination and source DCs use same coords */
716 MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
720 /* restore dest DC */
721 SetWorldTransform(hdcDest,&oldDestXf);
722 SetGraphicsMode(hdcDest,oldgMode);