2
This software may only be used by you under license from AT&T Corp.
3
("AT&T"). A copy of AT&T's Source Code Agreement is available at
4
AT&T's Internet website having the URL:
5
<http://www.research.att.com/sw/tools/graphviz/license/source.html>
6
If you received this software without first entering into a license
7
with AT&T, you have an infringing copy of this software and cannot use
8
it without violating AT&T's intellectual property rights.
19
make_vn_slot(graph_t *g, int r, int pos)
24
v = g->u.rank[r].v = ALLOC(g->u.rank[r].n+2,g->u.rank[r].v,node_t*);
25
for (i = g->u.rank[r].n; i > pos; i--) {
29
n = v[pos] = virtual_node(g);
30
n->u.order = pos; n->u.rank = r;
31
v[++(g->u.rank[r].n)] = NULL;
35
#define HLB 0 /* hard left bound */
36
#define HRB 1 /* hard right bound */
37
#define SLB 2 /* soft left bound */
38
#define SRB 3 /* soft right bound */
40
void findlr(node_t *u, node_t *v, int *lp, int *rp)
43
l = u->u.order; r = v->u.order;
44
if (l > r) {int t = l; l = r; r = t;}
48
void setbounds(node_t *v, int *bounds,int lpos, int rpos)
53
if (v->u.node_type == VIRTUAL) {
55
if (v->u.in.size == 0) { /* flat */
56
assert(v->u.out.size == 2);
57
findlr(v->u.out.list[0]->head,v->u.out.list[1]->head,&l,&r);
58
/* the other flat edge could be to the left or right */
59
if (r <= lpos) bounds[SLB] = bounds[HLB] = ord;
60
else if (l >= rpos) bounds[SRB] = bounds[HRB] = ord;
61
/* could be spanning this one */
62
else if ((l < lpos) && (r > rpos)) ; /* ignore */
63
/* must have intersecting ranges */
65
if ((l < lpos) || ((l == lpos) && (r < rpos)))
67
if ((r > rpos) || ((r == rpos) && (l > lpos)))
72
boolean onleft,onright;
73
onleft = onright = FALSE;
74
for (i = 0; (f = v->u.out.list[i]); i++) {
75
if (f->head->u.order <= lpos) {onleft = TRUE; continue;}
76
if (f->head->u.order >= rpos) {onright = TRUE; continue;}
78
if (onleft && (onright == FALSE)) bounds[HLB] = ord + 1;
79
if (onright && (onleft == FALSE)) bounds[HRB] = ord - 1;
84
int flat_limits(graph_t* g, edge_t* e)
86
int lnode,rnode,r,bounds[4],lpos,rpos,pos;
89
r = e->tail->u.rank - 1;
90
rank = g->u.rank[r].v;
92
rnode = g->u.rank[r].n - 1;
93
bounds[HLB] = bounds[SLB] = lnode - 1;
94
bounds[HRB] = bounds[SRB] = rnode + 1;
95
findlr(e->tail,e->head,&lpos,&rpos);
96
while (lnode <= rnode) {
97
setbounds(rank[lnode],bounds,lpos,rpos);
99
setbounds(rank[rnode],bounds,lpos,rpos);
101
if (bounds[HRB] - bounds[HLB] <= 1) break;
103
if (bounds[HLB] <= bounds[HRB])
104
pos = (bounds[HLB] + bounds[HRB] + 1) / 2;
106
pos = (bounds[SLB] + bounds[SRB] + 1) / 2;
110
void flat_node(edge_t* e)
118
if (e->u.label == NULL) return;
122
place = flat_limits(g,e);
123
/* grab ypos = LL.y of label box before make_vn_slot() */
124
if ((n = g->u.rank[r - 1].v[0]))
125
ypos = n->u.coord.y - g->u.rank[r - 1].ht2;
127
n = g->u.rank[r].v[0];
128
ypos = n->u.coord.y + g->u.rank[r].ht1 + g->u.ranksep;
130
vn = make_vn_slot(g,r-1,place);
131
dimen = e->u.label->dimen;
132
if (g->u.left_to_right) {float f = dimen.x; dimen.x = dimen.y; dimen.y = f;}
133
vn->u.ht = POINTS(dimen.y); h2 = vn->u.ht / 2;
134
vn->u.lw = vn->u.rw = POINTS(dimen.x)/2;
135
vn->u.label = e->u.label;
136
vn->u.coord.y = ypos + h2;
137
ve = virtual_edge(vn,e->tail,e); /* was NULL? */
138
ve->u.tail_port.p.x = -vn->u.lw;
139
ve->u.head_port.p.x = e->tail->u.rw;
140
ve->u.edge_type = FLATORDER;
141
ve = virtual_edge(vn,e->head,e);
142
ve->u.tail_port.p.x = vn->u.rw;
143
ve->u.head_port.p.x = e->head->u.lw;
144
ve->u.edge_type = FLATORDER;
145
/* another assumed symmetry of ht1/ht2 of a label node */
146
if (g->u.rank[r-1].ht1 < h2) g->u.rank[r-1].ht1 = h2;
147
if (g->u.rank[r-1].ht2 < h2) g->u.rank[r-1].ht2 = h2;
150
int flat_edges(graph_t* g)
152
int i,j,reset = FALSE;
156
if ((g->u.rank[0].flat) || (g->u.n_cluster > 0)) {
157
for (i = 0; (n = g->u.rank[0].v[i]); i++) {
158
for (j = 0; (e = n->u.flat_in.list[j]); j++) {
159
if (e->u.label) {abomination(g); break;}
166
for (n = g->u.nlist; n; n = n->u.next) {
167
if (n->u.flat_out.list) for (i = 0; (e = n->u.flat_out.list[i]); i++) {
172
if (reset) rec_reset_vlists(g);
176
void abomination(graph_t* g)
181
assert(g->u.minrank == 0);
182
/* 3 = one for new rank, one for sentinel, one for off-by-one */
183
r = g->u.maxrank + 3;
184
rptr = ALLOC(r,g->u.rank,rank_t);
185
g->u.rank = rptr + 1;
186
for (r = g->u.maxrank; r >= 0; r--)
187
g->u.rank[r] = g->u.rank[r-1];
188
g->u.rank[r].n = g->u.rank[0].an = 0;
189
g->u.rank[r].v = g->u.rank[0].av = N_NEW(2,node_t*);
190
g->u.rank[r].flat = NULL;
191
g->u.rank[r].ht1 = g->u.rank[r].ht2 = 1;
192
g->u.rank[r].pht1 = g->u.rank[r].pht2 = 1;