Class: Canopus::WrapMap

Inherits:
Object
  • Object
show all
Defined in:
lib/canopus/wrap_map.rb,
sig/display_stages.rbs

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width: nil, font: nil, font_size: 14, font_paths: nil, typesetter: nil) ⇒ WrapMap

Returns a new instance of WrapMap.

Parameters:

  • width: (Numeric, nil) (defaults to: nil)
  • font: (Alhena::Font, nil) (defaults to: nil)
  • font_size: (Numeric) (defaults to: 14)
  • font_paths: (Array[String], nil) (defaults to: nil)
  • typesetter: (Zaniah::TextSystem::Typesetter, nil) (defaults to: nil)

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/canopus/wrap_map.rb', line 6

def initialize(width: nil, font: nil, font_size: 14, font_paths: nil, typesetter: nil)
  raise ArgumentError, "use typesetter or font/font_paths, not both" if typesetter && (font || font_paths)
  font ||= typesetter&.font
  valid = font ? width.is_a?(Numeric) && width.finite? && width.positive? : width.is_a?(Integer) && width.positive?
  raise ArgumentError, "wrap width must be positive" if width && !valid
  raise ArgumentError, "font size must be finite and positive" unless font_size.is_a?(Numeric) && font_size.finite? && font_size.positive?
  @width, @font, @font_size = width, font, font_size
  @font_paths = font_paths&.frozen? ? font_paths : font_paths&.dup&.freeze
  @typesetter, @typesetters = typesetter, {}
  if @font
    @layout_template = if typesetter
      typesetter.fork(capacity: 32)
    else
      Zaniah::TextSystem::Typesetter.new(
        font: Alhena::Font.new(@font.data, index: @font.index, axes: @font.axis_values),
        font_db: Zaniah::TextSystem::FontDB.new(paths: @font_paths), capacity: 32,
        shaper: :native, segmenter: :native)
    end
  end
end

Instance Attribute Details

#font ⇒ Zaniah::TextSystem::_Font? (readonly)

Returns the value of attribute font.

Returns:

  • (Zaniah::TextSystem::_Font, nil)


5
6
7
# File 'lib/canopus/wrap_map.rb', line 5

def font
  @font
end

#font_paths ⇒ Array[String]? (readonly)

Returns the value of attribute font_paths.

Returns:

  • (Array[String], nil)


5
6
7
# File 'lib/canopus/wrap_map.rb', line 5

def font_paths
  @font_paths
end

#font_size ⇒ Numeric (readonly)

Returns the value of attribute font_size.

Returns:

  • (Numeric)


5
6
7
# File 'lib/canopus/wrap_map.rb', line 5

def font_size
  @font_size
end

#typesetter ⇒ Zaniah::TextSystem::Typesetter? (readonly)

Returns the value of attribute typesetter.

Returns:

  • (Zaniah::TextSystem::Typesetter, nil)


5
6
7
# File 'lib/canopus/wrap_map.rb', line 5

def typesetter
  @typesetter
end

#width ⇒ Numeric? (readonly)

Returns the value of attribute width.

Returns:

  • (Numeric, nil)


5
6
7
# File 'lib/canopus/wrap_map.rb', line 5

def width
  @width
end

Instance Method Details

#close ⇒ void

This method returns an undefined value.



50
51
52
53
54
55
# File 'lib/canopus/wrap_map.rb', line 50

def close
  @typesetters.each_value(&:close)
  @typesetters.clear
  @layout_template&.close
  @layout_template = nil
end

#transform(text, offsets, checkpoint: nil, overlays: [], tab_map: nil) ⇒ Array[([String, Array[Integer]] | [String, Array[Integer], Array[DisplayMap::OverlayMap::Inline]])]

Parameters:

  • text (String)
  • offsets (Array[Integer])
  • checkpoint: (^() -> void, nil) (defaults to: nil)
  • overlays: (Array[DisplayMap::OverlayMap::Inline]) (defaults to: [])
  • tab_map: (TabMap, nil) (defaults to: nil)

Returns:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/canopus/wrap_map.rb', line 26

def transform(text, offsets, checkpoint: nil, overlays: [], tab_map: nil)
  text, offsets, overlays = tab_map.transform(text, offsets, checkpoint: checkpoint, overlays: overlays) if tab_map
  return overlay_rows(text, offsets, overlays, checkpoint) unless overlays.empty?
  return pixel_rows(text, offsets, checkpoint) if @width && @font
  return [[text.freeze, offsets.freeze]] if !@width || (text.ascii_only? && text.length <= @width)
  rows, offset, chunk, positions, cells = [], 0, +"", [offsets.first], 0
  text.each_grapheme_cluster do |grapheme|
    checkpoint&.call if (offset & 1023).zero?
    advance = grapheme.ascii_only? ? grapheme.length : Zaniah::Unicode.width(grapheme)
    if !chunk.empty? && cells + advance > @width
      rows << [chunk.freeze, positions.freeze]
      chunk, positions, cells = +"", [offsets[offset]], 0
    end
    chunk << grapheme
    cells += advance
    grapheme.length.times do
      checkpoint&.call if (offset & 1023).zero?
      offset += 1
      positions << offsets[offset]
    end
  end
  rows << [chunk.freeze, positions.freeze]
  rows
end