[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