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