user32: Modify EDIT_GetLineRect to better handle RTL lines.
[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 = TRUE;
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     dst.visrect.left = dst.visrect.top = INT_MAX;
412     dst.visrect.right = dst.visrect.bottom = INT_MIN;
413     for (i = 0; i < ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2); i++)
414     {
415         ULONG v = ((ULONG *)grad_array)[i];
416         dst.visrect.left   = min( dst.visrect.left,   pts[v].x );
417         dst.visrect.top    = min( dst.visrect.top,    pts[v].y );
418         dst.visrect.right  = max( dst.visrect.right,  pts[v].x );
419         dst.visrect.bottom = max( dst.visrect.bottom, pts[v].y );
420     }
421
422     dst.x = dst.visrect.left;
423     dst.y = dst.visrect.top;
424     dst.width = dst.visrect.right - dst.visrect.left;
425     dst.height = dst.visrect.bottom - dst.visrect.top;
426     if (!clip_visrect( dc, &dst.visrect, &dst.visrect )) goto done;
427
428     /* query the bitmap format */
429     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
430     info->bmiHeader.biPlanes        = 1;
431     info->bmiHeader.biBitCount      = 0;
432     info->bmiHeader.biCompression   = BI_RGB;
433     info->bmiHeader.biXPelsPerMeter = 0;
434     info->bmiHeader.biYPelsPerMeter = 0;
435     info->bmiHeader.biClrUsed       = 0;
436     info->bmiHeader.biClrImportant  = 0;
437     info->bmiHeader.biWidth         = dst.visrect.right - dst.visrect.left;
438     info->bmiHeader.biHeight        = dst.visrect.bottom - dst.visrect.top;
439     info->bmiHeader.biSizeImage     = get_dib_image_size( info );
440     dev = GET_DC_PHYSDEV( dc, pPutImage );
441     err = dev->funcs->pPutImage( dev, 0, 0, info, NULL, NULL, NULL, 0 );
442     if ((err && err != ERROR_BAD_FORMAT) ||
443         !(bits.ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage )))
444     {
445         ret = FALSE;
446         goto done;
447     }
448     bits.is_copy = TRUE;
449     bits.free = free_heap_bits;
450
451     /* make src and points relative to the bitmap */
452     src = dst;
453     src.x -= dst.visrect.left;
454     src.y -= dst.visrect.top;
455     offset_rect( &src.visrect, -dst.visrect.left, -dst.visrect.top );
456     for (i = 0; i < nvert; i++)
457     {
458         pts[i].x -= dst.visrect.left;
459         pts[i].y -= dst.visrect.top;
460     }
461
462     rgn = CreateRectRgn( 0, 0, 0, 0 );
463     gradient_bitmapinfo( info, bits.ptr, vert_array, nvert, grad_array, ngrad, mode, pts, rgn );
464     OffsetRgn( rgn, dst.visrect.left, dst.visrect.top );
465     if (dev->funcs->pPutImage( dev, 0, rgn, info, &bits, &src, &dst, SRCCOPY )) ret = FALSE;
466
467     if (bits.free) bits.free( &bits );
468     DeleteObject( rgn );
469
470 done:
471     HeapFree( GetProcessHeap(), 0, pts );
472     return ret;
473 }
474
475 COLORREF nulldrv_GetPixel( PHYSDEV dev, INT x, INT y )
476 {
477     DC *dc = get_nulldrv_dc( dev );
478     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
479     BITMAPINFO *info = (BITMAPINFO *)buffer;
480     struct bitblt_coords src;
481     struct gdi_image_bits bits;
482     COLORREF ret;
483
484     src.visrect.left = x;
485     src.visrect.top  = y;
486     LPtoDP( dev->hdc, (POINT *)&src.visrect, 1 );
487     src.visrect.right  = src.visrect.left + 1;
488     src.visrect.bottom = src.visrect.top + 1;
489     src.x = src.visrect.left;
490     src.y = src.visrect.top;
491     src.width = src.height = 1;
492
493     if (!clip_visrect( dc, &src.visrect, &src.visrect )) return CLR_INVALID;
494
495     dev = GET_DC_PHYSDEV( dc, pGetImage );
496     if (dev->funcs->pGetImage( dev, 0, info, &bits, &src )) return CLR_INVALID;
497
498     ret = get_pixel_bitmapinfo( info, bits.ptr, &src );
499     if (bits.free) bits.free( &bits );
500     return ret;
501 }
502
503
504 /***********************************************************************
505  *           PatBlt    (GDI32.@)
506  */
507 BOOL WINAPI PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop)
508 {
509     DC * dc;
510     BOOL ret = FALSE;
511
512     if (rop_uses_src( rop )) return FALSE;
513     if ((dc = get_dc_ptr( hdc )))
514     {
515         struct bitblt_coords dst;
516         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPatBlt );
517
518         update_dc( dc );
519
520         dst.log_x      = left;
521         dst.log_y      = top;
522         dst.log_width  = width;
523         dst.log_height = height;
524         dst.layout     = dc->layout;
525         if (rop & NOMIRRORBITMAP)
526         {
527             dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
528             rop &= ~NOMIRRORBITMAP;
529         }
530         ret = !get_vis_rectangles( dc, &dst, NULL, NULL );
531
532         TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s  rop=%06x\n",
533               hdc, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
534               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
535
536         if (!ret) ret = physdev->funcs->pPatBlt( physdev, &dst, rop );
537
538         release_dc_ptr( dc );
539     }
540     return ret;
541 }
542
543
544 /***********************************************************************
545  *           BitBlt    (GDI32.@)
546  */
547 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
548                     INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
549 {
550     if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, width, height, rop );
551     else return StretchBlt( hdcDst, xDst, yDst, width, height,
552                             hdcSrc, xSrc, ySrc, width, height, rop );
553 }
554
555
556 /***********************************************************************
557  *           StretchBlt    (GDI32.@)
558  */
559 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
560                         HDC hdcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop )
561 {
562     BOOL ret = FALSE;
563     DC *dcDst, *dcSrc;
564
565     if (!rop_uses_src( rop )) return PatBlt( hdcDst, xDst, yDst, widthDst, heightDst, rop );
566
567     if (!(dcDst = get_dc_ptr( hdcDst ))) return FALSE;
568
569     if ((dcSrc = get_dc_ptr( hdcSrc )))
570     {
571         struct bitblt_coords src, dst;
572         PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pStretchBlt );
573         PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pStretchBlt );
574
575         update_dc( dcSrc );
576         update_dc( dcDst );
577
578         src.log_x      = xSrc;
579         src.log_y      = ySrc;
580         src.log_width  = widthSrc;
581         src.log_height = heightSrc;
582         src.layout     = dcSrc->layout;
583         dst.log_x      = xDst;
584         dst.log_y      = yDst;
585         dst.log_width  = widthDst;
586         dst.log_height = heightDst;
587         dst.layout     = dcDst->layout;
588         if (rop & NOMIRRORBITMAP)
589         {
590             src.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
591             dst.layout |= LAYOUT_BITMAPORIENTATIONPRESERVED;
592             rop &= ~NOMIRRORBITMAP;
593         }
594         ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
595
596         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",
597               hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
598               src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
599               hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
600               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect), rop );
601
602         if (!ret) ret = dst_dev->funcs->pStretchBlt( dst_dev, &dst, src_dev, &src, rop );
603         release_dc_ptr( dcSrc );
604     }
605     release_dc_ptr( dcDst );
606     return ret;
607 }
608
609 #define FRGND_ROP3(ROP4)        ((ROP4) & 0x00FFFFFF)
610 #define BKGND_ROP3(ROP4)        (ROP3Table[((ROP4)>>24) & 0xFF])
611
612 /***********************************************************************
613  *           MaskBlt [GDI32.@]
614  */
615 BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest,
616                         INT nWidth, INT nHeight, HDC hdcSrc,
617                         INT nXSrc, INT nYSrc, HBITMAP hbmMask,
618                         INT xMask, INT yMask, DWORD dwRop)
619 {
620     HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2;
621     HDC hDC1, hDC2;
622     HBRUSH hbrMask, hbrDst, hbrTmp;
623
624     static const DWORD ROP3Table[256] = 
625     {
626         0x00000042, 0x00010289,
627         0x00020C89, 0x000300AA,
628         0x00040C88, 0x000500A9,
629         0x00060865, 0x000702C5,
630         0x00080F08, 0x00090245,
631         0x000A0329, 0x000B0B2A,
632         0x000C0324, 0x000D0B25,
633         0x000E08A5, 0x000F0001,
634         0x00100C85, 0x001100A6,
635         0x00120868, 0x001302C8,
636         0x00140869, 0x001502C9,
637         0x00165CCA, 0x00171D54,
638         0x00180D59, 0x00191CC8,
639         0x001A06C5, 0x001B0768,
640         0x001C06CA, 0x001D0766,
641         0x001E01A5, 0x001F0385,
642         0x00200F09, 0x00210248,
643         0x00220326, 0x00230B24,
644         0x00240D55, 0x00251CC5,
645         0x002606C8, 0x00271868,
646         0x00280369, 0x002916CA,
647         0x002A0CC9, 0x002B1D58,
648         0x002C0784, 0x002D060A,
649         0x002E064A, 0x002F0E2A,
650         0x0030032A, 0x00310B28,
651         0x00320688, 0x00330008,
652         0x003406C4, 0x00351864,
653         0x003601A8, 0x00370388,
654         0x0038078A, 0x00390604,
655         0x003A0644, 0x003B0E24,
656         0x003C004A, 0x003D18A4,
657         0x003E1B24, 0x003F00EA,
658         0x00400F0A, 0x00410249,
659         0x00420D5D, 0x00431CC4,
660         0x00440328, 0x00450B29,
661         0x004606C6, 0x0047076A,
662         0x00480368, 0x004916C5,
663         0x004A0789, 0x004B0605,
664         0x004C0CC8, 0x004D1954,
665         0x004E0645, 0x004F0E25,
666         0x00500325, 0x00510B26,
667         0x005206C9, 0x00530764,
668         0x005408A9, 0x00550009,
669         0x005601A9, 0x00570389,
670         0x00580785, 0x00590609,
671         0x005A0049, 0x005B18A9,
672         0x005C0649, 0x005D0E29,
673         0x005E1B29, 0x005F00E9,
674         0x00600365, 0x006116C6,
675         0x00620786, 0x00630608,
676         0x00640788, 0x00650606,
677         0x00660046, 0x006718A8,
678         0x006858A6, 0x00690145,
679         0x006A01E9, 0x006B178A,
680         0x006C01E8, 0x006D1785,
681         0x006E1E28, 0x006F0C65,
682         0x00700CC5, 0x00711D5C,
683         0x00720648, 0x00730E28,
684         0x00740646, 0x00750E26,
685         0x00761B28, 0x007700E6,
686         0x007801E5, 0x00791786,
687         0x007A1E29, 0x007B0C68,
688         0x007C1E24, 0x007D0C69,
689         0x007E0955, 0x007F03C9,
690         0x008003E9, 0x00810975,
691         0x00820C49, 0x00831E04,
692         0x00840C48, 0x00851E05,
693         0x008617A6, 0x008701C5,
694         0x008800C6, 0x00891B08,
695         0x008A0E06, 0x008B0666,
696         0x008C0E08, 0x008D0668,
697         0x008E1D7C, 0x008F0CE5,
698         0x00900C45, 0x00911E08,
699         0x009217A9, 0x009301C4,
700         0x009417AA, 0x009501C9,
701         0x00960169, 0x0097588A,
702         0x00981888, 0x00990066,
703         0x009A0709, 0x009B07A8,
704         0x009C0704, 0x009D07A6,
705         0x009E16E6, 0x009F0345,
706         0x00A000C9, 0x00A11B05,
707         0x00A20E09, 0x00A30669,
708         0x00A41885, 0x00A50065,
709         0x00A60706, 0x00A707A5,
710         0x00A803A9, 0x00A90189,
711         0x00AA0029, 0x00AB0889,
712         0x00AC0744, 0x00AD06E9,
713         0x00AE0B06, 0x00AF0229,
714         0x00B00E05, 0x00B10665,
715         0x00B21974, 0x00B30CE8,
716         0x00B4070A, 0x00B507A9,
717         0x00B616E9, 0x00B70348,
718         0x00B8074A, 0x00B906E6,
719         0x00BA0B09, 0x00BB0226,
720         0x00BC1CE4, 0x00BD0D7D,
721         0x00BE0269, 0x00BF08C9,
722         0x00C000CA, 0x00C11B04,
723         0x00C21884, 0x00C3006A,
724         0x00C40E04, 0x00C50664,
725         0x00C60708, 0x00C707AA,
726         0x00C803A8, 0x00C90184,
727         0x00CA0749, 0x00CB06E4,
728         0x00CC0020, 0x00CD0888,
729         0x00CE0B08, 0x00CF0224,
730         0x00D00E0A, 0x00D1066A,
731         0x00D20705, 0x00D307A4,
732         0x00D41D78, 0x00D50CE9,
733         0x00D616EA, 0x00D70349,
734         0x00D80745, 0x00D906E8,
735         0x00DA1CE9, 0x00DB0D75,
736         0x00DC0B04, 0x00DD0228,
737         0x00DE0268, 0x00DF08C8,
738         0x00E003A5, 0x00E10185,
739         0x00E20746, 0x00E306EA,
740         0x00E40748, 0x00E506E5,
741         0x00E61CE8, 0x00E70D79,
742         0x00E81D74, 0x00E95CE6,
743         0x00EA02E9, 0x00EB0849,
744         0x00EC02E8, 0x00ED0848,
745         0x00EE0086, 0x00EF0A08,
746         0x00F00021, 0x00F10885,
747         0x00F20B05, 0x00F3022A,
748         0x00F40B0A, 0x00F50225,
749         0x00F60265, 0x00F708C5,
750         0x00F802E5, 0x00F90845,
751         0x00FA0089, 0x00FB0A09,
752         0x00FC008A, 0x00FD0A0A,
753         0x00FE02A9, 0x00FF0062,
754     };
755
756     if (!hbmMask)
757         return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
758
759     hbrMask = CreatePatternBrush(hbmMask);
760     hbrDst = SelectObject(hdcDest, GetStockObject(NULL_BRUSH));
761
762     /* make bitmap */
763     hDC1 = CreateCompatibleDC(hdcDest);
764     hBitmap1 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
765     hOldBitmap1 = SelectObject(hDC1, hBitmap1);
766
767     /* draw using bkgnd rop */
768     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
769     hbrTmp = SelectObject(hDC1, hbrDst);
770     BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop));
771     SelectObject(hDC1, hbrTmp);
772
773     /* make bitmap */
774     hDC2 = CreateCompatibleDC(hdcDest);
775     hBitmap2 = CreateCompatibleBitmap(hdcDest, nWidth, nHeight);
776     hOldBitmap2 = SelectObject(hDC2, hBitmap2);
777
778     /* draw using foregnd rop */
779     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
780     hbrTmp = SelectObject(hDC2, hbrDst);
781     BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
782
783     /* combine both using the mask as a pattern brush */
784     SelectObject(hDC2, hbrMask);
785     BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */ 
786     SelectObject(hDC2, hbrTmp);
787
788     /* blit to dst */
789     BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY);
790
791     /* restore all objects */
792     SelectObject(hdcDest, hbrDst);
793     SelectObject(hDC1, hOldBitmap1);
794     SelectObject(hDC2, hOldBitmap2);
795
796     /* delete all temp objects */
797     DeleteObject(hBitmap1);
798     DeleteObject(hBitmap2);
799     DeleteObject(hbrMask);
800
801     DeleteDC(hDC1);
802     DeleteDC(hDC2);
803
804     return TRUE;
805 }
806
807 /******************************************************************************
808  *           GdiTransparentBlt [GDI32.@]
809  */
810 BOOL WINAPI GdiTransparentBlt( HDC hdcDest, int xDest, int yDest, int widthDest, int heightDest,
811                             HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
812                             UINT crTransparent )
813 {
814     BOOL ret = FALSE;
815     HDC hdcWork;
816     HBITMAP bmpWork;
817     HGDIOBJ oldWork;
818     HDC hdcMask = NULL;
819     HBITMAP bmpMask = NULL;
820     HBITMAP oldMask = NULL;
821     COLORREF oldBackground;
822     COLORREF oldForeground;
823     int oldStretchMode;
824
825     if(widthDest < 0 || heightDest < 0 || widthSrc < 0 || heightSrc < 0) {
826         TRACE("Cannot mirror\n");
827         return FALSE;
828     }
829
830     oldBackground = SetBkColor(hdcDest, RGB(255,255,255));
831     oldForeground = SetTextColor(hdcDest, RGB(0,0,0));
832
833     /* Stretch bitmap */
834     oldStretchMode = GetStretchBltMode(hdcSrc);
835     if(oldStretchMode == BLACKONWHITE || oldStretchMode == WHITEONBLACK)
836         SetStretchBltMode(hdcSrc, COLORONCOLOR);
837     hdcWork = CreateCompatibleDC(hdcDest);
838     bmpWork = CreateCompatibleBitmap(hdcDest, widthDest, heightDest);
839     oldWork = SelectObject(hdcWork, bmpWork);
840     if(!StretchBlt(hdcWork, 0, 0, widthDest, heightDest, hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY)) {
841         TRACE("Failed to stretch\n");
842         goto error;
843     }
844     SetBkColor(hdcWork, crTransparent);
845
846     /* Create mask */
847     hdcMask = CreateCompatibleDC(hdcDest);
848     bmpMask = CreateCompatibleBitmap(hdcMask, widthDest, heightDest);
849     oldMask = SelectObject(hdcMask, bmpMask);
850     if(!BitBlt(hdcMask, 0, 0, widthDest, heightDest, hdcWork, 0, 0, SRCCOPY)) {
851         TRACE("Failed to create mask\n");
852         goto error;
853     }
854
855     /* Replace transparent color with black */
856     SetBkColor(hdcWork, RGB(0,0,0));
857     SetTextColor(hdcWork, RGB(255,255,255));
858     if(!BitBlt(hdcWork, 0, 0, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
859         TRACE("Failed to mask out background\n");
860         goto error;
861     }
862
863     /* Replace non-transparent area on destination with black */
864     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcMask, 0, 0, SRCAND)) {
865         TRACE("Failed to clear destination area\n");
866         goto error;
867     }
868
869     /* Draw the image */
870     if(!BitBlt(hdcDest, xDest, yDest, widthDest, heightDest, hdcWork, 0, 0, SRCPAINT)) {
871         TRACE("Failed to paint image\n");
872         goto error;
873     }
874
875     ret = TRUE;
876 error:
877     SetStretchBltMode(hdcSrc, oldStretchMode);
878     SetBkColor(hdcDest, oldBackground);
879     SetTextColor(hdcDest, oldForeground);
880     if(hdcWork) {
881         SelectObject(hdcWork, oldWork);
882         DeleteDC(hdcWork);
883     }
884     if(bmpWork) DeleteObject(bmpWork);
885     if(hdcMask) {
886         SelectObject(hdcMask, oldMask);
887         DeleteDC(hdcMask);
888     }
889     if(bmpMask) DeleteObject(bmpMask);
890     return ret;
891 }
892
893 /******************************************************************************
894  *           GdiAlphaBlend [GDI32.@]
895  */
896 BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
897                           HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
898                           BLENDFUNCTION blendFunction)
899 {
900     BOOL ret = FALSE;
901     DC *dcDst, *dcSrc;
902
903     dcSrc = get_dc_ptr( hdcSrc );
904     if (!dcSrc) return FALSE;
905
906     if ((dcDst = get_dc_ptr( hdcDst )))
907     {
908         struct bitblt_coords src, dst;
909         PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pAlphaBlend );
910         PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pAlphaBlend );
911
912         update_dc( dcSrc );
913         update_dc( dcDst );
914
915         src.log_x      = xSrc;
916         src.log_y      = ySrc;
917         src.log_width  = widthSrc;
918         src.log_height = heightSrc;
919         src.layout     = GetLayout( src_dev->hdc );
920         dst.log_x      = xDst;
921         dst.log_y      = yDst;
922         dst.log_width  = widthDst;
923         dst.log_height = heightDst;
924         dst.layout     = GetLayout( dst_dev->hdc );
925         ret = !get_vis_rectangles( dcDst, &dst, dcSrc, &src );
926
927         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",
928               hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
929               src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
930               hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
931               dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect),
932               blendFunction.BlendOp, blendFunction.BlendFlags,
933               blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
934
935         if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
936             (dcSrc->header.type == OBJ_MEMDC &&
937              (src.width > dcSrc->vis_rect.right - dcSrc->vis_rect.left - src.x ||
938               src.height > dcSrc->vis_rect.bottom - dcSrc->vis_rect.top - src.y)))
939         {
940             WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
941             SetLastError( ERROR_INVALID_PARAMETER );
942             ret = FALSE;
943         }
944         else if (dst.width < 0 || dst.height < 0)
945         {
946             WARN( "Invalid dst coords: (%d,%d), size %dx%d\n", dst.x, dst.y, dst.width, dst.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 }