metasm/gui/dasm_graph.rb in metasm-1.0.3 vs metasm/gui/dasm_graph.rb in metasm-1.0.4

- old
+ new

@@ -76,10 +76,31 @@ while head.to.length == 1 and head.to[0].from.length == 1 head = head.to[0] ar << head end + # recenter boxes (a -> [b, c, d] => center a around b+c+d) + (ar.length - 1).times { |i| + g = ar[i] + gn = ar[i+1] + withchld = g.content.find_all { |b| not b.to.empty? } + wc = withchld[0] + if withchld.length == 1 and wc.to.length >= 1 and wc.to & gn.content == wc.to + tox = wc.to.map { |b| b.x }.min + toxmax = wc.to.map { |b| b.x + b.w }.max + # dx1: center wc center around (wc.to.xmin + wc.to.xmax)/2 + dx1 = tox + (toxmax-tox)/2 - (wc.x + wc.w/2) + # dx2: center wc center around the mean of the centers of wc.to + dx2 = wc.to.map { |b| b.x + b.w/2 }.inject(0) { |a, b| a+b } / wc.to.length - (wc.x + wc.w/2) + dx = (dx1 + dx2) / 2 + ar.length.times { |j| + ar[j].w += dx + ar[j].content.each { |b| b.x += (j<=i ? dx/2 : -dx/2) } + } + end + } + # move boxes inside this group maxw = ar.map { |g| g.w }.max fullh = ar.inject(0) { |h, g| h + g.h } cury = -fullh/2 ar.each { |g| @@ -156,14 +177,52 @@ dx = curx - g.x g.content.each { |b| b.x += dx ; b.y += dy } curx += g.w } + + # shrink horizontally if possible + (ar.length - 1).times { |i1| + g1 = ar[i1] + g2 = ar[i1+1] + next if g1.content.empty? or g2.content.empty? + # only work with full groups, dont try to interleave gaps + # see if all of one's boxes can be slightly moved inside the other + g1ymin = g1.content.map { |b| b.y - 9 }.min + g1ymax = g1.content.map { |b| b.y + b.h + 9 }.max + g2ymin = g2.content.map { |b| b.y - 9 }.min + g2ymax = g2.content.map { |b| b.y + b.h + 9 }.max + g1_matchg2 = g1.content.find_all { |b| b.y + b.h > g2ymin and b.y < g2ymax } + g2_matchg1 = g2.content.find_all { |b| b.y + b.h > g1ymin and b.y < g1ymax } + if g1_matchg2.length > 0 and g2_matchg1.length > 0 + g1_up = g1.content.find_all { |b| b.y + b.h < g2ymin } + g1_down = g1.content.find_all { |b| b.y > g2ymax } + g2_up = g2.content.find_all { |b| b.y + b.h < g1ymin } + g2_down = g2.content.find_all { |b| b.y > g1ymax } + # avoid moving into an arrow + xmin = g1_matchg2.map { |b| b.x + b.w + 8 }.max + xmax = g2_matchg1.map { |b| b.x - 8 }.min + if g1_up.length > 0 and g1_down.length > 0 + xmin = [xmin, g1_up.map { |b| b.x + b.w/2 + 8 }.max, g1_down.map { |b| b.x + b.w/2 + 8 }.max].max + end + if g2_up.length > 0 and g2_down.length > 0 + xmax = [xmax, g2_up.map { |b| b.x + b.w/2 + 8 }.min, g2_down.map { |b| b.x + b.w/2 + 8 }.min].min + end + dx = xmax - xmin + if dx > 0 + ar.length.times { |i2| + ar[i2].content.each { |b| b.x += (i1 >= i2 ? dx/2 : -dx/2) } + } + end + end + } + # add a 'margin-top' proportionnal to the ar width # this gap should be relative to the real boxes and not possible previous gaps when # merging lines (eg long line + many if patterns -> dont duplicate gaps) boxen = ar.map { |g| g.content }.flatten + fullw = boxen.map { |g| g.x + g.w + 8 }.max - boxen.map { |g| g.x - 8 }.min realh = boxen.map { |g| g.y + g.h }.max - boxen.map { |g| g.y }.min if maxh < realh + fullw/4 maxh = realh + fullw/4 end @@ -638,11 +697,11 @@ # init group.to/from # must always point to something that is in the 'groups' array # no self references # a box is in one and only one group in 'groups' @groups.each { |g| - g.to = g.content.first.to.map { |t| h[t] if t != g }.compact - g.from = g.content.first.from.map { |f| h[f] if f != g }.compact + g.to = g.content.first.to.map { |t| h[t] if h[t] != g }.compact + g.from = g.content.first.from.map { |f| h[f] if h[f] != g }.compact } # order boxes order = order_graph(@groups)