[PATCH 1/2] gdi32: Cache the device caps from the reference dc, since the dc may become invalid.

Huw Davies huw at codeweavers.com
Tue Aug 22 06:42:34 CDT 2017


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/gdi32/enhmfdrv/dc.c             |  4 +++-
 dlls/gdi32/enhmfdrv/enhmetafiledrv.h |  3 +--
 dlls/gdi32/enhmfdrv/init.c           | 42 ++++++++++++++++++++++++++++--------
 3 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/dlls/gdi32/enhmfdrv/dc.c b/dlls/gdi32/enhmfdrv/dc.c
index 531392b456..37180fec9e 100644
--- a/dlls/gdi32/enhmfdrv/dc.c
+++ b/dlls/gdi32/enhmfdrv/dc.c
@@ -510,7 +510,9 @@ INT EMFDRV_GetDeviceCaps(PHYSDEV dev, INT cap)
 {
     EMFDRV_PDEVICE *physDev = get_emf_physdev( dev );
 
-    return GetDeviceCaps( physDev->ref_dc, cap );
+    if (cap >= 0 && cap < sizeof(physDev->dev_caps) / sizeof(physDev->dev_caps[0]))
+        return physDev->dev_caps[cap];
+    return 0;
 }
 
 
diff --git a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
index 547c411bc8..1763781d39 100644
--- a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
+++ b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
@@ -40,10 +40,9 @@ typedef struct
     HANDLE     hFile;              /* Handle for disk based MetaFile */
     HBRUSH     dc_brush;
     HPEN       dc_pen;
-    HDC        ref_dc;             /* Reference device */
-    HDC        screen_dc;          /* Screen DC if no reference device specified */
     INT        restoring;          /* RestoreDC counter */
     BOOL       path;
+    INT        dev_caps[COLORMGMTCAPS + 1];
 } EMFDRV_PDEVICE;
 
 static inline EMFDRV_PDEVICE *get_emf_physdev( PHYSDEV dev )
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index d241f217c6..6f9a95632c 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -301,6 +301,23 @@ HDC WINAPI CreateEnhMetaFileA(
     return hReturnDC;
 }
 
+static inline BOOL devcap_is_valid( int cap )
+{
+    if (cap >= 0 && cap <= ASPECTXY) return !(cap & 1);
+    if (cap >= PHYSICALWIDTH && cap <= COLORMGMTCAPS) return TRUE;
+    switch (cap)
+    {
+    case LOGPIXELSX:
+    case LOGPIXELSY:
+    case CAPS1:
+    case SIZEPALETTE:
+    case NUMRESERVED:
+    case COLORRES:
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /**********************************************************************
  *          CreateEnhMetaFileW   (GDI32.@)
  */
@@ -312,12 +329,13 @@ HDC WINAPI CreateEnhMetaFileW(
     )
 {
     static const WCHAR displayW[] = {'D','I','S','P','L','A','Y',0};
-    HDC ret;
+    HDC ret, ref_dc;
     DC *dc;
     EMFDRV_PDEVICE *physDev;
     HANDLE hFile;
     DWORD size = 0, length = 0;
     DWORD bytes_written;
+    int cap;
 
     TRACE("(%p %s %s %s)\n", hdc, debugstr_w(filename), wine_dbgstr_rect(rect), debugstr_w(description) );
 
@@ -350,13 +368,20 @@ HDC WINAPI CreateEnhMetaFileW(
     physDev->hFile = 0;
     physDev->dc_brush = 0;
     physDev->dc_pen = 0;
-    physDev->screen_dc = 0;
     physDev->restoring = 0;
     physDev->path = FALSE;
+
     if (hdc)  /* if no ref, use current display */
-        physDev->ref_dc = hdc;
+        ref_dc = hdc;
     else
-        physDev->ref_dc = physDev->screen_dc = CreateDCW( displayW, NULL, NULL, NULL );
+        ref_dc = CreateDCW( displayW, NULL, NULL, NULL );
+
+    memset( physDev->dev_caps, 0, sizeof(physDev->dev_caps) );
+    for (cap = 0; cap < sizeof(physDev->dev_caps) / sizeof(physDev->dev_caps[0]); cap++)
+        if (devcap_is_valid( cap ))
+            physDev->dev_caps[cap] = GetDeviceCaps( ref_dc, cap );
+
+    if (!hdc) DeleteDC( ref_dc );
 
     SetVirtualResolution(physDev->dev.hdc, 0, 0, 0, 0);
 
@@ -390,12 +415,12 @@ HDC WINAPI CreateEnhMetaFileW(
     physDev->emh->nPalEntries = 0; /* I guess this should start at 0 */
 
     /* Size in pixels */
-    physDev->emh->szlDevice.cx = GetDeviceCaps( physDev->ref_dc, HORZRES );
-    physDev->emh->szlDevice.cy = GetDeviceCaps( physDev->ref_dc, VERTRES );
+    physDev->emh->szlDevice.cx = physDev->dev_caps[HORZRES];
+    physDev->emh->szlDevice.cy = physDev->dev_caps[VERTRES];
 
     /* Size in millimeters */
-    physDev->emh->szlMillimeters.cx = GetDeviceCaps( physDev->ref_dc, HORZSIZE );
-    physDev->emh->szlMillimeters.cy = GetDeviceCaps( physDev->ref_dc, VERTSIZE );
+    physDev->emh->szlMillimeters.cx = physDev->dev_caps[HORZSIZE];
+    physDev->emh->szlMillimeters.cy = physDev->dev_caps[VERTSIZE];
 
     /* Size in micrometers */
     physDev->emh->szlMicrometers.cx = physDev->emh->szlMillimeters.cx * 1000;
@@ -457,7 +482,6 @@ HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */
 
     if (physDev->dc_brush) DeleteObject( physDev->dc_brush );
     if (physDev->dc_pen) DeleteObject( physDev->dc_pen );
-    if (physDev->screen_dc) DeleteDC( physDev->screen_dc );
 
     emr.emr.iType = EMR_EOF;
     emr.emr.nSize = sizeof(emr);
-- 
2.12.0




More information about the wine-patches mailing list