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