gdi32: Use EMR_PLGBLT to record PlgBlt.

And use NtGdiPlgBlt.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-09-09 14:01:02 +02:00 committed by Alexandre Julliard
parent dcf7d7d5c4
commit 03ec246e52
5 changed files with 134 additions and 13 deletions

View file

@ -1014,12 +1014,11 @@ BOOL WINAPI NtGdiAlphaBlend( HDC hdcDst, int xDst, int yDst, int widthDst, int h
}
/*********************************************************************
* PlgBlt [GDI32.@]
*
* NtGdiPlgBlt (win32u.@)
*/
BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth,
INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
BOOL WINAPI NtGdiPlgBlt( HDC hdcDest, const POINT *lpPoint, HDC hdcSrc, INT nXSrc, INT nYSrc,
INT nWidth, INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask,
DWORD bk_color )
{
DWORD prev_mode;
/* parallelogram coords */
@ -1071,20 +1070,18 @@ BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
) / det;
GetWorldTransform(hdcSrc,&SrcXf);
NtGdiGetTransform( hdcSrc, 0x203, &SrcXf );
combine_transform( &xf, &xf, &SrcXf );
/* save actual dest transform */
GetWorldTransform(hdcDest,&oldDestXf);
NtGdiGetTransform( hdcDest, 0x203, &oldDestXf );
SetWorldTransform(hdcDest,&xf);
NtGdiModifyWorldTransform( hdcDest, &xf, MWT_SET );
/* now destination and source DCs use same coords */
MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight,
hdcSrc, nXSrc,nYSrc,
hbmMask,xMask,yMask,
SRCCOPY);
NtGdiMaskBlt( hdcDest, nXSrc, nYSrc, nWidth, nHeight, hdcSrc, nXSrc, nYSrc,
hbmMask, xMask, yMask, SRCCOPY, 0 );
/* restore dest DC */
SetWorldTransform(hdcDest,&oldDestXf);
NtGdiModifyWorldTransform( hdcDest, &oldDestXf, MWT_SET );
NtGdiGetAndSetDCDword( hdcDest, NtGdiSetGraphicsMode, prev_mode, NULL );
return TRUE;

View file

@ -1484,6 +1484,109 @@ err:
return ret;
}
BOOL EMFDC_PlgBlt( DC_ATTR *dc_attr, const POINT *points, HDC hdc_src, INT x_src, INT y_src,
INT width, INT height, HBITMAP mask, INT x_mask, INT y_mask )
{
unsigned char mask_info_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
BITMAPINFO *mask_bits_info = (BITMAPINFO *)mask_info_buffer;
struct emf *emf = dc_attr->emf;
BITMAPINFO mask_info = {{ sizeof( mask_info.bmiHeader ) }};
BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }};
HBITMAP bitmap, blit_bitmap = NULL, mask_bitmap = NULL;
UINT bmi_size, size, mask_info_size = 0;
EMRPLGBLT *emr = NULL;
BITMAPINFO *bmi;
HDC blit_dc, mask_dc = NULL;
int x_min, y_min, x_max, y_max, i;
BOOL ret = FALSE;
if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE;
blit_dc = hdc_src;
blit_bitmap = bitmap;
if (!(bmi_size = get_bitmap_info( &blit_dc, &blit_bitmap, &src_info ))) return FALSE;
if (mask)
{
mask_dc = hdc_src;
mask_bitmap = mask;
if (!(mask_info_size = get_bitmap_info( &mask_dc, &mask_bitmap, &mask_info ))) goto err;
if (mask_info.bmiHeader.biBitCount == 1)
mask_info_size = sizeof(BITMAPINFOHEADER); /* don't include colors */
}
else mask_info.bmiHeader.biSizeImage = 0;
size = sizeof(*emr) + bmi_size + src_info.bmiHeader.biSizeImage +
mask_info_size + mask_info.bmiHeader.biSizeImage;
if (!(emr = HeapAlloc(GetProcessHeap(), 0, size))) goto err;
emr->emr.iType = EMR_PLGBLT;
emr->emr.nSize = size;
/* FIXME: not exactly what native does */
x_min = x_max = points[1].x + points[2].x - points[0].x;
y_min = y_max = points[1].y + points[2].y - points[0].y;
for (i = 0; i < ARRAYSIZE(emr->aptlDest); i++)
{
x_min = min( x_min, points[i].x );
y_min = min( y_min, points[i].y );
x_max = max( x_max, points[i].x );
y_max = max( y_min, points[i].y );
}
emr->rclBounds.left = x_min;
emr->rclBounds.top = y_min;
emr->rclBounds.right = x_max;
emr->rclBounds.bottom = y_max;
memcpy( emr->aptlDest, points, sizeof(emr->aptlDest) );
emr->xSrc = x_src;
emr->ySrc = y_src;
emr->cxSrc = width;
emr->cySrc = height;
NtGdiGetTransform( hdc_src, 0x204, &emr->xformSrc );
emr->crBkColorSrc = GetBkColor( hdc_src );
emr->iUsageSrc = DIB_RGB_COLORS;
emr->offBmiSrc = sizeof(*emr);
emr->cbBmiSrc = bmi_size;
emr->offBitsSrc = emr->offBmiSrc + bmi_size;
emr->cbBitsSrc = src_info.bmiHeader.biSizeImage;
emr->xMask = x_mask;
emr->yMask = y_mask;
emr->iUsageMask = DIB_PAL_MONO;
emr->offBmiMask = mask_info_size ? emr->offBitsSrc + emr->cbBitsSrc : 0;
emr->cbBmiMask = mask_info_size;
emr->offBitsMask = emr->offBmiMask + emr->cbBmiMask;
emr->cbBitsMask = mask_info.bmiHeader.biSizeImage;
bmi = (BITMAPINFO *)((char *)emr + emr->offBmiSrc);
bmi->bmiHeader = src_info.bmiHeader;
ret = GetDIBits( blit_dc, blit_bitmap, 0, src_info.bmiHeader.biHeight,
(char *)emr + emr->offBitsSrc, bmi, DIB_RGB_COLORS );
if (!ret) goto err;
if (mask_info_size)
{
mask_bits_info->bmiHeader = mask_info.bmiHeader;
ret = GetDIBits( blit_dc, mask_bitmap, 0, mask_info.bmiHeader.biHeight,
(char *)emr + emr->offBitsMask, mask_bits_info, DIB_RGB_COLORS );
if (ret) memcpy( (char *)emr + emr->offBmiMask, mask_bits_info, mask_info_size );
}
if (ret)
{
ret = emfdc_record( emf, (EMR *)emr );
if (ret) emfdc_update_bounds( emf, &emr->rclBounds );
}
err:
HeapFree( GetProcessHeap(), 0, emr );
if (mask_bitmap != mask) DeleteObject( mask_bitmap );
if (mask_dc != hdc_src) DeleteObject( mask_dc );
if (blit_bitmap != bitmap) DeleteObject( blit_bitmap );
if (blit_dc != hdc_src) DeleteDC( blit_dc );
return ret;
}
BOOL EMFDC_StretchDIBits( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst,
INT x_src, INT y_src, INT width_src, INT height_src, const void *bits,
const BITMAPINFO *info, UINT usage, DWORD rop )

View file

@ -212,6 +212,8 @@ extern BOOL EMFDC_MoveTo( DC_ATTR *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_OffsetClipRgn( DC_ATTR *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_PaintRgn( DC_ATTR *dc_attr, HRGN hrgn ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_PatBlt( DC_ATTR *dc_attr, INT left, INT top, INT width, INT height, DWORD rop );
extern BOOL EMFDC_PlgBlt( DC_ATTR *dc_attr, const POINT *point, HDC hdc_src, INT x_src, INT y_src,
INT width, INT height, HBITMAP mask, INT x_mask, INT y_mask ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_PolyBezier( DC_ATTR *dc_attr, const POINT *points, DWORD count ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_PolyBezierTo( DC_ATTR *dc_attr, const POINT *points, DWORD count ) DECLSPEC_HIDDEN;
extern BOOL EMFDC_PolyDraw( DC_ATTR *dc_attr, const POINT *points, const BYTE *types,

View file

@ -1516,6 +1516,22 @@ BOOL WINAPI MaskBlt( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height_ds
mask, x_mask, y_mask, rop, 0 /* FIXME */ );
}
/***********************************************************************
* PlgBlt (GDI32.@)
*/
BOOL WINAPI PlgBlt( HDC hdc, const POINT *points, HDC hdc_src, INT x_src, INT y_src,
INT width, INT height, HBITMAP mask, INT x_mask, INT y_mask )
{
DC_ATTR *dc_attr;
if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
if (dc_attr->emf && !EMFDC_PlgBlt( dc_attr, points, hdc_src, x_src, y_src,
width, height, mask, x_mask, y_mask ))
return FALSE;
return NtGdiPlgBlt( hdc, points, hdc_src, x_src, y_src, width, height,
mask, x_mask, y_mask, 0 /* FIXME */ );
}
/******************************************************************************
* GdiAlphaBlend (GDI32.@)
*/

View file

@ -353,6 +353,9 @@ INT WINAPI NtGdiOffsetClipRgn( HDC hdc, INT x, INT y );
INT WINAPI NtGdiOffsetRgn( HRGN hrgn, INT x, INT y );
BOOL WINAPI NtGdiPatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop );
HRGN WINAPI NtGdiPathToRegion( HDC hdc );
BOOL WINAPI NtGdiPlgBlt( HDC hdc, const POINT *point, HDC hdc_src, INT x_src, INT y_src,
INT width, INT height, HBITMAP mask, INT x_mask, INT y_mask,
DWORD bk_color );
BOOL WINAPI NtGdiPolyDraw(HDC hdc, const POINT *points, const BYTE *types, DWORD count );
ULONG WINAPI NtGdiPolyPolyDraw( HDC hdc, const POINT *points, const UINT *counts,
DWORD count, UINT function );