2 * GDI bit-blit operations
4 * Copyright 1993, 1994 Alexandre Julliard
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.
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.
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
29 #include "gdi_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(bitblt
);
34 static inline BOOL
rop_uses_src( DWORD rop
)
36 return ((rop
>> 2) & 0x330000) != (rop
& 0x330000);
39 BOOL
intersect_vis_rectangles( struct bitblt_coords
*dst
, struct bitblt_coords
*src
)
43 /* intersect the rectangles */
45 if ((src
->width
== dst
->width
) && (src
->height
== dst
->height
)) /* no stretching */
47 offset_rect( &src
->visrect
, dst
->x
- src
->x
, dst
->y
- src
->y
);
48 if (!intersect_rect( &rect
, &src
->visrect
, &dst
->visrect
)) return FALSE
;
49 src
->visrect
= dst
->visrect
= rect
;
50 offset_rect( &src
->visrect
, src
->x
- dst
->x
, src
->y
- dst
->y
);
54 /* map source rectangle into destination coordinates */
57 -src
->x
- (src
->width
< 0 ? 1 : 0),
58 -src
->y
- (src
->height
< 0 ? 1 : 0));
59 rect
.left
= rect
.left
* dst
->width
/ src
->width
;
60 rect
.top
= rect
.top
* dst
->height
/ src
->height
;
61 rect
.right
= rect
.right
* dst
->width
/ src
->width
;
62 rect
.bottom
= rect
.bottom
* dst
->height
/ src
->height
;
65 /* when the source rectangle needs to flip and it doesn't fit in the source device
66 area, the destination area isn't flipped. So, adjust destination coordinates */
67 if (src
->width
< 0 && dst
->width
> 0 &&
68 (src
->x
+ src
->width
+ 1 < src
->visrect
.left
|| src
->x
> src
->visrect
.right
))
69 dst
->x
+= (dst
->width
- rect
.right
) - rect
.left
;
70 else if (src
->width
> 0 && dst
->width
< 0 &&
71 (src
->x
< src
->visrect
.left
|| src
->x
+ src
->width
> src
->visrect
.right
))
72 dst
->x
-= rect
.right
- (dst
->width
- rect
.left
);
74 if (src
->height
< 0 && dst
->height
> 0 &&
75 (src
->y
+ src
->height
+ 1 < src
->visrect
.top
|| src
->y
> src
->visrect
.bottom
))
76 dst
->y
+= (dst
->height
- rect
.bottom
) - rect
.top
;
77 else if (src
->height
> 0 && dst
->height
< 0 &&
78 (src
->y
< src
->visrect
.top
|| src
->y
+ src
->height
> src
->visrect
.bottom
))
79 dst
->y
-= rect
.bottom
- (dst
->height
- rect
.top
);
81 offset_rect( &rect
, dst
->x
, dst
->y
);
83 /* avoid rounding errors */
88 if (!intersect_rect( &dst
->visrect
, &rect
, &dst
->visrect
)) return FALSE
;
90 /* map destination rectangle back to source coordinates */
93 -dst
->x
- (dst
->width
< 0 ? 1 : 0),
94 -dst
->y
- (dst
->height
< 0 ? 1 : 0));
95 rect
.left
= src
->x
+ rect
.left
* src
->width
/ dst
->width
;
96 rect
.top
= src
->y
+ rect
.top
* src
->height
/ dst
->height
;
97 rect
.right
= src
->x
+ rect
.right
* src
->width
/ dst
->width
;
98 rect
.bottom
= src
->y
+ rect
.bottom
* src
->height
/ dst
->height
;
101 /* avoid rounding errors */
106 if (!intersect_rect( &src
->visrect
, &rect
, &src
->visrect
)) return FALSE
;
111 static BOOL
get_vis_rectangles( DC
*dc_dst
, struct bitblt_coords
*dst
,
112 DC
*dc_src
, struct bitblt_coords
*src
)
116 /* get the destination visible rectangle */
118 rect
.left
= dst
->log_x
;
119 rect
.top
= dst
->log_y
;
120 rect
.right
= dst
->log_x
+ dst
->log_width
;
121 rect
.bottom
= dst
->log_y
+ dst
->log_height
;
122 lp_to_dp( dc_dst
, (POINT
*)&rect
, 2 );
125 dst
->width
= rect
.right
- rect
.left
;
126 dst
->height
= rect
.bottom
- rect
.top
;
127 if (dst
->layout
& LAYOUT_RTL
&& dst
->layout
& LAYOUT_BITMAPORIENTATIONPRESERVED
)
129 dst
->x
+= dst
->width
;
130 dst
->width
= -dst
->width
;
132 get_bounding_rect( &rect
, dst
->x
, dst
->y
, dst
->width
, dst
->height
);
134 clip_visrect( dc_dst
, &dst
->visrect
, &rect
);
136 /* get the source visible rectangle */
138 if (!src
) return !is_rect_empty( &dst
->visrect
);
140 rect
.left
= src
->log_x
;
141 rect
.top
= src
->log_y
;
142 rect
.right
= src
->log_x
+ src
->log_width
;
143 rect
.bottom
= src
->log_y
+ src
->log_height
;
144 lp_to_dp( dc_src
, (POINT
*)&rect
, 2 );
147 src
->width
= rect
.right
- rect
.left
;
148 src
->height
= rect
.bottom
- rect
.top
;
149 if (src
->layout
& LAYOUT_RTL
&& src
->layout
& LAYOUT_BITMAPORIENTATIONPRESERVED
)
151 src
->x
+= src
->width
;
152 src
->width
= -src
->width
;
154 get_bounding_rect( &rect
, src
->x
, src
->y
, src
->width
, src
->height
);
156 if (!clip_device_rect( dc_src
, &src
->visrect
, &rect
)) return FALSE
;
157 if (is_rect_empty( &dst
->visrect
)) return FALSE
;
159 return intersect_vis_rectangles( dst
, src
);
162 void CDECL
free_heap_bits( struct gdi_image_bits
*bits
)
164 HeapFree( GetProcessHeap(), 0, bits
->ptr
);
167 DWORD
convert_bits( const BITMAPINFO
*src_info
, struct bitblt_coords
*src
,
168 BITMAPINFO
*dst_info
, struct gdi_image_bits
*bits
)
172 BOOL top_down
= dst_info
->bmiHeader
.biHeight
< 0;
174 dst_info
->bmiHeader
.biWidth
= src
->visrect
.right
- src
->visrect
.left
;
175 dst_info
->bmiHeader
.biHeight
= src
->visrect
.bottom
- src
->visrect
.top
;
176 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
177 if (top_down
) dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
179 if (!(ptr
= HeapAlloc( GetProcessHeap(), 0, dst_info
->bmiHeader
.biSizeImage
)))
180 return ERROR_OUTOFMEMORY
;
182 err
= convert_bitmapinfo( src_info
, bits
->ptr
, src
, dst_info
, ptr
);
183 if (bits
->free
) bits
->free( bits
);
185 bits
->is_copy
= TRUE
;
186 bits
->free
= free_heap_bits
;
190 DWORD
stretch_bits( const BITMAPINFO
*src_info
, struct bitblt_coords
*src
,
191 BITMAPINFO
*dst_info
, struct bitblt_coords
*dst
,
192 struct gdi_image_bits
*bits
, int mode
)
197 dst_info
->bmiHeader
.biWidth
= dst
->visrect
.right
- dst
->visrect
.left
;
198 dst_info
->bmiHeader
.biHeight
= dst
->visrect
.bottom
- dst
->visrect
.top
;
199 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
201 if (src_info
->bmiHeader
.biHeight
< 0) dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
202 if (!(ptr
= HeapAlloc( GetProcessHeap(), 0, dst_info
->bmiHeader
.biSizeImage
)))
203 return ERROR_OUTOFMEMORY
;
205 err
= stretch_bitmapinfo( src_info
, bits
->ptr
, src
, dst_info
, ptr
, dst
, mode
);
206 if (bits
->free
) bits
->free( bits
);
208 bits
->is_copy
= TRUE
;
209 bits
->free
= free_heap_bits
;
213 static DWORD
blend_bits( const BITMAPINFO
*src_info
, const struct gdi_image_bits
*src_bits
,
214 struct bitblt_coords
*src
, BITMAPINFO
*dst_info
,
215 struct gdi_image_bits
*dst_bits
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
217 if (!dst_bits
->is_copy
)
219 int size
= dst_info
->bmiHeader
.biSizeImage
;
220 void *ptr
= HeapAlloc( GetProcessHeap(), 0, size
);
221 if (!ptr
) return ERROR_OUTOFMEMORY
;
222 memcpy( ptr
, dst_bits
->ptr
, size
);
223 if (dst_bits
->free
) dst_bits
->free( dst_bits
);
225 dst_bits
->is_copy
= TRUE
;
226 dst_bits
->free
= free_heap_bits
;
228 return blend_bitmapinfo( src_info
, src_bits
->ptr
, src
, dst_info
, dst_bits
->ptr
, dst
, blend
);
231 static RGBQUAD
get_dc_rgb_color( DC
*dc
, int color_table_size
, COLORREF color
)
233 RGBQUAD ret
= { 0, 0, 0, 0 };
235 if (color
& (1 << 24)) /* PALETTEINDEX */
239 if (!GetPaletteEntries( dc
->hPalette
, LOWORD(color
), 1, &pal
))
240 GetPaletteEntries( dc
->hPalette
, 0, 1, &pal
);
241 ret
.rgbRed
= pal
.peRed
;
242 ret
.rgbGreen
= pal
.peGreen
;
243 ret
.rgbBlue
= pal
.peBlue
;
246 if (color
>> 16 == 0x10ff) /* DIBINDEX */
248 if (color_table_size
)
250 if (LOWORD(color
) >= color_table_size
) color
= 0x10ff0000; /* fallback to index 0 */
251 *(DWORD
*)&ret
= color
;
255 ret
.rgbRed
= GetRValue( color
);
256 ret
.rgbGreen
= GetGValue( color
);
257 ret
.rgbBlue
= GetBValue( color
);
261 /* helper to retrieve either both colors or only the background color for monochrome blits */
262 void get_mono_dc_colors( DC
*dc
, int color_table_size
, BITMAPINFO
*info
, int count
)
264 info
->bmiColors
[count
- 1] = get_dc_rgb_color( dc
, color_table_size
, dc
->backgroundColor
);
265 if (count
> 1) info
->bmiColors
[0] = get_dc_rgb_color( dc
, color_table_size
, dc
->textColor
);
266 info
->bmiHeader
.biClrUsed
= count
;
269 /***********************************************************************
270 * null driver fallback implementations
273 BOOL CDECL
nulldrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
274 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
276 DC
*dc_src
= get_physdev_dc( src_dev
), *dc_dst
= get_nulldrv_dc( dst_dev
);
277 char src_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
278 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
279 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_buffer
;
280 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
282 struct gdi_image_bits bits
;
284 src_dev
= GET_DC_PHYSDEV( dc_src
, pGetImage
);
285 if (src_dev
->funcs
->pGetImage( src_dev
, src_info
, &bits
, src
))
288 dst_dev
= GET_DC_PHYSDEV( dc_dst
, pPutImage
);
289 copy_bitmapinfo( dst_info
, src_info
);
290 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, dst_info
, &bits
, src
, dst
, rop
);
291 if (err
== ERROR_BAD_FORMAT
)
293 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
295 /* 1-bpp source without a color table uses the destination DC colors */
296 if (src_info
->bmiHeader
.biBitCount
== 1 && !src_info
->bmiHeader
.biClrUsed
)
297 get_mono_dc_colors( dc_dst
, dst_info
->bmiHeader
.biClrUsed
, src_info
, 2 );
299 /* 1-bpp destination without a color table requires a fake 1-entry table
300 * that contains only the background color */
301 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
302 get_mono_dc_colors( dc_src
, src_info
->bmiHeader
.biClrUsed
, dst_info
, 1 );
304 if (!(err
= convert_bits( src_info
, src
, dst_info
, &bits
)))
306 /* get rid of the fake destination table */
307 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
308 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, dst_info
, &bits
, src
, dst
, rop
);
312 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
&&
313 ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)))
315 copy_bitmapinfo( src_info
, dst_info
);
316 err
= stretch_bits( src_info
, src
, dst_info
, dst
, &bits
, dc_dst
->stretchBltMode
);
317 if (!err
) err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, dst_info
, &bits
, src
, dst
, rop
);
320 if (bits
.free
) bits
.free( &bits
);
325 BOOL CDECL
nulldrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
326 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION func
)
328 DC
*dc_src
= get_physdev_dc( src_dev
), *dc_dst
= get_nulldrv_dc( dst_dev
);
329 char src_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
330 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
331 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_buffer
;
332 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
334 struct gdi_image_bits bits
;
336 src_dev
= GET_DC_PHYSDEV( dc_src
, pGetImage
);
337 err
= src_dev
->funcs
->pGetImage( src_dev
, src_info
, &bits
, src
);
340 dst_dev
= GET_DC_PHYSDEV( dc_dst
, pBlendImage
);
341 copy_bitmapinfo( dst_info
, src_info
);
342 err
= dst_dev
->funcs
->pBlendImage( dst_dev
, dst_info
, &bits
, src
, dst
, func
);
343 if (err
== ERROR_BAD_FORMAT
)
345 err
= convert_bits( src_info
, src
, dst_info
, &bits
);
346 if (!err
) err
= dst_dev
->funcs
->pBlendImage( dst_dev
, dst_info
, &bits
, src
, dst
, func
);
349 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
&&
350 ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)))
352 copy_bitmapinfo( src_info
, dst_info
);
353 err
= stretch_bits( src_info
, src
, dst_info
, dst
, &bits
, COLORONCOLOR
);
354 if (!err
) err
= dst_dev
->funcs
->pBlendImage( dst_dev
, dst_info
, &bits
, src
, dst
, func
);
357 if (bits
.free
) bits
.free( &bits
);
359 if (err
) SetLastError( err
);
364 DWORD CDECL
nulldrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
365 struct bitblt_coords
*src
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
367 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
368 BITMAPINFO
*dst_info
= (BITMAPINFO
*)buffer
;
369 struct gdi_image_bits dst_bits
;
370 struct bitblt_coords orig_dst
;
371 DWORD
*masks
= (DWORD
*)info
->bmiColors
;
372 DC
*dc
= get_nulldrv_dc( dev
);
375 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
376 if (info
->bmiHeader
.biBitCount
!= 32) goto update_format
;
377 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
379 if (blend
.AlphaFormat
& AC_SRC_ALPHA
) return ERROR_INVALID_PARAMETER
;
380 if (masks
[0] != 0xff0000 || masks
[1] != 0x00ff00 || masks
[2] != 0x0000ff)
384 if (!bits
) return ERROR_SUCCESS
;
385 if ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)) return ERROR_TRANSFORM_NOT_SUPPORTED
;
387 dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
389 err
= dev
->funcs
->pGetImage( dev
, dst_info
, &dst_bits
, dst
);
392 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
393 err
= blend_bits( info
, bits
, src
, dst_info
, &dst_bits
, dst
, blend
);
394 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, dst_info
, &dst_bits
, dst
, &orig_dst
, SRCCOPY
);
396 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
400 if (blend
.AlphaFormat
& AC_SRC_ALPHA
) /* source alpha requires A8R8G8B8 format */
401 return ERROR_INVALID_PARAMETER
;
403 info
->bmiHeader
.biPlanes
= 1;
404 info
->bmiHeader
.biBitCount
= 32;
405 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
406 info
->bmiHeader
.biClrUsed
= 0;
410 return ERROR_BAD_FORMAT
;
413 BOOL CDECL
nulldrv_GradientFill( PHYSDEV dev
, TRIVERTEX
*vert_array
, ULONG nvert
,
414 void * grad_array
, ULONG ngrad
, ULONG mode
)
416 DC
*dc
= get_nulldrv_dc( dev
);
417 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
418 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
419 struct bitblt_coords src
, dst
;
420 struct gdi_image_bits bits
;
427 if (!(pts
= HeapAlloc( GetProcessHeap(), 0, nvert
* sizeof(*pts
) ))) return FALSE
;
428 for (i
= 0; i
< nvert
; i
++)
430 pts
[i
].x
= vert_array
[i
].x
;
431 pts
[i
].y
= vert_array
[i
].y
;
433 lp_to_dp( dc
, pts
, nvert
);
435 /* compute bounding rect of all the rectangles/triangles */
436 reset_bounds( &dst
.visrect
);
437 for (i
= 0; i
< ngrad
* (mode
== GRADIENT_FILL_TRIANGLE
? 3 : 2); i
++)
439 ULONG v
= ((ULONG
*)grad_array
)[i
];
440 dst
.visrect
.left
= min( dst
.visrect
.left
, pts
[v
].x
);
441 dst
.visrect
.top
= min( dst
.visrect
.top
, pts
[v
].y
);
442 dst
.visrect
.right
= max( dst
.visrect
.right
, pts
[v
].x
);
443 dst
.visrect
.bottom
= max( dst
.visrect
.bottom
, pts
[v
].y
);
446 dst
.x
= dst
.visrect
.left
;
447 dst
.y
= dst
.visrect
.top
;
448 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
449 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
450 if (!clip_visrect( dc
, &dst
.visrect
, &dst
.visrect
)) goto done
;
452 /* query the bitmap format */
453 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
454 info
->bmiHeader
.biPlanes
= 1;
455 info
->bmiHeader
.biBitCount
= 0;
456 info
->bmiHeader
.biCompression
= BI_RGB
;
457 info
->bmiHeader
.biXPelsPerMeter
= 0;
458 info
->bmiHeader
.biYPelsPerMeter
= 0;
459 info
->bmiHeader
.biClrUsed
= 0;
460 info
->bmiHeader
.biClrImportant
= 0;
461 info
->bmiHeader
.biWidth
= dst
.visrect
.right
- dst
.visrect
.left
;
462 info
->bmiHeader
.biHeight
= dst
.visrect
.bottom
- dst
.visrect
.top
;
463 info
->bmiHeader
.biSizeImage
= 0;
464 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
465 err
= dev
->funcs
->pPutImage( dev
, 0, info
, NULL
, NULL
, NULL
, 0 );
466 if (err
&& err
!= ERROR_BAD_FORMAT
) goto done
;
468 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
469 if (!(bits
.ptr
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->bmiHeader
.biSizeImage
)))
472 bits
.free
= free_heap_bits
;
474 /* make src and points relative to the bitmap */
476 src
.x
-= dst
.visrect
.left
;
477 src
.y
-= dst
.visrect
.top
;
478 offset_rect( &src
.visrect
, -dst
.visrect
.left
, -dst
.visrect
.top
);
479 for (i
= 0; i
< nvert
; i
++)
481 pts
[i
].x
-= dst
.visrect
.left
;
482 pts
[i
].y
-= dst
.visrect
.top
;
485 rgn
= CreateRectRgn( 0, 0, 0, 0 );
486 gradient_bitmapinfo( info
, bits
.ptr
, vert_array
, nvert
, grad_array
, ngrad
, mode
, pts
, rgn
);
487 OffsetRgn( rgn
, dst
.visrect
.left
, dst
.visrect
.top
);
488 ret
= !dev
->funcs
->pPutImage( dev
, rgn
, info
, &bits
, &src
, &dst
, SRCCOPY
);
490 if (bits
.free
) bits
.free( &bits
);
494 HeapFree( GetProcessHeap(), 0, pts
);
498 COLORREF CDECL
nulldrv_GetPixel( PHYSDEV dev
, INT x
, INT y
)
500 DC
*dc
= get_nulldrv_dc( dev
);
501 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
502 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
503 struct bitblt_coords src
;
504 struct gdi_image_bits bits
;
507 src
.visrect
.left
= x
;
509 lp_to_dp( dc
, (POINT
*)&src
.visrect
, 1 );
510 src
.visrect
.right
= src
.visrect
.left
+ 1;
511 src
.visrect
.bottom
= src
.visrect
.top
+ 1;
512 src
.x
= src
.visrect
.left
;
513 src
.y
= src
.visrect
.top
;
514 src
.width
= src
.height
= 1;
516 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return CLR_INVALID
;
518 dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
519 if (dev
->funcs
->pGetImage( dev
, info
, &bits
, &src
)) return CLR_INVALID
;
521 ret
= get_pixel_bitmapinfo( info
, bits
.ptr
, &src
);
522 if (bits
.free
) bits
.free( &bits
);
527 /***********************************************************************
530 BOOL WINAPI
PatBlt( HDC hdc
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
535 if (rop_uses_src( rop
)) return FALSE
;
536 if ((dc
= get_dc_ptr( hdc
)))
538 struct bitblt_coords dst
;
544 dst
.log_width
= width
;
545 dst
.log_height
= height
;
546 dst
.layout
= dc
->layout
;
547 if (rop
& NOMIRRORBITMAP
)
549 dst
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
550 rop
&= ~NOMIRRORBITMAP
;
552 ret
= !get_vis_rectangles( dc
, &dst
, NULL
, NULL
);
554 TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s rop=%06x\n",
555 hdc
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
556 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
), rop
);
560 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pPatBlt
);
561 ret
= physdev
->funcs
->pPatBlt( physdev
, &dst
, rop
);
563 release_dc_ptr( dc
);
569 /***********************************************************************
572 BOOL WINAPI DECLSPEC_HOTPATCH
BitBlt( HDC hdcDst
, INT xDst
, INT yDst
, INT width
,
573 INT height
, HDC hdcSrc
, INT xSrc
, INT ySrc
, DWORD rop
)
575 if (!rop_uses_src( rop
)) return PatBlt( hdcDst
, xDst
, yDst
, width
, height
, rop
);
576 else return StretchBlt( hdcDst
, xDst
, yDst
, width
, height
,
577 hdcSrc
, xSrc
, ySrc
, width
, height
, rop
);
581 /***********************************************************************
582 * StretchBlt (GDI32.@)
584 BOOL WINAPI
StretchBlt( HDC hdcDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
585 HDC hdcSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, DWORD rop
)
590 if (!rop_uses_src( rop
)) return PatBlt( hdcDst
, xDst
, yDst
, widthDst
, heightDst
, rop
);
592 if (!(dcDst
= get_dc_ptr( hdcDst
))) return FALSE
;
594 if ((dcSrc
= get_dc_ptr( hdcSrc
)))
596 struct bitblt_coords src
, dst
;
603 src
.log_width
= widthSrc
;
604 src
.log_height
= heightSrc
;
605 src
.layout
= dcSrc
->layout
;
608 dst
.log_width
= widthDst
;
609 dst
.log_height
= heightDst
;
610 dst
.layout
= dcDst
->layout
;
611 if (rop
& NOMIRRORBITMAP
)
613 src
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
614 dst
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
615 rop
&= ~NOMIRRORBITMAP
;
617 ret
= !get_vis_rectangles( dcDst
, &dst
, dcSrc
, &src
);
619 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",
620 hdcSrc
, src
.log_x
, src
.log_y
, src
.log_width
, src
.log_height
,
621 src
.x
, src
.y
, src
.width
, src
.height
, wine_dbgstr_rect(&src
.visrect
),
622 hdcDst
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
623 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
), rop
);
627 PHYSDEV src_dev
= GET_DC_PHYSDEV( dcSrc
, pStretchBlt
);
628 PHYSDEV dst_dev
= GET_DC_PHYSDEV( dcDst
, pStretchBlt
);
629 ret
= dst_dev
->funcs
->pStretchBlt( dst_dev
, &dst
, src_dev
, &src
, rop
);
631 release_dc_ptr( dcSrc
);
633 release_dc_ptr( dcDst
);
637 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
638 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
640 /***********************************************************************
643 BOOL WINAPI
MaskBlt(HDC hdcDest
, INT nXDest
, INT nYDest
,
644 INT nWidth
, INT nHeight
, HDC hdcSrc
,
645 INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
646 INT xMask
, INT yMask
, DWORD dwRop
)
648 HBITMAP hBitmap1
, hOldBitmap1
, hBitmap2
, hOldBitmap2
;
650 HBRUSH hbrMask
, hbrDst
, hbrTmp
;
652 static const DWORD ROP3Table
[256] =
654 0x00000042, 0x00010289,
655 0x00020C89, 0x000300AA,
656 0x00040C88, 0x000500A9,
657 0x00060865, 0x000702C5,
658 0x00080F08, 0x00090245,
659 0x000A0329, 0x000B0B2A,
660 0x000C0324, 0x000D0B25,
661 0x000E08A5, 0x000F0001,
662 0x00100C85, 0x001100A6,
663 0x00120868, 0x001302C8,
664 0x00140869, 0x001502C9,
665 0x00165CCA, 0x00171D54,
666 0x00180D59, 0x00191CC8,
667 0x001A06C5, 0x001B0768,
668 0x001C06CA, 0x001D0766,
669 0x001E01A5, 0x001F0385,
670 0x00200F09, 0x00210248,
671 0x00220326, 0x00230B24,
672 0x00240D55, 0x00251CC5,
673 0x002606C8, 0x00271868,
674 0x00280369, 0x002916CA,
675 0x002A0CC9, 0x002B1D58,
676 0x002C0784, 0x002D060A,
677 0x002E064A, 0x002F0E2A,
678 0x0030032A, 0x00310B28,
679 0x00320688, 0x00330008,
680 0x003406C4, 0x00351864,
681 0x003601A8, 0x00370388,
682 0x0038078A, 0x00390604,
683 0x003A0644, 0x003B0E24,
684 0x003C004A, 0x003D18A4,
685 0x003E1B24, 0x003F00EA,
686 0x00400F0A, 0x00410249,
687 0x00420D5D, 0x00431CC4,
688 0x00440328, 0x00450B29,
689 0x004606C6, 0x0047076A,
690 0x00480368, 0x004916C5,
691 0x004A0789, 0x004B0605,
692 0x004C0CC8, 0x004D1954,
693 0x004E0645, 0x004F0E25,
694 0x00500325, 0x00510B26,
695 0x005206C9, 0x00530764,
696 0x005408A9, 0x00550009,
697 0x005601A9, 0x00570389,
698 0x00580785, 0x00590609,
699 0x005A0049, 0x005B18A9,
700 0x005C0649, 0x005D0E29,
701 0x005E1B29, 0x005F00E9,
702 0x00600365, 0x006116C6,
703 0x00620786, 0x00630608,
704 0x00640788, 0x00650606,
705 0x00660046, 0x006718A8,
706 0x006858A6, 0x00690145,
707 0x006A01E9, 0x006B178A,
708 0x006C01E8, 0x006D1785,
709 0x006E1E28, 0x006F0C65,
710 0x00700CC5, 0x00711D5C,
711 0x00720648, 0x00730E28,
712 0x00740646, 0x00750E26,
713 0x00761B28, 0x007700E6,
714 0x007801E5, 0x00791786,
715 0x007A1E29, 0x007B0C68,
716 0x007C1E24, 0x007D0C69,
717 0x007E0955, 0x007F03C9,
718 0x008003E9, 0x00810975,
719 0x00820C49, 0x00831E04,
720 0x00840C48, 0x00851E05,
721 0x008617A6, 0x008701C5,
722 0x008800C6, 0x00891B08,
723 0x008A0E06, 0x008B0666,
724 0x008C0E08, 0x008D0668,
725 0x008E1D7C, 0x008F0CE5,
726 0x00900C45, 0x00911E08,
727 0x009217A9, 0x009301C4,
728 0x009417AA, 0x009501C9,
729 0x00960169, 0x0097588A,
730 0x00981888, 0x00990066,
731 0x009A0709, 0x009B07A8,
732 0x009C0704, 0x009D07A6,
733 0x009E16E6, 0x009F0345,
734 0x00A000C9, 0x00A11B05,
735 0x00A20E09, 0x00A30669,
736 0x00A41885, 0x00A50065,
737 0x00A60706, 0x00A707A5,
738 0x00A803A9, 0x00A90189,
739 0x00AA0029, 0x00AB0889,
740 0x00AC0744, 0x00AD06E9,
741 0x00AE0B06, 0x00AF0229,
742 0x00B00E05, 0x00B10665,
743 0x00B21974, 0x00B30CE8,
744 0x00B4070A, 0x00B507A9,
745 0x00B616E9, 0x00B70348,
746 0x00B8074A, 0x00B906E6,
747 0x00BA0B09, 0x00BB0226,
748 0x00BC1CE4, 0x00BD0D7D,
749 0x00BE0269, 0x00BF08C9,
750 0x00C000CA, 0x00C11B04,
751 0x00C21884, 0x00C3006A,
752 0x00C40E04, 0x00C50664,
753 0x00C60708, 0x00C707AA,
754 0x00C803A8, 0x00C90184,
755 0x00CA0749, 0x00CB06E4,
756 0x00CC0020, 0x00CD0888,
757 0x00CE0B08, 0x00CF0224,
758 0x00D00E0A, 0x00D1066A,
759 0x00D20705, 0x00D307A4,
760 0x00D41D78, 0x00D50CE9,
761 0x00D616EA, 0x00D70349,
762 0x00D80745, 0x00D906E8,
763 0x00DA1CE9, 0x00DB0D75,
764 0x00DC0B04, 0x00DD0228,
765 0x00DE0268, 0x00DF08C8,
766 0x00E003A5, 0x00E10185,
767 0x00E20746, 0x00E306EA,
768 0x00E40748, 0x00E506E5,
769 0x00E61CE8, 0x00E70D79,
770 0x00E81D74, 0x00E95CE6,
771 0x00EA02E9, 0x00EB0849,
772 0x00EC02E8, 0x00ED0848,
773 0x00EE0086, 0x00EF0A08,
774 0x00F00021, 0x00F10885,
775 0x00F20B05, 0x00F3022A,
776 0x00F40B0A, 0x00F50225,
777 0x00F60265, 0x00F708C5,
778 0x00F802E5, 0x00F90845,
779 0x00FA0089, 0x00FB0A09,
780 0x00FC008A, 0x00FD0A0A,
781 0x00FE02A9, 0x00FF0062,
785 return BitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
787 hbrMask
= CreatePatternBrush(hbmMask
);
788 hbrDst
= NtGdiSelectBrush(hdcDest
, GetStockObject(NULL_BRUSH
));
791 hDC1
= CreateCompatibleDC(hdcDest
);
792 hBitmap1
= CreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
793 hOldBitmap1
= NtGdiSelectBitmap(hDC1
, hBitmap1
);
795 /* draw using bkgnd rop */
796 BitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
797 hbrTmp
= NtGdiSelectBrush(hDC1
, hbrDst
);
798 BitBlt(hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, BKGND_ROP3(dwRop
));
799 NtGdiSelectBrush(hDC1
, hbrTmp
);
802 hDC2
= CreateCompatibleDC(hdcDest
);
803 hBitmap2
= CreateCompatibleBitmap(hdcDest
, nWidth
, nHeight
);
804 hOldBitmap2
= NtGdiSelectBitmap(hDC2
, hBitmap2
);
806 /* draw using foregnd rop */
807 BitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
);
808 hbrTmp
= NtGdiSelectBrush(hDC2
, hbrDst
);
809 BitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
));
811 /* combine both using the mask as a pattern brush */
812 NtGdiSelectBrush(hDC2
, hbrMask
);
813 SetBrushOrgEx(hDC2
, -xMask
, -yMask
, NULL
);
814 BitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDC1
, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */
815 NtGdiSelectBrush(hDC2
, hbrTmp
);
818 BitBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC2
, 0, 0, SRCCOPY
);
820 /* restore all objects */
821 NtGdiSelectBrush(hdcDest
, hbrDst
);
822 NtGdiSelectBitmap(hDC1
, hOldBitmap1
);
823 NtGdiSelectBitmap(hDC2
, hOldBitmap2
);
825 /* delete all temp objects */
826 DeleteObject(hBitmap1
);
827 DeleteObject(hBitmap2
);
828 DeleteObject(hbrMask
);
836 /******************************************************************************
837 * GdiTransparentBlt [GDI32.@]
839 BOOL WINAPI
GdiTransparentBlt( HDC hdcDest
, int xDest
, int yDest
, int widthDest
, int heightDest
,
840 HDC hdcSrc
, int xSrc
, int ySrc
, int widthSrc
, int heightSrc
,
848 HBITMAP bmpMask
= NULL
;
849 HBITMAP oldMask
= NULL
;
850 COLORREF oldBackground
;
851 COLORREF oldForeground
;
855 if(widthDest
< 0 || heightDest
< 0 || widthSrc
< 0 || heightSrc
< 0) {
856 TRACE("Cannot mirror\n");
860 oldBackground
= SetBkColor(hdcDest
, RGB(255,255,255));
861 oldForeground
= SetTextColor(hdcDest
, RGB(0,0,0));
864 oldStretchMode
= GetStretchBltMode(hdcSrc
);
865 if(oldStretchMode
== BLACKONWHITE
|| oldStretchMode
== WHITEONBLACK
)
866 SetStretchBltMode(hdcSrc
, COLORONCOLOR
);
867 hdcWork
= CreateCompatibleDC(hdcDest
);
868 if ((GetObjectType( hdcDest
) != OBJ_MEMDC
||
869 GetObjectW( GetCurrentObject( hdcDest
, OBJ_BITMAP
), sizeof(dib
), &dib
) == sizeof(BITMAP
)) &&
870 GetDeviceCaps( hdcDest
, BITSPIXEL
) == 32)
872 /* screen DCs or DDBs are not supposed to have an alpha channel, so use a 24-bpp bitmap as copy */
874 info
.bmiHeader
.biSize
= sizeof(info
.bmiHeader
);
875 info
.bmiHeader
.biWidth
= widthDest
;
876 info
.bmiHeader
.biHeight
= heightDest
;
877 info
.bmiHeader
.biPlanes
= 1;
878 info
.bmiHeader
.biBitCount
= 24;
879 info
.bmiHeader
.biCompression
= BI_RGB
;
880 bmpWork
= CreateDIBSection( 0, &info
, DIB_RGB_COLORS
, NULL
, NULL
, 0 );
882 else bmpWork
= CreateCompatibleBitmap(hdcDest
, widthDest
, heightDest
);
883 oldWork
= NtGdiSelectBitmap(hdcWork
, bmpWork
);
884 if(!StretchBlt(hdcWork
, 0, 0, widthDest
, heightDest
, hdcSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, SRCCOPY
)) {
885 TRACE("Failed to stretch\n");
888 SetBkColor(hdcWork
, crTransparent
);
891 hdcMask
= CreateCompatibleDC(hdcDest
);
892 bmpMask
= CreateCompatibleBitmap(hdcMask
, widthDest
, heightDest
);
893 oldMask
= NtGdiSelectBitmap(hdcMask
, bmpMask
);
894 if(!BitBlt(hdcMask
, 0, 0, widthDest
, heightDest
, hdcWork
, 0, 0, SRCCOPY
)) {
895 TRACE("Failed to create mask\n");
899 /* Replace transparent color with black */
900 SetBkColor(hdcWork
, RGB(0,0,0));
901 SetTextColor(hdcWork
, RGB(255,255,255));
902 if(!BitBlt(hdcWork
, 0, 0, widthDest
, heightDest
, hdcMask
, 0, 0, SRCAND
)) {
903 TRACE("Failed to mask out background\n");
907 /* Replace non-transparent area on destination with black */
908 if(!BitBlt(hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcMask
, 0, 0, SRCAND
)) {
909 TRACE("Failed to clear destination area\n");
914 if(!BitBlt(hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcWork
, 0, 0, SRCPAINT
)) {
915 TRACE("Failed to paint image\n");
921 SetStretchBltMode(hdcSrc
, oldStretchMode
);
922 SetBkColor(hdcDest
, oldBackground
);
923 SetTextColor(hdcDest
, oldForeground
);
925 NtGdiSelectBitmap(hdcWork
, oldWork
);
928 if(bmpWork
) DeleteObject(bmpWork
);
930 NtGdiSelectBitmap(hdcMask
, oldMask
);
933 if(bmpMask
) DeleteObject(bmpMask
);
937 /******************************************************************************
938 * GdiAlphaBlend [GDI32.@]
940 BOOL WINAPI
GdiAlphaBlend(HDC hdcDst
, int xDst
, int yDst
, int widthDst
, int heightDst
,
941 HDC hdcSrc
, int xSrc
, int ySrc
, int widthSrc
, int heightSrc
,
942 BLENDFUNCTION blendFunction
)
947 dcSrc
= get_dc_ptr( hdcSrc
);
948 if (!dcSrc
) return FALSE
;
950 if ((dcDst
= get_dc_ptr( hdcDst
)))
952 struct bitblt_coords src
, dst
;
959 src
.log_width
= widthSrc
;
960 src
.log_height
= heightSrc
;
961 src
.layout
= dcSrc
->layout
;
964 dst
.log_width
= widthDst
;
965 dst
.log_height
= heightDst
;
966 dst
.layout
= dcDst
->layout
;
967 ret
= !get_vis_rectangles( dcDst
, &dst
, dcSrc
, &src
);
969 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",
970 hdcSrc
, src
.log_x
, src
.log_y
, src
.log_width
, src
.log_height
,
971 src
.x
, src
.y
, src
.width
, src
.height
, wine_dbgstr_rect(&src
.visrect
),
972 hdcDst
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
973 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
),
974 blendFunction
.BlendOp
, blendFunction
.BlendFlags
,
975 blendFunction
.SourceConstantAlpha
, blendFunction
.AlphaFormat
);
977 if (src
.x
< 0 || src
.y
< 0 || src
.width
< 0 || src
.height
< 0 ||
978 src
.log_width
< 0 || src
.log_height
< 0 ||
979 (!is_rect_empty( &dcSrc
->device_rect
) &&
980 (src
.width
> dcSrc
->device_rect
.right
- dcSrc
->vis_rect
.left
- src
.x
||
981 src
.height
> dcSrc
->device_rect
.bottom
- dcSrc
->vis_rect
.top
- src
.y
)))
983 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src
.x
, src
.y
, src
.width
, src
.height
);
984 SetLastError( ERROR_INVALID_PARAMETER
);
987 else if (dst
.log_width
< 0 || dst
.log_height
< 0)
989 WARN( "Invalid dst coords: (%d,%d), size %dx%d\n",
990 dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
);
991 SetLastError( ERROR_INVALID_PARAMETER
);
994 else if (dcSrc
== dcDst
&& src
.x
+ src
.width
> dst
.x
&& src
.x
< dst
.x
+ dst
.width
&&
995 src
.y
+ src
.height
> dst
.y
&& src
.y
< dst
.y
+ dst
.height
)
997 WARN( "Overlapping coords: (%d,%d), %dx%d and (%d,%d), %dx%d\n",
998 src
.x
, src
.y
, src
.width
, src
.height
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
999 SetLastError( ERROR_INVALID_PARAMETER
);
1004 PHYSDEV src_dev
= GET_DC_PHYSDEV( dcSrc
, pAlphaBlend
);
1005 PHYSDEV dst_dev
= GET_DC_PHYSDEV( dcDst
, pAlphaBlend
);
1006 ret
= dst_dev
->funcs
->pAlphaBlend( dst_dev
, &dst
, src_dev
, &src
, blendFunction
);
1008 release_dc_ptr( dcDst
);
1010 release_dc_ptr( dcSrc
);
1014 /*********************************************************************
1018 BOOL WINAPI
PlgBlt( HDC hdcDest
, const POINT
*lpPoint
,
1019 HDC hdcSrc
, INT nXSrc
, INT nYSrc
, INT nWidth
,
1020 INT nHeight
, HBITMAP hbmMask
, INT xMask
, INT yMask
)
1023 /* parallelogram coords */
1032 /* save actual mode, set GM_ADVANCED */
1033 oldgMode
= SetGraphicsMode(hdcDest
,GM_ADVANCED
);
1037 memcpy(plg
,lpPoint
,sizeof(POINT
)*3);
1040 rect
[1].x
= nXSrc
+ nWidth
;
1043 rect
[2].y
= nYSrc
+ nHeight
;
1044 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
1046 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
);
1048 if (fabs(det
) < 1e-5)
1050 SetGraphicsMode(hdcDest
,oldgMode
);
1054 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
1055 hdcSrc
, nXSrc
, nYSrc
, nWidth
, nHeight
, hdcDest
, plg
[0].x
, plg
[0].y
, plg
[1].x
, plg
[1].y
, plg
[2].x
, plg
[2].y
);
1058 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
;
1059 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
;
1060 xf
.eDx
= (rect
[0].x
*(rect
[1].y
*plg
[2].x
- rect
[2].y
*plg
[1].x
) -
1061 rect
[1].x
*(rect
[0].y
*plg
[2].x
- rect
[2].y
*plg
[0].x
) +
1062 rect
[2].x
*(rect
[0].y
*plg
[1].x
- rect
[1].y
*plg
[0].x
)
1066 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
;
1067 xf
.eM22
= (rect
[1].x
*(plg
[2].y
- plg
[0].y
) - rect
[2].x
*(plg
[1].y
- plg
[0].y
) - rect
[0].x
*(plg
[2].y
- plg
[1].y
)) / det
;
1068 xf
.eDy
= (rect
[0].x
*(rect
[1].y
*plg
[2].y
- rect
[2].y
*plg
[1].y
) -
1069 rect
[1].x
*(rect
[0].y
*plg
[2].y
- rect
[2].y
*plg
[0].y
) +
1070 rect
[2].x
*(rect
[0].y
*plg
[1].y
- rect
[1].y
*plg
[0].y
)
1073 GetWorldTransform(hdcSrc
,&SrcXf
);
1074 CombineTransform(&xf
,&xf
,&SrcXf
);
1076 /* save actual dest transform */
1077 GetWorldTransform(hdcDest
,&oldDestXf
);
1079 SetWorldTransform(hdcDest
,&xf
);
1080 /* now destination and source DCs use same coords */
1081 MaskBlt(hdcDest
,nXSrc
,nYSrc
,nWidth
,nHeight
,
1082 hdcSrc
, nXSrc
,nYSrc
,
1083 hbmMask
,xMask
,yMask
,
1085 /* restore dest DC */
1086 SetWorldTransform(hdcDest
,&oldDestXf
);
1087 SetGraphicsMode(hdcDest
,oldgMode
);