[5/7] gdiplus: GdipDrawPathArc

Evan Stade estade at gmail.com
Thu Jun 21 18:15:24 CDT 2007


Hi,

>From the graphicspath.c preamble:

/* ...
 * Currently implemented via GDI paths.  Each time points are added on to the
 * GDI+ path, it draws a new GDI path and appends that to the GDI+
path.  The GDI+
 * path is an array that grows exponentially.
 */

Changelog:
*added some implementation of GDI+ paths, and an example method that
uses it (GdipDrawPathArc)

 dlls/gdiplus/gdiplus.spec   |    2 -
 dlls/gdiplus/graphicspath.c |  107 +++++++++++++++++++++++++++++++++++++++++++
 include/gdiplusenums.h      |   12 +++++
 include/gdiplusflat.h       |    1
 4 files changed, 121 insertions(+), 1 deletions(-)

-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec
index 5ca2b0f..8cdb0b3 100644
--- a/dlls/gdiplus/gdiplus.spec
+++ b/dlls/gdiplus/gdiplus.spec
@@ -1,4 +1,4 @@
-@ stub GdipAddPathArc
+@ stdcall GdipAddPathArc(ptr long long long long long long)
 @ stub GdipAddPathArcI
 @ stub GdipAddPathBezier
 @ stub GdipAddPathBezierI
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
index 177fc82..fc35902 100644
--- a/dlls/gdiplus/graphicspath.c
+++ b/dlls/gdiplus/graphicspath.c
@@ -15,6 +15,9 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
+ * Currently implemented via GDI paths.  Each time points are added on to the
+ * GDI+ path, it draws a new GDI path and appends that to the GDI+ path.  The GDI+
+ * path is an array that grows exponentially.
  */
 
 #include <stdarg.h>
@@ -30,6 +33,107 @@ #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
 
+static BYTE convert_path_point_type(BYTE type)
+{
+   if(type & PT_CLOSEFIGURE)
+       FIXME("PT_CLOSEFIGURE not yet handled\n");
+
+    switch(type & ~PT_CLOSEFIGURE){
+        case PT_BEZIERTO:
+            return PathPointTypeBezier;
+        case PT_LINETO:
+            return PathPointTypeLine;
+        case PT_MOVETO:
+            return PathPointTypeStart;
+        default:
+            ERR("Unknown GDI path point type\n");
+            return 0;
+    }
+}
+
+static GpStatus add_path_points(GpPath* path, LPPOINT points, LPBYTE types,
+    INT count)
+{
+    INT old_count = path->pathdata.Count, i;
+
+    path->pathdata.Count += count;
+
+    /* initial allocation */
+    if(path->datalen == 0){
+        path->datalen = path->pathdata.Count * 2;
+        path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF));
+        if(!path->pathdata.Points)   return OutOfMemory;
+
+        path->pathdata.Types = GdipAlloc(path->datalen);
+        if(!path->pathdata.Types){
+            GdipFree(path->pathdata.Points);
+            return OutOfMemory;
+        }
+    }
+    /* reallocation, double size of arrays */
+    else if(path->datalen < path->pathdata.Count){
+        path->datalen *= 2;
+        path->pathdata.Points = GdipReAlloc(path->pathdata.Points,
+            path->datalen * sizeof(PointF));
+        if(!path->pathdata.Points)  return OutOfMemory;
+
+        path->pathdata.Types = GdipReAlloc(path->pathdata.Types,
+            path->datalen);
+        if(!path->pathdata.Types)   return OutOfMemory;
+    }
+
+    for(i = old_count; i < old_count + count; i++){
+        (path->pathdata.Points)[i].X = (REAL) points[i-old_count].x;
+        (path->pathdata.Points)[i].Y = (REAL) points[i-old_count].y;
+        (path->pathdata.Types)[i] = convert_path_point_type(types[i-old_count]);
+    }
+
+    return Ok;
+}
+
+static GpStatus append_gdi_path(GpPath *path, BOOL newfigure, BOOL closefigure)
+{
+    INT count = GetPath(path->graphics->hdc, NULL, NULL, 0), old_count;
+    POINT points[count];
+    BYTE types[count];
+    GpStatus ret;
+
+    GetPath(path->graphics->hdc, points, types, count);
+
+    old_count = path->pathdata.Count;
+    ret = add_path_points(path, points, types, count);
+
+    if(!newfigure)
+        (path->pathdata.Types)[old_count] = PathPointTypeLine;
+    if(closefigure)
+        (path->pathdata.Types)[old_count + count - 1] |= PathPointTypeCloseSubpath;
+
+    return ret;
+}
+
+GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x, REAL y, REAL width, REAL
+    height, REAL startAngle, REAL sweepAngle)
+{
+    BOOL newfigure;
+
+    if(!path || !(path->graphics))
+        return InvalidParameter;
+
+    /* create GDI path */
+    BeginPath(path->graphics->hdc);
+    GdipDrawArc(path->graphics, GDIP_PEN, x, y, width, height, startAngle,
+        sweepAngle);
+    EndPath(path->graphics->hdc);
+
+    newfigure = path->newfigure;
+    path->newfigure = FALSE;
+
+    /* copy GDI path to GDI+ path */
+    return append_gdi_path(path, newfigure, FALSE);
+
+    return Ok;
+}
+
 GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
 {
     HDC hdc;
@@ -64,6 +168,9 @@ GpStatus WINGDIPAPI GdipDeletePath(GpPat
 
     ReleaseDC(0, path->graphics->hdc);
     GdipDeleteGraphics(path->graphics);
+
+    GdipFree(path->pathdata.Points);
+    GdipFree(path->pathdata.Types);
     GdipFree(path);
 
     return Ok;
diff --git a/include/gdiplusenums.h b/include/gdiplusenums.h
index c6b5f15..dee2684 100644
--- a/include/gdiplusenums.h
+++ b/include/gdiplusenums.h
@@ -45,11 +45,23 @@ enum FillMode
     FillModeWinding     = 1
 };
 
+enum PathPointType{
+    PathPointTypeStart          = 0,    /* start of a figure */
+    PathPointTypeLine           = 1,
+    PathPointTypeBezier         = 3,
+    PathPointTypePathTypeMask   = 7,
+    PathPointTypePathDashMode   = 16,   /* not used */
+    PathPointTypePathMarker     = 32,
+    PathPointTypeCloseSubpath   = 128,  /* end of a closed figure */
+    PathPointTypeBezier3        = 3
+};
+
 #ifndef __cplusplus
 
 typedef enum Unit Unit;
 typedef enum BrushType BrushType;
 typedef enum FillMode FillMode;
+typedef enum PathPointType PathPointType;
 
 #endif /* end of c typedefs */
 
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 78db330..376af86 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -47,6 +47,7 @@ GpStatus WINGDIPAPI GdipCreateSolidFill(
 GpStatus WINGDIPAPI GdipGetBrushType(GpBrush*,GpBrushType*);
 GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush*);
 
+GpStatus WINGDIPAPI GdipAddPathArc(GpPath*,REAL,REAL,REAL,REAL,REAL,REAL);
 GpStatus WINGDIPAPI GdipCreatePath(GpFillMode,GpPath**);
 GpStatus WINGDIPAPI GdipDeletePath(GpPath*);
 
-- 
1.4.1


More information about the wine-patches mailing list