/* ======================================================= * * Copyright 1998-2005 Stephen C. Grubb * * http://ploticus.sourceforge.net * * Covered by GPL; see the file ./Copyright for details. * * ======================================================= */ /* SVG Driver for Ploticus - Copyright 2001 Bill Traill (bill@traill.demon.co.uk). * Portions Copyright 2001, 2002 Stephen C. Grubb * Covered by GPL; see the file ./Copyright for details. */ /* Checking for redundant calls is not done here; should be done by caller. special characters not delt with 04Nov01 bt Created svg driver based on existing postscript driver ps.c 12Nov01 bt Changed to relative addressing within a path. Added grouping of styles and a default style in elements Added some shorthand in the entity header Accuracy of some of the coords improved Added stoke to SVGfill to get rid of occasional ghost lines 16Nov01 scg Implemented for improved alignment; implemented .svgz; other integration issues June02 scg clickmap support added */ #ifndef NOSVG #include #include #include #ifdef WZ # include "zlib.h" #endif extern int TDH_err(), PLG_xrgb_to_rgb(), PLG_colorname_to_rgb(), PL_clickmap_out(); extern int atoi(), chmod(), unlink(); /* sure thing or return value not used */ extern int GL_member(), GL_goodnum(); #define Eerr(a,b,c) TDH_err(a,b,c) #define stricmp(a,b) strcasecmp(a,b) #define MARG_X 0 #define MARG_Y 0 static int svg_stdout; /* 1 if svg_fp is stdout */ static FILE *svg_fp; static double svg_x_size; /* width of the drawing area */ static double svg_y_size; /* height of the drawing area */ static int svg_path_in_prog =0; /* flag to indicate if an svg path is in progress */ static char svg_cur_color[80] = "#000000"; static char svg_dash_style[128]; static double svg_line_width=1; static char svg_font_name[100] = ""; /* current font name */ static int svg_chdir; /* char direction in degrees */ static int svg_currpointsz; /* current char size in points */ static char svg_font_weight[100]; static char svg_font_style[100]; static char svg_align[100]; static long svg_bbofs; /* byte offset of viewbox statement as returned by ftell() - scg */ static int svg_pixs_inch; /* number of pixels per inch - scg */ static int svg_dotag = 0; /* if 1, write a suitable html tag to stdout - scg */ static char svg_filename[256] = ""; /* output file name (was local) - scg */ static char svg_style[1024] = ""; /* line,font styles etc */ static char svg_new_style[1024] = ""; static int svg_style_in_prog = 0; /* flag to indicate if a current for attributes is open */ static double svg_last_x; static double svg_last_y; static char *svg_def_fill = "fill:#000000;"; /* char * added - scg */ static char *svg_def_stroke = "stroke:#000000;"; /* char * added - scg */ static char *svg_def_font = "&ff;Helvetica;"; /* char * added - scg */ static int svg_compress = 0; /* 1 = compress output; 0 = don't */ static char svg_compressmode[10] = "wb9"; static char svg_tmpfilename[256] = "/unnamed"; static int svg_tmpfile_used = 0; static char svg_encoding[80] = "iso-8859-1"; static int svg_xmldecl = 1; static int svg_clickmap = 0; static int svg_debug = 0; static char svg_tagparms[80] = ""; /* static char svg_linkparms[128] = ""; */ /* discontinued 5/29/06 - use the new [target=new] syntax in clickmapurl instead */ static int svg_generic_js = 0; static int esc_txt_svg(); static int svg_set_style(); static int svg_print_style(); static int svg_imgsetwidth = 0, svg_imgsetheight = 0; static char svg_imgpathname[256] = ""; /* ============================= */ int PLGS_initstatic() { svg_path_in_prog = 0; svg_line_width = 1; svg_dotag = 0; strcpy( svg_filename, "" ); strcpy( svg_style, "" ); strcpy( svg_new_style, "" ); svg_style_in_prog = 0; svg_compress = 0; strcpy( svg_compressmode, "wb9" ); strcpy( svg_tmpfilename, "/unnamed" ); strcpy( svg_encoding, "iso-8859-1" ); svg_tmpfile_used = 0; svg_xmldecl = 1; svg_clickmap = 0; svg_debug = 0; strcpy( svg_tagparms, "" ); strcpy( svg_cur_color, "#000000" ); svg_imgsetwidth = 0; svg_imgsetheight = 0; strcpy( svg_imgpathname, "" ); if( svg_font_name[0] == '\0' ) strcpy( svg_font_name, "Helvetica" ); return( 0 ); } /* ============================= */ static int svg_set_style() { char fontw[200] = ""; char fonts[200] = ""; char align[200] = ""; char font[200] = ""; char fill[200] = ""; char stroke[200] = ""; if (svg_font_weight[0] != '\0') sprintf(fontw,"&fw;%s;",svg_font_weight); if (svg_font_style[0] != '\0') sprintf(fonts,"&fst;%s;",svg_font_style); sprintf(font,"&ff;%s;",svg_font_name); if (!strcmp(font,svg_def_font)) strcpy(font,""); sprintf(fill,"fill:%s;",svg_cur_color); if (!strcmp(fill,svg_def_fill)) strcpy(fill,""); sprintf(stroke,"stroke:%s;",svg_cur_color); if (!strcmp(stroke,svg_def_stroke)) strcpy(stroke,""); if (!strcmp(svg_align, "start")) strcpy(align,"&as;"); if (!strcmp(svg_align, "middle")) strcpy(align,"&am;"); if (!strcmp(svg_align, "end")) strcpy(align,"&ae;"); sprintf (svg_new_style,"style=\"%s%s%s&sw;%3.1f;%s%s&fs;%dpt;%s\"", /* pt added after font size integer.. scg 3/16/06 */ fill,stroke,font,svg_line_width,fontw,fonts,svg_currpointsz,align); return( 0 ); } /* ============================= */ static int svg_print_style() { if (strcmp(svg_new_style,svg_style) ) { if (svg_style_in_prog) fprintf( svg_fp, ""); fprintf( svg_fp, "\n",svg_new_style); strcpy(svg_style,svg_new_style); svg_style_in_prog = 1; } return( 0 ); } /* ======================================== */ /* SETPARMS - allow caller to pass required parms that svg driver needs - MUST be called before setup() */ int PLGS_setparms( debug, tmpname, clickmap ) int debug; char *tmpname; int clickmap; { svg_debug = debug; sprintf( svg_tmpfilename, "%s_V", tmpname ); svg_clickmap = clickmap; return( 0 ); } /* ============================= */ /* SETUP */ int PLGS_setup( name, dev, outfile, pixs_inch, Ux, Uy, Upleftx, Uplefty ) char *name; /* arbitrary name */ char dev; /* 'p' = monochrome 'c' = color 'e' = eps */ char *outfile; /* file to put code in */ int pixs_inch; double Ux; double Uy; int Upleftx; int Uplefty; { /* set globals */ if( dev != 's' ) dev = 's'; if( svg_font_name[0] == '\0' ) strcpy( svg_font_name, "Helvetica" ); strcpy( svg_font_weight, "" ); strcpy( svg_font_style, "" ); strcpy( svg_align, "start" ); svg_chdir = 0; svg_currpointsz = 10; svg_pixs_inch = pixs_inch; /* scg */ svg_path_in_prog =0; svg_line_width=1; /* svg_dotag = 0; */ /* this may be set to 1 (from command line) before this point, so leave svg_dotag alone.. scg 1/20/06 */ strcpy( svg_style, "" ); strcpy( svg_new_style, "" ); svg_style_in_prog = 0; svg_tmpfile_used = 0; /* determine if we need to write to tmp file, and open appropriate file for write.. */ svg_stdout = 0; if( strcmp( outfile, "stdout" )==0 || outfile[0] == '\0' ) svg_stdout = 1; else strcpy( svg_filename, outfile ); if( svg_stdout || svg_compress ) { svg_fp = fopen( svg_tmpfilename, "w" ); /* output file */ if( svg_fp == NULL ) return( Eerr( 12031, "Cannot open tmp output file", svg_tmpfilename ) ); svg_tmpfile_used = 1; } else { svg_fp = fopen( svg_filename, "w" ); if( svg_fp == NULL ) return( Eerr( 12031, "Cannot open output file", svg_filename ) ); } if( svg_fp == NULL ) return( Eerr( 12031, "Cannot open output file", svg_filename ) ); svg_x_size = Ux * pixs_inch; svg_y_size = Uy * pixs_inch; /* print header */ if( svg_xmldecl ) fprintf( svg_fp, "\n", svg_encoding ); /* changing this section as a result of echlin mouseover enhancement.. scg 6/21/04 */ fprintf( svg_fp, " \n" ); fprintf( svg_fp, " \n" ); } /* this section was: * fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "\n"); fprintf( svg_fp, "]>\n"); fprintf( svg_fp, "\n"); svg_bbofs = ftell( svg_fp ); /* remember location of the viewBox line so we can update it later.. -scg */ /* */ /* these two statements will be overridden at eof when bounding box is known.. -scg */ /* a significant amount of padding is provided */ /* xmlns= added 10/2/03 scg */ fprintf( svg_fp, "\n" ); fprintf( svg_fp, "\n" ); /* close default style */ #ifdef PLOTICUS if( svg_clickmap ) { /* set a style for clickmap section */ if( svg_debug ) fprintf( svg_fp, "\n" ); else fprintf( svg_fp, "\n" ); PL_clickmap_out( 0, 0 ); /* this will call PLGS_clickregion() (herein).. */ fprintf( svg_fp, "\n" ); /* close style */ } #endif fprintf( svg_fp, "\n" ); /* close translation transform -scg */ fprintf( svg_fp, "\n" ); /* now go back and update viewbox - scg */ fseek( svg_fp, svg_bbofs, SEEK_SET ); /* xmlns= added 10/2/03 scg */ fprintf( svg_fp, " viewBox=\"0 0 %-5.2f %-5.2f\" %s \n", (x2-x1) * svg_pixs_inch, (y2-y1) * svg_pixs_inch, svg_tagparms ); fprintf( svg_fp, " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" ); if( svg_clickmap && !svg_generic_js ) { /* all this is replicated below (search on "bbofs") */ fprintf( svg_fp, " onload=\"init(evt)\"\n" ); /* xmlns:xlink used to be here.. scg 3/16/06 */ fprintf( svg_fp, " xmlns:a3=\"http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/\" \n" ); fprintf( svg_fp, " a3:scriptImplementation=\"Adobe\" >\n" ); fprintf( svg_fp, "