00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00165
00166
00167
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
00190
00191
00192
00193
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
00218
00219
00220
00221
00222
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
00329
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
00394
00395
00396
00397
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 }