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
33 #include "ntgdi_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(bitblt
);
38 static inline BOOL
rop_uses_src( DWORD rop
)
40 return ((rop
>> 2) & 0x330000) != (rop
& 0x330000);
43 BOOL
intersect_vis_rectangles( struct bitblt_coords
*dst
, struct bitblt_coords
*src
)
47 /* intersect the rectangles */
49 if ((src
->width
== dst
->width
) && (src
->height
== dst
->height
)) /* no stretching */
51 OffsetRect( &src
->visrect
, dst
->x
- src
->x
, dst
->y
- src
->y
);
52 if (!intersect_rect( &rect
, &src
->visrect
, &dst
->visrect
)) return FALSE
;
53 src
->visrect
= dst
->visrect
= rect
;
54 OffsetRect( &src
->visrect
, src
->x
- dst
->x
, src
->y
- dst
->y
);
58 /* map source rectangle into destination coordinates */
61 -src
->x
- (src
->width
< 0 ? 1 : 0),
62 -src
->y
- (src
->height
< 0 ? 1 : 0) );
63 rect
.left
= rect
.left
* dst
->width
/ src
->width
;
64 rect
.top
= rect
.top
* dst
->height
/ src
->height
;
65 rect
.right
= rect
.right
* dst
->width
/ src
->width
;
66 rect
.bottom
= rect
.bottom
* dst
->height
/ src
->height
;
69 /* when the source rectangle needs to flip and it doesn't fit in the source device
70 area, the destination area isn't flipped. So, adjust destination coordinates */
71 if (src
->width
< 0 && dst
->width
> 0 &&
72 (src
->x
+ src
->width
+ 1 < src
->visrect
.left
|| src
->x
> src
->visrect
.right
))
73 dst
->x
+= (dst
->width
- rect
.right
) - rect
.left
;
74 else if (src
->width
> 0 && dst
->width
< 0 &&
75 (src
->x
< src
->visrect
.left
|| src
->x
+ src
->width
> src
->visrect
.right
))
76 dst
->x
-= rect
.right
- (dst
->width
- rect
.left
);
78 if (src
->height
< 0 && dst
->height
> 0 &&
79 (src
->y
+ src
->height
+ 1 < src
->visrect
.top
|| src
->y
> src
->visrect
.bottom
))
80 dst
->y
+= (dst
->height
- rect
.bottom
) - rect
.top
;
81 else if (src
->height
> 0 && dst
->height
< 0 &&
82 (src
->y
< src
->visrect
.top
|| src
->y
+ src
->height
> src
->visrect
.bottom
))
83 dst
->y
-= rect
.bottom
- (dst
->height
- rect
.top
);
85 OffsetRect( &rect
, dst
->x
, dst
->y
);
87 /* avoid rounding errors */
92 if (!intersect_rect( &dst
->visrect
, &rect
, &dst
->visrect
)) return FALSE
;
94 /* map destination rectangle back to source coordinates */
97 -dst
->x
- (dst
->width
< 0 ? 1 : 0),
98 -dst
->y
- (dst
->height
< 0 ? 1 : 0) );
99 rect
.left
= src
->x
+ rect
.left
* src
->width
/ dst
->width
;
100 rect
.top
= src
->y
+ rect
.top
* src
->height
/ dst
->height
;
101 rect
.right
= src
->x
+ rect
.right
* src
->width
/ dst
->width
;
102 rect
.bottom
= src
->y
+ rect
.bottom
* src
->height
/ dst
->height
;
105 /* avoid rounding errors */
110 if (!intersect_rect( &src
->visrect
, &rect
, &src
->visrect
)) return FALSE
;
115 static BOOL
get_vis_rectangles( DC
*dc_dst
, struct bitblt_coords
*dst
,
116 DC
*dc_src
, struct bitblt_coords
*src
)
120 /* get the destination visible rectangle */
122 rect
.left
= dst
->log_x
;
123 rect
.top
= dst
->log_y
;
124 rect
.right
= dst
->log_x
+ dst
->log_width
;
125 rect
.bottom
= dst
->log_y
+ dst
->log_height
;
126 lp_to_dp( dc_dst
, (POINT
*)&rect
, 2 );
129 dst
->width
= rect
.right
- rect
.left
;
130 dst
->height
= rect
.bottom
- rect
.top
;
131 if (dst
->layout
& LAYOUT_RTL
&& dst
->layout
& LAYOUT_BITMAPORIENTATIONPRESERVED
)
133 dst
->x
+= dst
->width
;
134 dst
->width
= -dst
->width
;
136 get_bounding_rect( &rect
, dst
->x
, dst
->y
, dst
->width
, dst
->height
);
138 clip_visrect( dc_dst
, &dst
->visrect
, &rect
);
140 /* get the source visible rectangle */
142 if (!src
) return !IsRectEmpty( &dst
->visrect
);
144 rect
.left
= src
->log_x
;
145 rect
.top
= src
->log_y
;
146 rect
.right
= src
->log_x
+ src
->log_width
;
147 rect
.bottom
= src
->log_y
+ src
->log_height
;
148 lp_to_dp( dc_src
, (POINT
*)&rect
, 2 );
151 src
->width
= rect
.right
- rect
.left
;
152 src
->height
= rect
.bottom
- rect
.top
;
153 if (src
->layout
& LAYOUT_RTL
&& src
->layout
& LAYOUT_BITMAPORIENTATIONPRESERVED
)
155 src
->x
+= src
->width
;
156 src
->width
= -src
->width
;
158 get_bounding_rect( &rect
, src
->x
, src
->y
, src
->width
, src
->height
);
160 if (!clip_device_rect( dc_src
, &src
->visrect
, &rect
)) return FALSE
;
161 if (IsRectEmpty( &dst
->visrect
)) return FALSE
;
163 return intersect_vis_rectangles( dst
, src
);
166 void CDECL
free_heap_bits( struct gdi_image_bits
*bits
)
171 DWORD
convert_bits( const BITMAPINFO
*src_info
, struct bitblt_coords
*src
,
172 BITMAPINFO
*dst_info
, struct gdi_image_bits
*bits
)
176 BOOL top_down
= dst_info
->bmiHeader
.biHeight
< 0;
178 dst_info
->bmiHeader
.biWidth
= src
->visrect
.right
- src
->visrect
.left
;
179 dst_info
->bmiHeader
.biHeight
= src
->visrect
.bottom
- src
->visrect
.top
;
180 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
181 if (top_down
) dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
183 if (!(ptr
= malloc( dst_info
->bmiHeader
.biSizeImage
)))
184 return ERROR_OUTOFMEMORY
;
186 err
= convert_bitmapinfo( src_info
, bits
->ptr
, src
, dst_info
, ptr
);
187 if (bits
->free
) bits
->free( bits
);
189 bits
->is_copy
= TRUE
;
190 bits
->free
= free_heap_bits
;
194 DWORD
stretch_bits( const BITMAPINFO
*src_info
, struct bitblt_coords
*src
,
195 BITMAPINFO
*dst_info
, struct bitblt_coords
*dst
,
196 struct gdi_image_bits
*bits
, int mode
)
201 dst_info
->bmiHeader
.biWidth
= dst
->visrect
.right
- dst
->visrect
.left
;
202 dst_info
->bmiHeader
.biHeight
= dst
->visrect
.bottom
- dst
->visrect
.top
;
203 dst_info
->bmiHeader
.biSizeImage
= get_dib_image_size( dst_info
);
205 if (src_info
->bmiHeader
.biHeight
< 0) dst_info
->bmiHeader
.biHeight
= -dst_info
->bmiHeader
.biHeight
;
206 if (!(ptr
= malloc( dst_info
->bmiHeader
.biSizeImage
)))
207 return ERROR_OUTOFMEMORY
;
209 err
= stretch_bitmapinfo( src_info
, bits
->ptr
, src
, dst_info
, ptr
, dst
, mode
);
210 if (bits
->free
) bits
->free( bits
);
212 bits
->is_copy
= TRUE
;
213 bits
->free
= free_heap_bits
;
217 static DWORD
blend_bits( const BITMAPINFO
*src_info
, const struct gdi_image_bits
*src_bits
,
218 struct bitblt_coords
*src
, BITMAPINFO
*dst_info
,
219 struct gdi_image_bits
*dst_bits
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
221 if (!dst_bits
->is_copy
)
223 int size
= dst_info
->bmiHeader
.biSizeImage
;
224 void *ptr
= malloc( size
);
225 if (!ptr
) return ERROR_OUTOFMEMORY
;
226 memcpy( ptr
, dst_bits
->ptr
, size
);
227 if (dst_bits
->free
) dst_bits
->free( dst_bits
);
229 dst_bits
->is_copy
= TRUE
;
230 dst_bits
->free
= free_heap_bits
;
232 return blend_bitmapinfo( src_info
, src_bits
->ptr
, src
, dst_info
, dst_bits
->ptr
, dst
, blend
);
235 static RGBQUAD
get_dc_rgb_color( DC
*dc
, int color_table_size
, COLORREF color
)
237 RGBQUAD ret
= { 0, 0, 0, 0 };
239 if (color
& (1 << 24)) /* PALETTEINDEX */
243 if (!get_palette_entries( dc
->hPalette
, LOWORD(color
), 1, &pal
))
244 get_palette_entries( dc
->hPalette
, 0, 1, &pal
);
245 ret
.rgbRed
= pal
.peRed
;
246 ret
.rgbGreen
= pal
.peGreen
;
247 ret
.rgbBlue
= pal
.peBlue
;
250 if (color
>> 16 == 0x10ff) /* DIBINDEX */
252 if (color_table_size
)
254 if (LOWORD(color
) >= color_table_size
) color
= 0x10ff0000; /* fallback to index 0 */
255 *(DWORD
*)&ret
= color
;
259 ret
.rgbRed
= GetRValue( color
);
260 ret
.rgbGreen
= GetGValue( color
);
261 ret
.rgbBlue
= GetBValue( color
);
265 /* helper to retrieve either both colors or only the background color for monochrome blits */
266 void get_mono_dc_colors( DC
*dc
, int color_table_size
, BITMAPINFO
*info
, int count
)
268 info
->bmiColors
[count
- 1] = get_dc_rgb_color( dc
, color_table_size
, dc
->attr
->background_color
);
269 if (count
> 1) info
->bmiColors
[0] = get_dc_rgb_color( dc
, color_table_size
, dc
->attr
->text_color
);
270 info
->bmiHeader
.biClrUsed
= count
;
273 /***********************************************************************
274 * null driver fallback implementations
277 BOOL CDECL
nulldrv_StretchBlt( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
278 PHYSDEV src_dev
, struct bitblt_coords
*src
, DWORD rop
)
280 DC
*dc_src
= get_physdev_dc( src_dev
), *dc_dst
= get_nulldrv_dc( dst_dev
);
281 char src_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
282 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
283 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_buffer
;
284 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
286 struct gdi_image_bits bits
;
288 src_dev
= GET_DC_PHYSDEV( dc_src
, pGetImage
);
289 if (src_dev
->funcs
->pGetImage( src_dev
, src_info
, &bits
, src
))
292 dst_dev
= GET_DC_PHYSDEV( dc_dst
, pPutImage
);
293 copy_bitmapinfo( dst_info
, src_info
);
294 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, dst_info
, &bits
, src
, dst
, rop
);
295 if (err
== ERROR_BAD_FORMAT
)
297 DWORD dst_colors
= dst_info
->bmiHeader
.biClrUsed
;
299 /* 1-bpp source without a color table uses the destination DC colors */
300 if (src_info
->bmiHeader
.biBitCount
== 1 && !src_info
->bmiHeader
.biClrUsed
)
301 get_mono_dc_colors( dc_dst
, dst_info
->bmiHeader
.biClrUsed
, src_info
, 2 );
303 /* 1-bpp destination without a color table requires a fake 1-entry table
304 * that contains only the background color */
305 if (dst_info
->bmiHeader
.biBitCount
== 1 && !dst_colors
)
306 get_mono_dc_colors( dc_src
, src_info
->bmiHeader
.biClrUsed
, dst_info
, 1 );
308 if (!(err
= convert_bits( src_info
, src
, dst_info
, &bits
)))
310 /* get rid of the fake destination table */
311 dst_info
->bmiHeader
.biClrUsed
= dst_colors
;
312 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, dst_info
, &bits
, src
, dst
, rop
);
316 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
&&
317 ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)))
319 copy_bitmapinfo( src_info
, dst_info
);
320 err
= stretch_bits( src_info
, src
, dst_info
, dst
, &bits
, dc_dst
->attr
->stretch_blt_mode
);
321 if (!err
) err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, dst_info
, &bits
, src
, dst
, rop
);
324 if (bits
.free
) bits
.free( &bits
);
329 BOOL CDECL
nulldrv_AlphaBlend( PHYSDEV dst_dev
, struct bitblt_coords
*dst
,
330 PHYSDEV src_dev
, struct bitblt_coords
*src
, BLENDFUNCTION func
)
332 DC
*dc_src
= get_physdev_dc( src_dev
), *dc_dst
= get_nulldrv_dc( dst_dev
);
333 char src_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
334 char dst_buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
335 BITMAPINFO
*src_info
= (BITMAPINFO
*)src_buffer
;
336 BITMAPINFO
*dst_info
= (BITMAPINFO
*)dst_buffer
;
338 struct gdi_image_bits bits
;
340 src_dev
= GET_DC_PHYSDEV( dc_src
, pGetImage
);
341 err
= src_dev
->funcs
->pGetImage( src_dev
, src_info
, &bits
, src
);
344 dst_dev
= GET_DC_PHYSDEV( dc_dst
, pBlendImage
);
345 copy_bitmapinfo( dst_info
, src_info
);
346 err
= dst_dev
->funcs
->pBlendImage( dst_dev
, dst_info
, &bits
, src
, dst
, func
);
347 if (err
== ERROR_BAD_FORMAT
)
349 err
= convert_bits( src_info
, src
, dst_info
, &bits
);
350 if (!err
) err
= dst_dev
->funcs
->pBlendImage( dst_dev
, dst_info
, &bits
, src
, dst
, func
);
353 if (err
== ERROR_TRANSFORM_NOT_SUPPORTED
&&
354 ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)))
356 copy_bitmapinfo( src_info
, dst_info
);
357 err
= stretch_bits( src_info
, src
, dst_info
, dst
, &bits
, COLORONCOLOR
);
358 if (!err
) err
= dst_dev
->funcs
->pBlendImage( dst_dev
, dst_info
, &bits
, src
, dst
, func
);
361 if (bits
.free
) bits
.free( &bits
);
363 if (err
) RtlSetLastWin32Error( err
);
368 DWORD CDECL
nulldrv_BlendImage( PHYSDEV dev
, BITMAPINFO
*info
, const struct gdi_image_bits
*bits
,
369 struct bitblt_coords
*src
, struct bitblt_coords
*dst
, BLENDFUNCTION blend
)
371 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
372 BITMAPINFO
*dst_info
= (BITMAPINFO
*)buffer
;
373 struct gdi_image_bits dst_bits
;
374 struct bitblt_coords orig_dst
;
375 DWORD
*masks
= (DWORD
*)info
->bmiColors
;
376 DC
*dc
= get_nulldrv_dc( dev
);
379 if (info
->bmiHeader
.biPlanes
!= 1) goto update_format
;
380 if (info
->bmiHeader
.biBitCount
!= 32) goto update_format
;
381 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
383 if (blend
.AlphaFormat
& AC_SRC_ALPHA
) return ERROR_INVALID_PARAMETER
;
384 if (masks
[0] != 0xff0000 || masks
[1] != 0x00ff00 || masks
[2] != 0x0000ff)
388 if (!bits
) return ERROR_SUCCESS
;
389 if ((src
->width
!= dst
->width
) || (src
->height
!= dst
->height
)) return ERROR_TRANSFORM_NOT_SUPPORTED
;
391 dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
393 err
= dev
->funcs
->pGetImage( dev
, dst_info
, &dst_bits
, dst
);
396 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
397 err
= blend_bits( info
, bits
, src
, dst_info
, &dst_bits
, dst
, blend
);
398 if (!err
) err
= dev
->funcs
->pPutImage( dev
, 0, dst_info
, &dst_bits
, dst
, &orig_dst
, SRCCOPY
);
400 if (dst_bits
.free
) dst_bits
.free( &dst_bits
);
404 if (blend
.AlphaFormat
& AC_SRC_ALPHA
) /* source alpha requires A8R8G8B8 format */
405 return ERROR_INVALID_PARAMETER
;
407 info
->bmiHeader
.biPlanes
= 1;
408 info
->bmiHeader
.biBitCount
= 32;
409 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
410 info
->bmiHeader
.biClrUsed
= 0;
414 return ERROR_BAD_FORMAT
;
417 BOOL CDECL
nulldrv_GradientFill( PHYSDEV dev
, TRIVERTEX
*vert_array
, ULONG nvert
,
418 void * grad_array
, ULONG ngrad
, ULONG mode
)
420 DC
*dc
= get_nulldrv_dc( dev
);
421 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
422 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
423 struct bitblt_coords src
, dst
;
424 struct gdi_image_bits bits
;
431 if (!(pts
= malloc( nvert
* sizeof(*pts
) ))) return FALSE
;
432 for (i
= 0; i
< nvert
; i
++)
434 pts
[i
].x
= vert_array
[i
].x
;
435 pts
[i
].y
= vert_array
[i
].y
;
437 lp_to_dp( dc
, pts
, nvert
);
439 /* compute bounding rect of all the rectangles/triangles */
440 reset_bounds( &dst
.visrect
);
441 for (i
= 0; i
< ngrad
* (mode
== GRADIENT_FILL_TRIANGLE
? 3 : 2); i
++)
443 ULONG v
= ((ULONG
*)grad_array
)[i
];
444 dst
.visrect
.left
= min( dst
.visrect
.left
, pts
[v
].x
);
445 dst
.visrect
.top
= min( dst
.visrect
.top
, pts
[v
].y
);
446 dst
.visrect
.right
= max( dst
.visrect
.right
, pts
[v
].x
);
447 dst
.visrect
.bottom
= max( dst
.visrect
.bottom
, pts
[v
].y
);
450 dst
.x
= dst
.visrect
.left
;
451 dst
.y
= dst
.visrect
.top
;
452 dst
.width
= dst
.visrect
.right
- dst
.visrect
.left
;
453 dst
.height
= dst
.visrect
.bottom
- dst
.visrect
.top
;
454 if (!clip_visrect( dc
, &dst
.visrect
, &dst
.visrect
)) goto done
;
456 /* query the bitmap format */
457 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
458 info
->bmiHeader
.biPlanes
= 1;
459 info
->bmiHeader
.biBitCount
= 0;
460 info
->bmiHeader
.biCompression
= BI_RGB
;
461 info
->bmiHeader
.biXPelsPerMeter
= 0;
462 info
->bmiHeader
.biYPelsPerMeter
= 0;
463 info
->bmiHeader
.biClrUsed
= 0;
464 info
->bmiHeader
.biClrImportant
= 0;
465 info
->bmiHeader
.biWidth
= dst
.visrect
.right
- dst
.visrect
.left
;
466 info
->bmiHeader
.biHeight
= dst
.visrect
.bottom
- dst
.visrect
.top
;
467 info
->bmiHeader
.biSizeImage
= 0;
468 dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
469 err
= dev
->funcs
->pPutImage( dev
, 0, info
, NULL
, NULL
, NULL
, 0 );
470 if (err
&& err
!= ERROR_BAD_FORMAT
) goto done
;
472 info
->bmiHeader
.biSizeImage
= get_dib_image_size( info
);
473 if (!(bits
.ptr
= calloc( 1, info
->bmiHeader
.biSizeImage
)))
476 bits
.free
= free_heap_bits
;
478 /* make src and points relative to the bitmap */
480 src
.x
-= dst
.visrect
.left
;
481 src
.y
-= dst
.visrect
.top
;
482 OffsetRect( &src
.visrect
, -dst
.visrect
.left
, -dst
.visrect
.top
);
483 for (i
= 0; i
< nvert
; i
++)
485 pts
[i
].x
-= dst
.visrect
.left
;
486 pts
[i
].y
-= dst
.visrect
.top
;
489 rgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
490 gradient_bitmapinfo( info
, bits
.ptr
, vert_array
, nvert
, grad_array
, ngrad
, mode
, pts
, rgn
);
491 NtGdiOffsetRgn( rgn
, dst
.visrect
.left
, dst
.visrect
.top
);
492 ret
= !dev
->funcs
->pPutImage( dev
, rgn
, info
, &bits
, &src
, &dst
, SRCCOPY
);
494 if (bits
.free
) bits
.free( &bits
);
495 NtGdiDeleteObjectApp( rgn
);
502 COLORREF CDECL
nulldrv_GetPixel( PHYSDEV dev
, INT x
, INT y
)
504 DC
*dc
= get_nulldrv_dc( dev
);
505 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
506 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
507 struct bitblt_coords src
;
508 struct gdi_image_bits bits
;
511 src
.visrect
.left
= x
;
513 lp_to_dp( dc
, (POINT
*)&src
.visrect
, 1 );
514 src
.visrect
.right
= src
.visrect
.left
+ 1;
515 src
.visrect
.bottom
= src
.visrect
.top
+ 1;
516 src
.x
= src
.visrect
.left
;
517 src
.y
= src
.visrect
.top
;
518 src
.width
= src
.height
= 1;
520 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return CLR_INVALID
;
522 dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
523 if (dev
->funcs
->pGetImage( dev
, info
, &bits
, &src
)) return CLR_INVALID
;
525 ret
= get_pixel_bitmapinfo( info
, bits
.ptr
, &src
);
526 if (bits
.free
) bits
.free( &bits
);
531 /***********************************************************************
532 * NtGdiPatBlt (win32u.@)
534 BOOL WINAPI
NtGdiPatBlt( HDC hdc
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
539 if (rop_uses_src( rop
)) return FALSE
;
540 if ((dc
= get_dc_ptr( hdc
)))
542 struct bitblt_coords dst
;
548 dst
.log_width
= width
;
549 dst
.log_height
= height
;
550 dst
.layout
= dc
->attr
->layout
;
551 if (rop
& NOMIRRORBITMAP
)
553 dst
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
554 rop
&= ~NOMIRRORBITMAP
;
556 ret
= !get_vis_rectangles( dc
, &dst
, NULL
, NULL
);
558 TRACE("dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s rop=%06x\n",
559 hdc
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
560 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
), (int)rop
);
564 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pPatBlt
);
565 ret
= physdev
->funcs
->pPatBlt( physdev
, &dst
, rop
);
567 release_dc_ptr( dc
);
573 /***********************************************************************
574 * NtGdiBitBlt (win32u.@)
576 BOOL WINAPI
NtGdiBitBlt( HDC hdc_dst
, INT x_dst
, INT y_dst
, INT width
, INT height
,
577 HDC hdc_src
, INT x_src
, INT y_src
, DWORD rop
, DWORD bk_color
, FLONG fl
)
579 return NtGdiStretchBlt( hdc_dst
, x_dst
, y_dst
, width
, height
,
580 hdc_src
, x_src
, y_src
, width
, height
, rop
, bk_color
);
584 /***********************************************************************
585 * NtGdiStretchBlt (win32u.@)
587 BOOL WINAPI
NtGdiStretchBlt( HDC hdcDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
588 HDC hdcSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
589 DWORD rop
, COLORREF bk_color
)
594 if (!rop_uses_src( rop
)) return NtGdiPatBlt( hdcDst
, xDst
, yDst
, widthDst
, heightDst
, rop
);
596 if (!(dcDst
= get_dc_ptr( hdcDst
))) return FALSE
;
598 if ((dcSrc
= get_dc_ptr( hdcSrc
)))
600 struct bitblt_coords src
, dst
;
607 src
.log_width
= widthSrc
;
608 src
.log_height
= heightSrc
;
609 src
.layout
= dcSrc
->attr
->layout
;
612 dst
.log_width
= widthDst
;
613 dst
.log_height
= heightDst
;
614 dst
.layout
= dcDst
->attr
->layout
;
615 if (rop
& NOMIRRORBITMAP
)
617 src
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
618 dst
.layout
|= LAYOUT_BITMAPORIENTATIONPRESERVED
;
619 rop
&= ~NOMIRRORBITMAP
;
621 ret
= !get_vis_rectangles( dcDst
, &dst
, dcSrc
, &src
);
623 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",
624 hdcSrc
, src
.log_x
, src
.log_y
, src
.log_width
, src
.log_height
,
625 src
.x
, src
.y
, src
.width
, src
.height
, wine_dbgstr_rect(&src
.visrect
),
626 hdcDst
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
627 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
), (int)rop
);
631 PHYSDEV src_dev
= GET_DC_PHYSDEV( dcSrc
, pStretchBlt
);
632 PHYSDEV dst_dev
= GET_DC_PHYSDEV( dcDst
, pStretchBlt
);
633 ret
= dst_dev
->funcs
->pStretchBlt( dst_dev
, &dst
, src_dev
, &src
, rop
);
635 release_dc_ptr( dcSrc
);
637 release_dc_ptr( dcDst
);
641 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
642 #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF])
644 /***********************************************************************
645 * NtGdiMaskBlt (win32u.@)
647 BOOL WINAPI
NtGdiMaskBlt( HDC hdcDest
, INT nXDest
, INT nYDest
, INT nWidth
, INT nHeight
,
648 HDC hdcSrc
, INT nXSrc
, INT nYSrc
, HBITMAP hbmMask
,
649 INT xMask
, INT yMask
, DWORD dwRop
, DWORD bk_color
)
651 HBITMAP hBitmap1
, hOldBitmap1
, hBitmap2
, hOldBitmap2
;
653 HBRUSH hbrMask
, hbrDst
, hbrTmp
;
655 static const DWORD ROP3Table
[256] =
657 0x00000042, 0x00010289,
658 0x00020C89, 0x000300AA,
659 0x00040C88, 0x000500A9,
660 0x00060865, 0x000702C5,
661 0x00080F08, 0x00090245,
662 0x000A0329, 0x000B0B2A,
663 0x000C0324, 0x000D0B25,
664 0x000E08A5, 0x000F0001,
665 0x00100C85, 0x001100A6,
666 0x00120868, 0x001302C8,
667 0x00140869, 0x001502C9,
668 0x00165CCA, 0x00171D54,
669 0x00180D59, 0x00191CC8,
670 0x001A06C5, 0x001B0768,
671 0x001C06CA, 0x001D0766,
672 0x001E01A5, 0x001F0385,
673 0x00200F09, 0x00210248,
674 0x00220326, 0x00230B24,
675 0x00240D55, 0x00251CC5,
676 0x002606C8, 0x00271868,
677 0x00280369, 0x002916CA,
678 0x002A0CC9, 0x002B1D58,
679 0x002C0784, 0x002D060A,
680 0x002E064A, 0x002F0E2A,
681 0x0030032A, 0x00310B28,
682 0x00320688, 0x00330008,
683 0x003406C4, 0x00351864,
684 0x003601A8, 0x00370388,
685 0x0038078A, 0x00390604,
686 0x003A0644, 0x003B0E24,
687 0x003C004A, 0x003D18A4,
688 0x003E1B24, 0x003F00EA,
689 0x00400F0A, 0x00410249,
690 0x00420D5D, 0x00431CC4,
691 0x00440328, 0x00450B29,
692 0x004606C6, 0x0047076A,
693 0x00480368, 0x004916C5,
694 0x004A0789, 0x004B0605,
695 0x004C0CC8, 0x004D1954,
696 0x004E0645, 0x004F0E25,
697 0x00500325, 0x00510B26,
698 0x005206C9, 0x00530764,
699 0x005408A9, 0x00550009,
700 0x005601A9, 0x00570389,
701 0x00580785, 0x00590609,
702 0x005A0049, 0x005B18A9,
703 0x005C0649, 0x005D0E29,
704 0x005E1B29, 0x005F00E9,
705 0x00600365, 0x006116C6,
706 0x00620786, 0x00630608,
707 0x00640788, 0x00650606,
708 0x00660046, 0x006718A8,
709 0x006858A6, 0x00690145,
710 0x006A01E9, 0x006B178A,
711 0x006C01E8, 0x006D1785,
712 0x006E1E28, 0x006F0C65,
713 0x00700CC5, 0x00711D5C,
714 0x00720648, 0x00730E28,
715 0x00740646, 0x00750E26,
716 0x00761B28, 0x007700E6,
717 0x007801E5, 0x00791786,
718 0x007A1E29, 0x007B0C68,
719 0x007C1E24, 0x007D0C69,
720 0x007E0955, 0x007F03C9,
721 0x008003E9, 0x00810975,
722 0x00820C49, 0x00831E04,
723 0x00840C48, 0x00851E05,
724 0x008617A6, 0x008701C5,
725 0x008800C6, 0x00891B08,
726 0x008A0E06, 0x008B0666,
727 0x008C0E08, 0x008D0668,
728 0x008E1D7C, 0x008F0CE5,
729 0x00900C45, 0x00911E08,
730 0x009217A9, 0x009301C4,
731 0x009417AA, 0x009501C9,
732 0x00960169, 0x0097588A,
733 0x00981888, 0x00990066,
734 0x009A0709, 0x009B07A8,
735 0x009C0704, 0x009D07A6,
736 0x009E16E6, 0x009F0345,
737 0x00A000C9, 0x00A11B05,
738 0x00A20E09, 0x00A30669,
739 0x00A41885, 0x00A50065,
740 0x00A60706, 0x00A707A5,
741 0x00A803A9, 0x00A90189,
742 0x00AA0029, 0x00AB0889,
743 0x00AC0744, 0x00AD06E9,
744 0x00AE0B06, 0x00AF0229,
745 0x00B00E05, 0x00B10665,
746 0x00B21974, 0x00B30CE8,
747 0x00B4070A, 0x00B507A9,
748 0x00B616E9, 0x00B70348,
749 0x00B8074A, 0x00B906E6,
750 0x00BA0B09, 0x00BB0226,
751 0x00BC1CE4, 0x00BD0D7D,
752 0x00BE0269, 0x00BF08C9,
753 0x00C000CA, 0x00C11B04,
754 0x00C21884, 0x00C3006A,
755 0x00C40E04, 0x00C50664,
756 0x00C60708, 0x00C707AA,
757 0x00C803A8, 0x00C90184,
758 0x00CA0749, 0x00CB06E4,
759 0x00CC0020, 0x00CD0888,
760 0x00CE0B08, 0x00CF0224,
761 0x00D00E0A, 0x00D1066A,
762 0x00D20705, 0x00D307A4,
763 0x00D41D78, 0x00D50CE9,
764 0x00D616EA, 0x00D70349,
765 0x00D80745, 0x00D906E8,
766 0x00DA1CE9, 0x00DB0D75,
767 0x00DC0B04, 0x00DD0228,
768 0x00DE0268, 0x00DF08C8,
769 0x00E003A5, 0x00E10185,
770 0x00E20746, 0x00E306EA,
771 0x00E40748, 0x00E506E5,
772 0x00E61CE8, 0x00E70D79,
773 0x00E81D74, 0x00E95CE6,
774 0x00EA02E9, 0x00EB0849,
775 0x00EC02E8, 0x00ED0848,
776 0x00EE0086, 0x00EF0A08,
777 0x00F00021, 0x00F10885,
778 0x00F20B05, 0x00F3022A,
779 0x00F40B0A, 0x00F50225,
780 0x00F60265, 0x00F708C5,
781 0x00F802E5, 0x00F90845,
782 0x00FA0089, 0x00FB0A09,
783 0x00FC008A, 0x00FD0A0A,
784 0x00FE02A9, 0x00FF0062,
788 return NtGdiBitBlt( hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
,
789 nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), bk_color
, 0 );
791 hbrMask
= NtGdiCreatePatternBrushInternal( hbmMask
, FALSE
, FALSE
);
792 hbrDst
= NtGdiSelectBrush( hdcDest
, GetStockObject(NULL_BRUSH
) );
795 hDC1
= NtGdiCreateCompatibleDC( hdcDest
);
796 hBitmap1
= NtGdiCreateCompatibleBitmap( hdcDest
, nWidth
, nHeight
);
797 hOldBitmap1
= NtGdiSelectBitmap(hDC1
, hBitmap1
);
799 /* draw using bkgnd rop */
800 NtGdiBitBlt( hDC1
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0 );
801 hbrTmp
= NtGdiSelectBrush(hDC1
, hbrDst
);
802 NtGdiBitBlt( hDC1
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, BKGND_ROP3(dwRop
), 0, 0 );
803 NtGdiSelectBrush(hDC1
, hbrTmp
);
806 hDC2
= NtGdiCreateCompatibleDC( hdcDest
);
807 hBitmap2
= NtGdiCreateCompatibleBitmap( hdcDest
, nWidth
, nHeight
);
808 hOldBitmap2
= NtGdiSelectBitmap(hDC2
, hBitmap2
);
810 /* draw using foregnd rop */
811 NtGdiBitBlt( hDC2
, 0, 0, nWidth
, nHeight
, hdcDest
, nXDest
, nYDest
, SRCCOPY
, 0, 0 );
812 hbrTmp
= NtGdiSelectBrush(hDC2
, hbrDst
);
813 NtGdiBitBlt( hDC2
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, FRGND_ROP3(dwRop
), 0, 0 );
815 /* combine both using the mask as a pattern brush */
816 NtGdiSelectBrush(hDC2
, hbrMask
);
817 NtGdiSetBrushOrg( hDC2
, -xMask
, -yMask
, NULL
);
818 /* (D & P) | (S & ~P) */
819 NtGdiBitBlt(hDC2
, 0, 0, nWidth
, nHeight
, hDC1
, 0, 0, 0xac0744, 0, 0 );
820 NtGdiSelectBrush(hDC2
, hbrTmp
);
823 NtGdiBitBlt( hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hDC2
, 0, 0, SRCCOPY
, bk_color
, 0 );
825 /* restore all objects */
826 NtGdiSelectBrush(hdcDest
, hbrDst
);
827 NtGdiSelectBitmap(hDC1
, hOldBitmap1
);
828 NtGdiSelectBitmap(hDC2
, hOldBitmap2
);
830 /* delete all temp objects */
831 NtGdiDeleteObjectApp( hBitmap1
);
832 NtGdiDeleteObjectApp( hBitmap2
);
833 NtGdiDeleteObjectApp( hbrMask
);
835 NtGdiDeleteObjectApp( hDC1
);
836 NtGdiDeleteObjectApp( hDC2
);
841 /******************************************************************************
842 * NtGdiTransparentBlt (win32u.@)
844 BOOL WINAPI
NtGdiTransparentBlt( HDC hdcDest
, int xDest
, int yDest
, int widthDest
, int heightDest
,
845 HDC hdcSrc
, int xSrc
, int ySrc
, int widthSrc
, int heightSrc
,
853 HBITMAP bmpMask
= NULL
;
854 HBITMAP oldMask
= NULL
;
855 COLORREF oldBackground
;
856 COLORREF oldForeground
;
861 if(widthDest
< 0 || heightDest
< 0 || widthSrc
< 0 || heightSrc
< 0) {
862 TRACE("Cannot mirror\n");
866 if (!(dc_src
= get_dc_ptr( hdcSrc
))) return FALSE
;
868 NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetBkColor
, RGB(255,255,255), &oldBackground
);
869 NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetTextColor
, RGB(0,0,0), &oldForeground
);
872 oldStretchMode
= dc_src
->attr
->stretch_blt_mode
;
873 if (oldStretchMode
== BLACKONWHITE
|| oldStretchMode
== WHITEONBLACK
)
874 dc_src
->attr
->stretch_blt_mode
= COLORONCOLOR
;
875 hdcWork
= NtGdiCreateCompatibleDC( hdcDest
);
876 if ((get_gdi_object_type( hdcDest
) != NTGDI_OBJ_MEMDC
||
877 NtGdiExtGetObjectW( NtGdiGetDCObject( hdcDest
, NTGDI_OBJ_SURF
),
878 sizeof(dib
), &dib
) == sizeof(BITMAP
)) &&
879 NtGdiGetDeviceCaps( hdcDest
, BITSPIXEL
) == 32)
881 /* screen DCs or DDBs are not supposed to have an alpha channel, so use a 24-bpp bitmap as copy */
883 info
.bmiHeader
.biSize
= sizeof(info
.bmiHeader
);
884 info
.bmiHeader
.biWidth
= widthDest
;
885 info
.bmiHeader
.biHeight
= heightDest
;
886 info
.bmiHeader
.biPlanes
= 1;
887 info
.bmiHeader
.biBitCount
= 24;
888 info
.bmiHeader
.biCompression
= BI_RGB
;
889 bmpWork
= NtGdiCreateDIBSection( 0, NULL
, 0, &info
, DIB_RGB_COLORS
, 0, 0, 0, NULL
);
891 else bmpWork
= NtGdiCreateCompatibleBitmap( hdcDest
, widthDest
, heightDest
);
892 oldWork
= NtGdiSelectBitmap(hdcWork
, bmpWork
);
893 if (!NtGdiStretchBlt( hdcWork
, 0, 0, widthDest
, heightDest
, hdcSrc
, xSrc
, ySrc
,
894 widthSrc
, heightSrc
, SRCCOPY
, 0 ))
896 TRACE("Failed to stretch\n");
899 NtGdiGetAndSetDCDword( hdcWork
, NtGdiSetBkColor
, crTransparent
, NULL
);
902 hdcMask
= NtGdiCreateCompatibleDC( hdcDest
);
903 bmpMask
= NtGdiCreateCompatibleBitmap( hdcMask
, widthDest
, heightDest
);
904 oldMask
= NtGdiSelectBitmap(hdcMask
, bmpMask
);
905 if (!NtGdiBitBlt( hdcMask
, 0, 0, widthDest
, heightDest
, hdcWork
, 0, 0, SRCCOPY
, 0, 0 ))
907 TRACE("Failed to create mask\n");
911 /* Replace transparent color with black */
912 NtGdiGetAndSetDCDword( hdcWork
, NtGdiSetBkColor
, RGB(0,0,0), NULL
);
913 NtGdiGetAndSetDCDword( hdcWork
, NtGdiSetTextColor
, RGB(255,255,255), NULL
);
914 if (!NtGdiBitBlt( hdcWork
, 0, 0, widthDest
, heightDest
, hdcMask
, 0, 0, SRCAND
, 0, 0 ))
916 TRACE("Failed to mask out background\n");
920 /* Replace non-transparent area on destination with black */
921 if (!NtGdiBitBlt( hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcMask
, 0, 0, SRCAND
, 0, 0 ))
923 TRACE("Failed to clear destination area\n");
928 if (!NtGdiBitBlt( hdcDest
, xDest
, yDest
, widthDest
, heightDest
, hdcWork
, 0, 0, SRCPAINT
, 0, 0 ))
930 TRACE("Failed to paint image\n");
936 dc_src
->attr
->stretch_blt_mode
= oldStretchMode
;
937 release_dc_ptr( dc_src
);
938 NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetBkColor
, oldBackground
, NULL
);
939 NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetTextColor
, oldForeground
, NULL
);
941 NtGdiSelectBitmap(hdcWork
, oldWork
);
942 NtGdiDeleteObjectApp( hdcWork
);
944 if(bmpWork
) NtGdiDeleteObjectApp( bmpWork
);
946 NtGdiSelectBitmap(hdcMask
, oldMask
);
947 NtGdiDeleteObjectApp( hdcMask
);
949 if(bmpMask
) NtGdiDeleteObjectApp( bmpMask
);
953 /******************************************************************************
954 * NtGdiAlphaBlend (win32u.@)
956 BOOL WINAPI
NtGdiAlphaBlend( HDC hdcDst
, int xDst
, int yDst
, int widthDst
, int heightDst
,
957 HDC hdcSrc
, int xSrc
, int ySrc
, int widthSrc
, int heightSrc
,
958 BLENDFUNCTION blendFunction
, HANDLE xform
)
963 dcSrc
= get_dc_ptr( hdcSrc
);
964 if (!dcSrc
) return FALSE
;
966 if ((dcDst
= get_dc_ptr( hdcDst
)))
968 struct bitblt_coords src
, dst
;
975 src
.log_width
= widthSrc
;
976 src
.log_height
= heightSrc
;
977 src
.layout
= dcSrc
->attr
->layout
;
980 dst
.log_width
= widthDst
;
981 dst
.log_height
= heightDst
;
982 dst
.layout
= dcDst
->attr
->layout
;
983 ret
= !get_vis_rectangles( dcDst
, &dst
, dcSrc
, &src
);
985 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",
986 hdcSrc
, src
.log_x
, src
.log_y
, src
.log_width
, src
.log_height
,
987 src
.x
, src
.y
, src
.width
, src
.height
, wine_dbgstr_rect(&src
.visrect
),
988 hdcDst
, dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
,
989 dst
.x
, dst
.y
, dst
.width
, dst
.height
, wine_dbgstr_rect(&dst
.visrect
),
990 blendFunction
.BlendOp
, blendFunction
.BlendFlags
,
991 blendFunction
.SourceConstantAlpha
, blendFunction
.AlphaFormat
);
993 if (src
.x
< 0 || src
.y
< 0 || src
.width
< 0 || src
.height
< 0 ||
994 src
.log_width
< 0 || src
.log_height
< 0 ||
995 (!IsRectEmpty( &dcSrc
->device_rect
) &&
996 (src
.width
> dcSrc
->device_rect
.right
- dcSrc
->attr
->vis_rect
.left
- src
.x
||
997 src
.height
> dcSrc
->device_rect
.bottom
- dcSrc
->attr
->vis_rect
.top
- src
.y
)))
999 WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src
.x
, src
.y
, src
.width
, src
.height
);
1000 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
1003 else if (dst
.log_width
< 0 || dst
.log_height
< 0)
1005 WARN( "Invalid dst coords: (%d,%d), size %dx%d\n",
1006 dst
.log_x
, dst
.log_y
, dst
.log_width
, dst
.log_height
);
1007 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
1010 else if (dcSrc
== dcDst
&& src
.x
+ src
.width
> dst
.x
&& src
.x
< dst
.x
+ dst
.width
&&
1011 src
.y
+ src
.height
> dst
.y
&& src
.y
< dst
.y
+ dst
.height
)
1013 WARN( "Overlapping coords: (%d,%d), %dx%d and (%d,%d), %dx%d\n",
1014 src
.x
, src
.y
, src
.width
, src
.height
, dst
.x
, dst
.y
, dst
.width
, dst
.height
);
1015 RtlSetLastWin32Error( ERROR_INVALID_PARAMETER
);
1020 PHYSDEV src_dev
= GET_DC_PHYSDEV( dcSrc
, pAlphaBlend
);
1021 PHYSDEV dst_dev
= GET_DC_PHYSDEV( dcDst
, pAlphaBlend
);
1022 ret
= dst_dev
->funcs
->pAlphaBlend( dst_dev
, &dst
, src_dev
, &src
, blendFunction
);
1024 release_dc_ptr( dcDst
);
1026 release_dc_ptr( dcSrc
);
1030 /*********************************************************************
1031 * NtGdiPlgBlt (win32u.@)
1033 BOOL WINAPI
NtGdiPlgBlt( HDC hdcDest
, const POINT
*lpPoint
, HDC hdcSrc
, INT nXSrc
, INT nYSrc
,
1034 INT nWidth
, INT nHeight
, HBITMAP hbmMask
, INT xMask
, INT yMask
,
1038 /* parallelogram coords */
1047 /* save actual mode, set GM_ADVANCED */
1048 if (!NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetGraphicsMode
, GM_ADVANCED
, &prev_mode
))
1051 memcpy(plg
,lpPoint
,sizeof(POINT
)*3);
1054 rect
[1].x
= nXSrc
+ nWidth
;
1057 rect
[2].y
= nYSrc
+ nHeight
;
1058 /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
1060 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
);
1062 if (fabs(det
) < 1e-5)
1064 NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetGraphicsMode
, prev_mode
, NULL
);
1068 TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n",
1069 hdcSrc
, nXSrc
, nYSrc
, nWidth
, nHeight
, hdcDest
,
1070 (int)plg
[0].x
, (int)plg
[0].y
, (int)plg
[1].x
, (int)plg
[1].y
, (int)plg
[2].x
, (int)plg
[2].y
);
1073 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
;
1074 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
;
1075 xf
.eDx
= (rect
[0].x
*(rect
[1].y
*plg
[2].x
- rect
[2].y
*plg
[1].x
) -
1076 rect
[1].x
*(rect
[0].y
*plg
[2].x
- rect
[2].y
*plg
[0].x
) +
1077 rect
[2].x
*(rect
[0].y
*plg
[1].x
- rect
[1].y
*plg
[0].x
)
1081 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
;
1082 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
;
1083 xf
.eDy
= (rect
[0].x
*(rect
[1].y
*plg
[2].y
- rect
[2].y
*plg
[1].y
) -
1084 rect
[1].x
*(rect
[0].y
*plg
[2].y
- rect
[2].y
*plg
[0].y
) +
1085 rect
[2].x
*(rect
[0].y
*plg
[1].y
- rect
[1].y
*plg
[0].y
)
1088 NtGdiGetTransform( hdcSrc
, 0x203, &SrcXf
);
1089 combine_transform( &xf
, &xf
, &SrcXf
);
1091 /* save actual dest transform */
1092 NtGdiGetTransform( hdcDest
, 0x203, &oldDestXf
);
1094 NtGdiModifyWorldTransform( hdcDest
, &xf
, MWT_SET
);
1095 /* now destination and source DCs use same coords */
1096 NtGdiMaskBlt( hdcDest
, nXSrc
, nYSrc
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
,
1097 hbmMask
, xMask
, yMask
, SRCCOPY
, 0 );
1098 /* restore dest DC */
1099 NtGdiModifyWorldTransform( hdcDest
, &oldDestXf
, MWT_SET
);
1100 NtGdiGetAndSetDCDword( hdcDest
, NtGdiSetGraphicsMode
, prev_mode
, NULL
);