gdi32: Cache the device caps from the reference dc, since the dc may become invalid.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2017-08-22 12:42:34 +01:00 committed by Alexandre Julliard
parent e8ef521c83
commit 9ea33ed00a
3 changed files with 37 additions and 12 deletions

View file

@ -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;
}

View file

@ -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 )

View file

@ -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);