00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "render.h"
00023
00024 #ifdef DEBUG
00025 static int debugleveln(edge_t* e, int i)
00026 {
00027 return (GD_showboxes(e->head->graph) == i ||
00028 GD_showboxes(e->tail->graph) == i ||
00029 ED_showboxes(e) == i ||
00030 ND_showboxes(e->head) == i ||
00031 ND_showboxes(e->tail) == i);
00032 }
00033
00034 static void showPoints(point ps[], int pn)
00035 {
00036 char buf[BUFSIZ];
00037 int newcnt = Show_cnt + pn + 3;
00038 int bi, li;
00039
00040 Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
00041 li = Show_cnt+1;
00042 Show_boxes[li++] = strdup ("%% self list");
00043 Show_boxes[li++] = strdup ("dbgstart");
00044 for (bi = 0; bi < pn; bi++) {
00045 sprintf(buf, "%d %d point", ps[bi].x, ps[bi].y);
00046 Show_boxes[li++] = strdup (buf);
00047 }
00048 Show_boxes[li++] = strdup ("grestore");
00049
00050 Show_cnt = newcnt;
00051 Show_boxes[Show_cnt+1] = NULL;
00052 }
00053 #endif
00054
00055
00056
00057
00058
00059
00060
00061
00062 static void
00063 arrow_clip(edge_t * fe, node_t * hn,
00064 point * ps, int *startp, int *endp,
00065 bezier * spl, splineInfo * info)
00066 {
00067 edge_t *e;
00068 int i, j, sflag, eflag;
00069
00070 for (e = fe; ED_to_orig(e); e = ED_to_orig(e));
00071
00072 j = info->swapEnds(e);
00073 arrow_flags(e, &sflag, &eflag);
00074 if (info->splineMerge(hn))
00075 eflag = ARR_NONE;
00076 if (info->splineMerge(fe->tail))
00077 sflag = ARR_NONE;
00078 if (j) {
00079 i = sflag;
00080 sflag = eflag;
00081 eflag = i;
00082 }
00083
00084 if (sflag)
00085 *startp =
00086 arrowStartClip(e, ps, *startp, *endp, spl, sflag);
00087 if (eflag)
00088 *endp =
00089 arrowEndClip(e, ps, *startp, *endp, spl, eflag);
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 void bezier_clip(inside_t * inside_context,
00101 boolean(*inside) (inside_t * inside_context, pointf p),
00102 pointf * sp, boolean left_inside)
00103 {
00104 pointf seg[4], best[4], pt, opt, *left, *right;
00105 double low, high, t, *idir, *odir;
00106 boolean found;
00107 int i;
00108
00109 if (left_inside) {
00110 left = NULL;
00111 right = seg;
00112 pt = sp[0];
00113 idir = &low;
00114 odir = &high;
00115 } else {
00116 left = seg;
00117 right = NULL;
00118 pt = sp[3];
00119 idir = &high;
00120 odir = &low;
00121 }
00122 found = FALSE;
00123 low = 0.0;
00124 high = 1.0;
00125 do {
00126 opt = pt;
00127 t = (high + low) / 2.0;
00128 pt = Bezier(sp, 3, t, left, right);
00129 if (inside(inside_context, pt)) {
00130 *idir = t;
00131 } else {
00132 for (i = 0; i < 4; i++)
00133 best[i] = seg[i];
00134 found = TRUE;
00135 *odir = t;
00136 }
00137 } while (ABS(opt.x - pt.x) > .5 || ABS(opt.y - pt.y) > .5);
00138 if (found)
00139 for (i = 0; i < 4; i++)
00140 sp[i] = best[i];
00141 else
00142 for (i = 0; i < 4; i++)
00143 sp[i] = seg[i];
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153 static void
00154 shape_clip0(inside_t * inside_context, node_t * n, point curve[4],
00155 boolean left_inside)
00156 {
00157 int i, save_real_size;
00158 pointf c[4];
00159
00160 save_real_size = ND_rw_i(n);
00161 for (i = 0; i < 4; i++) {
00162 c[i].x = curve[i].x - ND_coord_i(n).x;
00163 c[i].y = curve[i].y - ND_coord_i(n).y;
00164 }
00165
00166 bezier_clip(inside_context, ND_shape(n)->fns->insidefn, c,
00167 left_inside);
00168
00169 for (i = 0; i < 4; i++) {
00170 curve[i].x = ROUND(c[i].x + ND_coord_i(n).x);
00171 curve[i].y = ROUND(c[i].y + ND_coord_i(n).y);
00172 }
00173 ND_rw_i(n) = save_real_size;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 void shape_clip(node_t * n, point curve[4])
00189 {
00190 int save_real_size;
00191 boolean left_inside;
00192 pointf c;
00193 inside_t inside_context;
00194
00195 if (ND_shape(n) == NULL || ND_shape(n)->fns->insidefn == NULL)
00196 return;
00197
00198 inside_context.s.n = n;
00199 inside_context.s.bp = NULL;
00200 save_real_size = ND_rw_i(n);
00201 c.x = curve[0].x - ND_coord_i(n).x;
00202 c.y = curve[0].y - ND_coord_i(n).y;
00203 left_inside = ND_shape(n)->fns->insidefn(&inside_context, c);
00204 ND_rw_i(n) = save_real_size;
00205 shape_clip0(&inside_context, n, curve, left_inside);
00206 }
00207
00208
00209
00210
00211 bezier *new_spline(edge_t * e, int sz)
00212 {
00213 bezier *rv;
00214
00215 while (ED_edge_type(e) != NORMAL)
00216 e = ED_to_orig(e);
00217 if (ED_spl(e) == NULL)
00218 ED_spl(e) = NEW(splines);
00219 ED_spl(e)->list = ALLOC(ED_spl(e)->size + 1, ED_spl(e)->list, bezier);
00220 rv = &(ED_spl(e)->list[ED_spl(e)->size++]);
00221 rv->list = N_NEW(sz, point);
00222 rv->size = sz;
00223 rv->sflag = rv->eflag = FALSE;
00224 return rv;
00225 }
00226
00227
00228
00229
00230
00231 void update_bb(graph_t * g, point pt)
00232 {
00233 if (pt.x > GD_bb(g).UR.x)
00234 GD_bb(g).UR.x = pt.x;
00235 if (pt.y > GD_bb(g).UR.y)
00236 GD_bb(g).UR.y = pt.y;
00237 if (pt.x < GD_bb(g).LL.x)
00238 GD_bb(g).LL.x = pt.x;
00239 if (pt.y < GD_bb(g).LL.y)
00240 GD_bb(g).LL.y = pt.y;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 void
00250 clip_and_install(edge_t * fe, node_t * hn, point * ps, int pn,
00251 splineInfo * info)
00252 {
00253 pointf p2;
00254 bezier *newspl;
00255 node_t *tn;
00256 int start, end, i, clipTail, clipHead;
00257 graph_t *g;
00258 edge_t *orig;
00259 box* tbox;
00260 box* hbox;
00261 inside_t inside_context;
00262
00263 tn = fe->tail;
00264 g = tn->graph;
00265 newspl = new_spline(fe, pn);
00266
00267 for (orig = fe; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
00268
00269
00270 if ((tn->u.rank == hn->u.rank) && (tn->u.order > hn->u.order)) {
00271 node_t *tmp;
00272 tmp = hn;
00273 hn = tn;
00274 tn = tmp;
00275 }
00276 if (tn == orig->tail) {
00277 clipTail = ED_tail_port(orig).clip;
00278 clipHead = ED_head_port(orig).clip;
00279 tbox = ED_tail_port(orig).bp;
00280 hbox = ED_head_port(orig).bp;
00281 }
00282 else {
00283 clipTail = ED_head_port(orig).clip;
00284 clipHead = ED_tail_port(orig).clip;
00285 hbox = ED_tail_port(orig).bp;
00286 tbox = ED_head_port(orig).bp;
00287 }
00288
00289
00290 if(clipTail && ND_shape(tn) && ND_shape(tn)->fns->insidefn) {
00291 inside_context.s.n = tn;
00292 inside_context.s.bp = tbox;
00293 for (start = 0; start < pn - 4; start += 3) {
00294 p2.x = ps[start + 3].x - ND_coord_i(tn).x;
00295 p2.y = ps[start + 3].y - ND_coord_i(tn).y;
00296 if (ND_shape(tn)->fns->insidefn(&inside_context, p2) == FALSE)
00297 break;
00298 }
00299 shape_clip0(&inside_context, tn, &ps[start], TRUE);
00300 } else
00301 start = 0;
00302 if(clipHead && ND_shape(hn) && ND_shape(hn)->fns->insidefn) {
00303 inside_context.s.n = hn;
00304 inside_context.s.bp = hbox;
00305 for (end = pn - 4; end > 0; end -= 3) {
00306 p2.x = ps[end].x - ND_coord_i(hn).x;
00307 p2.y = ps[end].y - ND_coord_i(hn).y;
00308 if (ND_shape(hn)->fns->insidefn(&inside_context, p2) == FALSE)
00309 break;
00310 }
00311 shape_clip0(&inside_context, hn, &ps[end], FALSE);
00312 } else
00313 end = pn - 4;
00314 for (; start < pn - 4; start += 3)
00315 if (ps[start].x != ps[start + 3].x
00316 || ps[start].y != ps[start + 3].y)
00317 break;
00318 for (; end > 0; end -= 3)
00319 if (ps[end].x != ps[end + 3].x || ps[end].y != ps[end + 3].y)
00320 break;
00321 arrow_clip(fe, hn, ps, &start, &end, newspl, info);
00322 for (i = start; i < end + 4; i++) {
00323 point pt;
00324 pt = newspl->list[i - start] = ps[i];
00325 update_bb(g, pt);
00326 }
00327 newspl->size = end - start + 4;
00328 }
00329
00330 static double
00331 conc_slope(node_t* n)
00332 {
00333 double s_in, s_out, m_in, m_out;
00334 int cnt_in, cnt_out;
00335 pointf p;
00336 edge_t *e;
00337
00338 s_in = s_out = 0.0;
00339 for (cnt_in = 0; (e = ND_in(n).list[cnt_in]); cnt_in++)
00340 s_in += ND_coord_i(e->tail).x;
00341 for (cnt_out = 0; (e = ND_out(n).list[cnt_out]); cnt_out++)
00342 s_out += ND_coord_i(e->head).x;
00343 p.x = ND_coord_i(n).x - (s_in / cnt_in);
00344 p.y = ND_coord_i(n).y - ND_coord_i(ND_in(n).list[0]->tail).y;
00345 m_in = atan2(p.y, p.x);
00346 p.x = (s_out / cnt_out) - ND_coord_i(n).x;
00347 p.y = ND_coord_i(ND_out(n).list[0]->head).y - ND_coord_i(n).y;
00348 m_out = atan2(p.y, p.x);
00349 return ((m_in + m_out) / 2.0);
00350 }
00351
00352 void add_box(path * P, box b)
00353 {
00354 if (b.LL.x < b.UR.x && b.LL.y < b.UR.y)
00355 P->boxes[P->nbox++] = b;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 #define FUDGE 2
00389
00390 void
00391 beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
00392 {
00393 int side, mask;
00394 node_t *n;
00395 int (*pboxfn) (node_t*, port*, int, box*, int*);
00396
00397 n = e->tail;
00398
00399 if (ND_shape(n))
00400 pboxfn = ND_shape(n)->fns->pboxfn;
00401 else
00402 pboxfn = NULL;
00403 P->start.p = add_points(ND_coord_i(n), ED_tail_port(e).p);
00404 P->ulpp = P->urpp = P->llpp = P->lrpp = NULL;
00405 if (merge) {
00406
00407 P->start.theta = conc_slope(e->tail);
00408 P->start.constrained = TRUE;
00409 } else {
00410 if (ED_tail_port(e).constrained) {
00411 P->start.theta = ED_tail_port(e).theta;
00412 P->start.constrained = TRUE;
00413 } else
00414 P->start.constrained = FALSE;
00415 }
00416 P->nbox = 0;
00417 P->data = (void *) e;
00418 endp->np = P->start.p;
00419 if ((et == REGULAREDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_tail_port(e).side))) {
00420 edge_t* orig;
00421 box b0, b = endp->nb;
00422 if (side & TOP) {
00423 endp->sidemask = TOP;
00424 if (P->start.p.x < ND_coord_i(n).x) {
00425 b0.LL.x = b.LL.x - 1;
00426
00427 b0.LL.y = P->start.p.y;
00428 b0.UR.x = b.UR.x;
00429 b0.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2 + GD_ranksep(n->graph)/2;
00430 b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - (FUDGE-2);
00431 b.UR.y = b0.LL.y;
00432 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00433 b.LL.x -= 1;
00434 endp->boxes[0] = b0;
00435 endp->boxes[1] = b;
00436 }
00437 else {
00438 b0.LL.x = b.LL.x;
00439 b0.LL.y = P->start.p.y;
00440
00441 b0.UR.x = b.UR.x+1;
00442 b0.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2 + GD_ranksep(n->graph)/2;
00443 b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + (FUDGE-2);
00444 b.UR.y = b0.LL.y;
00445 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00446 b.UR.x += 1;
00447 endp->boxes[0] = b0;
00448 endp->boxes[1] = b;
00449 }
00450 P->start.p.y += 1;
00451 endp->boxn = 2;
00452 }
00453 else if (side & BOTTOM) {
00454 endp->sidemask = BOTTOM;
00455 b.UR.y = MAX(b.UR.y,P->start.p.y);
00456 endp->boxes[0] = b;
00457 endp->boxn = 1;
00458 P->start.p.y -= 1;
00459 }
00460 else if (side & LEFT) {
00461 endp->sidemask = LEFT;
00462 b.UR.x = P->start.p.x;
00463 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00464 b.UR.y = P->start.p.y;
00465 endp->boxes[0] = b;
00466 endp->boxn = 1;
00467 P->start.p.x -= 1;
00468 }
00469 else {
00470 endp->sidemask = RIGHT;
00471 b.LL.x = P->start.p.x;
00472 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00473 b.UR.y = P->start.p.y;
00474 endp->boxes[0] = b;
00475 endp->boxn = 1;
00476 P->start.p.x += 1;
00477 }
00478 for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
00479 if (n == orig->tail)
00480 ED_tail_port(orig).clip = FALSE;
00481 else
00482 ED_head_port(orig).clip = FALSE;
00483 return;
00484 }
00485 if ((et == FLATEDGE) && ((side = ED_tail_port(e).side))) {
00486 box b0, b = endp->nb;
00487 edge_t* orig;
00488 if (side & TOP) {
00489 b.LL.y = MIN(b.LL.y,P->end.p.y);
00490 endp->boxes[0] = b;
00491 endp->boxn = 1;
00492 }
00493 else if (side & BOTTOM) {
00494 if (endp->sidemask == TOP) {
00495 b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00496 b0.UR.x = b.UR.x+1;
00497 b0.LL.x = P->start.p.x;
00498 b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
00499 b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + (FUDGE-2);
00500 b.LL.y = b0.UR.y;
00501 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00502 b.UR.x += 1;
00503 endp->boxes[0] = b0;
00504 endp->boxes[1] = b;
00505 endp->boxn = 2;
00506 }
00507 else {
00508 b.UR.y = MAX(b.UR.y,P->start.p.y);
00509 endp->boxes[0] = b;
00510 endp->boxn = 1;
00511 }
00512 }
00513 else if (side & LEFT) {
00514 b.UR.x = P->start.p.x+1;
00515 if (endp->sidemask == TOP) {
00516 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00517 b.LL.y = P->start.p.y-1;
00518 }
00519 else {
00520 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00521 b.UR.y = P->start.p.y+1;
00522 }
00523 endp->boxes[0] = b;
00524 endp->boxn = 1;
00525 }
00526 else {
00527 b.LL.x = P->start.p.x;
00528 if (endp->sidemask == TOP) {
00529 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00530 b.LL.y = P->start.p.y;
00531 }
00532 else {
00533 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00534 b.UR.y = P->start.p.y+1;
00535 }
00536 endp->boxes[0] = b;
00537 endp->boxn = 1;
00538 }
00539 for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
00540 if (n == orig->tail)
00541 ED_tail_port(orig).clip = FALSE;
00542 else
00543 ED_head_port(orig).clip = FALSE;
00544 endp->sidemask = side;
00545 return;
00546 }
00547
00548 if (et == REGULAREDGE) side = BOTTOM;
00549 else side = endp->sidemask;
00550 if (pboxfn
00551 && (mask = (*pboxfn) (n, &ED_tail_port(e), side, &endp->boxes[0], &endp->boxn)))
00552 endp->sidemask = mask;
00553 else {
00554 endp->boxes[0] = endp->nb;
00555 endp->boxn = 1;
00556
00557 switch (et) {
00558 case SELFEDGE:
00559
00560
00561
00562 assert(0);
00563 endp->boxes[0].UR.y = P->start.p.y - 1;
00564 endp->sidemask = BOTTOM;
00565 break;
00566 case FLATEDGE:
00567 if (endp->sidemask == TOP)
00568 endp->boxes[0].LL.y = P->start.p.y;
00569 else
00570 endp->boxes[0].UR.y = P->start.p.y;
00571 break;
00572 case REGULAREDGE:
00573 endp->boxes[0].UR.y = P->start.p.y;
00574 endp->sidemask = BOTTOM;
00575 P->start.p.y -= 1;
00576 break;
00577 }
00578 }
00579 }
00580
00581 void endpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
00582 {
00583 int side, mask;
00584 node_t *n;
00585 int (*pboxfn) (node_t* n, port*, int, box*, int*);
00586
00587 n = e->head;
00588
00589 if (ND_shape(n))
00590 pboxfn = ND_shape(n)->fns->pboxfn;
00591 else
00592 pboxfn = NULL;
00593 P->end.p = add_points(ND_coord_i(n), ED_head_port(e).p);
00594 if (merge) {
00595
00596 P->end.theta = conc_slope(e->head) + M_PI;
00597 assert(P->end.theta < 2 * M_PI);
00598 P->end.constrained = TRUE;
00599 } else {
00600 if (ED_head_port(e).constrained) {
00601 P->end.theta = ED_head_port(e).theta;
00602 P->end.constrained = TRUE;
00603 } else
00604 P->end.constrained = FALSE;
00605 }
00606 endp->np = P->end.p;
00607 if ((et == REGULAREDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_head_port(e).side))) {
00608 edge_t* orig;
00609 box b0, b = endp->nb;
00610 if (side & TOP) {
00611 endp->sidemask = TOP;
00612 b.LL.y = MIN(b.LL.y,P->end.p.y);
00613 endp->boxes[0] = b;
00614 endp->boxn = 1;
00615 P->start.p.y += 1;
00616 }
00617 else if (side & BOTTOM) {
00618 endp->sidemask = BOTTOM;
00619 if (P->end.p.x < ND_coord_i(n).x) {
00620 b0.LL.x = b.LL.x-1;
00621
00622 b0.UR.y = P->end.p.y;
00623 b0.UR.x = b.UR.x;
00624 b0.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2 - GD_ranksep(n->graph)/2;
00625 b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - (FUDGE-2);
00626 b.LL.y = b0.UR.y;
00627 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00628 b.LL.x -= 1;
00629 endp->boxes[0] = b0;
00630 endp->boxes[1] = b;
00631 }
00632 else {
00633 b0.LL.x = b.LL.x;
00634 b0.UR.y = P->end.p.y;
00635
00636 b0.UR.x = b.UR.x+1;
00637 b0.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2 - GD_ranksep(n->graph)/2;
00638 b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + (FUDGE-2);
00639 b.LL.y = b0.UR.y;
00640 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00641 b.UR.x += 1;
00642 endp->boxes[0] = b0;
00643 endp->boxes[1] = b;
00644 }
00645 endp->boxn = 2;
00646 P->end.p.y -= 1;
00647 }
00648 else if (side & LEFT) {
00649 endp->sidemask = LEFT;
00650 b.UR.x = P->end.p.x;
00651 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00652 b.LL.y = P->end.p.y;
00653 endp->boxes[0] = b;
00654 endp->boxn = 1;
00655 P->start.p.x -= 1;
00656 }
00657 else {
00658 endp->sidemask = RIGHT;
00659 b.LL.x = P->end.p.x;
00660 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00661 b.LL.y = P->end.p.y;
00662 endp->boxes[0] = b;
00663 endp->boxn = 1;
00664 P->start.p.x -= 1;
00665 }
00666 for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
00667 if (n == orig->head)
00668 ED_head_port(orig).clip = FALSE;
00669 else
00670 ED_tail_port(orig).clip = FALSE;
00671 endp->sidemask = side;
00672 return;
00673 }
00674
00675 if ((et == FLATEDGE) && ((side = ED_head_port(e).side))) {
00676 edge_t* orig;
00677 box b0, b = endp->nb;
00678 switch (side) {
00679 case LEFT:
00680 b.UR.x = P->end.p.x;
00681 if (endp->sidemask == TOP) {
00682 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00683 b.LL.y = P->end.p.y;
00684 }
00685 else {
00686 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00687 b.UR.y = P->end.p.y;
00688 }
00689 endp->boxes[0] = b;
00690 endp->boxn = 1;
00691 break;
00692 case RIGHT:
00693 b.LL.x = P->end.p.x-1;
00694 if (endp->sidemask == TOP) {
00695 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00696 b.LL.y = P->end.p.y-1;
00697 }
00698 else {
00699 b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00700 b.UR.y = P->end.p.y;
00701 }
00702 endp->boxes[0] = b;
00703 endp->boxn = 1;
00704 break;
00705 case TOP:
00706 b.LL.y = MIN(b.LL.y,P->end.p.y);
00707 endp->boxes[0] = b;
00708 endp->boxn = 1;
00709 break;
00710 case BOTTOM:
00711 if (endp->sidemask == TOP) {
00712 b0.LL.x = b.LL.x-1;
00713 b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
00714 b0.UR.x = P->end.p.x;
00715 b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
00716 b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - 2;
00717 b.LL.y = b0.UR.y;
00718 b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
00719 b.LL.x -= 1;
00720 endp->boxes[0] = b0;
00721 endp->boxes[1] = b;
00722 endp->boxn = 2;
00723 }
00724 else {
00725 b.UR.y = MAX(b.UR.y,P->start.p.y);
00726 endp->boxes[0] = b;
00727 endp->boxn = 1;
00728 }
00729 break;
00730 }
00731 for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
00732 if (n == orig->head)
00733 ED_head_port(orig).clip = FALSE;
00734 else
00735 ED_tail_port(orig).clip = FALSE;
00736 endp->sidemask = side;
00737 return;
00738 }
00739
00740 if (et == REGULAREDGE) side = TOP;
00741 else side = endp->sidemask;
00742 if (pboxfn
00743 && (mask = (*pboxfn) (n, &ED_head_port(e), side, &endp->boxes[0], &endp->boxn)))
00744 endp->sidemask = mask;
00745 else {
00746 endp->boxes[0] = endp->nb;
00747 endp->boxn = 1;
00748 switch (et) {
00749 case SELFEDGE:
00750
00751
00752
00753 assert(0);
00754 endp->boxes[0].LL.y = P->end.p.y + 1;
00755 endp->sidemask = TOP;
00756 break;
00757 case FLATEDGE:
00758 if (endp->sidemask == TOP)
00759 endp->boxes[0].LL.y = P->start.p.y;
00760 else
00761 endp->boxes[0].UR.y = P->start.p.y;
00762 break;
00763 case REGULAREDGE:
00764 endp->boxes[0].LL.y = P->end.p.y;
00765 endp->sidemask = TOP;
00766 P->start.p.y += 1;
00767 break;
00768 }
00769 }
00770 }
00771
00772 #ifdef OLD
00773
00774 #define ANYW 0
00775
00776 static int selfsidemap[16][3] = {
00777 {BOTTOM, BOTTOM, ANYW},
00778 {TOP, TOP, ANYW},
00779 {RIGHT, RIGHT, ANYW},
00780 {LEFT, LEFT, ANYW},
00781 {BOTTOM, LEFT, CCW},
00782 {LEFT, BOTTOM, CW},
00783 {TOP, RIGHT, CW},
00784 {RIGHT, TOP, CCW},
00785 {TOP, LEFT, CCW},
00786 {LEFT, TOP, CW},
00787 {BOTTOM, RIGHT, CCW},
00788 {RIGHT, BOTTOM, CW},
00789 {BOTTOM, TOP, CCW},
00790 {TOP, BOTTOM, CW},
00791 {LEFT, RIGHT, CCW},
00792 {RIGHT, LEFT, CW},
00793 };
00794
00795 static void
00796 chooseselfsides(pathend_t * tendp, pathend_t * hendp,
00797 int *tsidep, int *hsidep, int *dirp)
00798 {
00799 int i;
00800
00801 for (i = 0; i < 16; i++)
00802 if ((selfsidemap[i][0] & tendp->sidemask) &&
00803 (selfsidemap[i][1] & hendp->sidemask))
00804 break;
00805 if (i == 16)
00806 abort();
00807 *tsidep = selfsidemap[i][0], *hsidep = selfsidemap[i][1];
00808 *dirp = selfsidemap[i][2];
00809 if (*dirp == ANYW) {
00810 switch (*tsidep) {
00811 case BOTTOM:
00812 *dirp = (tendp->np.x < hendp->np.x) ? CCW : CW;
00813 break;
00814 case RIGHT:
00815 *dirp = (tendp->np.y < hendp->np.y) ? CCW : CW;
00816 break;
00817 case TOP:
00818 *dirp = (tendp->np.x > hendp->np.x) ? CCW : CW;
00819 break;
00820 case LEFT:
00821 *dirp = (tendp->np.y > hendp->np.y) ? CCW : CW;
00822 break;
00823 }
00824 }
00825 }
00826
00827 static box makeselfend(box b, int side, int dir, int dx, int dy)
00828 {
00829 box eb = { {0, 0}, {0, 0} };
00830
00831 switch (side) {
00832 case BOTTOM:
00833 eb = boxof(b.LL.x, b.LL.y - dy, b.UR.x, b.LL.y);
00834 (dir == CCW) ? (eb.UR.x += dx / 2) : (eb.LL.x -= dx / 2);
00835 break;
00836 case RIGHT:
00837 eb = boxof(b.UR.x, b.LL.y, b.UR.x + dx, b.UR.y);
00838 (dir == CCW) ? (eb.UR.y += dy / 2) : (eb.LL.y -= dy / 2);
00839 break;
00840 case TOP:
00841 eb = boxof(b.LL.x, b.UR.y, b.UR.x, b.UR.y + dy);
00842 (dir == CCW) ? (eb.LL.x -= dx / 2) : (eb.UR.x += dx / 2);
00843 break;
00844 case LEFT:
00845 eb = boxof(b.LL.x - dx, b.LL.y, b.LL.x, b.UR.y);
00846 (dir == CCW) ? (eb.LL.y -= dy / 2) : (eb.UR.y += dy / 2);
00847 break;
00848 }
00849 return eb;
00850 }
00851
00852 static box
00853 makeselfcomponent(box nb, int side, int dx, int dy, int w, int h)
00854 {
00855 box b = { {0, 0}, {0, 0} };
00856
00857 switch (side) {
00858 case BOTTOM:
00859 b.LL.x = nb.LL.x - dx - w, b.LL.y = nb.LL.y - dy - h;
00860 b.UR.x = nb.UR.x + dx + w, b.UR.y = b.LL.y + h;
00861 break;
00862 case RIGHT:
00863 b.LL.x = nb.UR.x + dx, b.LL.y = nb.LL.y - dy;
00864 b.UR.x = b.LL.x + w, b.UR.y = nb.UR.y + dy;
00865 break;
00866 case TOP:
00867 b.LL.x = nb.LL.x - dx - w, b.LL.y = nb.UR.y + dy;
00868 b.UR.x = nb.UR.x + dx + w, b.UR.y = b.LL.y + h;
00869 break;
00870 case LEFT:
00871 b.LL.x = nb.LL.x - dx - w, b.LL.y = nb.LL.y - dy;
00872 b.UR.x = b.LL.x + w, b.UR.y = nb.UR.y + dy;
00873 break;
00874 }
00875 return b;
00876 }
00877
00878 static void
00879 adjustselfends(box * tbp, box * hbp, point p, int side, int dir)
00880 {
00881 switch (side) {
00882 case BOTTOM:
00883 if (dir == CCW) {
00884 tbp->LL.x -= (tbp->UR.x - p.x), tbp->UR.x = p.x;
00885 hbp->UR.x += (p.x - hbp->LL.x), hbp->LL.x = p.x;
00886 } else {
00887 tbp->UR.x -= (tbp->LL.x - p.x), tbp->LL.x = p.x;
00888 hbp->LL.x += (p.x - hbp->UR.x), hbp->UR.x = p.x;
00889 }
00890 break;
00891 case RIGHT:
00892 if (dir == CCW) {
00893 tbp->LL.y -= (tbp->UR.y - p.y), tbp->UR.y = p.y;
00894 hbp->UR.y += (p.y - hbp->LL.y), hbp->LL.y = p.y;
00895 } else {
00896 tbp->UR.y -= (tbp->LL.y - p.y), tbp->LL.y = p.y;
00897 hbp->LL.y += (p.y - hbp->UR.y), hbp->UR.y = p.y;
00898 }
00899 break;
00900 case TOP:
00901 if (dir == CW) {
00902 tbp->LL.x -= (tbp->UR.x - p.x), tbp->UR.x = p.x;
00903 hbp->UR.x += (p.x - hbp->LL.x), hbp->LL.x = p.x;
00904 } else {
00905 tbp->UR.x -= (tbp->LL.x - p.x), tbp->LL.x = p.x;
00906 hbp->LL.x += (p.x - hbp->UR.x), hbp->UR.x = p.x;
00907 }
00908 break;
00909 case LEFT:
00910 if (dir == CW) {
00911 tbp->LL.y -= (tbp->UR.y - p.y), tbp->UR.y = p.y;
00912 hbp->UR.y += (p.y - hbp->LL.y), hbp->LL.y = p.y;
00913 } else {
00914 tbp->UR.y -= (tbp->LL.y - p.y), tbp->LL.y = p.y;
00915 hbp->LL.y += (p.y - hbp->UR.y), hbp->UR.y = p.y;
00916 }
00917 break;
00918 }
00919 }
00920
00921 static void
00922 completeselfpath(path * P, pathend_t * tendp, pathend_t * hendp,
00923 int tside, int hside, int dir, int dx, int dy, int w,
00924 int h)
00925 {
00926 int i, side;
00927 box boxes[4];
00928 box tb, hb;
00929 int boxn;
00930
00931 tb = makeselfend(tendp->boxes[tendp->boxn - 1], tside, dir, dx, dy);
00932 hb = makeselfend(hendp->boxes[hendp->boxn - 1],
00933 hside, OTHERDIR(dir), dx, dy);
00934
00935 if (tside == hside && tendp->np.x == hendp->np.x &&
00936 tendp->np.y == hendp->np.y)
00937 adjustselfends(&tb, &hb, tendp->np, tside, dir);
00938
00939 boxn = 0;
00940 for (side = tside;; side = NEXTSIDE(side, dir)) {
00941 boxes[boxn++] = makeselfcomponent(tendp->nb, side, dx, dy, w, h);
00942 if (side == hside)
00943 break;
00944 }
00945 for (i = 0; i < tendp->boxn; i++)
00946 add_box(P, tendp->boxes[i]);
00947 add_box(P, tb);
00948 for (i = 0; i < boxn; i++)
00949 add_box(P, boxes[i]);
00950 add_box(P, hb);
00951 for (i = hendp->boxn - 1; i >= 0; i--)
00952 add_box(P, hendp->boxes[i]);
00953 }
00954 #endif
00955
00956 static void
00957 selfBottom (edge_t* edges[], int ind, int cnt, int sizex, int stepy,
00958 splineInfo* sinfo)
00959 {
00960 int hy, ty, sgn;
00961 point tp, hp;
00962 node_t *n;
00963 edge_t *e;
00964 int i, stepx, dx, dy;
00965 double width, height;
00966 point points[1000];
00967 int pointn;
00968 point np;
00969
00970 e = edges[ind];
00971 n = e->tail;
00972
00973 stepx = (sizex / 2) / cnt;
00974 stepx = MAX(stepx,2);
00975 pointn = 0;
00976 np = ND_coord_i(n);
00977 tp = ED_tail_port(e).p;
00978 tp.x += np.x;
00979 tp.y += np.y;
00980 hp = ED_head_port(e).p;
00981 hp.x += np.x;
00982 hp.y += np.y;
00983 if (tp.x >= hp.x) sgn = 1;
00984 else sgn = -1;
00985 dy = ND_ht_i(n)/2, dx = 0;
00986 ty = MIN(dy, 3*(tp.y + dy - np.y));
00987 hy = MIN(dy, 3*(hp.y + dy - np.y));
00988 for (i = 0; i < cnt; i++) {
00989 e = edges[ind++];
00990 dy += stepy, ty += stepy, hy += stepy, dx += sgn*stepx;
00991 pointn = 0;
00992 points[pointn++] = tp;
00993 points[pointn++] = pointof(tp.x + dx, tp.y - ty / 3);
00994 points[pointn++] = pointof(tp.x + dx, np.y - dy);
00995 points[pointn++] = pointof((tp.x+hp.x)/2, np.y - dy);
00996 points[pointn++] = pointof(hp.x - dx, np.y - dy);
00997 points[pointn++] = pointof(hp.x - dx, hp.y - hy / 3);
00998 points[pointn++] = hp;
00999 if (ED_label(e)) {
01000 if (GD_flip(e->tail->graph)) {
01001 width = ED_label(e)->dimen.y;
01002 height = ED_label(e)->dimen.x;
01003 } else {
01004 width = ED_label(e)->dimen.x;
01005 height = ED_label(e)->dimen.y;
01006 }
01007 ED_label(e)->p.y = ND_coord_i(n).y - dy - height / 2.0;
01008 ED_label(e)->p.x = ND_coord_i(n).x;
01009 ED_label(e)->set = TRUE;
01010 if (height > stepy)
01011 dy += height - stepy;
01012 if (dx + stepx < width)
01013 dx += width - stepx;
01014 }
01015 clip_and_install(e, e->head, points, pointn, sinfo);
01016 #ifdef DEBUG
01017 if (debugleveln(e,1))
01018 showPoints (points, pointn);
01019 #endif
01020 }
01021 }
01022
01023
01024 static void
01025 selfTop (edge_t* edges[], int ind, int cnt, int sizex, int stepy,
01026 splineInfo* sinfo)
01027 {
01028 int hy, ty, sgn;
01029 point tp, hp;
01030 node_t *n;
01031 edge_t *e;
01032 int i, stepx, dx, dy;
01033 double width, height;
01034 point points[1000];
01035 int pointn;
01036 point np;
01037
01038 e = edges[ind];
01039 n = e->tail;
01040
01041 stepx = (sizex / 2) / cnt;
01042 stepx = MAX(stepx, 2);
01043 pointn = 0;
01044 np = ND_coord_i(n);
01045 tp = ED_tail_port(e).p;
01046 tp.x += np.x;
01047 tp.y += np.y;
01048 hp = ED_head_port(e).p;
01049 hp.x += np.x;
01050 hp.y += np.y;
01051 if (tp.x >= hp.x) sgn = 1;
01052 else sgn = -1;
01053 dy = ND_ht_i(n)/2, dx = 0;
01054 ty = MIN(dy, 3*(np.y + dy - tp.y));
01055 hy = MIN(dy, 3*(np.y + dy - hp.y));
01056 for (i = 0; i < cnt; i++) {
01057 e = edges[ind++];
01058 dy += stepy, ty += stepy, hy += stepy, dx += sgn*stepx;
01059 pointn = 0;
01060 points[pointn++] = tp;
01061 points[pointn++] = pointof(tp.x + dx, tp.y + ty / 3);
01062 points[pointn++] = pointof(tp.x + dx, np.y + dy);
01063 points[pointn++] = pointof((tp.x+hp.x)/2, np.y + dy);
01064 points[pointn++] = pointof(hp.x - dx, np.y + dy);
01065 points[pointn++] = pointof(hp.x - dx, hp.y + hy / 3);
01066 points[pointn++] = hp;
01067 if (ED_label(e)) {
01068 if (GD_flip(e->tail->graph)) {
01069 width = ED_label(e)->dimen.y;
01070 height = ED_label(e)->dimen.x;
01071 } else {
01072 width = ED_label(e)->dimen.x;
01073 height = ED_label(e)->dimen.y;
01074 }
01075 ED_label(e)->p.y = ND_coord_i(n).y + dy + height / 2.0;
01076 ED_label(e)->p.x = ND_coord_i(n).x;
01077 ED_label(e)->set = TRUE;
01078 if (height > stepy)
01079 dy += height - stepy;
01080 if (dx + stepx < width)
01081 dx += width - stepx;
01082 }
01083 clip_and_install(e, e->head, points, pointn, sinfo);
01084 #ifdef DEBUG
01085 if (debugleveln(e,1))
01086 showPoints (points, pointn);
01087 #endif
01088 }
01089 return;
01090 }
01091
01092 static void
01093 selfRight (edge_t* edges[], int ind, int cnt, int stepx, int sizey,
01094 splineInfo* sinfo)
01095 {
01096 int hx, tx, sgn;
01097 point tp, hp;
01098 node_t *n;
01099 edge_t *e;
01100 int i, stepy, dx, dy;
01101 double width, height;
01102 point points[1000];
01103 int pointn;
01104 point np;
01105
01106 e = edges[ind];
01107 n = e->tail;
01108
01109 stepy = (sizey / 2) / cnt;
01110 stepy = MAX(stepy, 2);
01111 pointn = 0;
01112 np = ND_coord_i(n);
01113 tp = ED_tail_port(e).p;
01114 tp.x += np.x;
01115 tp.y += np.y;
01116 hp = ED_head_port(e).p;
01117 hp.x += np.x;
01118 hp.y += np.y;
01119 if (tp.y >= hp.y) sgn = 1;
01120 else sgn = -1;
01121 dx = ND_rw_i(n), dy = 0;
01122 tx = MIN(dx, 3*(np.x + dx - tp.x));
01123 hx = MIN(dx, 3*(np.x + dx - hp.x));
01124 for (i = 0; i < cnt; i++) {
01125 e = edges[ind++];
01126 dx += stepx, tx += stepx, hx += stepx, dy += sgn*stepy;
01127 pointn = 0;
01128 points[pointn++] = tp;
01129 points[pointn++] = pointof(tp.x + tx / 3, tp.y + dy);
01130 points[pointn++] = pointof(np.x + dx, tp.y + dy);
01131 points[pointn++] = pointof(np.x + dx, (tp.y+hp.y)/2);
01132 points[pointn++] = pointof(np.x + dx, hp.y - dy);
01133 points[pointn++] = pointof(hp.x + hx / 3, hp.y - dy);
01134 points[pointn++] = hp;
01135 if (ED_label(e)) {
01136 if (GD_flip(e->tail->graph)) {
01137 width = ED_label(e)->dimen.y;
01138 height = ED_label(e)->dimen.x;
01139 } else {
01140 width = ED_label(e)->dimen.x;
01141 height = ED_label(e)->dimen.y;
01142 }
01143 ED_label(e)->p.x = ND_coord_i(n).x + dx + width / 2.0;
01144 ED_label(e)->p.y = ND_coord_i(n).y;
01145 ED_label(e)->set = TRUE;
01146 if (width > stepx)
01147 dx += width - stepx;
01148 if (dy + stepy < height)
01149 dy += height - stepy;
01150 }
01151 clip_and_install(e, e->head, points, pointn, sinfo);
01152 #ifdef DEBUG
01153 if (debugleveln(e,1))
01154 showPoints (points, pointn);
01155 #endif
01156 }
01157 return;
01158 }
01159
01160 static void
01161 selfLeft (edge_t* edges[], int ind, int cnt, int stepx, int sizey,
01162 splineInfo* sinfo)
01163 {
01164 int hx, tx, sgn;
01165 point tp, hp;
01166 node_t *n;
01167 edge_t *e;
01168 int i, stepy, dx, dy;
01169 double width, height;
01170 point points[1000];
01171 int pointn;
01172 point np;
01173
01174 e = edges[ind];
01175 n = e->tail;
01176
01177 stepy = (sizey / 2) / cnt;
01178 stepy = MAX(stepy,2);
01179 pointn = 0;
01180 np = ND_coord_i(n);
01181 tp = ED_tail_port(e).p;
01182 tp.x += np.x;
01183 tp.y += np.y;
01184 hp = ED_head_port(e).p;
01185 hp.x += np.x;
01186 hp.y += np.y;
01187 if (tp.y >= hp.y) sgn = 1;
01188 else sgn = -1;
01189 dx = ND_lw_i(n), dy = 0;
01190 tx = MIN(dx, 3*(tp.x + dx - np.x));
01191 hx = MIN(dx, 3*(hp.x + dx - np.x));
01192 for (i = 0; i < cnt; i++) {
01193 e = edges[ind++];
01194 dx += stepx, tx += stepx, hx += stepx, dy += sgn*stepy;
01195 pointn = 0;
01196 points[pointn++] = tp;
01197 points[pointn++] = pointof(tp.x - tx / 3, tp.y + dy);
01198 points[pointn++] = pointof(np.x - dx, tp.y + dy);
01199 points[pointn++] = pointof(np.x - dx, (tp.y+hp.y)/2);
01200 points[pointn++] = pointof(np.x - dx, hp.y - dy);
01201 points[pointn++] = pointof(hp.x - hx / 3, hp.y - dy);
01202 points[pointn++] = hp;
01203 if (ED_label(e)) {
01204 if (GD_flip(e->tail->graph)) {
01205 width = ED_label(e)->dimen.y;
01206 height = ED_label(e)->dimen.x;
01207 } else {
01208 width = ED_label(e)->dimen.x;
01209 height = ED_label(e)->dimen.y;
01210 }
01211 ED_label(e)->p.x = ND_coord_i(n).x - dx - width / 2.0;
01212 ED_label(e)->p.y = ND_coord_i(n).y;
01213 ED_label(e)->set = TRUE;
01214 if (width > stepx)
01215 dx += width - stepx;
01216 if (dy + stepy < height)
01217 dy += height - stepy;
01218 }
01219 clip_and_install(e, e->head, points, pointn, sinfo);
01220 #ifdef DEBUG
01221 if (debugleveln(e,1))
01222 showPoints (points, pointn);
01223 #endif
01224 }
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235 int
01236 selfRightSpace (edge_t* e)
01237 {
01238 int sw;
01239 double label_width;
01240 textlabel_t* l = ED_label(e);
01241
01242 if (((!ED_tail_port(e).defined) && (!ED_head_port(e).defined)) ||
01243 (!(ED_tail_port(e).side & LEFT) &&
01244 !(ED_head_port(e).side & LEFT) &&
01245 ((ED_tail_port(e).side != ED_head_port(e).side) ||
01246 (!(ED_tail_port(e).side & (TOP|BOTTOM)))))) {
01247 sw = SELF_EDGE_SIZE;
01248 if (l) {
01249 label_width = GD_flip(e->head->graph) ? l->dimen.y : l->dimen.x;
01250 sw += label_width;
01251 }
01252 }
01253 else sw = 0;
01254 return sw;
01255 }
01256
01257
01258
01259
01260
01261
01262
01263 void
01264 makeSelfEdge(path * P, edge_t * edges[], int ind, int cnt, int sizex,
01265 int sizey, splineInfo * sinfo)
01266 {
01267 edge_t *e;
01268 #ifdef OLD
01269 node_t *n;
01270 point *ps, np;
01271 pathend_t tend, hend;
01272 int i, j, maxx, stepy, dx, dy, tside, hside, dir, pn;
01273 double width, height;
01274 point points[1000];
01275 int pointn;
01276 #endif
01277
01278 e = edges[ind];
01279
01280
01281
01282
01283
01284 if (((!ED_tail_port(e).defined) && (!ED_head_port(e).defined)) ||
01285 (!(ED_tail_port(e).side & LEFT) &&
01286 !(ED_head_port(e).side & LEFT) &&
01287 ((ED_tail_port(e).side != ED_head_port(e).side) ||
01288 (!(ED_tail_port(e).side & (TOP|BOTTOM)))))) {
01289 selfRight(edges, ind, cnt, sizex, sizey, sinfo);
01290 }
01291
01292
01293 else if ((ED_tail_port(e).side & LEFT) || (ED_head_port(e).side & LEFT)) {
01294
01295
01296 if ((ED_tail_port(e).side & RIGHT) || (ED_head_port(e).side & RIGHT)) {
01297 selfTop(edges, ind, cnt, sizex, sizey, sinfo);
01298 }
01299 else {
01300 selfLeft(edges, ind, cnt, sizex, sizey, sinfo);
01301 }
01302 }
01303
01304
01305 else if (ED_tail_port(e).side & TOP) {
01306 selfTop(edges, ind, cnt, sizex, sizey, sinfo);
01307 }
01308 else if (ED_tail_port(e).side & BOTTOM) {
01309 selfBottom(edges, ind, cnt, sizex, sizey, sinfo);
01310 }
01311
01312 else assert(0);
01313
01314 #ifdef OLD
01315 tend.nb =
01316 boxof(ND_coord_i(n).x - ND_lw_i(n),
01317 ND_coord_i(n).y - ND_ht_i(n) / 2,
01318 ND_coord_i(n).x + ND_rw_i(n),
01319 ND_coord_i(n).y + ND_ht_i(n) / 2);
01320 hend.nb = tend.nb;
01321 stepy = stepx / 2;
01322 dx = 0, dy = 0;
01323 for (i = 0; i < cnt; i++) {
01324 e = edges[ind++];
01325 dx += stepx, dy += stepy;
01326
01327
01328 beginpath(P, e, SELFEDGE, &tend, sinfo->splineMerge(e->tail));
01329
01330
01331 endpath(P, e, SELFEDGE, &hend, sinfo->splineMerge(e->head));
01332
01333 chooseselfsides(&tend, &hend, &tside, &hside, &dir);
01334 completeselfpath(P, &tend, &hend, tside, hside, dir,
01335 dx, dy, stepx, stepx);
01336
01337 ps = routesplines(P, &pn);
01338 if (pn == 0)
01339 return;
01340 if (ED_label(e)) {
01341
01342 for (j = 0, maxx = ND_coord_i(n).x; j < P->nbox; j++)
01343 if (P->boxes[j].UR.x > maxx)
01344 maxx = P->boxes[j].UR.x;
01345 if (GD_flip(e->tail->graph))
01346 width = ED_label(e)->dimen.y;
01347 else
01348 width = ED_label(e)->dimen.x;
01349 ED_label(e)->p.x = maxx + width / 2.0;
01350 ED_label(e)->p.y = ND_coord_i(n).y;
01351 ED_label(e)->set = TRUE;
01352 if (width > stepx)
01353 dx += width - stepx;
01354 }
01355 clip_and_install(e, e->head, ps, pn, sinfo);
01356 }
01357 #endif
01358 }
01359
01360
01361 void place_portlabel(edge_t * e, boolean head_p)
01362
01363
01364
01365
01366 {
01367 textlabel_t *l;
01368 splines *spl;
01369 bezier *bez;
01370 double dist, angle;
01371 point p;
01372 pointf c[4], pf;
01373 int i;
01374
01375 if (ED_edge_type(e) == IGNORED)
01376 return;
01377 l = head_p ? ED_head_label(e) : ED_tail_label(e);
01378 spl = getsplinepoints(e);
01379 if (!head_p) {
01380 bez = &spl->list[0];
01381 if (bez->sflag) {
01382 p = bez->sp;
01383 P2PF(bez->list[0], pf);
01384 } else {
01385 p = bez->list[0];
01386 for (i = 0; i < 4; i++)
01387 P2PF(bez->list[i], c[i]);
01388 pf = Bezier(c, 3, 0.1, NULL, NULL);
01389 }
01390 } else {
01391 bez = &spl->list[spl->size - 1];
01392 if (bez->eflag) {
01393 p = bez->ep;
01394 P2PF(bez->list[bez->size - 1], pf);
01395 } else {
01396 p = bez->list[bez->size - 1];
01397 for (i = 0; i < 4; i++)
01398 P2PF(bez->list[bez->size - 4 + i], c[i]);
01399 pf = Bezier(c, 3, 0.9, NULL, NULL);
01400 }
01401 }
01402 angle = atan2(pf.y - p.y, pf.x - p.x) +
01403 RADIANS(late_double(e, E_labelangle, PORT_LABEL_ANGLE, -180.0));
01404 dist = PORT_LABEL_DISTANCE * late_double(e, E_labeldistance, 1.0, 0.0);
01405 l->p.x = p.x + ROUND(dist * cos(angle));
01406 l->p.y = p.y + ROUND(dist * sin(angle));
01407 l->set = TRUE;
01408 }
01409
01410 splines *getsplinepoints(edge_t * e)
01411 {
01412 edge_t *le;
01413 splines *sp;
01414
01415 for (le = e; !(sp = ED_spl(le)) && ED_edge_type(le) != NORMAL;
01416 le = ED_to_orig(le));
01417 if (sp == NULL)
01418 abort();
01419 return sp;
01420 }