gdi32: Use EMR_MASKBLT to record MaskBlt.

And use NtGdiMaskBlt.

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:00:56 +02:00 committed by Alexandre Julliard
parent 839a951f67
commit dcf7d7d5c4
5 changed files with 134 additions and 14 deletions

View file

@ -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);

View file

@ -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 )

View file

@ -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;

View file

@ -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.@)
*/

View file

@ -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 );