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 TRACE("%p %d,%d %dx%d %06x\n", hdc
, left
, top
, width
, height
, rop
);
221 if (rop_uses_src( rop
)) return FALSE
;
222 if ((dc
= get_dc_ptr( hdc
)))
224 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pPatBlt
);
226 bRet
= physdev
->funcs
->pPatBlt( physdev
, left
, top
, width
, height
, rop
);
227 release_dc_ptr( dc
);
233 /***********************************************************************
236 BOOL WINAPI
BitBlt( HDC hdcDst
, INT xDst
, INT yDst
, INT width
,
237 INT height
, HDC hdcSrc
, INT xSrc
, INT ySrc
, DWORD rop
)
239 if (!rop_uses_src( rop
)) return PatBlt( hdcDst
, xDst
, yDst
, width
, height
, rop
);
240 else return StretchBlt( hdcDst
, xDst
, yDst
, width
, height
,
241 hdcSrc
, xSrc
, ySrc
, width
, height
, rop
);
245 /***********************************************************************
246 * StretchBlt (GDI32.@)
248 BOOL WINAPI
StretchBlt( HDC hdcDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
249 HDC hdcSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, DWORD rop
)
254 if (!rop_uses_src( rop
)) return PatBlt( hdcDst
, xDst
, yDst
, widthDst
, heightDst
, rop
);
256 if (!(dcDst
= get_dc_ptr( hdcDst
))) return FALSE
;
258 if ((dcSrc
= get_dc_ptr( hdcSrc
)))
260 struct bitblt_coords src
, dst
;
261 PHYSDEV src_dev
= GET_DC_PHYSDEV( dcSrc
, pStretchBlt
);
262 PHYSDEV dst_dev
= GET_DC_PHYSDEV( dcDst
, pStretchBlt
);
269 src
.log_width
= widthSrc
;
270 src
.log_height
= heightSrc
;
271 src
.layout
= dcSrc
->layout
;
274 dst
.log_width
= widthDst
;
275 dst
.log_height
= heightDst
;
276 dst
.layout
= dcDst
->layout
;
277 if (rop
& NOMIRRORBITMAP
)
279 src
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
280 dst
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
281 rop
&= ~NOMIRRORBITMAP
;
283 get_vis_rectangles( dcDst
, &dst
, dcSrc
, &src
);
285 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",
286 hdcSrc
, src
.log_x
, src
.log_y
, src
.log_width
, src
.log_height
,
287 src
.x
, src
.y
, src
.width
, src
.height
, wine_dbgstr_rect(&src
.visrect
),
288 hdcDst
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
289 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
), rop
);
291 ret
= dst_dev
->funcs
->pStretchBlt( dst_dev
, &dst
, src_dev
, &src
, rop
);
292 release_dc_ptr( dcSrc
);
294 release_dc_ptr( dcDst
);
298 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
299 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
301 /***********************************************************************
304 BOOL WINAPI
MaskBlt(HDC hdcDest
, INT nXDest
, INT nYDest
,
305 INT nWidth
, INT nHeight
, HDC hdcSrc
,
306 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
307 INT xMask
, INT yMask
, DWORD dwRop
)
309 HBITMAP hBitmap1
, hOldBitmap1
, hBitmap2
, hOldBitmap2
;
311 HBRUSH hbrMask
, hbrDst
, hbrTmp
;
313 static const DWORD ROP3Table
[256] =
315 0x00000042, 0x00010289,
316 0x00020C89, 0x000300AA,
317 0x00040C88, 0x000500A9,
318 0x00060865, 0x000702C5,
319 0x00080F08, 0x00090245,
320 0x000A0329, 0x000B0B2A,
321 0x000C0324, 0x000D0B25,
322 0x000E08A5, 0x000F0001,
323 0x00100C85, 0x001100A6,
324 0x00120868, 0x001302C8,
325 0x00140869, 0x001502C9,
326 0x00165CCA, 0x00171D54,
327 0x00180D59, 0x00191CC8,
328 0x001A06C5, 0x001B0768,
329 0x001C06CA, 0x001D0766,
330 0x001E01A5, 0x001F0385,
331 0x00200F09, 0x00210248,
332 0x00220326, 0x00230B24,
333 0x00240D55, 0x00251CC5,
334 0x002606C8, 0x00271868,
335 0x00280369, 0x002916CA,
336 0x002A0CC9, 0x002B1D58,
337 0x002C0784, 0x002D060A,
338 0x002E064A, 0x002F0E2A,
339 0x0030032A, 0x00310B28,
340 0x00320688, 0x00330008,
341 0x003406C4, 0x00351864,
342 0x003601A8, 0x00370388,
343 0x0038078A, 0x00390604,
344 0x003A0644, 0x003B0E24,
345 0x003C004A, 0x003D18A4,
346 0x003E1B24, 0x003F00EA,
347 0x00400F0A, 0x00410249,
348 0x00420D5D, 0x00431CC4,
349 0x00440328, 0x00450B29,
350 0x004606C6, 0x0047076A,
351 0x00480368, 0x004916C5,
352 0x004A0789, 0x004B0605,
353 0x004C0CC8, 0x004D1954,
354 0x004E0645, 0x004F0E25,
355 0x00500325, 0x00510B26,
356 0x005206C9, 0x00530764,
357 0x005408A9, 0x00550009,
358 0x005601A9, 0x00570389,
359 0x00580785, 0x00590609,
360 0x005A0049, 0x005B18A9,
361 0x005C0649, 0x005D0E29,
362 0x005E1B29, 0x005F00E9,
363 0x00600365, 0x006116C6,
364 0x00620786, 0x00630608,
365 0x00640788, 0x00650606,
366 0x00660046, 0x006718A8,
367 0x006858A6, 0x00690145,
368 0x006A01E9, 0x006B178A,
369 0x006C01E8, 0x006D1785,
370 0x006E1E28, 0x006F0C65,
371 0x00700CC5, 0x00711D5C,
372 0x00720648, 0x00730E28,
373 0x00740646, 0x00750E26,
374 0x00761B28, 0x007700E6,
375 0x007801E5, 0x00791786,
376 0x007A1E29, 0x007B0C68,
377 0x007C1E24, 0x007D0C69,
378 0x007E0955, 0x007F03C9,
379 0x008003E9, 0x00810975,
380 0x00820C49, 0x00831E04,
381 0x00840C48, 0x00851E05,
382 0x008617A6, 0x008701C5,
383 0x008800C6, 0x00891B08,
384 0x008A0E06, 0x008B0666,
385 0x008C0E08, 0x008D0668,
386 0x008E1D7C, 0x008F0CE5,
387 0x00900C45, 0x00911E08,
388 0x009217A9, 0x009301C4,
389 0x009417AA, 0x009501C9,
390 0x00960169, 0x0097588A,
391 0x00981888, 0x00990066,
392 0x009A0709, 0x009B07A8,
393 0x009C0704, 0x009D07A6,
394 0x009E16E6, 0x009F0345,
395 0x00A000C9, 0x00A11B05,
396 0x00A20E09, 0x00A30669,
397 0x00A41885, 0x00A50065,
398 0x00A60706, 0x00A707A5,
399 0x00A803A9, 0x00A90189,
400 0x00AA0029, 0x00AB0889,
401 0x00AC0744, 0x00AD06E9,
402 0x00AE0B06, 0x00AF0229,
403 0x00B00E05, 0x00B10665,
404 0x00B21974, 0x00B30CE8,
405 0x00B4070A, 0x00B507A9,
406 0x00B616E9, 0x00B70348,
407 0x00B8074A, 0x00B906E6,
408 0x00BA0B09, 0x00BB0226,
409 0x00BC1CE4, 0x00BD0D7D,
410 0x00BE0269, 0x00BF08C9,
411 0x00C000CA, 0x00C11B04,
412 0x00C21884, 0x00C3006A,
413 0x00C40E04, 0x00C50664,
414 0x00C60708, 0x00C707AA,
415 0x00C803A8, 0x00C90184,
416 0x00CA0749, 0x00CB06E4,
417 0x00CC0020, 0x00CD0888,
418 0x00CE0B08, 0x00CF0224,
419 0x00D00E0A, 0x00D1066A,
420 0x00D20705, 0x00D307A4,
421 0x00D41D78, 0x00D50CE9,
422 0x00D616EA, 0x00D70349,
423 0x00D80745, 0x00D906E8,
424 0x00DA1CE9, 0x00DB0D75,
425 0x00DC0B04, 0x00DD0228,
426 0x00DE0268, 0x00DF08C8,
427 0x00E003A5, 0x00E10185,
428 0x00E20746, 0x00E306EA,
429 0x00E40748, 0x00E506E5,
430 0x00E61CE8, 0x00E70D79,
431 0x00E81D74, 0x00E95CE6,
432 0x00EA02E9, 0x00EB0849,
433 0x00EC02E8, 0x00ED0848,
434 0x00EE0086, 0x00EF0A08,
435 0x00F00021, 0x00F10885,
436 0x00F20B05, 0x00F3022A,
437 0x00F40B0A, 0x00F50225,
438 0x00F60265, 0x00F708C5,
439 0x00F802E5, 0x00F90845,
440 0x00FA0089, 0x00FB0A09,
441 0x00FC008A, 0x00FD0A0A,
442 0x00FE02A9, 0x00FF0062,
446 return BitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
448 hbrMask
= CreatePatternBrush(hbmMask
);
449 hbrDst
= SelectObject(hdcDest
, GetStockObject(NULL_BRUSH
));
452 hDC1
= CreateCompatibleDC(hdcDest
);
453 hBitmap1
= CreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
454 hOldBitmap1
= SelectObject(hDC1
, hBitmap1
);
456 /* draw using bkgnd rop */
457 BitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
458 hbrTmp
= SelectObject(hDC1
, hbrDst
);
459 BitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, BKGND_ROP3(dwRop
));
460 SelectObject(hDC1
, hbrTmp
);
463 hDC2
= CreateCompatibleDC(hdcDest
);
464 hBitmap2
= CreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
465 hOldBitmap2
= SelectObject(hDC2
, hBitmap2
);
467 /* draw using foregnd rop */
468 BitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
469 hbrTmp
= SelectObject(hDC2
, hbrDst
);
470 BitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
472 /* combine both using the mask as a pattern brush */
473 SelectObject(hDC2
, hbrMask
);
474 BitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDC1
, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
475 SelectObject(hDC2
, hbrTmp
);
478 BitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC2
, 0, 0, SRCCOPY
);
480 /* restore all objects */
481 SelectObject(hdcDest
, hbrDst
);
482 SelectObject(hDC1
, hOldBitmap1
);
483 SelectObject(hDC2
, hOldBitmap2
);
485 /* delete all temp objects */
486 DeleteObject(hBitmap1
);
487 DeleteObject(hBitmap2
);
488 DeleteObject(hbrMask
);
496 /******************************************************************************
497 * GdiTransparentBlt [GDI32.@]
499 BOOL WINAPI
GdiTransparentBlt( HDC hdcDest
, int xDest
, int yDest
, int widthDest
, int heightDest
,
500 HDC hdcSrc
, int xSrc
, int ySrc
, int widthSrc
, int heightSrc
,
508 HBITMAP bmpMask
= NULL
;
509 HBITMAP oldMask
= NULL
;
510 COLORREF oldBackground
;
511 COLORREF oldForeground
;
514 if(widthDest
< 0 || heightDest
< 0 || widthSrc
< 0 || heightSrc
< 0) {
515 TRACE("Cannot mirror\n");
519 oldBackground
= SetBkColor(hdcDest
, RGB(255,255,255));
520 oldForeground
= SetTextColor(hdcDest
, RGB(0,0,0));
523 oldStretchMode
= GetStretchBltMode(hdcSrc
);
524 if(oldStretchMode
== BLACKONWHITE
|| oldStretchMode
== WHITEONBLACK
)
525 SetStretchBltMode(hdcSrc
, COLORONCOLOR
);
526 hdcWork
= CreateCompatibleDC(hdcDest
);
527 bmpWork
= CreateCompatibleBitmap(hdcDest
, widthDest
, heightDest
);
528 oldWork
= SelectObject(hdcWork
, bmpWork
);
529 if(!StretchBlt(hdcWork
, 0, 0, widthDest
, heightDest
, hdcSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, SRCCOPY
)) {
530 TRACE("Failed to stretch\n");
533 SetBkColor(hdcWork
, crTransparent
);
536 hdcMask
= CreateCompatibleDC(hdcDest
);
537 bmpMask
= CreateCompatibleBitmap(hdcMask
, widthDest
, heightDest
);
538 oldMask
= SelectObject(hdcMask
, bmpMask
);
539 if(!BitBlt(hdcMask
, 0, 0, widthDest
, heightDest
, hdcWork
, 0, 0, SRCCOPY
)) {
540 TRACE("Failed to create mask\n");
544 /* Replace transparent color with black */
545 SetBkColor(hdcWork
, RGB(0,0,0));
546 SetTextColor(hdcWork
, RGB(255,255,255));
547 if(!BitBlt(hdcWork
, 0, 0, widthDest
, heightDest
, hdcMask
, 0, 0, SRCAND
)) {
548 TRACE("Failed to mask out background\n");
552 /* Replace non-transparent area on destination with black */
553 if(!BitBlt(hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcMask
, 0, 0, SRCAND
)) {
554 TRACE("Failed to clear destination area\n");
559 if(!BitBlt(hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcWork
, 0, 0, SRCPAINT
)) {
560 TRACE("Failed to paint image\n");
566 SetStretchBltMode(hdcSrc
, oldStretchMode
);
567 SetBkColor(hdcDest
, oldBackground
);
568 SetTextColor(hdcDest
, oldForeground
);
570 SelectObject(hdcWork
, oldWork
);
573 if(bmpWork
) DeleteObject(bmpWork
);
575 SelectObject(hdcMask
, oldMask
);
578 if(bmpMask
) DeleteObject(bmpMask
);
582 /******************************************************************************
583 * GdiAlphaBlend [GDI32.@]
585 BOOL WINAPI
GdiAlphaBlend(HDC hdcDst
, int xDst
, int yDst
, int widthDst
, int heightDst
,
586 HDC hdcSrc
, int xSrc
, int ySrc
, int widthSrc
, int heightSrc
,
587 BLENDFUNCTION blendFunction
)
592 TRACE( "%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
593 hdcSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, hdcDst
, xDst
, yDst
, widthDst
, heightDst
,
594 blendFunction
.BlendOp
, blendFunction
.BlendFlags
,
595 blendFunction
.SourceConstantAlpha
, blendFunction
.AlphaFormat
);
597 dcSrc
= get_dc_ptr( hdcSrc
);
598 if (!dcSrc
) return FALSE
;
600 if ((dcDst
= get_dc_ptr( hdcDst
)))
602 PHYSDEV src_dev
= GET_DC_PHYSDEV( dcSrc
, pAlphaBlend
);
603 PHYSDEV dst_dev
= GET_DC_PHYSDEV( dcDst
, pAlphaBlend
);
606 ret
= dst_dev
->funcs
->pAlphaBlend( dst_dev
, xDst
, yDst
, widthDst
, heightDst
,
607 src_dev
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendFunction
);
608 release_dc_ptr( dcDst
);
610 release_dc_ptr( dcSrc
);
614 /*********************************************************************
618 BOOL WINAPI
PlgBlt( HDC hdcDest
, const POINT
*lpPoint
,
619 HDC hdcSrc
, INT nXSrc
, INT nYSrc
, INT nWidth
,
620 INT nHeight
, HBITMAP hbmMask
, INT xMask
, INT yMask
)
623 /* parallelogram coords */
632 /* save actual mode, set GM_ADVANCED */
633 oldgMode
= SetGraphicsMode(hdcDest
,GM_ADVANCED
);
637 memcpy(plg
,lpPoint
,sizeof(POINT
)*3);
640 rect
[1].x
= nXSrc
+ nWidth
;
643 rect
[2].y
= nYSrc
+ nHeight
;
644 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
646 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
);
648 if (fabs(det
) < 1e-5)
650 SetGraphicsMode(hdcDest
,oldgMode
);
654 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
655 hdcSrc
, nXSrc
, nYSrc
, nWidth
, nHeight
, hdcDest
, plg
[0].x
, plg
[0].y
, plg
[1].x
, plg
[1].y
, plg
[2].x
, plg
[2].y
);
658 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
;
659 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
;
660 xf
.eDx
= (rect
[0].x
*(rect
[1].y
*plg
[2].x
- rect
[2].y
*plg
[1].x
) -
661 rect
[1].x
*(rect
[0].y
*plg
[2].x
- rect
[2].y
*plg
[0].x
) +
662 rect
[2].x
*(rect
[0].y
*plg
[1].x
- rect
[1].y
*plg
[0].x
)
666 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
;
667 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
;
668 xf
.eDy
= (rect
[0].x
*(rect
[1].y
*plg
[2].y
- rect
[2].y
*plg
[1].y
) -
669 rect
[1].x
*(rect
[0].y
*plg
[2].y
- rect
[2].y
*plg
[0].y
) +
670 rect
[2].x
*(rect
[0].y
*plg
[1].y
- rect
[1].y
*plg
[0].y
)
673 GetWorldTransform(hdcSrc
,&SrcXf
);
674 CombineTransform(&xf
,&xf
,&SrcXf
);
676 /* save actual dest transform */
677 GetWorldTransform(hdcDest
,&oldDestXf
);
679 SetWorldTransform(hdcDest
,&xf
);
680 /* now destination and source DCs use same coords */
681 MaskBlt(hdcDest
,nXSrc
,nYSrc
,nWidth
,nHeight
,
685 /* restore dest DC */
686 SetWorldTransform(hdcDest
,&oldDestXf
);
687 SetGraphicsMode(hdcDest
,oldgMode
);