gdi32: Implement FillPath, StrokeAndFillPath and StrokePath in the DIB driver.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3054c0fd1b
commit
b5cf73edd9
|
@ -424,7 +424,7 @@ const struct gdi_dc_funcs dib_driver =
|
|||
dibdrv_ExtFloodFill, /* pExtFloodFill */
|
||||
NULL, /* pExtSelectClipRgn */
|
||||
dibdrv_ExtTextOut, /* pExtTextOut */
|
||||
NULL, /* pFillPath */
|
||||
dibdrv_FillPath, /* pFillPath */
|
||||
NULL, /* pFillRgn */
|
||||
NULL, /* pFlattenPath */
|
||||
NULL, /* pFontIsLinked */
|
||||
|
@ -519,8 +519,8 @@ const struct gdi_dc_funcs dib_driver =
|
|||
NULL, /* pStartPage */
|
||||
dibdrv_StretchBlt, /* pStretchBlt */
|
||||
NULL, /* pStretchDIBits */
|
||||
NULL, /* pStrokeAndFillPath */
|
||||
NULL, /* pStrokePath */
|
||||
dibdrv_StrokeAndFillPath, /* pStrokeAndFillPath */
|
||||
dibdrv_StrokePath, /* pStrokePath */
|
||||
NULL, /* pUnrealizePalette */
|
||||
NULL, /* pWidenPath */
|
||||
dibdrv_wine_get_wgl_driver, /* wine_get_wgl_driver */
|
||||
|
|
|
@ -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_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
|
||||
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,
|
||||
struct bitblt_coords *src ) 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 BOOL dibdrv_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
|
||||
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;
|
||||
|
||||
static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev )
|
||||
|
|
|
@ -402,6 +402,73 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
|||
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
|
||||
black bkgnd. [A log-log plot of these data gives: y = 77.05 * x^0.4315]. */
|
||||
static const BYTE ramp[17] =
|
||||
|
@ -999,6 +1066,16 @@ BOOL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
|
|||
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
|
||||
*/
|
||||
|
@ -1499,3 +1576,23 @@ COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
|
|||
free_clipped_rects( &clipped_rects );
|
||||
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 );
|
||||
}
|
||||
|
|
|
@ -335,6 +335,7 @@ typedef struct
|
|||
/* path.c */
|
||||
|
||||
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_RestorePath( DC *dst, DC *src ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -273,6 +273,32 @@ static BOOL start_new_stroke( struct path_physdev *physdev )
|
|||
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
|
||||
*
|
||||
* Helper function for RoundRect() and Rectangle()
|
||||
|
@ -505,6 +531,37 @@ static BOOL PATH_DoArcPart(struct gdi_path *pPath, FLOAT_POINT corners[],
|
|||
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.@)
|
||||
|
|
Loading…
Reference in New Issue