From dcf7d7d5c4f550fa255b33adc0542f8a1934c48f Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 9 Sep 2021 14:00:56 +0200 Subject: [PATCH] gdi32: Use EMR_MASKBLT to record MaskBlt. And use NtGdiMaskBlt. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/bitblt.c | 29 ++++++------ dlls/gdi32/emfdc.c | 96 ++++++++++++++++++++++++++++++++++++++++ dlls/gdi32/gdi_private.h | 3 ++ dlls/gdi32/gdidc.c | 17 +++++++ include/ntgdi.h | 3 ++ 5 files changed, 134 insertions(+), 14 deletions(-) diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c index aa1ba0dda1e..a1b4b6fa393 100644 --- a/dlls/gdi32/bitblt.c +++ b/dlls/gdi32/bitblt.c @@ -567,7 +567,7 @@ BOOL WINAPI NtGdiPatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWOR /*********************************************************************** - * BitBlt (GDI32.@) + * NtGdiBitBlt (win32u.@) */ BOOL WINAPI NtGdiBitBlt( HDC hdc_dst, INT x_dst, INT y_dst, INT width, INT height, HDC hdc_src, INT x_src, INT y_src, DWORD rop, DWORD bk_color, FLONG fl ) @@ -638,12 +638,11 @@ BOOL WINAPI NtGdiStretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT h #define BKGND_ROP3(ROP4) (ROP3Table[((ROP4)>>24) & 0xFF]) /*********************************************************************** - * MaskBlt [GDI32.@] + * NtGdiMaskBlt (win32u.@) */ -BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest, - INT nWidth, INT nHeight, HDC hdcSrc, - INT nXSrc, INT nYSrc, HBITMAP hbmMask, - INT xMask, INT yMask, DWORD dwRop) +BOOL WINAPI NtGdiMaskBlt( HDC hdcDest, INT nXDest, INT nYDest, INT nWidth, INT nHeight, + HDC hdcSrc, INT nXSrc, INT nYSrc, HBITMAP hbmMask, + INT xMask, INT yMask, DWORD dwRop, DWORD bk_color ) { HBITMAP hBitmap1, hOldBitmap1, hBitmap2, hOldBitmap2; HDC hDC1, hDC2; @@ -782,9 +781,10 @@ BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest, }; if (!hbmMask) - return BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop)); + return NtGdiBitBlt( hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, + nXSrc, nYSrc, FRGND_ROP3(dwRop), bk_color, 0 ); - hbrMask = CreatePatternBrush(hbmMask); + hbrMask = NtGdiCreatePatternBrushInternal( hbmMask, FALSE, FALSE ); hbrDst = NtGdiSelectBrush( hdcDest, get_stock_object(NULL_BRUSH) ); /* make bitmap */ @@ -793,9 +793,9 @@ BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest, hOldBitmap1 = NtGdiSelectBitmap(hDC1, hBitmap1); /* draw using bkgnd rop */ - BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY); + NtGdiBitBlt( hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0 ); hbrTmp = NtGdiSelectBrush(hDC1, hbrDst); - BitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop)); + NtGdiBitBlt( hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, BKGND_ROP3(dwRop), 0, 0 ); NtGdiSelectBrush(hDC1, hbrTmp); /* make bitmap */ @@ -804,18 +804,19 @@ BOOL WINAPI MaskBlt(HDC hdcDest, INT nXDest, INT nYDest, hOldBitmap2 = NtGdiSelectBitmap(hDC2, hBitmap2); /* draw using foregnd rop */ - BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY); + NtGdiBitBlt( hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0 ); hbrTmp = NtGdiSelectBrush(hDC2, hbrDst); - BitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop)); + NtGdiBitBlt( hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0, 0 ); /* combine both using the mask as a pattern brush */ NtGdiSelectBrush(hDC2, hbrMask); SetBrushOrgEx(hDC2, -xMask, -yMask, NULL); - BitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744 ); /* (D & P) | (S & ~P) */ + /* (D & P) | (S & ~P) */ + NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDC1, 0, 0, 0xac0744, 0, 0 ); NtGdiSelectBrush(hDC2, hbrTmp); /* blit to dst */ - BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY); + NtGdiBitBlt( hdcDest, nXDest, nYDest, nWidth, nHeight, hDC2, 0, 0, SRCCOPY, bk_color, 0 ); /* restore all objects */ NtGdiSelectBrush(hdcDest, hbrDst); diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index 84069bdba3a..66c87ef9412 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -1388,6 +1388,102 @@ BOOL EMFDC_StretchBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, IN height_src, rop, EMR_STRETCHBLT ); } +BOOL EMFDC_MaskBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, HBITMAP mask, + INT x_mask, INT y_mask, DWORD rop ) +{ + 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; + EMRMASKBLT *emr = NULL; + BITMAPINFO *bmi; + HDC blit_dc, mask_dc = NULL; + BOOL ret = FALSE; + + if (!rop_uses_src( rop )) + return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width_dst, height_dst, rop ); + + 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_MASKBLT; + emr->emr.nSize = size; + emr->rclBounds.left = x_dst; + emr->rclBounds.top = y_dst; + emr->rclBounds.right = x_dst + width_dst - 1; + emr->rclBounds.bottom = y_dst + height_dst - 1; + emr->xDest = x_dst; + emr->yDest = y_dst; + emr->cxDest = width_dst; + emr->cyDest = height_dst; + emr->dwRop = rop; + emr->xSrc = x_src; + emr->ySrc = y_src; + 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 2dddf361d5b..2f0a6b4c0d7 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -203,6 +203,9 @@ extern BOOL EMFDC_IntersectClipRect( DC_ATTR *dc_attr, INT left, INT top, INT ri INT bottom ) DECLSPEC_HIDDEN; extern BOOL EMFDC_InvertRgn( DC_ATTR *dc_attr, HRGN hrgn ) DECLSPEC_HIDDEN; extern BOOL EMFDC_LineTo( DC_ATTR *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_MaskBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, HBITMAP mask, + INT x_mask, INT y_mask, DWORD rop ) DECLSPEC_HIDDEN; extern BOOL EMFDC_ModifyWorldTransform( DC_ATTR *dc_attr, const XFORM *xform, DWORD mode ) DECLSPEC_HIDDEN; extern BOOL EMFDC_MoveTo( DC_ATTR *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c index d5645595984..25ef85f2db5 100644 --- a/dlls/gdi32/gdidc.c +++ b/dlls/gdi32/gdidc.c @@ -1499,6 +1499,23 @@ BOOL WINAPI StretchBlt( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height height_src, rop, 0 /* FIXME */ ); } +/*********************************************************************** + * MaskBlt [GDI32.@] + */ +BOOL WINAPI MaskBlt( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, HBITMAP mask, + INT x_mask, INT y_mask, DWORD rop ) +{ + DC_ATTR *dc_attr; + + if (!(dc_attr = get_dc_attr( hdc ))) return FALSE; + if (dc_attr->emf && !EMFDC_MaskBlt( dc_attr, x_dst, y_dst, width_dst, height_dst, + hdc_src, x_src, y_src, mask, x_mask, y_mask, rop )) + return FALSE; + return NtGdiMaskBlt( hdc, x_dst, y_dst, width_dst, height_dst, hdc_src, x_src, y_src, + mask, x_mask, y_mask, rop, 0 /* FIXME */ ); +} + /****************************************************************************** * GdiAlphaBlend (GDI32.@) */ diff --git a/include/ntgdi.h b/include/ntgdi.h index 9e07268a307..cb7b9639e20 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -344,6 +344,9 @@ BOOL WINAPI NtGdiFontIsLinked( HDC hdc ); INT WINAPI NtGdiIntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom ); BOOL WINAPI NtGdiInvertRgn( HDC hdc, HRGN hrgn ); BOOL WINAPI NtGdiLineTo( HDC hdc, INT x, INT y ); +BOOL WINAPI NtGdiMaskBlt( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, HBITMAP mask, + INT x_mask, INT y_mask, DWORD rop, DWORD bk_color ); BOOL WINAPI NtGdiModifyWorldTransform( HDC hdc, const XFORM *xform, DWORD mode ); BOOL WINAPI NtGdiMoveTo( HDC hdc, INT x, INT y, POINT *pt ); INT WINAPI NtGdiOffsetClipRgn( HDC hdc, INT x, INT y );