aboutsummaryrefslogtreecommitdiffstats
path: root/src/libjwg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjwg.c')
-rw-r--r--src/libjwg.c815
1 files changed, 797 insertions, 18 deletions
diff --git a/src/libjwg.c b/src/libjwg.c
index f12f079..7678091 100644
--- a/src/libjwg.c
+++ b/src/libjwg.c
@@ -1,20 +1,799 @@
-/*
- * libjwg.c:
- *
- * Copyright (c) 2009 James McKenzie <20@madingley.org>,
- * All rights reserved.
- *
- */
-
-static char rcsid[] = "$Id$";
-
-/*
- * $Log$
- * Revision 1.1 2009/02/08 16:25:32 root
- * *** empty log message ***
- *
- *
- */
-
#include "project.h"
+#include <errno.h>
+
+/* Kludgy stuff to handle fortran */
+
+Handle_list handle_list;
+int list_created=0;
+int serial;
+
+
+/* Destructors */
+
+void Data_Destructor(Data data)
+{
+if (data->data) free(data->data);
+
+printf("JWG: Freeing data at %08x\n",(unsigned int) data->data);
+
+}
+
+void Handle_Destructor(Handle handle)
+{
+printf("JWG: Destroying handle %d\n",handle->serial);
+
+Obj_Delete(handle->private);
+
+fclose(handle->file);
+
+if (handle->data) Obj_Delete(handle->data);
+
+Obj_Remove(handle_list,handle);
+free(handle);
+
+}
+
+
+
+
+
+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 */
+
+
+char * jwg_fiddle_text(char *str,int len)
+{
+char *s,*ptr;
+
+s=(char *) malloc(len);
+
+bcopy(str,s,len);
+
+ptr=s+len;
+
+while ((ptr--)>s) {
+
+if (isgraph(*ptr)) {
+ ptr=s;
+} else {
+ *ptr=0;
+}
+
+}
+
+return(s);
+}
+
+
+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);
+
+}
+
+
+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) */
+
+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);
+}
+
+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);
+}
+
+
+
+
+
+void init_pen(Pen *pen)
+{
+pen->width=0.0;
+pen->color.r=0.0;
+pen->color.g=0.0;
+pen->color.b=0.0;
+}
+
+void init_brush(Brush *brush)
+{
+brush->density=1.0;
+brush->color.r=0.0;
+brush->color.g=0.0;
+brush->color.b=0.0;
+
+}
+
+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;
+}
+
+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;
+
+}
+
+
+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;
+}
+
+
+
+}
+
+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;
+}
+
+
+
+
+}
+
+
+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=CREATE_LIST(Handle);
+ serial=1;
+}
+
+if (!name) {
+ printf("JWG: passed null pointer for filename\n");
+ return(0);
+}
+
+ret=CREATE_OBJ(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);
+}
+
+
+
+
+Obj_Insert(handle_list,ret,ObjInsertTail);
+
+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=CREATE_OBJ(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) Obj_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);
+Obj_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;
+
+}