Graphviz 12.0.1~dev.20240715.2254
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 <cgraph/unreachable.h>
16#include <common/types.h>
17#include <common/utils.h>
18#include <gvc/gvplugin_render.h>
19#include <gvc/gvplugin_device.h>
20#include <gvc/gvio.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 /*
104 * alt text is intended for the visually impaired, but such
105 * folk are not likely to be clicking around on a graph anyway.
106 * IE on the PC platform (but not on Macs) incorrectly
107 * uses (non-empty) alt strings instead of title strings for tooltips.
108 * To make tooltips work and avoid this IE issue,
109 * while still satisfying usability guidelines
110 * that require that there is always an alt string,
111 * we generate just an empty alt string.
112 */
113 gvputs(job, " alt=\"\"");
114
115 gvputs(job, " coords=\"");
116 switch (map_shape) {
117 case MAP_CIRCLE:
118 gvprintf(job, "%.0f,%.0f,%.0f", AF[0].x, AF[0].y,
119 AF[1].x - AF[0].x);
120 break;
121 case MAP_RECTANGLE:
122 /* Y_GOES_DOWN so need UL to LR */
123 gvprintf(job, "%.0f,%.0f,%.0f,%.0f", AF[0].x, AF[1].y, AF[1].x,
124 AF[0].y);
125 break;
126 case MAP_POLYGON:
127 gvprintf(job, "%.0f,%.0f", AF[0].x, AF[0].y);
128 for (size_t i = 1; i < nump; i++) {
129 gvprintf(job, ",%.0f,%.0f", AF[i].x, AF[i].y);
130 }
131 break;
132 default:
133 break;
134 }
135 if (job->render.id == FORMAT_CMAPX)
136 gvputs(job, "\"/>\n");
137 else
138 gvputs(job, "\">\n");
139 }
140}
141
142static void map_begin_page(GVJ_t * job)
143{
144 obj_state_t *obj = job->obj;
145
146 switch (job->render.id) {
147 case FORMAT_IMAP:
148 gvputs(job, "base referer\n");
149 if (obj->url && obj->url[0]) {
150 gvputs(job, "default ");
151 gvputs_xml(job, obj->url);
152 gvputs(job, "\n");
153 }
154 break;
155 case FORMAT_ISMAP:
156 if (obj->url && obj->url[0]) {
157 gvputs(job, "default ");
158 gvputs_xml(job, obj->url);
159 gvputs(job, " ");
160 gvputs_xml(job, agnameof(obj->u.g));
161 gvputs(job, "\n");
162 }
163 break;
164 case FORMAT_CMAPX:
165 gvputs(job, "<map id=\"");
166 gvputs_xml(job, agnameof(obj->u.g));
167 gvputs(job, "\" name=\"");
168 gvputs_xml(job, agnameof(obj->u.g));
169 gvputs(job, "\">\n");
170 break;
171 default:
172 break;
173 }
174}
175
176static void map_end_page(GVJ_t * job)
177{
178 obj_state_t *obj = job->obj;
179
180 switch (job->render.id) {
181 case FORMAT_CMAP:
183 obj->url_map_p,obj->url_map_n,
184 obj->url, obj->tooltip, obj->target, obj->id);
185 break;
186 case FORMAT_CMAPX:
188 obj->url_map_p,obj->url_map_n,
189 obj->url, obj->tooltip, obj->target, obj->id);
190 gvputs(job, "</map>\n");
191 break;
192 default:
193 break;
194 }
195}
196
197static void map_begin_anchor(GVJ_t * job, char *url, char *tooltip, char *target, char *id)
198{
199 obj_state_t *obj = job->obj;
200
202 obj->url_map_p, obj->url_map_n,
203 url, tooltip, target, id);
204}
205
207 0, /* map_begin_job */
208 0, /* map_end_job */
209 0, /* map_begin_graph */
210 0, /* map_end_graph */
211 0, /* map_begin_layer */
212 0, /* map_end_layer */
215 0, /* map_begin_cluster */
216 0, /* map_end_cluster */
217 0, /* map_begin_nodes */
218 0, /* map_end_nodes */
219 0, /* map_begin_edges */
220 0, /* map_end_edges */
221 0, /* map_begin_node */
222 0, /* map_end_node */
223 0, /* map_begin_edge */
224 0, /* map_end_edge */
226 0, /* map_end_anchor */
227 0, /* map_begin_label */
228 0, /* map_end_label */
229 0, /* map_textpara */
230 0, /* map_resolve_color */
231 0, /* map_ellipse */
232 0, /* map_polygon */
233 0, /* map_bezier */
234 0, /* map_polyline */
235 0, /* map_comment */
236 0, /* map_library_shape */
237};
238
246 | GVRENDER_DOES_MAP_RECTANGLE, /* flags */
247 4., /* default pad - graph units */
248 NULL, /* knowncolors */
249 0, /* sizeof knowncolors */
250 0, /* color_type */
251};
252
255 | GVRENDER_DOES_MAP_POLYGON, /* flags */
256 {0.,0.}, /* default margin - points */
257 {0.,0.}, /* default page width, height - points */
258 {96.,96.}, /* default dpi */
259};
260
262 0, /* flags */
263 {0.,0.}, /* default margin - points */
264 {0.,0.}, /* default page width, height - points */
265 {96.,96.}, /* default dpi */
266};
267
272
274 {FORMAT_ISMAP, "ismap:map", 1, NULL, &device_features_map_nopoly},
275 {FORMAT_CMAP, "cmap:map", 1, NULL, &device_features_map},
276 {FORMAT_IMAP, "imap:map", 1, NULL, &device_features_map},
277 {FORMAT_CMAPX, "cmapx:map", 1, NULL, &device_features_map},
278 {FORMAT_IMAP, "imap_np:map", 1, NULL, &device_features_map_nopoly},
279 {FORMAT_CMAPX, "cmapx_np:map", 1, NULL, &device_features_map_nopoly},
280 {0, NULL, 0, NULL, NULL}
281};
static int flags
Definition gc.c:61
node NULL
Definition grammar.y:149
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:273
int gvputs(GVJ_t *job, const char *s)
Definition gvdevice.c:263
void gvprintf(GVJ_t *job, const char *format,...)
Definition gvdevice.c:394
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
union obj_state_s::@92 u
graph_t * g
Definition gvcjob.h:186
pointf * url_map_p
Definition gvcjob.h:240
char * tooltip
Definition gvcjob.h:216
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