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