#include stdio
#include "cgm.h"
#include "scale.h"

/*	CMS Generation: 3                        8-NOV-89
*/

extern FILE *fin,*fout;

/* interior styles */
#define HOLLOW 0
#define SOLID 1
#define	PATTERN 2                   
#define EMPTY 4

/* write bit pattern of header */
write_header(class,element,listlen)
short unsigned class,element,listlen;
{
	short unsigned header;

/* put out header bytes */
	header = 0;
	header= (class<<12)|(element<<5)|(listlen);

/* swap upper/lower bytes */ 
/* god knows why */
	header = (header<<8)|(header>>8);

	fwrite(&header,(size_t)1,(size_t)2,fout);

}

/* write string */
write_string(string)
char string[];
{	int listlen;

	listlen=strlen(string);
	fwrite(&listlen,(size_t)1,(size_t)1,fout);
	fwrite(string,(size_t)1,(size_t)listlen,fout);
	if( listlen %2) fwrite("\0",(size_t)1,(size_t)1,fout);
}

/* write pascal style string */
write_pstring(string)
char string[];
{	int listlen;

	listlen=strlen(string);
	fwrite(&listlen,(size_t)1,(size_t)1,fout);
	fwrite(string,(size_t)1,(size_t)listlen,fout);
	if (!(listlen %2)) fwrite("\0",(size_t)1,(size_t)1,fout);
}


/* write bit pattern of header */
write_integer(number)
int number;
{	
/* swap upper/lower bytes */                    
/* god knows why */
	number = (number<<8)|(number>>8);
	fwrite(&number,(size_t)1,(size_t)2,fout);
}                                         

/* standard mdraw -> metafile header */
standard_header(name)
char name[];
{
	short unsigned class,element,listlen;
	short unsigned header;
	char string[80];

/*** BEGIN METAFILE ***/
	
	listlen=strlen(name)+1;
	listlen += (listlen%2);
	write_header(DELIMITER,BEGIN_META,listlen);
	write_pstring(name);


/*** META_VERSION #1 ***/

	write_header(META_DESC,META_VERSION,2);
   	write_integer(1);

/*** metafile description ***/

	sprintf(string,"MDRAW Metafile Version 1.0");
	listlen=strlen(string)+1;
	listlen += (listlen%2);

	write_header(META_DESC,META_DESCRIPT,listlen);
	write_pstring(string);

/** virtual device coordinate type **/
	write_header(META_DESC,VDC_TYPE,2);
	write_integer(0);

/** integer precision **/
	write_header(META_DESC,INTEGER_PREC,2);
	write_integer(16);

/** REAL precision (32-BIT FIXED POINT) **/
	write_header(META_DESC,REAL_PREC,6);
	write_integer(1);
	write_integer(16);
	write_integer(16);

/** index precision **/
	write_header(META_DESC, INDEX_PREC,2);
	write_integer(16);

/** COLOR precision **/
	write_header(META_DESC, COLOR_PREC,2);
	write_integer(16);

/** COLOR index precision **/
	write_header(META_DESC, COLOR_INDEX_PREC,2);
	write_integer(16);

/** MAX COLOR **/
   	write_header(META_DESC, MAX_COLOR,2);
	write_integer(16);

/** COLOR VAL EXTENT **/
	write_header(META_DESC, COLOR_VAL_EXTANT,12);
	write_integer(0);
	write_integer(0);
	write_integer(0);
	write_integer(0x64);
	write_integer(0x64);
    	write_integer(0x64);

/** META ELEMENT LIST **/

/** FONT LIST **/
	
	write_header(META_DESC,FONT_LIST,31); /* length = partitioned */
	write_integer(0x60);
        write_pstring("Sans-serif Stroke");
        write_pstring("Sans-serif Stroke");
        write_pstring("Sans-serif Stroke");
        write_pstring("Sans-serif Stroke");
        write_pstring("Swiss");
        write_pstring("Swiss");
        write_pstring("Swiss");
        write_pstring("Swiss");

/* application data */
	write_header(EXTERNAL,APPLICATION_DATA,4);
   	write_integer(0x4C42);
	write_integer(0x0101);

	
}

/* standard mdraw -> metafile header */
standard_ending()
{
	short unsigned class,element,listlen;
	short unsigned header;
	char string[80];

/*** END metafile ***/
	write_header(DELIMITER,END_META,0);
	write_integer(0xFFFF);

}

/* standard begin picture stuff */
begin_picture(name)
char name[];
{
	short unsigned class,element,listlen;
	short unsigned header;
	char string[80];

/** begin picture **/
/** begin picture called 'name' **/
	listlen=strlen(name)+1;
	listlen += (listlen%2);
	write_header(DELIMITER,BEGIN_PIC,listlen);
	write_pstring(name);

/** scaling mode **/
	write_header(PICTURE_DESC,SCALING_MOD,6);
	write_integer(0);
	write_integer(0);
	write_integer(0);
	
/** color selection **/
	write_header(PICTURE_DESC,COLOR_SELECTION,2);
	write_integer(0);

/** line width specification **/
	write_header(PICTURE_DESC,LINE_WIDTH_SPEC,2);
	write_integer(0);
   
/** marker size spec **/
	write_header(PICTURE_DESC,MARKER_SIZE_SPEC,2);
	write_integer(0);
                                  
/** edge width spec **/
	write_header(PICTURE_DESC,EDGE_WIDTH_SPEC,2);
	write_integer(0);
	     
/** VDC (virtual device coord) extent **/
	write_header(PICTURE_DESC,VDC_EXTENT,8);
	write_integer(0);
	write_integer(0);
	write_integer(0x7FFF);
	write_integer(0x60B8);

/** begin body **/
	write_header(DELIMITER,BEGIN_PIC_BODY,0);

/** damn color table **/
	write_header(ATTRIBUTE,COLOR_TABLE,31);	/* partitioned length */
	write_integer(0x4A);
	write_integer(0x01);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x03f);
	write_integer(0x00);
	write_integer(0x03f);
	write_integer(0x00);
	write_integer(0x57);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x064);
	write_integer(0x02d);
	write_integer(0x06);

	write_integer(0x030);
	write_integer(0x08);
	write_integer(0x05);
	write_integer(0x030);
	write_integer(0x05);
	write_integer(0x04c);
	write_integer(0x05);
	write_integer(0x05f);

	write_integer(0x064);
	write_integer(0x064);
	write_integer(0x057);
	write_integer(0x05);
	write_integer(0x043);
	write_integer(0x05);
	write_integer(0x02d);
	write_integer(0x00);

	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x00);
	write_integer(0x03f);

/** coordinate integer precision **/
	write_header(CONTROL,VDC_INT_PREC,2);
	write_integer(0x10);
	
/** transparency on */
	write_header(CONTROL,TRANSPARENCY,2);
	write_integer(0x01);

/** clip off **/
	write_header(CONTROL,CLIP_INDICATOR,2);
	write_integer(0x00);



	write_header(ATTRIBUTE,EDGE_COLOR ,02);
	write_integer(0x01);
	write_header(ATTRIBUTE,EDGE_VISIBLE ,02);
	write_integer(0x01);
	write_header(ATTRIBUTE,EDGE_TYPE ,02);
	write_integer(0x01);
	write_header(ATTRIBUTE,EDGE_WIDTH ,02);
	write_integer(0x01);
	write_header(ATTRIBUTE,FILL_COLOR ,02);
	write_integer(0x01);
    	write_header(ATTRIBUTE,INTERIOR_STYLE ,02);
	write_integer(EMPTY); 


	write_header(ATTRIBUTE,TEXT_ALIGNMENT,8);	
	write_integer(1);	/* left alignment */
	write_integer(1);	/* top alignment */
	write_integer(1);
	write_integer(1);

/** stuff **/


}

/* standard begin picture stuff */ 
end_picture()
{

	write_header(DELIMITER,END_PIC,0);
}                                      


set_linestyle(style)
int style;
{
	write_header(ATTRIBUTE,LINE_TYPE,2);
	write_integer(style);
}
set_line_color(color)
int color;
{
	write_header(ATTRIBUTE,LINE_COLOR,2);
	write_integer(color);
}

set_line_width(width)
int width;
{
	write_header(ATTRIBUTE,LINE_WIDTH,2);
	write_integer(width);
}

set_fill_color(color)
int color;
{
	write_header(ATTRIBUTE,FILL_COLOR,2);
	write_integer(color);
}                       

set_fill_style(style)
int style;
{
	write_header(ATTRIBUTE,INTERIOR_STYLE,2);
	write_integer(style);
}

set_text_style(style)
int style;
{                                                    
	write_header(ATTRIBUTE,TEXT_FONT_INDEX,2);
	write_integer(style);
}

set_text_height(height)
int height;
{                                                    
	write_header(ATTRIBUTE,CHARACTER_HEIGHT,2);
	write_integer(height*TEXT_SCALE);
}

box(x,y,w,h)
int x,y,w,h;         
{
	y = MAX_Y-y;
	h = -h;

	write_header(PRIMITIVE,RECTANGLE,8);
	write_integer((int)(X_SCALE*x)+X_OFF);
	write_integer((int)(Y_SCALE*y)+Y_OFF);
	write_integer((int)(X_SCALE*(x+w))+X_OFF);  
	write_integer((int)(Y_SCALE*(y+h))+Y_OFF);

}

line(x,y,w,h)
int x,y,w,h;         
{
	y=MAX_Y-y;
	h= -h;

	write_header(PRIMITIVE,POLYLINE,8);
	write_integer((int)(x*X_SCALE)+X_OFF);
	write_integer((int)(y*Y_SCALE)+Y_OFF);
	write_integer((int)((x+w)*X_SCALE)+X_OFF);  
	write_integer((int)((y+h)*Y_SCALE)+Y_OFF);

}

polyline (dx,dy,n)
int dx[],dy[],n;
{
	int i,x,y;

	if (n> 0x1FFF) 
	{printf("\n Polyline too big n=%d\n",n);
	 return(-1);
	}

	write_header(PRIMITIVE,POLYLINE,31);	/* partitioned */
	write_integer(n*4);	/* four bytes per vertex */

	for(i=0;i<n;i++)
	{                                   
	x=dx[i];
	y=MAX_Y-dy[i];

	write_integer((int)((x)*X_SCALE)+X_OFF);
	write_integer((int)((y)*Y_SCALE)+Y_OFF);
	}

}

circle_arc_center(x,y,dx1,dy1,dx2,dy2,rad)
int x,y,dx1,dy1,dx2,dy2,rad;
{
	y  = MAX_Y-y;

	dy1= MAX_Y-dy1;
	dy2= MAX_Y-dy2;

	write_header(PRIMITIVE,ARC_CIRC_C_OPEN,14);
	write_integer((int)(x*X_SCALE+X_OFF));
	write_integer((int)(y*Y_SCALE+Y_OFF));
	write_integer((int)(dx1*X_SCALE+X_OFF));
	write_integer((int)(dy1*Y_SCALE+Y_OFF));
	write_integer((int)(dx2*X_SCALE+X_OFF));
	write_integer((int)(dy2*Y_SCALE+Y_OFF));
	write_integer((int)(rad*X_SCALE+X_OFF));

}                         

circle_arc_3pt(x,y,dx1,dy1,dx2,dy2)
int x,y,dx1,dy1,dx2,dy2;
{
	y   = MAX_Y-y;
	dy1 = MAX_Y-dy1;
	dy2 = MAX_Y-dy2;

	write_header(PRIMITIVE,ARC_CIRC_3_OPEN,12);
	write_integer((int)(x*X_SCALE+X_OFF));
	write_integer((int)(y*Y_SCALE+Y_OFF));
	write_integer((int)(dx1*X_SCALE+X_OFF));
	write_integer((int)(dy1*Y_SCALE+Y_OFF));
	write_integer((int)(dx2*X_SCALE+X_OFF));
	write_integer((int)(dy2*Y_SCALE+Y_OFF));

}                         

circle(x,y,xr,yr,rad)
int x,y,xr,yr,rad;
{
	int r;

    	if (rad == 0)
		r=(int) sqrt( (xr*xr)+(yr*yr));
	else 
		r=rad;

	y = MAX_Y-y;

	printf(" circle (%d,%d):%d -->\t",x,y,r);
	printf(" CIRCLE (%d,%d):%d\n",(int)(x*X_SCALE)+X_OFF,
		(int)(y*Y_SCALE)+Y_OFF,(int)(r*X_SCALE) );

	write_header(PRIMITIVE,CIRCLE,6);
	write_integer( (int)(x*X_SCALE)+X_OFF);
	write_integer( (int)(y*Y_SCALE)+Y_OFF);
	write_integer( (int)(r*X_SCALE));


}


text(x,y,string)
int x,y;
char string[];
{	int len;

	y= MAX_Y-y;

	len= 1+strlen(string);
	write_header(PRIMITIVE,TEXT,6+len);
	write_integer((int)(x*X_SCALE+X_OFF));
	write_integer((int)(y*Y_SCALE+Y_OFF-200)); /* offset to look good */
	write_integer(0x01);	/* final */
	write_pstring(string);

}


