w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

backend_svg.c
Go to the documentation of this file.
1 /* Copyright (C) 2001-2019 Peter Selinger.
2  This file is part of Potrace. It is free software and it is covered
3  by the GNU General Public License. See the file COPYING for details. */
4 
5 
6 /* The SVG backend of Potrace. */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <string.h>
15 #include <math.h>
16 
17 #include "potracelib.h"
18 #include "curve.h"
19 #include "main.h"
20 #include "backend_svg.h"
21 #include "lists.h"
22 #include "auxiliary.h"
23 
24 /* ---------------------------------------------------------------------- */
25 /* path-drawing auxiliary functions */
26 
27 /* coordinate quantization */
28 static inline point_t unit(dpoint_t p) {
29  point_t q;
30 
31  q.x = (long)(floor(p.x*info.unit+.5));
32  q.y = (long)(floor(p.y*info.unit+.5));
33  return q;
34 }
35 
36 static point_t cur;
37 static char lastop = 0;
38 static int column = 0;
39 static int newline = 1;
40 
41 static void shiptoken(FILE *fout, const char *token) {
42  int c = strlen(token);
43  if (!newline && column+c+1 > 75) {
44  fprintf(fout, "\n");
45  column = 0;
46  newline = 1;
47  } else if (!newline) {
48  fprintf(fout, " ");
49  column++;
50  }
51  fprintf(fout, "%s", token);
52  column += c;
53  newline = 0;
54 }
55 
56 static void ship(FILE *fout, const char *fmt, ...) {
57  va_list args;
58  static char buf[4096]; /* static string limit is okay here because
59  we only use constant format strings - for
60  the same reason, it is okay to use
61  vsprintf instead of vsnprintf below. */
62  char *p, *q;
63 
64  va_start(args, fmt);
65  vsprintf(buf, fmt, args);
66  buf[4095] = 0;
67  va_end(args);
68 
69  p = buf;
70  while ((q = strchr(p, ' ')) != NULL) {
71  *q = 0;
72  shiptoken(fout, p);
73  p = q+1;
74  }
75  shiptoken(fout, p);
76 }
77 
78 static void svg_moveto(FILE *fout, dpoint_t p) {
79  cur = unit(p);
80 
81  ship(fout, "M%ld %ld", cur.x, cur.y);
82  lastop = 'M';
83 }
84 
85 static void svg_rmoveto(FILE *fout, dpoint_t p) {
86  point_t q;
87 
88  q = unit(p);
89  ship(fout, "m%ld %ld", q.x-cur.x, q.y-cur.y);
90  cur = q;
91  lastop = 'm';
92 }
93 
94 static void svg_lineto(FILE *fout, dpoint_t p) {
95  point_t q;
96 
97  q = unit(p);
98 
99  if (lastop != 'l') {
100  ship(fout, "l%ld %ld", q.x-cur.x, q.y-cur.y);
101  } else {
102  ship(fout, "%ld %ld", q.x-cur.x, q.y-cur.y);
103  }
104  cur = q;
105  lastop = 'l';
106 }
107 
109  point_t q1, q2, q3;
110 
111  q1 = unit(p1);
112  q2 = unit(p2);
113  q3 = unit(p3);
114 
115  if (lastop != 'c') {
116  ship(fout, "c%ld %ld %ld %ld %ld %ld", q1.x-cur.x, q1.y-cur.y, q2.x-cur.x, q2.y-cur.y, q3.x-cur.x, q3.y-cur.y);
117  } else {
118  ship(fout, "%ld %ld %ld %ld %ld %ld", q1.x-cur.x, q1.y-cur.y, q2.x-cur.x, q2.y-cur.y, q3.x-cur.x, q3.y-cur.y);
119  }
120  cur = q3;
121  lastop = 'c';
122 }
123 
124 /* ---------------------------------------------------------------------- */
125 /* functions for converting a path to an SVG path element */
126 
127 /* Explicit encoding. If abs is set, move to first coordinate
128  absolutely. */
129 static int svg_path(FILE *fout, potrace_curve_t *curve, int abs) {
130  int i;
131  dpoint_t *c;
132  int m = curve->n;
133 
134  c = curve->c[m-1];
135  if (abs) {
136  svg_moveto(fout, c[2]);
137  } else {
138  svg_rmoveto(fout, c[2]);
139  }
140 
141  for (i=0; i<m; i++) {
142  c = curve->c[i];
143  switch (curve->tag[i]) {
144  case POTRACE_CORNER:
145  svg_lineto(fout, c[1]);
146  svg_lineto(fout, c[2]);
147  break;
148  case POTRACE_CURVETO:
149  svg_curveto(fout, c[0], c[1], c[2]);
150  break;
151  }
152  }
153  newline = 1;
154  shiptoken(fout, "z");
155  return 0;
156 }
157 
158 /* produce a jaggy path - for debugging. If abs is set, move to first
159  coordinate absolutely. If abs is not set, move to first coordinate
160  relatively, and traverse path in the opposite direction. */
161 static int svg_jaggy_path(FILE *fout, point_t *pt, int n, int abs) {
162  int i;
163  point_t cur, prev;
164 
165  if (abs) {
166  cur = prev = pt[n-1];
168  for (i=0; i<n; i++) {
169  if (pt[i].x != cur.x && pt[i].y != cur.y) {
170  cur = prev;
172  }
173  prev = pt[i];
174  }
175  svg_lineto(fout, dpoint(pt[n-1]));
176  } else {
177  cur = prev = pt[0];
179  for (i=n-1; i>=0; i--) {
180  if (pt[i].x != cur.x && pt[i].y != cur.y) {
181  cur = prev;
183  }
184  prev = pt[i];
185  }
186  svg_lineto(fout, dpoint(pt[0]));
187  }
188  newline = 1;
189  shiptoken(fout, "z");
190  return 0;
191 }
192 
194  potrace_path_t *p, *q;
195 
196  for (p=tree; p; p=p->sibling) {
197  if (info.grouping == 2) {
198  fprintf(fout, "<g>\n");
199  fprintf(fout, "<g>\n");
200  }
201  column = fprintf(fout, "<path fill=\"#%06x\" stroke=\"none\" d=\"", info.color);
202  newline = 1;
203  lastop = 0;
204  if (info.debug == 1) {
205  svg_jaggy_path(fout, p->priv->pt, p->priv->len, 1);
206  } else {
207  svg_path(fout, &p->curve, 1);
208  }
209  fprintf(fout, "\"/>\n");
210  for (q=p->childlist; q; q=q->sibling) {
211  column = fprintf(fout, "<path fill=\"#%06x\" stroke=\"none\" d=\"", info.fillcolor);
212  newline = 1;
213  lastop = 0;
214  if (info.debug == 1) {
215  svg_jaggy_path(fout, q->priv->pt, q->priv->len, 1);
216  } else {
217  svg_path(fout, &q->curve, 1);
218  }
219  fprintf(fout, "\"/>\n");
220  }
221  if (info.grouping == 2) {
222  fprintf(fout, "</g>\n");
223  }
224  for (q=p->childlist; q; q=q->sibling) {
225  write_paths_opaque(fout, q->childlist);
226  }
227  if (info.grouping == 2) {
228  fprintf(fout, "</g>\n");
229  }
230  }
231 }
232 
234  potrace_path_t *p, *q;
235 
236  for (p=tree; p; p=p->sibling) {
237  if (info.grouping == 2) {
238  fprintf(fout, "<g>\n");
239  }
240  if (info.grouping != 0) {
241  column = fprintf(fout, "<path d=\"");
242  newline = 1;
243  lastop = 0;
244  }
245  if (info.debug == 1) {
246  svg_jaggy_path(fout, p->priv->pt, p->priv->len, 1);
247  } else {
248  svg_path(fout, &p->curve, 1);
249  }
250  for (q=p->childlist; q; q=q->sibling) {
251  if (info.debug == 1) {
252  svg_jaggy_path(fout, q->priv->pt, q->priv->len, 0);
253  } else {
254  svg_path(fout, &q->curve, 0);
255  }
256  }
257  if (info.grouping != 0) {
258  fprintf(fout, "\"/>\n");
259  }
260  for (q=p->childlist; q; q=q->sibling) {
261  write_paths_transparent_rec(fout, q->childlist);
262  }
263  if (info.grouping == 2) {
264  fprintf(fout, "</g>\n");
265  }
266  }
267 }
268 
270  if (info.grouping == 0) {
271  column = fprintf(fout, "<path d=\"");
272  newline = 1;
273  lastop = 0;
274  }
276  if (info.grouping == 0) {
277  fprintf(fout, "\"/>\n");
278  }
279 }
280 
281 /* ---------------------------------------------------------------------- */
282 /* Backend. */
283 
284 /* public interface for SVG */
285 int page_svg(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
286 
287  double bboxx = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
288  double bboxy = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
289  double origx = imginfo->trans.orig[0] + imginfo->lmar;
290  double origy = bboxy - imginfo->trans.orig[1] - imginfo->bmar;
291  double scalex = imginfo->trans.scalex / info.unit;
292  double scaley = -imginfo->trans.scaley / info.unit;
293 
294  /* header */
295  fprintf(fout, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
296  fprintf(fout, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n");
297  fprintf(fout, " \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n");
298 
299  /* set bounding box and namespace */
300  fprintf(fout, "<svg version=\"1.0\" xmlns=\"http://www.w3.org/2000/svg\"\n");
301  fprintf(fout, " width=\"%fpt\" height=\"%fpt\" viewBox=\"0 0 %f %f\"\n",
302  bboxx, bboxy, bboxx, bboxy);
303  fprintf(fout, " preserveAspectRatio=\"xMidYMid meet\">\n");
304 
305  /* metadata: creator */
306  fprintf(fout, "<metadata>\n");
307  fprintf(fout, "Created by " POTRACE " " VERSION ", written by Peter Selinger 2001-2019\n");
308  fprintf(fout, "</metadata>\n");
309 
310  /* use a "group" tag to establish coordinate system and style */
311  fprintf(fout, "<g transform=\"");
312  if (origx != 0 || origy != 0) {
313  fprintf(fout, "translate(%f,%f) ", origx, origy);
314  }
315  if (info.angle != 0) {
316  fprintf(fout, "rotate(%.2f) ", -info.angle);
317  }
318  fprintf(fout, "scale(%f,%f)", scalex, scaley);
319  fprintf(fout, "\"\n");
320  fprintf(fout, "fill=\"#%06x\" stroke=\"none\">\n", info.color);
321 
322  if (info.opaque) {
323  write_paths_opaque(fout, plist);
324  } else {
326  }
327 
328  /* write footer */
329  fprintf(fout, "</g>\n");
330  fprintf(fout, "</svg>\n");
331  fflush(fout);
332 
333  return 0;
334 }
335 
336 /* the Gimppath backend is identical, except that it disables
337  --opaque, enables --flat, and the dimensions are pixel-based */
338 int page_gimp(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
339  info.opaque = 0;
340  info.grouping = 0;
341  return page_svg(fout, plist, imginfo);
342 }
q
Definition: afm2pl.c:2287
static void svg_curveto(FILE *fout, dpoint_t p1, dpoint_t p2, dpoint_t p3)
Definition: backend_svg.c:108
int page_svg(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo)
Definition: backend_svg.c:285
static void svg_lineto(FILE *fout, dpoint_t p)
Definition: backend_svg.c:94
static void write_paths_transparent(FILE *fout, potrace_path_t *tree)
Definition: backend_svg.c:269
static void write_paths_transparent_rec(FILE *fout, potrace_path_t *tree)
Definition: backend_svg.c:233
static void ship(FILE *fout, const char *fmt,...)
Definition: backend_svg.c:56
static int column
Definition: backend_svg.c:38
static int newline
Definition: backend_svg.c:39
static int svg_jaggy_path(FILE *fout, point_t *pt, int n, int abs)
Definition: backend_svg.c:161
int page_gimp(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo)
Definition: backend_svg.c:338
static point_t unit(dpoint_t p)
Definition: backend_svg.c:28
static void svg_rmoveto(FILE *fout, dpoint_t p)
Definition: backend_svg.c:85
static char lastop
Definition: backend_svg.c:37
static void write_paths_opaque(FILE *fout, potrace_path_t *tree)
Definition: backend_svg.c:193
static void svg_moveto(FILE *fout, dpoint_t p)
Definition: backend_svg.c:78
static void shiptoken(FILE *fout, const char *token)
Definition: backend_svg.c:41
static point_t cur
Definition: backend_svg.c:36
static int svg_path(FILE *fout, potrace_curve_t *curve, int abs)
Definition: backend_svg.c:129
char * p2
Definition: bmpfont.h:62
char * p1
Definition: bmpfont.h:62
#define n
Definition: t4ht.c:1290
#define q1
#define q3
#define q2
#define fflush
Definition: xxstdio.h:24
FILE * fout
#define info
Definition: dviinfo.c:42
static FIELD_PTR prev
Definition: genind.c:36
@ VERSION
Definition: genrb.cpp:69
#define c(n)
Definition: gpos-common.c:150
#define strchr
Definition: gsftopk.c:59
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
#define buf
#define fprintf
Definition: mendex.h:64
#define floor(x)
Definition: cpascal.h:52
char args[100]
Definition: fixwrites.c:7
static float origx
Definition: lexyy.cpp:1540
static float origy
Definition: lexyy.cpp:1540
static dpoint_t dpoint(point_t p)
Definition: auxiliary.h:31
#define POTRACE_CURVETO
Definition: potracelib.h:74
#define POTRACE_CORNER
Definition: potracelib.h:75
float x
Definition: cordic.py:15
#define abs(a)
Definition: pbmplus.h:225
#define POTRACE
Definition: config.h:78
Definition: usprintf.c:39
Definition: mpost.c:242
Definition: main.h:99
double tmar
Definition: main.h:104
double rmar
Definition: main.h:104
trans_t trans
Definition: main.h:105
double bmar
Definition: main.h:104
double lmar
Definition: main.h:104
long x
Definition: auxiliary.h:23
long y
Definition: auxiliary.h:24
Definition: parser.c:43
double scalex
Definition: trans.h:17
double scaley
Definition: trans.h:17
double orig[2]
Definition: trans.h:14
double bb[2]
Definition: trans.h:13
#define FILE
Definition: t1stdio.h:34
*job_name strlen((char *) job_name) - 4)
char fmt[256]
Definition: tex4ht.c:3925
m
Definition: tex4ht.c:3990
#define va_start(pvar)
Definition: varargs.h:30
#define va_end(pvar)
Definition: varargs.h:38
char * va_list
Definition: varargs.h:22
PATTERN * pt
Definition: vlna.c:74