gdiplus: paths implementation [try2]

Evan Stade estade at gmail.com
Mon Jun 25 21:15:41 CDT 2007


Hi,

try2: no longer relies on global pen instance.  Instead, creates and
destroys a dummy pen.

Changelog:
*added the helper functions that implement GDI+ paths (creating and
adding on to, but not drawing)
*Added GdipAddPathArc (as an example of how to use the helper functions)
*added an enumeration

 dlls/gdiplus/gdiplus.spec      |    2 -
 dlls/gdiplus/gdiplus_private.h |    1
 dlls/gdiplus/graphicspath.c    |  118 ++++++++++++++++++++++++++++++++++++++++
 include/gdiplusenums.h         |   12 ++++
 include/gdiplusflat.h          |    1
 5 files changed, 132 insertions(+), 2 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/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index e221044..2f610a0 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -54,6 +54,7 @@ struct GpPath{
     GpGraphics* graphics;
     GpPathData pathdata;
     BOOL newfigure; /* whether the next drawing action starts a new figure */
+    UINT datalen;
 };
 
 #endif
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
index cce60c6..78a5761 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,116 @@ #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
 
+static BYTE convert_path_point_type(BYTE type)
+{
+    BYTE retval = 0;
+
+    if(type & PT_CLOSEFIGURE)
+       retval = PathPointTypeCloseSubpath;
+
+    switch(type & ~PT_CLOSEFIGURE){
+        case PT_BEZIERTO:
+            return retval | PathPointTypeBezier;
+        case PT_LINETO:
+            return retval | PathPointTypeLine;
+        case PT_MOVETO:
+            return retval | 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;
+        TRACE("init\n");
+        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){
+        TRACE("realloc\n");
+        path->datalen *= 2;
+        path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0,
+            path->pathdata.Points, path->datalen * sizeof(PointF));
+        if(!path->pathdata.Points)  return OutOfMemory;
+
+        path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0,
+            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;
+    GpPen * pen;
+
+    TRACE("called\n");
+
+    if(!path || !(path->graphics))
+        return InvalidParameter;
+    if(GdipCreatePen1((ARGB) 0, 0, UnitPixel, &pen) != Ok)
+        return GenericError;
+
+    /* create GDI path */
+    BeginPath(path->graphics->hdc);
+    GdipDrawArc(path->graphics, pen, x, y, width, height, startAngle,
+        sweepAngle);
+    EndPath(path->graphics->hdc);
+
+    newfigure = path->newfigure;
+    path->newfigure = FALSE;
+
+    GdipDeletePen(pen);
+
+    /* copy GDI path to GDI+ path */
+    return append_gdi_path(path, newfigure, FALSE);
+}
+
 GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
 {
     HDC hdc;
@@ -60,8 +173,11 @@ GpStatus WINGDIPAPI GdipDeletePath(GpPat
     if(!path || !(path->graphics))
         return InvalidParameter;
 
-    ReleaseDC(0, path->graphics->hdc);
+    DeleteDC(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