gdi32: Implement FillPath, StrokeAndFillPath and StrokePath in the DIB driver.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2016-06-16 14:06:48 +09:00
parent 3054c0fd1b
commit b5cf73edd9
5 changed files with 161 additions and 3 deletions

View File

@ -424,7 +424,7 @@ const struct gdi_dc_funcs dib_driver =
dibdrv_ExtFloodFill, /* pExtFloodFill */ dibdrv_ExtFloodFill, /* pExtFloodFill */
NULL, /* pExtSelectClipRgn */ NULL, /* pExtSelectClipRgn */
dibdrv_ExtTextOut, /* pExtTextOut */ dibdrv_ExtTextOut, /* pExtTextOut */
NULL, /* pFillPath */ dibdrv_FillPath, /* pFillPath */
NULL, /* pFillRgn */ NULL, /* pFillRgn */
NULL, /* pFlattenPath */ NULL, /* pFlattenPath */
NULL, /* pFontIsLinked */ NULL, /* pFontIsLinked */
@ -519,8 +519,8 @@ const struct gdi_dc_funcs dib_driver =
NULL, /* pStartPage */ NULL, /* pStartPage */
dibdrv_StretchBlt, /* pStretchBlt */ dibdrv_StretchBlt, /* pStretchBlt */
NULL, /* pStretchDIBits */ NULL, /* pStretchDIBits */
NULL, /* pStrokeAndFillPath */ dibdrv_StrokeAndFillPath, /* pStrokeAndFillPath */
NULL, /* pStrokePath */ dibdrv_StrokePath, /* pStrokePath */
NULL, /* pUnrealizePalette */ NULL, /* pUnrealizePalette */
NULL, /* pWidenPath */ NULL, /* pWidenPath */
dibdrv_wine_get_wgl_driver, /* wine_get_wgl_driver */ dibdrv_wine_get_wgl_driver, /* wine_get_wgl_driver */

View File

@ -120,6 +120,7 @@ extern BOOL dibdrv_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT b
extern BOOL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type ) DECLSPEC_HIDDEN; extern BOOL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type ) DECLSPEC_HIDDEN;
extern BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, extern BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
const RECT *rect, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN; const RECT *rect, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
extern BOOL dibdrv_FillPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
extern DWORD dibdrv_GetImage( PHYSDEV dev, BITMAPINFO *info, struct gdi_image_bits *bits, extern DWORD dibdrv_GetImage( PHYSDEV dev, BITMAPINFO *info, struct gdi_image_bits *bits,
struct bitblt_coords *src ) DECLSPEC_HIDDEN; struct bitblt_coords *src ) DECLSPEC_HIDDEN;
extern COLORREF dibdrv_GetNearestColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF dibdrv_GetNearestColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
@ -150,6 +151,8 @@ extern COLORREF dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HID
extern COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; extern COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN;
extern BOOL dibdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst, extern BOOL dibdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop ) DECLSPEC_HIDDEN; PHYSDEV src_dev, struct bitblt_coords *src, DWORD rop ) DECLSPEC_HIDDEN;
extern BOOL dibdrv_StrokeAndFillPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
extern BOOL dibdrv_StrokePath( PHYSDEV dev ) DECLSPEC_HIDDEN;
extern struct opengl_funcs *dibdrv_wine_get_wgl_driver( PHYSDEV dev, UINT version ) DECLSPEC_HIDDEN; extern struct opengl_funcs *dibdrv_wine_get_wgl_driver( PHYSDEV dev, UINT version ) DECLSPEC_HIDDEN;
static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev ) static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev )

View File

@ -402,6 +402,73 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
return ret; return ret;
} }
/* helper for path stroking and filling functions */
static BOOL stroke_and_fill_path( dibdrv_physdev *dev, BOOL stroke, BOOL fill )
{
POINT *points;
BYTE *types;
BOOL ret = TRUE;
HRGN outline = 0, interior = 0;
int i, pos, total;
if (dev->brush.style == BS_NULL) fill = FALSE;
total = get_gdi_flat_path( dev->dev.hdc, &points, &types, fill ? &interior : NULL );
if (total == -1) return FALSE;
if (!total) goto done;
if (stroke && dev->pen_uses_region) outline = CreateRectRgn( 0, 0, 0, 0 );
/* if not using a region, paint the interior first so the outline can overlap it */
if (interior && !outline)
{
ret = brush_region( dev, interior );
DeleteObject( interior );
interior = 0;
}
if (stroke)
{
pos = 0;
for (i = 1; i < total; i++)
{
if (types[i] != PT_MOVETO) continue;
if (i > pos + 1)
{
reset_dash_origin( dev );
dev->pen_lines( dev, i - pos, points + pos,
fill || types[i - 1] & PT_CLOSEFIGURE, outline );
}
pos = i;
}
if (i > pos + 1)
{
reset_dash_origin( dev );
dev->pen_lines( dev, i - pos, points + pos,
fill || types[i - 1] & PT_CLOSEFIGURE, outline );
}
}
add_pen_lines_bounds( dev, total, points, outline );
if (interior)
{
CombineRgn( interior, interior, outline, RGN_DIFF );
ret = brush_region( dev, interior );
DeleteObject( interior );
}
if (outline)
{
if (ret) ret = pen_region( dev, outline );
DeleteObject( outline );
}
done:
HeapFree( GetProcessHeap(), 0, points );
HeapFree( GetProcessHeap(), 0, types );
return ret;
}
/* Intensities of the 17 glyph levels when drawn with text component of 0xff on a /* Intensities of the 17 glyph levels when drawn with text component of 0xff on a
black bkgnd. [A log-log plot of these data gives: y = 77.05 * x^0.4315]. */ black bkgnd. [A log-log plot of these data gives: y = 77.05 * x^0.4315]. */
static const BYTE ramp[17] = static const BYTE ramp[17] =
@ -999,6 +1066,16 @@ BOOL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
return TRUE; return TRUE;
} }
/***********************************************************************
* dibdrv_FillPath
*/
BOOL dibdrv_FillPath( PHYSDEV dev )
{
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
return stroke_and_fill_path( pdev, FALSE, TRUE );
}
/*********************************************************************** /***********************************************************************
* dibdrv_GetNearestColor * dibdrv_GetNearestColor
*/ */
@ -1499,3 +1576,23 @@ COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
free_clipped_rects( &clipped_rects ); free_clipped_rects( &clipped_rects );
return color; return color;
} }
/***********************************************************************
* dibdrv_StrokeAndFillPath
*/
BOOL dibdrv_StrokeAndFillPath( PHYSDEV dev )
{
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
return stroke_and_fill_path( pdev, TRUE, TRUE );
}
/***********************************************************************
* dibdrv_StrokePath
*/
BOOL dibdrv_StrokePath( PHYSDEV dev )
{
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
return stroke_and_fill_path( pdev, TRUE, FALSE );
}

View File

@ -335,6 +335,7 @@ typedef struct
/* path.c */ /* path.c */
extern void free_gdi_path( struct gdi_path *path ) DECLSPEC_HIDDEN; extern void free_gdi_path( struct gdi_path *path ) DECLSPEC_HIDDEN;
extern int get_gdi_flat_path( HDC hdc, POINT **points, BYTE **flags, HRGN *rgn ) DECLSPEC_HIDDEN;
extern BOOL PATH_SavePath( DC *dst, DC *src ) 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_RestorePath( DC *dst, DC *src ) DECLSPEC_HIDDEN;

View File

@ -273,6 +273,32 @@ static BOOL start_new_stroke( struct path_physdev *physdev )
return add_log_points( physdev, &pos, 1, PT_MOVETO ) != NULL; return add_log_points( physdev, &pos, 1, PT_MOVETO ) != NULL;
} }
/* convert a (flattened) path to a region */
static HRGN path_to_region( const struct gdi_path *path, int mode )
{
int i, pos, polygons, *counts;
HRGN hrgn;
if (!path->count) return 0;
if (!(counts = HeapAlloc( GetProcessHeap(), 0, (path->count / 2) * sizeof(*counts) ))) return 0;
pos = polygons = 0;
assert( path->flags[0] == PT_MOVETO );
for (i = 1; i < path->count; i++)
{
if (path->flags[i] != PT_MOVETO) continue;
counts[polygons++] = i - pos;
pos = i;
}
if (i > pos + 1) counts[polygons++] = i - pos;
assert( polygons <= path->count / 2 );
hrgn = CreatePolyPolygonRgn( path->points, counts, polygons, mode );
HeapFree( GetProcessHeap(), 0, counts );
return hrgn;
}
/* PATH_CheckCorners /* PATH_CheckCorners
* *
* Helper function for RoundRect() and Rectangle() * Helper function for RoundRect() and Rectangle()
@ -505,6 +531,37 @@ static BOOL PATH_DoArcPart(struct gdi_path *pPath, FLOAT_POINT corners[],
return TRUE; return TRUE;
} }
/* retrieve a flattened path in device coordinates, and optionally its region */
/* the DC path is deleted; the returned data must be freed by caller */
/* helper for stroke_and_fill_path in the DIB driver */
int get_gdi_flat_path( HDC hdc, POINT **points, BYTE **flags, HRGN *rgn )
{
DC *dc = get_dc_ptr( hdc );
int ret = -1;
if (!dc) return -1;
if (dc->path)
{
struct gdi_path *path = PATH_FlattenPath( dc->path );
free_gdi_path( dc->path );
dc->path = NULL;
if (path)
{
ret = path->count;
*points = path->points;
*flags = path->flags;
if (rgn) *rgn = path_to_region( path, GetPolyFillMode( hdc ));
HeapFree( GetProcessHeap(), 0, path );
}
}
else SetLastError( ERROR_CAN_NOT_COMPLETE );
release_dc_ptr( dc );
return ret;
}
/*********************************************************************** /***********************************************************************
* BeginPath (GDI32.@) * BeginPath (GDI32.@)