From 4396a79edebc381bb5b394c0a1f315efb07da372 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 24 Oct 2012 18:24:03 +0200 Subject: [PATCH] gdi32: Add a DC hook flag to reset the DC state. --- dlls/gdi32/dc.c | 122 ++++++++++++++++++++++++++++---------- dlls/gdi32/tests/dc.c | 3 - dlls/user32/painting.c | 16 +---- include/wine/gdi_driver.h | 1 + 4 files changed, 94 insertions(+), 48 deletions(-) diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 030304cface..b59c154641b 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -70,6 +70,56 @@ static inline DC *get_dc_obj( HDC hdc ) } +/*********************************************************************** + * set_initial_dc_state + */ +static void set_initial_dc_state( DC *dc ) +{ + dc->wndOrgX = 0; + dc->wndOrgY = 0; + dc->wndExtX = 1; + dc->wndExtY = 1; + dc->vportOrgX = 0; + dc->vportOrgY = 0; + dc->vportExtX = 1; + dc->vportExtY = 1; + dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */ + dc->layout = 0; + dc->font_code_page = CP_ACP; + dc->ROPmode = R2_COPYPEN; + dc->polyFillMode = ALTERNATE; + dc->stretchBltMode = BLACKONWHITE; + dc->relAbsMode = ABSOLUTE; + dc->backgroundMode = OPAQUE; + dc->backgroundColor = RGB( 255, 255, 255 ); + dc->dcBrushColor = RGB( 255, 255, 255 ); + dc->dcPenColor = RGB( 0, 0, 0 ); + dc->textColor = RGB( 0, 0, 0 ); + dc->brushOrgX = 0; + dc->brushOrgY = 0; + dc->mapperFlags = 0; + dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP; + dc->charExtra = 0; + dc->breakExtra = 0; + dc->breakRem = 0; + dc->MapMode = MM_TEXT; + dc->GraphicsMode = GM_COMPATIBLE; + dc->CursPosX = 0; + dc->CursPosY = 0; + dc->ArcDirection = AD_COUNTERCLOCKWISE; + dc->xformWorld2Wnd.eM11 = 1.0f; + dc->xformWorld2Wnd.eM12 = 0.0f; + dc->xformWorld2Wnd.eM21 = 0.0f; + dc->xformWorld2Wnd.eM22 = 1.0f; + dc->xformWorld2Wnd.eDx = 0.0f; + dc->xformWorld2Wnd.eDy = 0.0f; + dc->xformWorld2Vport = dc->xformWorld2Wnd; + dc->xformVport2World = dc->xformWorld2Wnd; + dc->vport2WorldValid = TRUE; + + reset_bounds( &dc->bounds ); +} + /*********************************************************************** * alloc_dc_ptr */ @@ -84,40 +134,12 @@ DC *alloc_dc_ptr( WORD magic ) dc->module = gdi32_module; dc->thread = GetCurrentThreadId(); dc->refcount = 1; - dc->wndExtX = 1; - dc->wndExtY = 1; - dc->vportExtX = 1; - dc->vportExtY = 1; - dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */ dc->hPen = GDI_inc_ref_count( GetStockObject( BLACK_PEN )); dc->hBrush = GDI_inc_ref_count( GetStockObject( WHITE_BRUSH )); dc->hFont = GDI_inc_ref_count( GetStockObject( SYSTEM_FONT )); dc->hPalette = GetStockObject( DEFAULT_PALETTE ); - dc->font_code_page = CP_ACP; - dc->ROPmode = R2_COPYPEN; - dc->polyFillMode = ALTERNATE; - dc->stretchBltMode = BLACKONWHITE; - dc->relAbsMode = ABSOLUTE; - dc->backgroundMode = OPAQUE; - dc->backgroundColor = RGB( 255, 255, 255 ); - dc->dcBrushColor = RGB( 255, 255, 255 ); - dc->dcPenColor = RGB( 0, 0, 0 ); - dc->textColor = RGB( 0, 0, 0 ); - dc->textAlign = TA_LEFT | TA_TOP | TA_NOUPDATECP; - dc->MapMode = MM_TEXT; - dc->GraphicsMode = GM_COMPATIBLE; - dc->ArcDirection = AD_COUNTERCLOCKWISE; - dc->xformWorld2Wnd.eM11 = 1.0f; - dc->xformWorld2Wnd.eM12 = 0.0f; - dc->xformWorld2Wnd.eM21 = 0.0f; - dc->xformWorld2Wnd.eM22 = 1.0f; - dc->xformWorld2Wnd.eDx = 0.0f; - dc->xformWorld2Wnd.eDy = 0.0f; - dc->xformWorld2Vport = dc->xformWorld2Wnd; - dc->xformVport2World = dc->xformWorld2Wnd; - dc->vport2WorldValid = TRUE; - reset_bounds( &dc->bounds ); + set_initial_dc_state( dc ); if (!(dc->hSelf = alloc_gdi_handle( dc, magic, &dc_funcs ))) { @@ -519,6 +541,44 @@ BOOL nulldrv_RestoreDC( PHYSDEV dev, INT level ) } +/*********************************************************************** + * reset_dc_state + */ +static BOOL reset_dc_state( HDC hdc ) +{ + DC *dc, *dcs, *next; + + if (!(dc = get_dc_ptr( hdc ))) return FALSE; + + set_initial_dc_state( dc ); + SetBkColor( hdc, RGB( 255, 255, 255 )); + SetTextColor( hdc, RGB( 0, 0, 0 )); + SelectObject( hdc, GetStockObject( WHITE_BRUSH )); + SelectObject( hdc, GetStockObject( SYSTEM_FONT )); + SelectObject( hdc, GetStockObject( BLACK_PEN )); + SetVirtualResolution( hdc, 0, 0, 0, 0 ); + GDISelectPalette( hdc, GetStockObject( DEFAULT_PALETTE ), FALSE ); + SetBoundsRect( hdc, NULL, DCB_DISABLE ); + AbortPath( hdc ); + + if (dc->hClipRgn) DeleteObject( dc->hClipRgn ); + if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn ); + dc->hClipRgn = 0; + dc->hMetaRgn = 0; + update_dc_clipping( dc ); + + for (dcs = dc->saved_dc; dcs; dcs = next) + { + next = dcs->saved_dc; + free_dc_state( dcs ); + } + dc->saved_dc = NULL; + dc->saveLevel = 0; + release_dc_ptr( dc ); + return TRUE; +} + + /*********************************************************************** * SaveDC (GDI32.@) */ @@ -1217,8 +1277,6 @@ WORD WINAPI SetHookFlags( HDC hdc, WORD flags ) if (!dc) return 0; - /* "Undocumented Windows" info is slightly confusing. */ - TRACE("hDC %p, flags %04x\n",hdc,flags); if (flags & DCHF_INVALIDATEVISRGN) @@ -1227,6 +1285,8 @@ WORD WINAPI SetHookFlags( HDC hdc, WORD flags ) ret = InterlockedExchange( &dc->dirty, 0 ); GDI_ReleaseObj( hdc ); + + if (flags & DCHF_RESETDC) ret = reset_dc_state( hdc ); return ret; } diff --git a/dlls/gdi32/tests/dc.c b/dlls/gdi32/tests/dc.c index e2860449a16..8baacc2c1b0 100644 --- a/dlls/gdi32/tests/dc.c +++ b/dlls/gdi32/tests/dc.c @@ -124,10 +124,7 @@ static void test_savedc_2(void) rc_clip.left, rc_clip.top, rc_clip.right, rc_clip.bottom); ret = SaveDC(hdc); -todo_wine -{ ok(ret == 1, "ret = %d\n", ret); -} ret = IntersectClipRect(hdc, 0, 0, 50, 50); if (ret == COMPLEXREGION) diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index e9705fe0eee..b2ddfe69161 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -177,16 +177,6 @@ static void update_visible_region( struct dce *dce ) } -/*********************************************************************** - * reset_dce_attrs - */ -static void reset_dce_attrs( struct dce *dce ) -{ - RestoreDC( dce->hdc, 1 ); /* initial save level is always 1 */ - SaveDC( dce->hdc ); /* save the state again for next time */ -} - - /*********************************************************************** * release_dce */ @@ -235,8 +225,6 @@ static struct dce *alloc_dce(void) HeapFree( GetProcessHeap(), 0, dce ); return 0; } - SaveDC( dce->hdc ); - dce->hwnd = 0; dce->clip_rgn = 0; dce->flags = 0; @@ -352,7 +340,7 @@ void free_dce( struct dce *dce, HWND hwnd ) if (!--dce->count) { /* turn it into a cache entry */ - reset_dce_attrs( dce ); + SetHookFlags( dce->hdc, DCHF_RESETDC ); release_dce( dce ); dce->flags |= DCX_CACHE; } @@ -470,7 +458,7 @@ static INT release_dc( HWND hwnd, HDC hdc, BOOL end_paint ) dce = (struct dce *)GetDCHook( hdc, NULL ); if (dce && dce->count) { - if (!(dce->flags & DCX_NORESETATTRS)) reset_dce_attrs( dce ); + if (!(dce->flags & DCX_NORESETATTRS)) SetHookFlags( dce->hdc, DCHF_RESETDC ); if (end_paint || (dce->flags & DCX_CACHE)) delete_clip_rgn( dce ); if (dce->flags & DCX_CACHE) dce->count = 0; ret = TRUE; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 3d4e6c5604b..1f6376cecd5 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -265,6 +265,7 @@ static inline ULONG window_surface_release( struct window_surface *surface ) #define DCHC_DELETEDC 0x0002 #define DCHF_INVALIDATEVISRGN 0x0001 #define DCHF_VALIDATEVISRGN 0x0002 +#define DCHF_RESETDC 0x0004 /* Wine extension */ typedef BOOL (CALLBACK *DCHOOKPROC)(HDC,WORD,DWORD_PTR,LPARAM);