diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 088f6c71e65..f25eb8d2d20 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -79,7 +79,8 @@ DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic ) dc->funcs = funcs; dc->nulldrv.funcs = &null_driver; - dc->physDev = NULL; + dc->nulldrv.next = NULL; + dc->physDev = &dc->nulldrv; dc->thread = GetCurrentThreadId(); dc->refcount = 1; dc->dirty = 0; @@ -228,6 +229,34 @@ void update_dc( DC *dc ) } +/*********************************************************************** + * push_dc_driver + * + * Push a driver on top of the DC driver stack. + */ +void push_dc_driver( DC * dc, PHYSDEV physdev ) +{ + physdev->next = dc->physDev; + physdev->hdc = dc->hSelf; + dc->physDev = physdev; + dc->funcs = physdev->funcs; +} + + +/*********************************************************************** + * pop_dc_driver + * + * Pop the top driver from the DC driver stack. + */ +void pop_dc_driver( DC * dc, PHYSDEV physdev ) +{ + assert( physdev == dc->physDev ); + assert( physdev != &dc->nulldrv ); + dc->physDev = physdev->next; + dc->funcs = dc->physDev->funcs; +} + + /*********************************************************************** * DC_DeleteObject */ @@ -633,6 +662,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, { HDC hdc; DC * dc; + PHYSDEV physdev; const DC_FUNCTIONS *funcs; WCHAR buf[300]; @@ -663,14 +693,15 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf ); if (dc->funcs->pCreateDC && - !dc->funcs->pCreateDC( hdc, &dc->physDev, buf, device, output, initData )) + !dc->funcs->pCreateDC( hdc, &physdev, buf, device, output, initData )) { WARN("creation aborted by device\n" ); goto error; } - dc->physDev->funcs = funcs; - dc->physDev->hdc = hdc; + physdev->funcs = funcs; + push_dc_driver( dc, physdev ); + dc->vis_rect.left = 0; dc->vis_rect.top = 0; dc->vis_rect.right = GetDeviceCaps( hdc, DESKTOPHORZRES ); @@ -782,21 +813,20 @@ HDC WINAPI CreateCompatibleDC( HDC hdc ) dc->vis_rect.bottom = 1; if (!(dc->hVisRgn = CreateRectRgn( 0, 0, 1, 1 ))) goto error; /* default bitmap is 1x1 */ - /* Copy the driver-specific physical device info into - * the new DC. The driver may use this read-only info - * while creating the compatible DC below. */ - dc->physDev = physDev; ret = dc->hSelf; + /* Pass the driver-specific physical device info into + * the new DC. The driver may use this read-only info + * while creating the compatible DC. */ if (dc->funcs->pCreateDC && - !dc->funcs->pCreateDC( dc->hSelf, &dc->physDev, NULL, NULL, NULL, NULL )) + !dc->funcs->pCreateDC( dc->hSelf, &physDev, NULL, NULL, NULL, NULL )) { WARN("creation aborted by device\n"); goto error; } - dc->physDev->funcs = funcs; - dc->physDev->hdc = hdc; + physDev->funcs = funcs; + push_dc_driver( dc, physDev ); DC_InitDC( dc ); release_dc_ptr( dc ); return ret; diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c index efa91eed8c3..241bd7e4a59 100644 --- a/dlls/gdi32/enhmfdrv/init.c +++ b/dlls/gdi32/enhmfdrv/init.c @@ -319,9 +319,8 @@ HDC WINAPI CreateEnhMetaFileW( free_dc_ptr( dc ); return 0; } - dc->physDev = (PHYSDEV)physDev; physDev->dev.funcs = &EMFDRV_Funcs; - physDev->dev.hdc = dc->hSelf; + push_dc_driver( dc, &physDev->dev ); physDev->hdc = dc->hSelf; if(description) { /* App name\0Title\0\0 */ diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index efa61a092d7..7b72c45c710 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -75,6 +75,7 @@ typedef struct tagGDIOBJHDR typedef struct gdi_physdev { const struct tagDC_FUNCS *funcs; + struct gdi_physdev *next; HDC hdc; } *PHYSDEV; @@ -377,6 +378,8 @@ extern BOOL free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; extern DC *get_dc_ptr( HDC hdc ) DECLSPEC_HIDDEN; extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; extern void update_dc( DC *dc ) DECLSPEC_HIDDEN; +extern void push_dc_driver( DC * dc, PHYSDEV physdev ) DECLSPEC_HIDDEN; +extern void pop_dc_driver( DC * dc, PHYSDEV physdev ) DECLSPEC_HIDDEN; extern void DC_InitDC( DC * dc ) DECLSPEC_HIDDEN; extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN; extern INT save_dc_state( HDC hdc ) DECLSPEC_HIDDEN; @@ -395,7 +398,14 @@ extern const DC_FUNCTIONS *DRIVER_get_display_driver(void) DECLSPEC_HIDDEN; extern const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN; extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN; -#define GET_DC_PHYSDEV(dc,func) ((dc)->physDev->funcs->func ? (dc)->physDev : &(dc)->nulldrv) +static inline PHYSDEV get_physdev_entry_point( PHYSDEV dev, size_t offset ) +{ + while (!((void **)dev->funcs)[offset / sizeof(void *)]) dev = dev->next; + return dev; +} + +#define GET_DC_PHYSDEV(dc,func) get_physdev_entry_point( (dc)->physDev, FIELD_OFFSET(DC_FUNCTIONS,func)) +#define GET_NEXT_PHYSDEV(dev,func) get_physdev_entry_point( (dev)->next, FIELD_OFFSET(DC_FUNCTIONS,func)) /* enhmetafile.c */ extern HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c index 4659e7305ad..3bb815b4db5 100644 --- a/dlls/gdi32/mfdrv/init.c +++ b/dlls/gdi32/mfdrv/init.c @@ -171,9 +171,8 @@ static DC *MFDRV_AllocMetaFile(void) free_dc_ptr( dc ); return NULL; } - dc->physDev = (PHYSDEV)physDev; physDev->dev.funcs = &MFDRV_Funcs; - physDev->dev.hdc = dc->hSelf; + push_dc_driver( dc, &physDev->dev ); physDev->hdc = dc->hSelf; if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) ))) diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 62f9ccccb3e..c6c7571b2c1 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -353,7 +353,7 @@ typedef struct { typedef struct { - void *reserved[2]; /* reserved for gdi */ + void *reserved[3]; /* reserved for gdi */ HDC hdc; PSFONT font; /* Current PS font */ DOWNLOAD *downloaded_fonts; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index da59d7e370c..6048096c78d 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -144,7 +144,7 @@ struct xrender_info; /* X physical device */ typedef struct { - void *reserved[2]; /* reserved for gdi */ + void *reserved[3]; /* reserved for gdi */ HDC hdc; GC gc; /* X Window GC */ Drawable drawable;