aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <>2009-02-08 16:49:14 +0000
committerroot <>2009-02-08 16:49:14 +0000
commit8646c6b2ddaf32ac7342cc8b61e559d46885af4f (patch)
tree226d8347d9c674ed6f2d0a185b904e5f57037c42
parent5d3e093d432a31fb8a8267cbf30f1ed892f49508 (diff)
downloadlibjwg-8646c6b2ddaf32ac7342cc8b61e559d46885af4f.tar.gz
libjwg-8646c6b2ddaf32ac7342cc8b61e559d46885af4f.tar.bz2
libjwg-8646c6b2ddaf32ac7342cc8b61e559d46885af4f.zip
*** empty log message ***
-rw-r--r--src/Makefile.am8
-rw-r--r--src/cgm.c231
-rw-r--r--src/contour.c383
-rw-r--r--src/ctext.c18
-rw-r--r--src/fish.h102
-rw-r--r--src/fortran.h24
-rw-r--r--src/ftext.c0
-rw-r--r--src/ftext.f29
-rw-r--r--src/libjwg.c815
-rw-r--r--src/project.h77
-rw-r--r--src/xfig.c253
11 files changed, 1851 insertions, 89 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index fb8a416..17c94d8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,9 @@
# $Id$
#
# $Log$
+# Revision 1.2 2009/02/08 16:48:21 root
+# *** empty log message ***
+#
# Revision 1.1 2009/02/08 16:25:32 root
# *** empty log message ***
#
@@ -17,10 +20,11 @@
INCLUDES =
-SRCS= libjwg.c version.c
+SRCS= libjwg.c version.c cgm.c contour.c ctext.c ftext.c version.c xfig.c
+FSRCS=ftext.f
CPROTO=cproto
-JWGSRCS=${SRCS}
+JWGSRCS=${SRCS} ${FSRCS}
noinst_HEADERS= project.h prototypes.h jwg-tail.h ext_prototypes.h
diff --git a/src/cgm.c b/src/cgm.c
new file mode 100644
index 0000000..18bd762
--- /dev/null
+++ b/src/cgm.c
@@ -0,0 +1,231 @@
+#include "project.h"
+#include "cd/cd.h"
+BEGIN_OBJECT(CGMc)
+ int r,g,b,n;
+END_OBJECT(CGMc)
+
+CREATOR(CGMc)=Obj_DefaultCreator;
+DESTRUCTOR(CGMc)=Obj_DefaultDestructor;
+
+BEGIN_OBJECT(Private)
+ CGMc_list cgmcs;
+ int maxcol;
+ cdImagePtr im;
+ FILE *file;
+END_OBJECT(Private)
+
+
+int cgm_sortout_color(Private p,int r,int g,int b)
+{
+CGMc c;
+
+c=p->cgmcs->head;
+
+while (c)
+{
+if ((c->r==r) && (c->g==g) && (c->b==b)) return(c->n);
+c=c->next;
+}
+
+
+c=CREATE_OBJ(CGMc);
+c->r=r;
+c->g=g;
+c->b=b;
+c->n=cdImageColorAllocate(p->im,r,g,b);
+
+Obj_Insert(p->cgmcs,c,ObjInsertHead);
+
+
+return(c->n);
+}
+
+static void private_constructor(Private p)
+{
+char name[1024];
+
+p->cgmcs=CREATE_LIST(CGMc);
+/* We need a square image otherwise nasty things happen to
+lines!*/
+p->im=cdImageCreate(7100,7100);
+}
+
+static void private_destructor(Private p)
+{
+CGMc c;
+int i;
+
+printf("JWG: Writing cgm file \n");
+
+Obj_Delete(p->cgmcs);
+
+cdImageCgm(p->im,p->file);
+cdImageDestroy(p->im);
+
+free(p);
+}
+
+
+CREATOR(Private)=private_constructor;
+DESTRUCTOR(Private)=private_destructor;
+
+
+void cgm_init_private(Handle h)
+{
+Private p;
+
+p=CREATE_OBJ(Private);
+p->file=h->file;
+
+h->private=(void *) p;
+
+}
+
+
+
+void cgm_do_line(Handle h,Jwgline *line)
+{
+Private p=(Private) h->private;
+int i,c;
+int r,g,b;
+int n=line->npts;
+int w;
+cdPointPtr ptr,base;
+
+r=(int) (h->pen.color.r*255.0);
+g=(int) (h->pen.color.g*255.0);
+b=(int) (h->pen.color.b*255.0);
+c=cgm_sortout_color(p,r,g,b);
+
+
+if (h->pen.width==0.0) {
+ w=1;
+} else {
+ w=(int) (h->pen.width/7.10);
+ if (w<1) w=1;
+}
+
+cdSetLineWidth(p->im,w);
+cdSetLineType(p->im,1);
+cdSetLineColor(p->im,c);
+
+ptr=base=(cdPointPtr) malloc(sizeof(struct cdPointStruct) * n);
+
+for (i=0;i<n;++i) {
+
+ptr->x=(int) line->data[i].x;
+ptr->y=(int) line->data[i].y;
+ptr++;
+}
+
+cdPolyLine(p->im,base,n);
+
+free(base);
+
+
+}
+
+void cgm_init_xform(Handle h)
+{
+/* this should map 1000,1414.21 to an A4 page */
+
+h->transform.xc=0.0;
+h->transform.yc=0.0;
+h->transform.a=5.0;
+h->transform.d=5.0;
+
+h->transform.b=0.0;
+h->transform.c=0.0;
+
+
+}
+
+void cgm_do_poly(Handle h,Jwgline *line)
+{
+int i,c;
+int r,g,b;
+int n=line->npts;
+Private p=(Private) h->private;
+cdPointPtr ptr,base;
+
+r=(int) (h->brush.color.r*255.0);
+g=(int) (h->brush.color.g*255.0);
+b=(int) (h->brush.color.b*255.0);
+c=cgm_sortout_color(p,r,g,b);
+
+cdSetFillStyle(p->im,1);
+cdSetFillColor(p->im,c);
+cdSetEdgeVis(p->im,0);
+
+ptr=base=(cdPointPtr) malloc(sizeof(struct cdPointStruct) * n);
+
+for (i=0;i<n;++i) {
+
+ptr->x=(int) line->data[i].x;
+ptr->y=(int) line->data[i].y;
+ptr++;
+}
+
+cdPolygon(p->im,base,n);
+
+free(base);
+
+}
+
+
+void cgm_do_text(Handle h,Jwgpos pos,char *str)
+{
+int color,r,g,b;
+Transform t=h->transform;
+Private p=(Private) h->private;
+float s;
+int height;
+
+height=(int) h->ink.height;
+
+r=(int) (h->ink.color.r*255.0);
+g=(int) (h->ink.color.g*255.0);
+b=(int) (h->ink.color.b*255.0);
+color=cgm_sortout_color(p,r,g,b);
+
+if (t.det<0) {
+ printf("JWG: Text cannot be written backwards in a CGM file\n");
+ return;
+}
+
+{
+float a,b,c,d;
+
+a=fabs(t.a);
+b=fabs(t.b);
+c=fabs(t.c);
+d=fabs(t.d);
+
+s=(a>b) ? a: ((b>c) ? b: ((c>d) ? c: d));
+
+s=16384.0/s;
+
+
+}
+
+{
+int a,b,c,d;
+
+a=(int) (s*t.a);
+b=(int) (s*t.b);
+c=(int) (s*t.c);
+d=(int) (s*t.d);
+
+printf("JWG: Text vectors are up=(%d,%d) right=(%d,%d)\n",c,d,a,b);
+cdSetTextOrient(p->im, c, d, a, b);
+}
+
+cdSetTextHeight(p->im,height);
+
+cdSetTextFont(p->im,5);
+cdSetTextColor(p->im,color);
+
+cdText(p->im,(int) pos.x,(int) pos.y,str);
+
+return;
+}
diff --git a/src/contour.c b/src/contour.c
new file mode 100644
index 0000000..8022adb
--- /dev/null
+++ b/src/contour.c
@@ -0,0 +1,383 @@
+#include "project.h"
+
+#ifndef PI
+#define PI 3.141592654
+#endif
+
+
+typedef struct {
+ int x, y;
+} Point;
+
+typedef struct contour_struct {
+ float *data;
+ float **dcol;
+ unsigned char *flags;
+ unsigned char **fcol;
+ int x, y;
+ int x1, y1;
+ Jwgline current_line;
+ int current_line_size;
+ int lp;
+ Handle h;
+} *Contour;
+
+
+#define INRANGE(l1,l2,c) ( ((c)<(l2)) && ((c)>=(l1)) )
+#define RANGEX(c,x) ( ((x)>0) ? ( ((x)<((c)->x1)) ? (x):((c)->x1)) : 1)
+#define RANGEY(c,y) (((y)>0) ? ( ((y)<((c)->y1)) ? (y):((c)->y1)) : 1)
+
+#define FLAGS(c,p) ((c->fcol[p.y])[p.x])
+#define DATA(c,p) ((c->dcol[p.y])[p.x])
+
+#define DEF_LINE_SIZE 8192
+
+
+
+
+
+void
+cont_reset_point(Contour c)
+{
+ c->current_line.npts = 0;
+}
+
+void
+cont_add_point(Contour c, Jwgpos pos)
+{
+ Jwgpos *ptr;
+ int n;
+
+ if (c->current_line.npts == c->current_line_size) {
+ /* uh-oh we're about to over flow */
+
+ ptr = c->current_line.data;
+
+
+ n = c->current_line_size;
+ printf("JWG: CONTOUR: Increasing maximum line size from %d to %d\n",
+ n, n * 2);
+
+ c->current_line_size = n * 2;
+
+ c->current_line.data = malloc(sizeof(Jwgpos) * n * 2);
+ bcopy(ptr, c->current_line.data, sizeof(Jwgpos) * n);
+
+ free(ptr);
+
+ }
+ jwg_xform(c->h, &pos);
+
+ c->current_line.data[c->current_line.npts] = pos;
+ c->current_line.npts++;
+
+}
+
+unsigned char
+find_direction(Point p1, Point p2)
+{
+ p2.x -= p1.x;
+ p2.y -= p1.y;
+
+ switch (p2.y) {
+ case -1:
+ switch (p2.x) {
+ case -1:
+ return (1);
+ case 0:
+ return (2);
+ case 1:
+ return (4);
+ }
+ case 0:
+ switch (p2.x) {
+ case -1:
+ return (128);
+ case 1:
+ return (8);
+ }
+ case 1:
+ switch (p2.x) {
+ case -1:
+ return (64);
+ case 0:
+ return (32);
+ case 1:
+ return (16);
+ }
+ }
+
+
+ fprintf(stderr, "Contouring cockup type 3 ... (bye bye)\n");
+ abort();
+
+}
+
+Point
+add_direction(Point p, int d)
+{
+ Point dirs[8] = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}};
+
+ p.x = dirs[d].x;
+ p.y = dirs[d].y;
+
+ return (p);
+}
+
+
+int
+points_marked(Contour c, Point p1, Point p2)
+{
+ return (c->fcol[p1.y])[p1.x] & find_direction(p1, p2);
+}
+
+void
+mark_points(Contour c, Point p1, Point p2)
+{
+ (c->fcol[p1.y])[p1.x] |= find_direction(p1, p2);
+ (c->fcol[p2.y])[p2.x] |= find_direction(p2, p1);
+}
+
+
+
+trace(Contour c, Point p1, Point p2, Point pl, float level)
+{
+ Point pn;
+ float v1, v2, vn;
+ Jwgpos pos;
+ float r;
+
+printf(".");
+fflush(stdout);
+
+ if (!c->lp)
+ {
+ pos.x = 1;
+ pos.y = 1;
+
+ cont_add_point(c, pos);
+ }
+
+ v1 = DATA(c, p1);
+ v2 = DATA(c, p2);
+
+ while (1) {
+
+ /*
+ * printf("(%d,%d,%f) (%d,%d,%f) (%d,%d,%f)\n", p1.x, p1.y, DATA(c, p1),
+ * p2.x, p2.y, DATA(c, p2), pl.x, pl.y, DATA(c, pl));
+ */
+
+ r = (v2 - v1);
+ if (r == 0.0) {
+ r = 0.5;
+ } else {
+ r = (level - v1) / r;
+ }
+
+ pos.x = r * (float) RANGEX(c, p2.x);
+ pos.y = r * (float) RANGEY(c, p2.y);
+
+ r = 1.0 - r;
+
+ pos.x += r * (float) RANGEX(c, p1.x);
+ pos.y += r * (float) RANGEY(c, p1.y);
+
+ cont_add_point(c, pos);
+
+
+
+
+
+
+
+ if (DATA(c, p1) > level) {
+ printf("Contouring cockup type 1 -- bye bye\n");
+ abort();
+ }
+ if (DATA(c, p2) <= level) {
+ printf("Contouring cockup type 2 -- bye bye\n");
+ abort();
+ }
+ if (points_marked(c, p1, p2)) {
+ if (c->lp) {
+ jwg_write_line(c->h, &c->current_line);
+ c->current_line.npts = 0;
+ } else {
+ pos.x = 1;
+ pos.y = 1;
+
+ cont_add_point(c, pos);
+ }
+
+
+ return;
+ }
+ mark_points(c, p1, p2);
+
+ pn.x = p1.x + p2.x - pl.x;
+ pn.y = p1.y + p2.y - pl.y;
+
+ vn = DATA(c, pn);
+
+ if (vn <= level) {
+ pl = p1;
+ p1 = pn;
+ v1 = vn;
+ } else {
+ pl = p2;
+ p2 = pn;
+ v2 = vn;
+ }
+
+
+
+
+ }
+
+}
+
+
+
+
+
+possible(Contour c, int x1, int y1, int x2, int y2, int xl, int yl, float level)
+{
+ Point p1, p2, pl;
+
+ p1.x = x1;
+ p1.y = y1;
+ p2.x = x2;
+ p2.y = y2;
+ pl.x = xl;
+ pl.y = yl;
+
+ if (points_marked(c, p1, p2))
+ return;
+
+ trace(c, p1, p2, pl, level);
+
+
+}
+
+
+contour(Contour c, float level)
+{
+ int x, y;
+ float **c0, **c1;
+ float *r00, *r10, *r11, *r01;
+
+ c1 = c0 = c->dcol;
+ c1--;
+
+ for (y = 0; y < c->y; ++y) {
+ r00 = r01 = *(c0);
+ r01--;
+ if (y) {
+ r10 = r11 = *(c1);
+ r11--;
+ }
+ for (x = 0; x < c->x; ++x) {
+
+ if (x) {
+ if (INRANGE(*r00, *r01, level))
+ possible(c, x, y, x - 1, y, x, y - 1, level);
+ if (INRANGE(*r01, *r00, level))
+ possible(c, x - 1, y, x, y, x - 1, y + 1, level);
+ }
+ if (y) {
+ if (INRANGE(*r00, *r10, level))
+ possible(c, x, y - 1, x, y, x - 1, y, level);
+ if (INRANGE(*r10, *r00, level))
+ possible(c, x, y, x, y - 1, x + 1, y - 1, level);
+ }
+ r00++;
+ r10++;
+ r11++;
+ r01++;
+ }
+ c0++;
+ c1++;
+ }
+
+}
+
+
+
+void
+do_contour(Handle h, float level, int side, int lp)
+{
+ Contour c = (Contour) malloc(sizeof(struct contour_struct));
+ int i;
+ float hug = 1.0e10 * (float) side;
+
+
+ c->data = h->data->data;
+ c->x1 = c->x = h->data->w;
+ c->y1 = c->y = h->data->h;
+
+
+ c->dcol = (float **) malloc(sizeof(float *) * c->y);
+
+
+
+ c->dcol[0] = c->data;
+ for (i = 1; i < c->y; ++i)
+ c->dcol[i] = c->dcol[i - 1] + c->x;
+
+ c->flags = (unsigned char *) malloc(c->x * c->y);
+ bzero(c->flags, c->x * c->y);
+
+ c->fcol = (unsigned char **) malloc(c->y * sizeof(unsigned char *));
+
+ c->fcol[0] = c->flags;
+ for (i = 1; i < c->y; ++i)
+ c->fcol[i] = c->fcol[i - 1] + c->x;
+
+ c->x1--;
+ c->y1--;
+
+ for (i = 0; i < c->y; ++i) {
+ (c->dcol[i])[0] = hug;
+ (c->dcol[i])[c->x1] = hug;
+ }
+ for (i = 0; i < c->x; ++i) {
+ (c->dcol[0])[i] = hug;
+ (c->dcol[c->y1])[i] = hug;
+ }
+
+ c->x1--;
+ c->y1--;
+
+ /*
+ * { Point p;
+ *
+ * for (p.y=0;p.y<c->y;++p.y) { for (p.x=0;p.x<c->x;++p.x) {
+ *
+ * printf("%.1f ",DATA(c,p));
+ *
+ * } printf("\n");
+ *
+ * }
+ * } */
+
+ c->current_line.npts = 0;
+ c->current_line_size = DEF_LINE_SIZE;
+ c->current_line.data = (Jwgpos *) malloc(sizeof(Jwgpos) * DEF_LINE_SIZE);
+
+ c->h = h;
+ c->lp = lp;
+
+ contour(c, level);
+ printf("\n");
+
+
+ if (!c->lp)
+ jwg_write_polygon(c->h, &c->current_line);
+
+ free(c->flags);
+ free(c->fcol);
+ free(c->dcol);
+ free(c->current_line.data);
+
+}
diff --git a/src/ctext.c b/src/ctext.c
new file mode 100644
index 0000000..4f82832
--- /dev/null
+++ b/src/ctext.c
@@ -0,0 +1,18 @@
+#include "project.h"
+
+Textrequest_list textrequests;
+
+void jwg_priv_init_textlist()
+{
+
+
+
+
+
+
+
+
+
+}
+
+
diff --git a/src/fish.h b/src/fish.h
new file mode 100644
index 0000000..1a7a874
--- /dev/null
+++ b/src/fish.h
@@ -0,0 +1,102 @@
+#include <string.h>
+
+typedef struct {
+ float x,y;
+} Jwgpos;
+
+typedef struct {
+ Jwgpos *data;
+ int npts;
+} Jwgline;
+
+
+
+typedef struct {
+ float xc,yc;
+ float a,b,c,d;
+ float det;
+} Transform;
+
+BEGIN_OBJECT(Data)
+ int w,h;
+ int l;
+ float *data;
+END_OBJECT(Data);
+
+extern void Data_Destructor(Data);
+
+CREATOR(Data)=Obj_DefaultCreator;
+DESTRUCTOR(Data)=Data_Destructor;
+
+typedef struct {
+ float r,g,b;
+} Color;
+
+typedef struct {
+ float width;
+ Color color;
+} Pen;
+
+typedef struct {
+ float density;
+ Color color;
+} Brush;
+
+typedef struct {
+ int font;
+ Color color;
+ float height;
+} Ink;
+
+
+#define JWG_FM_XFIG 0
+#define JWG_FM_CGM 1
+
+#define JWG_DEFAULT_LINE_SIZE 4096
+
+BEGIN_OBJECT(Handle)
+ int serial;
+
+ struct Handle_struct *stack;
+
+ Data data;
+ Transform transform;
+
+ Brush brush;
+ Pen pen;
+ Ink ink;
+
+ int format;
+ FILE *file;
+
+ Jwgline current_line;
+ int current_line_size;
+
+ void *private;
+END_OBJECT(Handle)
+
+extern void Handle_Destructor(Handle);
+
+CREATOR(Handle)=Obj_DefaultCreator;
+DESTRUCTOR(Handle)=Handle_Destructor;
+
+extern void jwg_xform(Handle,Jwgpos *);
+extern void jwg_write_line(Handle,Jwgline *);
+extern void jwg_write_polygon(Handle,Jwgline *);
+
+extern float jwg_decompose_matrix(Transform,int);
+
+
+extern int jwg_create_handle(int *,char *,int);
+extern void jwg_pass_data(int *,float *,int *,int *,int *);
+extern void jwg_destory_data(int *);
+extern void jwg_set_xform(int *,float *,float *,float *,float *, float *, float *);
+extern void jwg_set_brush(int *, float *,float *,float *,float *);
+extern void jwg_set_pen(int *, float *,float *,float *,float *);
+extern void jwg_set_textcolor(int *,float *,float *,float *);
+extern void jwg_set_textheight(int *,float *);
+extern void jwg_draw_text(int *,float *,float *,char *,int);
+extern void jwg_contour(int *, float *,int *,int *);
+extern void jwg_draw_line(int *,float *,float *,int *);
+extern void jwg_draw_polygon(int *,float *,float *,int *);
+extern void jwg_destroy_handle(int *);
diff --git a/src/fortran.h b/src/fortran.h
new file mode 100644
index 0000000..22c2cd1
--- /dev/null
+++ b/src/fortran.h
@@ -0,0 +1,24 @@
+#define FORT(x) x ## __
+
+#define jwg_create_handle FORT(jwg_create_handle)
+#define jwg_pass_data FORT(jwg_pass_data)
+#define jwg_destroy_data FORT(jwg_destroy_data)
+#define jwg_set_xform FORT(jwg_set_xform)
+#define jwg_set_brush FORT(jwg_set_brush)
+#define jwg_set_pen FORT(jwg_set_pen)
+#define jwg_contour FORT(jwg_contour)
+#define jwg_draw_line FORT(jwg_draw_line)
+#define jwg_draw_polygon FORT(jwg_draw_polygon)
+#define jwg_destroy_handle FORT(jwg_destroy_handle)
+#define jwg_pop_state FORT(jwg_pop_state)
+#define jwg_push_state FORT(jwg_push_state)
+#define jwg_add_xform FORT(jwg_add_xform)
+#define jwg_def_xform FORT(jwg_def_xform)
+#define jwg_add_point FORT(jwg_add_point)
+#define jwg_reset_point FORT(jwg_reset_point)
+#define jwg_close_line FORT(jwg_close_line)
+#define jwg_close_polygon FORT(jwg_close_polygon)
+#define jwg_draw_text FORT(jwg_draw_text)
+#define jwg_set_textcolor FORT(jwg_set_textcolor)
+#define jwg_set_textheight FORT(jwg_set_textheight)
+#define jwg_draw_text_matrix FORT(jwg_draw_text_matrix)
diff --git a/src/ftext.c b/src/ftext.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ftext.c
diff --git a/src/ftext.f b/src/ftext.f
new file mode 100644
index 0000000..f1de29d
--- /dev/null
+++ b/src/ftext.f
@@ -0,0 +1,29 @@
+ function jwg_open_textunit
+
+ integer jwg_priv_init_textlist*4
+
+ parameter (default_textunit=32767)
+
+ character textpipe*1024
+ integer textunit*4,setup*4
+
+
+ setup=jwg_priv_init_textlist
+
+C Is all this gubbins working or do we need to fiddle?
+
+ if (setup.ne.0) then
+C
+C this will check that the string is correctly passed
+C
+ textpipe='sanity check'
+
+ call jwg_priv_setup_textpipe(textpipe)
+
+ textunit=default_textunit
+ open (file=textpipe,unit=textunit,action='write',status=old)
+
+ endif
+
+ jwg_open_textunit=textunit
+
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;
+
+}
diff --git a/src/project.h b/src/project.h
index 7e5289d..4179632 100644
--- a/src/project.h
+++ b/src/project.h
@@ -1,78 +1,17 @@
-/*
- * project.h:
- *
- * Copyright (c) 2009 James McKenzie <20@madingley.org>,
- * All rights reserved.
- *
- */
-
-/*
- * $Id$
- */
-
-/*
- * $Log$
- * Revision 1.1 2009/02/08 16:25:32 root
- * *** empty log message ***
- *
- *
- */
-
-#ifndef __PROJECT_H__
-#define __PROJECT_H__
-
-#include "config.h"
-
-#ifdef TM_IN_SYS_TIME
-#include <sys/time.h>
-#ifdef TIME_WITH_SYS_TIME
-#include <time.h>
-#endif
-#else
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#endif
-#include <time.h>
-#endif
-
#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef HAVE_MALLOC_H
+#include <fcntl.h>
+#include <math.h>
#include <malloc.h>
-#endif
-
-#ifdef HAVE_STRING_H
#include <string.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
#include <strings.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+#include <gobj.h>
-#if defined(HAVE_STDINT_H)
-#include <stdint.h>
-#elif defined(HAVE_SYS_INT_TYPES_H)
-#include <sys/int_types.h>
-#endif
-#ifdef INT_PROTOS
-#define INTERNAL
-#define EXTERNAL
-#else
-#ifdef EXT_PROTOS
-#define INTERNAL static
-#define EXTERNAL
-#else
-#define INTERNAL
-#define EXTERNAL
-#endif
-#endif
+#include "fortran.h"
-#include "prototypes.h"
+#include "jwg.h"
-#endif /* __PROJECT_H__ */
+#define PI 3.141592653589793238462643383276
+#define R2D 57.295779513082320876798154814169
+#define D2R 0.017453292519943295769236907684
diff --git a/src/xfig.c b/src/xfig.c
new file mode 100644
index 0000000..10da5e4
--- /dev/null
+++ b/src/xfig.c
@@ -0,0 +1,253 @@
+#include "project.h"
+
+BEGIN_OBJECT(Xfc)
+ int r,g,b,n;
+END_OBJECT(Xfc)
+
+CREATOR(Xfc)=Obj_DefaultCreator;
+DESTRUCTOR(Xfc)=Obj_DefaultDestructor;
+
+BEGIN_OBJECT(Private)
+ Xfc_list xfcs;
+ int maxcol;
+ FILE *tmpfile;
+ FILE *file;
+END_OBJECT(Private)
+
+static void private_constructor(Private p)
+{
+char name[1024];
+
+p->xfcs=CREATE_LIST(Xfc);
+
+p->tmpfile=fopen(tmpnam(name),"w+");
+
+unlink(name);
+
+
+
+}
+
+#define BUFSIZ 1024
+
+static void private_destructor(Private p)
+{
+Xfc c;
+char buf[BUFSIZ];
+int i;
+
+fflush(p->tmpfile);
+rewind(p->tmpfile);
+
+
+printf("JWG: Writing xfig colors\n");
+
+c=p->xfcs->head;
+
+while (c) {
+fprintf(p->file,"0 %d #%02x%02x%02x\n",c->n,c->r,c->g,c->b);
+c=c->next;
+}
+
+
+Obj_Delete(p->xfcs);
+
+printf("JWG: Writing xfig file\n");
+
+while ((i=fread(buf,1,BUFSIZ,p->tmpfile))>0) {
+
+ fwrite(buf,1,i,p->file);
+}
+
+fclose(p->tmpfile);
+
+printf("JWG: xfig done\n");
+
+
+
+free(p);
+}
+
+
+CREATOR(Private)=private_constructor;
+DESTRUCTOR(Private)=private_destructor;
+
+
+
+
+void xfig_init_private(Handle h)
+{
+Private p;
+
+p=CREATE_OBJ(Private);
+p->maxcol=32;
+p->file=h->file;
+
+h->private=(void *) p;
+
+ fprintf(h->file,"#FIG 3.1\n");
+ fprintf(h->file,"Portrait\nFlush Left\nInches\n1200 2\n");
+
+}
+
+
+int xfig_sortout_color(Handle h,int r,int g,int b)
+{
+Private p=(Private) h->private;
+Xfc c;
+
+c=p->xfcs->head;
+
+while (c)
+{
+if ((c->r==r) && (c->g==g) && (c->b==b)) return(c->n);
+c=c->next;
+}
+
+if (p->maxcol==512) {
+ printf("JWG: Xfig colors exhusted: this kludge needs fixing...\n");
+ return(32);
+}
+
+c=CREATE_OBJ(Xfc);
+c->r=r;
+c->g=g;
+c->b=b;
+c->n=(p->maxcol++);
+
+Obj_Insert(p->xfcs,c,ObjInsertHead);
+
+
+return(c->n);
+}
+
+void xfig_do_line(Handle h,Jwgline *line)
+{
+Private p=(Private) h->private;
+int i,c;
+int r,g,b;
+int w;
+int x,y;
+int n=line->npts;
+extern double sqrt(double);
+extern double fabs(double);
+
+r=(int) (h->pen.color.r*255.0);
+g=(int) (h->pen.color.g*255.0);
+b=(int) (h->pen.color.b*255.0);
+c=xfig_sortout_color(h,r,g,b);
+
+if (h->pen.width==0.0) {
+ w=1;
+} else {
+ w=(int) ((h->pen.width)/15.0);
+ if (w<1) w=1;
+}
+
+
+
+fprintf(p->tmpfile,"2 1 0 %d %d 0 0 0 -1 0.0 1 1 -1 0 0 %d\n",w,c,n);
+
+for (i=0;i<n;++i) {
+
+x=(int) line->data[i].x;
+y=(int) line->data[i].y;
+
+fprintf(p->tmpfile,"%d %d ",x,y);
+}
+fprintf(p->tmpfile,"\n");
+
+
+}
+
+void xfig_init_xform(Handle h)
+{
+
+h->transform.xc=0.0;
+h->transform.yc=14422.8;
+h->transform.a=10.2;
+h->transform.d=-10.2;
+
+h->transform.b=0.0;
+h->transform.c=0.0;
+
+
+}
+
+xfig_do_poly(Handle h,Jwgline *line)
+{
+int i,c;
+int r,g,b;
+int w;
+int x,y;
+int n=line->npts;
+Private p=(Private) h->private;
+
+r=(int) (h->brush.color.r*255.0);
+g=(int) (h->brush.color.g*255.0);
+b=(int) (h->brush.color.b*255.0);
+c=xfig_sortout_color(h,r,g,b);
+
+
+printf("COL FOR POLY %d\n",c);
+
+
+fprintf(p->tmpfile,"2 3 0 0 0 %d 0 0 20 0.0 1 1 -1 0 0 %d\n",c,n+1);
+
+for (i=0;i<n;++i) {
+
+x=(int) line->data[i].x;
+y=(int) line->data[i].y;
+
+fprintf(p->tmpfile,"%d %d ",x,y);
+}
+
+x=(int) line->data->x;
+y=(int) line->data->y;
+
+fprintf(p->tmpfile,"%d %d",x,y);
+
+fprintf(p->tmpfile,"\n");
+
+}
+
+void xfig_do_text(Handle h,Jwgpos pos,char *str)
+{
+int c,r,g,b;
+int x,y;
+double atan2(double,double);
+
+Transform t=h->transform;
+Private p=(Private) h->private;
+int height;
+float angle;
+
+x=(int) pos.x;
+y=(int) pos.y;
+
+height=(int) (h->ink.height/16.66);
+
+r=(int) (h->ink.color.r*255.0);
+g=(int) (h->ink.color.g*255.0);
+b=(int) (h->ink.color.b*255.0);
+c=xfig_sortout_color(h,r,g,b);
+
+
+if (t.det>0) {
+ printf("JWG: Text cannot be written backwards in an xfig file\n");
+ return;
+}
+
+
+angle=-atan2(t.b,t.a);
+
+
+fprintf(p->tmpfile,"4 0 %d 0 0 %d %d %f 4 1 1 %d %d %s\\001\n",c,0,
+ height, angle,x,y,str);
+
+
+
+
+
+return;
+}