/***************************************************************************** ** 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 #include #include #include #include #include #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;ifp=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;iN_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;ifp, " %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;ifp, " -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;ifp, " %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;ifp, " -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; }