Class: Pdfrb::Layout::MultiCellTextLayout

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/layout/multi_cell_text_layout.rb

Overview

Multi-cell text layout: flows text across an arbitrary shape defined by a series of horizontal bands. Used for magazine- style layouts where text wraps around images, sidebars, or irregular page regions.

A band is a rectangular region with [x, y, width, height] in PDF coordinates (origin bottom-left). The layouter fills bands top-to-bottom, left-to-right.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bands:, style: Style.new(:base)) ⇒ MultiCellTextLayout

Returns a new instance of MultiCellTextLayout.



16
17
18
19
# File 'lib/pdfrb/layout/multi_cell_text_layout.rb', line 16

def initialize(bands:, style: Style.new(:base))
  @bands = bands
  @style = style
end

Instance Attribute Details

#bandsObject (readonly)

Returns the value of attribute bands.



14
15
16
# File 'lib/pdfrb/layout/multi_cell_text_layout.rb', line 14

def bands
  @bands
end

#styleObject (readonly)

Returns the value of attribute style.



14
15
16
# File 'lib/pdfrb/layout/multi_cell_text_layout.rb', line 14

def style
  @style
end

Instance Method Details

#layout(text) ⇒ Object

Lay out text into the bands. Returns an Array of [band_index, lines] pairs where each line is a Layout::Line.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/pdfrb/layout/multi_cell_text_layout.rb', line 23

def layout(text)
  layouter = TextLayouter.new(@style)
  result = []
  words = text.to_s.split(/(\s+)/)
  current_band = 0
  cursor_height = band_height(current_band)
  current_chunk = +""

  words.each do |word|
    trial = current_chunk + word
    lines = layouter.layout(trial, band_width(current_band))
    total_h = lines.sum { |l| line_height(l) }

    if total_h > cursor_height && current_band < @bands.length - 1
      # Flush current chunk to current band
      result << [current_band, layouter.layout(current_chunk, band_width(current_band))] if current_chunk.length.positive?
      current_band += 1
      cursor_height = band_height(current_band)
      current_chunk = +word
    else
      current_chunk = trial
    end
  end
  result << [current_band, layouter.layout(current_chunk, band_width(current_band))] if current_chunk.length.positive?
  result
end