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