Class: Marvi::Diagram::Grid

Inherits:
Object
  • Object
show all
Defined in:
lib/marvi/diagram.rb

Overview

A sparse character canvas that merges box-drawing line strokes so that crossing or joining connectors render as the correct junction glyph.

Constant Summary collapse

STROKE =
{up: 1, down: 2, left: 4, right: 8}.freeze
MASK_TO_CHAR =
{
  1 => "", 2 => "", 3 => "",
  4 => "", 8 => "", 12 => "",
  10 => "", 6 => "", 9 => "", 5 => "",
  11 => "", 7 => "", 14 => "", 13 => "", 15 => ""
}.freeze
CHAR_TO_MASK =
MASK_TO_CHAR.each_with_object({}) do |(mask, char), h|
  # Keep the richest mask for each glyph so re-merging is lossless.
  h[char] = mask if !h.key?(char) || mask > h[char]
end.freeze

Instance Method Summary collapse

Constructor Details

#initializeGrid

Returns a new instance of Grid.



64
65
66
# File 'lib/marvi/diagram.rb', line 64

def initialize
  @cells = {}
end

Instance Method Details

#line(row, col, strokes) ⇒ Object

Add line strokes at a cell, merging with any existing line glyph.



75
76
77
78
79
80
# File 'lib/marvi/diagram.rb', line 75

def line(row, col, strokes)
  mask = strokes.sum { |s| STROKE.fetch(s) }
  existing = @cells[[row, col]]
  mask |= CHAR_TO_MASK[existing] if existing && CHAR_TO_MASK.key?(existing)
  @cells[[row, col]] = MASK_TO_CHAR.fetch(mask)
end

#set(row, col, char) ⇒ Object

Place an opaque glyph (box border, label text, arrowhead) that does not participate in stroke merging.



70
71
72
# File 'lib/marvi/diagram.rb', line 70

def set(row, col, char)
  @cells[[row, col]] = char
end

#to_spansObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/marvi/diagram.rb', line 82

def to_spans
  return [] if @cells.empty?

  rows = @cells.keys.map(&:first)
  cols = @cells.keys.map(&:last)
  (rows.min..rows.max).map do |r|
    buffer = +""
    (cols.min..cols.max).each do |c|
      char = @cells[[r, c]]
      next if char == WIDE_FILLER
      buffer << (char || " ")
    end
    [Span.new(text: buffer.rstrip, color: COLOR)]
  end
end