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