diagrammatron 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 393c2881f870f2371e5af2e9a33fcfac3f82d9c3da69f7f377d87606b7230557
4
- data.tar.gz: '019f726f35066af4fc209d61a2adbf36de1c6393d0089924912ca6c0e73baef0'
3
+ metadata.gz: 7f4b7974989ef344d2eaaae0c54f82567b8ed9edd9c7fb5d2dfc3e405895efa7
4
+ data.tar.gz: efdd52da27d648f9da7fed309ba668eae6237eeddd51a703c47c46c45c394435
5
5
  SHA512:
6
- metadata.gz: 737105dcbe2c8dc6d636833079d2313be3b5f2c66d86d252127664948365b92f976622b65019e9b5ddd1f7b760f35a15fef9e30fdd749fae99441a31fb03bb8e
7
- data.tar.gz: c091a6a5f862353afb8f730dbf8b35cf226c5627e6d352f1ad8366ca6d03cb338e61264c22876948806afdc0965f1df0ee81223f07750f61c73a8cd171ab0538
6
+ metadata.gz: e235a20fb0fb4013e4f0006731743830f84500519d2ab4262b04caa9bae0962bd7da5127cd30e44c9e6bf891b735a02f10fe193149047fa6b54ec0bd6185f2e5
7
+ data.tar.gz: e6c4c3db889c83d23390ee874379215747fb4336fbb3f1f2f543226ab72788fe948a6394e500ea89ed4d4a013126a324b10fa5b49bf73be9233cd94e9781a024
@@ -158,6 +158,10 @@ Segment = Struct.new(:vertical, :cc, :range, :edge_index, :at_node, :segment_ind
158
158
  def increase?
159
159
  range[0] < range[1]
160
160
  end
161
+
162
+ def within(s)
163
+ s.range.min < range.min && range.max < s.range.max
164
+ end
161
165
  end
162
166
 
163
167
  def segment(x0, y0, x1, y1)
@@ -415,40 +419,16 @@ def path_order_at_side(a, b, conn)
415
419
  d
416
420
  end
417
421
 
418
- def segment_order(a, b)
419
- d = a[1] <=> b[1]
422
+ def length_order(a, b)
423
+ d = a[2].length <=> b[2].length
420
424
  return d unless d.zero?
421
- case a[1]
422
- when 0 # Ascending on length, range minimum. =|
423
- d = a[2].length <=> b[2].length
424
- return d unless d.zero?
425
- d = a[2].range.min <=> b[2].range.min
426
- return d unless d.zero?
427
- when 1 # Top left, vertical, bottom right: -|_
428
- d = a[2].range.min <=> b[2].range.min # Ascend on minimum.
429
- return d unless d.zero?
430
- d = a[2].length <=> b[2].length # Ascend on length.
431
- return d unless d.zero?
432
- when 2 # From top right, down, bottom left: _|-
433
- d = a[2].range.max <=> b[2].range.max # Descend on maximum.
434
- return -d unless d.zero?
435
- d = a[2].length <=> b[2].length # Ascend on length.
436
- return d unless d.zero?
437
- when 3 # Descending on length, range maximum. |=
438
- d = a[2].length <=> b[2].length
439
- return -d unless d.zero?
440
- d = a[2].range.max <=> b[2].range.max
441
- return -d unless d.zero?
442
- end
443
425
  a[0].edge_index <=> b[0].edge_index
444
426
  end
445
427
 
446
- def zigzag_order(from_right_up_to_left, from_left_up_to_right)
447
- # Eventually interleave the two sets, if it makes sense.
448
- out = []
449
- from_right_up_to_left.each { |x| out.push x }
450
- from_left_up_to_right.each { |x| out.push x }
451
- out
428
+ def min_order(a, b)
429
+ d = a[2].range.min <=> b[2].range.min
430
+ return d unless d.zero?
431
+ a[0].edge_index <=> b[0].edge_index
452
432
  end
453
433
 
454
434
  def overlaps_set(c, others)
@@ -458,47 +438,59 @@ def overlaps_set(c, others)
458
438
  false
459
439
  end
460
440
 
461
- def group_minimal_offsets(group)
462
- return 0 if group.empty?
463
- off = { 1 => [] }
464
- cands = off.keys
465
- group.each do |a|
466
- fit = false
467
- cands.each do |k|
468
- next if overlaps_set(a[2], off[k])
469
- off[k].push(a)
470
- fit = true
471
- break
441
+ def layered_order(u_shaped, z_shaped)
442
+ u_shaped.sort! { |a, b| length_order(a, b) }
443
+ z_shaped.sort! { |a, b| min_order(a, b) }
444
+ out = []
445
+ layer = []
446
+ until u_shaped.empty?
447
+ rejects = []
448
+ found = false
449
+ u_shaped.each do |a|
450
+ unless overlaps_set(a[2], layer)
451
+ found = true
452
+ # Creates crossing by putting in front of shorter segment fully within?
453
+ rejects.each do |r|
454
+ if r[2].within(a[2])
455
+ found = false
456
+ break
457
+ end
458
+ end
459
+ end
460
+ if found
461
+ layer.push a
462
+ found = false
463
+ else
464
+ rejects.push a
465
+ end
466
+ end
467
+ u_shaped = rejects
468
+ unless layer.empty?
469
+ out.concat layer
470
+ out.push nil
471
+ layer = []
472
472
  end
473
- next if fit
474
- cands.push(cands.last + 1)
475
- off[cands.last] = [ a ]
476
473
  end
477
- off.each_pair do |offset, fitting|
478
- fitting.each do |sg|
479
- sg[0].offset = offset
474
+ until z_shaped.empty?
475
+ rejects = []
476
+ found = false
477
+ z_shaped.each do |a|
478
+ if overlaps_set(a[2], layer)
479
+ rejects.push a
480
+ else
481
+ layer.push a
482
+ found = true
483
+ end
484
+ end
485
+ z_shaped = rejects
486
+ unless layer.empty?
487
+ out.concat layer
488
+ out.push nil
489
+ layer = []
480
490
  end
481
491
  end
482
- off.keys.max
483
- end
484
-
485
- def group_stacked_offsets(group)
486
- return 0 if group.empty?
487
- group.each_index do |k|
488
- group[k][0].offset = k + 1
489
- end
490
- return group.size
491
- %q(
492
- # This produces narrower gaps but they may be less clear.
493
- prev = group[0]
494
- prev[0].offset = 1
495
- (1...group.size).each do |k|
496
- g = group[k]
497
- g[0].offset = prev[0].offset + (g[2].range_overlap(prev[2]) ? 1 : 0)
498
- prev = g
499
- end
500
- prev[0].offset
501
- )
492
+ out.concat(layer) unless layer.empty?
493
+ out
502
494
  end
503
495
 
504
496
  def direct_range(paths)
@@ -631,36 +623,22 @@ def place_edges(work)
631
623
  end
632
624
  gaps.each_value do |direction|
633
625
  direction.each_value do |gap|
634
- #gap.sort! { |a, b| segment_order(a, b) }
635
626
  gleft = gap.select { |a| a[1].zero? }
636
- gleft.sort! { |a, b| segment_order(a, b) }
627
+ grul = gap.select { |a| a[1] == 1 }
628
+ glur = gap.select { |a| a[1] == 2 }
637
629
  gright = gap.select { |a| a[1] == 3 }
638
- gright.sort! { |a, b| segment_order(a, b) }
639
- gright.reverse!
640
- grul = gap.select() { |a| a[1] == 1 }
641
- grul.sort! { |a, b| segment_order(a, b) }
642
- glur = gap.select() { |a| a[1] == 2 }
643
- glur.sort! { |a, b| segment_order(a, b) }
644
- gmiddle = zigzag_order(grul, glur)
645
- gmiddle.each do |s|
646
- s[1] = 1
647
- end
648
- gap = gleft + gmiddle + gright
649
- c = [
650
- group_minimal_offsets(gleft),
651
- group_stacked_offsets(gmiddle),
652
- 0,
653
- group_minimal_offsets(gright)
654
- ]
655
- before = [ 0 ]
656
- denominator = 1 + c[0]
657
- (1...c.size).each do |k|
658
- denominator += c[k]
659
- before.push(c[k - 1] + before.last)
660
- end
661
- gap.each do |sg|
662
- sg[0].offset = c[sg[1]] + 1 - sg[0].offset if sg[1] > 1
663
- sg[0].offset = Rational(sg[0].offset + before[sg[1]], denominator)
630
+ all = layered_order(gleft, grul)
631
+ all.push nil
632
+ all.concat(layered_order(gright, glur).reverse)
633
+ # Give each rational offset using layer index + 1 and layer count + 2.
634
+ denominator = 2 + all.count { |x| x.nil? }
635
+ layer = 1
636
+ all.each do |sg|
637
+ if sg.nil?
638
+ layer += 1
639
+ else
640
+ sg[0].offset = Rational(layer, denominator)
641
+ end
664
642
  end
665
643
  end
666
644
  end
@@ -80,9 +80,10 @@ class Styles
80
80
  def base_styles(m, styles, group)
81
81
  d = styles.dig(group, 'default')
82
82
  if d.nil?
83
- d = m.fetch('default', {}) if d.nil?
83
+ d = m.fetch('default', {}) # No default in styles.
84
84
  else
85
85
  m['default'] = m.fetch('default', {}).merge(d)
86
+ d = m['default']
86
87
  end
87
88
  styles.fetch(group, {}).each_pair do |name, values|
88
89
  s = d.clone
@@ -280,6 +281,27 @@ def apply(doc, template)
280
281
  out
281
282
  end
282
283
 
284
+ def reverse_depth_order(a, b)
285
+ d = b['depth'] <=> a['depth']
286
+ return d unless d.zero?
287
+ d = a['index'] <=> b['index']
288
+ return d unless d.zero?
289
+ a['kind'] <=> b['kind']
290
+ end
291
+
292
+ def reverse_depth_sort(items)
293
+ arr = []
294
+ items.each_index do |k|
295
+ arr.push({
296
+ 'depth' => items[k].fetch('depth', 0),
297
+ 'index' => k,
298
+ 'kind' => items[k].fetch('kind', 'unknown')
299
+ })
300
+ end
301
+ arr.sort! { |a, b| reverse_depth_order(a, b) }
302
+ arr.map { |x| items[x['index']] }
303
+ end
304
+
283
305
  def main
284
306
  template = nil
285
307
  input = nil
@@ -354,6 +376,30 @@ Output is the file produced by the erb-template.
354
376
  remap_coordinates(xcoords, xmax, x2min, doc.dig('diagram', 'edge_gap'))
355
377
  remap_coordinates(ycoords, ymax, y2min, doc.dig('diagram', 'edge_gap'))
356
378
 
379
+ doc['nodes'] = reverse_depth_sort(doc.fetch('nodes', []))
380
+ doc['edges'] = reverse_depth_sort(doc.fetch('edges', []))
381
+ all = doc.fetch('nodes', []).map do |a|
382
+ {
383
+ 'kind' => 'node',
384
+ 'depth' => a.fetch('depth', 0),
385
+ 'item' => a
386
+ }
387
+ end
388
+ all.concat(doc.fetch('edges', []).map do |a|
389
+ {
390
+ 'kind' => 'edge',
391
+ 'depth' => a.fetch('depth', 0),
392
+ 'item' => a
393
+ }
394
+ end)
395
+ all = reverse_depth_sort(all)
396
+ doc['all'] = all.map do |x|
397
+ {
398
+ 'kind' => x['kind'],
399
+ 'item' => x['item']
400
+ }
401
+ end
402
+
357
403
  dump_result(output, apply(doc, template), 5)
358
404
  end
359
405
 
@@ -19,6 +19,7 @@ styles:
19
19
  fill: "#ffffff"
20
20
  stroke: "#000000"
21
21
  stroke_width: 2
22
+ depth: 0
22
23
  size_estimator: |
23
24
  $render.default_size($render.node['font_size'],
24
25
  $render.node['font_width'], $render.node['font_height'],
@@ -29,4 +30,5 @@ styles:
29
30
  default:
30
31
  stroke_width: 2
31
32
  stroke: "#000000"
32
- base64template: PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwlPQp3LCBoaCA9ICRyZW5kZXIuZGltZW5zaW9ucwpoaCArPSAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnaGVpZ2h0X21hcmdpbicpCgpvdXQgPSBbCiAgJSg8c3ZnIHdpZHRoPSIje3cgKyAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnd2lkdGhfbWFyZ2luJyl9IiBoZWlnaHQ9IiN7aGh9IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiPikKXQokcmVuZGVyLmRvYy5mZXRjaCgnZWRnZXMnLCBbXSkuZWFjaCBkbyB8ZWRnZXwKICBsaW5lc3R5bGUgPSAlKGZpbGw9Im5vbmUiIHN0cm9rZT0iI3tlZGdlWydzdHJva2UnXX0iIHN0cm9rZS13aWR0aD0iI3tlZGdlWydzdHJva2Vfd2lkdGgnXX0iKQogIHBhdGggPSBlZGdlLmZldGNoKCdwYXRoJywgbmlsKQogIG5leHQgaWYgcGF0aC5uaWw/CiAgcGF0aC5lYWNoIGRvIHxwfAogICAgcFsneG8nXSA9IHBbJ3hvJ10udG9faS50b19zCiAgICBwWyd5byddID0gKGhoIC0gcFsneW8nXSkudG9faS50b19zCiAgZW5kCiAgaWYgcGF0aC5zaXplID09IDIKICAgIG91dC5wdXNoKCUoPGxpbmUgI3tsaW5lc3R5bGV9IHgxPSIje3BhdGhbMF1bJ3hvJ119IiB4Mj0iI3twYXRoWzFdWyd4byddfSIgeTE9IiN7cGF0aFswXVsneW8nXX0iIHkyPSIje3BhdGhbMV1bJ3lvJ119Ii8+KSkKICBlbHNlCiAgICBwdHMgPSBwYXRoLm1hcCB7IHxwfCAiI3twWyd4byddfSwje3BbJ3lvJ119IiB9CiAgICBvdXQucHVzaCglKDxwb2x5bGluZSAje2xpbmVzdHlsZX0gcG9pbnRzPSIje3B0cy5qb2luKCcgJyl9Ii8+KSkKICBlbmQKZW5kCiRyZW5kZXIuZG9jLmZldGNoKCdub2RlcycsIFtdKS5lYWNoIGRvIHxub2RlfAogIHcgPSBub2RlWyd3J10udG9faQogIGggPSBub2RlWydoJ10udG9faQogIHggPSBub2RlWyd4byddLnRvX2kKICB5ID0gaGggLSBub2RlWyd5byddLnRvX2kgLSBoCiAgbm9kZXN0eWxlID0gJShmaWxsPSIje25vZGVbJ2ZpbGwnXX0iIHN0cm9rZT0iI3tub2RlWydzdHJva2UnXX0iIHN0cm9rZS13aWR0aD0iI3tub2RlWydzdHJva2Vfd2lkdGgnXX0iKQogIG91dC5wdXNoKCUoPHJlY3QgI3tub2Rlc3R5bGV9IGhlaWdodD0iI3tofSIgd2lkdGg9IiN7d30iIHg9IiN7eH0iIHk9IiN7eX0iLz4pKQogIHggKz0gbm9kZVsnd2lkdGhfbWFyZ2luJ10KICBmcyA9IG5vZGVbJ2ZvbnRfc2l6ZSddCiAgbGggPSBmcyAqICgxICsgbm9kZVsnZm9udF9saW5lX3NwYWNpbmcnXSkKICB5ICs9IG5vZGVbJ2hlaWdodF9tYXJnaW4nXSArIGZzICogbm9kZVsnZm9udF9hc2NlbmQnXSAjIEJhc2VsaW5lIGZvciBmaXJzdCBsaW5lLgogIHVybCA9IG5vZGUuZmV0Y2goJ3VybCcsIG5pbCkKICB1cmwuZW5jb2RlISg6eG1sID0+IDphdHRyKSB1bmxlc3MgdXJsLm5pbD8KICB5MCA9IHkKICB0ZXh0c3R5bGUgPSAlKGZpbGw9IiN7bm9kZVsnZm9udF9maWxsJ119IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iI3tmc30iIHN0cm9rZT0iI3tub2RlWydmb250X2ZpbGwnXX0iIHN0cm9rZS13aWR0aD0iMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIpCiAgbGlua3N0eWxlID0gJShmaWxsPSIje25vZGVbJ3VybF9maWxsJ119IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iI3tmc30iIHN0cm9rZT0iI3tub2RlWyd1cmxfZmlsbCddfSIgc3Ryb2tlLXdpZHRoPSIwIiB4bWw6c3BhY2U9InByZXNlcnZlIikKICBub2RlWyd0ZXh0J10uZWFjaCBkbyB8bGluZXwKICAgIGxpbmUuZW5jb2RlISg6eG1sID0+IDp0ZXh0KQogICAgaWYgdXJsLm5pbD8KICAgICAgb3V0LnB1c2goJSg8dGV4dCAje3RleHRzdHlsZX0geD0iI3t4fSIgeT0iI3t5MH0iPiN7bGluZX08L3RleHQ+KSkKICAgIGVsc2UKICAgICAgb3V0LnB1c2goJSg8YSB4bGluazpocmVmPSN7dXJsfSB0YXJnZXQ9Il9wYXJlbnQiPjx0ZXh0ICN7bGlua3N0eWxlfSB4PSIje3h9IiB5PSIje3kwfSI+I3tsaW5lfTwvdGV4dD48L2E+KSkKICAgIGVuZAogICAgeTAgKz0gbGggIyBTaGlmdCBiYXNlbGluZSBieSBmdWxsIGxpbmUgKyBzcGFjaW5nIGhlaWdodC4KICBlbmQKZW5kCm91dC5qb2luKCJcbiIpCiU+Cjwvc3ZnPgo=
33
+ depth: 0
34
+ base64template: PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwlPQp3LCBoaCA9ICRyZW5kZXIuZGltZW5zaW9ucwpoaCArPSAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnaGVpZ2h0X21hcmdpbicpCgpvdXQgPSBbCiAgJSg8c3ZnIHdpZHRoPSIje3cgKyAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnd2lkdGhfbWFyZ2luJyl9IiBoZWlnaHQ9IiN7aGh9IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiPikKXQokcmVuZGVyLmRvY1snYWxsJ10uZWFjaCBkbyB8aXRlbXwKICBpZiBpdGVtWydraW5kJ10gPT0gJ25vZGUnCiAgICBub2RlID0gaXRlbVsnaXRlbSddCiAgICB3ID0gbm9kZVsndyddLnRvX2kKICAgIGggPSBub2RlWydoJ10udG9faQogICAgeCA9IG5vZGVbJ3hvJ10udG9faQogICAgeSA9IGhoIC0gbm9kZVsneW8nXS50b19pIC0gaAogICAgbm9kZXN0eWxlID0gJShmaWxsPSIje25vZGVbJ2ZpbGwnXX0iIHN0cm9rZT0iI3tub2RlWydzdHJva2UnXX0iIHN0cm9rZS13aWR0aD0iI3tub2RlWydzdHJva2Vfd2lkdGgnXX0iKQogICAgb3V0LnB1c2goJSg8cmVjdCAje25vZGVzdHlsZX0gaGVpZ2h0PSIje2h9IiB3aWR0aD0iI3t3fSIgeD0iI3t4fSIgeT0iI3t5fSIvPikpCiAgICB4ICs9IG5vZGVbJ3dpZHRoX21hcmdpbiddCiAgICBmcyA9IG5vZGVbJ2ZvbnRfc2l6ZSddCiAgICBsaCA9IGZzICogKDEgKyBub2RlWydmb250X2xpbmVfc3BhY2luZyddKQogICAgeSArPSBub2RlWydoZWlnaHRfbWFyZ2luJ10gKyBmcyAqIG5vZGVbJ2ZvbnRfYXNjZW5kJ10gIyBCYXNlbGluZSBmb3IgZmlyc3QgbGluZS4KICAgIHVybCA9IG5vZGUuZmV0Y2goJ3VybCcsIG5pbCkKICAgIHVybC5lbmNvZGUhKDp4bWwgPT4gOmF0dHIpIHVubGVzcyB1cmwubmlsPwogICAgeTAgPSB5CiAgICB0ZXh0c3R5bGUgPSAlKGZpbGw9IiN7bm9kZVsnZm9udF9maWxsJ119IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iI3tmc30iIHN0cm9rZT0iI3tub2RlWydmb250X2ZpbGwnXX0iIHN0cm9rZS13aWR0aD0iMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIpCiAgICBsaW5rc3R5bGUgPSAlKGZpbGw9IiN7bm9kZVsndXJsX2ZpbGwnXX0iIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIje2ZzfSIgc3Ryb2tlPSIje25vZGVbJ3VybF9maWxsJ119IiBzdHJva2Utd2lkdGg9IjAiIHhtbDpzcGFjZT0icHJlc2VydmUiKQogICAgbm9kZVsndGV4dCddLmVhY2ggZG8gfGxpbmV8CiAgICAgIGxpbmUuZW5jb2RlISg6eG1sID0+IDp0ZXh0KQogICAgICBpZiB1cmwubmlsPwogICAgICAgIG91dC5wdXNoKCUoPHRleHQgI3t0ZXh0c3R5bGV9IHg9IiN7eH0iIHk9IiN7eTB9Ij4je2xpbmV9PC90ZXh0PikpCiAgICAgIGVsc2UKICAgICAgICBvdXQucHVzaCglKDxhIHhsaW5rOmhyZWY9I3t1cmx9IHRhcmdldD0iX3BhcmVudCI+PHRleHQgI3tsaW5rc3R5bGV9IHg9IiN7eH0iIHk9IiN7eTB9Ij4je2xpbmV9PC90ZXh0PjwvYT4pKQogICAgICBlbmQKICAgICAgeTAgKz0gbGggIyBTaGlmdCBiYXNlbGluZSBieSBmdWxsIGxpbmUgKyBzcGFjaW5nIGhlaWdodC4KICAgIGVuZAogIGVsc2UKICAgIGVkZ2UgPSBpdGVtWydpdGVtJ10KICAgIGxpbmVzdHlsZSA9ICUoZmlsbD0ibm9uZSIgc3Ryb2tlPSIje2VkZ2VbJ3N0cm9rZSddfSIgc3Ryb2tlLXdpZHRoPSIje2VkZ2VbJ3N0cm9rZV93aWR0aCddfSIpCiAgICBwYXRoID0gZWRnZS5mZXRjaCgncGF0aCcsIG5pbCkKICAgIG5leHQgaWYgcGF0aC5uaWw/CiAgICBwYXRoLmVhY2ggZG8gfHB8CiAgICAgIHBbJ3hvJ10gPSBwWyd4byddLnRvX2kudG9fcwogICAgICBwWyd5byddID0gKGhoIC0gcFsneW8nXSkudG9faS50b19zCiAgICBlbmQKICAgIGlmIHBhdGguc2l6ZSA9PSAyCiAgICAgIG91dC5wdXNoKCUoPGxpbmUgI3tsaW5lc3R5bGV9IHgxPSIje3BhdGhbMF1bJ3hvJ119IiB4Mj0iI3twYXRoWzFdWyd4byddfSIgeTE9IiN7cGF0aFswXVsneW8nXX0iIHkyPSIje3BhdGhbMV1bJ3lvJ119Ii8+KSkKICAgIGVsc2UKICAgICAgcHRzID0gcGF0aC5tYXAgeyB8cHwgIiN7cFsneG8nXX0sI3twWyd5byddfSIgfQogICAgICBvdXQucHVzaCglKDxwb2x5bGluZSAje2xpbmVzdHlsZX0gcG9pbnRzPSIje3B0cy5qb2luKCcgJyl9Ii8+KSkKICAgIGVuZAogIGVuZAplbmQKb3V0LmpvaW4oIlxuIikKJT4KPC9zdmc+Cg==
data/template/root.yaml CHANGED
@@ -18,6 +18,7 @@ styles:
18
18
  fill: "#ffffff"
19
19
  stroke: "#000000"
20
20
  stroke_width: 2
21
+ depth: 0
21
22
  size_estimator: |
22
23
  $render.default_size($render.node['font_size'],
23
24
  $render.node['font_width'], $render.node['font_height'],
@@ -28,3 +29,4 @@ styles:
28
29
  default:
29
30
  stroke_width: 2
30
31
  stroke: "#000000"
32
+ depth: 0
data/template/svg_1.1.erb CHANGED
@@ -6,45 +6,48 @@ hh += $render.doc.dig('diagram', 'height_margin')
6
6
  out = [
7
7
  %(<svg width="#{w + $render.doc.dig('diagram', 'width_margin')}" height="#{hh}" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">)
8
8
  ]
9
- $render.doc.fetch('edges', []).each do |edge|
10
- linestyle = %(fill="none" stroke="#{edge['stroke']}" stroke-width="#{edge['stroke_width']}")
11
- path = edge.fetch('path', nil)
12
- next if path.nil?
13
- path.each do |p|
14
- p['xo'] = p['xo'].to_i.to_s
15
- p['yo'] = (hh - p['yo']).to_i.to_s
16
- end
17
- if path.size == 2
18
- out.push(%(<line #{linestyle} x1="#{path[0]['xo']}" x2="#{path[1]['xo']}" y1="#{path[0]['yo']}" y2="#{path[1]['yo']}"/>))
9
+ $render.doc['all'].each do |item|
10
+ if item['kind'] == 'node'
11
+ node = item['item']
12
+ w = node['w'].to_i
13
+ h = node['h'].to_i
14
+ x = node['xo'].to_i
15
+ y = hh - node['yo'].to_i - h
16
+ nodestyle = %(fill="#{node['fill']}" stroke="#{node['stroke']}" stroke-width="#{node['stroke_width']}")
17
+ out.push(%(<rect #{nodestyle} height="#{h}" width="#{w}" x="#{x}" y="#{y}"/>))
18
+ x += node['width_margin']
19
+ fs = node['font_size']
20
+ lh = fs * (1 + node['font_line_spacing'])
21
+ y += node['height_margin'] + fs * node['font_ascend'] # Baseline for first line.
22
+ url = node.fetch('url', nil)
23
+ url.encode!(:xml => :attr) unless url.nil?
24
+ y0 = y
25
+ textstyle = %(fill="#{node['font_fill']}" font-family="serif" font-size="#{fs}" stroke="#{node['font_fill']}" stroke-width="0" xml:space="preserve")
26
+ linkstyle = %(fill="#{node['url_fill']}" font-family="serif" font-size="#{fs}" stroke="#{node['url_fill']}" stroke-width="0" xml:space="preserve")
27
+ node['text'].each do |line|
28
+ line.encode!(:xml => :text)
29
+ if url.nil?
30
+ out.push(%(<text #{textstyle} x="#{x}" y="#{y0}">#{line}</text>))
31
+ else
32
+ out.push(%(<a xlink:href=#{url} target="_parent"><text #{linkstyle} x="#{x}" y="#{y0}">#{line}</text></a>))
33
+ end
34
+ y0 += lh # Shift baseline by full line + spacing height.
35
+ end
19
36
  else
20
- pts = path.map { |p| "#{p['xo']},#{p['yo']}" }
21
- out.push(%(<polyline #{linestyle} points="#{pts.join(' ')}"/>))
22
- end
23
- end
24
- $render.doc.fetch('nodes', []).each do |node|
25
- w = node['w'].to_i
26
- h = node['h'].to_i
27
- x = node['xo'].to_i
28
- y = hh - node['yo'].to_i - h
29
- nodestyle = %(fill="#{node['fill']}" stroke="#{node['stroke']}" stroke-width="#{node['stroke_width']}")
30
- out.push(%(<rect #{nodestyle} height="#{h}" width="#{w}" x="#{x}" y="#{y}"/>))
31
- x += node['width_margin']
32
- fs = node['font_size']
33
- lh = fs * (1 + node['font_line_spacing'])
34
- y += node['height_margin'] + fs * node['font_ascend'] # Baseline for first line.
35
- url = node.fetch('url', nil)
36
- url.encode!(:xml => :attr) unless url.nil?
37
- y0 = y
38
- textstyle = %(fill="#{node['font_fill']}" font-family="serif" font-size="#{fs}" stroke="#{node['font_fill']}" stroke-width="0" xml:space="preserve")
39
- linkstyle = %(fill="#{node['url_fill']}" font-family="serif" font-size="#{fs}" stroke="#{node['url_fill']}" stroke-width="0" xml:space="preserve")
40
- node['text'].each do |line|
41
- line.encode!(:xml => :text)
42
- if url.nil?
43
- out.push(%(<text #{textstyle} x="#{x}" y="#{y0}">#{line}</text>))
37
+ edge = item['item']
38
+ linestyle = %(fill="none" stroke="#{edge['stroke']}" stroke-width="#{edge['stroke_width']}")
39
+ path = edge.fetch('path', nil)
40
+ next if path.nil?
41
+ path.each do |p|
42
+ p['xo'] = p['xo'].to_i.to_s
43
+ p['yo'] = (hh - p['yo']).to_i.to_s
44
+ end
45
+ if path.size == 2
46
+ out.push(%(<line #{linestyle} x1="#{path[0]['xo']}" x2="#{path[1]['xo']}" y1="#{path[0]['yo']}" y2="#{path[1]['yo']}"/>))
44
47
  else
45
- out.push(%(<a xlink:href=#{url} target="_parent"><text #{linkstyle} x="#{x}" y="#{y0}">#{line}</text></a>))
48
+ pts = path.map { |p| "#{p['xo']},#{p['yo']}" }
49
+ out.push(%(<polyline #{linestyle} points="#{pts.join(' ')}"/>))
46
50
  end
47
- y0 += lh # Shift baseline by full line + spacing height.
48
51
  end
49
52
  end
50
53
  out.join("\n")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diagrammatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismo Kärkkäinen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-31 00:00:00.000000000 Z
11
+ date: 2023-02-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14