Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
gvrender_core_map.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
13#include <stdlib.h>
14
15#include <common/types.h>
16#include <common/utils.h>
17#include <gvc/gvplugin_render.h>
18#include <gvc/gvplugin_device.h>
19#include <gvc/gvio.h>
20#include <util/unreachable.h>
21
23
24// wrapper around `xml_escape` to set flags for URL escaping
25static void xml_url_puts(GVJ_t *job, const char *s) {
26 const xml_flags_t flags = {0};
27 (void)xml_escape(s, flags, (int(*)(void*, const char*))gvputs, job);
28}
29
30static void map_output_shape(GVJ_t *job, map_shape_t map_shape, pointf *AF, size_t nump,
31 char* url, char *tooltip, char *target, char *id)
32{
33 if (!AF || !nump)
34 return;
35
36 if (job->render.id == FORMAT_IMAP && url && url[0]) {
37 switch (map_shape) {
38 case MAP_RECTANGLE:
39 /* Y_GOES_DOWN so need UL to LR */
40 gvprintf(job, "rect %s %.0f,%.0f %.0f,%.0f\n", url, AF[0].x,
41 AF[1].y, AF[1].x, AF[0].y);
42 break;
43 case MAP_CIRCLE:
44 gvprintf(job, "circle %s %.0f,%.0f,%.0f\n", url, AF[0].x, AF[0].y,
45 AF[1].x - AF[0].x);
46 break;
47 case MAP_POLYGON:
48 gvprintf(job, "poly %s", url);
49 for (size_t i = 0; i < nump; i++) {
50 gvprintf(job, " %.0f,%.0f", AF[i].x, AF[i].y);
51 }
52 gvputs(job, "\n");
53 break;
54 default:
56 }
57
58 } else if (job->render.id == FORMAT_ISMAP && url && url[0]) {
59 switch (map_shape) {
60 case MAP_RECTANGLE:
61 /* Y_GOES_DOWN so need UL to LR */
62 gvprintf(job, "rectangle (%.0f,%.0f) (%.0f,%.0f) %s %s\n",
63 AF[0].x, AF[1].y, AF[1].x, AF[0].y, url, tooltip);
64 break;
65 default:
67 }
68
69 } else if (job->render.id == FORMAT_CMAP || job->render.id == FORMAT_CMAPX) {
70 switch (map_shape) {
71 case MAP_CIRCLE:
72 gvputs(job, "<area shape=\"circle\"");
73 break;
74 case MAP_RECTANGLE:
75 gvputs(job, "<area shape=\"rect\"");
76 break;
77 case MAP_POLYGON:
78 gvputs(job, "<area shape=\"poly\"");
79 break;
80 default:
82 }
83 if (id && id[0]) {
84 gvputs(job, " id=\"");
85 xml_url_puts(job, id);
86 gvputs(job, "\"");
87 }
88 if (url && url[0]) {
89 gvputs(job, " href=\"");
90 xml_url_puts(job, url);
91 gvputs(job, "\"");
92 }
93 if (target && target[0]) {
94 gvputs(job, " target=\"");
95 gvputs_xml(job, target);
96 gvputs(job, "\"");
97 }
98 if (tooltip && tooltip[0]) {
99 gvputs(job, " title=\"");
100 gvputs_xml(job, tooltip);
101 gvputs(job, "\"");
102 }
103 // FIXME:
104 // - https://gitlab.com/graphviz/graphviz/-/issues/265
105 // - https://gitlab.com/graphviz/graphviz/-/issues/2220
106 gvputs(job, " alt=\"\"");
107
108 gvputs(job, " coords=\"");
109 switch (map_shape) {
110 case MAP_CIRCLE:
111 gvprintf(job, "%.0f,%.0f,%.0f", AF[0].x, AF[0].y,
112 AF[1].x - AF[0].x);
113 break;
114 case MAP_RECTANGLE:
115 /* Y_GOES_DOWN so need UL to LR */
116 gvprintf(job, "%.0f,%.0f,%.0f,%.0f", AF[0].x, AF[1].y, AF[1].x,
117 AF[0].y);
118 break;
119 case MAP_POLYGON:
120 gvprintf(job, "%.0f,%.0f", AF[0].x, AF[0].y);
121 for (size_t i = 1; i < nump; i++) {
122 gvprintf(job, ",%.0f,%.0f", AF[i].x, AF[i].y);
123 }
124 break;
125 default:
126 break;
127 }
128 if (job->render.id == FORMAT_CMAPX)
129 gvputs(job, "\"/>\n");
130 else
131 gvputs(job, "\">\n");
132 }
133}
134
135static void map_begin_page(GVJ_t * job)
136{
137 obj_state_t *obj = job->obj;
138
139 switch (job->render.id) {
140 case FORMAT_IMAP:
141 gvputs(job, "base referer\n");
142 if (obj->url && obj->url[0]) {
143 gvputs(job, "default ");
144 gvputs_xml(job, obj->url);
145 gvputs(job, "\n");
146 }
147 break;
148 case FORMAT_ISMAP:
149 if (obj->url && obj->url[0]) {
150 gvputs(job, "default ");
151 gvputs_xml(job, obj->url);
152 gvputs(job, " ");
153 gvputs_xml(job, agnameof(obj->u.g));
154 gvputs(job, "\n");
155 }
156 break;
157 case FORMAT_CMAPX:
158 gvputs(job, "<map id=\"");
159 gvputs_xml(job, agnameof(obj->u.g));
160 gvputs(job, "\" name=\"");
161 gvputs_xml(job, agnameof(obj->u.g));
162 gvputs(job, "\">\n");
163 break;
164 default:
165 break;
166 }
167}
168
169static void map_end_page(GVJ_t * job)
170{
171 obj_state_t *obj = job->obj;
172
173 switch (job->render.id) {
174 case FORMAT_CMAP:
176 obj->url_map_p,obj->url_map_n,
177 obj->url, obj->tooltip, obj->target, obj->id);
178 break;
179 case FORMAT_CMAPX:
181 obj->url_map_p,obj->url_map_n,
182 obj->url, obj->tooltip, obj->target, obj->id);
183 gvputs(job, "</map>\n");
184 break;
185 default:
186 break;
187 }
188}
189
190static void map_begin_anchor(GVJ_t * job, char *url, char *tooltip, char *target, char *id)
191{
192 obj_state_t *obj = job->obj;
193
195 obj->url_map_p, obj->url_map_n,
196 url, tooltip, target, id);
197}
198
200 0, /* map_begin_job */
201 0, /* map_end_job */
202 0, /* map_begin_graph */
203 0, /* map_end_graph */
204 0, /* map_begin_layer */
205 0, /* map_end_layer */
208 0, /* map_begin_cluster */
209 0, /* map_end_cluster */
210 0, /* map_begin_nodes */
211 0, /* map_end_nodes */
212 0, /* map_begin_edges */
213 0, /* map_end_edges */
214 0, /* map_begin_node */
215 0, /* map_end_node */
216 0, /* map_begin_edge */
217 0, /* map_end_edge */
219 0, /* map_end_anchor */
220 0, /* map_begin_label */
221 0, /* map_end_label */
222 0, /* map_textpara */
223 0, /* map_resolve_color */
224 0, /* map_ellipse */
225 0, /* map_polygon */
226 0, /* map_bezier */
227 0, /* map_polyline */
228 0, /* map_comment */
229 0, /* map_library_shape */
230};
231
239 | GVRENDER_DOES_MAP_RECTANGLE, /* flags */
240 4., /* default pad - graph units */
241 NULL, /* knowncolors */
242 0, /* sizeof knowncolors */
243 0, /* color_type */
244};
245
248 | GVRENDER_DOES_MAP_POLYGON, /* flags */
249 {0.,0.}, /* default margin - points */
250 {0.,0.}, /* default page width, height - points */
251 {96.,96.}, /* default dpi */
252};
253
255 0, /* flags */
256 {0.,0.}, /* default margin - points */
257 {0.,0.}, /* default page width, height - points */
258 {96.,96.}, /* default dpi */
259};
260
265
267 {FORMAT_ISMAP, "ismap:map", 1, NULL, &device_features_map_nopoly},
268 {FORMAT_CMAP, "cmap:map", 1, NULL, &device_features_map},
269 {FORMAT_IMAP, "imap:map", 1, NULL, &device_features_map},
270 {FORMAT_CMAPX, "cmapx:map", 1, NULL, &device_features_map},
271 {FORMAT_IMAP, "imap_np:map", 1, NULL, &device_features_map_nopoly},
272 {FORMAT_CMAPX, "cmapx_np:map", 1, NULL, &device_features_map_nopoly},
273 {0, NULL, 0, NULL, NULL}
274};
static int flags
Definition gc.c:61
node NULL
Definition grammar.y:163
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
#define EMIT_CLUSTERS_LAST
Definition gvcjob.h:84
#define GVRENDER_DOES_TOOLTIPS
Definition gvcjob.h:103
#define GVRENDER_DOES_LABELS
Definition gvcjob.h:96
map_shape_t
Definition gvcjob.h:166
@ MAP_CIRCLE
Definition gvcjob.h:166
@ MAP_POLYGON
Definition gvcjob.h:166
@ MAP_RECTANGLE
Definition gvcjob.h:166
#define GVRENDER_DOES_MAPS
Definition gvcjob.h:97
#define GVRENDER_DOES_TARGETS
Definition gvcjob.h:104
#define GVRENDER_Y_GOES_DOWN
Definition gvcjob.h:94
#define GVRENDER_DOES_MAP_POLYGON
Definition gvcjob.h:100
#define GVRENDER_DOES_MAP_RECTANGLE
Definition gvcjob.h:98
#define GVRENDER_DOES_MAP_CIRCLE
Definition gvcjob.h:99
int gvputs_xml(GVJ_t *job, const char *s)
Definition gvdevice.c:274
int gvputs(GVJ_t *job, const char *s)
Definition gvdevice.c:264
void gvprintf(GVJ_t *job, const char *format,...)
Definition gvdevice.c:395
static void map_begin_anchor(GVJ_t *job, char *url, char *tooltip, char *target, char *id)
static gvdevice_features_t device_features_map_nopoly
gvplugin_installed_t gvrender_map_types[]
static gvrender_engine_t map_engine
static void map_output_shape(GVJ_t *job, map_shape_t map_shape, pointf *AF, size_t nump, char *url, char *tooltip, char *target, char *id)
static void map_begin_page(GVJ_t *job)
static gvdevice_features_t device_features_map
gvplugin_installed_t gvdevice_map_types[]
static void map_end_page(GVJ_t *job)
format_type
@ FORMAT_IMAP
@ FORMAT_CMAP
@ FORMAT_ISMAP
@ FORMAT_CMAPX
static gvrender_features_t render_features_map
static void xml_url_puts(GVJ_t *job, const char *s)
obj_state_t * obj
Definition gvcjob.h:269
gvplugin_active_render_t render
Definition gvcjob.h:285
ingroup plugin_api
Definition gvplugin.h:35
graph_t * g
Definition gvcjob.h:186
pointf * url_map_p
Definition gvcjob.h:240
char * tooltip
Definition gvcjob.h:216
union obj_state_s::@89 u
char * url
Definition gvcjob.h:210
char * target
Definition gvcjob.h:221
map_shape_t url_map_shape
Definition gvcjob.h:238
char * id
Definition gvcjob.h:211
size_t url_map_n
Definition gvcjob.h:239
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t
Definition grammar.c:93
#define UNREACHABLE()
Definition unreachable.h:30
int xml_escape(const char *s, xml_flags_t flags, int(*cb)(void *state, const char *s), void *state)
Definition xml.c:179