diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c index f23a502c45d..e8c59f9baf0 100644 --- a/dlls/winex11.drv/graphics.c +++ b/dlls/winex11.drv/graphics.c @@ -1227,6 +1227,107 @@ BOOL X11DRV_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWO return TRUE; } +/* helper for path stroking and filling functions */ +static BOOL x11drv_stroke_and_fill_path( PHYSDEV dev, BOOL stroke, BOOL fill ) +{ + X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); + POINT *points; + BYTE *flags; + BOOL ret = FALSE; + XPoint *xpoints; + int i, j, size; + + FlattenPath( dev->hdc ); + if ((size = GetPath( dev->hdc, NULL, NULL, 0 )) == -1) return FALSE; + if (!size) + { + AbortPath( dev->hdc ); + return TRUE; + } + xpoints = HeapAlloc( GetProcessHeap(), 0, (size + 1) * sizeof(*xpoints) ); + points = HeapAlloc( GetProcessHeap(), 0, size * sizeof(*points) ); + flags = HeapAlloc( GetProcessHeap(), 0, size * sizeof(*flags) ); + if (!points || !flags || !xpoints) goto done; + if (GetPath( dev->hdc, points, flags, size ) == -1) goto done; + LPtoDP( dev->hdc, points, size ); + + if (fill && X11DRV_SetupGCForBrush( physDev )) + { + XRectangle *rect; + HRGN hrgn = PathToRegion( dev->hdc ); + RGNDATA *data = X11DRV_GetRegionData( hrgn, 0 ); + + DeleteObject( hrgn ); + if (!data) goto done; + rect = (XRectangle *)data->Buffer; + for (i = 0; i < data->rdh.nCount; i++) + { + rect[i].x += physDev->dc_rect.left; + rect[i].y += physDev->dc_rect.top; + } + + XFillRectangles( gdi_display, physDev->drawable, physDev->gc, rect, data->rdh.nCount ); + HeapFree( GetProcessHeap(), 0, data ); + } + + if (stroke && X11DRV_SetupGCForPen ( physDev )) + { + for (i = j = 0; i < size; i++, j++) + { + if (flags[i] == PT_MOVETO) + { + if (j > 1) + { + if (fill || (flags[i - 1] & PT_CLOSEFIGURE)) xpoints[j++] = xpoints[0]; + XDrawLines( gdi_display, physDev->drawable, physDev->gc, xpoints, j, CoordModeOrigin ); + } + j = 0; + } + xpoints[j].x = physDev->dc_rect.left + points[i].x; + xpoints[j].y = physDev->dc_rect.top + points[i].y; + } + if (j > 1) + { + if (fill || (flags[i - 1] & PT_CLOSEFIGURE)) xpoints[j++] = xpoints[0]; + XDrawLines( gdi_display, physDev->drawable, physDev->gc, xpoints, j, CoordModeOrigin ); + } + } + + add_pen_device_bounds( physDev, points, size ); + AbortPath( dev->hdc ); + ret = TRUE; + +done: + HeapFree( GetProcessHeap(), 0, xpoints ); + HeapFree( GetProcessHeap(), 0, points ); + HeapFree( GetProcessHeap(), 0, flags ); + return ret; +} + +/********************************************************************** + * X11DRV_FillPath + */ +BOOL X11DRV_FillPath( PHYSDEV dev ) +{ + return x11drv_stroke_and_fill_path( dev, FALSE, TRUE ); +} + +/********************************************************************** + * X11DRV_StrokeAndFillPath + */ +BOOL X11DRV_StrokeAndFillPath( PHYSDEV dev ) +{ + return x11drv_stroke_and_fill_path( dev, TRUE, TRUE ); +} + +/********************************************************************** + * X11DRV_StrokePath + */ +BOOL X11DRV_StrokePath( PHYSDEV dev ) +{ + return x11drv_stroke_and_fill_path( dev, TRUE, FALSE ); +} + /********************************************************************** * X11DRV_InternalFloodFill diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 6bc4fb36ad8..af2fd921c6a 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -494,7 +494,7 @@ static const struct gdi_dc_funcs x11drv_funcs = X11DRV_ExtFloodFill, /* pExtFloodFill */ NULL, /* pExtSelectClipRgn */ NULL, /* pExtTextOut */ - NULL, /* pFillPath */ + X11DRV_FillPath, /* pFillPath */ NULL, /* pFillRgn */ NULL, /* pFlattenPath */ NULL, /* pFontIsLinked */ @@ -589,8 +589,8 @@ static const struct gdi_dc_funcs x11drv_funcs = NULL, /* pStartPage */ X11DRV_StretchBlt, /* pStretchBlt */ NULL, /* pStretchDIBits */ - NULL, /* pStrokeAndFillPath */ - NULL, /* pStrokePath */ + X11DRV_StrokeAndFillPath, /* pStrokeAndFillPath */ + X11DRV_StrokePath, /* pStrokePath */ X11DRV_UnrealizePalette, /* pUnrealizePalette */ NULL, /* pWidenPath */ X11DRV_wine_get_wgl_driver, /* wine_get_wgl_driver */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 23f4ab66a75..21808518474 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -150,6 +150,7 @@ extern BOOL X11DRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom, extern BOOL X11DRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; extern INT X11DRV_EnumICMProfiles( PHYSDEV dev, ICMENUMPROCW proc, LPARAM lparam ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType ) DECLSPEC_HIDDEN; +extern BOOL X11DRV_FillPath( PHYSDEV dev ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetDeviceGammaRamp( PHYSDEV dev, LPVOID ramp ) DECLSPEC_HIDDEN; extern BOOL X11DRV_GetICMProfile( PHYSDEV dev, LPDWORD size, LPWSTR filename ) DECLSPEC_HIDDEN; extern DWORD X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info, @@ -183,6 +184,8 @@ extern BOOL X11DRV_SetDeviceGammaRamp( PHYSDEV dev, LPVOID ramp ) DECLSPEC_HIDDE extern COLORREF X11DRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; extern BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst, PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop ) DECLSPEC_HIDDEN; +extern BOOL X11DRV_StrokeAndFillPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL X11DRV_StrokePath( PHYSDEV dev ) DECLSPEC_HIDDEN; extern BOOL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN; /* X11 driver internal functions */