/*--------------------------------------------------------------*/
/*	Bitmap Driver 1.0 (VAX C, TURBO  C) , for GLE V3.0	*/
/*--------------------------------------------------------------*/
/* This version writes the PATH to a temporary file which can
/* then be read by a bitmap driver (which has more memory available) */
/*---------------------------------------------------------------------------*/
#include "all.h"
#include <math.h>
#include "core.h"
#include "mygraph.h"
#include "mydev.h"
#ifndef __TURBOC__
#define huge
#else
#include <alloc.h>
#endif
extern int dev_fill,dev_font;
extern int gunit;
extern struct gmodel g;
/*---------------------------------------------------------------------------*/
#define pi 3.141592653
#define false 0
#define true (!false)
#define dbg if ((gle_debug & 64)>0)
extern int gle_debug;
int getch(void);
int kbhit(void);


int path_newpath(void);
int path_lwidth(float x);
int path_stroke(void);
int path_fill(void);
int path_lstyle(long x);
int path_dashlen(float x);
int path_dline(float x,float y);
int path_size(float x,float y);
int path_row(float x1, float y1, float x2, float y2);
int path_box(float x1, float y1, float x2, float y2);
int dpath_box(double x1, double  y1, double  x2, double y2);
int path_alloc(void);
int path_move(float x1, float y1);
int path_line(float x1, float y1);
int path_closepath(void);
/*---------------------------------------------------------------------------*/
long d_curcolor,d_curfill;
/*---------------------------------------------------------------------------*/
/*   Path variables for bitmap */
typedef union {long l; float f;} longfloat;
longfloat *path;
int npath;
int npath_alloc;

#include "dvipath.h"
path_reset()
{
}
path_newpath(void)
{
	path_alloc();
	path[npath++].l = p_newpath;
}
path_move(float x,float y)
{
	path_alloc();
	path[npath++].l = p_move;
	path[npath++].f = x;
	path[npath++].f = y;
}
path_lwidth(float x)
{
	path_alloc();
	path[npath++].l = p_lwidth;
	path[npath++].f = x;
}
path_setcolor(int r, int g, int b, int f)
{
	path_alloc();
	path[npath++].l = p_setcolor;
	path[npath++].l = r;
	path[npath++].l = g;
	path[npath++].l = b;
	path[npath++].l = f;
}
path_stroke(void)
{
	path_alloc();
	path[npath++].l = p_stroke;
}
path_fill(void)
{
	path_alloc();
	path[npath++].l = p_fill;
}
path_int(int x)
{
	path_alloc();
	path[npath++].l = x;
}
path_lstyle(long x)
{
	path_alloc();
	path[npath++].l = p_lstyle;
	path[npath++].l = x;
}
path_dline(float x,float y)
{
	path_alloc();
	path[npath++].l = p_dline;
	path[npath++].f = x;
	path[npath++].f = y;
}
path_size(float x,float y)
{
	path_alloc();
	path[npath++].l = p_size;
	path[npath++].f = x;
	path[npath++].f = y;
}
path_dashlen(float x)
{
	path_alloc();
	path[npath++].l = p_dashlen;
	path[npath++].f = x;
}
path_line(float x,float y)
{
	path_alloc();
	path[npath++].l = p_line;
	path[npath++].f = x;
	path[npath++].f = y;
}
path_bezier(float x1, float y1, float x2, float y2,float x3, float y3)
{
	path_alloc();
	path[npath++].l = p_bezier;
	path[npath++].f = x1;	path[npath++].f = y1;
	path[npath++].f = x2;	path[npath++].f = y2;
	path[npath++].f = x3;	path[npath++].f = y3;
}
path_closepath()
{
	path_alloc();
	path[npath++].l = p_closepath;
}
path_box(float x1, float y1, float x2, float y2)
{
	path_move(x1,y1);
	path_line(x2,y1);
	path_line(x2,y2);
	path_line(x1,y2);
	path_closepath();
}
path_alloc(void)
{
	static int npa;
	long *a;
	if (npath > 100) path_flush();
	if (npath < (npath_alloc-20)) return;
	npath_alloc = 20 + 2 * npath;
	a = myallocz(npath_alloc*sizeof(long));
	if (a==NULL) {
		gle_abort("Unable to allocate memory for path \n");
	}
	if (path != NULL) {
		memcpy(a,path,(npa)*sizeof(long));
		myfree(path);
	}
	npa = npath_alloc;
	path = (longfloat *) a;
}
path_free(void)
{
	if (path==NULL) return;
	myfree(path);
	path = NULL;
	npath = 0;
	npath_alloc = 0;
}

d_devcmd(char *s)
{}
dxy(double x, double y, float *dx, float *dy)
{
	static double fx,fy;
	g_dev(x,y,&fx,&fy);
	*dx = fx;
	*dy = fy;
}
rxy(double x, double y, int *dx, int *dy)
{
	static double fx,fy,zx,zy;
	g_dev(x,y,&fx,&fy);
	g_dev(0.0,0.0,&zx,&zy);
	*dx = (int) ( (fx-zx) );
	*dy = (int) ( (fy-zy) );
}
/*---------------------------------------------------------------------------*/
d_dfont(char *c)
{
	/* only used for the DFONT driver which builds fonts (never used)*/
}
/*---------------------------------------------------------------------------*/
d_message(char *s)
{
	printf("%s\n",s);
}
/*---------------------------------------------------------------------------*/
d_source(char *s)
{
	s=s;
}
/*---------------------------------------------------------------------------*/
d_get_type(char *t)
{
	strcpy(t,"OUTPUT, BITMAP, BLACKANDWHITE, HARDCOPY, FILLPATH");
}
/*---------------------------------------------------------------------------*/
d_set_path(int onoff)
{
}
/*---------------------------------------------------------------------------*/
d_newpath()
{
	path_flush();
	path_newpath();
}
/*---------------------------------------------------------------------------*/
FILE *dout;
path_flush(void)
{
	if (npath>0) fwrite(path,sizeof(long),npath,dout);
	npath = 0;
}
d_open(double width, double height)
{
	char *outfile;
	outfile = "out.dvi";
	dout = fopen(outfile,"wb");
	if (dout == NULL) gle_abort("Unable to open OUT.dvi epson output file \n");
	path_alloc();
	path_size(width,height);
	if (!dev_font) plotter_fonts();
}
/*---------------------------------------------------------------------------*/
d_tidyup()
{
	gprint("AARRRrrrrgg,  watch out I'm dying!!!\n");
}
d_close()
{
	g_flush();
	path_flush();
	path_free();
	fclose(dout);
#ifndef unix
	printf("Now enter one of:\n");
	printf("   dviprint -depson [-hires] (to print to a dot matrix printer)\n");
	printf("   dviprint -dlj    [-hires] (to print to HP LaserJet/Deskjet)\n");
	printf("   dviprint -dpj    [-hires] (to print to HP Paintjet)\n");
	printf("   dviprint -dvt             (Preview on screen)\n");
	printf("   dviprint                  (to see other valid qualifiers)\n");
#endif
}
/*---------------------------------------------------------------------------*/
d_set_line_cap(int i)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_join(int i)
{
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_miterlimit(double d)
{
	int i=0;
	i++;
}
/*---------------------------------------------------------------------------*/
d_set_line_width(double w)
{
	float dx,dy,zx,zy;

	dxy(w,w,&dx,&dy);
	dxy(0.0,0.0,&zx,&zy);
	path_lwidth(sqrt(pow(dx-zx,2) + pow(dy-zy,2)));
	path_lwidth(w);
}
/*---------------------------------------------------------------------------*/
d_set_line_styled(double dd)
{
	path_dashlen(dd);
}
d_set_line_style(char *s)
{
	static char *defline[] = {"","","12","41","14","92",
        "1282","9229","4114","54"};
	int i,j,nblack,nwhite;
	char *ss;
	long pat;
/* lstyle pattern output in dvi file is a 32 bit integer:
      First 27 bits (starting with MSB) is the pattern, last 5 bits
      (bits 0 to 4) is one less than the number of the last bit in the pattern.
      This allows continuous patterns (no funny glitches every 32 dots).
*/

	if (!g.inpath) g_flush();
	if (strlen(s)==1) s = defline[*s-'0'];
	if (strcmp(s,"")==0) {
		pat = 0x8000001e; 	/* pattern is one dot repeated */
		path_lstyle(pat);
		return;
	}
	ss = s;

        pat = 0;                 /* make up to 27 bit pattern from digits */
	for (i=31; i>4;) {
	    nblack = *s - '0';
	    s++;
	    for (j=0; j<nblack; j++) {
		pat = pat | (1L << i);
		i--;
	    }
	    if (*s == 0)  s = ss;   /* if odd number of digits, repeat */
	    nwhite = *s - '0';
	    s++;
	    i = i - nwhite;
	    if (*s == 0) {          /* stop if at end of digit string */
                if (i < 4)  i = 4;
                pat = (pat & 0xffffffe0) | i;
                break;
            }
	}
	path_lstyle(pat);
/*        printf ("Pattern: %s %X  %d\n", ss, pat, pat&0x1f); */
}
/*---------------------------------------------------------------------------*/
d_fill()
{
	set_fill();
	path_fill();
	set_color();
}
/*---------------------------------------------------------------------------*/
d_fill_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;

	path_move( (*wkx)[0], (*wky)[0]);
	for (i=1;i<nwk;i++) {
		path_line( (*wkx)[i], (*wky)[i]);
	}
	d_fill();
}
d_line_ary(int nwk,double (*wkx)[],double (*wky)[])
{
	int i;

	path_move( (*wkx)[0], (*wky)[0]);
	for (i=1;i<nwk;i++) {
		path_line( (*wkx)[i], (*wky)[i]);
	}
	d_stroke();
}
/*---------------------------------------------------------------------------*/
d_stroke()
{
	path_stroke();
}
/*---------------------------------------------------------------------------*/
d_clip()
{
	path_int(p_clip);
}
/*---------------------------------------------------------------------------*/
d_set_matrix(double newmat[3][3])
{

}
/*---------------------------------------------------------------------------*/
d_move(double zx,double zy)
{
}
/*---------------------------------------------------------------------------*/
d_reverse() 	/* reverse the order of stuff in the current path */
{
}
/*---------------------------------------------------------------------------*/
d_closepath()
{
	path_closepath();
}
int bit_line( double x, double y);
/*---------------------------------------------------------------------------*/
d_line(double zx,double zy)
{
	float dx,dy;
	if (g.xinline==false) {
		dxy(g.curx,g.cury,&dx,&dy);
		path_move(dx,dy);
	}
	if (g.inpath==false) {
		dxy(zx,zy,&dx,&dy);
		path_dline(dx,dy);
		return;
	}
	dxy(zx,zy,&dx,&dy);
	path_line(dx,dy);
}
/*---------------------------------------------------------------------------*/
d_clear()
{
}
/*---------------------------------------------------------------------------*/
d_flush()
{
}
/*---------------------------------------------------------------------------*/
d_arcto(dbl x1,dbl y1,dbl x2,dbl y2,dbl rrr)
{
	df_arcto(x1,y1,x2,y2,rrr);
}
/*---------------------------------------------------------------------------*/
d_arc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	df_arc(r,t1,t2,cx,cy);
}
/*---------------------------------------------------------------------------*/
d_narc(dbl r,dbl t1,dbl t2,dbl cx,dbl cy)
{
	df_arc(r,t1,t2,cx,cy);
}
/*---------------------------------------------------------------------------*/
d_box_fill(dbl x1, dbl y1, dbl x2, dbl y2)
{
	set_fill();
	if (g.inpath==true) dpath_box(x1,y1,x2,y2);
	else {
		g_flush();
		d_newpath();
		dpath_box(x1,y1,x2,y2);
		d_fill();
	}
	set_color();
}
d_box_stroke(dbl x1, dbl y1, dbl x2, dbl y2)
{
	if (g.inpath==true) df_box_stroke(x1,y1,x2,y2);
	else {
		g_flush();
		d_newpath();
		df_box_stroke(x1,y1,x2,y2);
		d_stroke();
	}
}
/*---------------------------------------------------------------------------*/
d_circle_stroke(double zr)
{
	double xx,yy;
	g_get_xy(&xx,&yy);
	df_circle_stroke(zr);
	g_move(xx,yy);
}
d_circle_fill(double zr)
{
	int savep;
	double xx,yy;
	g_get_xy(&xx,&yy);
	savep = g.inpath;
	g.inpath = true;
	set_fill();
	df_circle_fill(zr);
	d_fill();
	set_color();
	g.inpath = savep;
	g_move(xx,yy);
}
/*---------------------------------------------------------------------------*/
int df_bezier(dbl x1,dbl y1,dbl x2,dbl y2,dbl x3,dbl y3);
d_bezier(dbl x1,dbl y1,dbl x2,dbl y2,dbl x3,dbl y3)
{
	float dx1,dy1,dx2,dy2,dx3,dy3,dx0,dy0;

	if (g.xinline==false) {
		dxy(g.curx,g.cury,&dx0,&dy0);
		path_move(dx0,dy0);
	}

	dxy(x1,y1,&dx1,&dy1);
	dxy(x2,y2,&dx2,&dy2);
	dxy(x3,y3,&dx3,&dy3);
	path_bezier(dx1,dy1,dx2,dy2,dx3,dy3);
	if (g.inpath != true) path_stroke();
}
dpath_box(dbl x1,dbl y1,dbl x2,dbl y2)
{
	float dx1,dy1,dx2,dy2,dx3,dy3,dx4,dy4;

	dxy(x1,y1,&dx1,&dy1);
	dxy(x2,y1,&dx2,&dy2);
	dxy(x2,y2,&dx3,&dy3);
	dxy(x1,y2,&dx4,&dy4);

	path_move(dx1,dy1);
	path_line(dx2,dy2);
	path_line(dx3,dy3);
	path_line(dx4,dy4);
	path_closepath();
}
/*---------------------------------------------------------------------------*/
set_color()
{
	colortyp cc;
	cc.l = d_curcolor;
	path_setcolor(cc.b[B_R],cc.b[B_G],cc.b[B_B],cc.b[B_F]);
}
set_fill()
{
	colortyp cc;
	cc.l = d_curfill;
	path_setcolor(cc.b[B_R],cc.b[B_G],cc.b[B_B],cc.b[B_F]);
}
d_set_color(long f)
{
	d_curcolor = f;
	set_color();
}
d_set_fill(long f)
{
	d_curfill = f;
}
/*---------------------------------------------------------------------------*/
d_beginclip()
{
	path_int(p_saveclip);
}
d_endclip()
{
	path_int(p_restoreclip);
}
struct char_data {float wx,wy,x1,y1,x2,y2; };
int font_get_chardata(struct char_data **cd, int ff, int cc);
/*---------------------------------------------------------------------------*/
int safnt;
int simple_char(int cc);
d_char(int font, int cc)
{
	static struct char_data cd;
	static int ix1,ix2,iy1,iy2;
	static int ux,uy;
	char ss[2];

	ss[0] = cc;
	ss[1] = 0;
	if (safnt==0) safnt = pass_font("PLSR");
	if (font_get_encoding(font)>2) {
		my_char(font,cc);
		return;
	}
	my_char(safnt,cc);
}

