|
Graphviz 2.29.20120208.0545
|
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 #include "render.h" 00015 #include "agxbuf.h" 00016 #include <stdarg.h> 00017 #include <string.h> 00018 00019 #define YDIR(y) (Y_invert ? (Y_off - (y)) : (y)) 00020 #define YFDIR(y) (Y_invert ? (YF_off - (y)) : (y)) 00021 00022 double Y_off; /* ymin + ymax */ 00023 double YF_off; /* Y_off in inches */ 00024 00025 #ifdef WITH_CGRAPH 00026 static int (*putstr) (void *chan, const char *str); 00027 00028 static void agputs (const char* s, FILE* fp) 00029 { 00030 putstr ((void*)fp, s); 00031 } 00032 static void agputc (int c, FILE* fp) 00033 { 00034 static char buf[2] = {'\0','\0'}; 00035 buf[0] = c; 00036 putstr ((void*)fp, buf); 00037 } 00038 00039 #endif 00040 00041 static void printstring(FILE * f, char *prefix, char *s) 00042 { 00043 if (prefix) agputs(prefix, f); 00044 agputs(s, f); 00045 } 00046 00047 static void printint(FILE * f, char *prefix, int i) 00048 { 00049 char buf[BUFSIZ]; 00050 00051 if (prefix) agputs(prefix, f); 00052 sprintf(buf, "%d", i); 00053 agputs(buf, f); 00054 } 00055 00056 static void printdouble(FILE * f, char *prefix, double v) 00057 { 00058 char buf[BUFSIZ]; 00059 00060 if (prefix) agputs(prefix, f); 00061 sprintf(buf, "%.5g", v); 00062 agputs(buf, f); 00063 } 00064 00065 static void printpoint(FILE * f, pointf p) 00066 { 00067 printdouble(f, " ", PS2INCH(p.x)); 00068 printdouble(f, " ", PS2INCH(YDIR(p.y))); 00069 } 00070 00071 /* setYInvert: 00072 * Set parameters used to flip coordinate system (y=0 at top). 00073 * Values do not need to be unset, since if Y_invert is set, it's 00074 * set for * all graphs during current run, so each will 00075 * reinitialize the values for its bbox. 00076 */ 00077 static void setYInvert(graph_t * g) 00078 { 00079 if (Y_invert) { 00080 Y_off = GD_bb(g).UR.y + GD_bb(g).LL.y; 00081 YF_off = PS2INCH(Y_off); 00082 } 00083 } 00084 00085 /* canon: 00086 * Canonicalize a string which may not have been allocated using agstrdup. 00087 */ 00088 static char* canon (graph_t *g, char* s) 00089 { 00090 #ifndef WITH_CGRAPH 00091 char* ns = agstrdup (s); 00092 char* cs = agcanonStr (ns); 00093 agstrfree (ns); 00094 #else 00095 char* ns = agstrdup (g, s); 00096 char* cs = agcanonStr (ns); 00097 agstrfree (g, ns); 00098 #endif 00099 return cs; 00100 } 00101 00102 static void writenodeandport(FILE * f, node_t * node, char *port) 00103 { 00104 char *name; 00105 if (IS_CLUST_NODE(node)) 00106 name = canon (agraphof(node), strchr(agnameof(node), ':') + 1); 00107 else 00108 name = agcanonStr (agnameof(node)); 00109 printstring(f, " ", name); /* slimey i know */ 00110 if (port && *port) 00111 printstring(f, ":", agcanonStr(port)); 00112 } 00113 00114 /* _write_plain: 00115 */ 00116 void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend) 00117 { 00118 int i, j, splinePoints; 00119 char *tport, *hport; 00120 node_t *n; 00121 edge_t *e; 00122 bezier bz; 00123 pointf pt; 00124 char *lbl; 00125 char* fillcolor; 00126 00127 #ifdef WITH_CGRAPH 00128 putstr = g->clos->disc.io->putstr; 00129 #endif 00130 // setup_graph(job, g); 00131 setYInvert(g); 00132 pt = GD_bb(g).UR; 00133 printdouble(f, "graph ", job->zoom); 00134 printdouble(f, " ", PS2INCH(pt.x)); 00135 printdouble(f, " ", PS2INCH(pt.y)); 00136 agputc('\n', f); 00137 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00138 if (IS_CLUST_NODE(n)) 00139 continue; 00140 printstring(f, "node ", agcanonStr(agnameof(n))); 00141 printpoint(f, ND_coord(n)); 00142 if (ND_label(n)->html) /* if html, get original text */ 00143 #ifndef WITH_CGRAPH 00144 lbl = agcanonStr (agxget(n, N_label->index)); 00145 #else 00146 lbl = agcanonStr (agxget(n, N_label)); 00147 #endif 00148 else 00149 lbl = canon(agraphof(n),ND_label(n)->text); 00150 printdouble(f, " ", ND_width(n)); 00151 printdouble(f, " ", ND_height(n)); 00152 printstring(f, " ", lbl); 00153 printstring(f, " ", late_nnstring(n, N_style, "solid")); 00154 printstring(f, " ", ND_shape(n)->name); 00155 printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR)); 00156 fillcolor = late_nnstring(n, N_fillcolor, ""); 00157 if (fillcolor[0] == '\0') 00158 fillcolor = late_nnstring(n, N_color, DEFAULT_FILL); 00159 printstring(f, " ", fillcolor); 00160 agputc('\n', f); 00161 } 00162 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00163 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00164 00165 #ifndef WITH_CGRAPH 00166 /* FIXME - there must be a proper way to get port info - these are 00167 * supposed to be private to libgraph - from libgraph.h */ 00168 #define TAILX 1 00169 #define HEADX 2 00170 00171 if (extend && e->attr) { 00172 tport = e->attr[TAILX]; 00173 hport = e->attr[HEADX]; 00174 } 00175 #else /* WITH_CGRAPH */ 00176 if (extend) { //assuming these two attrs have already been created by cgraph 00177 if (!(tport = agget(e,"tailport"))) 00178 tport = ""; 00179 if (!(hport = agget(e,"headport"))) 00180 hport = ""; 00181 } 00182 #endif /* WITH_CGRAPH */ 00183 else 00184 tport = hport = ""; 00185 if (ED_spl(e)) { 00186 splinePoints = 0; 00187 for (i = 0; i < ED_spl(e)->size; i++) { 00188 bz = ED_spl(e)->list[i]; 00189 splinePoints += bz.size; 00190 } 00191 printstring(f, NULL, "edge"); 00192 writenodeandport(f, agtail(e), tport); 00193 writenodeandport(f, aghead(e), hport); 00194 printint(f, " ", splinePoints); 00195 for (i = 0; i < ED_spl(e)->size; i++) { 00196 bz = ED_spl(e)->list[i]; 00197 for (j = 0; j < bz.size; j++) 00198 printpoint(f, bz.list[j]); 00199 } 00200 } 00201 if (ED_label(e)) { 00202 printstring(f, " ", canon(agraphof(agtail(e)),ED_label(e)->text)); 00203 printpoint(f, ED_label(e)->pos); 00204 } 00205 printstring(f, " ", late_nnstring(e, E_style, "solid")); 00206 printstring(f, " ", late_nnstring(e, E_color, DEFAULT_COLOR)); 00207 agputc('\n', f); 00208 } 00209 } 00210 agputs("stop\n", f); 00211 } 00212 00213 static void set_record_rects(node_t * n, field_t * f, agxbuf * xb) 00214 { 00215 int i; 00216 char buf[BUFSIZ]; 00217 00218 if (f->n_flds == 0) { 00219 sprintf(buf, "%.5g,%.5g,%.5g,%.5g ", 00220 f->b.LL.x + ND_coord(n).x, 00221 YDIR(f->b.LL.y + ND_coord(n).y), 00222 f->b.UR.x + ND_coord(n).x, 00223 YDIR(f->b.UR.y + ND_coord(n).y)); 00224 agxbput(xb, buf); 00225 } 00226 for (i = 0; i < f->n_flds; i++) 00227 set_record_rects(n, f->fld[i], xb); 00228 } 00229 00230 static void rec_attach_bb(graph_t * g, Agsym_t* bbsym) 00231 { 00232 int c; 00233 char buf[BUFSIZ]; 00234 pointf pt; 00235 00236 sprintf(buf, "%.5g,%.5g,%.5g,%.5g", GD_bb(g).LL.x, YDIR(GD_bb(g).LL.y), 00237 GD_bb(g).UR.x, YDIR(GD_bb(g).UR.y)); 00238 #ifndef WITH_CGRAPH 00239 agxset(g, bbsym->index, buf); 00240 #else 00241 agxset(g, bbsym, buf); 00242 #endif 00243 if (GD_label(g) && GD_label(g)->text[0]) { 00244 pt = GD_label(g)->pos; 00245 sprintf(buf, "%.5g,%.5g", pt.x, YDIR(pt.y)); 00246 agset(g, "lp", buf); 00247 pt = GD_label(g)->dimen; 00248 sprintf(buf, "%.2f", PS2INCH(pt.x)); 00249 agset (g, "lwidth", buf); 00250 sprintf(buf, "%.2f", PS2INCH(pt.y)); 00251 agset (g, "lheight", buf); 00252 } 00253 for (c = 1; c <= GD_n_cluster(g); c++) 00254 rec_attach_bb(GD_clust(g)[c], bbsym); 00255 } 00256 00257 void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) 00258 { 00259 int e_arrows; /* graph has edges with end arrows */ 00260 int s_arrows; /* graph has edges with start arrows */ 00261 int i, j, sides; 00262 char buf[BUFSIZ]; /* Used only for small strings */ 00263 unsigned char xbuffer[BUFSIZ]; /* Initial buffer for xb */ 00264 agxbuf xb; 00265 node_t *n; 00266 edge_t *e; 00267 pointf ptf; 00268 int dim3 = (GD_odim(g) >= 3); 00269 Agsym_t* bbsym; 00270 00271 gv_fixLocale (1); 00272 e_arrows = s_arrows = 0; 00273 setYInvert(g); 00274 agxbinit(&xb, BUFSIZ, xbuffer); 00275 #ifndef WITH_CGRAPH 00276 safe_dcl(g, g->proto->n, "pos", "", agnodeattr); 00277 safe_dcl(g, g->proto->n, "rects", "", agnodeattr); 00278 N_width = safe_dcl(g, g->proto->n, "width", "", agnodeattr); 00279 N_height = safe_dcl(g, g->proto->n, "height", "", agnodeattr); 00280 safe_dcl(g, g->proto->e, "pos", "", agedgeattr); 00281 if (GD_has_labels(g) & NODE_XLABEL) 00282 safe_dcl(g, g->proto->n, "xlp", "", agnodeattr); 00283 if (GD_has_labels(g) & EDGE_LABEL) 00284 safe_dcl(g, g->proto->e, "lp", "", agedgeattr); 00285 if (GD_has_labels(g) & EDGE_XLABEL) 00286 safe_dcl(g, g->proto->e, "xlp", "", agedgeattr); 00287 if (GD_has_labels(g) & HEAD_LABEL) 00288 safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr); 00289 if (GD_has_labels(g) & TAIL_LABEL) 00290 safe_dcl(g, g->proto->e, "tail_lp", "", agedgeattr); 00291 if (GD_label(g)) { 00292 safe_dcl(g, g, "lp", "", agraphattr); 00293 safe_dcl(g, g, "lwidth", "", agraphattr); 00294 safe_dcl(g, g, "lheight", "", agraphattr); 00295 if (GD_label(g)->text[0]) { 00296 ptf = GD_label(g)->pos; 00297 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00298 agset(g, "lp", buf); 00299 ptf = GD_label(g)->dimen; 00300 sprintf(buf, "%.2f", PS2INCH(ptf.x)); 00301 agset(g, "lwidth", buf); 00302 sprintf(buf, "%.2f", PS2INCH(ptf.y)); 00303 agset(g, "lheight", buf); 00304 } 00305 } 00306 bbsym = safe_dcl(g, g, "bb", "", agraphattr); 00307 #else 00308 safe_dcl(g, AGNODE, "pos", ""); 00309 safe_dcl(g, AGNODE, "rects", ""); 00310 N_width = safe_dcl(g, AGNODE, "width", ""); 00311 N_height = safe_dcl(g, AGNODE, "height", ""); 00312 safe_dcl(g, AGEDGE, "pos", ""); 00313 if (GD_has_labels(g) & NODE_XLABEL) 00314 safe_dcl(g, AGNODE, "xlp", ""); 00315 if (GD_has_labels(g) & EDGE_LABEL) 00316 safe_dcl(g, AGEDGE, "lp", ""); 00317 if (GD_has_labels(g) & EDGE_XLABEL) 00318 safe_dcl(g, AGEDGE, "xlp", ""); 00319 if (GD_has_labels(g) & HEAD_LABEL) 00320 safe_dcl(g, AGEDGE, "head_lp", ""); 00321 if (GD_has_labels(g) & TAIL_LABEL) 00322 safe_dcl(g, AGEDGE, "tail_lp", ""); 00323 if (GD_label(g)) { 00324 safe_dcl(g, AGRAPH, "lp", ""); 00325 safe_dcl(g, AGRAPH, "lwidth", ""); 00326 safe_dcl(g, AGRAPH, "lheight", ""); 00327 if (GD_label(g)->text[0]) { 00328 ptf = GD_label(g)->pos; 00329 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00330 agset(g, "lp", buf); 00331 ptf = GD_label(g)->dimen; 00332 sprintf(buf, "%.2f", PS2INCH(ptf.x)); 00333 agset(g, "lwidth", buf); 00334 sprintf(buf, "%.2f", PS2INCH(ptf.y)); 00335 agset(g, "lheight", buf); 00336 } 00337 } 00338 bbsym = safe_dcl(g, AGRAPH, "bb", ""); 00339 #endif 00340 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00341 if (dim3) { 00342 int k; 00343 00344 sprintf(buf, "%.5g,%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y), POINTS_PER_INCH*(ND_pos(n)[2])); 00345 agxbput (&xb, buf); 00346 for (k = 3; k < GD_odim(g); k++) { 00347 sprintf(buf, ",%.5g", POINTS_PER_INCH*(ND_pos(n)[k])); 00348 agxbput (&xb, buf); 00349 } 00350 agset(n, "pos", agxbuse(&xb)); 00351 } else { 00352 sprintf(buf, "%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y)); 00353 agset(n, "pos", buf); 00354 } 00355 sprintf(buf, "%.5g", PS2INCH(ND_ht(n))); 00356 #ifndef WITH_CGRAPH 00357 agxset(n, N_height->index, buf); 00358 sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n))); 00359 agxset(n, N_width->index, buf); 00360 #else 00361 agxset(n, N_height, buf); 00362 sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n))); 00363 agxset(n, N_width, buf); 00364 #endif 00365 if (ND_xlabel(n) && ND_xlabel(n)->set) { 00366 ptf = ND_xlabel(n)->pos; 00367 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00368 agset(n, "xlp", buf); 00369 } 00370 if (strcmp(ND_shape(n)->name, "record") == 0) { 00371 set_record_rects(n, ND_shape_info(n), &xb); 00372 agxbpop(&xb); /* get rid of last space */ 00373 agset(n, "rects", agxbuse(&xb)); 00374 } else { 00375 polygon_t *poly; 00376 int i; 00377 if (N_vertices && isPolygon(n)) { 00378 poly = (polygon_t *) ND_shape_info(n); 00379 sides = poly->sides; 00380 if (sides < 3) { 00381 char *p = agget(n, "samplepoints"); 00382 if (p) 00383 sides = atoi(p); 00384 else 00385 sides = 8; 00386 if (sides < 3) 00387 sides = 8; 00388 } 00389 for (i = 0; i < sides; i++) { 00390 if (i > 0) 00391 agxbputc(&xb, ' '); 00392 if (poly->sides >= 3) 00393 sprintf(buf, "%.5g %.5g", 00394 PS2INCH(poly->vertices[i].x), 00395 YFDIR(PS2INCH(poly->vertices[i].y))); 00396 else 00397 sprintf(buf, "%.5g %.5g", 00398 ND_width(n) / 2.0 * cos(i / (double) sides * M_PI * 2.0), 00399 YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * M_PI * 2.0))); 00400 agxbput(&xb, buf); 00401 } 00402 #ifndef WITH_CGRAPH 00403 agxset(n, N_vertices->index, agxbuse(&xb)); 00404 #else /* WITH_CGRAPH */ 00405 agxset(n, N_vertices, agxbuse(&xb)); 00406 #endif /* WITH_CGRAPH */ 00407 } 00408 } 00409 if (State >= GVSPLINES) { 00410 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00411 if (ED_edge_type(e) == IGNORED) 00412 continue; 00413 if (ED_spl(e) == NULL) 00414 continue; /* reported in postproc */ 00415 for (i = 0; i < ED_spl(e)->size; i++) { 00416 if (i > 0) 00417 agxbputc(&xb, ';'); 00418 if (ED_spl(e)->list[i].sflag) { 00419 s_arrows = 1; 00420 sprintf(buf, "s,%.5g,%.5g ", 00421 ED_spl(e)->list[i].sp.x, 00422 YDIR(ED_spl(e)->list[i].sp.y)); 00423 agxbput(&xb, buf); 00424 } 00425 if (ED_spl(e)->list[i].eflag) { 00426 e_arrows = 1; 00427 sprintf(buf, "e,%.5g,%.5g ", 00428 ED_spl(e)->list[i].ep.x, 00429 YDIR(ED_spl(e)->list[i].ep.y)); 00430 agxbput(&xb, buf); 00431 } 00432 for (j = 0; j < ED_spl(e)->list[i].size; j++) { 00433 if (j > 0) 00434 agxbputc(&xb, ' '); 00435 ptf = ED_spl(e)->list[i].list[j]; 00436 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00437 agxbput(&xb, buf); 00438 } 00439 } 00440 agset(e, "pos", agxbuse(&xb)); 00441 if (ED_label(e)) { 00442 ptf = ED_label(e)->pos; 00443 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00444 agset(e, "lp", buf); 00445 } 00446 if (ED_xlabel(e) && ED_xlabel(e)->set) { 00447 ptf = ED_xlabel(e)->pos; 00448 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00449 agset(e, "xlp", buf); 00450 } 00451 if (ED_head_label(e)) { 00452 ptf = ED_head_label(e)->pos; 00453 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00454 agset(e, "head_lp", buf); 00455 } 00456 if (ED_tail_label(e)) { 00457 ptf = ED_tail_label(e)->pos; 00458 sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); 00459 agset(e, "tail_lp", buf); 00460 } 00461 } 00462 } 00463 } 00464 rec_attach_bb(g, bbsym); 00465 agxbfree(&xb); 00466 00467 if (HAS_CLUST_EDGE(g)) 00468 undoClusterEdges(g); 00469 00470 *sp = s_arrows; 00471 *ep = e_arrows; 00472 gv_fixLocale (0); 00473 } 00474 00475 void attach_attrs(graph_t * g) 00476 { 00477 int e, s; 00478 attach_attrs_and_arrows (g, &s, &e); 00479 } 00480 00481 void output_point(agxbuf *xbuf, pointf p) 00482 { 00483 char buf[BUFSIZ]; 00484 sprintf(buf, "%d %d ", ROUND(p.x), ROUND(YDIR(p.y))); 00485 agxbput(xbuf, buf); 00486 } 00487
1.7.4