quartz/tests: Skip some tests if not allowed to register filters.
[wine] / dlls / gdi32 / bitblt.c
1 /*
2  * GDI bit-blit operations
3  *
4  * Copyright 1993, 1994  Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #include <math.h>
26 #ifdef HAVE_FLOAT_H
27 #include <float.h>
28 #endif
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "gdi_private.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt);
37
38 static inline BOOL rop_uses_src( DWORD rop )
39 {
40     return ((rop >> 2) & 0x330000) != (rop & 0x330000);
41 }
42
43 static inline void swap_ints( int *i, int *j )
44 {
45     int tmp = *i;
46     *i = *j;
47     *j = tmp;
48 }
49
50 static BOOL get_vis_rectangles( DC *dc_dst, struct bitblt_coords *dst,
51                                 DC *dc_src, struct bitblt_coords *src )
52 {
53     RECT rect, clip;
54
55     /* get the destination visible rectangle */
56
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 );
62     dst->x      = rect.left;
63     dst->y      = rect.top;
64     dst->width  = rect.right - rect.left;
65     dst->height = rect.bottom - rect.top;
66     if (dst->layout & LAYOUT_RTL && dst->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
67     {
68         swap_ints( &rect.left, &rect.right );
69         dst->x = rect.left;
70         dst->width = rect.right - rect.left;
71     }
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++; }
74
75     if (get_clip_box( dc_dst, &clip ))
76         intersect_rect( &dst->visrect, &rect, &clip );
77     else
78         dst->visrect = rect;
79
80     /* get the source visible rectangle */
81
82     if (!src) return !is_rect_empty( &dst->visrect );
83
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 );
89     src->x      = rect.left;
90     src->y      = rect.top;
91     src->width  = rect.right - rect.left;
92     src->height = rect.bottom - rect.top;
93     if (src->layout & LAYOUT_RTL && src->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
94     {
95         swap_ints( &rect.left, &rect.right );
96         src->x = rect.left;
97         src->width = rect.right - rect.left;
98     }
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++; }
101
102     /* source is not clipped */
103     if (dc_src->header.type == OBJ_MEMDC)
104         intersect_rect( &src->visrect, &rect, &dc_src->vis_rect );
105     else
106         src->visrect = rect;  /* FIXME: clip to device size */
107
108     if (is_rect_empty( &src->visrect )) return FALSE;
109     if (is_rect_empty( &dst->visrect )) return FALSE;
110
111     /* intersect the rectangles */
112
113     if ((src->width == dst->width) && (src->height == dst->height)) /* no stretching */
114     {
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 );
119     }
120     else  /* stretching */
121     {
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 );
129
130         /* avoid rounding errors */
131         rect.left--;
132         rect.top--;
133         rect.right++;
134         rect.bottom++;
135         if (!intersect_rect( &dst->visrect, &rect, &dst->visrect )) return FALSE;
136
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 );
144
145         /* avoid rounding errors */
146         rect.left--;
147         rect.top--;
148         rect.right++;
149         rect.bottom++;
150         if (!intersect_rect( &src->visrect, &rect, &src->visrect )) return FALSE;
151     }
152     return TRUE;
153 }
154
155 void free_heap_bits( struct gdi_image_bits *bits )
156 {
157     HeapFree( GetProcessHeap(), 0, bits->ptr );
158 }
159
160 static DWORD convert_bits( const BITMAPINFO *src_info, struct bitblt_coords *src,
161                            BITMAPINFO *dst_info, struct gdi_image_bits *bits )
162 {
163     void *ptr;
164     DWORD err;
165
166     dst_info->bmiHeader.biWidth = src->visrect.right - src->visrect.left;
167     if (!(ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ))))
168         return ERROR_OUTOFMEMORY;
169
170     err = convert_bitmapinfo( src_info, bits->ptr, src, dst_info, ptr );
171     if (bits->free) bits->free( bits );
172     bits->ptr = ptr;
173     bits->is_copy = TRUE;
174     bits->free = free_heap_bits;
175     return err;
176 }
177
178 static DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src,
179                            BITMAPINFO *dst_info, struct bitblt_coords *dst,
180                            struct gdi_image_bits *bits, int mode )
181 {
182     void *ptr;
183     DWORD err;
184
185     dst_info->bmiHeader.biWidth = dst->visrect.right - dst->visrect.left;
186     dst_info->bmiHeader.biHeight = dst->visrect.bottom - dst->visrect.top;
187     if (src_info->bmiHeader.biHeight < 0) dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight;
188     if (!(ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ))))
189         return ERROR_OUTOFMEMORY;
190
191     err = stretch_bitmapinfo( src_info, bits->ptr, src, dst_info, ptr, dst, mode );
192     if (bits->free) bits->free( bits );
193     bits->ptr = ptr;
194     bits->is_copy = TRUE;
195     bits->free = free_heap_bits;
196     return err;
197 }
198
199 /***********************************************************************
200  *           null driver fallback implementations
201  */
202
203 BOOL nulldrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
204                          PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop )
205 {
206     DC *dc_src, *dc_dst = get_nulldrv_dc( dst_dev );
207     char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
208     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
209     BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
210     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
211     DWORD err;
212     struct gdi_image_bits bits;
213
214     if (!(dc_src = get_dc_ptr( src_dev->hdc ))) return FALSE;
215     src_dev = GET_DC_PHYSDEV( dc_src, pGetImage );
216     err = src_dev->funcs->pGetImage( src_dev, 0, src_info, &bits, src );
217     release_dc_ptr( dc_src );
218     if (err) return FALSE;
219
220     dst_dev = GET_DC_PHYSDEV( dc_dst, pPutImage );
221     memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
222     err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, dst_info, &bits, src, dst, rop );
223     if (err == ERROR_BAD_FORMAT)
224     {
225         /* 1-bpp source without a color table uses the destination DC colors */
226         if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
227         {
228             COLORREF color = GetTextColor( dst_dev->hdc );
229             src_info->bmiColors[0].rgbRed      = GetRValue( color );
230             src_info->bmiColors[0].rgbGreen    = GetGValue( color );
231             src_info->bmiColors[0].rgbBlue     = GetBValue( color );
232             src_info->bmiColors[0].rgbReserved = 0;
233             color = GetBkColor( dst_dev->hdc );
234             src_info->bmiColors[1].rgbRed      = GetRValue( color );
235             src_info->bmiColors[1].rgbGreen    = GetGValue( color );
236             src_info->bmiColors[1].rgbBlue     = GetBValue( color );
237             src_info->bmiColors[1].rgbReserved = 0;
238             src_info->bmiHeader.biClrUsed = 2;
239         }
240
241         /* 1-bpp destination without a color table requires a fake 1-entry table
242          * that contains only the background color */
243         if (dst_info->bmiHeader.biBitCount == 1 && !dst_info->bmiHeader.biClrUsed)
244         {
245             COLORREF color = GetBkColor( src_dev->hdc );
246             dst_info->bmiColors[0].rgbRed      = GetRValue( color );
247             dst_info->bmiColors[0].rgbGreen    = GetGValue( color );
248             dst_info->bmiColors[0].rgbBlue     = GetBValue( color );
249             dst_info->bmiColors[0].rgbReserved = 0;
250             dst_info->bmiHeader.biClrUsed = 1;
251         }
252
253         if (!(err = convert_bits( src_info, src, dst_info, &bits )))
254         {
255             /* get rid of the fake 1-bpp table */
256             if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
257             err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, dst_info, &bits, src, dst, rop );
258         }
259     }
260
261     if (err == ERROR_TRANSFORM_NOT_SUPPORTED &&
262         ((src->width != dst->width) || (src->height != dst->height)))
263     {
264         memcpy( src_info, dst_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
265         err = stretch_bits( src_info, src, dst_info, dst, &bits, GetStretchBltMode( dst_dev->hdc ));
266         if (!err) err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, dst_info, &bits, src, dst, rop );
267     }
268
269     if (bits.free) bits.free( &bits );
270     return !err;
271 }
272
273
274 BOOL nulldrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
275                          PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION func )
276 {
277     DC *dc_src, *dc_dst = get_nulldrv_dc( dst_dev );
278     char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
279     char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
280     BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
281     BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
282     DWORD err;
283     struct gdi_image_bits bits;
284
285     if (!(dc_src = get_dc_ptr( src_dev->hdc ))) return FALSE;
286     src_dev = GET_DC_PHYSDEV( dc_src, pGetImage );
287     err = src_dev->funcs->pGetImage( src_dev, 0, src_info, &bits, src );
288     release_dc_ptr( dc_src );
289     if (err) return FALSE;
290
291     dst_dev = GET_DC_PHYSDEV( dc_dst, pBlendImage );
292     memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
293     err = dst_dev->funcs->pBlendImage( dst_dev, dst_info, &bits, src, dst, func );
294     if (err == ERROR_BAD_FORMAT)
295     {
296         err = convert_bits( src_info, src, dst_info, &bits );
297         if (!err) err = dst_dev->funcs->pBlendImage( dst_dev, dst_info, &bits, src, dst, func );
298     }
299
300     if (err == ERROR_TRANSFORM_NOT_SUPPORTED &&
301         ((src->width != dst->width) || (src->height != dst->height)))
302     {
303         memcpy( src_info, dst_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
304         err = stretch_bits( src_info, src, dst_info, dst, &bits, COLORONCOLOR );
305         if (!err) err = dst_dev->funcs->pBlendImage( dst_dev, dst_info, &bits, src, dst, func );
306     }
307
308     if (bits.free) bits.free( &bits );
309     return !err;
310 }
311
312
313 /***********************************************************************
314  *           PatBlt    (GDI32.@)
315  */
316 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop)
317 {
318     DC * dc;
319     BOOL ret = FALSE;
320
321     if (rop_uses_src( rop )) return FALSE;
322     if ((dc = get_dc_ptr( hdc )))
323     {
324         struct bitblt_coords dst;
325         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPatBlt );
326
327         update_dc( dc );
328
329         dst.log_x      = left;
330         dst.log_y      = top;
331         dst.log_width  = width;
332         dst.log_height = height;
333         dst.layout     = dc->layout;
334         if (rop & NOMIRRORBITMAP)
335         {
336             dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
337             rop &= ~NOMIRRORBITMAP;
338         }
339         ret = !get_vis_rectangles( dc, &dst, NULL, NULL );
340
341         TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s  rop=%06x\n",
342               hdc, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
343               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
344
345         if (!ret) ret = physdev->funcs->pPatBlt( physdev, &dst, rop );
346
347         release_dc_ptr( dc );
348     }
349     return ret;
350 }
351
352
353 /***********************************************************************
354  *           BitBlt    (GDI32.@)
355  */
356 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
357                     INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
358 {
359     if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, width, height, rop );
360     else return StretchBlt( hdcDst, xDst, yDst, width, height,
361                             hdcSrc, xSrc, ySrc, width, height, rop );
362 }
363
364
365 /***********************************************************************
366  *           StretchBlt    (GDI32.@)
367  */
368 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
369                         HDC hdcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop )
370 {
371     BOOL ret = FALSE;
372     DC *dcDst, *dcSrc;
373
374     if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, widthDst, heightDst, rop );
375
376     if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
377
378     if ((dcSrc = get_dc_ptr( hdcSrc )))
379     {
380         struct bitblt_coords src, dst;
381         PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pStretchBlt );
382         PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pStretchBlt );
383
384         update_dc( dcSrc );
385         update_dc( dcDst );
386
387         src.log_x      = xSrc;
388         src.log_y      = ySrc;
389         src.log_width  = widthSrc;
390         src.log_height = heightSrc;
391         src.layout     = dcSrc->layout;
392         dst.log_x      = xDst;
393         dst.log_y      = yDst;
394         dst.log_width  = widthDst;
395         dst.log_height = heightDst;
396         dst.layout     = dcDst->layout;
397         if (rop & NOMIRRORBITMAP)
398         {
399             src.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
400             dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
401             rop &= ~NOMIRRORBITMAP;
402         }
403         ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
404
405         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",
406               hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
407               src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
408               hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
409               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
410
411         if (!ret) ret = dst_dev->funcs->pStretchBlt( dst_dev, &dst, src_dev, &src, rop );
412         release_dc_ptr( dcSrc );
413     }
414     release_dc_ptr( dcDst );
415     return ret;
416 }
417
418 #define FRGND_ROP3(ROP4)        ((ROP4) & 0x00FFFFFF)
419 #define BKGND_ROP3(ROP4)        (ROP3Table[((ROP4)>>24) & 0xFF])
420
421 /***********************************************************************
422  *           MaskBlt [GDI32.@]
423  */
424 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
425                         INT nWidth, INT nHeight, HDC hdcSrc,
426                         INT nXSrc, INT nYSrc, HBITMAP hbmMask,
427                         INT xMask, INT yMask, DWORD dwRop)
428 {
429     HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
430     HDC hDC1, hDC2;
431     HBRUSH hbrMask, hbrDst, hbrTmp;
432
433     static const DWORD ROP3Table[256] = 
434     {
435         0x00000042, 0x00010289,
436         0x00020C89, 0x000300AA,
437         0x00040C88, 0x000500A9,
438         0x00060865, 0x000702C5,
439         0x00080F08, 0x00090245,
440         0x000A0329, 0x000B0B2A,
441         0x000C0324, 0x000D0B25,
442         0x000E08A5, 0x000F0001,
443         0x00100C85, 0x001100A6,
444         0x00120868, 0x001302C8,
445         0x00140869, 0x001502C9,
446         0x00165CCA, 0x00171D54,
447         0x00180D59, 0x00191CC8,
448         0x001A06C5, 0x001B0768,
449         0x001C06CA, 0x001D0766,
450         0x001E01A5, 0x001F0385,
451         0x00200F09, 0x00210248,
452         0x00220326, 0x00230B24,
453         0x00240D55, 0x00251CC5,
454         0x002606C8, 0x00271868,
455         0x00280369, 0x002916CA,
456         0x002A0CC9, 0x002B1D58,
457         0x002C0784, 0x002D060A,
458         0x002E064A, 0x002F0E2A,
459         0x0030032A, 0x00310B28,
460         0x00320688, 0x00330008,
461         0x003406C4, 0x00351864,
462         0x003601A8, 0x00370388,
463         0x0038078A, 0x00390604,
464         0x003A0644, 0x003B0E24,
465         0x003C004A, 0x003D18A4,
466         0x003E1B24, 0x003F00EA,
467         0x00400F0A, 0x00410249,
468         0x00420D5D, 0x00431CC4,
469         0x00440328, 0x00450B29,
470         0x004606C6, 0x0047076A,
471         0x00480368, 0x004916C5,
472         0x004A0789, 0x004B0605,
473         0x004C0CC8, 0x004D1954,
474         0x004E0645, 0x004F0E25,
475         0x00500325, 0x00510B26,
476         0x005206C9, 0x00530764,
477         0x005408A9, 0x00550009,
478         0x005601A9, 0x00570389,
479         0x00580785, 0x00590609,
480         0x005A0049, 0x005B18A9,
481         0x005C0649, 0x005D0E29,
482         0x005E1B29, 0x005F00E9,
483         0x00600365, 0x006116C6,
484         0x00620786, 0x00630608,
485         0x00640788, 0x00650606,
486         0x00660046, 0x006718A8,
487         0x006858A6, 0x00690145,
488         0x006A01E9, 0x006B178A,
489         0x006C01E8, 0x006D1785,
490         0x006E1E28, 0x006F0C65,
491         0x00700CC5, 0x00711D5C,
492         0x00720648, 0x00730E28,
493         0x00740646, 0x00750E26,
494         0x00761B28, 0x007700E6,
495         0x007801E5, 0x00791786,
496         0x007A1E29, 0x007B0C68,
497         0x007C1E24, 0x007D0C69,
498         0x007E0955, 0x007F03C9,
499         0x008003E9, 0x00810975,
500         0x00820C49, 0x00831E04,
501         0x00840C48, 0x00851E05,
502         0x008617A6, 0x008701C5,
503         0x008800C6, 0x00891B08,
504         0x008A0E06, 0x008B0666,
505         0x008C0E08, 0x008D0668,
506         0x008E1D7C, 0x008F0CE5,
507         0x00900C45, 0x00911E08,
508         0x009217A9, 0x009301C4,
509         0x009417AA, 0x009501C9,
510         0x00960169, 0x0097588A,
511         0x00981888, 0x00990066,
512         0x009A0709, 0x009B07A8,
513         0x009C0704, 0x009D07A6,
514         0x009E16E6, 0x009F0345,
515         0x00A000C9, 0x00A11B05,
516         0x00A20E09, 0x00A30669,
517         0x00A41885, 0x00A50065,
518         0x00A60706, 0x00A707A5,
519         0x00A803A9, 0x00A90189,
520         0x00AA0029, 0x00AB0889,
521         0x00AC0744, 0x00AD06E9,
522         0x00AE0B06, 0x00AF0229,
523         0x00B00E05, 0x00B10665,
524         0x00B21974, 0x00B30CE8,
525         0x00B4070A, 0x00B507A9,
526         0x00B616E9, 0x00B70348,
527         0x00B8074A, 0x00B906E6,
528         0x00BA0B09, 0x00BB0226,
529         0x00BC1CE4, 0x00BD0D7D,
530         0x00BE0269, 0x00BF08C9,
531         0x00C000CA, 0x00C11B04,
532         0x00C21884, 0x00C3006A,
533         0x00C40E04, 0x00C50664,
534         0x00C60708, 0x00C707AA,
535         0x00C803A8, 0x00C90184,
536         0x00CA0749, 0x00CB06E4,
537         0x00CC0020, 0x00CD0888,
538         0x00CE0B08, 0x00CF0224,
539         0x00D00E0A, 0x00D1066A,
540         0x00D20705, 0x00D307A4,
541         0x00D41D78, 0x00D50CE9,
542         0x00D616EA, 0x00D70349,
543         0x00D80745, 0x00D906E8,
544         0x00DA1CE9, 0x00DB0D75,
545         0x00DC0B04, 0x00DD0228,
546         0x00DE0268, 0x00DF08C8,
547         0x00E003A5, 0x00E10185,
548         0x00E20746, 0x00E306EA,
549         0x00E40748, 0x00E506E5,
550         0x00E61CE8, 0x00E70D79,
551         0x00E81D74, 0x00E95CE6,
552         0x00EA02E9, 0x00EB0849,
553         0x00EC02E8, 0x00ED0848,
554         0x00EE0086, 0x00EF0A08,
555         0x00F00021, 0x00F10885,
556         0x00F20B05, 0x00F3022A,
557         0x00F40B0A, 0x00F50225,
558         0x00F60265, 0x00F708C5,
559         0x00F802E5, 0x00F90845,
560         0x00FA0089, 0x00FB0A09,
561         0x00FC008A, 0x00FD0A0A,
562         0x00FE02A9, 0x00FF0062,
563     };
564
565     if (!hbmMask)
566         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
567
568     hbrMask = CreatePatternBrush(hbmMask);
569     hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
570
571     /* make bitmap */
572     hDC1 = CreateCompatibleDC(hdcDest);
573     hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
574     hOldBitmap1 = SelectObject(hDC1, hBitmap1);
575
576     /* draw using bkgnd rop */
577     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
578     hbrTmp = SelectObject(hDC1, hbrDst);
579     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
580     SelectObject(hDC1, hbrTmp);
581
582     /* make bitmap */
583     hDC2 = CreateCompatibleDC(hdcDest);
584     hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
585     hOldBitmap2 = SelectObject(hDC2, hBitmap2);
586
587     /* draw using foregnd rop */
588     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
589     hbrTmp = SelectObject(hDC2, hbrDst);
590     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
591
592     /* combine both using the mask as a pattern brush */
593     SelectObject(hDC2, hbrMask);
594     BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */ 
595     SelectObject(hDC2, hbrTmp);
596
597     /* blit to dst */
598     BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
599
600     /* restore all objects */
601     SelectObject(hdcDest, hbrDst);
602     SelectObject(hDC1, hOldBitmap1);
603     SelectObject(hDC2, hOldBitmap2);
604
605     /* delete all temp objects */
606     DeleteObject(hBitmap1);
607     DeleteObject(hBitmap2);
608     DeleteObject(hbrMask);
609
610     DeleteDC(hDC1);
611     DeleteDC(hDC2);
612
613     return TRUE;
614 }
615
616 /******************************************************************************
617  *           GdiTransparentBlt [GDI32.@]
618  */
619 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
620                             HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
621                             UINT crTransparent )
622 {
623     BOOL ret = FALSE;
624     HDC hdcWork;
625     HBITMAP bmpWork;
626     HGDIOBJ oldWork;
627     HDC hdcMask = NULL;
628     HBITMAP bmpMask = NULL;
629     HBITMAP oldMask = NULL;
630     COLORREF oldBackground;
631     COLORREF oldForeground;
632     int oldStretchMode;
633
634     if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
635         TRACE("Cannot mirror\n");
636         return FALSE;
637     }
638
639     oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
640     oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
641
642     /* Stretch bitmap */
643     oldStretchMode = GetStretchBltMode(hdcSrc);
644     if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
645         SetStretchBltMode(hdcSrc, COLORONCOLOR);
646     hdcWork = CreateCompatibleDC(hdcDest);
647     bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
648     oldWork = SelectObject(hdcWork, bmpWork);
649     if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
650         TRACE("Failed to stretch\n");
651         goto error;
652     }
653     SetBkColor(hdcWork, crTransparent);
654
655     /* Create mask */
656     hdcMask = CreateCompatibleDC(hdcDest);
657     bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
658     oldMask = SelectObject(hdcMask, bmpMask);
659     if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
660         TRACE("Failed to create mask\n");
661         goto error;
662     }
663
664     /* Replace transparent color with black */
665     SetBkColor(hdcWork, RGB(0,0,0));
666     SetTextColor(hdcWork, RGB(255,255,255));
667     if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
668         TRACE("Failed to mask out background\n");
669         goto error;
670     }
671
672     /* Replace non-transparent area on destination with black */
673     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
674         TRACE("Failed to clear destination area\n");
675         goto error;
676     }
677
678     /* Draw the image */
679     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
680         TRACE("Failed to paint image\n");
681         goto error;
682     }
683
684     ret = TRUE;
685 error:
686     SetStretchBltMode(hdcSrc, oldStretchMode);
687     SetBkColor(hdcDest, oldBackground);
688     SetTextColor(hdcDest, oldForeground);
689     if(hdcWork) {
690         SelectObject(hdcWork, oldWork);
691         DeleteDC(hdcWork);
692     }
693     if(bmpWork) DeleteObject(bmpWork);
694     if(hdcMask) {
695         SelectObject(hdcMask, oldMask);
696         DeleteDC(hdcMask);
697     }
698     if(bmpMask) DeleteObject(bmpMask);
699     return ret;
700 }
701
702 /******************************************************************************
703  *           GdiAlphaBlend [GDI32.@]
704  */
705 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
706                           HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
707                           BLENDFUNCTION blendFunction)
708 {
709     BOOL ret = FALSE;
710     DC *dcDst, *dcSrc;
711
712     dcSrc = get_dc_ptr( hdcSrc );
713     if (!dcSrc) return FALSE;
714
715     if ((dcDst = get_dc_ptr( hdcDst )))
716     {
717         struct bitblt_coords src, dst;
718         PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pAlphaBlend );
719         PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pAlphaBlend );
720
721         update_dc( dcSrc );
722         update_dc( dcDst );
723
724         src.log_x      = xSrc;
725         src.log_y      = ySrc;
726         src.log_width  = widthSrc;
727         src.log_height = heightSrc;
728         src.layout     = GetLayout( src_dev->hdc );
729         dst.log_x      = xDst;
730         dst.log_y      = yDst;
731         dst.log_width  = widthDst;
732         dst.log_height = heightDst;
733         dst.layout     = GetLayout( dst_dev->hdc );
734         ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
735
736         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",
737               hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
738               src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
739               hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
740               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect),
741               blendFunction.BlendOp, blendFunction.BlendFlags,
742               blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
743
744         if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
745             (dcSrc->header.type == OBJ_MEMDC &&
746              (src.width > dcSrc->vis_rect.right - dcSrc->vis_rect.left - src.x ||
747               src.height > dcSrc->vis_rect.bottom - dcSrc->vis_rect.top - src.y)))
748         {
749             WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
750             SetLastError( ERROR_INVALID_PARAMETER );
751             ret = FALSE;
752         }
753         else if (dst.width < 0 || dst.height < 0)
754         {
755             WARN( "Invalid dst coords: (%d,%d), size %dx%d\n", dst.x, dst.y, dst.width, dst.height );
756             SetLastError( ERROR_INVALID_PARAMETER );
757             ret = FALSE;
758         }
759         else if (!ret) ret = dst_dev->funcs->pAlphaBlend( dst_dev, &dst, src_dev, &src, blendFunction );
760
761         release_dc_ptr( dcDst );
762     }
763     release_dc_ptr( dcSrc );
764     return ret;
765 }
766
767 /*********************************************************************
768  *      PlgBlt [GDI32.@]
769  *
770  */
771 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
772                         HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
773                         INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
774 {
775     int oldgMode;
776     /* parallelogram coords */
777     POINT plg[3];
778     /* rect coords */
779     POINT rect[3];
780     XFORM xf;
781     XFORM SrcXf;
782     XFORM oldDestXf;
783     double det;
784
785     /* save actual mode, set GM_ADVANCED */
786     oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
787     if (oldgMode == 0)
788         return FALSE;
789
790     memcpy(plg,lpPoint,sizeof(POINT)*3);
791     rect[0].x = nXSrc;
792     rect[0].y = nYSrc;
793     rect[1].x = nXSrc + nWidth;
794     rect[1].y = nYSrc;
795     rect[2].x = nXSrc;
796     rect[2].y = nYSrc + nHeight;
797     /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
798     /* determinant */
799     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);
800
801     if (fabs(det) < 1e-5)
802     {
803         SetGraphicsMode(hdcDest,oldgMode);
804         return FALSE;
805     }
806
807     TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
808         hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
809
810     /* X components */
811     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;
812     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;
813     xf.eDx  = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
814                rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
815                rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
816                ) / det;
817
818     /* Y components */
819     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;
820     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;
821     xf.eDy  = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
822                rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
823                rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
824                ) / det;
825
826     GetWorldTransform(hdcSrc,&SrcXf);
827     CombineTransform(&xf,&xf,&SrcXf);
828
829     /* save actual dest transform */
830     GetWorldTransform(hdcDest,&oldDestXf);
831
832     SetWorldTransform(hdcDest,&xf);
833     /* now destination and source DCs use same coords */
834     MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
835             hdcSrc, nXSrc,nYSrc,
836             hbmMask,xMask,yMask,
837             SRCCOPY);
838     /* restore dest DC */
839     SetWorldTransform(hdcDest,&oldDestXf);
840     SetGraphicsMode(hdcDest,oldgMode);
841
842     return TRUE;
843 }