gdiplus: Remove unreachable break after return (Smatch).
[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         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPatBlt );
522
523         update_dc( dc );
524
525         dst.log_x      = left;
526         dst.log_y      = top;
527         dst.log_width  = width;
528         dst.log_height = height;
529         dst.layout     = dc->layout;
530         if (rop & NOMIRRORBITMAP)
531         {
532             dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
533             rop &= ~NOMIRRORBITMAP;
534         }
535         ret = !get_vis_rectangles( dc, &dst, NULL, NULL );
536
537         TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s  rop=%06x\n",
538               hdc, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
539               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
540
541         if (!ret) ret = physdev->funcs->pPatBlt( physdev, &dst, rop );
542
543         release_dc_ptr( dc );
544     }
545     return ret;
546 }
547
548
549 /***********************************************************************
550  *           BitBlt    (GDI32.@)
551  */
552 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
553                     INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
554 {
555     if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, width, height, rop );
556     else return StretchBlt( hdcDst, xDst, yDst, width, height,
557                             hdcSrc, xSrc, ySrc, width, height, rop );
558 }
559
560
561 /***********************************************************************
562  *           StretchBlt    (GDI32.@)
563  */
564 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
565                         HDC hdcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop )
566 {
567     BOOL ret = FALSE;
568     DC *dcDst, *dcSrc;
569
570     if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, widthDst, heightDst, rop );
571
572     if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
573
574     if ((dcSrc = get_dc_ptr( hdcSrc )))
575     {
576         struct bitblt_coords src, dst;
577         PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pStretchBlt );
578         PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pStretchBlt );
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) ret = dst_dev->funcs->pStretchBlt( dst_dev, &dst, src_dev, &src, rop );
608         release_dc_ptr( dcSrc );
609     }
610     release_dc_ptr( dcDst );
611     return ret;
612 }
613
614 #define FRGND_ROP3(ROP4)        ((ROP4) & 0x00FFFFFF)
615 #define BKGND_ROP3(ROP4)        (ROP3Table[((ROP4)>>24) & 0xFF])
616
617 /***********************************************************************
618  *           MaskBlt [GDI32.@]
619  */
620 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
621                         INT nWidth, INT nHeight, HDC hdcSrc,
622                         INT nXSrc, INT nYSrc, HBITMAP hbmMask,
623                         INT xMask, INT yMask, DWORD dwRop)
624 {
625     HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
626     HDC hDC1, hDC2;
627     HBRUSH hbrMask, hbrDst, hbrTmp;
628
629     static const DWORD ROP3Table[256] = 
630     {
631         0x00000042, 0x00010289,
632         0x00020C89, 0x000300AA,
633         0x00040C88, 0x000500A9,
634         0x00060865, 0x000702C5,
635         0x00080F08, 0x00090245,
636         0x000A0329, 0x000B0B2A,
637         0x000C0324, 0x000D0B25,
638         0x000E08A5, 0x000F0001,
639         0x00100C85, 0x001100A6,
640         0x00120868, 0x001302C8,
641         0x00140869, 0x001502C9,
642         0x00165CCA, 0x00171D54,
643         0x00180D59, 0x00191CC8,
644         0x001A06C5, 0x001B0768,
645         0x001C06CA, 0x001D0766,
646         0x001E01A5, 0x001F0385,
647         0x00200F09, 0x00210248,
648         0x00220326, 0x00230B24,
649         0x00240D55, 0x00251CC5,
650         0x002606C8, 0x00271868,
651         0x00280369, 0x002916CA,
652         0x002A0CC9, 0x002B1D58,
653         0x002C0784, 0x002D060A,
654         0x002E064A, 0x002F0E2A,
655         0x0030032A, 0x00310B28,
656         0x00320688, 0x00330008,
657         0x003406C4, 0x00351864,
658         0x003601A8, 0x00370388,
659         0x0038078A, 0x00390604,
660         0x003A0644, 0x003B0E24,
661         0x003C004A, 0x003D18A4,
662         0x003E1B24, 0x003F00EA,
663         0x00400F0A, 0x00410249,
664         0x00420D5D, 0x00431CC4,
665         0x00440328, 0x00450B29,
666         0x004606C6, 0x0047076A,
667         0x00480368, 0x004916C5,
668         0x004A0789, 0x004B0605,
669         0x004C0CC8, 0x004D1954,
670         0x004E0645, 0x004F0E25,
671         0x00500325, 0x00510B26,
672         0x005206C9, 0x00530764,
673         0x005408A9, 0x00550009,
674         0x005601A9, 0x00570389,
675         0x00580785, 0x00590609,
676         0x005A0049, 0x005B18A9,
677         0x005C0649, 0x005D0E29,
678         0x005E1B29, 0x005F00E9,
679         0x00600365, 0x006116C6,
680         0x00620786, 0x00630608,
681         0x00640788, 0x00650606,
682         0x00660046, 0x006718A8,
683         0x006858A6, 0x00690145,
684         0x006A01E9, 0x006B178A,
685         0x006C01E8, 0x006D1785,
686         0x006E1E28, 0x006F0C65,
687         0x00700CC5, 0x00711D5C,
688         0x00720648, 0x00730E28,
689         0x00740646, 0x00750E26,
690         0x00761B28, 0x007700E6,
691         0x007801E5, 0x00791786,
692         0x007A1E29, 0x007B0C68,
693         0x007C1E24, 0x007D0C69,
694         0x007E0955, 0x007F03C9,
695         0x008003E9, 0x00810975,
696         0x00820C49, 0x00831E04,
697         0x00840C48, 0x00851E05,
698         0x008617A6, 0x008701C5,
699         0x008800C6, 0x00891B08,
700         0x008A0E06, 0x008B0666,
701         0x008C0E08, 0x008D0668,
702         0x008E1D7C, 0x008F0CE5,
703         0x00900C45, 0x00911E08,
704         0x009217A9, 0x009301C4,
705         0x009417AA, 0x009501C9,
706         0x00960169, 0x0097588A,
707         0x00981888, 0x00990066,
708         0x009A0709, 0x009B07A8,
709         0x009C0704, 0x009D07A6,
710         0x009E16E6, 0x009F0345,
711         0x00A000C9, 0x00A11B05,
712         0x00A20E09, 0x00A30669,
713         0x00A41885, 0x00A50065,
714         0x00A60706, 0x00A707A5,
715         0x00A803A9, 0x00A90189,
716         0x00AA0029, 0x00AB0889,
717         0x00AC0744, 0x00AD06E9,
718         0x00AE0B06, 0x00AF0229,
719         0x00B00E05, 0x00B10665,
720         0x00B21974, 0x00B30CE8,
721         0x00B4070A, 0x00B507A9,
722         0x00B616E9, 0x00B70348,
723         0x00B8074A, 0x00B906E6,
724         0x00BA0B09, 0x00BB0226,
725         0x00BC1CE4, 0x00BD0D7D,
726         0x00BE0269, 0x00BF08C9,
727         0x00C000CA, 0x00C11B04,
728         0x00C21884, 0x00C3006A,
729         0x00C40E04, 0x00C50664,
730         0x00C60708, 0x00C707AA,
731         0x00C803A8, 0x00C90184,
732         0x00CA0749, 0x00CB06E4,
733         0x00CC0020, 0x00CD0888,
734         0x00CE0B08, 0x00CF0224,
735         0x00D00E0A, 0x00D1066A,
736         0x00D20705, 0x00D307A4,
737         0x00D41D78, 0x00D50CE9,
738         0x00D616EA, 0x00D70349,
739         0x00D80745, 0x00D906E8,
740         0x00DA1CE9, 0x00DB0D75,
741         0x00DC0B04, 0x00DD0228,
742         0x00DE0268, 0x00DF08C8,
743         0x00E003A5, 0x00E10185,
744         0x00E20746, 0x00E306EA,
745         0x00E40748, 0x00E506E5,
746         0x00E61CE8, 0x00E70D79,
747         0x00E81D74, 0x00E95CE6,
748         0x00EA02E9, 0x00EB0849,
749         0x00EC02E8, 0x00ED0848,
750         0x00EE0086, 0x00EF0A08,
751         0x00F00021, 0x00F10885,
752         0x00F20B05, 0x00F3022A,
753         0x00F40B0A, 0x00F50225,
754         0x00F60265, 0x00F708C5,
755         0x00F802E5, 0x00F90845,
756         0x00FA0089, 0x00FB0A09,
757         0x00FC008A, 0x00FD0A0A,
758         0x00FE02A9, 0x00FF0062,
759     };
760
761     if (!hbmMask)
762         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
763
764     hbrMask = CreatePatternBrush(hbmMask);
765     hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
766
767     /* make bitmap */
768     hDC1 = CreateCompatibleDC(hdcDest);
769     hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
770     hOldBitmap1 = SelectObject(hDC1, hBitmap1);
771
772     /* draw using bkgnd rop */
773     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
774     hbrTmp = SelectObject(hDC1, hbrDst);
775     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
776     SelectObject(hDC1, hbrTmp);
777
778     /* make bitmap */
779     hDC2 = CreateCompatibleDC(hdcDest);
780     hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
781     hOldBitmap2 = SelectObject(hDC2, hBitmap2);
782
783     /* draw using foregnd rop */
784     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
785     hbrTmp = SelectObject(hDC2, hbrDst);
786     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
787
788     /* combine both using the mask as a pattern brush */
789     SelectObject(hDC2, hbrMask);
790     BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */ 
791     SelectObject(hDC2, hbrTmp);
792
793     /* blit to dst */
794     BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
795
796     /* restore all objects */
797     SelectObject(hdcDest, hbrDst);
798     SelectObject(hDC1, hOldBitmap1);
799     SelectObject(hDC2, hOldBitmap2);
800
801     /* delete all temp objects */
802     DeleteObject(hBitmap1);
803     DeleteObject(hBitmap2);
804     DeleteObject(hbrMask);
805
806     DeleteDC(hDC1);
807     DeleteDC(hDC2);
808
809     return TRUE;
810 }
811
812 /******************************************************************************
813  *           GdiTransparentBlt [GDI32.@]
814  */
815 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
816                             HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
817                             UINT crTransparent )
818 {
819     BOOL ret = FALSE;
820     HDC hdcWork;
821     HBITMAP bmpWork;
822     HGDIOBJ oldWork;
823     HDC hdcMask = NULL;
824     HBITMAP bmpMask = NULL;
825     HBITMAP oldMask = NULL;
826     COLORREF oldBackground;
827     COLORREF oldForeground;
828     int oldStretchMode;
829
830     if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
831         TRACE("Cannot mirror\n");
832         return FALSE;
833     }
834
835     oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
836     oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
837
838     /* Stretch bitmap */
839     oldStretchMode = GetStretchBltMode(hdcSrc);
840     if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
841         SetStretchBltMode(hdcSrc, COLORONCOLOR);
842     hdcWork = CreateCompatibleDC(hdcDest);
843     bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
844     oldWork = SelectObject(hdcWork, bmpWork);
845     if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
846         TRACE("Failed to stretch\n");
847         goto error;
848     }
849     SetBkColor(hdcWork, crTransparent);
850
851     /* Create mask */
852     hdcMask = CreateCompatibleDC(hdcDest);
853     bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
854     oldMask = SelectObject(hdcMask, bmpMask);
855     if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
856         TRACE("Failed to create mask\n");
857         goto error;
858     }
859
860     /* Replace transparent color with black */
861     SetBkColor(hdcWork, RGB(0,0,0));
862     SetTextColor(hdcWork, RGB(255,255,255));
863     if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
864         TRACE("Failed to mask out background\n");
865         goto error;
866     }
867
868     /* Replace non-transparent area on destination with black */
869     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
870         TRACE("Failed to clear destination area\n");
871         goto error;
872     }
873
874     /* Draw the image */
875     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
876         TRACE("Failed to paint image\n");
877         goto error;
878     }
879
880     ret = TRUE;
881 error:
882     SetStretchBltMode(hdcSrc, oldStretchMode);
883     SetBkColor(hdcDest, oldBackground);
884     SetTextColor(hdcDest, oldForeground);
885     if(hdcWork) {
886         SelectObject(hdcWork, oldWork);
887         DeleteDC(hdcWork);
888     }
889     if(bmpWork) DeleteObject(bmpWork);
890     if(hdcMask) {
891         SelectObject(hdcMask, oldMask);
892         DeleteDC(hdcMask);
893     }
894     if(bmpMask) DeleteObject(bmpMask);
895     return ret;
896 }
897
898 /******************************************************************************
899  *           GdiAlphaBlend [GDI32.@]
900  */
901 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
902                           HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
903                           BLENDFUNCTION blendFunction)
904 {
905     BOOL ret = FALSE;
906     DC *dcDst, *dcSrc;
907
908     dcSrc = get_dc_ptr( hdcSrc );
909     if (!dcSrc) return FALSE;
910
911     if ((dcDst = get_dc_ptr( hdcDst )))
912     {
913         struct bitblt_coords src, dst;
914         PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pAlphaBlend );
915         PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pAlphaBlend );
916
917         update_dc( dcSrc );
918         update_dc( dcDst );
919
920         src.log_x      = xSrc;
921         src.log_y      = ySrc;
922         src.log_width  = widthSrc;
923         src.log_height = heightSrc;
924         src.layout     = GetLayout( src_dev->hdc );
925         dst.log_x      = xDst;
926         dst.log_y      = yDst;
927         dst.log_width  = widthDst;
928         dst.log_height = heightDst;
929         dst.layout     = GetLayout( dst_dev->hdc );
930         ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
931
932         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",
933               hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
934               src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
935               hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
936               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect),
937               blendFunction.BlendOp, blendFunction.BlendFlags,
938               blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
939
940         if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
941             src.log_width < 0 || src.log_height < 0 ||
942             (!is_rect_empty( &dcSrc->device_rect ) &&
943              (src.width > dcSrc->device_rect.right - dcSrc->vis_rect.left - src.x ||
944               src.height > dcSrc->device_rect.bottom - dcSrc->vis_rect.top - src.y)))
945         {
946             WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
947             SetLastError( ERROR_INVALID_PARAMETER );
948             ret = FALSE;
949         }
950         else if (dst.log_width < 0 || dst.log_height < 0)
951         {
952             WARN( "Invalid dst coords: (%d,%d), size %dx%d\n",
953                   dst.log_x, dst.log_y, dst.log_width, dst.log_height );
954             SetLastError( ERROR_INVALID_PARAMETER );
955             ret = FALSE;
956         }
957         else if (dcSrc == dcDst && src.x + src.width > dst.x && src.x < dst.x + dst.width &&
958                  src.y + src.height > dst.y && src.y < dst.y + dst.height)
959         {
960             WARN( "Overlapping coords: (%d,%d), %dx%d and (%d,%d), %dx%d\n",
961                   src.x, src.y, src.width, src.height, dst.x, dst.y, dst.width, dst.height );
962             SetLastError( ERROR_INVALID_PARAMETER );
963             ret = FALSE;
964         }
965         else if (!ret) ret = dst_dev->funcs->pAlphaBlend( dst_dev, &dst, src_dev, &src, blendFunction );
966
967         release_dc_ptr( dcDst );
968     }
969     release_dc_ptr( dcSrc );
970     return ret;
971 }
972
973 /*********************************************************************
974  *      PlgBlt [GDI32.@]
975  *
976  */
977 BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
978                         HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
979                         INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
980 {
981     int oldgMode;
982     /* parallelogram coords */
983     POINT plg[3];
984     /* rect coords */
985     POINT rect[3];
986     XFORM xf;
987     XFORM SrcXf;
988     XFORM oldDestXf;
989     double det;
990
991     /* save actual mode, set GM_ADVANCED */
992     oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
993     if (oldgMode == 0)
994         return FALSE;
995
996     memcpy(plg,lpPoint,sizeof(POINT)*3);
997     rect[0].x = nXSrc;
998     rect[0].y = nYSrc;
999     rect[1].x = nXSrc + nWidth;
1000     rect[1].y = nYSrc;
1001     rect[2].x = nXSrc;
1002     rect[2].y = nYSrc + nHeight;
1003     /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
1004     /* determinant */
1005     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);
1006
1007     if (fabs(det) < 1e-5)
1008     {
1009         SetGraphicsMode(hdcDest,oldgMode);
1010         return FALSE;
1011     }
1012
1013     TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
1014         hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y);
1015
1016     /* X components */
1017     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;
1018     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;
1019     xf.eDx  = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) -
1020                rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) +
1021                rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x)
1022                ) / det;
1023
1024     /* Y components */
1025     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;
1026     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;
1027     xf.eDy  = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) -
1028                rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) +
1029                rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
1030                ) / det;
1031
1032     GetWorldTransform(hdcSrc,&SrcXf);
1033     CombineTransform(&xf,&xf,&SrcXf);
1034
1035     /* save actual dest transform */
1036     GetWorldTransform(hdcDest,&oldDestXf);
1037
1038     SetWorldTransform(hdcDest,&xf);
1039     /* now destination and source DCs use same coords */
1040     MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
1041             hdcSrc, nXSrc,nYSrc,
1042             hbmMask,xMask,yMask,
1043             SRCCOPY);
1044     /* restore dest DC */
1045     SetWorldTransform(hdcDest,&oldDestXf);
1046     SetGraphicsMode(hdcDest,oldgMode);
1047
1048     return TRUE;
1049 }