/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/common/postproc.c

Go to the documentation of this file.
00001 /* $Id: postproc.c,v 1.13 2007/12/12 03:31:34 erg Exp $ $Revision: 1.13 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 #include "render.h"
00019 
00020 
00021 static int Rankdir;
00022 static boolean Flip;
00023 static point Offset;
00024 
00025 static void place_flip_graph_label(graph_t * g);
00026 
00027 #define M1 \
00028 "/pathbox {\n\
00029     /Y exch %d sub def\n\
00030     /X exch %d sub def\n\
00031     /y exch %d sub def\n\
00032     /x exch %d sub def\n\
00033     newpath x y moveto\n\
00034     X y lineto\n\
00035     X Y lineto\n\
00036     x Y lineto\n\
00037     closepath stroke\n \
00038 } def\n\
00039 /dbgstart { gsave %d %d translate } def\n\
00040 /arrowlength 10 def\n\
00041 /arrowwidth arrowlength 2 div def\n\
00042 /arrowhead {\n\
00043     gsave\n\
00044     rotate\n\
00045     currentpoint\n\
00046     newpath\n\
00047     moveto\n\
00048     arrowlength arrowwidth 2 div rlineto\n\
00049     0 arrowwidth neg rlineto\n\
00050     closepath fill\n\
00051     grestore\n\
00052 } bind def\n\
00053 /makearrow {\n\
00054     currentpoint exch pop sub exch currentpoint pop sub atan\n\
00055     arrowhead\n\
00056 } bind def\n\
00057 /point {\
00058     newpath\
00059     2 0 360 arc fill\
00060 } def\
00061 /makevec {\n\
00062     /Y exch def\n\
00063     /X exch def\n\
00064     /y exch def\n\
00065     /x exch def\n\
00066     newpath x y moveto\n\
00067     X Y lineto stroke\n\
00068     X Y moveto\n\
00069     x y makearrow\n\
00070 } def\n"
00071 #define M2 \
00072 "/pathbox {\n\
00073     /X exch neg %d sub def\n\
00074     /Y exch %d sub def\n\
00075     /x exch neg %d sub def\n\
00076     /y exch %d sub def\n\
00077     newpath x y moveto\n\
00078     X y lineto\n\
00079     X Y lineto\n\
00080     x Y lineto\n\
00081     closepath stroke\n\
00082 } def\n"
00083 
00084 static point map_point(point p)
00085 {
00086     p = ccwrotatep(p, Rankdir*90);
00087     p.x -= Offset.x;
00088     p.y -= Offset.y;
00089     return p;
00090 }
00091 
00092 static void map_edge(edge_t * e)
00093 {
00094     int j, k;
00095     bezier bz;
00096 
00097     if (ED_spl(e) == NULL) {
00098         if ((Concentrate == FALSE) || (ED_edge_type(e) != IGNORED))
00099             agerr(AGERR, "lost %s %s edge\n", e->tail->name,
00100                   e->head->name);
00101         return;
00102     }
00103     for (j = 0; j < ED_spl(e)->size; j++) {
00104         bz = ED_spl(e)->list[j];
00105         for (k = 0; k < bz.size; k++)
00106             bz.list[k] = map_point(bz.list[k]);
00107         if (bz.sflag)
00108             ED_spl(e)->list[j].sp = map_point(ED_spl(e)->list[j].sp);
00109         if (bz.eflag)
00110             ED_spl(e)->list[j].ep = map_point(ED_spl(e)->list[j].ep);
00111     }
00112     if (ED_label(e))
00113         ED_label(e)->p = map_point(ED_label(e)->p);
00114     /* vladimir */
00115     if (ED_head_label(e))
00116         ED_head_label(e)->p = map_point(ED_head_label(e)->p);
00117     if (ED_tail_label(e))
00118         ED_tail_label(e)->p = map_point(ED_tail_label(e)->p);
00119 }
00120 
00121 void translate_bb(graph_t * g, int rankdir)
00122 {
00123     int c;
00124     box bb, new_bb;
00125 
00126     bb = GD_bb(g);
00127     if (rankdir == RANKDIR_LR || rankdir == RANKDIR_BT) {
00128         new_bb.LL = map_point(pointof(bb.LL.x, bb.UR.y));
00129         new_bb.UR = map_point(pointof(bb.UR.x, bb.LL.y));
00130     } else {
00131         new_bb.LL = map_point(pointof(bb.LL.x, bb.LL.y));
00132         new_bb.UR = map_point(pointof(bb.UR.x, bb.UR.y));
00133     }
00134     GD_bb(g) = new_bb;
00135     if (GD_label(g)) {
00136         GD_label(g)->p = map_point(GD_label(g)->p);
00137     }
00138     for (c = 1; c <= GD_n_cluster(g); c++)
00139         translate_bb(GD_clust(g)[c], rankdir);
00140 }
00141 
00142 void dot_nodesize(node_t * n, boolean flip)
00143 {
00144     double x, y;
00145     int ps;
00146 
00147     if (flip == FALSE) {
00148         x = ND_width(n);
00149         y = ND_height(n);
00150     } else {
00151         y = ND_width(n);
00152         x = ND_height(n);
00153     }
00154     ps = POINTS(x) / 2;
00155     if (ps < 1)
00156         ps = 1;
00157     ND_lw_i(n) = ND_rw_i(n) = ps;
00158     if (x == y)
00159         ND_ht_i(n) = 2*ps;
00160     else
00161         ND_ht_i(n) = POINTS(y);
00162 }
00163 
00164 /* translate_drawing:
00165  * Translate and/or rotate nodes, spline points, and bbox info if
00166  * Offset is non-trivial.
00167  * Also, if Rankdir, reset ND_lw, ND_rw, and ND_ht to correct value.
00168  */
00169 static void translate_drawing(graph_t * g)
00170 {
00171     node_t *v;
00172     edge_t *e;
00173     int shift = (Offset.x || Offset.y);
00174 
00175     if (!shift && !Rankdir) return;
00176     for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
00177         if (Rankdir) dot_nodesize(v, FALSE);
00178         if (shift) {
00179             ND_coord_i(v) = map_point(ND_coord_i(v));
00180             if (State == GVSPLINES)
00181                 for (e = agfstout(g, v); e; e = agnxtout(g, e))
00182                     map_edge(e);
00183         }
00184     }
00185     if (shift)
00186         translate_bb(g, GD_rankdir(g));
00187 }
00188 
00189 /* place_root_label:
00190  * Set position of root graph label.
00191  * Note that at this point, after translate_drawing, a
00192  * flipped drawing has been transposed, so we don't have
00193  * to worry about switching x and y.
00194  */
00195 static void place_root_label(graph_t * g, point d)
00196 {
00197     point p;
00198 
00199     if (GD_label_pos(g) & LABEL_AT_RIGHT) {
00200         p.x = GD_bb(g).UR.x - d.x / 2;
00201     } else if (GD_label_pos(g) & LABEL_AT_LEFT) {
00202         p.x = GD_bb(g).LL.x + d.x / 2;
00203     } else {
00204         p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2;
00205     }
00206 
00207     if (GD_label_pos(g) & LABEL_AT_TOP) {
00208         p.y = GD_bb(g).UR.y - d.y / 2;
00209     } else {
00210         p.y = GD_bb(g).LL.y + d.y / 2;
00211     }
00212 
00213     GD_label(g)->p = p;
00214     GD_label(g)->set = TRUE;
00215 }
00216 
00217 /* dotneato_postprocess:
00218  * Set graph and cluster label positions.
00219  * Add space for root graph label and translate graph accordingly.
00220  * Set final nodesize using ns.
00221  * Assumes the boxes of all clusters have been computed.
00222  * When done, the bounding box of g has LL at origin.
00223  */
00224 void dotneato_postprocess(Agraph_t * g)
00225 {
00226     int diff;
00227     pointf dimen;
00228     point d = { 0, 0 };
00229 
00230     Rankdir = GD_rankdir(g);
00231     Flip = GD_flip(g);
00232     if (Flip)
00233         place_flip_graph_label(g);
00234     else
00235         place_graph_label(g);
00236 
00237     if (GD_label(g) && !GD_label(g)->set) {
00238         dimen = GD_label(g)->dimen;
00239         PAD(dimen);
00240         PF2P(dimen, d);
00241         if (Flip) {
00242             if (GD_label_pos(g) & LABEL_AT_TOP) {
00243                 GD_bb(g).UR.x += d.y;
00244             } else {
00245                 GD_bb(g).LL.x -= d.y;
00246             }
00247 
00248             if (d.x > GD_bb(g).UR.y - GD_bb(g).LL.y) {
00249                 diff = d.x - (GD_bb(g).UR.y - GD_bb(g).LL.y);
00250                 diff = diff / 2;
00251                 GD_bb(g).LL.y -= diff;
00252                 GD_bb(g).UR.y += diff;
00253             }
00254         } else {
00255             if (GD_label_pos(g) & LABEL_AT_TOP) {
00256                 if (Rankdir == RANKDIR_TB)
00257                     GD_bb(g).UR.y += d.y;
00258                 else
00259                     GD_bb(g).LL.y -= d.y;
00260             } else {
00261                 if (Rankdir == RANKDIR_TB)
00262                     GD_bb(g).LL.y -= d.y;
00263                 else
00264                     GD_bb(g).UR.y += d.y;
00265             }
00266 
00267             if (d.x > GD_bb(g).UR.x - GD_bb(g).LL.x) {
00268                 diff = d.x - (GD_bb(g).UR.x - GD_bb(g).LL.x);
00269                 diff = diff / 2;
00270                 GD_bb(g).LL.x -= diff;
00271                 GD_bb(g).UR.x += diff;
00272             }
00273         }
00274     }
00275     switch (Rankdir) {
00276     case RANKDIR_TB:
00277         Offset = GD_bb(g).LL;
00278         break;
00279     case RANKDIR_LR:
00280         Offset = pointof(-GD_bb(g).UR.y, GD_bb(g).LL.x);
00281         break;
00282     case RANKDIR_BT:
00283         Offset = pointof(GD_bb(g).LL.x, -GD_bb(g).UR.y);
00284         break;
00285     case RANKDIR_RL:
00286         Offset = pointof(GD_bb(g).LL.y, GD_bb(g).LL.x);
00287         break;
00288     }
00289     translate_drawing(g);
00290     if (GD_label(g) && !GD_label(g)->set)
00291         place_root_label(g, d);
00292 
00293     if (Show_boxes) {
00294         char buf[BUFSIZ];
00295         if (Flip)
00296             sprintf(buf, M2, Offset.x, Offset.y, Offset.x, Offset.y);
00297         else
00298             sprintf(buf, M1, Offset.y, Offset.x, Offset.y, Offset.x, 
00299                  -Offset.x, -Offset.y);
00300         Show_boxes[0] = strdup(buf);
00301     }
00302 }
00303 
00304 #if 0
00305 void osize_label(textlabel_t * label, int *b, int *t, int *l, int *r)
00306 {
00307     point pt, sz2;
00308     pointf dimen;
00309 
00310     dimen = label->dimen;
00311     PAD(dimen);
00312     sz2 = cvt2pt(label->dimen);
00313     sz2.x /= 2;
00314     sz2.y /= 2;
00315     pt = add_points(label->p, sz2);
00316     if (*r < pt.x)
00317         *r = pt.x;
00318     if (*t < pt.y)
00319         *t = pt.y;
00320     pt = sub_points(label->p, sz2);
00321     if (*l > pt.x)
00322         *l = pt.x;
00323     if (*b > pt.y)
00324         *b = pt.y;
00325 }
00326 #endif
00327 
00328 /* place_flip_graph_label:
00329  * Put cluster labels recursively in the flip case.
00330  */
00331 static void place_flip_graph_label(graph_t * g)
00332 {
00333     int c;
00334     point p, d;
00335 #ifdef OLD
00336     int maxx, minx;
00337     int maxy, miny;
00338     pointf dimen;
00339 #endif
00340 
00341     if ((g != g->root) && (GD_label(g)) && !GD_label(g)->set) {
00342 
00343         if (GD_label_pos(g) & LABEL_AT_TOP) {
00344             d = GD_border(g)[RIGHT_IX];
00345             p.x = GD_bb(g).UR.x - d.x / 2;
00346 #ifdef OLD
00347             maxx = GD_bb(g).UR.x + d.y;
00348             GD_bb(g).UR.x = maxx;
00349             if (GD_bb(g->root).UR.x < maxx)
00350                 GD_bb(g->root).UR.x = maxx;
00351 #endif
00352         } else {
00353             d = GD_border(g)[LEFT_IX];
00354             p.x = GD_bb(g).LL.x + d.x / 2;
00355 #ifdef OLD
00356             minx = GD_bb(g).LL.x - d.y;
00357             GD_bb(g).LL.x = minx;
00358             if (GD_bb(g->root).LL.x > minx)
00359                 GD_bb(g->root).LL.x = minx;
00360 #endif
00361         }
00362 
00363         if (GD_label_pos(g) & LABEL_AT_RIGHT) {
00364             p.y = GD_bb(g).LL.y + d.y / 2;
00365 #ifdef OLD
00366             maxy = p.y + d.x / 2;
00367             if (GD_bb(g->root).UR.y < maxy)
00368                 GD_bb(g->root).UR.y = maxy;
00369 #endif
00370         } else if (GD_label_pos(g) & LABEL_AT_LEFT) {
00371             p.y = GD_bb(g).UR.y - d.y / 2;
00372 #ifdef OLD
00373             miny = p.y - d.x / 2;
00374             if (GD_bb(g->root).LL.y > miny)
00375                 GD_bb(g->root).LL.y = miny;
00376 #endif
00377         } else {
00378             p.y = (GD_bb(g).LL.y + GD_bb(g).UR.y) / 2;
00379 #ifdef OLD
00380             maxy = p.y + d.x / 2;
00381             miny = p.y - d.x / 2;
00382 #endif
00383         }
00384 
00385         GD_label(g)->p = p;
00386         GD_label(g)->set = TRUE;
00387     }
00388 
00389     for (c = 1; c <= GD_n_cluster(g); c++)
00390         place_flip_graph_label(GD_clust(g)[c]);
00391 }
00392 
00393 /* place_graph_label:
00394  * Put cluster labels recursively in the non-flip case.
00395  * The adjustments to the bounding boxes should no longer
00396  * be necessary, since we now guarantee the label fits in
00397  * the cluster.
00398  */
00399 void place_graph_label(graph_t * g)
00400 {
00401     int c;
00402 #ifdef OLD
00403     int minx, maxx;
00404 #endif
00405     point p, d;
00406 
00407     if ((g != g->root) && (GD_label(g)) && !GD_label(g)->set) {
00408         if (GD_label_pos(g) & LABEL_AT_TOP) {
00409             d = GD_border(g)[TOP_IX];
00410             p.y = GD_bb(g).UR.y - d.y / 2;
00411         } else {
00412             d = GD_border(g)[BOTTOM_IX];
00413             p.y = GD_bb(g).LL.y + d.y / 2;
00414         }
00415 
00416         if (GD_label_pos(g) & LABEL_AT_RIGHT) {
00417             p.x = GD_bb(g).UR.x - d.x / 2;
00418 #ifdef OLD
00419             minx = p.x - d.x / 2;
00420             if (GD_bb(g).LL.x > minx)
00421                 GD_bb(g).LL.x = minx;
00422             if (GD_bb(g->root).LL.x > minx)
00423                 GD_bb(g->root).LL.x = minx;
00424 #endif
00425         } else if (GD_label_pos(g) & LABEL_AT_LEFT) {
00426             p.x = GD_bb(g).LL.x + d.x / 2;
00427 #ifdef OLD
00428             maxx = p.x + d.x / 2;
00429             if (GD_bb(g).UR.x < maxx)
00430                 GD_bb(g).UR.x = maxx;
00431             if (GD_bb(g->root).UR.x < maxx)
00432                 GD_bb(g->root).UR.x = maxx;
00433 #endif
00434         } else {
00435             p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2;
00436 #ifdef OLD
00437             maxx = p.x + d.x / 2;
00438             minx = p.x - d.x / 2;
00439             if (GD_bb(g).UR.x < maxx)
00440                 GD_bb(g).UR.x = maxx;
00441             if (GD_bb(g).LL.x > minx)
00442                 GD_bb(g).LL.x = minx;
00443             if (GD_bb(g->root).UR.x < maxx)
00444                 GD_bb(g->root).UR.x = maxx;
00445             if (GD_bb(g->root).LL.x > minx)
00446                 GD_bb(g->root).LL.x = minx;
00447 #endif
00448         }
00449         GD_label(g)->p = p;
00450         GD_label(g)->set = TRUE;
00451     }
00452 
00453     for (c = 1; c <= GD_n_cluster(g); c++)
00454         place_graph_label(GD_clust(g)[c]);
00455 }

Generated on Mon Mar 31 19:03:25 2008 for Graphviz by  doxygen 1.5.1