|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include <stdlib.h> 00019 00020 #include "gvplugin_render.h" 00021 #include "gvplugin_device.h" 00022 #include "gvio.h" 00023 00024 extern char *xml_string(char *str); 00025 extern char *xml_url_string(char *str); 00026 00027 typedef enum { FORMAT_IMAP, FORMAT_ISMAP, FORMAT_CMAP, FORMAT_CMAPX, } format_type; 00028 00029 static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, int nump, 00030 char* url, char *tooltip, char *target, char *id) 00031 { 00032 int i; 00033 00034 static point *A; 00035 static int size_A; 00036 00037 if (!AF || !nump) 00038 return; 00039 00040 if (size_A < nump) { 00041 size_A = nump + 10; 00042 A = realloc(A, size_A * sizeof(point)); 00043 } 00044 for (i = 0; i < nump; i++) 00045 PF2P(AF[i], A[i]); 00046 00047 if (job->render.id == FORMAT_IMAP && url && url[0]) { 00048 switch (map_shape) { 00049 case MAP_RECTANGLE: 00050 /* Y_GOES_DOWN so need UL to LR */ 00051 gvprintf(job, "rect %s %d,%d %d,%d\n", url, 00052 A[0].x, A[1].y, A[1].x, A[0].y); 00053 break; 00054 case MAP_CIRCLE: 00055 gvprintf(job, "circle %s %d,%d,%d\n", url, 00056 A[0].x, A[0].y, A[1].x-A[0].x); 00057 break; 00058 case MAP_POLYGON: 00059 gvprintf(job, "poly %s", url); 00060 for (i = 0; i < nump; i++) 00061 gvprintf(job, " %d,%d", A[i].x, A[i].y); 00062 gvputs(job, "\n"); 00063 break; 00064 default: 00065 assert(0); 00066 break; 00067 } 00068 00069 } else if (job->render.id == FORMAT_ISMAP && url && url[0]) { 00070 switch (map_shape) { 00071 case MAP_RECTANGLE: 00072 /* Y_GOES_DOWN so need UL to LR */ 00073 gvprintf(job, "rectangle (%d,%d) (%d,%d) %s %s\n", 00074 A[0].x, A[1].y, A[1].x, A[0].y, url, tooltip); 00075 break; 00076 default: 00077 assert(0); 00078 break; 00079 } 00080 00081 } else if (job->render.id == FORMAT_CMAP || job->render.id == FORMAT_CMAPX) { 00082 switch (map_shape) { 00083 case MAP_CIRCLE: 00084 gvputs(job, "<area shape=\"circle\""); 00085 break; 00086 case MAP_RECTANGLE: 00087 gvputs(job, "<area shape=\"rect\""); 00088 break; 00089 case MAP_POLYGON: 00090 gvputs(job, "<area shape=\"poly\""); 00091 break; 00092 default: 00093 assert(0); 00094 break; 00095 } 00096 if (id && id[0]) { 00097 gvputs(job, " id=\""); 00098 gvputs(job, xml_url_string(id)); 00099 gvputs(job, "\""); 00100 } 00101 if (url && url[0]) { 00102 gvputs(job, " href=\""); 00103 gvputs(job, xml_url_string(url)); 00104 gvputs(job, "\""); 00105 } 00106 if (target && target[0]) { 00107 gvputs(job, " target=\""); 00108 gvputs(job, xml_string(target)); 00109 gvputs(job, "\""); 00110 } 00111 if (tooltip && tooltip[0]) { 00112 gvputs(job, " title=\""); 00113 gvputs(job, xml_string(tooltip)); 00114 gvputs(job, "\""); 00115 } 00116 /* 00117 * alt text is intended for the visually impaired, but such 00118 * folk are not likely to be clicking around on a graph anyway. 00119 * IE on the PC platform (but not on Macs) incorrectly 00120 * uses (non-empty) alt strings instead of title strings for tooltips. 00121 * To make tooltips work and avoid this IE issue, 00122 * while still satisfying usability guidelines 00123 * that require that there is always an alt string, 00124 * we generate just an empty alt string. 00125 */ 00126 gvputs(job, " alt=\"\""); 00127 00128 gvputs(job, " coords=\""); 00129 switch (map_shape) { 00130 case MAP_CIRCLE: 00131 gvprintf(job, "%d,%d,%d", A[0].x, A[0].y, A[1].x-A[0].x); 00132 break; 00133 case MAP_RECTANGLE: 00134 /* Y_GOES_DOWN so need UL to LR */ 00135 gvprintf(job, "%d,%d,%d,%d", A[0].x, A[1].y, A[1].x, A[0].y); 00136 break; 00137 case MAP_POLYGON: 00138 gvprintf(job, "%d,%d", A[0].x, A[0].y); 00139 for (i = 1; i < nump; i++) 00140 gvprintf(job, ",%d,%d", A[i].x, A[i].y); 00141 break; 00142 default: 00143 break; 00144 } 00145 if (job->render.id == FORMAT_CMAPX) 00146 gvputs(job, "\"/>\n"); 00147 else 00148 gvputs(job, "\">\n"); 00149 } 00150 } 00151 00152 static void map_begin_page(GVJ_t * job) 00153 { 00154 obj_state_t *obj = job->obj; 00155 char *s; 00156 00157 switch (job->render.id) { 00158 case FORMAT_IMAP: 00159 gvputs(job, "base referer\n"); 00160 if (obj->url && obj->url[0]) { 00161 gvputs(job, "default "); 00162 gvputs(job, xml_string(obj->url)); 00163 gvputs(job, "\n"); 00164 } 00165 break; 00166 case FORMAT_ISMAP: 00167 if (obj->url && obj->url[0]) { 00168 gvputs(job, "default "); 00169 gvputs(job, xml_string(obj->url)); 00170 gvputs(job, " "); 00171 gvputs(job, xml_string(agnameof(obj->u.g))); 00172 gvputs(job, "\n"); 00173 } 00174 break; 00175 case FORMAT_CMAPX: 00176 s = xml_string(agnameof(obj->u.g)); 00177 gvputs(job, "<map id=\""); 00178 gvputs(job, s); 00179 gvputs(job, "\" name=\""); 00180 gvputs(job, s); 00181 gvputs(job, "\">\n"); 00182 break; 00183 default: 00184 break; 00185 } 00186 } 00187 00188 static void map_end_page(GVJ_t * job) 00189 { 00190 obj_state_t *obj = job->obj; 00191 00192 switch (job->render.id) { 00193 case FORMAT_CMAP: 00194 map_output_shape(job, obj->url_map_shape, 00195 obj->url_map_p,obj->url_map_n, 00196 obj->url, obj->tooltip, obj->target, obj->id); 00197 break; 00198 case FORMAT_CMAPX: 00199 map_output_shape(job, obj->url_map_shape, 00200 obj->url_map_p,obj->url_map_n, 00201 obj->url, obj->tooltip, obj->target, obj->id); 00202 gvputs(job, "</map>\n"); 00203 break; 00204 default: 00205 break; 00206 } 00207 } 00208 00209 #if 0 00210 static void map_begin_cluster(GVJ_t * job) 00211 { 00212 obj_state_t *obj = job->obj; 00213 00214 gvprintf(job, "%% %s\n", obj->u.sg->name); 00215 00216 map_output_shape(job, obj->url_map_shape, obj->url_map_p, obj->url_map_n, 00217 obj->url, obj->tooltip, obj->target); 00218 } 00219 00220 static void map_begin_node(GVJ_t * job) 00221 { 00222 obj_state_t *obj = job->obj; 00223 00224 map_output_shape(job, obj->url_map_shape, obj->url_map_p,obj->url_map_n, 00225 obj->url, obj->tooltip, obj->target); 00226 } 00227 00228 static void 00229 map_begin_edge(GVJ_t * job) 00230 { 00231 obj_state_t *obj = job->obj; 00232 int i, j = 0; 00233 00234 map_output_shape(job, obj->url_map_shape, obj->url_map_p, obj->url_map_n, 00235 obj->url, obj->tooltip, obj->target); 00236 map_output_shape(job, MAP_RECTANGLE, obj->tailurl_map_p, 2, 00237 obj->tailurl, obj->tailtooltip, obj->tailtarget); 00238 map_output_shape(job, MAP_RECTANGLE, obj->headurl_map_p, 2, 00239 obj->headurl, obj->headtooltip, obj->headtarget); 00240 map_output_shape(job, MAP_RECTANGLE, obj->tailendurl_map_p,2, 00241 obj->url, obj->tooltip, obj->target); 00242 map_output_shape(job, MAP_RECTANGLE, obj->headendurl_map_p, 2, 00243 obj->url, obj->tooltip, obj->target); 00244 for (i = 0; i < obj->url_bsplinemap_poly_n; i++) { 00245 map_output_shape(job, MAP_POLYGON, 00246 obj->url_bsplinemap_p+j, obj->url_bsplinemap_n[i], 00247 obj->url, obj->tooltip, obj->target); 00248 j += obj->url_bsplinemap_n[i]; 00249 } 00250 } 00251 #endif 00252 00253 static void map_begin_anchor(GVJ_t * job, char *url, char *tooltip, char *target, char *id) 00254 { 00255 obj_state_t *obj = job->obj; 00256 00257 map_output_shape(job, obj->url_map_shape, 00258 obj->url_map_p, obj->url_map_n, 00259 url, tooltip, target, id); 00260 } 00261 00262 static gvrender_engine_t map_engine = { 00263 0, /* map_begin_job */ 00264 0, /* map_end_job */ 00265 0, /* map_begin_graph */ 00266 0, /* map_end_graph */ 00267 0, /* map_begin_layer */ 00268 0, /* map_end_layer */ 00269 map_begin_page, 00270 map_end_page, 00271 0, /* map_begin_cluster */ 00272 0, /* map_end_cluster */ 00273 0, /* map_begin_nodes */ 00274 0, /* map_end_nodes */ 00275 0, /* map_begin_edges */ 00276 0, /* map_end_edges */ 00277 0, /* map_begin_node */ 00278 0, /* map_end_node */ 00279 0, /* map_begin_edge */ 00280 0, /* map_end_edge */ 00281 map_begin_anchor, 00282 0, /* map_end_anchor */ 00283 0, /* map_begin_label */ 00284 0, /* map_end_label */ 00285 0, /* map_textpara */ 00286 0, /* map_resolve_color */ 00287 0, /* map_ellipse */ 00288 0, /* map_polygon */ 00289 0, /* map_bezier */ 00290 0, /* map_polyline */ 00291 0, /* map_comment */ 00292 0, /* map_library_shape */ 00293 }; 00294 00295 static gvrender_features_t render_features_map = { 00296 EMIT_CLUSTERS_LAST 00297 | GVRENDER_Y_GOES_DOWN 00298 | GVRENDER_DOES_MAPS 00299 | GVRENDER_DOES_LABELS 00300 | GVRENDER_DOES_TOOLTIPS 00301 | GVRENDER_DOES_TARGETS 00302 | GVRENDER_DOES_MAP_RECTANGLE, /* flags */ 00303 4., /* default pad - graph units */ 00304 NULL, /* knowncolors */ 00305 0, /* sizeof knowncolors */ 00306 0, /* color_type */ 00307 }; 00308 00309 static gvdevice_features_t device_features_map = { 00310 GVRENDER_DOES_MAP_CIRCLE 00311 | GVRENDER_DOES_MAP_POLYGON, /* flags */ 00312 {0.,0.}, /* default margin - points */ 00313 {0.,0.}, /* default page width, height - points */ 00314 {96.,96.}, /* default dpi */ 00315 }; 00316 00317 static gvdevice_features_t device_features_map_nopoly = { 00318 0, /* flags */ 00319 {0.,0.}, /* default margin - points */ 00320 {0.,0.}, /* default page width, height - points */ 00321 {96.,96.}, /* default dpi */ 00322 }; 00323 00324 gvplugin_installed_t gvrender_map_types[] = { 00325 {FORMAT_ISMAP, "map", 1, &map_engine, &render_features_map}, 00326 {0, NULL, 0, NULL, NULL} 00327 }; 00328 00329 gvplugin_installed_t gvdevice_map_types[] = { 00330 {FORMAT_ISMAP, "ismap:map", 1, NULL, &device_features_map_nopoly}, 00331 {FORMAT_CMAP, "cmap:map", 1, NULL, &device_features_map}, 00332 {FORMAT_IMAP, "imap:map", 1, NULL, &device_features_map}, 00333 {FORMAT_CMAPX, "cmapx:map", 1, NULL, &device_features_map}, 00334 {FORMAT_IMAP, "imap_np:map", 1, NULL, &device_features_map_nopoly}, 00335 {FORMAT_CMAPX, "cmapx_np:map", 1, NULL, &device_features_map_nopoly}, 00336 {0, NULL, 0, NULL, NULL} 00337 };
1.7.5