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