Graphviz  2.41.20170921.2350
mpgen.c
Go to the documentation of this file.
1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 /* mpgen.c 1999-Feb-23 Jim Hefferon jim@joshua.smcvt.edu
15  * Adapted from psgen.c. See 1st_read.mp.
16  */
17 #include "render.h"
18 #ifndef _WIN32
19 #include <unistd.h>
20 #endif
21 #include <sys/stat.h>
22 
23 
24 #define NONE 0
25 #define NODE 1
26 #define EDGE 2
27 #define CLST 3
28 
29 /* static point Pages; */
30 /* static box PB; */
31 static int onetime = TRUE;
32 
33 static const char **U_lib;
34 
35 typedef struct grcontext_t {
36  char *color, *font;
37  double size;
38 } grcontext_t;
39 
40 #define STACKSIZE 32 /* essentially infinite? */
41 static grcontext_t S[STACKSIZE];
42 static int SP = 0;
43 
44 static void mp_reset(void)
45 {
46  onetime = TRUE;
47 }
48 
49 /* mp_cat_libfile:
50  * Write library files onto the given file pointer.
51  * arglib is an NULL-terminated array of char*
52  * Each non-trivial entry should be the name of a file to be included.
53  * stdlib is an NULL-terminated array of char*
54  * Each of these is a line of a standard library to be included.
55  * If any item in arglib is the empty string, the stdlib is not used.
56  * The stdlib is printed first, if used, followed by the user libraries.
57  * We check that for web-safe file usage.
58  */
59 static void mp_cat_libfile(FILE * ofp, const char **arglib, const char **stdlib)
60 {
61  FILE *fp;
62  const char **s, *bp, *p, *path;
63  int i;
64  boolean use_stdlib = TRUE;
65 
66  /* check for empty string to turn off stdlib */
67  if (arglib) {
68  for (i = 0; use_stdlib && ((p = arglib[i])); i++) {
69  if (*p == '\0')
70  use_stdlib = FALSE;
71  }
72  }
73  if (use_stdlib)
74  for (s = stdlib; *s; s++) {
75  fputs(*s, ofp);
76  fputc('\n', ofp);
77  }
78  if (arglib) {
79  for (i = 0; (p = arglib[i]) != 0; i++) {
80  if (*p == '\0')
81  continue; /* ignore empty string */
82  path = safefile(p); /* make sure filename is okay */
83  if (!path) {
84  agerr(AGWARN, "can't find library file %s\n", p);
85  }
86  else if ((fp = fopen(path, "r"))) {
87  while ((bp = Fgets(fp)))
88  fputs(bp, ofp);
89  fputc('\n', ofp); /* append a newline just in case */
90  fclose (fp);
91  } else
92  agerr(AGWARN, "can't open library file %s\n", path);
93  }
94  }
95 }
96 
97 static void
98 mp_begin_job(FILE * ofp, graph_t * g, const char **lib, char *info[], point pages)
99 {
100  /* pages and libraries not here (yet?) */
101  /* Pages = pages; */
102  U_lib = lib;
103  /* N_pages = pages.x * pages.y; */
104  /* Cur_page = 0; */
105 
106  fprintf(Output_file, "%%--- graphviz MetaPost input\n");
107  fprintf(Output_file, "%% Created by program: %s version %s (%s)\n",
108  info[0], info[1], info[2]);
109  fprintf(Output_file, "%% Title: %s\n", agnameof(g));
110  fprintf(Output_file,
111  "%% Put this between beginfig and endfig. See 1st_read.mp.\n");
112  fprintf(Output_file, "%% \n");
113 }
114 
115 static void mp_end_job(void)
116 {
117  fprintf(Output_file, "%% End of graphviz MetaPost input\n");
118  fprintf(Output_file, "%% \n");
119 }
120 
121 static void mp_comment(char *str)
122 {
123  fprintf(Output_file, "%% %s\n", str);
124 }
125 
126 static void mp_begin_graph(GVC_t * gvc, graph_t * g, box bb, point pb)
127 {
128  /* PB = bb; */
129  static const char *mp_lib[] = {0};
130  if (onetime) {
131  fprintf(Output_file, "%% BoundingBox: %d %d %d %d\n",
132  bb.LL.x, bb.LL.y, bb.UR.x + 1, bb.UR.y + 1);
133  mp_cat_libfile(Output_file,U_lib,mp_lib);
134  onetime = FALSE;
135  }
136 }
137 
138 static void
139 mp_begin_page(graph_t * g, point page, double scale, int rot, point offset)
140 {
141  assert(SP == 0);
142  S[SP].font = "";
143  S[SP].color = "black";
144  S[SP].size = 0.0;
145 }
146 
147 static void mp_begin_context(void)
148 {
149  if (SP == STACKSIZE - 1)
150  agerr(AGWARN, "mpgen stack overflow\n");
151  else {
152  SP++;
153  S[SP] = S[SP - 1];
154  }
155 }
156 
157 static void mp_end_context(void)
158 {
159  if (SP == 0)
160  agerr(AGWARN, "mpgen stack underflow\n");
161  else
162  SP--;
163 }
164 
165 static void mp_set_font(char *name, double size)
166 {
167  if (strcmp(S[SP].font, name) || (size != S[SP].size)) {
168  fprintf(Output_file, "%% GV set font: %.2f /%s ignored\n", size,
169  name);
170  S[SP].font = name;
171  S[SP].size = size;
172  }
173 }
174 
175 static void mp_set_color(char *name)
176 {
177  static char *op[] = { "graph", "node", "edge", "sethsb" };
178  gvcolor_t color;
179 
180  if (strcmp(name, S[SP].color)) {
181  colorxlate(name, &color, HSVA_DOUBLE);
182  fprintf(Output_file, "%% GV set color: %.3f %.3f %.3f %scolor\n",
183  color.u.HSVA[0], color.u.HSVA[1], color.u.HSVA[2], op[Obj]);
184  }
185  S[SP].color = name;
186 }
187 
188 static void mp_set_style(char **s)
189 {
190  char *line, *p;
191 
192  while ((p = line = *s++)) {
193  while (*p)
194  p++;
195  p++;
196  while (*p) {
197  fprintf(Output_file, "%% GV set style: %s \n", p);
198  while (*p)
199  p++;
200  p++;
201  }
202  fprintf(Output_file, "%% GV set style:: %s\n", line);
203  }
204 }
205 
206 static char *mp_string(char *s)
207 {
208  static char *buf = NULL;
209  static int bufsize = 0;
210  int pos = 0;
211  char *p;
212 
213  if (!buf) {
214  bufsize = 64;
215  buf = N_GNEW(bufsize, char);
216  }
217 
218  p = buf;
219  while (*s) {
220  if (pos > (bufsize - 8)) {
221  bufsize *= 2;
222  buf = grealloc(buf, bufsize);
223  p = buf + pos;
224  }
225  if ((*s == LPAREN) || (*s == RPAREN)) {
226  *p++ = '\\';
227  pos++;
228  }
229  *p++ = *s++;
230  pos++;
231  }
232  *p = '\0';
233  return buf;
234 }
235 
236 static void mp_textpara(point p, textpara_t * para)
237 {
238  fprintf(Output_file, "label(btex %s etex,(%dbp,%dbp)) withcolor %s;\n",
239  mp_string(para->str), p.x, p.y, S[SP].color);
240 }
241 
242 static void
243 mp_bezier(point * A, int n, int arrow_at_start, int arrow_at_end, int filled)
244 {
245  int j;
246  if (arrow_at_start || arrow_at_end)
247  agerr(AGERR, "mp_bezier illegal arrow args\n");
248  fprintf(Output_file, "draw (%dbp,%dbp) ", A[0].x, A[0].y);
249  for (j = 1; j < n; j += 3)
250  fprintf(Output_file,
251  "\n ..controls (%dbp,%dbp) and (%dbp,%dbp).. (%dbp,%dbp)",
252  A[j].x, A[j].y, A[j + 1].x, A[j + 1].y, A[j + 2].x,
253  A[j + 2].y);
254  fprintf(Output_file, " withcolor %s;\n", S[SP].color);
255 }
256 
257 static void mp_polygon(point * A, int n, int filled)
258 {
259  int j;
260  if (filled) {
261  fprintf(Output_file, " fill (%dbp,%dbp)", A[0].x, A[0].y);
262  for (j = 1; j < n; j++)
263  fprintf(Output_file, "\n --(%dbp,%dbp)", A[j].x, A[j].y);
264  fprintf(Output_file, "\n --cycle withcolor %s;\n", S[SP].color);
265  }
266  fprintf(Output_file, "draw (%dbp,%dbp) ", A[0].x, A[0].y);
267  for (j = 1; j < n; j++)
268  fprintf(Output_file, "\n --(%dbp,%dbp)", A[j].x, A[j].y);
269  fprintf(Output_file, "\n --cycle withcolor %s;\n", S[SP].color);
270 }
271 
272 static void mp_ellipse(point p, int rx, int ry, int filled)
273 {
274  if (filled)
275  fprintf(Output_file,
276  " fill fullcircle xscaled %dbp yscaled %dbp shifted (%dbp,%dbp) withcolor %s;\n",
277  2 * rx, 2 * ry, p.x, p.y, S[SP].color);
278  fprintf(Output_file,
279  "draw fullcircle xscaled %dbp yscaled %dbp shifted (%dbp,%dbp);\n",
280  2 * rx, 2 * ry, p.x, p.y);
281 }
282 
283 static void mp_polyline(point * A, int n)
284 {
285  int j;
286 
287  fprintf(Output_file, "draw (%dbp,%dbp) ", A[0].x, A[0].y);
288  for (j = 1; j < n; j++)
289  fprintf(Output_file, "\n --(%dbp,%dbp)", A[j].x, A[j].y);
290  fprintf(Output_file, " withcolor %s;\n", S[SP].color);
291 }
292 
293 static void mp_usershape(usershape_t *us, boxf b, point *A, int n, boolean filled)
294 {
295  int j;
296  fprintf(Output_file, "%%GV USER SHAPE [ ");
297  for (j = 0; j < n; j++)
298  fprintf(Output_file, "%d %d ", A[j].x, A[j].y);
299  fprintf(Output_file, "%d %d ", A[0].x, A[0].y);
300  fprintf(Output_file, "] %d %s %s ignored\n", n,
301  (filled ? "true" : "false"), us->name);
302 }
303 
304 codegen_t MP_CodeGen = {
305  mp_reset,
306  mp_begin_job, mp_end_job,
307  mp_begin_graph, 0, /* mp_end_graph */
308  mp_begin_page, 0, /* mp_end_page */
309  0, /* mp_begin_layer */ 0, /* mp_end_layer */
310  0, /* mp_begin_cluster */ 0, /* mp_end_cluster */
311  0, /* mp_begin_nodes */ 0, /* mp_end_nodes */
312  0, /* mp_begin_edges */ 0, /* mp_end_edges */
313  0, /* mp_begin_node */ 0, /* mp_end_node */
314  0, /* mp_begin_edge */ 0, /* mp_end_edge */
315  mp_begin_context, mp_end_context,
316  0, /* mp_begin_anchor */ 0, /* mp_end_anchor */
317  mp_set_font, mp_textpara,
318  mp_set_color, mp_set_color, mp_set_style,
319  mp_ellipse, mp_polygon,
320  mp_bezier, mp_polyline,
321  0, /* bezier_has_arrows */
322  mp_comment,
323  mp_usershape
324 };
Definition: cgraph.h:388
#define RPAREN
Definition: const.h:19
void * grealloc(void *ptr, size_t size)
Definition: memory.c:54
char * color
Definition: mpgen.c:36
char * font
Definition: mpgen.c:36
#define assert(x)
Definition: cghdr.h:47
codegen_t MP_CodeGen
Definition: mpgen.c:304
Definition: color.h:34
int agerr(agerrlevel_t level, const char *fmt,...)
Definition: agerror.c:141
point UR
Definition: geom.h:33
int x
Definition: geom.h:26
Definition: cgraph.h:388
#define LPAREN
Definition: const.h:18
struct path path
Definition: gvcint.h:70
CGRAPH_API char * agnameof(void *)
Definition: id.c:143
char * Fgets(FILE *fp)
Definition: utils.c:282
point LL
Definition: geom.h:33
Definition: grammar.c:79
int colorxlate(char *str, gvcolor_t *color, color_type_t target_type)
Definition: colxlate.c:254
const char * safefile(const char *filename)
Definition: utils.c:376
#define NULL
Definition: logic.h:39
Definition: geom.h:26
GVC_t * gvc
Definition: htmlparse.c:87
double size
Definition: mpgen.c:37
struct grcontext_t grcontext_t
agxbuf * str
Definition: htmlparse.c:85
int y
Definition: geom.h:26
const char * name
Definition: usershape.h:53
Definition: geom.h:35
#define N_GNEW(n, t)
Definition: agxbuf.c:20
#define FALSE
Definition: cgraph.h:35
#define STACKSIZE
Definition: mpgen.c:40
Definition: geom.h:33
#define TRUE
Definition: cgraph.h:38