gdi32: Push a path driver on the DC stack when a path is opened.
This commit is contained in:
parent
97a261d573
commit
8a7bf0a2ab
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue