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