gdi32: Push a path driver on the DC stack when a path is opened.

This commit is contained in:
Alexandre Julliard 2011-10-24 18:13:21 +02:00
parent 97a261d573
commit 8a7bf0a2ab
4 changed files with 274 additions and 51 deletions

View File

@ -675,7 +675,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
HGDIOBJ ret;
BITMAPOBJ *bitmap;
DC *dc;
PHYSDEV physdev = NULL, old_physdev = NULL;
PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
if (!(dc = get_dc_ptr( hdc ))) return 0;
@ -701,6 +701,8 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
goto done;
}
if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
if(old_physdev == dc->dibdrv)
old_physdev = pop_dc_driver( &dc->physDev );
@ -752,6 +754,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
if (old_physdev && old_physdev == dc->dibdrv)
push_dc_driver( &dc->physDev, old_physdev, old_physdev->funcs );
}
if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
release_dc_ptr( dc );
return ret;
}

View File

@ -416,8 +416,6 @@ INT nulldrv_SaveDC( PHYSDEV dev )
newdc->BoundsRect = dc->BoundsRect;
newdc->gdiFont = dc->gdiFont;
PATH_InitGdiPath( &newdc->path );
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
newdc->hVisRgn = 0;
@ -437,7 +435,7 @@ INT nulldrv_SaveDC( PHYSDEV dev )
/* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
if (!PATH_AssignGdiPath( &newdc->path, &dc->path ))
if (!PATH_SavePath( newdc, dc ))
{
release_dc_ptr( dc );
free_dc_state( newdc );
@ -468,7 +466,7 @@ BOOL nulldrv_RestoreDC( PHYSDEV dev, INT level )
/* restore the state */
if (!PATH_AssignGdiPath( &dc->path, &dcs->path )) return FALSE;
if (!PATH_RestorePath( dc, dcs )) return FALSE;
dc->flags = dcs->flags;
dc->layout = dcs->layout;
@ -799,6 +797,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
free_dc_state( dcs );
}
AbortPath( hdc );
SelectObject( hdc, GetStockObject(BLACK_PEN) );
SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
SelectObject( hdc, GetStockObject(SYSTEM_FONT) );

View File

@ -270,6 +270,7 @@ extern DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struc
/* driver.c */
extern const struct gdi_dc_funcs null_driver DECLSPEC_HIDDEN;
extern const struct gdi_dc_funcs dib_driver DECLSPEC_HIDDEN;
extern const struct gdi_dc_funcs path_driver DECLSPEC_HIDDEN;
extern const struct gdi_dc_funcs *font_driver DECLSPEC_HIDDEN;
extern const struct gdi_dc_funcs *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN;
extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN;
@ -321,7 +322,8 @@ extern METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mr, LPCVOID filename, BOO
extern void PATH_InitGdiPath(GdiPath *pPath) DECLSPEC_HIDDEN;
extern void PATH_DestroyGdiPath(GdiPath *pPath) DECLSPEC_HIDDEN;
extern BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc) DECLSPEC_HIDDEN;
extern BOOL PATH_SavePath( DC *dst, DC *src ) DECLSPEC_HIDDEN;
extern BOOL PATH_RestorePath( DC *dst, DC *src ) DECLSPEC_HIDDEN;
extern BOOL PATH_MoveTo(DC *dc) DECLSPEC_HIDDEN;
extern BOOL PATH_LineTo(DC *dc, INT x, INT y) DECLSPEC_HIDDEN;

View File

@ -4,6 +4,7 @@
* Copyright 1997, 1998 Martin Boehme
* 1999 Huw D M Davies
* Copyright 2005 Dmitry Timoshkov
* Copyright 2011 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -69,18 +70,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
* PT_MOVETO. Note that this is not the same as the definition of a figure;
* a figure can contain several strokes.
*
* I modified the drawing functions (MoveTo, LineTo etc.) to test whether
* the path is open and to call the corresponding function in path.c if this
* is the case. A more elegant approach would be to modify the function
* pointers in the DC_FUNCTIONS structure; however, this would be a lot more
* complex. Also, the performance degradation caused by my approach in the
* case where no path is open is so small that it cannot be measured.
*
* Martin Boehme
*/
/* FIXME: A lot of stuff isn't implemented yet. There is much more to come. */
#define NUM_ENTRIES_INITIAL 16 /* Initial size of points / flags arrays */
#define GROW_FACTOR_NUMER 2 /* Numerator of grow factor for the array */
#define GROW_FACTOR_DENOM 1 /* Denominator of grow factor */
@ -92,6 +84,25 @@ typedef struct tagFLOAT_POINT
} FLOAT_POINT;
struct path_physdev
{
struct gdi_physdev dev;
GdiPath *path;
};
static inline struct path_physdev *get_path_physdev( PHYSDEV dev )
{
return (struct path_physdev *)dev;
}
static inline void pop_path_driver( DC *dc )
{
PHYSDEV dev = pop_dc_driver( &dc->physDev );
assert( dev->funcs == &path_driver );
HeapFree( GetProcessHeap(), 0, dev );
}
/* Performs a world-to-viewport transformation on the specified point (which
* is in floating point format).
*/
@ -219,6 +230,35 @@ static BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint, BYTE flags)
return TRUE;
}
/* PATH_AssignGdiPath
*
* Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is
* performed, i.e. the contents of the pPoints and pFlags arrays are copied,
* not just the pointers. Since this means that the arrays in pPathDest may
* need to be resized, pPathDest should have been initialized using
* PATH_InitGdiPath (in C++, this function would be an assignment operator,
* not a copy constructor).
* Returns TRUE if successful, else FALSE.
*/
static BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc)
{
/* Make sure destination arrays are big enough */
if(!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
return FALSE;
/* Perform the copy operation */
memcpy(pPathDest->pPoints, pPathSrc->pPoints,
sizeof(POINT)*pPathSrc->numEntriesUsed);
memcpy(pPathDest->pFlags, pPathSrc->pFlags,
sizeof(BYTE)*pPathSrc->numEntriesUsed);
pPathDest->state=pPathSrc->state;
pPathDest->numEntriesUsed=pPathSrc->numEntriesUsed;
pPathDest->newStroke=pPathSrc->newStroke;
return TRUE;
}
/* PATH_CheckCorners
*
* Helper function for PATH_RoundRect() and PATH_Rectangle()
@ -735,8 +775,62 @@ BOOL WINAPI SelectClipPath(HDC hdc, INT iMode)
/***********************************************************************
* Exported functions
* pathdrv_AbortPath
*/
static BOOL pathdrv_AbortPath( PHYSDEV dev )
{
DC *dc = get_dc_ptr( dev->hdc );
if (!dc) return FALSE;
PATH_EmptyPath( &dc->path );
pop_path_driver( dc );
release_dc_ptr( dc );
return TRUE;
}
/***********************************************************************
* pathdrv_EndPath
*/
static BOOL pathdrv_EndPath( PHYSDEV dev )
{
DC *dc = get_dc_ptr( dev->hdc );
if (!dc) return FALSE;
dc->path.state = PATH_Closed;
pop_path_driver( dc );
release_dc_ptr( dc );
return TRUE;
}
/***********************************************************************
* pathdrv_CreateDC
*/
static BOOL pathdrv_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
LPCWSTR output, const DEVMODEW *devmode )
{
struct path_physdev *physdev = HeapAlloc( GetProcessHeap(), 0, sizeof(*physdev) );
DC *dc;
if (!physdev) return FALSE;
dc = get_dc_ptr( (*dev)->hdc );
physdev->path = &dc->path;
push_dc_driver( dev, &physdev->dev, &path_driver );
release_dc_ptr( dc );
return TRUE;
}
/*************************************************************
* pathdrv_DeleteDC
*/
static BOOL pathdrv_DeleteDC( PHYSDEV dev )
{
assert( 0 ); /* should never be called */
return TRUE;
}
/* PATH_InitGdiPath
*
@ -765,35 +859,29 @@ void PATH_DestroyGdiPath(GdiPath *pPath)
HeapFree( GetProcessHeap(), 0, pPath->pFlags );
}
/* PATH_AssignGdiPath
*
* Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is
* performed, i.e. the contents of the pPoints and pFlags arrays are copied,
* not just the pointers. Since this means that the arrays in pPathDest may
* need to be resized, pPathDest should have been initialized using
* PATH_InitGdiPath (in C++, this function would be an assignment operator,
* not a copy constructor).
* Returns TRUE if successful, else FALSE.
*/
BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc)
BOOL PATH_SavePath( DC *dst, DC *src )
{
assert(pPathDest!=NULL && pPathSrc!=NULL);
PATH_InitGdiPath( &dst->path );
return PATH_AssignGdiPath( &dst->path, &src->path );
}
/* Make sure destination arrays are big enough */
if(!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed))
return FALSE;
BOOL PATH_RestorePath( DC *dst, DC *src )
{
BOOL ret;
/* Perform the copy operation */
memcpy(pPathDest->pPoints, pPathSrc->pPoints,
sizeof(POINT)*pPathSrc->numEntriesUsed);
memcpy(pPathDest->pFlags, pPathSrc->pFlags,
sizeof(BYTE)*pPathSrc->numEntriesUsed);
pPathDest->state=pPathSrc->state;
pPathDest->numEntriesUsed=pPathSrc->numEntriesUsed;
pPathDest->newStroke=pPathSrc->newStroke;
return TRUE;
if (src->path.state == PATH_Open && dst->path.state != PATH_Open)
{
if (!path_driver.pCreateDC( &dst->physDev, NULL, NULL, NULL, NULL )) return FALSE;
ret = PATH_AssignGdiPath( &dst->path, &src->path );
if (!ret) pop_path_driver( dst );
}
else if (src->path.state != PATH_Open && dst->path.state == PATH_Open)
{
ret = PATH_AssignGdiPath( &dst->path, &src->path );
if (ret) pop_path_driver( dst );
}
else ret = PATH_AssignGdiPath( &dst->path, &src->path );
return ret;
}
/* PATH_MoveTo
@ -2089,6 +2177,7 @@ BOOL nulldrv_BeginPath( PHYSDEV dev )
/* If path is already open, do nothing */
if (dc->path.state != PATH_Open)
{
if (!path_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) return FALSE;
PATH_EmptyPath(&dc->path);
dc->path.newStroke = TRUE;
dc->path.state = PATH_Open;
@ -2098,15 +2187,8 @@ BOOL nulldrv_BeginPath( PHYSDEV dev )
BOOL nulldrv_EndPath( PHYSDEV dev )
{
DC *dc = get_nulldrv_dc( dev );
if (dc->path.state != PATH_Open)
{
SetLastError( ERROR_CAN_NOT_COMPLETE );
return FALSE;
}
dc->path.state = PATH_Closed;
return TRUE;
SetLastError( ERROR_CAN_NOT_COMPLETE );
return FALSE;
}
BOOL nulldrv_AbortPath( PHYSDEV dev )
@ -2222,3 +2304,140 @@ BOOL nulldrv_WidenPath( PHYSDEV dev )
}
return PATH_WidenPath( dc );
}
const struct gdi_dc_funcs path_driver =
{
NULL, /* pAbortDoc */
pathdrv_AbortPath, /* pAbortPath */
NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
NULL, /* pArc */
NULL, /* pArcTo */
NULL, /* pBeginPath */
NULL, /* pBlendImage */
NULL, /* pChoosePixelFormat */
NULL, /* pChord */
NULL, /* pCloseFigure */
NULL, /* pCreateBitmap */
NULL, /* pCreateCompatibleDC */
pathdrv_CreateDC, /* pCreateDC */
NULL, /* pCreateDIBSection */
NULL, /* pDeleteBitmap */
pathdrv_DeleteDC, /* pDeleteDC */
NULL, /* pDeleteObject */
NULL, /* pDescribePixelFormat */
NULL, /* pDeviceCapabilities */
NULL, /* pEllipse */
NULL, /* pEndDoc */
NULL, /* pEndPage */
pathdrv_EndPath, /* pEndPath */
NULL, /* pEnumFonts */
NULL, /* pEnumICMProfiles */
NULL, /* pExcludeClipRect */
NULL, /* pExtDeviceMode */
NULL, /* pExtEscape */
NULL, /* pExtFloodFill */
NULL, /* pExtSelectClipRgn */
NULL, /* pExtTextOut */
NULL, /* pFillPath */
NULL, /* pFillRgn */
NULL, /* pFlattenPath */
NULL, /* pFontIsLinked */
NULL, /* pFrameRgn */
NULL, /* pGdiComment */
NULL, /* pGdiRealizationInfo */
NULL, /* pGetCharABCWidths */
NULL, /* pGetCharABCWidthsI */
NULL, /* pGetCharWidth */
NULL, /* pGetDeviceCaps */
NULL, /* pGetDeviceGammaRamp */
NULL, /* pGetFontData */
NULL, /* pGetFontUnicodeRanges */
NULL, /* pGetGlyphIndices */
NULL, /* pGetGlyphOutline */
NULL, /* pGetICMProfile */
NULL, /* pGetImage */
NULL, /* pGetKerningPairs */
NULL, /* pGetNearestColor */
NULL, /* pGetOutlineTextMetrics */
NULL, /* pGetPixel */
NULL, /* pGetPixelFormat */
NULL, /* pGetSystemPaletteEntries */
NULL, /* pGetTextCharsetInfo */
NULL, /* pGetTextExtentExPoint */
NULL, /* pGetTextExtentExPointI */
NULL, /* pGetTextFace */
NULL, /* pGetTextMetrics */
NULL, /* pIntersectClipRect */
NULL, /* pInvertRgn */
NULL, /* pLineTo */
NULL, /* pModifyWorldTransform */
NULL, /* pMoveTo */
NULL, /* pOffsetClipRgn */
NULL, /* pOffsetViewportOrg */
NULL, /* pOffsetWindowOrg */
NULL, /* pPaintRgn */
NULL, /* pPatBlt */
NULL, /* pPie */
NULL, /* pPolyBezier */
NULL, /* pPolyBezierTo */
NULL, /* pPolyDraw */
NULL, /* pPolyPolygon */
NULL, /* pPolyPolyline */
NULL, /* pPolygon */
NULL, /* pPolyline */
NULL, /* pPolylineTo */
NULL, /* pPutImage */
NULL, /* pRealizeDefaultPalette */
NULL, /* pRealizePalette */
NULL, /* pRectangle */
NULL, /* pResetDC */
NULL, /* pRestoreDC */
NULL, /* pRoundRect */
NULL, /* pSaveDC */
NULL, /* pScaleViewportExt */
NULL, /* pScaleWindowExt */
NULL, /* pSelectBitmap */
NULL, /* pSelectBrush */
NULL, /* pSelectClipPath */
NULL, /* pSelectFont */
NULL, /* pSelectPalette */
NULL, /* pSelectPen */
NULL, /* pSetArcDirection */
NULL, /* pSetBkColor */
NULL, /* pSetBkMode */
NULL, /* pSetDCBrushColor */
NULL, /* pSetDCPenColor */
NULL, /* pSetDIBColorTable */
NULL, /* pSetDIBitsToDevice */
NULL, /* pSetDeviceClipping */
NULL, /* pSetDeviceGammaRamp */
NULL, /* pSetLayout */
NULL, /* pSetMapMode */
NULL, /* pSetMapperFlags */
NULL, /* pSetPixel */
NULL, /* pSetPixelFormat */
NULL, /* pSetPolyFillMode */
NULL, /* pSetROP2 */
NULL, /* pSetRelAbs */
NULL, /* pSetStretchBltMode */
NULL, /* pSetTextAlign */
NULL, /* pSetTextCharacterExtra */
NULL, /* pSetTextColor */
NULL, /* pSetTextJustification */
NULL, /* pSetViewportExt */
NULL, /* pSetViewportOrg */
NULL, /* pSetWindowExt */
NULL, /* pSetWindowOrg */
NULL, /* pSetWorldTransform */
NULL, /* pStartDoc */
NULL, /* pStartPage */
NULL, /* pStretchBlt */
NULL, /* pStretchDIBits */
NULL, /* pStrokeAndFillPath */
NULL, /* pStrokePath */
NULL, /* pSwapBuffers */
NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */
/* OpenGL not supported */
};