gdiplus: Implemented GdipDrawCurve2.
This commit is contained in:
parent
c42f8794a1
commit
5c8b83c524
|
@ -153,7 +153,7 @@
|
||||||
@ stub GdipDrawClosedCurve2I
|
@ stub GdipDrawClosedCurve2I
|
||||||
@ stub GdipDrawClosedCurve
|
@ stub GdipDrawClosedCurve
|
||||||
@ stub GdipDrawClosedCurveI
|
@ stub GdipDrawClosedCurveI
|
||||||
@ stub GdipDrawCurve2
|
@ stdcall GdipDrawCurve2(ptr ptr ptr long long)
|
||||||
@ stub GdipDrawCurve2I
|
@ stub GdipDrawCurve2I
|
||||||
@ stub GdipDrawCurve3
|
@ stub GdipDrawCurve3
|
||||||
@ stub GdipDrawCurve3I
|
@ stub GdipDrawCurve3I
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#include "gdiplus_private.h"
|
#include "gdiplus_private.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
/* looks-right constant */
|
||||||
|
#define TENSION_CONST (0.3)
|
||||||
|
|
||||||
static inline INT roundr(REAL x)
|
static inline INT roundr(REAL x)
|
||||||
{
|
{
|
||||||
return (INT) floor(x+0.5);
|
return (INT) floor(x+0.5);
|
||||||
|
@ -77,6 +80,34 @@ static GpStatus draw_pie(GpGraphics *graphics, HBRUSH gdibrush, HPEN gdipen,
|
||||||
return Ok;
|
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)
|
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
|
||||||
{
|
{
|
||||||
if(hdc == NULL)
|
if(hdc == NULL)
|
||||||
|
@ -160,6 +191,58 @@ GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics *graphics, GpPen *pen, REAL x1,
|
||||||
return Ok;
|
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,
|
GpStatus WINGDIPAPI GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1,
|
||||||
INT y1, INT x2, INT y2)
|
INT y1, INT x2, INT y2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#define WINGDIPAPI __stdcall
|
#define WINGDIPAPI __stdcall
|
||||||
|
|
||||||
|
#define GDIPCONST const
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,6 +36,7 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *);
|
||||||
GpStatus WINGDIPAPI GdipDrawArc(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
|
GpStatus WINGDIPAPI GdipDrawArc(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
|
||||||
GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,
|
GpStatus WINGDIPAPI GdipDrawBezier(GpGraphics*,GpPen*,REAL,REAL,REAL,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 GdipDrawLineI(GpGraphics*,GpPen*,INT,INT,INT,INT);
|
||||||
GpStatus WINGDIPAPI GdipDrawPie(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
|
GpStatus WINGDIPAPI GdipDrawPie(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL,REAL,REAL);
|
||||||
GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics*,GpPen*,INT,INT,INT,INT);
|
GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics*,GpPen*,INT,INT,INT,INT);
|
||||||
|
|
|
@ -38,5 +38,6 @@ typedef struct GpSolidFill GpSolidFill;
|
||||||
typedef Status GpStatus;
|
typedef Status GpStatus;
|
||||||
typedef Unit GpUnit;
|
typedef Unit GpUnit;
|
||||||
typedef BrushType GpBrushType;
|
typedef BrushType GpBrushType;
|
||||||
|
typedef PointF GpPointF;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,7 +45,57 @@ enum Status{
|
||||||
PropertyNotSupported = 20
|
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;
|
typedef enum Status Status;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue