|
Graphviz
2.31.20130522.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 <stdarg.h> 00019 #include <stdlib.h> 00020 #include <string.h> 00021 00022 #include "macros.h" 00023 #include "const.h" 00024 00025 #include "gvplugin_render.h" 00026 #include "gvplugin_device.h" 00027 #include "gvio.h" 00028 #include "gvcint.h" 00029 00030 typedef enum { FORMAT_TK, } format_type; 00031 00032 static char *tkgen_string(char *s) 00033 { 00034 return s; 00035 } 00036 00037 static void tkgen_print_color(GVJ_t * job, gvcolor_t color) 00038 { 00039 switch (color.type) { 00040 case COLOR_STRING: 00041 gvputs(job, color.u.string); 00042 break; 00043 case RGBA_BYTE: 00044 if (color.u.rgba[3] == 0) /* transparent */ 00045 gvputs(job, "\"\""); 00046 else 00047 gvprintf(job, "#%02x%02x%02x", 00048 color.u.rgba[0], color.u.rgba[1], color.u.rgba[2]); 00049 break; 00050 default: 00051 assert(0); /* internal error */ 00052 } 00053 } 00054 00055 static void tkgen_print_tags(GVJ_t *job) 00056 { 00057 char *ObjType, *ObjPart; 00058 unsigned int ObjId; 00059 obj_state_t *obj = job->obj; 00060 int ObjFlag; 00061 #ifndef WITH_CGRAPH 00062 int ObjHandle; 00063 #endif 00064 00065 switch (obj->emit_state) { 00066 case EMIT_NDRAW: 00067 ObjType = "node"; 00068 ObjPart = "shape"; 00069 ObjFlag = 1; 00070 ObjId = AGSEQ(obj->u.n); 00071 #ifndef WITH_CGRAPH 00072 ObjHandle = obj->u.n->handle; 00073 #endif 00074 break; 00075 case EMIT_NLABEL: 00076 ObjType = "node"; 00077 ObjPart = "label"; 00078 ObjFlag = 0; 00079 ObjId = AGSEQ(obj->u.n); 00080 #ifndef WITH_CGRAPH 00081 ObjHandle = obj->u.n->handle; 00082 #endif 00083 break; 00084 case EMIT_EDRAW: 00085 case EMIT_TDRAW: 00086 case EMIT_HDRAW: 00087 ObjType = "edge"; 00088 ObjPart = "shape"; 00089 ObjFlag = 1; 00090 ObjId = AGSEQ(obj->u.e); 00091 #ifndef WITH_CGRAPH 00092 ObjHandle = obj->u.e->handle; 00093 #endif 00094 break; 00095 case EMIT_ELABEL: 00096 case EMIT_TLABEL: 00097 case EMIT_HLABEL: 00098 ObjType = "edge"; 00099 ObjPart = "label"; 00100 ObjFlag = 0; 00101 ObjId = AGSEQ(obj->u.e); 00102 #ifndef WITH_CGRAPH 00103 ObjHandle = obj->u.e->handle; 00104 #endif 00105 break; 00106 case EMIT_GDRAW: 00107 ObjType = "graph"; 00108 ObjPart = "shape"; 00109 ObjFlag = 1; 00110 ObjId = -1; /* hack! */ 00111 #ifndef WITH_CGRAPH 00112 ObjHandle = obj->u.g->handle; 00113 #endif 00114 break; 00115 case EMIT_GLABEL: 00116 ObjType = "graph"; 00117 ObjPart = "label"; 00118 ObjFlag = 0; 00119 ObjType = "graph label"; 00120 ObjId = -1; /* hack! */ 00121 #ifndef WITH_CGRAPH 00122 ObjHandle = obj->u.g->handle; 00123 #endif 00124 break; 00125 case EMIT_CDRAW: 00126 ObjType = "graph"; 00127 ObjPart = "shape"; 00128 ObjFlag = 1; 00129 #ifndef WITH_CGRAPH 00130 ObjId = obj->u.sg->meta_node->id; 00131 ObjHandle = obj->u.sg->handle; 00132 #else 00133 ObjId = AGSEQ(obj->u.sg); 00134 #endif 00135 break; 00136 case EMIT_CLABEL: 00137 ObjType = "graph"; 00138 ObjPart = "label"; 00139 ObjFlag = 0; 00140 #ifndef WITH_CGRAPH 00141 ObjId = obj->u.sg->meta_node->id; 00142 ObjHandle = obj->u.sg->handle; 00143 #else 00144 ObjId = AGSEQ(obj->u.sg); 00145 #endif 00146 break; 00147 default: 00148 assert (0); 00149 break; 00150 } 00151 #ifndef WITH_CGRAPH 00152 gvprintf(job, " -tags {%d%s%d}", ObjFlag, ObjType, ObjHandle); 00153 #else 00154 gvprintf(job, " -tags {%d%s%d}", ObjFlag, ObjType, ObjId); 00155 #endif 00156 } 00157 00158 static void tkgen_canvas(GVJ_t * job) 00159 { 00160 if (job->external_context) 00161 gvputs(job, job->imagedata); 00162 else 00163 gvputs(job, "$c"); 00164 } 00165 00166 static void tkgen_comment(GVJ_t * job, char *str) 00167 { 00168 gvputs(job, "# "); 00169 gvputs(job, tkgen_string(str)); 00170 gvputs(job, "\n"); 00171 } 00172 00173 static void tkgen_begin_job(GVJ_t * job) 00174 { 00175 gvputs(job, "# Generated by "); 00176 gvputs(job, tkgen_string(job->common->info[0])); 00177 gvputs(job, " version "); 00178 gvputs(job, tkgen_string(job->common->info[1])); 00179 gvputs(job, " ("); 00180 gvputs(job, tkgen_string(job->common->info[2])); 00181 gvputs(job, ")\n"); 00182 } 00183 00184 static void tkgen_begin_graph(GVJ_t * job) 00185 { 00186 obj_state_t *obj = job->obj; 00187 00188 gvputs(job, "#"); 00189 if (agnameof(obj->u.g)[0]) { 00190 gvputs(job, " Title: "); 00191 gvputs(job, tkgen_string(agnameof(obj->u.g))); 00192 } 00193 gvprintf(job, " Pages: %d\n", job->pagesArraySize.x * job->pagesArraySize.y); 00194 } 00195 00196 static int first_periphery; 00197 00198 static void tkgen_begin_node(GVJ_t * job) 00199 { 00200 first_periphery = 1; /* FIXME - this is an ugly hack! */ 00201 } 00202 00203 static void tkgen_begin_edge(GVJ_t * job) 00204 { 00205 first_periphery = -1; /* FIXME - this is an ugly ugly hack! Need this one for arrowheads. */ 00206 } 00207 00208 static void tkgen_textpara(GVJ_t * job, pointf p, textpara_t * para) 00209 { 00210 obj_state_t *obj = job->obj; 00211 const char *font; 00212 int size; 00213 00214 if (obj->pen != PEN_NONE) { 00215 /* determine font size */ 00216 /* round fontsize down, better too small than too big */ 00217 size = (int)(para->fontsize * job->zoom); 00218 /* don't even bother if fontsize < 1 point */ 00219 if (size) { 00220 tkgen_canvas(job); 00221 gvputs(job, " create text "); 00222 p.y -= size * 0.55; /* cl correction */ 00223 gvprintpointf(job, p); 00224 gvputs(job, " -text {"); 00225 gvputs(job, para->str); 00226 gvputs(job, "}"); 00227 gvputs(job, " -fill "); 00228 tkgen_print_color(job, obj->pencolor); 00229 gvputs(job, " -font {"); 00230 /* tk doesn't like PostScript font names like "Times-Roman" */ 00231 /* so use family names */ 00232 if (para->postscript_alias) 00233 font = para->postscript_alias->family; 00234 else 00235 font = para->fontname; 00236 gvputs(job, "\""); 00237 gvputs(job, font); 00238 gvputs(job, "\""); 00239 /* use -ve fontsize to indicate pixels - see "man n font" */ 00240 gvprintf(job, " %d}", size); 00241 switch (para->just) { 00242 case 'l': 00243 gvputs(job, " -anchor w"); 00244 break; 00245 case 'r': 00246 gvputs(job, " -anchor e"); 00247 break; 00248 default: 00249 case 'n': 00250 break; 00251 } 00252 tkgen_print_tags(job); 00253 gvputs(job, "\n"); 00254 } 00255 } 00256 } 00257 00258 static void tkgen_ellipse(GVJ_t * job, pointf * A, int filled) 00259 { 00260 obj_state_t *obj = job->obj; 00261 pointf r; 00262 00263 if (obj->pen != PEN_NONE) { 00264 /* A[] contains 2 points: the center and top right corner. */ 00265 r.x = A[1].x - A[0].x; 00266 r.y = A[1].y - A[0].y; 00267 A[0].x -= r.x; 00268 A[0].y -= r.y; 00269 tkgen_canvas(job); 00270 gvputs(job, " create oval "); 00271 gvprintpointflist(job, A, 2); 00272 gvputs(job, " -fill "); 00273 if (filled) 00274 tkgen_print_color(job, obj->fillcolor); 00275 else if (first_periphery) 00276 /* tk ovals default to no fill, some fill 00277 * is necessary else "canvas find overlapping" doesn't 00278 * work as expected, use white instead */ 00279 gvputs(job, "white"); 00280 else 00281 gvputs(job, "\"\""); 00282 if (first_periphery == 1) 00283 first_periphery = 0; 00284 gvputs(job, " -width "); 00285 gvprintdouble(job, obj->penwidth); 00286 gvputs(job, " -outline "); 00287 tkgen_print_color(job, obj->pencolor); 00288 if (obj->pen == PEN_DASHED) 00289 gvputs(job, " -dash 5"); 00290 if (obj->pen == PEN_DOTTED) 00291 gvputs(job, " -dash 2"); 00292 tkgen_print_tags(job); 00293 gvputs(job, "\n"); 00294 } 00295 } 00296 00297 static void 00298 tkgen_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, 00299 int arrow_at_end, int filled) 00300 { 00301 obj_state_t *obj = job->obj; 00302 00303 if (obj->pen != PEN_NONE) { 00304 tkgen_canvas(job); 00305 gvputs(job, " create line "); 00306 gvprintpointflist(job, A, n); 00307 gvputs(job, " -fill "); 00308 tkgen_print_color(job, obj->pencolor); 00309 gvputs(job, " -width "); 00310 gvprintdouble(job, obj->penwidth); 00311 if (obj->pen == PEN_DASHED) 00312 gvputs(job, " -dash 5"); 00313 if (obj->pen == PEN_DOTTED) 00314 gvputs(job, " -dash 2"); 00315 gvputs(job, " -smooth bezier "); 00316 tkgen_print_tags(job); 00317 gvputs(job, "\n"); 00318 } 00319 } 00320 00321 static void tkgen_polygon(GVJ_t * job, pointf * A, int n, int filled) 00322 { 00323 obj_state_t *obj = job->obj; 00324 00325 if (obj->pen != PEN_NONE) { 00326 tkgen_canvas(job); 00327 gvputs(job, " create polygon "); 00328 gvprintpointflist(job, A, n); 00329 gvputs(job, " -fill "); 00330 if (filled) 00331 tkgen_print_color(job, obj->fillcolor); 00332 else if (first_periphery) 00333 /* tk polygons default to black fill, some fill 00334 * is necessary else "canvas find overlapping" doesn't 00335 * work as expected, use white instead */ 00336 gvputs(job, "white"); 00337 else 00338 gvputs(job, "\"\""); 00339 if (first_periphery == 1) 00340 first_periphery = 0; 00341 gvputs(job, " -width "); 00342 gvprintdouble(job, obj->penwidth); 00343 gvputs(job, " -outline "); 00344 tkgen_print_color(job, obj->pencolor); 00345 if (obj->pen == PEN_DASHED) 00346 gvputs(job, " -dash 5"); 00347 if (obj->pen == PEN_DOTTED) 00348 gvputs(job, " -dash 2"); 00349 tkgen_print_tags(job); 00350 gvputs(job, "\n"); 00351 } 00352 } 00353 00354 static void tkgen_polyline(GVJ_t * job, pointf * A, int n) 00355 { 00356 obj_state_t *obj = job->obj; 00357 00358 if (obj->pen != PEN_NONE) { 00359 tkgen_canvas(job); 00360 gvputs(job, " create line "); 00361 gvprintpointflist(job, A, n); 00362 gvputs(job, " -fill "); 00363 tkgen_print_color(job, obj->pencolor); 00364 if (obj->pen == PEN_DASHED) 00365 gvputs(job, " -dash 5"); 00366 if (obj->pen == PEN_DOTTED) 00367 gvputs(job, " -dash 2"); 00368 tkgen_print_tags(job); 00369 gvputs(job, "\n"); 00370 } 00371 } 00372 00373 gvrender_engine_t tkgen_engine = { 00374 tkgen_begin_job, 00375 0, /* tkgen_end_job */ 00376 tkgen_begin_graph, 00377 0, /* tkgen_end_graph */ 00378 0, /* tkgen_begin_layer */ 00379 0, /* tkgen_end_layer */ 00380 0, /* tkgen_begin_page */ 00381 0, /* tkgen_end_page */ 00382 0, /* tkgen_begin_cluster */ 00383 0, /* tkgen_end_cluster */ 00384 0, /* tkgen_begin_nodes */ 00385 0, /* tkgen_end_nodes */ 00386 0, /* tkgen_begin_edges */ 00387 0, /* tkgen_end_edges */ 00388 tkgen_begin_node, 00389 0, /* tkgen_end_node */ 00390 tkgen_begin_edge, 00391 0, /* tkgen_end_edge */ 00392 0, /* tkgen_begin_anchor */ 00393 0, /* tkgen_end_anchor */ 00394 0, /* tkgen_begin_label */ 00395 0, /* tkgen_end_label */ 00396 tkgen_textpara, 00397 0, /* tkgen_resolve_color */ 00398 tkgen_ellipse, 00399 tkgen_polygon, 00400 tkgen_bezier, 00401 tkgen_polyline, 00402 tkgen_comment, 00403 0, /* tkgen_library_shape */ 00404 }; 00405 00406 gvrender_features_t render_features_tk = { 00407 GVRENDER_Y_GOES_DOWN 00408 | GVRENDER_NO_WHITE_BG, /* flags */ 00409 4., /* default pad - graph units */ 00410 NULL, /* knowncolors */ 00411 0, /* sizeof knowncolors */ 00412 COLOR_STRING, /* color_type */ 00413 }; 00414 00415 gvdevice_features_t device_features_tk = { 00416 0, /* flags */ 00417 {0.,0.}, /* default margin - points */ 00418 {0.,0.}, /* default page width, height - points */ 00419 {96.,96.}, /* default dpi */ 00420 }; 00421 00422 gvplugin_installed_t gvrender_tk_types[] = { 00423 {FORMAT_TK, "tk", 1, &tkgen_engine, &render_features_tk}, 00424 {0, NULL, 0, NULL, NULL} 00425 }; 00426 00427 gvplugin_installed_t gvdevice_tk_types[] = { 00428 {FORMAT_TK, "tk:tk", 1, NULL, &device_features_tk}, 00429 {0, NULL, 0, NULL, NULL} 00430 };
1.7.5