[2/2] gdiplus: GdipDrawCurve2 [try2]

Evan Stade estade at gmail.com
Tue Jun 19 21:31:28 CDT 2007


Hi,

try2: followed helper function naming convention

Changelog:
*Implemented GdipDrawCurve2
*wrote typedefs for PointF, GpPointF, GDIPCONST

 dlls/gdiplus/gdiplus.spec |    2 +
 dlls/gdiplus/graphics.c   |   83 +++++++++++++++++++++++++++++++++++++++++++++
 include/gdiplusflat.h     |    3 ++
 include/gdiplusgpstubs.h  |    1 +
 include/gdiplustypes.h    |   52 ++++++++++++++++++++++++++++
 5 files changed, 139 insertions(+), 2 deletions(-)

-- 
Evan Stade
-------------- next part --------------
diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec
index 3036155..775bde3 100644
--- a/dlls/gdiplus/gdiplus.spec
+++ b/dlls/gdiplus/gdiplus.spec
@@ -153,7 +153,7 @@
 @ stub GdipDrawClosedCurve2I
 @ stub GdipDrawClosedCurve
 @ stub GdipDrawClosedCurveI
-@ stub GdipDrawCurve2
+@ stdcall GdipDrawCurve2(ptr ptr ptr long long)
 @ stub GdipDrawCurve2I
 @ stub GdipDrawCurve3
 @ stub GdipDrawCurve3I
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index a4ba0ca..f917b65 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -27,6 +27,9 @@ #include "gdiplus.h"
 #include "gdiplus_private.h"
 #include "wine/debug.h"
 
+/* looks-right constant */
+#define TENSION_CONST (0.3)
+
 static inline INT roundr(REAL x)
 {
     return (INT) floor(x+0.5);
@@ -77,6 +80,34 @@ static GpStatus draw_pie(GpGraphics *gra
     return Ok;
 }
 
+/* GdipDrawCurve helper function.
+ * Calculates Bezier points from cardinal spline points. */
+static void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
+    REAL *y1, REAL *x2, REAL *y2)
+{
+    REAL xdiff, ydiff;
+
+    /* calculate tangent */
+    xdiff = pts[2].X - pts[0].X;
+    ydiff = pts[2].Y - pts[0].Y;
+
+    /* apply tangent to get control points */
+    *x1 = pts[1].X - tension * xdiff;
+    *y1 = pts[1].Y - tension * ydiff;
+    *x2 = pts[1].X + tension * xdiff;
+    *y2 = pts[1].Y + tension * ydiff;
+}
+
+/* GdipDrawCurve helper function.
+ * Calculates Bezier points from cardinal spline endpoints. */
+static void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
+    REAL tension, REAL *x, REAL *y)
+{
+    /* tangent at endpoints is the line from the endpoint to the adjacent point */
+    *x = roundr(tension * (xadj - xend) + xend);
+    *y = roundr(tension * (yadj - yend) + yend);
+}
+
 GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
 {
     if(hdc == NULL)
@@ -160,6 +191,58 @@ GpStatus WINGDIPAPI GdipDrawBezier(GpGra
     return Ok;
 }
 
+/* Approximates cardinal spline with Bezier curves. */
+GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics *graphics, GpPen *pen,
+    GDIPCONST GpPointF *points, INT count, REAL tension)
+{
+    HGDIOBJ old_pen;
+
+    /* PolyBezier expects count*3-2 points. */
+    int i, len_pt = count*3-2;
+    POINT pt[len_pt];
+    REAL x1, x2, y1, y2;
+
+    if(!graphics || !pen)
+        return InvalidParameter;
+
+    tension = tension * TENSION_CONST;
+
+    calc_curve_bezier_endp(points[0].X, points[0].Y, points[1].X, points[1].Y,
+        tension, &x1, &y1);
+
+    pt[0].x = roundr(points[0].X);
+    pt[0].y = roundr(points[0].Y);
+    pt[1].x = roundr(x1);
+    pt[1].y = roundr(y1);
+
+    for(i = 0; i < count-2; i++){
+        calc_curve_bezier(&(points[i]), tension, &x1, &y1, &x2, &y2);
+
+        pt[3*i+2].x = roundr(x1);
+        pt[3*i+2].y = roundr(y1);
+        pt[3*i+3].x = roundr(points[i+1].X);
+        pt[3*i+3].y = roundr(points[i+1].Y);
+        pt[3*i+4].x = roundr(x2);
+        pt[3*i+4].y = roundr(y2);
+    }
+
+    calc_curve_bezier_endp(points[count-1].X, points[count-1].Y,
+        points[count-2].X, points[count-2].Y, tension, &x1, &y1);
+
+    pt[len_pt-2].x = x1;
+    pt[len_pt-2].y = y1;
+    pt[len_pt-1].x = roundr(points[count-1].X);
+    pt[len_pt-1].y = roundr(points[count-1].Y);
+
+    old_pen = SelectObject(graphics->hdc, pen->gdipen);
+
+    PolyBezier(graphics->hdc, pt, len_pt);
+
+    SelectObject(graphics->hdc, old_pen);
+
+    return Ok;
+}
+
 GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1,
     INT y1, INT x2, INT y2)
 {
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 538f1f4..e5c46b3 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -21,6 +21,8 @@ #define _FLATAPI_H
 
 #define WINGDIPAPI __stdcall
 
+#define GDIPCONST const
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -34,6 +36,7 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(G
 GpStatus WINGDIPAPI GdipDrawArc(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
 GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,
     REAL,REAL,REAL);
+GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT,REAL);
 GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics*,GpPen*,INT,INT,INT,INT);
 GpStatus WINGDIPAPI GdipDrawPie(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
 GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics*,GpPen*,INT,INT,INT,INT);
diff --git a/include/gdiplusgpstubs.h b/include/gdiplusgpstubs.h
index dcafc11..727ca06 100644
--- a/include/gdiplusgpstubs.h
+++ b/include/gdiplusgpstubs.h
@@ -38,5 +38,6 @@ #endif /* end of c declarations */
 typedef Status GpStatus;
 typedef Unit GpUnit;
 typedef BrushType GpBrushType;
+typedef PointF GpPointF;
 
 #endif
diff --git a/include/gdiplustypes.h b/include/gdiplustypes.h
index 006fe09..38fdf58 100644
--- a/include/gdiplustypes.h
+++ b/include/gdiplustypes.h
@@ -45,7 +45,57 @@ enum Status{
     PropertyNotSupported        = 20
 };
 
-#ifndef __cplusplus
+#ifdef __cplusplus
+
+class PointF
+{
+public:
+   PointF()
+   {
+       X = Y = 0.0f;
+   }
+
+   PointF(IN const PointF &pt)
+   {
+       X = pt.X;
+       Y = pt.Y;
+   }
+
+   /* FIXME: missing constructor that takes a SizeF */
+
+   PointF(IN REAL x, IN REAL y)
+   {
+       X = x;
+       Y = y;
+   }
+
+   PointF operator+(IN const PointF& pt) const
+   {
+       return PointF(X + pt.X, Y + pt.Y);
+   }
+
+   PointF operator-(IN const PointF& pt) const
+   {
+       return PointF(X - pt.X, Y - pt.Y);
+   }
+
+   BOOL Equals(IN const PointF& pt)
+   {
+       return (X == pt.X) && (Y == pt.Y);
+   }
+
+public:
+    REAL X;
+    REAL Y;
+};
+
+#else /* end of c++ typedefs */
+
+typedef struct PointF
+{
+    REAL X;
+    REAL Y;
+} PointF;
 
 typedef enum Status Status;
 
-- 
1.4.1


More information about the wine-patches mailing list