Graphviz  2.41.20171026.1811
gvrender_core_tk.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 #include "config.h"
15 
16 #include <stdarg.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #include "macros.h"
21 #include "const.h"
22 
23 #include "gvplugin_render.h"
24 #include "gvplugin_device.h"
25 #include "gvio.h"
26 #include "gvcint.h"
27 
28 typedef enum { FORMAT_TK, } format_type;
29 
30 static char *tkgen_string(char *s)
31 {
32  return s;
33 }
34 
35 static void tkgen_print_color(GVJ_t * job, gvcolor_t color)
36 {
37  switch (color.type) {
38  case COLOR_STRING:
39  gvputs(job, color.u.string);
40  break;
41  case RGBA_BYTE:
42  if (color.u.rgba[3] == 0) /* transparent */
43  gvputs(job, "\"\"");
44  else
45  gvprintf(job, "#%02x%02x%02x",
46  color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]);
47  break;
48  default:
49  assert(0); /* internal error */
50  }
51 }
52 
53 static void tkgen_print_tags(GVJ_t *job)
54 {
55  char *ObjType;
56  unsigned int ObjId;
57  obj_state_t *obj = job->obj;
58  int ObjFlag;
59 
60  switch (obj->emit_state) {
61  case EMIT_NDRAW:
62  ObjType = "node";
63  ObjFlag = 1;
64  ObjId = AGID(obj->u.n);
65  break;
66  case EMIT_NLABEL:
67  ObjType = "node";
68  ObjFlag = 0;
69  ObjId = AGID(obj->u.n);
70  break;
71  case EMIT_EDRAW:
72  case EMIT_TDRAW:
73  case EMIT_HDRAW:
74  ObjType = "edge";
75  ObjFlag = 1;
76  ObjId = AGID(obj->u.e);
77  break;
78  case EMIT_ELABEL:
79  case EMIT_TLABEL:
80  case EMIT_HLABEL:
81  ObjType = "edge";
82  ObjFlag = 0;
83  ObjId = AGID(obj->u.e);
84  break;
85  case EMIT_GDRAW:
86  ObjType = "graph";
87  ObjFlag = 1;
88  ObjId = AGID(obj->u.g);
89  break;
90  case EMIT_GLABEL:
91  ObjFlag = 0;
92  ObjType = "graph label";
93  ObjId = AGID(obj->u.g);
94  break;
95  case EMIT_CDRAW:
96  ObjType = "graph";
97  ObjFlag = 1;
98  ObjId = AGID(obj->u.sg);
99  break;
100  case EMIT_CLABEL:
101  ObjType = "graph";
102  ObjFlag = 0;
103  ObjId = AGID(obj->u.sg);
104  break;
105  default:
106  assert (0);
107  break;
108  }
109  gvprintf(job, " -tags {%d%s%p}", ObjFlag, ObjType, ObjId);
110 }
111 
112 static void tkgen_canvas(GVJ_t * job)
113 {
114  if (job->external_context)
115  gvputs(job, job->imagedata);
116  else
117  gvputs(job, "$c");
118 }
119 
120 static void tkgen_comment(GVJ_t * job, char *str)
121 {
122  gvputs(job, "# ");
123  gvputs(job, tkgen_string(str));
124  gvputs(job, "\n");
125 }
126 
127 static void tkgen_begin_job(GVJ_t * job)
128 {
129  gvputs(job, "# Generated by ");
130  gvputs(job, tkgen_string(job->common->info[0]));
131  gvputs(job, " version ");
132  gvputs(job, tkgen_string(job->common->info[1]));
133  gvputs(job, " (");
134  gvputs(job, tkgen_string(job->common->info[2]));
135  gvputs(job, ")\n");
136 }
137 
138 static int first_periphery;
139 
140 static void tkgen_begin_graph(GVJ_t * job)
141 {
142  obj_state_t *obj = job->obj;
143 
144  gvputs(job, "#");
145  if (agnameof(obj->u.g)[0]) {
146  gvputs(job, " Title: ");
147  gvputs(job, tkgen_string(agnameof(obj->u.g)));
148  }
149  gvprintf(job, " Pages: %d\n", job->pagesArraySize.x * job->pagesArraySize.y);
150 
151  first_periphery = 0;
152 }
153 
154 static void tkgen_begin_node(GVJ_t * job)
155 {
156  first_periphery = 1; /* FIXME - this is an ugly hack! */
157 }
158 
159 static void tkgen_begin_edge(GVJ_t * job)
160 {
161  first_periphery = -1; /* FIXME - this is an ugly ugly hack! Need this one for arrowheads. */
162 }
163 
164 static void tkgen_textspan(GVJ_t * job, pointf p, textspan_t * span)
165 {
166  obj_state_t *obj = job->obj;
167  const char *font;
168  PostscriptAlias *pA;
169  int size;
170 
171  if (obj->pen != PEN_NONE) {
172  /* determine font size */
173  /* round fontsize down, better too small than too big */
174  size = (int)(span->font->size * job->zoom);
175  /* don't even bother if fontsize < 1 point */
176  if (size) {
177  tkgen_canvas(job);
178  gvputs(job, " create text ");
179  p.y -= size * 0.55; /* cl correction */
180  gvprintpointf(job, p);
181  gvputs(job, " -text {");
182  gvputs(job, span->str);
183  gvputs(job, "}");
184  gvputs(job, " -fill ");
185  tkgen_print_color(job, obj->pencolor);
186  gvputs(job, " -font {");
187  /* tk doesn't like PostScript font names like "Times-Roman" */
188  /* so use family names */
189  pA = span->font->postscript_alias;
190  if (pA)
191  font = pA->family;
192  else
193  font = span->font->name;
194  gvputs(job, "\"");
195  gvputs(job, font);
196  gvputs(job, "\"");
197  /* use -ve fontsize to indicate pixels - see "man n font" */
198  gvprintf(job, " %d}", size);
199  switch (span->just) {
200  case 'l':
201  gvputs(job, " -anchor w");
202  break;
203  case 'r':
204  gvputs(job, " -anchor e");
205  break;
206  default:
207  case 'n':
208  break;
209  }
210  tkgen_print_tags(job);
211  gvputs(job, "\n");
212  }
213  }
214 }
215 
216 static void tkgen_ellipse(GVJ_t * job, pointf * A, int filled)
217 {
218  obj_state_t *obj = job->obj;
219  pointf r;
220 
221  if (obj->pen != PEN_NONE) {
222  /* A[] contains 2 points: the center and top right corner. */
223  r.x = A[1].x - A[0].x;
224  r.y = A[1].y - A[0].y;
225  A[0].x -= r.x;
226  A[0].y -= r.y;
227  tkgen_canvas(job);
228  gvputs(job, " create oval ");
229  gvprintpointflist(job, A, 2);
230  gvputs(job, " -fill ");
231  if (filled)
232  tkgen_print_color(job, obj->fillcolor);
233  else if (first_periphery)
234  /* tk ovals default to no fill, some fill
235  * is necessary else "canvas find overlapping" doesn't
236  * work as expected, use white instead */
237  gvputs(job, "white");
238  else
239  gvputs(job, "\"\"");
240  if (first_periphery == 1)
241  first_periphery = 0;
242  gvputs(job, " -width ");
243  gvprintdouble(job, obj->penwidth);
244  gvputs(job, " -outline ");
245  tkgen_print_color(job, obj->pencolor);
246  if (obj->pen == PEN_DASHED)
247  gvputs(job, " -dash 5");
248  if (obj->pen == PEN_DOTTED)
249  gvputs(job, " -dash 2");
250  tkgen_print_tags(job);
251  gvputs(job, "\n");
252  }
253 }
254 
255 static void
256 tkgen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start,
257  int arrow_at_end, int filled)
258 {
259  obj_state_t *obj = job->obj;
260 
261  if (obj->pen != PEN_NONE) {
262  tkgen_canvas(job);
263  gvputs(job, " create line ");
264  gvprintpointflist(job, A, n);
265  gvputs(job, " -fill ");
266  tkgen_print_color(job, obj->pencolor);
267  gvputs(job, " -width ");
268  gvprintdouble(job, obj->penwidth);
269  if (obj->pen == PEN_DASHED)
270  gvputs(job, " -dash 5");
271  if (obj->pen == PEN_DOTTED)
272  gvputs(job, " -dash 2");
273  gvputs(job, " -smooth bezier ");
274  tkgen_print_tags(job);
275  gvputs(job, "\n");
276  }
277 }
278 
279 static void tkgen_polygon(GVJ_t * job, pointf * A, int n, int filled)
280 {
281  obj_state_t *obj = job->obj;
282 
283  if (obj->pen != PEN_NONE) {
284  tkgen_canvas(job);
285  gvputs(job, " create polygon ");
286  gvprintpointflist(job, A, n);
287  gvputs(job, " -fill ");
288  if (filled)
289  tkgen_print_color(job, obj->fillcolor);
290  else if (first_periphery)
291  /* tk polygons default to black fill, some fill
292  * is necessary else "canvas find overlapping" doesn't
293  * work as expected, use white instead */
294  gvputs(job, "white");
295  else
296  gvputs(job, "\"\"");
297  if (first_periphery == 1)
298  first_periphery = 0;
299  gvputs(job, " -width ");
300  gvprintdouble(job, obj->penwidth);
301  gvputs(job, " -outline ");
302  tkgen_print_color(job, obj->pencolor);
303  if (obj->pen == PEN_DASHED)
304  gvputs(job, " -dash 5");
305  if (obj->pen == PEN_DOTTED)
306  gvputs(job, " -dash 2");
307  tkgen_print_tags(job);
308  gvputs(job, "\n");
309  }
310 }
311 
312 static void tkgen_polyline(GVJ_t * job, pointf * A, int n)
313 {
314  obj_state_t *obj = job->obj;
315 
316  if (obj->pen != PEN_NONE) {
317  tkgen_canvas(job);
318  gvputs(job, " create line ");
319  gvprintpointflist(job, A, n);
320  gvputs(job, " -fill ");
321  tkgen_print_color(job, obj->pencolor);
322  if (obj->pen == PEN_DASHED)
323  gvputs(job, " -dash 5");
324  if (obj->pen == PEN_DOTTED)
325  gvputs(job, " -dash 2");
326  tkgen_print_tags(job);
327  gvputs(job, "\n");
328  }
329 }
330 
332  tkgen_begin_job,
333  0, /* tkgen_end_job */
334  tkgen_begin_graph,
335  0, /* tkgen_end_graph */
336  0, /* tkgen_begin_layer */
337  0, /* tkgen_end_layer */
338  0, /* tkgen_begin_page */
339  0, /* tkgen_end_page */
340  0, /* tkgen_begin_cluster */
341  0, /* tkgen_end_cluster */
342  0, /* tkgen_begin_nodes */
343  0, /* tkgen_end_nodes */
344  0, /* tkgen_begin_edges */
345  0, /* tkgen_end_edges */
346  tkgen_begin_node,
347  0, /* tkgen_end_node */
348  tkgen_begin_edge,
349  0, /* tkgen_end_edge */
350  0, /* tkgen_begin_anchor */
351  0, /* tkgen_end_anchor */
352  0, /* tkgen_begin_label */
353  0, /* tkgen_end_label */
354  tkgen_textspan,
355  0, /* tkgen_resolve_color */
356  tkgen_ellipse,
357  tkgen_polygon,
358  tkgen_bezier,
359  tkgen_polyline,
360  tkgen_comment,
361  0, /* tkgen_library_shape */
362 };
363 
366  | GVRENDER_NO_WHITE_BG, /* flags */
367  4., /* default pad - graph units */
368  NULL, /* knowncolors */
369  0, /* sizeof knowncolors */
370  COLOR_STRING, /* color_type */
371 };
372 
374  0, /* flags */
375  {0.,0.}, /* default margin - points */
376  {0.,0.}, /* default page width, height - points */
377  {96.,96.}, /* default dpi */
378 };
379 
381  {FORMAT_TK, "tk", 1, &tkgen_engine, &render_features_tk},
382  {0, NULL, 0, NULL, NULL}
383 };
384 
386  {FORMAT_TK, "tk:tk", 1, NULL, &device_features_tk},
387  {0, NULL, 0, NULL, NULL}
388 };
union color_s::@10 u
char * imagedata
Definition: gvcjob.h:306
void gvprintpointflist(GVJ_t *job, pointf *p, int n)
Definition: gvdevice.c:585
#define AGID(obj)
Definition: cgraph.h:114
pen_type pen
Definition: gvcjob.h:206
double size
Definition: textspan.h:52
point pagesArraySize
Definition: gvcjob.h:313
#define assert(x)
Definition: cghdr.h:47
Definition: geom.h:28
Definition: color.h:34
gvcolor_t pencolor
Definition: gvcjob.h:203
Definition: gvcjob.h:271
char * name
Definition: textspan.h:49
int x
Definition: geom.h:26
obj_state_t * obj
Definition: gvcjob.h:278
#define GVRENDER_Y_GOES_DOWN
Definition: gvcjob.h:96
int gvputs(GVJ_t *job, const char *s)
Definition: gvdevice.c:270
char * str
Definition: textspan.h:59
color_type_t type
Definition: color.h:44
int
Definition: grammar.c:1264
gvplugin_installed_t gvdevice_tk_types[]
double y
Definition: geom.h:28
CGRAPH_API char * agnameof(void *)
Definition: id.c:143
gvplugin_installed_t gvrender_tk_types[]
char * string
Definition: color.h:41
GVCOMMON_t * common
Definition: gvcjob.h:276
char ** info
Definition: gvcommon.h:22
void gvprintpointf(GVJ_t *job, pointf p)
Definition: gvdevice.c:573
PostscriptAlias * postscript_alias
Definition: textspan.h:51
Definition: grammar.c:79
emit_state_t emit_state
Definition: gvcjob.h:201
graph_t * g
Definition: gvcjob.h:195
#define GVRENDER_NO_WHITE_BG
Definition: gvcjob.h:109
void gvprintdouble(GVJ_t *job, double num)
Definition: gvdevice.c:557
format_type
gvrender_engine_t tkgen_engine
#define NULL
Definition: logic.h:39
graph_t * sg
Definition: gvcjob.h:196
double x
Definition: geom.h:28
boolean external_context
Definition: gvcjob.h:305
char just
Definition: textspan.h:65
gvrender_features_t render_features_tk
union obj_state_s::@23 u
gvdevice_features_t device_features_tk
edge_t * e
Definition: gvcjob.h:198
agxbuf * str
Definition: htmlparse.c:85
gvcolor_t fillcolor
Definition: gvcjob.h:203
node_t * n
Definition: gvcjob.h:197
double penwidth
Definition: gvcjob.h:208
int y
Definition: geom.h:26
unsigned char rgba[4]
Definition: color.h:38
double zoom
Definition: gvcjob.h:327
char * family
Definition: textspan.h:34
void gvprintf(GVJ_t *job, const char *format,...)
Definition: gvdevice.c:389
textfont_t * font
Definition: textspan.h:60