#ifndef __PATH2D_H
#define __PATH2D_H
#include "user.h"
#include "matrix.h"
#include "itemarr.h"
typedef struct{
double x,y;
} PTDBL;
typedef struct{
double left,top,right,bottom;
} RECTDBL;
typedef struct{
double left,top,right,bottom,cxArc,cyArc;
} ROUNDRECT;
typedef struct{
DWORD type;
double coords[6];
} PATHSEGMENT;
typedef struct{
DWORD type;
double coords[8];
} FULLPATHSEGMENT;
typedef struct {
LPVOID (*Init)(LPVOID data);
int (*Next)(LPVOID h, PATHSEGMENT *segment);
void (*Free)(LPVOID h);
int (*GetWinding)(LPVOID h);
} PATHITERATOR;
typedef struct{
int state;
double curx,cury,movx,movy;
} FULLPATHCONTEXT;
typedef struct{
PATHITERATOR *iterator;
LPVOID data;
MATRIX *matrix;
double tolerance;
} FLATPATHPARAMS;
typedef struct{
double startX,startY;
double endX,endY;
double radiusX,radiusY;
double rotation;
BOOL largearc;
BOOL sweep;
} SVGARC;
typedef struct{
double centerX,centerY;
double radiusX,radiusY;
double startangle;
double sweepangle;
double phi;
} CENTERARC;
#define ISONE(value) (abs(value-1.0)<2.22E-15)
#define ISZERO(value) (abs(value)<2.22E-15)
#define DoubleIsFinite(x) (abs(x)<=1.7976931348623157e+308)
#define FloatIsFinite(x) (abs(x)<=3.402823E+38f)
inline double ModDouble(double x, double y){
if(x>=0 && y>0 && x<y){
return x;
} else {
return x-y*floor(x/y);
}
}
inline int ModInt(int x, int y){
if(x>=0){
return (y>0 && x<y) ? x : x%y;
} else {
return x%y ? y+x%y : 0;
}
}
inline BOOL AreClose(double a, double b){
return (abs(a-b)<2.22E-15);
}
inline BOOL LessThan(double a, double b){
return (a<b) && !AreClose(a,b);
}
inline BOOL LessOrClose(double a, double b){
return (a<b) || AreClose(a,b);
}
inline BOOL GreaterThan(double a, double b){
return (a>b) && !AreClose(a,b);
}
inline BOOL GreaterOrClose(double a, double b){
return (a>b) || AreClose(a,b);
}
#define RectDblToInt(rcdbl,rcint) \
do{(rcint)->left=floor((rcdbl)->left);\
(rcint)->top=floor((rcdbl)->top);\
(rcint)->right=ceil((rcdbl)->right);\
(rcint)->bottom=ceil((rcdbl)->bottom);}while(0)
#define RectNormalize(rc,tmp) \
do{\
if((rc)->left>(rc)->right){\
tmp=(rc)->left;(rc)->left=(rc)->right;(rc)->right=tmp;\
}\
if((rc)->top>(rc)->bottom){\
tmp=(rc)->bottom;(rc)->bottom=(rc)->top;(rc)->top=tmp;\
}\
}while(0)
#define RectIsEmpty(rc) \
((rc)->left>=(rc)->right||(rc)->top>=(rc)->bottom)
#define RectAddPoint(rc,x,y) \
do{(rc)->left=min((rc)->left,x);\
(rc)->top=min((rc)->top,y);\
(rc)->right=max((rc)->right,x);\
(rc)->bottom=max((rc)->bottom,y);}while(0)
#define RectAddRect(rc,rc2) \
do{\
(rc)->left=min((rc)->left,(rc2)->left);\
(rc)->top=min((rc)->top,(rc2)->top);\
(rc)->right=max((rc)->right,(rc2)->left);\
(rc)->bottom=max((rc)->bottom,(rc2)->top);\
(rc)->left=min((rc)->left,(rc2)->right);\
(rc)->top=min((rc)->top,(rc2)->bottom);\
(rc)->right=max((rc)->right,(rc2)->right);\
(rc)->bottom=max((rc)->bottom,(rc2)->bottom);\
}while(0)
#define PATH_MOVETO 1
#define PATH_LINETO 2
#define PATH_QUADTO 3
#define PATH_CUBICTO 4
#define PATH_CLOSE 5
#define WIND_NONZERO 1
#define WIND_EVENODD 2
extern PATHITERATOR RectPath;
extern PATHITERATOR RoundRectPath;
extern PATHITERATOR EllipsePath;
extern PATHITERATOR LinePath;
extern PATHITERATOR QuadPath;
extern PATHITERATOR CubicPath;
extern PATHITERATOR FlatPathIterator;
extern PATHITERATOR CubicToQuadIterator;
extern PATHITERATOR PathSegmentsNonZero;
extern PATHITERATOR PathSegmentsEvenOdd;
double SegmentDistanceSq(
double x0, double y0, double x1, double y1,
double ptx, double pty
);
double PerpendicularDistance(
double x0, double y0, double x1, double y1,
double ptx, double pty
);
double PointDistance(double x1,double y1,double x2,double y2);
void LineSubdivide(double *src,double *left,double *right,double t);
void QuadSubdivide(double *src,double *left,double *right,double t);
void CubicSubdivide(double *src,double *left,double *right,double t);
double QuadFlatnessSq(double *c);
double CubicFlatnessSq(double *c);
void CubicCurveFromQuadratic(double *pSrc,double *pDst);
double SegmentDistanceSq(
double x0, double y0, double x1, double y1,
double ptx, double pty
);
double QuadControlPolygonLength(double *qc);
double QuadChordLength(double *qc);
double QuadCalcLength(double *qc, double tolerance);
double CubicControlPolygonLength(double *qc);
double CubicChordLength(double *qc);
double CubicCalcLength(double *qc, double tolerance);
int SolveLinear(double c[2], double s[1]);
int SolveQuadratic(double c[3], double s[2]);
int SolveCubic(double c[4], double s[3]);
BOOL PathMoveTo(ITEMARRAY *ia, double x, double y);
BOOL PathAddPoint(ITEMARRAY *ia, double x, double y);
BOOL PathLineTo(ITEMARRAY *ia, double x, double y);
BOOL PathQuadTo(ITEMARRAY *ia,
double x, double y, double x1, double y1);
BOOL PathCubicTo(ITEMARRAY *ia,
double x, double y, double x1, double y1, double x2, double y2);
BOOL PathSmoothQuadTo(ITEMARRAY *ia, double x, double y);
BOOL PathSmoothCubicTo(ITEMARRAY *ia, double x1, double y1, double x2, double y2);
BOOL PathClose(ITEMARRAY *ia);
BOOL PathGetEndPoint(ITEMARRAY *ia,double *endpt);
BOOL PathAddSegment(ITEMARRAY*ia,PATHSEGMENT*ps);
BOOL PathAddArc(
ITEMARRAY *ia,
double centerX,
double centerY,
double radiusX,
double radiusY,
double start,
double sweep,
double phi
);
BOOL PathArcTo(
ITEMARRAY *ia,
double centerX,
double centerY,
double radiusX,
double radiusY,
double start,
double sweep,
double phi
);
BOOL PathAddSvgArc(
ITEMARRAY*ia,
double x0, double x1,
double x, double y,
double rx, double ry, double phi,
BOOL largeArc, BOOL sweep
);
BOOL PathSvgArcTo(
ITEMARRAY*ia,
double x, double y,
double rx, double ry, double phi,
BOOL largeArc, BOOL sweep
);
void PathCardinalSplineTo(
ITEMARRAY *path,
double *coords,
LONG numpoints,
double tension
);
void PathAddCardinalSpline(
ITEMARRAY *path,
double *coords,
LONG numpoints,
double tension,
BOOL closefigure
);
BOOL PathTransform(ITEMARRAY *path,MATRIX*xfm);
double *PathSegmentEndPoint(PATHSEGMENT *ps);
BOOL PathSegmentTransform(PATHSEGMENT *ps, MATRIX *xfm);
int PathGetBounds(PATHITERATOR*pcb,LPVOID data,MATRIX*xfm,RECTDBL*prc);
BOOL PathAppendPath(
ITEMARRAY *ia,
PATHITERATOR *pcb,
LPVOID data,
MATRIX *xfm,
BOOL connect
);
void DebugOutPathSegment(PATHSEGMENT *ps, LPCTSTR add);
void DebugOutPathSegmentAsSvg(PATHSEGMENT *ps);
void DebugOutFullPathSegment(FULLPATHSEGMENT*ps,LPCTSTR add);
BOOL ViewSpaceCalcTransformEx(
MATRIX*xfmDst,
RECTDBL*rcViewport,
RECTDBL*rcWindow,
int align,
int meetOrSlice
);
void FullPathContextInit(FULLPATHCONTEXT *fpc);
BOOL FullPathSegmentTransform(FULLPATHSEGMENT*ps,MATRIX*xfm);
void FullToPathSegment(
FULLPATHSEGMENT *fullSegment,
PATHSEGMENT *pathSegment
);
int FullPathIteratorNext(
PATHITERATOR *iter,
LPVOID h,
FULLPATHCONTEXT *fpc,
FULLPATHSEGMENT *fps,
MATRIX *matrix
);
int ClosedPathIteratorNext(
PATHITERATOR *iter,
LPVOID h,
FULLPATHCONTEXT *fpc,
FULLPATHSEGMENT *fps,
MATRIX *matrix
);
#endif