/* Easy to use default routines for simple drivers (line output only) */
/*---------------------------------------------------------------------------*/
#include <math.h>
#include "all.h"
#include "mygraph.h"
#include "mydev.h"
#include "core.h"
#include "justify.h"
extern struct gmodel g;
/*---------------------------------------------------------------------------*/
#if (defined M_PI && !defined PI)
#define PI M_PI
#define pi M_PI
#elif defined PI
#define pi PI
#else
#define PI 3.141592653
#define pi 3.141592653
#endif

#define true (!false)
#define false 0
int clipvec(dbl x1,dbl y1,dbl x2,dbl y2,dbl wxmin,dbl wymin,dbl wxmax,dbl wymax);
int xdf_barc(double r,dbl t1,dbl t2,dbl cx,dbl cy);
/*---------------------------------------------------------------------------*/
#define CSTEP (360/6)

df_bezier(dbl x1,dbl y1,dbl x2,dbl y2,dbl x3,dbl y3)
{
	double ax,bx,cx,ay,by,cy,dist;
	double xxx,yyy,i,t,nstep,x0,y0;
	g_get_xy(&x0,&y0);
	dist = fabs(x3-x0) + fabs(y3-y0);
	nstep = 10;
	if (dist>3) nstep = 20;
	if (dist<.5) nstep = 5;
	if (dist<.3) nstep = 3;
	if (dist<.1) {
		g_line(x3,y3);
		return;
	}
	cx = (x1-x0)*3;
	bx = (x2-x1)*3-cx;
	ax = x3-x0-cx-bx;
	cy = (y1-y0)*3;
	by = (y2-y1)*3-cy;
	ay = y3-y0-cy-by;
	for (i=0;i<=nstep;i++) {
		t = i/nstep;
		xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
		yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
		g_line(xxx,yyy);
	}
}

df_arcto(dbl x1,dbl y1,dbl x2,dbl y2,dbl rrr)
{
	double x0,y0,r1,a1,r2,a2,r3,a3,a4,r5,sx,sy,ex,ey;
	double bx1,by1,bx2,by2,dist,neg;
	g_get_xy(&x0,&y0);
	xy_polar(x1-x0,y1-y0,&r1,&a1);
	xy_polar(x2-x1,y2-y1,&r2,&a2);
	neg = 1;
	a4 = (180-a2+a1);
	a3 = a2 + (a4/2);
	if ((a4/2)>90 && (a4/2)<180 ) neg = -1;
	if ((a4/2)<0 && (a4/2)>-90 ) neg = -1;
	r3 = neg*rrr/(tan((pi/180)*a4/2));
	polar_xy(-r3,a1,&sx,&sy); sx += x1; sy += y1;
	polar_xy(r3,a2,&ex,&ey); ex += x1; ey += y1;
	g_line(sx,sy);
	dist = sqrt((ex-sx)*(ex-sx) + (ey-sy)*(ey-sy));
	polar_xy(r1+ dist/2.5-r3,a1,&bx1,&by1); bx1 += x0; by1 += y0;
	polar_xy(-r2+ -dist/2.5+r3,a2,&bx2,&by2); bx2 += x2; by2 += y2;
	g_bezier(bx1,by1,bx2,by2,ex,ey);
	g_line(x2,y2);
}
df_arc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	/* circle from t1 to t2, lets use 6 bezier's for a circle */
	double stz;
	int nst,i;

	/* if (t2<t1) t2 = t2 + 360 ; a.r. */
	for (;t2<t1;)
	      t2 = t2 + 360;

	nst = floor((t2-t1)/CSTEP)+1;
	stz = (t2-t1) / nst;
	for (i=1;i<=nst;i++)
		xdf_barc(r,t1+stz*(i-1),t1+stz*i,cx,cy);
}
xdf_barc(double r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	double rx1,ry1,rx2,ry2,d,dx1,dy1,dx2,dy2;

	polar_xy(r,t1,&rx1,&ry1);
	polar_xy(r,t2,&rx2,&ry2);
	d = sqrt( (rx2-rx1)*(rx2-rx1) + (ry2-ry1)*(ry2-ry1));
	polar_xy(d/3,t1+90,&dx1,&dy1);
	polar_xy(d/3,t2-90,&dx2,&dy2);
	if (g.inpath) {
		g_line(rx1+cx,ry1+cy);
		g_bezier(rx1+cx+dx1,ry1+cy+dy1
			,rx2+cx+dx2,ry2+cy+dy2,rx2+cx,ry2+cy);
	} else {
		g_move(rx1+cx,ry1+cy);
		g_bezier(rx1+cx+dx1,ry1+cy+dy1
			,rx2+cx+dx2,ry2+cy+dy2,rx2+cx,ry2+cy);
		g_move(cx,cy);
	}
}
df_box_stroke(dbl x1, dbl y1, dbl x2, dbl y2)
{
	double ox,oy;
	g_get_xy(&ox,&oy);
	g_move(x1,y1);
	g_line(x2,y1);
	g_line(x2,y2);
	g_line(x1,y2);
	g_closepath();
	g_move(ox,oy);
}

df_box_fill(dbl x1, dbl y1, dbl x2, dbl y2)
{
	double dx,dy,cs,x,y;
	int32 fc,oldcolor;
	colortyp  cc;
	g_get_fill(&fc);
	cc.l = fc;
	cs = cc.b[B_R]*3 + cc.b[B_B] + cc.b[B_G]*2;
	if (cs>(6*250)) return; /* white, dont try and fill it in */
	cs = (cs+50)/700;

	if (x1>x2) {dx = x1; x1 = x2; x2 = dx; }
	if (y1>y2) {dy = y1; y1 = y2; y2 = dy; }
	dx = x2-x1;
	dy = y2-y1;
	if (dx==0 || dy==0) return;
		/* cs = color intensity  (measure in cm) */
		/* set pen color to fill color now */
	g_get_color(&oldcolor);
	g_get_fill(&fc);
	g_set_color(fc);
	for (y = y1-dx; y<y2; y+=cs) {
		clipvec(x1,y,x2,y+cs-.4,x1,y1,x2,y2);
	}
	g_set_color(oldcolor);
}
clipvec(dbl x1,dbl y1,dbl x2,dbl y2,dbl wxmin,dbl wymin,dbl wxmax,dbl wymax)
{

	int invis;
	if (x1>=wxmin && x1<=wxmax && y1>=wymin && y1<=wymax
	  && x2 >= wxmin && x2<=wxmax && y2>=wymin && y2<=wymax);
	else {          /* ok one or both are outside our box */
		gclip(&x1,&y1,&x2,&y2,wxmin,wymin,wxmax,wymax,&invis);
		if (invis) return;
	}
	g_move(x1,y1);
	g_line(x2,y2);
}
df_circle_stroke(dbl r)
{
	double cx,cy;
	g_get_xy(&cx,&cy);
	df_arc(r,0.0,360.0,cx,cy);
}
df_circle_fill(dbl r)
{
	double cx,cy;
	g_get_xy(&cx,&cy);
	df_arc(r,0.0,360.0,cx,cy);
}



