00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <render.h>
00024 #include <pack.h>
00025 #include <pointset.h>
00026 #include <math.h>
00027
00028 #define C 100
00029
00030 #define MOVEPT(p) ((p).x += dx, (p).y += dy)
00031 #define GRID(x,s) (((x) + ((s)-1)) / (s))
00032 #define CELL(p,s) ((p).x = (p).x/(s), (p).y = ((p).y/(s)))
00033 #define SGN(a) (((a)<0)? -1 : 1)
00034
00035 typedef struct {
00036 Agraph_t *graph;
00037 int perim;
00038 point *cells;
00039 int nc;
00040 int index;
00041
00042 } ginfo;
00043
00044
00045
00046
00047
00048
00049 static int computeStep(int ng, Agraph_t ** gs, int margin)
00050 {
00051 double l1, l2;
00052 double a, b, c, d, r;
00053 double W, H;
00054 Agraph_t *g;
00055 int i;
00056
00057 a = C * ng - 1;
00058 c = 0;
00059 b = 0;
00060 for (i = 0; i < ng; i++) {
00061 g = gs[i];
00062 W = GD_bb(g).UR.x - GD_bb(g).LL.x + 2 * margin;
00063 H = GD_bb(g).UR.y - GD_bb(g).LL.y + 2 * margin;
00064 b -= (W + H);
00065 c -= (W * H);
00066 }
00067 d = b * b - 4.0 * a * c;
00068 if (d < 0) {
00069 agerr(AGERR, "libpack: disc = %f ( < 0)\n", d);
00070 return -1;
00071 }
00072 r = sqrt(d);
00073 l1 = (-b + r) / (2 * a);
00074 l2 = (-b - r) / (2 * a);
00075 if (Verbose > 2) {
00076 fprintf(stderr, "Packing: compute grid size\n");
00077 fprintf(stderr, "a %f b %f c %f d %f r %f\n", a, b, c, d, r);
00078 fprintf(stderr, "root %d (%f) %d (%f)\n", (int) l1, l1, (int) l2,
00079 l2);
00080 fprintf(stderr, " r1 %f r2 %f\n", a * l1 * l1 + b * l1 + c,
00081 a * l2 * l2 + b * l2 + c);
00082 }
00083
00084 return (int) l1;
00085 }
00086
00087
00088
00089
00090
00091 static int cmpf(const void *X, const void *Y)
00092 {
00093 ginfo *x = *(ginfo **) X;
00094 ginfo *y = *(ginfo **) Y;
00095
00096 return (y->perim - x->perim);
00097 }
00098
00099
00100
00101
00102
00103
00104 void fillLine(point p, point q, PointSet * ps)
00105 {
00106 int x1 = p.x;
00107 int y1 = p.y;
00108 int x2 = q.x;
00109 int y2 = q.y;
00110 int d, x, y, ax, ay, sx, sy, dx, dy;
00111
00112 dx = x2 - x1;
00113 ax = ABS(dx) << 1;
00114 sx = SGN(dx);
00115 dy = y2 - y1;
00116 ay = ABS(dy) << 1;
00117 sy = SGN(dy);
00118
00119
00120 x = x1;
00121 y = y1;
00122 if (ax > ay) {
00123 d = ay - (ax >> 1);
00124 for (;;) {
00125
00126 addPS(ps, x, y);
00127 if (x == x2)
00128 return;
00129 if (d >= 0) {
00130 y += sy;
00131 d -= ax;
00132 }
00133 x += sx;
00134 d += ay;
00135 }
00136 } else {
00137 d = ax - (ay >> 1);
00138 for (;;) {
00139
00140 addPS(ps, x, y);
00141 if (y == y2)
00142 return;
00143 if (d >= 0) {
00144 x += sx;
00145 d -= ay;
00146 }
00147 y += sy;
00148 d += ax;
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156
00157 static void
00158 fillEdge(Agedge_t * e, point pt, PointSet * ps, int dx, int dy,
00159 int ssize, int doS)
00160 {
00161 int j, k;
00162 bezier bz;
00163 point hpt;
00164 Agnode_t *h;
00165
00166
00167 if (!doS || !ED_spl(e)) {
00168 h = e->head;
00169 hpt = coord(h);
00170 MOVEPT(hpt);
00171 CELL(hpt, ssize);
00172 fillLine(pt, hpt, ps);
00173 return;
00174 }
00175
00176 for (j = 0; j < ED_spl(e)->size; j++) {
00177 bz = ED_spl(e)->list[j];
00178 if (bz.sflag) {
00179 pt = bz.sp;
00180 hpt = bz.list[0];
00181 k = 1;
00182 } else {
00183 pt = bz.list[0];
00184 hpt = bz.list[1];
00185 k = 2;
00186 }
00187 MOVEPT(pt);
00188 CELL(pt, ssize);
00189 MOVEPT(hpt);
00190 CELL(hpt, ssize);
00191 fillLine(pt, hpt, ps);
00192
00193 for (; k < bz.size; k++) {
00194 pt = hpt;
00195 hpt = bz.list[k];
00196 MOVEPT(hpt);
00197 CELL(hpt, ssize);
00198 fillLine(pt, hpt, ps);
00199 }
00200
00201 if (bz.eflag) {
00202 pt = hpt;
00203 hpt = bz.ep;
00204 MOVEPT(hpt);
00205 CELL(hpt, ssize);
00206 fillLine(pt, hpt, ps);
00207 }
00208 }
00209
00210 }
00211
00212
00213
00214
00215
00216 static void
00217 genBox(Agraph_t * g, ginfo * info, int ssize, int margin, point center)
00218 {
00219 PointSet *ps;
00220 int W, H;
00221 point UR, LL;
00222 box bb = GD_bb(g);
00223 int x, y;
00224
00225 ps = newPS();
00226
00227 LL.x = center.x - margin;
00228 LL.y = center.y - margin;
00229 UR.x = center.x + bb.UR.x - bb.LL.x + margin;
00230 UR.y = center.y + bb.UR.y - bb.LL.y + margin;
00231 CELL(LL, ssize);
00232 CELL(UR, ssize);
00233
00234 for (x = LL.x; x <= UR.x; x++)
00235 for (y = LL.y; y <= UR.y; y++)
00236 addPS(ps, x, y);
00237
00238 info->graph = g;
00239 info->cells = pointsOf(ps);
00240 info->nc = sizeOf(ps);
00241 W = GRID(bb.UR.x - bb.LL.x + 2 * margin, ssize);
00242 H = GRID(bb.UR.y - bb.LL.y + 2 * margin, ssize);
00243 info->perim = W + H;
00244
00245 if (Verbose > 2) {
00246 int i;
00247 fprintf(stderr, "%s no. cells %d W %d H %d\n", g->name, info->nc,
00248 W, H);
00249 for (i = 0; i < info->nc; i++)
00250 fprintf(stderr, " %d %d cell\n", info->cells[i].x,
00251 info->cells[i].y);
00252 }
00253
00254 freePS(ps);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 static int
00268 genPoly(Agraph_t * root, Agraph_t * g, ginfo * info,
00269 int ssize, pack_info * pinfo, point center)
00270 {
00271 PointSet *ps;
00272 int W, H;
00273 point LL, UR;
00274 point pt, s2;
00275 Agraph_t *eg;
00276 Agnode_t *n;
00277 Agedge_t *e;
00278 int x, y;
00279 int dx, dy;
00280 graph_t *subg;
00281 int margin = pinfo->margin;
00282 int doSplines = pinfo->doSplines;
00283 box bb;
00284
00285 if (root)
00286 eg = root;
00287 else
00288 eg = g;
00289
00290 ps = newPS();
00291 dx = center.x - GD_bb(g).LL.x;
00292 dy = center.y - GD_bb(g).LL.y;
00293
00294 if (pinfo->mode == l_clust) {
00295 int i;
00296 void **alg;
00297
00298
00299 alg = N_GNEW(agnnodes(g), void *);
00300 for (i = 0, n = agfstnode(g); n; n = agnxtnode(g, n)) {
00301 alg[i++] = n->u.alg;
00302 n->u.alg = 0;
00303 }
00304
00305
00306 for (i = 1; i <= GD_n_cluster(g); i++) {
00307 subg = GD_clust(g)[i];
00308 bb = GD_bb(subg);
00309 if ((bb.UR.x > bb.LL.x) && (bb.UR.y > bb.LL.y)) {
00310 MOVEPT(bb.LL);
00311 MOVEPT(bb.UR);
00312 bb.LL.x -= margin;
00313 bb.LL.y -= margin;
00314 bb.UR.x += margin;
00315 bb.UR.y += margin;
00316 CELL(bb.LL, ssize);
00317 CELL(bb.UR, ssize);
00318
00319 for (x = bb.LL.x; x <= bb.UR.x; x++)
00320 for (y = bb.LL.y; y <= bb.UR.y; y++)
00321 addPS(ps, x, y);
00322
00323
00324 for (n = agfstnode(subg); n; n = agnxtnode(subg, n))
00325 ND_clust(n) = subg;
00326 }
00327 }
00328
00329
00330 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00331 pt = coord(n);
00332 MOVEPT(pt);
00333 if (!ND_clust(n)) {
00334 s2.x = margin + ND_xsize(n) / 2;
00335 s2.y = margin + ND_ysize(n) / 2;
00336 LL = sub_points(pt, s2);
00337 UR = add_points(pt, s2);
00338 CELL(LL, ssize);
00339 CELL(UR, ssize);
00340
00341 for (x = LL.x; x <= UR.x; x++)
00342 for (y = LL.y; y <= UR.y; y++)
00343 addPS(ps, x, y);
00344
00345 CELL(pt, ssize);
00346 for (e = agfstout(eg, n); e; e = agnxtout(eg, e)) {
00347 fillEdge(e, pt, ps, dx, dy, ssize, doSplines);
00348 }
00349 } else {
00350 CELL(pt, ssize);
00351 for (e = agfstout(eg, n); e; e = agnxtout(eg, e)) {
00352 if (ND_clust(n) == ND_clust(e->head))
00353 continue;
00354 fillEdge(e, pt, ps, dx, dy, ssize, doSplines);
00355 }
00356 }
00357 }
00358
00359
00360 for (i = 0, n = agfstnode(g); n; n = agnxtnode(g, n)) {
00361 n->u.alg = alg[i++];
00362 }
00363 free(alg);
00364
00365 } else
00366 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00367 pt = coord(n);
00368 MOVEPT(pt);
00369 s2.x = margin + ND_xsize(n) / 2;
00370 s2.y = margin + ND_ysize(n) / 2;
00371 LL = sub_points(pt, s2);
00372 UR = add_points(pt, s2);
00373 CELL(LL, ssize);
00374 CELL(UR, ssize);
00375
00376 for (x = LL.x; x <= UR.x; x++)
00377 for (y = LL.y; y <= UR.y; y++)
00378 addPS(ps, x, y);
00379
00380 CELL(pt, ssize);
00381 for (e = agfstout(eg, n); e; e = agnxtout(eg, e)) {
00382 fillEdge(e, pt, ps, dx, dy, ssize, doSplines);
00383 }
00384 }
00385
00386 info->graph = g;
00387 info->cells = pointsOf(ps);
00388 info->nc = sizeOf(ps);
00389 W = GRID(GD_bb(g).UR.x - GD_bb(g).LL.x + 2 * margin, ssize);
00390 H = GRID(GD_bb(g).UR.y - GD_bb(g).LL.y + 2 * margin, ssize);
00391 info->perim = W + H;
00392
00393 if (Verbose > 2) {
00394 int i;
00395 fprintf(stderr, "%s no. cells %d W %d H %d\n", g->name, info->nc,
00396 W, H);
00397 for (i = 0; i < info->nc; i++)
00398 fprintf(stderr, " %d %d cell\n", info->cells[i].x,
00399 info->cells[i].y);
00400 }
00401
00402 freePS(ps);
00403 return 0;
00404 }
00405
00406
00407
00408
00409
00410 static int
00411 fits(int x, int y, ginfo * info, PointSet * ps, point * place, int step)
00412 {
00413 point *cells = info->cells;
00414 int n = info->nc;
00415 point cell;
00416 int i;
00417 point LL;
00418
00419 for (i = 0; i < n; i++) {
00420 cell = *cells;
00421 cell.x += x;
00422 cell.y += y;
00423 if (inPS(ps, cell))
00424 return 0;
00425 cells++;
00426 }
00427
00428 LL = GD_bb(info->graph).LL;
00429 place->x = step * x - LL.x;
00430 place->y = step * y - LL.y;
00431
00432 cells = info->cells;
00433 for (i = 0; i < n; i++) {
00434 cell = *cells;
00435 cell.x += x;
00436 cell.y += y;
00437 insertPS(ps, cell);
00438 cells++;
00439 }
00440
00441 if (Verbose >= 2)
00442 fprintf(stderr, "cc (%d cells) at (%d,%d) (%d,%d)\n", n, x, y,
00443 place->x, place->y);
00444 return 1;
00445 }
00446
00447
00448
00449
00450
00451
00452 static void
00453 placeFixed(ginfo * info, PointSet * ps, point * place, point center)
00454 {
00455 point *cells = info->cells;
00456 int n = info->nc;
00457 int i;
00458
00459 place->x = -center.x;
00460 place->y = -center.y;
00461
00462 for (i = 0; i < n; i++) {
00463 insertPS(ps, *cells++);
00464 }
00465
00466 if (Verbose >= 2)
00467 fprintf(stderr, "cc (%d cells) at (%d,%d)\n", n, place->x,
00468 place->y);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 static void
00478 placeGraph(int i, ginfo * info, PointSet * ps, point * place, int step,
00479 int margin)
00480 {
00481 int x, y;
00482 int W, H;
00483 int bnd;
00484
00485 if (i == 0) {
00486 Agraph_t *g = info->graph;
00487 W = GRID(GD_bb(g).UR.x - GD_bb(g).LL.x + 2 * margin, step);
00488 H = GRID(GD_bb(g).UR.y - GD_bb(g).LL.y + 2 * margin, step);
00489 if (fits(-W / 2, -H / 2, info, ps, place, step))
00490 return;
00491 }
00492
00493 if (fits(0, 0, info, ps, place, step))
00494 return;
00495 W = GD_bb(info->graph).UR.x - GD_bb(info->graph).LL.x;
00496 H = GD_bb(info->graph).UR.y - GD_bb(info->graph).LL.y;
00497 if (W >= H) {
00498 for (bnd = 1;; bnd++) {
00499 x = 0;
00500 y = -bnd;
00501 for (; x < bnd; x++)
00502 if (fits(x, y, info, ps, place, step))
00503 return;
00504 for (; y < bnd; y++)
00505 if (fits(x, y, info, ps, place, step))
00506 return;
00507 for (; x > -bnd; x--)
00508 if (fits(x, y, info, ps, place, step))
00509 return;
00510 for (; y > -bnd; y--)
00511 if (fits(x, y, info, ps, place, step))
00512 return;
00513 for (; x < 0; x++)
00514 if (fits(x, y, info, ps, place, step))
00515 return;
00516 }
00517 } else {
00518 for (bnd = 1;; bnd++) {
00519 y = 0;
00520 x = -bnd;
00521 for (; y > -bnd; y--)
00522 if (fits(x, y, info, ps, place, step))
00523 return;
00524 for (; x < bnd; x++)
00525 if (fits(x, y, info, ps, place, step))
00526 return;
00527 for (; y < bnd; y++)
00528 if (fits(x, y, info, ps, place, step))
00529 return;
00530 for (; x > -bnd; x--)
00531 if (fits(x, y, info, ps, place, step))
00532 return;
00533 for (; y > 0; y--)
00534 if (fits(x, y, info, ps, place, step))
00535 return;
00536 }
00537 }
00538 }
00539
00540 #ifdef DEBUG
00541 void dumpp(ginfo * info, char *pfx)
00542 {
00543 point *cells = info->cells;
00544 int i, c_cnt = info->nc;
00545
00546 fprintf(stderr, "%s\n", pfx);
00547 for (i = 0; i < c_cnt; i++) {
00548 fprintf(stderr, "%d %d box\n", cells[i].x, cells[i].y);
00549 }
00550 }
00551 #endif
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 point *putGraphs(int ng, Agraph_t ** gs, Agraph_t * root,
00574 pack_info * pinfo)
00575 {
00576 int stepSize;
00577 ginfo *info;
00578 ginfo **sinfo;
00579 point *places;
00580 Dict_t *ps;
00581 int i;
00582 boolean *fixed = pinfo->fixed;
00583 int fixed_cnt = 0;
00584 box fixed_bb = { {0, 0}, {0, 0} };
00585 point center;
00586
00587 if (ng <= 0)
00588 return 0;
00589
00590
00591
00592 for (i = 0; i < ng; i++) {
00593 Agraph_t *g = gs[i];
00594 compute_bb(g);
00595 if (fixed && fixed[i]) {
00596 if (fixed_cnt) {
00597 box bb = GD_bb(g);
00598 fixed_bb.LL.x = MIN(bb.LL.x, fixed_bb.LL.x);
00599 fixed_bb.LL.y = MIN(bb.LL.y, fixed_bb.LL.y);
00600 fixed_bb.UR.x = MAX(bb.UR.x, fixed_bb.UR.x);
00601 fixed_bb.UR.y = MAX(bb.UR.y, fixed_bb.UR.y);
00602 } else
00603 fixed_bb = GD_bb(g);
00604 fixed_cnt++;
00605 }
00606 if (Verbose > 2) {
00607 fprintf(stderr, "bb[%s] %d %d %d %d\n", g->name, GD_bb(g).LL.x,
00608 GD_bb(g).LL.y, GD_bb(g).UR.x, GD_bb(g).UR.y);
00609 }
00610 }
00611
00612
00613 stepSize = computeStep(ng, gs, pinfo->margin);
00614 if (Verbose)
00615 fprintf(stderr, "step size = %d\n", stepSize);
00616 if (stepSize < 0)
00617 return 0;
00618
00619
00620 if (fixed) {
00621 center.x = (fixed_bb.LL.x + fixed_bb.UR.x) / 2;
00622 center.y = (fixed_bb.LL.y + fixed_bb.UR.y) / 2;
00623 } else
00624 center.x = center.y = 0;
00625 info = N_NEW(ng, ginfo);
00626 for (i = 0; i < ng; i++) {
00627 info[i].index = i;
00628 if (pinfo->mode == l_graph)
00629 genBox(gs[i], info + i, stepSize, pinfo->margin, center);
00630 else if (genPoly(root, gs[i], info + i, stepSize, pinfo, center)) {
00631 return 0;
00632 }
00633 }
00634
00635
00636 sinfo = N_NEW(ng, ginfo *);
00637 for (i = 0; i < ng; i++) {
00638 sinfo[i] = info + i;
00639 }
00640 qsort(sinfo, ng, sizeof(ginfo *), cmpf);
00641
00642 ps = newPS();
00643 places = N_NEW(ng, point);
00644 if (fixed) {
00645 for (i = 0; i < ng; i++) {
00646 if (fixed[i])
00647 placeFixed(sinfo[i], ps, places + (sinfo[i]->index),
00648 center);
00649 }
00650 for (i = 0; i < ng; i++) {
00651 if (!fixed[i])
00652 placeGraph(i, sinfo[i], ps, places + (sinfo[i]->index),
00653 stepSize, pinfo->margin);
00654 }
00655 } else {
00656 for (i = 0; i < ng; i++)
00657 placeGraph(i, sinfo[i], ps, places + (sinfo[i]->index),
00658 stepSize, pinfo->margin);
00659 }
00660
00661 free(sinfo);
00662 for (i = 0; i < ng; i++)
00663 free(info[i].cells);
00664 free(info);
00665 freePS(ps);
00666
00667 if (Verbose > 1)
00668 for (i = 0; i < ng; i++)
00669 fprintf(stderr, "pos[%d] %d %d\n", i, places[i].x,
00670 places[i].y);
00671
00672 return places;
00673 }
00674
00675
00676
00677
00678 static void shiftEdge(Agedge_t * e, int dx, int dy)
00679 {
00680 int j, k;
00681 bezier bz;
00682
00683 if (ED_label(e))
00684 MOVEPT(ED_label(e)->p);
00685 if (ED_head_label(e))
00686 MOVEPT(ED_head_label(e)->p);
00687 if (ED_tail_label(e))
00688 MOVEPT(ED_tail_label(e)->p);
00689
00690 if (ED_spl(e) == NULL)
00691 return;
00692
00693 for (j = 0; j < ED_spl(e)->size; j++) {
00694 bz = ED_spl(e)->list[j];
00695 for (k = 0; k < bz.size; k++)
00696 MOVEPT(bz.list[k]);
00697 if (bz.sflag)
00698 MOVEPT(ED_spl(e)->list[j].sp);
00699 if (bz.eflag)
00700 MOVEPT(ED_spl(e)->list[j].ep);
00701 }
00702 }
00703
00704
00705
00706 static void shiftGraph(Agraph_t * g, int dx, int dy)
00707 {
00708 graph_t *subg;
00709 box bb = GD_bb(g);
00710 int i;
00711
00712 bb.LL.x += dx;
00713 bb.UR.x += dx;
00714 bb.LL.y += dy;
00715 bb.UR.y += dy;
00716 GD_bb(g) = bb;
00717
00718 if (GD_label(g))
00719 MOVEPT(GD_label(g)->p);
00720
00721 for (i = 1; i <= GD_n_cluster(g); i++) {
00722 subg = GD_clust(g)[i];
00723 shiftGraph(subg, dx, dy);
00724 }
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 static int
00751 shiftGraphs(int ng, Agraph_t ** gs, point * pp, Agraph_t * root,
00752 int doSplines)
00753 {
00754 int i;
00755 int dx, dy;
00756 double fx, fy;
00757 point p;
00758 Agraph_t *g;
00759 Agraph_t *eg;
00760 Agnode_t *n;
00761 Agedge_t *e;
00762
00763 if (ng <= 0)
00764 return abs(ng);
00765
00766 for (i = 0; i < ng; i++) {
00767 g = gs[i];
00768 if (root)
00769 eg = root;
00770 else
00771 eg = g;
00772 p = pp[i];
00773 dx = p.x;
00774 dy = p.y;
00775 fx = PS2INCH(dx);
00776 fy = PS2INCH(dy);
00777
00778 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00779 ND_pos(n)[0] += fx;
00780 ND_pos(n)[1] += fy;
00781 MOVEPT(ND_coord_i(n));
00782 if (doSplines) {
00783 for (e = agfstout(eg, n); e; e = agnxtout(eg, e))
00784 shiftEdge(e, dx, dy);
00785 }
00786 }
00787 shiftGraph(g, dx, dy);
00788 }
00789
00790 return 0;
00791 }
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 int packGraphs(int ng, Agraph_t ** gs, Agraph_t * root, pack_info * info)
00806 {
00807 int ret;
00808 point *pp = putGraphs(ng, gs, root, info);
00809
00810 if (!pp)
00811 return 1;
00812 ret = shiftGraphs(ng, gs, pp, root, info->doSplines);
00813 free(pp);
00814 return ret;
00815 }
00816
00817
00818
00819
00820
00821
00822 int
00823 packSubgraphs(int ng, Agraph_t ** gs, Agraph_t * root, pack_info * info)
00824 {
00825 int ret;
00826
00827 ret = packGraphs(ng, gs, root, info);
00828 if (ret == 0) {
00829 int i, j;
00830 box bb;
00831 graph_t* g;
00832
00833 compute_bb(root);
00834 bb = GD_bb(root);
00835 for (i = 0; i < ng; i++) {
00836 g = gs[i];
00837 for (j = 1; j <= GD_n_cluster(g); j++) {
00838 EXPANDBB(bb,GD_bb(GD_clust(g)[j]));
00839 }
00840 }
00841 GD_bb(root) = bb;
00842 }
00843 return ret;
00844 }
00845
00846
00847
00848
00849 int
00850 pack_graph(int ng, Agraph_t** gs, Agraph_t* root, boolean* fixed)
00851 {
00852 int ret;
00853 pack_info info;
00854
00855 info.margin = getPack (root, CL_OFFSET, CL_OFFSET);;
00856 info.mode = getPackMode (root, l_graph);
00857 info.doSplines = 1;
00858 info.fixed = fixed;
00859 ret = packSubgraphs(ng, gs, root, &info);
00860 if (ret == 0) dotneato_postprocess (root);
00861 return ret;
00862 }
00863
00864
00865
00866
00867
00868 pack_mode getPackMode(Agraph_t * g, pack_mode dflt)
00869 {
00870 char *p = agget(g, "packmode");
00871 pack_mode mode = dflt;
00872
00873 if (p && *p) {
00874 switch (*p) {
00875 #ifdef NOT_IMPLEMENTED
00876 case 'b':
00877 if (streq(p, "bisect"))
00878 mode = l_bisect;
00879 break;
00880 #endif
00881 case 'c':
00882 if (streq(p, "cluster"))
00883 mode = l_clust;
00884 break;
00885 case 'g':
00886 if (streq(p, "graph"))
00887 mode = l_graph;
00888 break;
00889 #ifdef NOT_IMPLEMENTED
00890 case 'h':
00891 if (streq(p, "hull"))
00892 mode = l_hull;
00893 break;
00894 #endif
00895 case 'n':
00896 if (streq(p, "node"))
00897 mode = l_node;
00898 break;
00899 #ifdef NOT_IMPLEMENTED
00900 case 't':
00901 if (streq(p, "tile"))
00902 mode = l_tile;
00903 break;
00904 #endif
00905 }
00906 }
00907 return mode;
00908 }
00909
00910
00911
00912
00913
00914
00915 int getPack(Agraph_t * g, int not_def, int dflt)
00916 {
00917 char *p;
00918 int i;
00919 int v = not_def;
00920
00921 if ((p = agget(g, "pack"))) {
00922 if ((sscanf(p, "%d", &i) == 1) && (i >= 0))
00923 v = i;
00924 else if ((*p == 't') || (*p == 'T'))
00925 v = dflt;
00926 }
00927
00928 return v;
00929 }