gdiplus: Implemented GdipDrawCurve2.
This commit is contained in:
parent
c42f8794a1
commit
5c8b83c524
|
@ -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
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#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 *graphics, HBRUSH gdibrush, HPEN gdipen,
|
|||
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(GpGraphics *graphics, GpPen *pen, REAL x1,
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#define WINGDIPAPI __stdcall
|
||||
|
||||
#define GDIPCONST const
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -34,6 +36,7 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *);
|
|||
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);
|
||||
|
|
|
@ -38,5 +38,6 @@ typedef struct GpSolidFill GpSolidFill;
|
|||
typedef Status GpStatus;
|
||||
typedef Unit GpUnit;
|
||||
typedef BrushType GpBrushType;
|
||||
typedef PointF GpPointF;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue