Jacek Caban : gdi32: Use EMR_PLGBLT to record PlgBlt.
Alexandre Julliard
julliard at winehq.org
Thu Sep 9 15:42:31 CDT 2021
Module: wine
Branch: master
Commit: 03ec246e5282ab3f76e1df312272598eeba69260
URL: https://source.winehq.org/git/wine.git/?a=commit;h=03ec246e5282ab3f76e1df312272598eeba69260
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu Sep 9 14:01:02 2021 +0200
gdi32: Use EMR_PLGBLT to record PlgBlt.
And use NtGdiPlgBlt.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 );
More information about the wine-cvs
mailing list