|
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 #ifdef WIN32 00019 #include <io.h> 00020 #include "compat.h" 00021 #endif 00022 00023 #include <stdarg.h> 00024 #include <stdlib.h> 00025 #include <string.h> 00026 00027 #include "macros.h" 00028 #include "const.h" 00029 00030 #include "gvplugin_render.h" 00031 #include "gvplugin_device.h" 00032 #include "agxbuf.h" 00033 #include "utils.h" 00034 #include "gvio.h" 00035 00036 #define GNEW(t) (t*)malloc(sizeof(t)) 00037 00038 /* #define NEW_XDOT */ 00039 00040 typedef enum { 00041 FORMAT_DOT, 00042 FORMAT_CANON, 00043 FORMAT_PLAIN, 00044 FORMAT_PLAIN_EXT, 00045 FORMAT_XDOT 00046 } format_type; 00047 00048 #ifdef WIN32 /*dependencies*/ 00049 #ifdef WITH_CGRAPH 00050 #pragma comment( lib, "cgraph.lib" ) 00051 #else 00052 #pragma comment( lib, "graph.lib" ) 00053 #endif 00054 #pragma comment( lib, "gvc.lib" ) 00055 // #pragma comment( lib, "ingraphs.lib" ) 00056 #endif 00057 00058 #define XDOTVERSION "1.2" 00059 00060 #define NUMXBUFS (EMIT_HLABEL+1) 00061 /* There are as many xbufs as there are values of emit_state_t. 00062 * However, only the first NUMXBUFS are distinct. Nodes, clusters, and 00063 * edges are drawn atomically, so they share the DRAW and LABEL buffers 00064 */ 00065 static agxbuf xbuf[NUMXBUFS]; 00066 static agxbuf* xbufs[] = { 00067 xbuf+EMIT_GDRAW, xbuf+EMIT_CDRAW, xbuf+EMIT_TDRAW, xbuf+EMIT_HDRAW, 00068 xbuf+EMIT_GLABEL, xbuf+EMIT_CLABEL, xbuf+EMIT_TLABEL, xbuf+EMIT_HLABEL, 00069 xbuf+EMIT_CDRAW, xbuf+EMIT_CDRAW, xbuf+EMIT_CLABEL, xbuf+EMIT_CLABEL, 00070 }; 00071 static double penwidth [] = { 00072 1, 1, 1, 1, 00073 1, 1, 1, 1, 00074 1, 1, 1, 1, 00075 }; 00076 00077 typedef struct { 00078 attrsym_t *g_draw; 00079 attrsym_t *g_l_draw; 00080 attrsym_t *n_draw; 00081 attrsym_t *n_l_draw; 00082 attrsym_t *e_draw; 00083 attrsym_t *h_draw; 00084 attrsym_t *t_draw; 00085 attrsym_t *e_l_draw; 00086 attrsym_t *hl_draw; 00087 attrsym_t *tl_draw; 00088 unsigned char buf[NUMXBUFS][BUFSIZ]; 00089 } xdot_state_t; 00090 static xdot_state_t* xd; 00091 00092 static void xdot_str (GVJ_t *job, char* pfx, char* s) 00093 { 00094 emit_state_t emit_state = job->obj->emit_state; 00095 char buf[BUFSIZ]; 00096 00097 sprintf (buf, "%s%d -", pfx, (int)strlen(s)); 00098 agxbput(xbufs[emit_state], buf); 00099 agxbput(xbufs[emit_state], s); 00100 agxbputc(xbufs[emit_state], ' '); 00101 } 00102 00103 static void xdot_points(GVJ_t *job, char c, pointf * A, int n) 00104 { 00105 emit_state_t emit_state = job->obj->emit_state; 00106 char buf[BUFSIZ]; 00107 int i, rc; 00108 00109 rc = agxbputc(xbufs[emit_state], c); 00110 sprintf(buf, " %d ", n); 00111 agxbput(xbufs[emit_state], buf); 00112 for (i = 0; i < n; i++) 00113 output_point(xbufs[emit_state], A[i]); 00114 } 00115 00116 static char* 00117 color2str (unsigned char rgba[4]) 00118 { 00119 static char buf [10]; 00120 00121 sprintf (buf, "#%02x%02x%02x%02x", rgba[0], rgba[1], rgba[2], rgba[3]); 00122 return buf; 00123 } 00124 00125 static void xdot_pencolor (GVJ_t *job) 00126 { 00127 xdot_str (job, "c ", color2str (job->obj->pencolor.u.rgba)); 00128 } 00129 00130 static void xdot_fillcolor (GVJ_t *job) 00131 { 00132 xdot_str (job, "C ", color2str (job->obj->fillcolor.u.rgba)); 00133 } 00134 00135 static void xdot_style (GVJ_t *job) 00136 { 00137 unsigned char buf[BUFSIZ]; 00138 agxbuf xbuf; 00139 char* p, **s; 00140 int more; 00141 00142 /* First, check if penwidth state is correct */ 00143 if (job->obj->penwidth != penwidth[job->obj->emit_state]) { 00144 penwidth[job->obj->emit_state] = job->obj->penwidth; 00145 sprintf ((char*)buf, "setlinewidth(%.3f)", job->obj->penwidth); 00146 xdot_str (job, "S ", (char*)buf); 00147 } 00148 00149 /* now process raw style, if any */ 00150 s = job->obj->rawstyle; 00151 if (!s) 00152 return; 00153 00154 agxbinit(&xbuf, BUFSIZ, buf); 00155 while ((p = *s++)) { 00156 if (streq(p, "filled") || streq(p, "bold") || streq(p, "setlinewidth")) continue; 00157 agxbput(&xbuf, p); 00158 while (*p) 00159 p++; 00160 p++; 00161 if (*p) { /* arguments */ 00162 agxbputc(&xbuf, '('); 00163 more = 0; 00164 while (*p) { 00165 if (more) 00166 agxbputc(&xbuf, ','); 00167 agxbput(&xbuf, p); 00168 while (*p) p++; 00169 p++; 00170 more++; 00171 } 00172 agxbputc(&xbuf, ')'); 00173 } 00174 xdot_str (job, "S ", agxbuse(&xbuf)); 00175 } 00176 00177 agxbfree(&xbuf); 00178 00179 } 00180 00181 static void xdot_end_node(GVJ_t* job) 00182 { 00183 Agnode_t* n = job->obj->u.n; 00184 if (agxblen(xbufs[EMIT_NDRAW])) 00185 #ifndef WITH_CGRAPH 00186 agxset(n, xd->n_draw->index, agxbuse(xbufs[EMIT_NDRAW])); 00187 #else /* WITH_CGRAPH */ 00188 agxset(n, xd->n_draw, agxbuse(xbufs[EMIT_NDRAW])); 00189 #endif /* WITH_CGRAPH */ 00190 if (agxblen(xbufs[EMIT_NLABEL])) 00191 #ifndef WITH_CGRAPH 00192 agxset(n, xd->n_l_draw->index, agxbuse(xbufs[EMIT_NLABEL])); 00193 #else /* WITH_CGRAPH */ 00194 agxset(n, xd->n_l_draw, agxbuse(xbufs[EMIT_NLABEL])); 00195 #endif /* WITH_CGRAPH */ 00196 penwidth[EMIT_NDRAW] = 1; 00197 penwidth[EMIT_NLABEL] = 1; 00198 } 00199 00200 static void xdot_end_edge(GVJ_t* job) 00201 { 00202 Agedge_t* e = job->obj->u.e; 00203 00204 if (agxblen(xbufs[EMIT_EDRAW])) 00205 #ifndef WITH_CGRAPH 00206 agxset(e, xd->e_draw->index, agxbuse(xbufs[EMIT_EDRAW])); 00207 #else /* WITH_CGRAPH */ 00208 agxset(e, xd->e_draw, agxbuse(xbufs[EMIT_EDRAW])); 00209 #endif /* WITH_CGRAPH */ 00210 if (agxblen(xbufs[EMIT_TDRAW])) 00211 #ifndef WITH_CGRAPH 00212 agxset(e, xd->t_draw->index, agxbuse(xbufs[EMIT_TDRAW])); 00213 #else /* WITH_CGRAPH */ 00214 agxset(e, xd->t_draw, agxbuse(xbufs[EMIT_TDRAW])); 00215 #endif /* WITH_CGRAPH */ 00216 if (agxblen(xbufs[EMIT_HDRAW])) 00217 #ifndef WITH_CGRAPH 00218 agxset(e, xd->h_draw->index, agxbuse(xbufs[EMIT_HDRAW])); 00219 #else /* WITH_CGRAPH */ 00220 agxset(e, xd->h_draw, agxbuse(xbufs[EMIT_HDRAW])); 00221 #endif /* WITH_CGRAPH */ 00222 if (agxblen(xbufs[EMIT_ELABEL])) 00223 #ifndef WITH_CGRAPH 00224 agxset(e, xd->e_l_draw->index,agxbuse(xbufs[EMIT_ELABEL])); 00225 #else /* WITH_CGRAPH */ 00226 agxset(e, xd->e_l_draw,agxbuse(xbufs[EMIT_ELABEL])); 00227 #endif /* WITH_CGRAPH */ 00228 if (agxblen(xbufs[EMIT_TLABEL])) 00229 #ifndef WITH_CGRAPH 00230 agxset(e, xd->tl_draw->index, agxbuse(xbufs[EMIT_TLABEL])); 00231 #else /* WITH_CGRAPH */ 00232 agxset(e, xd->tl_draw, agxbuse(xbufs[EMIT_TLABEL])); 00233 #endif /* WITH_CGRAPH */ 00234 if (agxblen(xbufs[EMIT_HLABEL])) 00235 #ifndef WITH_CGRAPH 00236 agxset(e, xd->hl_draw->index, agxbuse(xbufs[EMIT_HLABEL])); 00237 #else /* WITH_CGRAPH */ 00238 agxset(e, xd->hl_draw, agxbuse(xbufs[EMIT_HLABEL])); 00239 #endif /* WITH_CGRAPH */ 00240 penwidth[EMIT_EDRAW] = 1; 00241 penwidth[EMIT_ELABEL] = 1; 00242 penwidth[EMIT_TDRAW] = 1; 00243 penwidth[EMIT_HDRAW] = 1; 00244 penwidth[EMIT_TLABEL] = 1; 00245 penwidth[EMIT_HLABEL] = 1; 00246 } 00247 00248 #ifdef NEW_XDOT 00249 /* xdot_begin_anchor: 00250 * The encoding of which fields are present assumes that one of the fields is present, 00251 * so there is never a 0 after the H. 00252 */ 00253 static void xdot_begin_anchor(GVJ_t * job, char *href, char *tooltip, char *target, char *id) 00254 { 00255 emit_state_t emit_state = job->obj->emit_state; 00256 char buf[3]; /* very small integer */ 00257 unsigned int flags = 0; 00258 00259 agxbput(xbufs[emit_state], "H "); 00260 if (href) 00261 flags |= 1; 00262 if (tooltip) 00263 flags |= 2; 00264 if (target) 00265 flags |= 4; 00266 sprintf (buf, "%d ", flags); 00267 agxbput(xbufs[emit_state], buf); 00268 if (href) 00269 xdot_str (job, "", href); 00270 if (tooltip) 00271 xdot_str (job, "", tooltip); 00272 if (target) 00273 xdot_str (job, "", target); 00274 } 00275 00276 static void xdot_end_anchor(GVJ_t * job) 00277 { 00278 emit_state_t emit_state = job->obj->emit_state; 00279 00280 agxbput(xbufs[emit_state], "H 0 "); 00281 } 00282 #endif 00283 00284 static void xdot_end_cluster(GVJ_t * job) 00285 { 00286 Agraph_t* cluster_g = job->obj->u.sg; 00287 00288 #ifndef WITH_CGRAPH 00289 agxset(cluster_g, xd->g_draw->index, agxbuse(xbufs[EMIT_CDRAW])); 00290 #else /* WITH_CGRAPH */ 00291 agxset(cluster_g, xd->g_draw, agxbuse(xbufs[EMIT_CDRAW])); 00292 #endif /* WITH_CGRAPH */ 00293 if (GD_label(cluster_g)) 00294 #ifndef WITH_CGRAPH 00295 agxset(cluster_g, xd->g_l_draw->index, agxbuse(xbufs[EMIT_CLABEL])); 00296 #else /* WITH_CGRAPH */ 00297 agxset(cluster_g, xd->g_l_draw, agxbuse(xbufs[EMIT_CLABEL])); 00298 #endif /* WITH_CGRAPH */ 00299 penwidth[EMIT_CDRAW] = 1; 00300 penwidth[EMIT_CLABEL] = 1; 00301 } 00302 00303 /* 00304 * John M. suggests: 00305 * You might want to add four more: 00306 * 00307 * _ohdraw_ (optional head-end arrow for edges) 00308 * _ohldraw_ (optional head-end label for edges) 00309 * _otdraw_ (optional tail-end arrow for edges) 00310 * _otldraw_ (optional tail-end label for edges) 00311 * 00312 * that would be generated when an additional option is supplied to 00313 * dot, etc. and 00314 * these would be the arrow/label positions to use if a user want to flip the 00315 * direction of an edge (as sometimes is there want). 00316 * 00317 * N.B. John M. asks: 00318 * By the way, I don't know if you ever plan to add other letters for 00319 * the xdot spec, but could you reserve "a" and also "A" (for attribute), 00320 * "n" and also "N" (for numeric), "w" (for sWitch), "s" (for string) 00321 * and "t" (for tooltip) and "x" (for position). We use those letters in 00322 * our drawing spec (and also "<" and ">"), so if you start generating 00323 * output with them, it could break what we have. 00324 */ 00325 static void 00326 xdot_begin_graph (graph_t *g, int s_arrows, int e_arrows) 00327 { 00328 int i; 00329 00330 xd = GNEW(xdot_state_t); 00331 00332 if (GD_n_cluster(g)) 00333 #ifndef WITH_CGRAPH 00334 xd->g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); 00335 #else 00336 xd->g_draw = safe_dcl(g, AGRAPH, "_draw_", ""); 00337 #endif 00338 else 00339 xd->g_draw = NULL; 00340 if (GD_has_labels(g) & GRAPH_LABEL) 00341 #ifndef WITH_CGRAPH 00342 xd->g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr); 00343 #else 00344 xd->g_l_draw = safe_dcl(g, AGRAPH, "_ldraw_", ""); 00345 #endif 00346 else 00347 xd->g_l_draw = NULL; 00348 00349 #ifndef WITH_CGRAPH 00350 xd->n_draw = safe_dcl(g, g->proto->n, "_draw_", "", agnodeattr); 00351 xd->n_l_draw = safe_dcl(g, g->proto->n, "_ldraw_", "", agnodeattr); 00352 00353 xd->e_draw = safe_dcl(g, g->proto->e, "_draw_", "", agedgeattr); 00354 #else 00355 xd->n_draw = safe_dcl(g, AGNODE, "_draw_", ""); 00356 xd->n_l_draw = safe_dcl(g, AGNODE, "_ldraw_", ""); 00357 00358 xd->e_draw = safe_dcl(g, AGEDGE, "_draw_", ""); 00359 #endif 00360 if (e_arrows) 00361 #ifndef WITH_CGRAPH 00362 xd->h_draw = safe_dcl(g, g->proto->e, "_hdraw_", "", agedgeattr); 00363 #else 00364 xd->h_draw = safe_dcl(g, AGEDGE, "_hdraw_", ""); 00365 #endif 00366 else 00367 xd->h_draw = NULL; 00368 if (s_arrows) 00369 #ifndef WITH_CGRAPH 00370 xd->t_draw = safe_dcl(g, g->proto->e, "_tdraw_", "", agedgeattr); 00371 #else 00372 xd->t_draw = safe_dcl(g, AGEDGE, "_tdraw_", ""); 00373 #endif 00374 else 00375 xd->t_draw = NULL; 00376 if (GD_has_labels(g) & (EDGE_LABEL|EDGE_XLABEL)) 00377 #ifndef WITH_CGRAPH 00378 xd->e_l_draw = safe_dcl(g, g->proto->e, "_ldraw_", "", agedgeattr); 00379 #else 00380 xd->e_l_draw = safe_dcl(g, AGEDGE, "_ldraw_", ""); 00381 #endif 00382 else 00383 xd->e_l_draw = NULL; 00384 if (GD_has_labels(g) & HEAD_LABEL) 00385 #ifndef WITH_CGRAPH 00386 xd->hl_draw = safe_dcl(g, g->proto->e, "_hldraw_", "", agedgeattr); 00387 #else 00388 xd->hl_draw = safe_dcl(g, AGEDGE, "_hldraw_", ""); 00389 #endif 00390 else 00391 xd->hl_draw = NULL; 00392 if (GD_has_labels(g) & TAIL_LABEL) 00393 #ifndef WITH_CGRAPH 00394 xd->tl_draw = safe_dcl(g, g->proto->e, "_tldraw_", "", agedgeattr); 00395 #else 00396 xd->tl_draw = safe_dcl(g, AGEDGE, "_tldraw_", ""); 00397 #endif 00398 else 00399 xd->tl_draw = NULL; 00400 00401 for (i = 0; i < NUMXBUFS; i++) 00402 agxbinit(xbuf+i, BUFSIZ, xd->buf[i]); 00403 } 00404 00405 static void dot_begin_graph(GVJ_t *job) 00406 { 00407 int e_arrows; /* graph has edges with end arrows */ 00408 int s_arrows; /* graph has edges with start arrows */ 00409 graph_t *g = job->obj->u.g; 00410 00411 switch (job->render.id) { 00412 case FORMAT_DOT: 00413 attach_attrs(g); 00414 break; 00415 case FORMAT_CANON: 00416 if (HAS_CLUST_EDGE(g)) 00417 undoClusterEdges(g); 00418 break; 00419 case FORMAT_PLAIN: 00420 case FORMAT_PLAIN_EXT: 00421 break; 00422 case FORMAT_XDOT: 00423 attach_attrs_and_arrows(g, &s_arrows, &e_arrows); 00424 xdot_begin_graph(g, s_arrows, e_arrows); 00425 } 00426 } 00427 00428 static void xdot_end_graph(graph_t* g) 00429 { 00430 int i; 00431 00432 if (agxblen(xbufs[EMIT_GDRAW])) { 00433 if (!xd->g_draw) 00434 #ifndef WITH_CGRAPH 00435 xd->g_draw = safe_dcl(g, g, "_draw_", "", agraphattr); 00436 agxset(g, xd->g_draw->index, agxbuse(xbufs[EMIT_GDRAW])); 00437 #else /* WITH_CGRAPH */ 00438 xd->g_draw = safe_dcl(g, AGRAPH, "_draw_", ""); 00439 agxset(g, xd->g_draw, agxbuse(xbufs[EMIT_GDRAW])); 00440 #endif /* WITH_CGRAPH */ 00441 } 00442 if (GD_label(g)) 00443 #ifndef WITH_CGRAPH 00444 agxset(g, xd->g_l_draw->index, agxbuse(xbufs[EMIT_GLABEL])); 00445 #else /* WITH_CGRAPH */ 00446 agxset(g, xd->g_l_draw, agxbuse(xbufs[EMIT_GLABEL])); 00447 #endif /* WITH_CGRAPH */ 00448 agsafeset (g, "xdotversion", XDOTVERSION, ""); 00449 00450 for (i = 0; i < NUMXBUFS; i++) 00451 agxbfree(xbuf+i); 00452 free (xd); 00453 penwidth[EMIT_GDRAW] = 1; 00454 penwidth[EMIT_GLABEL] = 1; 00455 } 00456 00457 #ifdef WITH_CGRAPH 00458 typedef int (*putstrfn) (void *chan, const char *str); 00459 typedef int (*flushfn) (void *chan); 00460 #endif 00461 static void dot_end_graph(GVJ_t *job) 00462 { 00463 graph_t *g = job->obj->u.g; 00464 #ifdef WITH_CGRAPH 00465 Agiodisc_t* io_save; 00466 static Agiodisc_t io; 00467 00468 if (io.afread == NULL) { 00469 io.afread = AgIoDisc.afread; 00470 io.putstr = (putstrfn)gvputs; 00471 io.flush = (flushfn)gvflush; 00472 } 00473 #endif 00474 00475 #ifndef WITH_CGRAPH 00476 agsetiodisc(NULL, gvfwrite, gvferror); 00477 #else 00478 io_save = g->clos->disc.io; 00479 g->clos->disc.io = &io; 00480 #endif 00481 switch (job->render.id) { 00482 case FORMAT_PLAIN: 00483 write_plain(job, g, (FILE*)job, FALSE); 00484 break; 00485 case FORMAT_PLAIN_EXT: 00486 write_plain(job, g, (FILE*)job, TRUE); 00487 break; 00488 case FORMAT_DOT: 00489 case FORMAT_CANON: 00490 if (!(job->flags & OUTPUT_NOT_REQUIRED)) 00491 agwrite(g, (FILE*)job); 00492 break; 00493 case FORMAT_XDOT: 00494 xdot_end_graph(g); 00495 if (!(job->flags & OUTPUT_NOT_REQUIRED)) 00496 agwrite(g, (FILE*)job); 00497 break; 00498 } 00499 #ifndef WITH_CGRAPH 00500 agsetiodisc(NULL, NULL, NULL); 00501 #else 00502 g->clos->disc.io = io_save; 00503 #endif 00504 } 00505 00506 static void xdot_textpara(GVJ_t * job, pointf p, textpara_t * para) 00507 { 00508 emit_state_t emit_state = job->obj->emit_state; 00509 00510 char buf[BUFSIZ]; 00511 int j; 00512 00513 sprintf(buf, "F %f ", para->fontsize); 00514 agxbput(xbufs[emit_state], buf); 00515 xdot_str (job, "", para->fontname); 00516 xdot_pencolor(job); 00517 00518 switch (para->just) { 00519 case 'l': 00520 j = -1; 00521 break; 00522 case 'r': 00523 j = 1; 00524 break; 00525 default: 00526 case 'n': 00527 j = 0; 00528 break; 00529 } 00530 agxbput(xbufs[emit_state], "T "); 00531 output_point(xbufs[emit_state], p); 00532 sprintf(buf, "%d %d ", j, (int) para->width); 00533 agxbput(xbufs[emit_state], buf); 00534 xdot_str (job, "", para->str); 00535 } 00536 00537 static void xdot_ellipse(GVJ_t * job, pointf * A, int filled) 00538 { 00539 emit_state_t emit_state = job->obj->emit_state; 00540 00541 char buf[BUFSIZ]; 00542 00543 xdot_style (job); 00544 xdot_pencolor (job); 00545 if (filled) { 00546 xdot_fillcolor (job); 00547 agxbput(xbufs[emit_state], "E "); 00548 } 00549 else 00550 agxbput(xbufs[emit_state], "e "); 00551 output_point(xbufs[emit_state], A[0]); 00552 sprintf(buf, "%d %d ", ROUND(A[1].x - A[0].x), ROUND(A[1].y - A[0].y)); 00553 agxbput(xbufs[emit_state], buf); 00554 } 00555 00556 static void xdot_bezier(GVJ_t * job, pointf * A, int n, int arrow_at_start, int arrow_at_end, int filled) 00557 { 00558 xdot_style (job); 00559 xdot_pencolor (job); 00560 if (filled) { 00561 xdot_fillcolor (job); 00562 xdot_points(job, 'b', A, n); /* NB - 'B' & 'b' are reversed in comparison to the other items */ 00563 } 00564 else 00565 xdot_points(job, 'B', A, n); 00566 } 00567 00568 static void xdot_polygon(GVJ_t * job, pointf * A, int n, int filled) 00569 { 00570 xdot_style (job); 00571 xdot_pencolor (job); 00572 if (filled) { 00573 xdot_fillcolor (job); 00574 xdot_points(job, 'P', A, n); 00575 } 00576 else 00577 xdot_points(job, 'p', A, n); 00578 } 00579 00580 static void xdot_polyline(GVJ_t * job, pointf * A, int n) 00581 { 00582 xdot_style (job); 00583 xdot_pencolor (job); 00584 xdot_points(job, 'L', A, n); 00585 } 00586 00587 void core_loadimage_xdot(GVJ_t * job, usershape_t *us, boxf b, boolean filled) 00588 { 00589 emit_state_t emit_state = job->obj->emit_state; 00590 char buf[BUFSIZ]; 00591 00592 agxbput(xbufs[emit_state], "I "); 00593 output_point(xbufs[emit_state], b.LL); 00594 sprintf(buf, "%d %d ", ROUND(b.UR.x - b.LL.x), ROUND(b.UR.y - b.LL.y)); 00595 agxbput(xbufs[emit_state], buf); 00596 xdot_str (job, "", (char*)(us->name)); 00597 } 00598 00599 gvrender_engine_t dot_engine = { 00600 0, /* dot_begin_job */ 00601 0, /* dot_end_job */ 00602 dot_begin_graph, 00603 dot_end_graph, 00604 0, /* dot_begin_layer */ 00605 0, /* dot_end_layer */ 00606 0, /* dot_begin_page */ 00607 0, /* dot_end_page */ 00608 0, /* dot_begin_cluster */ 00609 0, /* dot_end_cluster */ 00610 0, /* dot_begin_nodes */ 00611 0, /* dot_end_nodes */ 00612 0, /* dot_begin_edges */ 00613 0, /* dot_end_edges */ 00614 0, /* dot_begin_node */ 00615 0, /* dot_end_node */ 00616 0, /* dot_begin_edge */ 00617 0, /* dot_end_edge */ 00618 0, /* dot_begin_anchor */ 00619 0, /* dot_end_anchor */ 00620 0, /* dot_begin_label */ 00621 0, /* dot_end_label */ 00622 0, /* dot_textpara */ 00623 0, /* dot_resolve_color */ 00624 0, /* dot_ellipse */ 00625 0, /* dot_polygon */ 00626 0, /* dot_bezier */ 00627 0, /* dot_polyline */ 00628 0, /* dot_comment */ 00629 0, /* dot_library_shape */ 00630 }; 00631 00632 gvrender_engine_t xdot_engine = { 00633 0, /* xdot_begin_job */ 00634 0, /* xdot_end_job */ 00635 dot_begin_graph, 00636 dot_end_graph, 00637 0, /* xdot_begin_layer */ 00638 0, /* xdot_end_layer */ 00639 0, /* xdot_begin_page */ 00640 0, /* xdot_end_page */ 00641 0, /* xdot_begin_cluster */ 00642 xdot_end_cluster, 00643 0, /* xdot_begin_nodes */ 00644 0, /* xdot_end_nodes */ 00645 0, /* xdot_begin_edges */ 00646 0, /* xdot_end_edges */ 00647 0, /* xdot_begin_node */ 00648 xdot_end_node, 00649 0, /* xdot_begin_edge */ 00650 xdot_end_edge, 00651 #ifdef NEW_XDOT 00652 xdot_begin_anchor, 00653 xdot_end_anchor, 00654 #else 00655 0, /* xdot_begin_anchor */ 00656 0, /* xdot_end_anchor */ 00657 #endif 00658 0, /* xdot_begin_label */ 00659 0, /* xdot_end_label */ 00660 xdot_textpara, 00661 0, /* xdot_resolve_color */ 00662 xdot_ellipse, 00663 xdot_polygon, 00664 xdot_bezier, 00665 xdot_polyline, 00666 0, /* xdot_comment */ 00667 0, /* xdot_library_shape */ 00668 }; 00669 00670 gvrender_features_t render_features_dot = { 00671 GVRENDER_DOES_TRANSFORM, /* not really - uses raw graph coords */ /* flags */ 00672 0., /* default pad - graph units */ 00673 NULL, /* knowncolors */ 00674 0, /* sizeof knowncolors */ 00675 COLOR_STRING, /* color_type */ 00676 }; 00677 00678 gvrender_features_t render_features_xdot = { 00679 GVRENDER_DOES_TRANSFORM /* not really - uses raw graph coords */ 00680 | GVRENDER_DOES_MAPS 00681 | GVRENDER_DOES_TARGETS 00682 | GVRENDER_DOES_TOOLTIPS, /* flags */ 00683 0., /* default pad - graph units */ 00684 NULL, /* knowncolors */ 00685 0, /* sizeof knowncolors */ 00686 RGBA_BYTE, /* color_type */ 00687 }; 00688 00689 gvdevice_features_t device_features_canon = { 00690 LAYOUT_NOT_REQUIRED, /* flags */ 00691 {0.,0.}, /* default margin - points */ 00692 {0.,0.}, /* default height, width - device units */ 00693 {72.,72.}, /* default dpi */ 00694 }; 00695 00696 gvdevice_features_t device_features_dot = { 00697 0, /* flags */ 00698 {0.,0.}, /* default margin - points */ 00699 {0.,0.}, /* default page width, height - points */ 00700 {72.,72.}, /* default dpi */ 00701 }; 00702 00703 gvplugin_installed_t gvrender_dot_types[] = { 00704 {FORMAT_DOT, "dot", 1, &dot_engine, &render_features_dot}, 00705 {FORMAT_XDOT, "xdot", 1, &xdot_engine, &render_features_xdot}, 00706 {0, NULL, 0, NULL, NULL} 00707 }; 00708 00709 gvplugin_installed_t gvdevice_dot_types[] = { 00710 {FORMAT_DOT, "dot:dot", 1, NULL, &device_features_dot}, 00711 {FORMAT_DOT, "gv:dot", 1, NULL, &device_features_dot}, 00712 {FORMAT_CANON, "canon:dot", 1, NULL, &device_features_canon}, 00713 {FORMAT_PLAIN, "plain:dot", 1, NULL, &device_features_dot}, 00714 {FORMAT_PLAIN_EXT, "plain-ext:dot", 1, NULL, &device_features_dot}, 00715 {FORMAT_XDOT, "xdot:xdot", 1, NULL, &device_features_dot}, 00716 {0, NULL, 0, NULL, NULL} 00717 };
1.7.5