From 03ec246e5282ab3f76e1df312272598eeba69260 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 9 Sep 2021 14:01:02 +0200 Subject: [PATCH] gdi32: Use EMR_PLGBLT to record PlgBlt. And use NtGdiPlgBlt. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/bitblt.c | 23 ++++----- dlls/gdi32/emfdc.c | 103 +++++++++++++++++++++++++++++++++++++++ dlls/gdi32/gdi_private.h | 2 + dlls/gdi32/gdidc.c | 16 ++++++ include/ntgdi.h | 3 ++ 5 files changed, 134 insertions(+), 13 deletions(-) diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c index a1b4b6fa393..33ce6966f87 100644 --- a/dlls/gdi32/bitblt.c +++ b/dlls/gdi32/bitblt.c @@ -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; diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index 66c87ef9412..79220a5e1e0 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -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 ) diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 2f0a6b4c0d7..e1ba092a08e 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -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, diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c index 25ef85f2db5..61b318ce067 100644 --- a/dlls/gdi32/gdidc.c +++ b/dlls/gdi32/gdidc.c @@ -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.@) */ diff --git a/include/ntgdi.h b/include/ntgdi.h index cb7b9639e20..44a27878792 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -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 );