From: Huw Davies Subject: [PATCH 1/2] gdi32: Cache the device caps from the reference dc, since the dc may become invalid. Message-Id: <20170822114235.32517-1-huw@codeweavers.com> Date: Tue, 22 Aug 2017 12:42:34 +0100 Signed-off-by: Huw Davies --- 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