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