#include "project.h" #include /* Kludgy stuff to handle fortran */ static Handle_list handle_list; static int list_created=0; static int serial; static void Data_Destructor(Data data); static void Handle_Destructor(Handle handle); CONSTRUCTOR(Data)=GObj_DefaultConstructor; DESTRUCTOR(Data)=Data_Destructor; CONSTRUCTOR(Handle)=GObj_DefaultConstructor; DESTRUCTOR(Handle)=Handle_Destructor; /* Destructors */ static void Data_Destructor(Data data) { if (data->data) free(data->data); printf("JWG: Freeing data at %08x\n",(unsigned int) data->data); } static void Handle_Destructor(Handle handle) { printf("JWG: Destroying handle %d\n",handle->serial); GObj_Delete(handle->private); fclose(handle->file); if (handle->data) GObj_Delete(handle->data); GObj_Remove(handle_list,handle); } static Handle handle_from_serial(int serial) { Handle ret; ret=handle_list->head; while (ret) { if (ret->serial==serial) return(ret); ret=ret->next; } printf("JWG: Could not find handle associated with serial %d\n",serial); printf("JWG: Expect very bad things to happen.\n"); return(ret); } /* C visible stuff */ static char * jwg_fiddle_text(char *str,int len) { char *s,*ptr; s=(char *) malloc(len+1024); bcopy(str,s,len); ptr=s+len; while ((ptr--)>s) { if (isgraph(*ptr)) { ptr=s; } else { *ptr=0; } } return(s); } INTERNAL void jwg_xform(Handle h,Jwgpos *pos) { float x,y; x=pos->x; y=pos->y; pos->x=h->transform.xc+(h->transform.a*x)+(h->transform.b*y); pos->y=h->transform.yc+(h->transform.c*x)+(h->transform.d*y); } static void jwg_recalc_det(Handle h) { Transform t=h->transform; h->transform.det=(t.a*t.d)-(t.b*t.c); if (h->transform.det==0.0) { printf("JWG: Your transform matrix is now singular - I hope\n"); printf("JWG: you know what you are doing.\n"); } } /* Ok this is a horid kludge for devices that can't do things */ /* like text at a reasonable angle....*/ /* N describes the handedness of the devices */ /* coord system 1=left handed (assumes y is inverted) */ static float jwg_decompose_matrix(Transform t,int n) { float m1,m2,r; float th; /* We're in trouble if there's a reflection in there so */ /* Patch it up! */ if (n) { t.c=-t.c; t.d=-t.d; } if (t.det<0) { printf("JWG: jwg_decompose_matrix found a reflection. You are probably trying\n"); printf("JWG: to write text backwards on a device which can't\n"); t.c=-t.c; t.d=-t.d; } m1=hypot(t.a,t.c); m2=hypot(t.b,t.d); if (m1>m2) { r=m1/m2; } else { r=m2/m1; } if (r>1.001) { printf("JWG: jwg_decompse_matrix found a non conformal transformation expect\n"); printf("JWG: angles to be wrong\n"); } th=atan2(t.c,t.a); return(th); } static Transform jwg_unitize(Transform t) { Transform ret; ret.a=t.a/t.det; ret.b=t.b/t.det; ret.c=t.c/t.det; ret.d=t.d/t.det; ret.det=1.0; return(ret); } static void init_pen(Pen *pen) { pen->width=0.0; pen->color.r=0.0; pen->color.g=0.0; pen->color.b=0.0; } static void init_brush(Brush *brush) { brush->density=1.0; brush->color.r=0.0; brush->color.g=0.0; brush->color.b=0.0; } static void init_ink(Ink *ink) { ink->font=0; ink->color.r=0.0; ink->color.g=0.0; ink->color.b=0.0; ink->height=10.0; } static void init_transform(Handle h) { h->transform.xc=0.0; h->transform.yc=0.0; h->transform.a=1.0; h->transform.b=0.0; h->transform.c=0.0; h->transform.d=1.0; switch(h->format) { case 0: xfig_init_xform(h); break; case 1: cgm_init_xform(h); break; default: printf("JWG: Cannot find initial xform matrix - you have probably\n"); printf("JWG: Specified an unknown format - using identity matrix\n"); } jwg_recalc_det(h); /* Kludge*/ h->ink.height*=h->transform.det; } INTERNAL void jwg_write_line(Handle h,Jwgline *line) { switch (h->format) { case 0: xfig_do_line(h,line); break; case 1: cgm_do_line(h,line); break; } } INTERNAL void jwg_write_polygon(Handle h,Jwgline *line) { switch (h->format) { case 0: xfig_do_poly(h,line); break; case 1: cgm_do_poly(h,line); break; } } static void jwg_print_transform(Transform t) { printf("/%03.3f %03.3f %03.3f\\\n",t.a,t.b,t.xc); printf("|%03.3f %03.3f %03.3f|\n",t.c,t.d,t.yc); printf("\\ 0.000 0.000 1.000/\n"); } /* Fortran Visible Stuff */ int jwg_create_handle(int *format,char *fname,int len) { Handle ret; char *name; name=jwg_fiddle_text(fname,len); if (!list_created) { printf("JWG: Initializing\n"); handle_list=NEW_LIST(Handle); serial=1; } if (!name) { printf("JWG: passed null pointer for filename\n"); return(0); } ret=NEW(Handle); printf("JWG: Creating handle %d\n",serial); ret->serial=serial++; ret->format=*format; ret->stack=(Handle) NULL; init_pen(&ret->pen); init_brush(&ret->brush); init_ink(&ret->ink); init_transform(ret); ret->data=(Data) NULL; ret->current_line_size=JWG_DEFAULT_LINE_SIZE; ret->current_line.data=(Jwgpos *) malloc(sizeof(Jwgpos)*ret->current_line_size); ret->current_line.npts=0; ret->file=fopen(name,"w"); if (!ret->file) { printf("JWG: couldn't open file %s: %s",name,strerror(errno)); free(name); return(-1); } free(name); switch(ret->format) { case 0: xfig_init_private(ret); break; case 1: cgm_init_private(ret); break; default: printf("JWG: Unknown format %d\n",ret->format); return(-1); } GObj_InsertTail(handle_list,ret); return(ret->serial); } void jwg_pass_data(int *serial,float *ptr,int *w,int *h,int *l) { Handle ha=handle_from_serial(*serial); int size; Data data; float *dptr; if (ha->data) { printf("JWG: Attempt to pass data when data allready present\n"); printf("JWG: you must first deallocate data resources\n"); return; } data=NEW(Data); ha->data=data; data->w=(*w)+2; data->h=(*h)+2; size=sizeof(float)*(data->w)*(data->h); dptr=data->data=(float *) malloc(size); bzero(dptr,size); printf("JWG: Allocated %d bytes for data at %08x\n",size,(unsigned int) data->data); size=(*w)*sizeof(float); { int mh=(*h); dptr+=data->w; while (mh--) { bcopy(ptr,dptr+1,size); ptr+=(*l); dptr+=data->w; } } } void jwg_destroy_data(int *serial) { Handle h=handle_from_serial(*serial); if (h->data) GObj_Delete(h->data); h->data=(Data) NULL; } void jwg_set_xform(int *serial,float *xc,float *yc,float *a, float *b, float *c, float *d) { Handle h=handle_from_serial(*serial); h->transform.xc=*xc; h->transform.yc=*yc; h->transform.a=*a; h->transform.b=*b; h->transform.c=*c; h->transform.d=*d; jwg_recalc_det(h); } void jwg_add_xform(int *serial,float *xc,float *yc,float *a, float *b, float *c, float *d) { Handle h=handle_from_serial(*serial); Transform t; t=h->transform; h->transform.xc=(t.a*(*xc))+(t.b*(*yc))+t.xc; h->transform.yc=(t.c*(*xc))+(t.d*(*yc))+t.yc; h->transform.a=(t.a*(*a))+(t.b*(*c)); h->transform.b=(t.a*(*b))+(t.b*(*d)); h->transform.c=(t.c*(*a))+(t.d*(*c)); h->transform.d=(t.c*(*b))+(t.d*(*d)); jwg_recalc_det(h); } void jwg_add_rotation(int *serial,float *th) { Handle h=handle_from_serial(*serial); Transform t; extern double sin(double); float a=cos(*th); float b=-sin(*th); float c=sin(*th); float d=sin(*th); t=h->transform; h->transform.xc=t.xc; h->transform.yc=t.yc; h->transform.a=(t.a*(a))+(t.b*(c)); h->transform.b=(t.a*(b))+(t.b*(d)); h->transform.c=(t.c*(a))+(t.d*(c)); h->transform.d=(t.c*(b))+(t.d*(d)); jwg_recalc_det(h); } void jwg_def_xform(int *serial) { Handle h=handle_from_serial(*serial); init_transform(h); jwg_recalc_det(h); } void jwg_set_brush(int *serial, float *r,float *g,float *b,float *density) { Handle h=handle_from_serial(*serial); h->brush.density=*density; h->brush.color.r=*r; h->brush.color.g=*g; h->brush.color.b=*b; } void jwg_set_pen(int *serial, float *r,float *g,float *b,float *width) { Handle h=handle_from_serial(*serial); extern double sqrt(double); extern double fabs(double); h->pen.width=(*width)*sqrt(fabs(h->transform.det)); h->pen.color.r=*r; h->pen.color.g=*g; h->pen.color.b=*b; } void jwg_set_textcolor(int *serial, float *r,float *g,float *b) { Handle h=handle_from_serial(*serial); h->ink.color.r=*r; h->ink.color.g=*g; h->ink.color.b=*b; } void jwg_set_textheight(int *serial, float *height) { Handle h=handle_from_serial(*serial); extern double hypot(double,double); float moo; moo=hypot(h->transform.b,h->transform.d); h->ink.height=*height*moo; printf("JWG: height is now %f specified %f\n",(float) h->ink.height,*height); } void jwg_contour(int *serial, float *level,int *side,int *lp) { extern void do_contour(Handle,float,int,int); Handle h=handle_from_serial(*serial); printf("JWG: called jwg_contour(%d,%f,%d,%d)\n",*serial,*level,*side,*lp); do_contour( h, *level, *side, *lp); } void jwg_draw_line(int *serial,float *x,float *y,int *n) { Handle h=handle_from_serial(*serial); int m=*n; Jwgline line; Jwgpos *ptr; ptr=line.data=(Jwgpos *) malloc(sizeof(Jwgpos)*(*n)); line.npts=*n; while (m--) { ptr->x=*(x++); ptr->y=*(y++); jwg_xform(h,ptr++); } jwg_write_line(h,&line); } void jwg_draw_polygon(int *serial,float *x, float *y,int *n) { Handle h=handle_from_serial(*serial); int m=*n; Jwgline line; Jwgpos *ptr; ptr=line.data=(Jwgpos *) malloc(sizeof(Jwgpos)*(*n)); line.npts=*n; while (m--) { ptr->x=*(x++); ptr->y=*(y++); jwg_xform(h,ptr++); } jwg_write_polygon(h,&line); } void jwg_reset_point(int *serial) { Handle h=handle_from_serial(*serial); h->current_line.npts=0; } void jwg_add_point(int *serial,float *x,float *y) { Handle h=handle_from_serial(*serial); Jwgpos *ptr; int n; if (h->current_line.npts==h->current_line_size) { /* uh-oh we're about to over flow */ ptr=h->current_line.data; n=h->current_line_size; printf("JWG: Increasing maximum line size from %d to %d\n", n,n*2); h->current_line_size=n*2; h->current_line.data=malloc(sizeof(Jwgpos)*n*2); bcopy(ptr,h->current_line.data,sizeof(Jwgpos)*n); free(ptr); } h->current_line.data[h->current_line.npts].x=*x; h->current_line.data[h->current_line.npts].y=*y; h->current_line.npts++; } void jwg_close_polygon(int *serial) { Handle h=handle_from_serial(*serial); Jwgline line; Jwgpos *ptr; int m; line=h->current_line; if (!line.npts) return; ptr=line.data; m=line.npts; while (m--) { jwg_xform(h,ptr++); } jwg_write_polygon(h,&line); h->current_line.npts=0; } void jwg_close_line(int *serial) { Handle h=handle_from_serial(*serial); Jwgline line; Jwgpos *ptr; int m; line=h->current_line; if (!line.npts) return; ptr=line.data; m=line.npts; while (m--) { jwg_xform(h,ptr++); } jwg_write_line(h,&line); h->current_line.npts=0; } void jwg_destroy_handle(int *serial) { Handle h=handle_from_serial(*serial); GObj_Delete(h); } void jwg_push_state(int *serial) { Handle h=handle_from_serial(*serial); Handle s; s=(Handle) malloc(sizeof(struct Handle_struct)); bcopy(h,s,sizeof(struct Handle_struct)); h->stack=s; /* We also need to have a new current line */ h->current_line.npts=0; h->current_line_size=JWG_DEFAULT_LINE_SIZE; h->current_line.data=(Jwgpos *) malloc(sizeof(Jwgpos)*h->current_line_size); } void jwg_pop_state(int *serial) { Handle h=handle_from_serial(*serial); Handle n,p,s; if (!h->stack) { printf("JWG: attempt to pop from empty stack\n"); printf("JWG: carrying on (probably shouldn't) \n"); return; } if (h->current_line.npts) printf("JWG: warning poping state with non emtpy current line\n"); free(h->current_line.data); n=h->next; p=h->prev; s=h->stack; bcopy(s,h,sizeof(struct Handle_struct)); h->next=n; h->prev=p; free(s); } void jwg_draw_text(int *serial,float *x,float *y,char *str,int len) { Handle h=handle_from_serial(*serial); char *s,*ptr; Jwgpos pos; pos.x=*x; pos.y=*y; jwg_xform(h,&pos); s=jwg_fiddle_text(str,len); switch(h->format) { case 0: xfig_do_text(h,pos,s); break; case 1: cgm_do_text(h,pos,s); break; default: printf("JWG: Text not yet implemented on this device\n"); break; } } void jwg_draw_text_matrix(int *serial,float *x,float *y,float *a,float *b,float *c,float *d,char *str,int len) { Handle h=handle_from_serial(*serial); char *s,*ptr; Jwgpos pos; Transform t; pos.x=*x; pos.y=*y; jwg_xform(h,&pos); t=h->transform; h->transform.a=(t.a*(*a))+(t.b*(*c)); h->transform.b=(t.a*(*b))+(t.b*(*d)); h->transform.c=(t.c*(*a))+(t.d*(*c)); h->transform.d=(t.c*(*b))+(t.d*(*d)); s=jwg_fiddle_text(str,len); switch(h->format) { case 0: xfig_do_text(h,pos,s); break; case 1: cgm_do_text(h,pos,s); break; default: printf("JWG: Text not yet implemented on this device\n"); break; } h->transform=t; }