1 /*
2 * TransFig: Facility for Translating Fig code
3 * Copyright (c) 1999 by T. Sato
4 * Parts Copyright (c) 2002 by Anthony Starks
5 * Parts Copyright (c) 2002,2003,2004,2005,2006 by Martin Kroeker
6 * Parts Copyright (c) 2002 by Brian V. Smith
7 *
8 * Any party obtaining a copy of these files is granted, free of charge, a
9 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
10 * nonexclusive right and license to deal in this software and
11 * documentation files (the "Software"), including without limitation the
12 * rights to use, copy, modify, merge, publish and/or distribute copies of
13 * the Software, and to permit persons who receive copies from any such
14 * party to do so, with the only requirement being that this copyright
15 * notice remain intact.
16 *
17 */
18
19 /*
20 *
21 * SVG driver for fig2dev
22 *
23 * from fig2svg -- convert FIG 3.2 to SVG
24 *
25 * Original author: Anthony Starks (ajstarks@home.com)
26 * Created: 17 May 2000
27 * Converted to gensvg by Brian Smith
28 * Further modified by Martin Kroeker (martin@ruby.chemie.uni-freiburg.de)
29 * incorporating changes by Philipp Hahn and Justus Piater
30 *
31 * PH: Philipp Hahn
32 * JP: Justus Piater
33 * MK: Martin Kroeker
34 * BS: Brian Smith
35 * RE: Russell Edwards
36 *
37 * MK 04-Dec-02: partial support for the symbol font, bigger fontscale, text alignment,
38 * dashed and dotted lines, bugfix for missing % in stroke-color statement of arcs
39 * FIXME: lacks support for arrowheads; fill patterns; percent grayscale fills
40 * MK 08-Dec-02: rotated text; shades and tints of fill colors; filled circles
41 * MK 11-Dec-02: scaling;proper font/slant/weight support; changed arc code
42 * 12-Dec-02: fixes by Brian Smith: scale factor, orientation, ellipse fills
43 * MK 14-Dec-02: arc code rewrite, simplified line style handling,
44 * arrowheads on arcs and lines (FIXME: not clipped), stroke->color command
45 * is simply 'stroke'
46 * MK 15-Dec-02: catch pattern fill flags, convert to tinted fills for now
47 * MK 18-Dec-02: fill patterns; fixes by BS: arrowhead scale & position,
48 * circle by diameter
49 * PH 03-Feb-03: Fix CIRCLE_BY_DIA, color/fill styles, update SVG DTD
50 * MK 10-Feb-03: do not encode space characters when in symbol font;
51 * always encode characters '&', '<' and '>'. Leave non-
52 * alphabetic characters in the lower half of the symbol
53 * font unchanged.
54 * MK 12-Feb-03: Added complete character conversion tables for the symbol
55 * and dingbat fonts (based on the information in Unicode
56 * Inc.'s symbol.txt and zdingbat.txt tables, version 0.2)
57 * MK 18-Feb-03: Added cap and join style fields for line and arc
58 * MK 24-Feb-03: Symbol and Dingbat fonts are no longer translated to
59 * font-family="Times" with both bold and italic flags set.
60 * MK 17-Jun-03: Fix for rotation angle bug. Correct rendering of 'tinted'
61 * colors using code from www.cs.rit.edu. Added forgotten
62 * pattern fill option for ellipses (circles).
63 * JP 21-Jan-04: Calculate proper bounding box instead of current paper
64 * dimensions. Added missing semicolons in some property
65 * strings, and proper linebreak characters in multi-line
66 * format strings.
67 * MK 23-Jan-04: Pattern-filled objects are now drawn twice - painting the
68 * pattern over the fill color (if any). This solves the problem
69 * of missing color support in pattern fills (as reported by JP)
70 * Corrected filling of ellipses, which was still B/W only.
71 * Fixed bad tiling of diagonal patterns 1 - 3 (the old formula
72 * favoured exact angles over seamless tiling). Updated DTD.
73 * MK 25-Jan-04: Endpoints of polylines are now truncated when arrowheads
74 * are drawn. Corrected rendering of type 0 (stick) arrowheads.
75 * MK 28-Jan-04: Fix for arc arrowhead orientation.
76 * MK 31-Jan-04: Corrected arc angle calculation (this time for good ?)
77 * MK 22-Feb-04: Picture support
78 * JP 1-Mar-04: Closed arrowheads should use polygons instead of polylines
79 * JP 3-Mar-04: Corrected font family selection
80 * JP 26-Mar-04: Corrected (and simplified) calculation of white-tinted
81 * fill colors (and removed the HSV/RGB conversion code)
82 * MK 29-Mar-04: Added code for rounded boxes (polyline subtype 4)
83 * MK 30-Mar-04: Added code for boxes, explicit support for polygons
84 * MK 10-Apr-04: Added xml-space:preserve qualifier on texts to preserve
85 * whitespace. Rewrote fill pattern handling to generate
86 * patterns as needed - adding support for penwidth and color.
87 * Corrected tiling of all shingle patterns and reversal
88 * of horizontal shingles.
89 * RE 6-May-04: Changed degrees() to double for more precision
90 * Added linewidth() to transform all line widths in the
91 * same way as genps.c : thin lines get thinner
92 * Changed circle radius to use F_ellipse::radiuses.x instead
93 * of start and end (which seemed not to work correctly)
94 * Query: Is this broken for byradius or bydiameter??
95 * Added rotation to ellipses
96 * Changed back to mapping Symbol to Times, greeks look a bit
97 * better. Ultimately embedding PS fonts would be better.
98 * Removed newlines inside <text> printf, otherwise they get
99 * rendered as spaces due to xml:space="preserve"
100 * Removed extraneous comma between two halves of format
101 * string in gensvg_arc, fixes Seg fault.
102 * MK 3-Aug-04 Split the multi-line format string in gensvg_arc in two to
103 * get rid of (compiler version-dependant) segfaults for good.
104 * MK 11-Sep-05: Added explicit stroke color to text to prevent black outline
105 * on colored text.
106 * Added support for latex-special formatted text, converting
107 * sub- and superscripts to either baseline-shift=sub/super
108 * (the intended way of doing this in SVG) or "dy" offsets
109 * (less elegant, but more likely to be supported by browsers
110 * and editors) depending on the NOSUPER define below.
111 * Tested with Batik-1.6, konqueror-3.4, firefox-1.5b1,
112 * inkscape-0.41
113 * MK 15-Sep-05: Use a font-family list of "Times,Symbol" for symbol
114 * characters - the Times fontface does not contain all
115 * elements of the Symbol font on all platforms.
116 * MK 4-Nov-05: Corrected length and appearance of stick-type arrows.
117 * MK 2-Jan-06: Added support for filled arcs.
118 * MK 26-Feb-06: Added support for dashed circles, ellipses and arcs.
119 * Dash/gap lengths are now drawn according to style_val.
120 * Fixed several glitches uncovered by splint.
121 * MK 22-Apr-06: Corrected blue component of shaded colors (was always
122 * zero due to missing parentheses around typecast). Corrected
123 * arrowheads of large arrows by adding an increased miterlimit.
124 * Corrected position of backward arrowheads on polylines with
125 * both forward and backward arrows.
126 * MK 2-Jul-06: Patterns do not inherit their line width from the parent object
127 * (which may be zero if no visible boundary is desired), so always
128 * use linewidth:1
129 * MK 22-Oct-06: Changed unicode variant of lowercase phi to match its X11 Symbol
130 * counterpart.
131 * *********************************************************************************
132 * W3 recommendations for
133 * 1.3 SVG Namespace, Public Identifier and System Identifier
134 *
135 * The following are the SVG 1.1 namespace, public identifier and system identifier:
136 *
137 * SVG Namespace:
138 * http://www.w3.org/2000/svg
139 * xmlns:xlink="http://www.w3.org/1999/xlink"
140 * Public Identifier for SVG 1.1:
141 * PUBLIC "-//W3C//DTD SVG 1.1//EN"
142 * System Identifier for the SVG 1.1 Recommendation:
143 * http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd
144 *
145 * The following is an example document type declaration for an SVG document:
146 *
147 * <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
148 * "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
149 *
150 * Note that DTD listed in the System Identifier is a modularized DTD (ie. its
151 * contents are spread over multiple files), which means that a validator may have
152 * to fetch the multiple modules in order to validate. For that reason, there is
153 * a single flattened DTD available that corresponds to the SVG 1.1 modularized DTD.
154 * It can be found at http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-flat.dtd.
155 * *********************************************************************************
156 */
157
158 /*
159 * use a workaround for sub-/superscripting as long as most browsers do not
160 * support the baseline-shift=sub/super attribute
161 */
162 #define NOSUPER 1
163
164 #include "fig2dev.h"
165 #include "object.h"
166 #include "bound.h"
167 #include "../../patchlevel.h"
168
169 static void svg_arrow();
170 static void generate_tile(int);
171 static void svg_dash(int,double);
172
173 #define PREAMBLE "<?xml version=\"1.0\" standalone=\"no\"?>\n"\
174 "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n"\
175 "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
176 const char *joinstyle[] = { "miter","round","bevel"};
177 const char *capstyle[] = { "butt","round", "square"};
178 static unsigned int symbolchar[256]=
179 {0,0,0,0,0,0,0,0,0,0,
180 0,0,0,0,0,0,0,0,0,0,
181 0,0,0,0,0,0,0,0,0,0,
182 0,0,0x0020,0x0021,0x2200,0x0023,0x2203,0x0025,
183 0x0026,0x220B,0x0028,0x0029,0x2217,0x002B,0x002C,0x2212,0x002E,0x002F,0x0030,
184 0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,
185 0x003C,0x003D,0x003E,0x003F,0x2245,0x0391,0x0392,0x03A7,0x0394,0x0395,
186 0x03A6,0x0393,0x0397,0x0399,0x03D1,0x039A,0x039B,0x039C,0x039D,0x039F,0x03A0,
187 0x0398,0x03A1,0x03A3,0x03A4,0x03A5,0x03C2,0x03A9,0x039E,0x03A8,0x0396,
188 0x005B,0x2234,0x005D,0x22A5,0x005F,0xF8E5,0x03B1,0x03B2,0x03C7,0x03B4,0x03B5,
189 0x03D5 /*0x03C6*/,0x03B3,0x03B7,0x03B9,0x03D5,0x03BA,0x03BB,0x03BC,0x03BD,0x03BF,
190 0x03C0,0x03B8,0x03C1,0x03C3,0x03C4,0x03C5,0x03D6,0x03C9,0x03BE,0x03C8,0x03B6,
191 0x007B,0x007C,0x007D,0x223C,0,0,0,0,0,0,0,0,0,
192 0,0,0,0,0,0,0,0,0,0,
193 0,0,0,0,0,0,0,0,0,0, 0,0,
194 0,0,0x20AC,0x03D2,0x2032,0x2264,0x2044,0x221E,
195 0x0192,0x2663,0x2666,0x2665,0x2660,0x2194,0x2190,0x2191,0x2192,0x2193,0x00B0,
196 0x00B1,0x2033,0x2265,0x00D7,0x221D,0x2202,0x2022,0x00F7,0x2260,0x2261,0x2248,
197 0x2026,0xF8E6,0xF8E7,0x21B5,0x2135,0x2111,0x211C,0x2118,0x2297,0x2295,0x2205,
198 0x2229,0x222A,0x2283,0x2287,0x2284,0x2282,0x2286,0x2208,0x2209,0x2220,0x2207,
199 0xF6DA,0xF6D9,0xF6DB,0x220F,0x221A,0x22C5,0x00AC,0x2227,0x2228,0x21D4,0x21D0,
200 0x21D1,0x21D2,0x21D3,0x25CA,0x2329,0xF8E8,0xF8E9,0xF8EA,0x2211,0xF8EB,0xF8EC,
201 0xF8ED,0xF8EE,0xF8EF,0xF8F0,0xF8F1,0xF8F2,0xF8F3,0xF8F4,0,0x232A,0x222B,0x2320,
202 0xF8F5,0x2321,0xF8F6,0xF8F7,0xF8F8,0xF8F9,0xF8FA,0xF8FB,0xF8FC,0xF8FD,0xF8FE,0
203 };
204
205 static unsigned int dingbatchar[256]=
206 {0,0,0,0,0,0,0,0,0,0,
207 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0x0020,
208 0x2701,0x2702,0x2703,0x2704,0x260E,0x2706,0x2707,0x2708,0x2709,0x261B,
209 0x261E,0x270C,0x270D,0x270E,0x270F,0x2710,0x2711,0x2712,0x2713,0x2714,
210 0x2715,0x2716,0x2717,0x2718,0x2719,0x271A,0x271B,0x271C,0x271D,0x271E,
211 0x271F,0x2720,0x2721,0x2722,0x2723,0x2724,0x2725,0x2726,0x2727,0x2605,
212 0x2729,0x272A,0x272B,0x272C,0x272D,0x272E,0x272F,0x2730,0x2731,0x2732,
213 0x2733,0x2734,0x2735,0x2736,0x2737,0x2738,0x2739,0x273A,0x273B,0x273C,
214 0x273D,0x273E,0x273F,0x2740,0x2741,0x2742,0x2743,0x2744,0x2745,0x2746,
215 0x2747,0x2748,0x2749,0x274A,0x274B,0x25CF,0x274D,0x25A0,0x274F,0x2750,
216 0x2751,0x2752,0x25B2,0x25BC,0x25C6,0x2756,0x25D7,0x2758,0x2759,0x275A,
217 0x275B,0x275C,0x275D,0x275E,0,0xF8D7,0xF8D8,0xF8D9,0xF8DA,0xF8DB,
218 0xF8DC,0xF8DD,0xF8DE,0xF8DF,0xF8E0,0xF8E1,0xF8E2,0xF8E3,0xF8E4,0,0,
219 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
220 0,0x2761,0x2762,0x2763,
221 0x2764,0x2765,0x2766,0x2767,0x2663,0x2666,0x2665,0x2660,0x2460,0x2461,
222 0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,0x2468,0x2469,0x2776,0x2777,
223 0x2778,0x2779,0x277A,0x277B,0x277C,0x277D,0x277E,0x277F,0x2780,0x2781,
224 0x2782,0x2783,0x2784,0x2785,0x2786,0x2787,0x2788,0x2789,0x278A,0x278B,
225 0x278C,0x278D,0x278E,0x278F,0x2790,0x2791,0x2792,0x2793,0x2794,0x2192,
226 0x2194,0x2195,0x2798,0x2799,0x279A,0x279B,0x279C,0x279D,0x279E,0x279F,
227 0x27A0,0x27A1,0x27A2,0x27A3,0x27A4,0x27A5,0x27A6,0x27A7,0x27A8,0x27A9,
228 0x27AA,0x27AB,0x27AC,0x27AD,0x27AE,0x27AF,0,0x27B1,0x27B2,0x27B3,0x27B4,
229 0x27B5,0x27B6,0x27B7,0x27B8,0x27B9,0x27BA,0x27BB,0x27BC,0x27BD,0x27BE,0
230 };
231
232 /* arrowhead arrays */
233 Point points[50], fillpoints[50], clippoints[50];
234 int npoints, nfillpoints, nclippoints;
235 int arrowx1, arrowy1; /* first point of object */
236 int arrowx2, arrowy2; /* second point of object */
237
238 static int tileno=0; /* number of current tile */
239
240 static F_point *p;
241
242 static unsigned int
rgbColorVal(int colorIndex)243 rgbColorVal (int colorIndex)
244 { /* taken from genptk.c */
245 unsigned int rgb;
246 static unsigned int rgbColors[NUM_STD_COLS] = {
247 0x000000, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff,
248 0xffff00, 0xffffff, 0x00008f, 0x0000b0, 0x0000d1, 0x87cfff,
249 0x008f00, 0x00b000, 0x00d100, 0x008f8f, 0x00b0b0, 0x00d1d1,
250 0x8f0000, 0xb00000, 0xd10000, 0x8f008f, 0xb000b0, 0xd100d1,
251 0x803000, 0xa14000, 0xb46100, 0xff8080, 0xffa1a1, 0xffbfbf,
252 0xffe0e0, 0xffd600
253 };
254
255 if (colorIndex == DEFAULT)
256 rgb = rgbColors[0];
257 else if (colorIndex < NUM_STD_COLS)
258 rgb = rgbColors[colorIndex];
259 else
260 rgb = ((user_colors[colorIndex - NUM_STD_COLS].r & 0xff) << 16)
261 | ((user_colors[colorIndex - NUM_STD_COLS].g & 0xff) << 8)
262 | (user_colors[colorIndex - NUM_STD_COLS].b & 0xff);
263 return rgb;
264 }
265
266 static unsigned int
rgbFillVal(int colorIndex,int area_fill)267 rgbFillVal (int colorIndex, int area_fill)
268 {
269 unsigned int rgb, r, g, b;
270 float t;
271 short tintflag = 0;
272 static unsigned int rgbColors[NUM_STD_COLS] = {
273 0x000000, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff,
274 0xffff00, 0xffffff, 0x00008f, 0x0000b0, 0x0000d1, 0x87cfff,
275 0x008f00, 0x00b000, 0x00d100, 0x008f8f, 0x00b0b0, 0x00d1d1,
276 0x8f0000, 0xb00000, 0xd10000, 0x8f008f, 0xb000b0, 0xd100d1,
277 0x803000, 0xa14000, 0xb46100, 0xff8080, 0xffa1a1, 0xffbfbf,
278 0xffe0e0, 0xffd600
279 };
280
281
282 if (colorIndex == DEFAULT)
283 rgb = rgbColors[0];
284 else if (colorIndex < NUM_STD_COLS)
285 rgb = rgbColors[colorIndex];
286 else
287 rgb = ((user_colors[colorIndex - NUM_STD_COLS].r & 0xff) << 16)
288 | ((user_colors[colorIndex - NUM_STD_COLS].g & 0xff) << 8)
289 | (user_colors[colorIndex - NUM_STD_COLS].b & 0xff);
290
291 tintflag = 0;
292 if (area_fill > 20) {
293 tintflag = 1;
294 area_fill -= 20;
295 }
296 if (colorIndex > 0 && colorIndex != 7) {
297 if (tintflag) {
298 r = ((rgb & ~0xFFFF) >> 16);
299 g = ((rgb & 0xFF00) >> 8);
300 b = (rgb & ~0xFFFF00) ;
301
302 t= area_fill / 20.;
303 r += t * (0xFF-r);
304 g += t * (0xff-g);
305 b += t * (0xff-b);
306
307 rgb = ((r &0xff) << 16) + ((g&0xff) << 8) + (b&0xff);
308 }
309 else
310 rgb = (((int) ((area_fill / 20.) * ((rgb & ~0xFFFF) >> 16)) << 16) +
311 ((int) ((area_fill / 20.) * ((rgb & 0xFF00) >> 8)) << 8)
312 + ((int) ((area_fill / 20.) * (rgb & ~0xFFFF00))) );
313 }
314 else {
315 if (colorIndex == 0 || colorIndex == DEFAULT)
316 area_fill = 20 - area_fill;
317 rgb =
318 ((area_fill * 255 / 20) << 16) + ((area_fill * 255 / 20) << 8) +
319 area_fill * 255 / 20;
320 }
321
322 return rgb;
323 }
324
325 static double
degrees(double angle)326 degrees (double angle)
327 {
328 return -angle / M_PI * 180.0;
329 }
330
331 static int
linewidth_adj(int linewidth)332 linewidth_adj(int linewidth)
333 {
334 /* Adjustment as in genps.c */
335 return (double)linewidth <= THICK_SCALE ? linewidth/2 : linewidth-THICK_SCALE;
336 }
337
338
339 void
gensvg_option(opt,optarg)340 gensvg_option (opt, optarg)
341 char opt;
342 char *optarg;
343 {
344 switch (opt) {
345 case 'L': /* ignore language and magnif. */
346 case 'm':
347 break;
348 case 'z':
349 (void) strcpy (papersize, optarg);
350 paperspec = True;
351 break;
352 default:
353 put_msg (Err_badarg, opt, "svg");
354 exit (1);
355 }
356 }
357
358 void
gensvg_start(objects)359 gensvg_start (objects)
360 F_compound *objects;
361 {
362 struct paperdef *pd;
363 int pagewidth = -1, pageheight = -1;
364 int vx, vy, vw, vh;
365 time_t when;
366 char stime[80];
367
368 fprintf (tfp, "%s\n", PREAMBLE);
369 fprintf (tfp, "<!-- Creator: %s Version %s Patchlevel %s -->\n",
370 prog, VERSION, PATCHLEVEL);
371
372 (void) time (&when);
373 strcpy (stime, ctime (&when));
374 /* remove trailing newline from date/time */
375 stime[strlen (stime) - 1] = '\0';
376 fprintf (tfp, "<!-- CreationDate: %s -->\n", stime);
377 fprintf (tfp, "<!-- Magnification: %.3f -->\n", mag);
378
379 /* convert paper size from ppi to inches */
380 for (pd = paperdef; pd->name != NULL; pd++)
381 if (strcasecmp (papersize, pd->name) == 0) {
382 pagewidth = pd->width;
383 pageheight = pd->height;
384 strcpy (papersize, pd->name); /* use the "nice" form */
385 break;
386 }
387 if (pagewidth < 0 || pageheight < 0) {
388 (void) fprintf (stderr, "Unknown paper size `%s'\n", papersize);
389 exit (1);
390 }
391 if (landscape) {
392 vw = pagewidth;
393 pagewidth = pageheight;
394 pageheight = vw;
395 }
396 vx = (int) (llx * mag);
397 vy = (int) (lly * mag);
398 vw = (int) ((urx - llx) * mag);
399 vh = (int) ((ury - lly) * mag);
400 fprintf (tfp,
401 "<svg\txmlns=\"http://www.w3.org/2000/svg\"\n\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n\twidth=\"%.1fin\" height=\"%.1fin\"\n\tviewBox=\"%d %d %d %d\">\n",
402 vw / ppi, vh / ppi, vx, vy, vw, vh);
403
404 if (objects->comments)
405 print_comments ("<desc>", objects->comments, "</desc>");
406 fprintf (tfp, "<g style=\"stroke-width:.025in; fill:none\">\n");
407 /* only define the patterns if one is used */
408
409
410 }
411
412 int
gensvg_end()413 gensvg_end ()
414 {
415 fprintf (tfp, "</g>\n</svg>\n");
416 return 0;
417 }
418
419 void
gensvg_line(l)420 gensvg_line (l)
421 F_line *l;
422 {
423 int px,py,firstpoint;
424 int px2,py2,width,height,rotation;
425 double dx,dy,len,cosa,sina,cosa1,sina1;
426 double hl;
427
428
429 if (!l->points) return; /*safeguard against old, buggy fig files*/
430
431 if (l->type ==5 ) {
432 fprintf (tfp,"<!-- Image -->\n");
433 fprintf (tfp,"<image xlink:href=\"file://%s\" preserveAspectRatio=\"none\"\n",l->pic->file);
434 p=l->points;
435 px=p->x;
436 py=p->y;
437 px2=p->next->next->x;
438 py2=p->next->next->y;
439 width=px2-px;
440 height=py2-py;
441 rotation=0;
442 if (width<0 && height <0)
443 rotation=180;
444 else if (width <0 && height >=0)
445 rotation=90;
446 else if (width >=0 && height <0)
447 rotation=270;
448 if (l->pic->flipped) rotation-=90;
449 height=abs(height);
450 width=abs(width);
451 px=(px<px2)?px:px2;
452 py=(py<py2)?py:py2;
453 px2=px+width/2;
454 py2=py+height/2;
455 if (l->pic->flipped) {
456 fprintf (tfp,"transform=\"rotate(%d %d %d) scale(-1,1) translate(%d,%d)\"\n",
457 rotation,px2,py2,-2*px2,0);
458 } else if (rotation !=0) {
459 fprintf (tfp,"transform=\"rotate(%d %d %d)\"\n",rotation,px2,py2);
460 }
461
462 fprintf (tfp,"x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" />\n",
463 (int)(px*mag), (int)(py*mag), (int)(width*mag), (int)(height*mag));
464 return;
465 }
466
467 if (l->type == 2 || l->type == 4) /* box or arc box */
468 {
469 fprintf (tfp, "<!-- Line: box -->\n");
470 print_comments ("<!-- ", l->comments, " -->");
471 px=l->points->x;
472 py=l->points->y;
473 px2=l->points->next->next->x;
474 py2=l->points->next->next->y;
475 width=abs(px2-px);
476 height=abs(py2-py);
477 px=(px<px2)?px:px2;
478 py=(py<py2)?py:py2;
479
480 fprintf (tfp, "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%d\" \n",
481 (int)(px*mag),(int)(py*mag),(int)(width*mag),(int)(height*mag),
482 (l->type == 2 ? 0 : (int)(l->radius*mag)));
483 fprintf (tfp, "style=\"stroke:#%6.6x;stroke-width:%d;\n",
484 rgbColorVal (l->pen_color), (int) ceil (linewidth_adj(l->thickness) * mag));
485
486 fprintf (tfp, "stroke-linejoin:%s; stroke-linecap:%s;\n",
487 joinstyle[l->join_style],capstyle[l->cap_style]);
488
489 if (l->style > 0)
490 svg_dash(l->style,l->style_val);
491
492 if (l->fill_style != -1 )
493 fprintf (tfp, "fill:#%6.6x;\n", rgbFillVal (l->fill_color,
494 (l->fill_style>40 ? 20 : l->fill_style)));
495 fprintf (tfp, "\"/>\n");
496
497 if (l->fill_style > 40) { /*repeat object to paint pattern over fill */
498
499 fprintf (tfp, "<g style=\"stroke:#%6.6x; stroke-width:1\" >\n",
500 rgbColorVal(l->pen_color));
501 generate_tile(l->fill_style - 40);
502 fprintf (tfp, "</g>\n");
503
504 fprintf (tfp, "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%d\" \n",
505 (int)(px*mag),(int)(py*mag),(int)(width*mag),(int)(height*mag),
506 (l->type == 2 ? 0 : (int)(l->radius*mag)));
507 fprintf (tfp, "style=\"stroke:#%6.6x;stroke-width:%d;\n",
508 rgbColorVal (l->pen_color), (int) ceil (linewidth_adj(l->thickness) * mag));
509
510 fprintf (tfp, "stroke-linejoin:%s; stroke-linecap:%s;\n",
511 joinstyle[l->join_style],capstyle[l->cap_style]);
512
513 if (l->style > 0)
514 svg_dash(l->style,l->style_val);
515
516 fprintf (tfp, "fill:url(#tile%d);\n", tileno);
517 fprintf (tfp, "\"/>\n");
518 }
519 return;
520 }
521
522 fprintf (tfp, "<!-- Line -->\n");
523 print_comments ("<!-- ", l->comments, " -->");
524 fprintf (tfp, "<%s points=\"", (l->type == 1 ? "polyline" : "polygon"));
525 px=py=-100000;
526 firstpoint=0;
527 for (p = l->points; p; p = p->next) {
528 if (px != -100000) {
529 if (firstpoint && l->back_arrow) {
530 dx=(double)(p->x-px);
531 dy=(double)(p->y-py);
532 len=sqrt(dx*dx+dy*dy);
533 sina1= dy/len;
534 cosa1= dx/len;
535 if (l->back_arrow->type != 0 )
536 hl= l->back_arrow->ht;
537 else
538 hl = 1.1 * l->thickness;
539 px += (int)(hl * cosa1 +0.5);
540 py += (int)(hl * sina1 +0.5);
541 firstpoint=0;
542 }
543 fprintf(tfp, "%d,%d\n", (int) (px*mag), (int) (py*mag));
544 }
545 arrowx1 = arrowx2;
546 arrowy1 = arrowy2;
547 arrowx2 = p->x;
548 arrowy2 = p->y;
549 if (px == -100000) firstpoint=1;
550 px=p->x;
551 py=p->y;
552 }
553 if (!l->for_arrow)
554 fprintf(tfp, "%d,%d\n", (int) (px*mag), (int) (py*mag));
555 else {
556 dx=(double)(arrowx2-arrowx1);
557 dy=(double)(arrowy2-arrowy1);
558 len=sqrt(dx*dx+dy*dy);
559 sina= dy/len;
560 cosa= dx/len;
561 if (l->for_arrow->type != 0)
562 hl= l->for_arrow->ht;
563 else
564 hl = 1.1*l->thickness;
565 px = arrowx2 - (int)(hl * cosa +0.5);
566 py = arrowy2 - (int)(hl * sina +0.5);
567 fprintf(tfp, "%d,%d\n", (int) (px*mag), (int) (py*mag));
568 }
569 fprintf (tfp, "\" style=\"stroke:#%6.6x;stroke-width:%d;\n",
570 rgbColorVal (l->pen_color), (int) ceil (linewidth_adj(l->thickness) * mag));
571
572 fprintf (tfp, "stroke-linejoin:%s; stroke-linecap:%s;\n",
573 joinstyle[l->join_style],capstyle[l->cap_style]);
574
575 if (l->style > 0)
576 svg_dash(l->style,l->style_val);
577
578 if (l->fill_style != -1 )
579 fprintf (tfp, "fill:#%6.6x;\n", rgbFillVal (l->fill_color, (l->fill_style>40 ? 20 : l->fill_style)));
580 fprintf (tfp, "\"/>\n");
581
582 if (l->fill_style > 40) { /*repeat object to paint pattern over fill */
583
584 fprintf (tfp, "<g style=\"stroke:#%6.6x; stroke-width:1\" >\n",
585 rgbColorVal(l->pen_color) );
586 generate_tile(l->fill_style - 40);
587 fprintf (tfp, "</g>\n");
588
589 fprintf (tfp, "<%s points=\"", (l->type == 1 ? "polyline" : "polygon"));
590 for (p = l->points; p; p = p->next) {
591 fprintf (tfp, "%d,%d\n", (int) (p->x * mag), (int) (p->y * mag));
592 }
593
594 fprintf (tfp, "\" style=\"stroke:#%6.6x;stroke-width:%d;\n",
595 rgbColorVal (l->pen_color), (int) ceil (linewidth_adj(l->thickness) * mag));
596
597 fprintf (tfp, "stroke-linejoin:%s; stroke-linecap:%s;\n",
598 joinstyle[l->join_style],capstyle[l->cap_style]);
599
600 if (l->style > 0)
601 svg_dash(l->style,l->style_val);
602
603 fprintf (tfp, "fill:url(#tile%d);\n", tileno);
604 fprintf (tfp, "\"/>\n");
605 }
606
607
608 if (l->for_arrow != NULL) {
609 arrowx2+=l->thickness*cosa;
610 arrowy2+=l->thickness*sina;
611 svg_arrow(l, l->for_arrow, l->pen_color);
612 }
613 if (l->back_arrow != NULL) {
614 p = l->points;
615 if (!p) return; /*safeguard against old, buggy fig files*/
616 arrowx2=p->x - l->thickness*cosa1 ;
617 arrowy2=p->y - l->thickness*sina1 ;
618 p = p->next;
619 if (!p) return; /*safeguard against old, buggy fig files*/
620 arrowx1 = p->x;
621 arrowy1 = p->y;
622 svg_arrow(l, l->back_arrow, l->pen_color);
623 }
624 }
625
626
627 void
gensvg_spline(s)628 gensvg_spline (s) /* not used by fig2dev */
629 F_spline *s;
630 {
631 fprintf (tfp, "<!-- Spline -->\n");
632 print_comments ("<!-- ", s->comments, " -->");
633
634 fprintf (tfp, "<path style=\"stroke:#%6.6x;stroke-width:%d\" d=\"",
635 rgbColorVal (s->pen_color), (int) ceil (linewidth_adj(s->thickness) * mag));
636 fprintf (tfp, "M %d,%d \n C", (int) (s->points->x * mag), (int) (s->points->y * mag));
637 for (p = s->points++; p; p = p->next) {
638 fprintf (tfp, "%d,%d\n", (int) (p->x * mag), (int) (p->y * mag));
639 }
640 fprintf (tfp, "\"/>\n");
641 }
642
643 void
gensvg_arc(a)644 gensvg_arc (a)
645 F_arc *a;
646 {
647 double radius;
648 double x, y, angle, dx, dy;
649
650 fprintf (tfp, "<!-- Arc -->\n");
651 print_comments ("<!-- ", a->comments, " -->");
652
653 dx = a->point[0].x - a->center.x;
654 dy = a->point[0].y - a->center.y;
655 radius = sqrt (dx * dx + dy * dy);
656
657
658 x= (a->point[0].x-a->center.x) * (a->point[2].x-a->center.x)
659 +(a->point[0].y-a->center.y) * (a->point[2].y-a->center.y);
660 y= (a->point[0].x-a->center.x) * (a->point[2].y-a->center.y)
661 -(a->point[0].y-a->center.y) * (a->point[2].x-a->center.x);
662
663 if (x == 0.0 && y == 0.0)
664 angle=0.0;
665 else
666 angle = atan2(y,x);
667
668 if (angle <0.0) angle += 2.*M_PI;
669
670 angle *= 180./M_PI;
671
672 if (a->direction==1) angle = 360.-angle;
673
674 fprintf (tfp, "<path style=\"stroke:#%6.6x;stroke-width:%d;stroke-linecap:%s;",
675 rgbColorVal (a->pen_color), (int) ceil (linewidth_adj(a->thickness) * mag),
676 capstyle[a->cap_style]);
677
678 if (a->style > 0)
679 svg_dash(a->style,a->style_val);
680
681 if (a->fill_style != -1)
682 fprintf (tfp, "fill:#%6.6x\"\n", rgbFillVal (a->fill_color, (a->fill_style > 40 ? 20 : a->fill_style)));
683 else
684 fprintf (tfp,"\"\n");
685
686 fprintf (tfp, "d=\"M %d,%d A %d %d % d % d % d % d % d \" />\n",
687 (int) (a->point[0].x * mag),
688 (int) (a->point[0].y * mag),
689 (int) (radius * mag), (int) (radius * mag),
690 0,
691 (fabs(angle) >180. ) ? 1 : 0,
692 (fabs(angle) >0. && a->direction==0) ? 1 : 0,
693 (int) (a->point[2].x * mag), (int) (a->point[2].y * mag));
694
695 if (a->fill_style > 40) {
696
697 fprintf (tfp, "<g style=\"stroke:#%6.6x; stroke-width:1\" >\n",
698 rgbColorVal(a->pen_color) );
699 generate_tile(a->fill_style - 40);
700 fprintf (tfp, "</g>\n");
701
702 fprintf (tfp, "<path style=\"stroke:#%6.6x;stroke-width:%d;stroke-linecap:%s;fill:url(#tile%d);\"\n",
703 rgbColorVal (a->pen_color), (int) ceil (linewidth_adj(a->thickness) * mag),
704 capstyle[a->cap_style],tileno);
705 fprintf (tfp, "d=\"M %d,%d A %d %d % d % d % d % d % d \" />\n",
706 (int) (a->point[0].x * mag),
707 (int) (a->point[0].y * mag),
708 (int) (radius * mag), (int) (radius * mag),
709 0,
710 (fabs(angle) >180. ) ? 1 : 0,
711 (fabs(angle) >0. && a->direction==0) ? 1 : 0,
712 (int) (a->point[2].x * mag), (int) (a->point[2].y * mag));
713 }
714
715 if (a->for_arrow) {
716 arrowx2 = a->point[2].x;
717 arrowy2 = a->point[2].y;
718 compute_arcarrow_angle (a->center.x, a->center.y,
719 (double) arrowx2, (double) arrowy2,
720 a->direction, a->for_arrow, &arrowx1, &arrowy1);
721 svg_arrow(a, a->for_arrow, a->pen_color);
722 }
723
724 if (a->back_arrow) {
725 arrowx2 = a->point[0].x;
726 arrowy2 = a->point[0].y;
727 compute_arcarrow_angle (a->center.x, a->center.y,
728 (double) arrowx2, (double) arrowy2,
729 a->direction ^ 1, a->back_arrow, &arrowx1, &arrowy1);
730 svg_arrow(a, a->back_arrow, a->pen_color);
731 }
732 }
733
734 void
gensvg_ellipse(e)735 gensvg_ellipse (e)
736 F_ellipse *e;
737 {
738 int cx = (int) (e->center.x * mag);
739 int cy = (int) (e->center.y * mag);
740 if (e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA) {
741 int r = (int) (e->radiuses.x * mag);
742 fprintf (tfp, "<!-- Circle -->\n");
743 print_comments ("<!-- ", e->comments, " -->");
744 fprintf (tfp, "<circle cx=\"%d\" cy=\"%d\" r=\"%d\"\n style=\"", cx, cy, r);
745 if (e->fill_style != -1)
746 fprintf (tfp, "fill:#%6.6x;", rgbFillVal (e->fill_color, (e->fill_style > 40 ? 20 : e->fill_style)));
747 if (e->style > 0) {
748 svg_dash(e->style,e->style_val);
749 }
750 fprintf (tfp, "stroke:#%6.6x;stroke-width:%d;\"/>\n",
751 rgbColorVal (e->pen_color), (int) ceil (linewidth_adj(e->thickness) * mag));
752
753 if (e->fill_style > 40) {
754
755 fprintf (tfp, "<g style=\"stroke:#%6.6x; stroke-width:1\" >\n",
756 rgbColorVal(e->pen_color) );
757 generate_tile(e->fill_style - 40);
758 fprintf (tfp, "</g>\n");
759
760 fprintf (tfp, "<circle cx=\"%d\" cy=\"%d\" r=\"%d\"\n style=\"", cx, cy, r);
761 fprintf (tfp, "fill:url(#tile%d);\n", tileno);
762 fprintf (tfp, "stroke:#%6.6x;stroke-width:%d;\"/>\n",
763 rgbColorVal (e->pen_color), (int) ceil (linewidth_adj(e->thickness) * mag));
764 }
765 }
766 else {
767 int rx = (int) (e->radiuses.x * mag);
768 int ry = (int) (e->radiuses.y * mag);
769 fprintf (tfp, "<!-- Ellipse -->\n");
770 print_comments ("<!-- ", e->comments, " -->");
771 fprintf (tfp, "<ellipse transform=\"translate(%d,%d) rotate(%.8lf)\" rx=\"%d\" ry=\"%d\"\n style=\"",
772 cx, cy, degrees(e->angle), rx, ry);
773 if (e->fill_style != -1)
774 fprintf (tfp, "fill:#%6.6x;", rgbFillVal (e->fill_color, (e->fill_style > 40 ? 20 : e->fill_style)));
775 if (e->style > 0)
776 svg_dash(e->style,e->style_val);
777
778 fprintf (tfp, "stroke:#%6.6x;stroke-width:%d;\"/>\n",
779 rgbColorVal (e->pen_color), (int) ceil (linewidth_adj(e->thickness) * mag));
780
781 if (e->fill_style > 40) {
782
783 fprintf (tfp, "<g style=\"stroke:#%6.6x; stroke-width:1\" >\n",
784 rgbColorVal(e->pen_color) );
785 generate_tile(e->fill_style - 40);
786 fprintf (tfp, "</g>\n");
787 fprintf (tfp, "<ellipse transform=\"translate(%d,%d) rotate(%.8lf)\" rx=\"%d\" ry=\"%d\"\n style=\"",
788 cx, cy, degrees(e->angle), rx, ry);
789 fprintf (tfp, "fill:url(#tile%d);\n", tileno);
790 fprintf (tfp, "stroke:#%6.6x;stroke-width:%d;\"/>\n",
791 rgbColorVal (e->pen_color), (int) ceil (linewidth_adj(e->thickness) * mag));
792 }
793 }
794 }
795
796 void
gensvg_text(t)797 gensvg_text (t)
798 F_text *t;
799 {
800 unsigned char *cp;
801 int ch;
802 const char *anchor[3] = { "start", "middle", "end" };
803 static const char *family[9] = { "Times", "AvantGarde",
804 "Bookman", "Courier", "Helvetica", "Helvetica Narrow",
805 "New Century Schoolbook", "Palatino", "Times,Symbol"
806 };
807 int x = (int) (t->base_x * mag);
808 int y = (int) (t->base_y * mag);
809 int dy = 0;
810
811 fprintf (tfp, "<!-- Text -->\n");
812 print_comments ("<!-- ", t->comments, " -->");
813
814 if (t->angle != 0) {
815 fprintf (tfp, "<g transform=\"translate(%d,%d) rotate(%.8lf)\" >\n",
816 x, y, degrees (t->angle));
817 x = y = 0;
818 }
819 fprintf (tfp, "<text xml:space=\"preserve\" x=\"%d\" y=\"%d\" fill=\"#%6.6x\" font-family=\"%s\" "\
820 "font-style=\"%s\" font-weight=\"%s\" font-size=\"%d\" text-anchor=\"%s\">",
821 x, y, rgbColorVal (t->color), family[t->font / 4],
822 ( (t->font % 2 == 0 || t->font >31) ? "normal" : "italic"),
823 ( (t->font % 4 < 2 || t->font >31) ? "normal" : "bold"), (int) (ceil (t->size * 12 * mag)),
824 anchor[t->type]);
825
826 if (t->font == 32) {
827 for (cp = (unsigned char *) t->cstring; *cp; cp++) {
828 ch=*cp;
829 fprintf (tfp, "&#%d;", symbolchar[ch]);
830 }
831 }
832 else if (t->font == 34) {
833 for (cp = (unsigned char *) t->cstring; *cp; cp++) {
834 ch=*cp;
835 fprintf (tfp, "&#%d;", dingbatchar[ch]);
836 }
837 }
838 else if (special_text(t)) {
839 int supsub=0;
840 int old_dy=0;
841 dy=0;
842 for (cp = (unsigned char *) t->cstring; *cp; cp++) {
843 ch = *cp;
844 if (( supsub == 2 &&ch == '}' ) || supsub==1) {
845 #ifdef NOSUPER
846 fprintf(tfp,"</tspan><tspan dy=\"%d\">",-dy);
847 old_dy=-dy;
848 #else
849 fprintf(tfp,"</tspan>");
850 #endif
851 supsub=0;
852 if (ch == '}') {
853 cp++;
854 ch=*cp;
855 }
856 }
857 if (ch == '_' || ch == '^') {
858 supsub=1;
859 #ifdef NOSUPER
860 if (dy != 0) fprintf(tfp,"</tspan>");
861 if (ch == '_') dy=(int)(35.*mag);
862 if (ch == '^') dy=(int)(-50.*mag);
863 fprintf(tfp,"<tspan font-size=\"%d\" dy=\"%d\">",(int) (ceil (t->size * 8 * mag)),dy+old_dy);
864 old_dy=0;
865 #else
866 fprintf(tfp,"<tspan font-size=\"%d\" baseline-shift=\"",(int) (ceil (t->size * 8 * mag)));
867 if (ch == '_') fprintf(tfp,"sub\">");
868 if (ch == '^') fprintf(tfp,"super\">");
869 #endif
870 cp++;
871 ch=*cp;
872 if (ch == '{' ) {
873 supsub=2;
874 cp++;
875 ch=*cp;
876 }
877 }
878 #ifdef NOSUPER
879 else old_dy=0;
880 #endif
881 if (ch < 128 && ch != 38 && ch != 60 && ch != 62
882 && ch != '$')
883 (void)fputc (ch, tfp);
884 else if (ch != '$')
885 fprintf (tfp, "&#%d;", ch);
886 }
887 } else {
888 for (cp = (unsigned char *) t->cstring; *cp; cp++) {
889 ch = *cp;
890 if (ch < 128 && ch != 38 && ch != 60 && ch != 62)
891 (void)fputc (ch, tfp);
892 else
893 fprintf (tfp, "&#%d;", ch);
894 }
895 }
896 #ifdef NOSUPER
897 if (dy != 0) fprintf(tfp,"</tspan>");
898 #endif
899 fprintf (tfp, "</text>\n");
900 if (t->angle != 0)
901 fprintf (tfp, "</g>");
902 }
903
904 static void
svg_arrow(F_line * obj,F_arrow * arrow,int pen_color)905 svg_arrow(F_line *obj, F_arrow *arrow, int pen_color)
906 {
907 int i;
908 if (arrow) {
909 calc_arrow(arrowx1, arrowy1, arrowx2, arrowy2,
910 obj->thickness, arrow,
911 points, &npoints, fillpoints, &nfillpoints, clippoints, &nclippoints);
912
913 fprintf (tfp, "<!-- Arrowhead on XXXpoint %d %d - %d %d-->\n",(int)(arrowx1*mag),(int)(arrowy1*mag),(int)(arrowx2*mag),(int)(arrowy2*mag));
914 fprintf (tfp, "<%s points=\"", (arrow->type == 0 ? "polyline" : "polygon"));
915 for (i = 0; i < npoints; i++) {
916 fprintf (tfp, "%d %d\n", (int) (points[i].x * mag),
917 (int) (points[i].y * mag));
918 }
919 if (arrow->type > 0)
920 fprintf (tfp, "\n");
921 fprintf (tfp, "\" style=\"stroke:#%6.6x;stroke-width:%d;stroke-miterlimit:8;\n",
922 rgbColorVal (pen_color), (int) ceil (linewidth_adj((int)arrow->thickness) * mag));
923 if (arrow->type > 0) {
924 if (arrow->style == 0 && nfillpoints == 0)
925 fprintf (tfp, "fill:white;\"/>\n");
926 else {
927 if (nfillpoints == 0)
928 fprintf (tfp, "fill:#%6.6x;\"/>\n", rgbColorVal (pen_color));
929 else {
930 /* first fill with white */
931 fprintf (tfp, "fill:white;\"/>\n");
932 fprintf (tfp, "<!-- Just filled with white now fill special area -->\n");
933 /* now fill the special area */
934 fprintf (tfp, "<path d=\"M ");
935 for (i = 0; i < nfillpoints; i++) {
936 fprintf (tfp, "%d %d\n", (int) (fillpoints[i].x * mag),
937 (int) (fillpoints[i].y * mag));
938 }
939 fprintf (tfp, "Z\n");
940 fprintf (tfp, "\" style=\"stroke:#%6.6x;stroke-width:%d;stroke-miterlimit:8;\n",
941 rgbColorVal (pen_color), (int) ceil (linewidth_adj((int)arrow->thickness) * mag));
942 fprintf (tfp, "fill:#%6.6x;\"/>\n", rgbColorVal (pen_color));
943 }
944 }
945 } else
946 fprintf (tfp, "\"/>\n");
947 }
948 }
949
generate_tile(int number)950 void generate_tile(int number) {
951
952 tileno++;
953 fprintf (tfp, "<defs>\n");
954 fprintf (tfp, "<pattern id=\"tile%d\" x=\"0\" y=\"0\" width=\"200\" height=\"200\"\n",
955 tileno);
956 fprintf (tfp, " patternUnits=\"userSpaceOnUse\">\n");
957
958 switch(number) {
959 case 1:
960 fprintf (tfp, "<path d=\"M 0 -100 200 20\" />\n");
961 fprintf (tfp, "<path d=\"M 0 -60 200 60\" />\n");
962 fprintf (tfp, "<path d=\"M 0 -20 200 100\" />\n");
963 fprintf (tfp, "<path d=\"M 0 20 200 140\" />\n");
964 fprintf (tfp, "<path d=\"M 0 60 200 180\" />\n");
965 fprintf (tfp, "<path d=\"M 0 100 200 220\" />\n");
966 fprintf (tfp, "<path d=\"M 0 140 200 260\" />\n");
967 fprintf (tfp, "<path d=\"M 0 180 200 300\" />\n");
968 break;
969
970 case 2:
971 fprintf (tfp, "<path d=\"M 200 -100 0 20\" />\n");
972 fprintf (tfp, "<path d=\"M 200 -60 0 60\" />\n");
973 fprintf (tfp, "<path d=\"M 200 -20 0 100\" />\n");
974 fprintf (tfp, "<path d=\"M 200 20 0 140\" />\n");
975 fprintf (tfp, "<path d=\"M 200 60 0 180\" />\n");
976 fprintf (tfp, "<path d=\"M 200 100 0 220\" />\n");
977 fprintf (tfp, "<path d=\"M 200 140 0 260\" />\n");
978 fprintf (tfp, "<path d=\"M 200 180 0 300\" />\n");
979 break;
980
981 case 3:
982 fprintf (tfp, "<path d=\"M 0 -100 200 20\" />\n");
983 fprintf (tfp, "<path d=\"M 200 -100 0 20\" />\n");
984 fprintf (tfp, "<path d=\"M 0 -60 200 60\" />\n");
985 fprintf (tfp, "<path d=\"M 200 -60 0 60\" />\n");
986 fprintf (tfp, "<path d=\"M 0 -20 200 100\" />\n");
987 fprintf (tfp, "<path d=\"M 200 -20 0 100\" />\n");
988 fprintf (tfp, "<path d=\"M 0 20 200 140\" />\n");
989 fprintf (tfp, "<path d=\"M 200 20 0 140\" />\n");
990 fprintf (tfp, "<path d=\"M 0 60 200 180\" />\n");
991 fprintf (tfp, "<path d=\"M 200 60 0 180\" />\n");
992 fprintf (tfp, "<path d=\"M 0 100 200 220\" />\n");
993 fprintf (tfp, "<path d=\"M 200 100 0 220\" />\n");
994 fprintf (tfp, "<path d=\"M 0 140 200 260\" />\n");
995 fprintf (tfp, "<path d=\"M 200 140 0 260\" />\n");
996 fprintf (tfp, "<path d=\"M 0 180 200 300\" />\n");
997 fprintf (tfp, "<path d=\"M 200 180 0 300\" />\n");
998 break;
999
1000 case 4:
1001 fprintf (tfp, "<path d=\"M 100 0 200 100\" />\n");
1002 fprintf (tfp, "<path d=\"M 0 0 200 200\" />\n");
1003 fprintf (tfp, "<path d=\"M 0 100 100 200\" />\n");
1004 break;
1005
1006 case 5:
1007 fprintf (tfp, "<path d=\"M 100 0 0 100\" />\n");
1008 fprintf (tfp, "<path d=\"M 200 0 0 200\" />\n");
1009 fprintf (tfp, "<path d=\"M 200 100 100 200\" />\n");
1010 break;
1011
1012 case 6:
1013 fprintf (tfp, "<path d=\"M 100 0 200 100\" />\n");
1014 fprintf (tfp, "<path d=\"M 0 0 200 200\" />\n");
1015 fprintf (tfp, "<path d=\"M 0 100 100 200\" />\n");
1016 fprintf (tfp, "<path d=\"M 100 0 0 100\" />\n");
1017 fprintf (tfp, "<path d=\"M 200 0 0 200\" />\n");
1018 fprintf (tfp, "<path d=\"M 200 100 100 200\" />\n");
1019 break;
1020
1021 case 7:
1022 fprintf (tfp, "<path d=\"M 0 0 0 50\" />\n");
1023 fprintf (tfp, "<path d=\"M 0 50 200 50\" />\n");
1024 fprintf (tfp, "<path d=\"M 100 50 100 150\" />\n");
1025 fprintf (tfp, "<path d=\"M 0 150 200 150\" />\n");
1026 fprintf (tfp, "<path d=\"M 0 150 0 200\" />\n");
1027 break;
1028
1029 case 8:
1030 fprintf (tfp, "<path d=\"M 0 0 50 0\" />\n");
1031 fprintf (tfp, "<path d=\"M 50 0 50 200\" />\n");
1032 fprintf (tfp, "<path d=\"M 50 100 150 100\" />\n");
1033 fprintf (tfp, "<path d=\"M 150 0 150 200\" />\n");
1034 fprintf (tfp, "<path d=\"M 150 0 200 0\" />\n");
1035 break;
1036
1037 case 9:
1038 fprintf (tfp, "<path d=\"M 0 50 200 50\" />\n");
1039 fprintf (tfp, "<path d=\"M 0 150 200 150\" />\n");
1040 break;
1041
1042 case 10:
1043 fprintf (tfp, "<path d=\"M 50 0 50 200\" />\n");
1044 fprintf (tfp, "<path d=\"M 150 0 150 200\" />\n");
1045 break;
1046
1047 case 11:
1048 fprintf (tfp, "<path d=\"M 0 50 200 50\" />\n");
1049 fprintf (tfp, "<path d=\"M 0 150 200 150\" />\n");
1050 fprintf (tfp, "<path d=\"M 50 0 50 200\" />\n");
1051 fprintf (tfp, "<path d=\"M 150 0 150 200\" />\n");
1052 break;
1053
1054 case 12:
1055 fprintf (tfp, "<path d=\"M 175 0 150 50\" />\n");
1056 fprintf (tfp, "<path d=\"M 0 50 200 50\" />\n");
1057 fprintf (tfp, "<path d=\"M 100 50 50 150\" />\n");
1058 fprintf (tfp, "<path d=\"M 0 150 200 150\" />\n");
1059 fprintf (tfp, "<path d=\"M 200 150 175 200\" />\n");
1060 break;
1061
1062 case 13:
1063 fprintf (tfp, "<path d=\"M 13 0 25 50\" />\n");
1064 fprintf (tfp, "<path d=\"M 0 50 200 50\" />\n");
1065 fprintf (tfp, "<path d=\"M 100 50 125 150\" />\n");
1066 fprintf (tfp, "<path d=\"M 0 150 200 150\" />\n");
1067 fprintf (tfp, "<path d=\"M 0 150 13 200\" />\n");
1068 break;
1069
1070
1071 case 14:
1072 fprintf (tfp, "<path d=\"M 0 13 50 25\" />\n");
1073 fprintf (tfp, "<path d=\"M 50 0 50 200\" />\n");
1074 fprintf (tfp, "<path d=\"M 50 100 150 125\" />\n");
1075 fprintf (tfp, "<path d=\"M 150 0 150 200\" />\n");
1076 fprintf (tfp, "<path d=\"M 150 0 200 13\" />\n");
1077 break;
1078
1079 case 15:
1080 fprintf (tfp, "<path d=\"M 0 13 50 0\" />\n");
1081 fprintf (tfp, "<path d=\"M 50 0 50 200\" />\n");
1082 fprintf (tfp, "<path d=\"M 50 125 150 100\" />\n");
1083 fprintf (tfp, "<path d=\"M 150 0 150 200\" />\n");
1084 fprintf (tfp, "<path d=\"M 150 25 200 13\" />\n");
1085 break;
1086
1087 case 16:
1088 fprintf (tfp, "<path d=\"M 0 50 A 50 50 0 1 0 100 50\" />\n");
1089 fprintf (tfp, "<path d=\"M 100 50 A 50 50 0 1 0 200 50\" />\n");
1090 fprintf (tfp, "<path d=\"M 50 100 A 50 50 0 1 0 150 100\" />\n");
1091 fprintf (tfp, "<path d=\"M 0 150 A 50 50 0 0 0 50 100\" />\n");
1092 fprintf (tfp, "<path d=\"M 150 100 A 50 50 0 1 0 200 50\" />\n");
1093 fprintf (tfp, "<path d=\"M 50 0 A 50 50 0 1 0 150 0\" />\n");
1094 fprintf (tfp, "<path d=\"M 150 0 A 50 50 0 0 0 200 50\" />\n");
1095 fprintf (tfp, "<path d=\"M 0 50 A 50 50 0 0 0 50 0\" />\n");
1096 fprintf (tfp, "<path d=\"M 0 150 A 50 50 0 1 0 100 150\" />\n");
1097 fprintf (tfp, "<path d=\"M 100 150 A 50 50 0 1 0 200 150\" />\n");
1098 break;
1099
1100 case 17:
1101 fprintf (tfp, "<g transform=\"scale(0.5)\" >\n");
1102 fprintf (tfp, "<path d=\"M 0 50 A 50 50 0 1 0 100 50\" />\n");
1103 fprintf (tfp, "<path d=\"M 100 50 A 50 50 0 1 0 200 50\" />\n");
1104 fprintf (tfp, "<path d=\"M 50 100 A 50 50 0 1 0 150 100\" />\n");
1105 fprintf (tfp, "<path d=\"M 0 150 A 50 50 0 0 0 50 100\" />\n");
1106 fprintf (tfp, "<path d=\"M 150 100 A 50 50 0 1 0 200 50\" />\n");
1107 fprintf (tfp, "<path d=\"M 50 0 A 50 50 0 1 0 150 0\" />\n");
1108 fprintf (tfp, "<path d=\"M 150 0 A 50 50 0 0 0 200 50\" />\n");
1109 fprintf (tfp, "<path d=\"M 0 50 A 50 50 0 0 0 50 0\" />\n");
1110 fprintf (tfp, "<path d=\"M 0 150 A 50 50 0 1 0 100 150\" />\n");
1111 fprintf (tfp, "<path d=\"M 100 150 A 50 50 0 1 0 200 150\" />\n");
1112 fprintf (tfp, "</g>\n");
1113 break;
1114
1115 case 18:
1116 fprintf (tfp, "<circle cx=\"100\" cy=\"100\" r=\"100\" />\n");
1117 break;
1118
1119 case 19:
1120 fprintf (tfp, "<path d=\"M 0 50 45 0 105 0 140 50 200 50 \" />\n");
1121 fprintf (tfp, "<path d=\"M 0 50 45 100 105 100 140 50 200 50\" />\n");
1122 fprintf (tfp, "<path d=\"M 0 150 45 100 105 100 140 150 200 150\" />\n");
1123 fprintf (tfp, "<path d=\"M 0 150 45 200 105 200 140 150 200 150\" />\n");
1124 break;
1125
1126 case 20:
1127 fprintf (tfp, "<path d=\"M 0 70 65 0 140 0 200 70 \" />\n");
1128 fprintf (tfp, "<path d=\"M 0 70 0 130 65 200 140 200 200 130 200 70\" />\n");
1129 break;
1130
1131 case 21:
1132 fprintf (tfp, "<path d=\"M 50 0 75 25 100 0 M 150 0 175 25 200 0\" />\n");
1133 fprintf (tfp, "<path d=\"M 0 50 25 25 75 75 125 25 175 75 200 50\" />\n");
1134 fprintf (tfp, "<path d=\"M 0 100 25 75 75 125 125 75 175 125 200 100\" />\n");
1135 fprintf (tfp, "<path d=\"M 0 150 25 125 75 175 125 125 175 175 200 150\" />\n");
1136 fprintf (tfp, "<path d=\"M 0 200 25 175 75 225 125 175 175 225 200 200\" />\n");
1137 break;
1138
1139 case 22:
1140 fprintf (tfp, "<path d=\"M 0 50 25 75 0 100 M 0 150 25 175 0 200\" />\n");
1141 fprintf (tfp, "<path d=\"M 50 0 25 25 75 75 25 125 75 175 50 200\" />\n");
1142 fprintf (tfp, "<path d=\"M 100 0 75 25 125 75 75 125 125 175 100 200\" />\n");
1143 fprintf (tfp, "<path d=\"M 150 0 125 25 175 75 125 125 175 175 150 200\" />\n");
1144 fprintf (tfp, "<path d=\"M 200 0 175 25 225 75 175 125 225 175 200 200\" />\n");
1145 break;
1146
1147 }
1148 fprintf (tfp, "</pattern>\n");
1149 fprintf (tfp, "</defs>\n");
1150
1151 return;
1152
1153 } /* generate_tile */
1154
svg_dash(int style,double val)1155 void svg_dash(int style, double val)
1156 {
1157 fprintf (tfp, "stroke-dasharray:");
1158 switch (style) {
1159 case 1:
1160 default:
1161 fprintf(tfp,"%d %d;",(int)(val*10*mag),(int)(val*10*mag));
1162 break;
1163 case 2:
1164 fprintf(tfp,"10 %d;",(int)(val*10*mag));
1165 break;
1166 case 3:
1167 fprintf(tfp,"%d %d 10 %d;",(int)(val*10*mag),
1168 (int)(val*5*mag),(int)(val*5*mag));
1169 break;
1170 case 4:
1171 fprintf(tfp,"%d %d 10 %d 10 %d;",(int)(val*10*mag),
1172 (int)(val*3*mag),(int)(val*3*mag),(int)(val*3*mag));
1173 break;
1174 case 5:
1175 fprintf(tfp,"%d %d 10 %d 10 %d 10 %d;",(int)(val*10*mag),
1176 (int)(val*3*mag),(int)(val*3*mag),(int)(val*3*mag),(int)(val*3*mag));
1177 break;
1178 }
1179 }
1180
1181 /* driver defs */
1182
1183 struct driver dev_svg = {
1184 gensvg_option,
1185 gensvg_start,
1186 gendev_null,
1187 gensvg_arc,
1188 gensvg_ellipse,
1189 gensvg_line,
1190 gensvg_spline,
1191 gensvg_text,
1192 gensvg_end,
1193 INCLUDE_TEXT
1194 };
1195