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, BOOL WINAPI NtGdiPlgBlt( HDC hdcDest, const POINT *lpPoint, HDC hdcSrc, INT nXSrc, INT nYSrc,
HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth, INT nWidth, INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask,
INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask) DWORD bk_color )
{ {
DWORD prev_mode; DWORD prev_mode;
/* parallelogram coords */ /* 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) rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y)
) / det; ) / det;
GetWorldTransform(hdcSrc,&SrcXf); NtGdiGetTransform( hdcSrc, 0x203, &SrcXf );
combine_transform( &xf, &xf, &SrcXf ); combine_transform( &xf, &xf, &SrcXf );
/* save actual dest transform */ /* 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 */ /* now destination and source DCs use same coords */
MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight, NtGdiMaskBlt( hdcDest, nXSrc, nYSrc, nWidth, nHeight, hdcSrc, nXSrc, nYSrc,
hdcSrc, nXSrc,nYSrc, hbmMask, xMask, yMask, SRCCOPY, 0 );
hbmMask,xMask,yMask,
SRCCOPY);
/* restore dest DC */ /* restore dest DC */
SetWorldTransform(hdcDest,&oldDestXf); NtGdiModifyWorldTransform( hdcDest, &oldDestXf, MWT_SET );
NtGdiGetAndSetDCDword( hdcDest, NtGdiSetGraphicsMode, prev_mode, NULL ); NtGdiGetAndSetDCDword( hdcDest, NtGdiSetGraphicsMode, prev_mode, NULL );
return TRUE; return TRUE;

View file

@ -1484,6 +1484,109 @@ err:
return ret; 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, 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, INT x_src, INT y_src, INT width_src, INT height_src, const void *bits,
const BITMAPINFO *info, UINT usage, DWORD rop ) 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_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_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_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_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_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, 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 */ ); 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.@) * 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 ); INT WINAPI NtGdiOffsetRgn( HRGN hrgn, INT x, INT y );
BOOL WINAPI NtGdiPatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop ); BOOL WINAPI NtGdiPatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop );
HRGN WINAPI NtGdiPathToRegion( HDC hdc ); 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 ); BOOL WINAPI NtGdiPolyDraw(HDC hdc, const POINT *points, const BYTE *types, DWORD count );
ULONG WINAPI NtGdiPolyPolyDraw( HDC hdc, const POINT *points, const UINT *counts, ULONG WINAPI NtGdiPolyPolyDraw( HDC hdc, const POINT *points, const UINT *counts,
DWORD count, UINT function ); DWORD count, UINT function );