Jacek Caban : gdi32: Handle EMFs recording directly in LineTo implementation.

Alexandre Julliard julliard at winehq.org
Wed Jul 21 16:04:30 CDT 2021


Module: wine
Branch: master
Commit: 340a445289ed5777bfc177336fb6e315dfda273c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=340a445289ed5777bfc177336fb6e315dfda273c

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Jul 20 09:18:50 2021 +0200

gdi32: Handle EMFs recording directly in LineTo implementation.

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/enhmfdrv/dc.c       | 13 +------------
 dlls/gdi32/enhmfdrv/graphics.c | 28 +++++++++++++++-------------
 dlls/gdi32/enhmfdrv/init.c     |  1 +
 dlls/gdi32/gdi_private.h       | 12 ++++++++++--
 dlls/gdi32/gdidc.c             | 16 ++++++++++++++++
 dlls/gdi32/objects.c           |  2 +-
 include/ntgdi.h                |  1 +
 7 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/dlls/gdi32/enhmfdrv/dc.c b/dlls/gdi32/enhmfdrv/dc.c
index 9edd09a179e..79c3032daa6 100644
--- a/dlls/gdi32/enhmfdrv/dc.c
+++ b/dlls/gdi32/enhmfdrv/dc.c
@@ -734,17 +734,6 @@ static BOOL CDECL emfpathdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
             next->funcs->pExtTextOut( next, x, y, flags, rect, str, count, dx ));
 }
 
-/***********************************************************************
- *           emfpathdrv_LineTo
- */
-static BOOL CDECL emfpathdrv_LineTo( PHYSDEV dev, INT x, INT y )
-{
-    PHYSDEV emfdev = get_emfdev( dev );
-    PHYSDEV next = GET_NEXT_PHYSDEV( dev, pLineTo );
-
-    return (emfdev->funcs->pLineTo( emfdev, x, y ) && next->funcs->pLineTo( next, x, y ));
-}
-
 /***********************************************************************
  *           emfpathdrv_MoveTo
  */
@@ -953,7 +942,7 @@ static const struct gdi_dc_funcs emfpath_driver =
     NULL,                               /* pGradientFill */
     NULL,                               /* pIntersectClipRect */
     NULL,                               /* pInvertRgn */
-    emfpathdrv_LineTo,                  /* pLineTo */
+    NULL,                               /* pLineTo */
     NULL,                               /* pModifyWorldTransform */
     emfpathdrv_MoveTo,                  /* pMoveTo */
     NULL,                               /* pOffsetClipRgn */
diff --git a/dlls/gdi32/enhmfdrv/graphics.c b/dlls/gdi32/enhmfdrv/graphics.c
index f504aee8e36..8d6445779b9 100644
--- a/dlls/gdi32/enhmfdrv/graphics.c
+++ b/dlls/gdi32/enhmfdrv/graphics.c
@@ -133,23 +133,29 @@ BOOL CDECL EMFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
 }
 
 /***********************************************************************
- *           EMFDRV_LineTo
+ *           EMFDC_LineTo
  */
-BOOL CDECL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y )
+BOOL EMFDC_LineTo( DC_ATTR *dc_attr, INT x, INT y )
 {
-    EMFDRV_PDEVICE *physDev = get_emf_physdev( dev );
-    DC *dc = get_physdev_dc( dev );
-    POINT pt;
     EMRLINETO emr;
-    RECTL bounds;
 
     emr.emr.iType = EMR_LINETO;
     emr.emr.nSize = sizeof(emr);
     emr.ptl.x = x;
     emr.ptl.y = y;
+    return EMFDRV_WriteRecord( dc_attr->emf, &emr.emr );
+}
 
-    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
-    	return FALSE;
+
+/***********************************************************************
+ *           EMFDRV_LineTo
+ */
+BOOL CDECL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y )
+{
+    EMFDRV_PDEVICE *physDev = get_emf_physdev( dev );
+    DC *dc = get_physdev_dc( dev );
+    RECTL bounds;
+    POINT pt;
 
     pt = dc->attr->cur_pos;
 
@@ -157,14 +163,10 @@ BOOL CDECL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y )
     bounds.top    = min(y, pt.y);
     bounds.right  = max(x, pt.x);
     bounds.bottom = max(y, pt.y);
-
-    if(!physDev->path)
-        EMFDRV_UpdateBBox( dev, &bounds );
-
+    EMFDRV_UpdateBBox( &physDev->dev, &bounds );
     return TRUE;
 }
 
-
 /***********************************************************************
  *           EMFDRV_ArcChordPie
  */
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index 9a611e0f1bc..62e35fe4029 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -342,6 +342,7 @@ HDC WINAPI CreateEnhMetaFileW(
         free_dc_ptr( dc );
         return 0;
     }
+    dc->attr->emf = physDev;
     if(description) { /* App name\0Title\0\0 */
         length = lstrlenW(description);
 	length += lstrlenW(description + length + 1);
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 436846c5bd5..bb4504f4934 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -31,10 +31,15 @@
 void set_gdi_client_ptr( HGDIOBJ handle, void *ptr ) DECLSPEC_HIDDEN;
 void *get_gdi_client_ptr( HGDIOBJ handle, WORD type ) DECLSPEC_HIDDEN;
 
+static inline WORD gdi_handle_type( HGDIOBJ obj )
+{
+    unsigned int handle = HandleToULong( obj );
+    return (handle & NTGDI_HANDLE_TYPE_MASK) >> NTGDI_HANDLE_TYPE_SHIFT;
+}
+
 static inline BOOL is_meta_dc( HDC hdc )
 {
-    unsigned int handle = HandleToULong( hdc );
-    return (handle & NTGDI_HANDLE_TYPE_MASK) >> NTGDI_HANDLE_TYPE_SHIFT == NTGDI_OBJ_METADC;
+    return gdi_handle_type( hdc ) == NTGDI_OBJ_METADC;
 }
 
 extern BOOL METADC_Arc( HDC hdc, INT left, INT top, INT right, INT bottom,
@@ -46,4 +51,7 @@ extern BOOL METADC_MoveTo( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN;
 extern BOOL METADC_Pie( HDC hdc, INT left, INT top, INT right, INT bottom,
                         INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN;
 
+/* enhanced metafiles */
+extern BOOL EMFDC_LineTo( DC_ATTR *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN;
+
 #endif /* __WINE_GDI_PRIVATE_H */
diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c
index 01c9dfdf8c7..c011d66deb9 100644
--- a/dlls/gdi32/gdidc.c
+++ b/dlls/gdi32/gdidc.c
@@ -25,14 +25,30 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
 
+static DC_ATTR *get_dc_attr( HDC hdc )
+{
+    WORD type = gdi_handle_type( hdc );
+    DC_ATTR *dc_attr;
+    if ((type & 0x1f) != NTGDI_OBJ_DC || !(dc_attr = get_gdi_client_ptr( hdc, 0 )))
+    {
+        SetLastError( ERROR_INVALID_HANDLE );
+        return NULL;
+    }
+    return dc_attr;
+}
+
 /***********************************************************************
  *           LineTo    (GDI32.@)
  */
 BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
 {
+    DC_ATTR *dc_attr;
+
     TRACE( "%p, (%d, %d)\n", hdc, x, y );
 
     if (is_meta_dc( hdc )) return METADC_LineTo( hdc, x, y );
+    if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
+    if (dc_attr->emf && !EMFDC_LineTo( dc_attr, x, y )) return FALSE;
     return NtGdiLineTo( hdc, x, y );
 }
 
diff --git a/dlls/gdi32/objects.c b/dlls/gdi32/objects.c
index e5aafc1fed4..e614a9d6a52 100644
--- a/dlls/gdi32/objects.c
+++ b/dlls/gdi32/objects.c
@@ -70,7 +70,7 @@ void set_gdi_client_ptr( HGDIOBJ obj, void *ptr )
 void *get_gdi_client_ptr( HGDIOBJ obj, WORD type )
 {
     GDI_HANDLE_ENTRY *entry = handle_entry( obj );
-    if (!entry || entry->ExtType != type || !entry->UserPointer)
+    if (!entry || (type && entry->ExtType != type) || !entry->UserPointer)
         return NULL;
     return (void *)(UINT_PTR)entry->UserPointer;
 }
diff --git a/include/ntgdi.h b/include/ntgdi.h
index b03ffc0fea8..53915033c89 100644
--- a/include/ntgdi.h
+++ b/include/ntgdi.h
@@ -89,6 +89,7 @@ enum
 typedef struct DC_ATTR
 {
     POINT     cur_pos;
+    void     *emf;
 } DC_ATTR;
 
 #endif /* __WINESRC__ */




More information about the wine-cvs mailing list