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