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