Alexandre Julliard : gdi32: Implement FillPath, StrokeAndFillPath and StrokePath in the DIB driver.
Alexandre Julliard
julliard at winehq.org
Thu Jun 16 10:20:56 CDT 2016
Module: wine
Branch: master
Commit: b5cf73edd952ef91a525871d9b330fd51831197e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b5cf73edd952ef91a525871d9b330fd51831197e
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Jun 16 14:06:48 2016 +0900
gdi32: Implement FillPath, StrokeAndFillPath and StrokePath in the DIB driver.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/gdi32/dibdrv/dc.c | 6 +--
dlls/gdi32/dibdrv/dibdrv.h | 3 ++
dlls/gdi32/dibdrv/graphics.c | 97 ++++++++++++++++++++++++++++++++++++++++++++
dlls/gdi32/gdi_private.h | 1 +
dlls/gdi32/path.c | 57 ++++++++++++++++++++++++++
5 files changed, 161 insertions(+), 3 deletions(-)
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index 4aa1d1d..314c651 100644
--- a/dlls/gdi32/dibdrv/dc.c
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -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 */
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
index c64058b..fc28acc 100644
--- a/dlls/gdi32/dibdrv/dibdrv.h
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -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 )
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index 2c865c0..bfb3451 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -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] =
@@ -1000,6 +1067,16 @@ BOOL dibdrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
}
/***********************************************************************
+ * dibdrv_FillPath
+ */
+BOOL dibdrv_FillPath( PHYSDEV dev )
+{
+ dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
+
+ return stroke_and_fill_path( pdev, FALSE, TRUE );
+}
+
+/***********************************************************************
* dibdrv_GetNearestColor
*/
COLORREF dibdrv_GetNearestColor( PHYSDEV dev, COLORREF color )
@@ -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 );
+}
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 08a5d3b..15e50e1 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -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;
diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c
index 0d89cfb..06fac77 100644
--- a/dlls/gdi32/path.c
+++ b/dlls/gdi32/path.c
@@ -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.@)
More information about the wine-cvs
mailing list