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