Mercurial > hg > camir-aes2014
comparison toolboxes/graph_visualisation/lib/lefty/dotty_layout.lefty @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 # | |
2 # dotty_layout: layout functions and data structures | |
3 # | |
4 dotty.grablserver = function (lserver) { | |
5 local fd; | |
6 | |
7 if (~dotty.lservers[lserver] | tablesize (dotty.lservers[lserver]) == 0) { | |
8 if (~((fd = openio ('pipe', lserver, 'r+', '%e -Txdot')) >= 0)) { | |
9 dotty.message (0, concat ('cannot start ', lserver)); | |
10 return null; | |
11 } | |
12 dotty.lservers[lserver][fd] = [ | |
13 'fd' = fd; | |
14 'count' = 0; | |
15 ]; | |
16 } | |
17 for (fd in dotty.lservers[lserver]) { | |
18 dotty.lservers[lserver][fd].count = dotty.lservers[ | |
19 lserver | |
20 ][fd].count + 1; | |
21 dotty.lservers.inuse[fd] = dotty.lservers[lserver][fd]; | |
22 remove (fd, dotty.lservers[lserver]); | |
23 return fd; | |
24 } | |
25 }; | |
26 dotty.releaselserver = function (lserver, fd, state) { | |
27 if (state == 'bad' | dotty.lservers.inuse[fd].count > 40) { | |
28 closeio (fd, 'kill'); | |
29 remove (fd, dotty.lservers.inuse); | |
30 return; | |
31 } | |
32 dotty.lservers[lserver][fd] = dotty.lservers.inuse[fd]; | |
33 remove (fd, dotty.lservers.inuse); | |
34 }; | |
35 dotty.protogt.startlayout = function (gt) { | |
36 local lpt, fd; | |
37 | |
38 if (gt.layoutpending >= 1) { | |
39 lpt = dotty.layoutpending[gt.gtid]; | |
40 if (gt.layoutmode == 'async') | |
41 monitor ('off', lpt.fd); | |
42 dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); | |
43 remove (gt.gtid, dotty.layoutpending); | |
44 gt.layoutpending = 0; | |
45 gt.haveinput = 0; | |
46 dotty.popbusy (gt, gt.views); | |
47 } | |
48 if (~((fd = dotty.grablserver (gt.lserver)) >= 0)) | |
49 return null; | |
50 dotty.pushbusy (gt, gt.views); | |
51 writegraph (fd, gt.graph, 1); | |
52 gt.layoutpending = 1; | |
53 dotty.layoutpending[gt.gtid] = [ | |
54 'fd' = fd; | |
55 'gtid' = gt.gtid; | |
56 ]; | |
57 if (gt.layoutmode == 'async') | |
58 monitor ('on', fd); | |
59 return 1; | |
60 }; | |
61 dotty.protogt.finishlayout = function (gt) { | |
62 local graph, lpt, fd; | |
63 | |
64 if (~(gt.layoutpending >= 1)) { | |
65 dotty.message (0, concat ('no layout pending for graph ', gt.gtid)); | |
66 return null; | |
67 } | |
68 lpt = dotty.layoutpending[gt.gtid]; | |
69 if (~(graph = readgraph (lpt.fd))) { | |
70 if (gt.layoutmode == 'async') | |
71 monitor ('off', lpt.fd); | |
72 dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); | |
73 if (gt.layoutpending == 2) { | |
74 dotty.message (0, concat ('giving up on ', gt.lserver)); | |
75 if ((fd = openio ('file', 'dottybug.dot', 'w+')) >= 0) { | |
76 writegraph (fd, gt.graph, 0); | |
77 closeio (fd); | |
78 dotty.message ( | |
79 0, concat ('graph that causes ', gt.lserver) | |
80 ); | |
81 dotty.message ( | |
82 0, 'to fail has been saved in file dottybug.dot' | |
83 ); | |
84 dotty.message ( | |
85 0, 'please fill out a bug report at' | |
86 ); | |
87 dotty.message ( | |
88 0, 'http://www.graphviz.org/bugs/bugform.html' | |
89 ); | |
90 } | |
91 dotty.popbusy (gt, gt.views); | |
92 gt.layoutpending = 0; | |
93 gt.haveinput = 0; | |
94 return 1; | |
95 } | |
96 dotty.message ( | |
97 1, concat ('lost connection to ', gt.lserver, ', restarting...') | |
98 ); | |
99 lpt.fd = dotty.grablserver (gt.lserver); | |
100 writegraph (lpt.fd, gt.graph, 1); | |
101 if (gt.layoutmode == 'async') | |
102 monitor ('on', lpt.fd); | |
103 gt.layoutpending = 2; | |
104 gt.haveinput = 0; | |
105 return null; | |
106 } | |
107 if (gt.layoutmode == 'async') | |
108 monitor ('off', lpt.fd); | |
109 dotty.releaselserver (gt.lserver, lpt.fd, null); | |
110 remove (gt.gtid, dotty.layoutpending); | |
111 gt.layoutpending = 0; | |
112 gt.haveinput = 0; | |
113 gt.unpacklayout (gt, graph); | |
114 dotty.popbusy (gt, gt.views); | |
115 return 1; | |
116 }; | |
117 dotty.protogt.cancellayout = function (gt) { | |
118 local lpt, vid; | |
119 | |
120 if (gt.layoutpending >= 1) { | |
121 lpt = dotty.layoutpending[gt.gtid]; | |
122 if (gt.layoutmode == 'async') | |
123 monitor ('off', lpt.fd); | |
124 dotty.releaselserver (gt.lserver, lpt.fd, 'bad'); | |
125 remove (gt.gtid, dotty.layoutpending); | |
126 gt.layoutpending = 0; | |
127 gt.haveinput = 0; | |
128 dotty.popbusy (gt, gt.views); | |
129 } | |
130 }; | |
131 dotty.protogt.unpacklayout = function (gt, graph2) { | |
132 local graph, gid, sgraph1, sgraph2, nid, node1, node2, eid, edge1, edge2; | |
133 local t1, pos, size; | |
134 | |
135 graph = gt.graph; | |
136 for (gid in graph2.graphdict) { | |
137 if (~(sgraph1 = graph.graphs[graph.graphdict[gid]])) | |
138 continue; | |
139 sgraph2 = graph2.graphs[graph2.graphdict[gid]]; | |
140 sgraph1.draws = gt.unpackalldraw (gt, sgraph2.graphattr); | |
141 } | |
142 for (nid in graph2.nodedict) { | |
143 if (~(node1 = graph.nodes[graph.nodedict[nid]])) | |
144 continue; | |
145 node2 = graph2.nodes[graph2.nodedict[nid]]; | |
146 node1.draws = gt.unpackalldraw (gt, node2.attr); | |
147 t1 = split (node2.attr.pos, ','); | |
148 pos = ['x' = ston (t1[0]); 'y' = ston (t1[1]);]; | |
149 size = [ | |
150 'x' = ston (node2.attr.width) * 72; | |
151 'y' = ston (node2.attr.height) * 72; | |
152 ]; | |
153 node1.pos = pos; | |
154 node1.size = size; | |
155 node1.rect = [ | |
156 0 = ['x' = pos.x - size.x / 2; 'y' = pos.y - size.y / 2;]; | |
157 1 = ['x' = pos.x + size.x / 2; 'y' = pos.y + size.y / 2;]; | |
158 ]; | |
159 } | |
160 for (eid in graph2.edges) { | |
161 edge2 = graph2.edges[eid]; | |
162 if (edge2.attr.id) { | |
163 if (~(edge1 = graph.edges[ston (edge2.attr.id)])) | |
164 continue; | |
165 } else if (graph == graph2) | |
166 edge1 = edge2; | |
167 edge1.draws = gt.unpackalldraw (gt, edge2.attr); | |
168 } | |
169 graph.draws = gt.unpackalldraw (gt, graph2.graphattr); | |
170 t1 = split (graph2.graphattr.bb, ','); | |
171 graph.rect[0].x = ston (t1[0]); | |
172 graph.rect[0].y = ston (t1[1]); | |
173 graph.rect[1].x = ston (t1[2]); | |
174 graph.rect[1].y = ston (t1[3]); | |
175 if (gt.graph ~= graph2) | |
176 return; | |
177 # strip position and size info from the attributes | |
178 for (gid in graph2.graphdict) { | |
179 sgraph2 = graph2.graphs[graph2.graphdict[gid]]; | |
180 gt.removealldraw (gt, sgraph2.graphattr); | |
181 if (sgraph2.graphattr.bb) | |
182 remove ('bb', sgraph2.graphattr); | |
183 } | |
184 for (nid in graph2.nodedict) { | |
185 node2 = graph2.nodes[graph2.nodedict[nid]]; | |
186 gt.removealldraw (gt, node2.attr); | |
187 if (node2.attr.rects) | |
188 remove ('rects', node2.attr); | |
189 remove ('pos', node2.attr); | |
190 remove ('width', node2.attr); | |
191 remove ('height', node2.attr); | |
192 } | |
193 for (eid in graph2.edges) { | |
194 edge2 = graph2.edges[eid]; | |
195 gt.removealldraw (gt, edge2.attr); | |
196 if (edge2.attr.pos) | |
197 remove ('pos', edge2.attr); | |
198 if (edge2.attr.lp) | |
199 remove ('lp', edge2.attr); | |
200 } | |
201 gt.removealldraw (gt, graph2.graphattr); | |
202 remove ('bb', graph2.graphattr); | |
203 if (graph2.graphattr.lp) | |
204 remove ('lp', graph2.graphattr); | |
205 }; | |
206 # | |
207 # draw directive parsing | |
208 # | |
209 dotty.protogt.unpackalldraw = function (gt, attr) { | |
210 local o, did; | |
211 | |
212 o = []; | |
213 if (attr._draw_) | |
214 o._draw_ = gt.unpackdraw (gt, attr._draw_); | |
215 if (attr._ldraw_) | |
216 o._ldraw_ = gt.unpackdraw (gt, attr._ldraw_); | |
217 if (attr._hdraw_) | |
218 o._hdraw_ = gt.unpackdraw (gt, attr._hdraw_); | |
219 if (attr._tdraw_) | |
220 o._tdraw_ = gt.unpackdraw (gt, attr._tdraw_); | |
221 if (attr._hldraw_) | |
222 o._hldraw_ = gt.unpackdraw (gt, attr._hldraw_); | |
223 if (attr._tldraw_) | |
224 o._tldraw_ = gt.unpackdraw (gt, attr._tldraw_); | |
225 for (did in o) | |
226 if (o[did].ep) { | |
227 o.ep = o[did].ep; | |
228 break; | |
229 } | |
230 return o; | |
231 }; | |
232 dotty.protogt.removealldraw = function (gt, attr) { | |
233 if (attr._draw_) | |
234 remove ('_draw_', attr); | |
235 if (attr._ldraw_) | |
236 remove ('_ldraw_', attr); | |
237 if (attr._hdraw_) | |
238 remove ('_hdraw_', attr); | |
239 if (attr._tdraw_) | |
240 remove ('_tdraw_', attr); | |
241 if (attr._hldraw_) | |
242 remove ('_hldraw_', attr); | |
243 if (attr._tldraw_) | |
244 remove ('_tldraw_', attr); | |
245 }; | |
246 dotty.protogt.unpackdraw = function (gt, attr) { | |
247 local oo, o, tt, t, n, i, j, s, l, ep; | |
248 | |
249 oo = []; | |
250 t = split (attr, ' ', 0); | |
251 n = tablesize (t); | |
252 if (t[n - 1] == '') { | |
253 remove (n - 1, t); | |
254 n = n - 1; | |
255 } | |
256 i = 0; | |
257 while (i < n) { | |
258 o = []; | |
259 if (t[i] == 'E') { | |
260 o.type = t[i]; | |
261 o.c.x = ston (t[i + 1]); | |
262 o.c.y = ston (t[i + 2]); | |
263 o.s.x = ston (t[i + 3]); | |
264 o.s.y = ston (t[i + 4]); | |
265 i = i + 5; | |
266 } else if (t[i] == 'e') { | |
267 o.type = t[i]; | |
268 o.c.x = ston (t[i + 1]); | |
269 o.c.y = ston (t[i + 2]); | |
270 o.s.x = ston (t[i + 3]); | |
271 o.s.y = ston (t[i + 4]); | |
272 i = i + 5; | |
273 } else if (t[i] == 'P') { | |
274 o.type = t[i]; | |
275 o.n = ston (t[i + 1]); | |
276 for (j = 0; j < o.n; j = j + 1) { | |
277 o.ps[j].x = ston (t[i + 2 + j * 2]); | |
278 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); | |
279 } | |
280 i = i + 2 + o.n * 2; | |
281 o.ps[o.n] = o.ps[0]; | |
282 o.n = o.n + 1; | |
283 } else if (t[i] == 'p') { | |
284 o.type = t[i]; | |
285 o.n = ston (t[i + 1]); | |
286 for (j = 0; j < o.n; j = j + 1) { | |
287 o.ps[j].x = ston (t[i + 2 + j * 2]); | |
288 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); | |
289 } | |
290 i = i + 2 + o.n * 2; | |
291 o.ps[o.n] = o.ps[0]; | |
292 o.n = o.n + 1; | |
293 } else if (t[i] == 'L') { | |
294 o.type = t[i]; | |
295 o.n = ston (t[i + 1]); | |
296 for (j = 0; j < o.n; j = j + 1) { | |
297 o.ps[j].x = ston (t[i + 2 + j * 2]); | |
298 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); | |
299 } | |
300 i = i + 2 + o.n * 2; | |
301 if (~ep) | |
302 ep = copy (o.ps[1]); | |
303 } else if (t[i] == 'B') { | |
304 o.type = t[i]; | |
305 o.n = ston (t[i + 1]); | |
306 for (j = 0; j < o.n; j = j + 1) { | |
307 o.ps[j].x = ston (t[i + 2 + j * 2]); | |
308 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); | |
309 } | |
310 i = i + 2 + o.n * 2; | |
311 if (~ep) | |
312 ep = copy (o.ps[1]); | |
313 } else if (t[i] == 'b') { | |
314 o.type = t[i]; | |
315 o.n = ston (t[i + 1]); | |
316 for (j = 0; j < o.n; j = j + 1) { | |
317 o.ps[j].x = ston (t[i + 2 + j * 2]); | |
318 o.ps[j].y = ston (t[i + 2 + j * 2 + 1]); | |
319 } | |
320 i = i + 2 + o.n * 2; | |
321 if (~ep) | |
322 ep = copy (o.ps[1]); | |
323 } else if (t[i] == 'T') { | |
324 o.type = t[i]; | |
325 o.p.x = ston (t[i + 1]); | |
326 o.p.y = ston (t[i + 2]); | |
327 o.j = ston (t[i + 3]); | |
328 if (o.j == -1) | |
329 o.j = 'lb'; | |
330 else if (o.j == 1) | |
331 o.j = 'rb'; | |
332 else if (o.j == 0) | |
333 o.j = 'cb'; | |
334 o.w = ston (t[i + 4]); | |
335 o.n = ston (t[i + 5]); | |
336 i = i + 6; | |
337 s = t[i]; | |
338 i = i + 1; | |
339 l = strlen (s) - 1; | |
340 while (l < o.n) { | |
341 s = concat (s, ' ', t[i]); | |
342 l = l + 1 + strlen (t[i]); | |
343 i = i + 1; | |
344 } | |
345 tt = split (s, ''); | |
346 l = tablesize (tt); | |
347 s = ''; | |
348 for (j = 1; j < l; j = j + 1) | |
349 s = concat (s, tt[j]); | |
350 o.s = s; | |
351 } else if (t[i] == 'C') { | |
352 o.type = t[i]; | |
353 o.n = ston (t[i + 1]); | |
354 i = i + 2; | |
355 s = t[i]; | |
356 i = i + 1; | |
357 l = strlen (s) - 1; | |
358 while (l < o.n) { | |
359 s = concat (s, ' ', t[i]); | |
360 l = l + 1 + strlen (t[i]); | |
361 i = i + 1; | |
362 } | |
363 tt = split (s, ''); | |
364 l = tablesize (tt); | |
365 s = ''; | |
366 for (j = 1; j < l; j = j + 1) | |
367 s = concat (s, tt[j]); | |
368 o.fillcolor = gt.getcolor (gt.views, s); | |
369 } else if (t[i] == 'c') { | |
370 o.type = t[i]; | |
371 o.n = ston (t[i + 1]); | |
372 i = i + 2; | |
373 s = t[i]; | |
374 i = i + 1; | |
375 l = strlen (s) - 1; | |
376 while (l < o.n) { | |
377 s = concat (s, ' ', t[i]); | |
378 l = l + 1 + strlen (t[i]); | |
379 i = i + 1; | |
380 } | |
381 tt = split (s, ''); | |
382 l = tablesize (tt); | |
383 s = ''; | |
384 for (j = 1; j < l; j = j + 1) | |
385 s = concat (s, tt[j]); | |
386 o.drawcolor = gt.getcolor (gt.views, s); | |
387 } else if (t[i] == 'F') { | |
388 o.type = t[i]; | |
389 o.fs = ston (t[i + 1]); | |
390 o.n = ston (t[i + 2]); | |
391 i = i + 3; | |
392 s = t[i]; | |
393 i = i + 1; | |
394 l = strlen (s) - 1; | |
395 while (l < o.n) { | |
396 s = concat (s, ' ', t[i]); | |
397 l = l + 1 + strlen (t[i]); | |
398 i = i + 1; | |
399 } | |
400 tt = split (s, ''); | |
401 l = tablesize (tt); | |
402 s = ''; | |
403 for (j = 1; j < l; j = j + 1) | |
404 s = concat (s, tt[j]); | |
405 o.ofn = s; | |
406 o.fn = dotty.fontmap[s]; | |
407 } else if (t[i] == 'S') { | |
408 o.type = t[i]; | |
409 o.n = ston (t[i + 1]); | |
410 i = i + 2; | |
411 s = t[i]; | |
412 i = i + 1; | |
413 l = strlen (s) - 1; | |
414 while (l < o.n) { | |
415 s = concat (s, ' ', t[i]); | |
416 l = l + 1 + strlen (t[i]); | |
417 i = i + 1; | |
418 } | |
419 tt = split (s, ''); | |
420 l = tablesize (tt); | |
421 s = ''; | |
422 for (j = 1; j < l; j = j + 1) | |
423 s = concat (s, tt[j]); | |
424 if ( | |
425 s == 'solid' | s == 'dashed' | s == 'dotted' | | |
426 s == 'longdashed' | s == 'shortdashed' | |
427 ) | |
428 o.style = s; | |
429 else if (s == 'bold') | |
430 o.width = 3; | |
431 else { | |
432 tt = split (s, '('); | |
433 if (tt[0] == 'setlinewidth') { | |
434 tt = split (tt[1], ')'); | |
435 o.width = ston (tt[0]); | |
436 } else | |
437 continue; | |
438 } | |
439 } else if (t[i] == 'I') { | |
440 i = i + 7; | |
441 } else { | |
442 dotty.message (0, concat ('draw language parser error: ', t[i])); | |
443 return null; | |
444 } | |
445 oo[tablesize (oo)] = o; | |
446 } | |
447 oo.ep = ep; | |
448 return oo; | |
449 }; |