Class: Marvi::Diagram::Grid
- Inherits:
-
Object
- Object
- Marvi::Diagram::Grid
- 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
-
#initialize ⇒ Grid
constructor
A new instance of Grid.
-
#line(row, col, strokes) ⇒ Object
Add line strokes at a cell, merging with any existing line glyph.
-
#set(row, col, char) ⇒ Object
Place an opaque glyph (box border, label text, arrowhead) that does not participate in stroke merging.
- #to_spans ⇒ Object
Constructor Details
#initialize ⇒ Grid
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_spans ⇒ Object
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 |