WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / RNAforester / g2-0.70 / src / FIG / g2_FIG.c
diff --git a/binaries/src/ViennaRNA/RNAforester/g2-0.70/src/FIG/g2_FIG.c b/binaries/src/ViennaRNA/RNAforester/g2-0.70/src/FIG/g2_FIG.c
new file mode 100644 (file)
index 0000000..1570738
--- /dev/null
@@ -0,0 +1,486 @@
+/*****************************************************************************
+**  Copyright (C) 1998-2004  Ljubomir Milanovic & Horst Wagner
+**  This file is part of the g2 library
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+
+#include "g2.h"
+#include "g2_device.h"
+#include "g2_util.h"
+#include "g2_config.h"
+
+#include "g2_FIG.h"
+#include "g2_FIG_P.h"
+#include "g2_FIG_funix.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif /* PI */
+
+static int N_FIG=0;
+static g2_FIG_device *g2_FIG_dev=NULL;
+
+/**
+ * \ingroup physdev
+ * \defgroup FIG FIG
+ *
+ * FIG devices generate output in the FIG 3.2 format. For more details
+ * about FIG format and xfig application please visit http://www.xfig.org .
+ *
+ * \note FIG is a vector-oriented (as oposed to pixel-oriented) format.
+ *       Therefore ::g2_image function and splines are not optimally supported. 
+ */
+
+
+/**
+ *
+ * Create a FIG device. g2 uses A4 paper size (landscape orientation) as default.
+ *
+ * \param file_name fig file name
+ *
+ * \return physical device id
+ *
+ * \ingroup FIG
+ */
+G2L int g2_open_FIG(const char *file_name)
+{
+    g2_FIG_device *figout=NULL;
+    int pid=-1, i;
+    int vid;
+    FILE *fp;
+
+    if((fp=fopen(file_name, "w"))==NULL) {
+       g2_log(Error, "g2_attach_PS: Error! Can not open file '%s'\n",
+              file_name);
+       return -1;
+    }
+    
+    if(g2_FIG_dev==NULL) {
+       g2_FIG_dev=g2_malloc(sizeof(g2_FIG_device));
+       N_FIG=1;                                  /* first FIG device */
+       figout=&g2_FIG_dev[N_FIG-1];
+       pid=0;
+    } else {
+       for(i=0;i<N_FIG;i++) {                    /* find free place */
+           if(g2_FIG_dev[i].fp==NULL) {
+               figout=&g2_FIG_dev[i];
+               pid=i;
+               break;
+           }
+       }
+       if(i==N_FIG) {                            /* free place not avail. */
+           N_FIG++;
+           g2_FIG_dev=g2_realloc(g2_FIG_dev, sizeof(g2_FIG_device)*N_FIG);
+           figout=&g2_FIG_dev[N_FIG-1];
+           pid=N_FIG-1;
+       }
+    }
+
+    vid = g2_register_physical_device(pid, NULL,
+                                     g2_IntCoor, g2_FIG_funix,
+                                     1200./80., -1200./80.,
+                                     0.0, 595/72*1200-160);
+                                   /* -180 is a hand-made correcture factor */
+
+    /* init FIG structures */
+    figout->fp=fp;
+    figout->pen_color=1;
+    figout->thickness=-1;
+    figout->font_size=-1;
+    figout->N_inks=0;
+
+    /* write file header (incl. color placeholder) */
+    g2_FIG_write_file_header(figout);
+    
+    /* g2 settings callbacks */
+    g2_allocate_basic_colors(vid);
+    g2_pen(vid, 1);
+    g2_set_line_width(vid, 1);
+    g2_set_dash(vid, 0, NULL);
+    g2_set_font_size(vid, 12);
+
+    return vid;
+}
+
+
+
+/*
+ *
+ *  Write header for fig file
+ *
+ */
+int g2_FIG_write_file_header(g2_FIG_device *fig)
+{
+    int i;
+    
+    fprintf(fig->fp, "#FIG 3.2\n");
+    fprintf(fig->fp, "#Creator: g2 %s\n", G2_VERSION);
+    
+    fprintf(fig->fp, "Landscape\n");
+    fprintf(fig->fp, "Flush Left\n");
+    fprintf(fig->fp, "Metric\n");
+    fprintf(fig->fp, "A4\n");
+    fprintf(fig->fp, "100\n");
+    fprintf(fig->fp, "Single\n");
+    fprintf(fig->fp, "-2\n");
+    fprintf(fig->fp, "1200 2\n");
+
+    /* write placeholder for all colors */
+    fgetpos(fig->fp, &(fig->color_file_pos));
+    for(i=0;i<512;i++)
+       fprintf(fig->fp, "0 %3d #%02x%02x%02x\n",32+i, 0xff, 0xff, 0xff);
+
+    return 0;
+}
+
+
+/*
+ *
+ *    Delete FIG device
+ *
+ */
+int g2_FIG_delete(int pid, void *pdp)
+{
+    int i;
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+
+    /* now write all defined  colors to the reserved place */
+    fsetpos(fig->fp, &(fig->color_file_pos));
+    for(i=0;i<fig->N_inks;i++) {
+       fprintf(fig->fp, "0 %3d #%02x%02x%02x\n",
+               32+i,
+               (int)fig->inks[i].red,
+               (int)fig->inks[i].green,
+               (int)fig->inks[i].blue);
+    }
+    
+    fclose(fig->fp);
+    fig->fp=NULL;                                /* free place */
+    return 0;
+}
+
+
+
+int g2_FIG_ink(int pid, void *pdp,
+             double red, double green, double blue)
+{
+    /* the fig pen space is betwen 32 and 543, total of 512 colors,
+       in g2 implementation from 0000 to 0777.
+       On the other hand ink space is between #000000 and #ffffff. */
+
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+
+    if(fig->N_inks>=512)
+       return -1;
+
+    fig->inks[fig->N_inks].red   = red*0xff;
+    fig->inks[fig->N_inks].green = green*0xff;
+    fig->inks[fig->N_inks].blue  = blue*0xff;
+
+    return fig->N_inks++;
+}
+
+
+
+int g2_FIG_pen(int pid, void *pdp, int color)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+
+    if(color>=fig->N_inks) {
+       return -1;
+    }
+
+    fig->pen_color = 32+color;
+
+    return 0;
+}
+
+
+
+int g2_FIG_set_background(int pid, void *pdp, int color)
+{
+    return -1;
+}
+
+
+
+int g2_FIG_clear_palette(int pid, void *pdp)
+{
+    return -1;
+}
+
+
+
+int g2_FIG_set_line_width(int pid, void *pdp, int w)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fig->thickness = w*80./1200.;
+    return 0;
+}
+
+
+
+int g2_FIG_set_dash(int pid, void *pdp, int N, int *data)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    int black, white;
+    
+    if(N==0 || data==NULL) {
+       fig->line_style=0;
+       fig->style_val=-1;
+       return 0;
+    }
+    if(N<2) {
+       return -1;
+    }
+    black = data[0]*80./1200.;  /* FIG format has no sofistificated dash concept */
+    white = data[1]*80./1200.;  /* we will do out best */
+    if(black<4) {
+       fig->line_style = 2;
+    } else {
+       fig->line_style = 1;
+    }
+    fig->style_val = white;
+    return 0;
+}
+
+
+
+int g2_FIG_set_font_size(int pid, void *pdp, int size)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fig->font_size = size*72./1200.;
+    return 0;
+}
+
+
+
+int g2_FIG_clear(int pid, void *pdp)
+{
+    return -1;
+}
+
+
+
+int g2_FIG_flush(int pid, void *pdp)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fflush(fig->fp);
+    return 0;
+}
+
+
+
+int g2_FIG_plot(int pid, void *pdp, int x, int y)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fprintf(fig->fp, "2 1 0 %d %d -1 1 1 -1 -1 1 0 -1 0 0 2\n",
+           1, fig->pen_color);
+    fprintf(fig->fp, " %d %d\n %d %d\n", x, y, x+1, y);
+    return 0;
+}
+
+
+
+int g2_FIG_line(int pid, void *pdp, int x1, int y1, int x2, int y2)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fprintf(fig->fp, "2 1 %d %d %d -1 1 1 -1 %d 1 0 -1 0 0 2\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->style_val);
+    fprintf(fig->fp, " %d %d\n %d %d\n", x1, y1, x2, y2);
+    return 0;
+}
+
+
+
+int g2_FIG_poly_line(int pid, void *pdp, int N, int *points)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    int i;
+
+    fprintf(fig->fp,"2 1 %d %d %d -1 1 1 -1 %d 1 0 -1 0 0 %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->style_val, N);
+    for(i=0;i<2*N;i+=2) {
+       fprintf(fig->fp, " %d %d\n", points[i], points[i+1]);
+    }
+    return 0;
+}
+
+
+
+int g2_FIG_polygon(int pid, void *pdp, int N, int *points)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    int i;
+
+    if(N<2) {
+       return -1;
+    }
+    
+    fprintf(fig->fp,"2 3 %d %d %d -1 1 1 -1 %d 1 0 -1 0 0 %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->style_val, N+1);
+    for(i=0;i<2*N;i+=2) {
+       fprintf(fig->fp, " %d %d\n", points[i], points[i+1]);
+    }
+    fprintf(fig->fp, " %d %d\n", points[0], points[1]);
+    return 0;
+}
+
+
+
+int g2_FIG_filled_polygon(int pid, void *pdp, int N, int *points)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    int i;
+
+    if(N<2) {
+       return -1;
+    }
+    
+    fprintf(fig->fp,"2 3 %d %d %d %d 1 1 20 %d 1 0 -1 0 0 %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->pen_color,
+           fig->style_val, N+1);
+    for(i=0;i<2*N;i+=2) {
+       fprintf(fig->fp, " %d %d\n", points[i], points[i+1]);
+    }
+    fprintf(fig->fp, " %d %d\n", points[0], points[1]);
+    return 0;
+}
+
+
+int g2_FIG_arc(int pid, void *pdp,
+              int x, int y,
+              int r1, int r2,
+              double a1, double a2)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    double a0, d;
+    double a0_rad, da_rad;
+    int N, i;
+
+    a0=fmod(a1, 360.) + (a1<0? 360:0);   /* map a1 to [0, 360) */
+    d=a2>a1? a2-a1:a2-a1+360;
+
+    N=3+d/18;
+
+    a0_rad = a0*2.*PI/360.;
+    da_rad =  d*2.*PI/360./(N-1);
+
+    fprintf(fig->fp, "3 2 %d %d %d -1 1 -1-1 %d 0 0 0 %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->style_val, N);
+    for(i=0;i<N;i++) {
+       fprintf(fig->fp, " %d %d\n",
+               (int)(x+r1*cos(a0_rad+i*da_rad)),
+               (int)(y-r2*sin(a0_rad+i*da_rad)));
+    }
+    fprintf(fig->fp, " -1");
+    for(i=1;i<N-1;i++) {
+       fprintf(fig->fp, " -1");
+    }
+    fprintf(fig->fp, " -1\n");
+    
+    return 0;
+}
+
+
+int g2_FIG_filled_arc(int pid, void *pdp,
+                     int x, int y,
+                     int r1, int r2,
+                     double a1, double a2)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    double a0, d;
+    double a0_rad, da_rad;
+    int N, i;
+
+    a0=fmod(a1, 360.) + (a1<0? 360:0);   /* map a1 to [0, 360) */
+    d=a2>a1? a2-a1:a2-a1+360;
+
+    N=3+d/18;
+
+    a0_rad = a0*2.*PI/360.;
+    da_rad =  d*2.*PI/360./(N-1);
+
+    fprintf(fig->fp, "3 2 %d %d %d %d 1 -1 20 %d 0 0 0 %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->pen_color,
+           fig->style_val, N+2);
+    for(i=0;i<N;i++) {
+       fprintf(fig->fp, " %d %d\n",
+               (int)(x+r1*cos(a0_rad+i*da_rad)), (int)(y-r2*sin(a0_rad+i*da_rad)));
+    }
+    fprintf(fig->fp, " %d %d\n", x, y); 
+    fprintf(fig->fp, " %d %d\n",
+           (int)(x+r1*cos(a0_rad+0*da_rad)),
+           (int)(y-r2*sin(a0_rad+0*da_rad))); 
+    fprintf(fig->fp, " 0");
+    for(i=1;i<N-1;i++) {
+       fprintf(fig->fp, " -1");
+    }
+    fprintf(fig->fp, " 0 0 0\n");
+    
+    return 0;
+}
+
+
+int g2_FIG_ellipse(int pid, void *pdp,
+                 int x, int y,
+                 int r1, int r2)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fprintf(fig->fp,"1 1 %d %d %d -1  1 -1 -1 %d 1 0.0 %d %d %d %d %d %d %d %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->style_val,
+           x, y, r1, r2, x, y, x+r1, y+r2);
+
+    return 0;
+}
+
+
+int g2_FIG_filled_ellipse(int pid, void *pdp,
+                        int x, int y,
+                        int r1, int r2)
+{
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    fprintf(fig->fp,"1 1 %d %d %d %d 1 -1 20 %d 1 0.0 %d %d %d %d %d %d %d %d\n",
+           fig->line_style, fig->thickness, fig->pen_color, fig->pen_color, fig->style_val,
+           x, y, r1, r2, x, y, x+r1, y+r2);
+
+    return 0;
+}
+  
+
+int g2_FIG_draw_string(int pid, void *pdp,
+                     int x, int y, const char *text)
+{
+    const char *c;
+    g2_FIG_device *fig=&g2_FIG_dev[pid];
+    if(fig->font_size<=0)
+       return 0;
+    fprintf(fig->fp,"4 0 %d 1 -1 0 %d 0 5 %d %d %d %d ",
+           fig->pen_color, fig->font_size, fig->font_size, fig->font_size*strlen(text), x, y);
+    for(c=text;*c;c++) {
+       if(*c=='\\')
+           fputc('\\', fig->fp); /* escape \\ */
+       fputc(*c, fig->fp);
+    }
+    fprintf(fig->fp,"\\001\n");
+    return 0;
+}