Class: Eleanor::Paragraph

Inherits:
Object
  • Object
show all
Defined in:
lib/eleanor.rb,
lib/eleanor/hpdfpaper.rb

Overview

Base Paragraph class from which all paragraphs inherit.

Note that Eleanor.load_config dynamically adds both class and instance methods to Paragraph and its subclasses depending on the options present in the user’s configuration file. See “Configuration” in the README.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(screenplay, input_line, last_character_cue, split_state = :whole) ⇒ Paragraph

A paragraph must be attached to a screenplay. input_line is the line of raw text used to build the paragraph. last_character_cue should be a reference to the last CharacterCue paragraph seen in the input and is used to keep track of Dialog continuations. split_state should be one of :whole, :orphan, or :widow and indicates if the paragraph is intact on one page, split across pages and at the bottom of the first page, or split across pages and at the top of the second page.



114
115
116
117
118
119
120
121
122
123
# File 'lib/eleanor.rb', line 114

def initialize screenplay, input_line, last_character_cue, split_state=:whole
  @screenplay= screenplay
  @last_character_cue= last_character_cue
  @split_state= split_state
  @is_first_on_page= false
  @input_line= (self.respond_to?(:text) ? self.text : input_line)
  @fixed_line= fix_input_line
  @sentences= @fixed_line.split(/ {2,}/)
  break_lines!
end

Instance Attribute Details

#input_lineObject (readonly)

See initialize



96
97
98
# File 'lib/eleanor.rb', line 96

def input_line
  @input_line
end

#is_first_on_pageObject

Set by pagination



93
94
95
# File 'lib/eleanor.rb', line 93

def is_first_on_page
  @is_first_on_page
end

#last_character_cueObject (readonly)

See initialize



96
97
98
# File 'lib/eleanor.rb', line 96

def last_character_cue
  @last_character_cue
end

#linesObject (readonly)

Array of lines in the paragraph



99
100
101
# File 'lib/eleanor.rb', line 99

def lines
  @lines
end

#screenplayObject (readonly)

See initialize



96
97
98
# File 'lib/eleanor.rb', line 96

def screenplay
  @screenplay
end

#split_stateObject (readonly)

See initialize



96
97
98
# File 'lib/eleanor.rb', line 96

def split_state
  @split_state
end

Instance Method Details

#heightObject

The height (a Length) of the paragraph given its screenplay’s line height and the number of lines in the paragraph.



103
104
105
# File 'lib/eleanor.rb', line 103

def height
  @screenplay.line_height * @lines.size
end

#keep_with_next?(para) ⇒ Boolean

Returns true if the paragraph should be kept on the same page as para.

Returns:

  • (Boolean)


126
127
128
129
130
131
132
# File 'lib/eleanor.rb', line 126

def keep_with_next? para
  if self.class.keep_with_nexts.is_a? Array
    self.class.keep_with_nexts.include? para.class.name[/[^:]+$/]
  else
    self.keep_with_nexts(:next_para => para)
  end
end

#margin_between(para) ⇒ Object

Returns the Length between the paragraph and para.



135
136
137
138
# File 'lib/eleanor.rb', line 135

def margin_between para
  [self.margin_bottom(:next_para => para),
   para.margin_top(:prev_para => self)].max
end

#split(max_orphan_height) ⇒ Object

Splits the paragraph across a page break, respecting orphan and widow sentences and lines. Returns [orphan, widow], where orphan is a new paragraph suitable for the bottom of the existing page, and widow is a new paragraph suitable for the top of a new page. orphan’s height will be no more than max_orphan_height (a Length). If such constraints cannot be satisfied, the paragraph cannot be broken, and [nil, self] is returned.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/eleanor.rb', line 147

def split max_orphan_height
  if !self.can_break_across_pages ||
      @sentences.size < (self.min_orphan_sentences_allowed +
                         self.min_widow_sentences_allowed)
    return [nil, self]
  end
  # [[orphan_para, widow_para] | orphan_para has
  #   self.class.min_orphan_sentences_allowed sentences, ... ]
  # assume self.class.min_orphan_sentences_allowed >= 1
  # assume self.class.min_widow_sentences_allowed >= 1
  lo= self.min_orphan_sentences_allowed - 1
  hi= @sentences.size - self.min_widow_sentences_allowed - 1
  (lo..hi).inject([]) do |paras, i|
    orphan= slice(0..i, :orphan)
    break paras if orphan && orphan.height > max_orphan_height
    widow= slice((i + 1)..-1, :widow)
    paras << [orphan, widow]
  end.reverse_each do |paras|
    if paras[0].lines.size >= self.min_orphan_lines_allowed &&
        paras[1].lines.size >= self.min_widow_lines_allowed
      return paras
    end
  end
  [nil, self]
end

#to_sObject



173
174
175
# File 'lib/eleanor.rb', line 173

def to_s
  "[#{self.class.name[/[^:]+$/]}] #{@input_line}"
end

#write_to_paper(pdf_page, line_height_pts) ⇒ Object

An implementation detail in the backend. See lib/eleanor/hpdfpaper.rb.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/eleanor/hpdfpaper.rb', line 202

def write_to_paper pdf_page, line_height_pts
  underline_broken= false
  @lines.each do |line|
    if underline_broken
      line= '_' + line
      underline_broken= false
    end
    if line.count('_') % 2 == 1
      line << '_'
      underline_broken= true
    end
    case self.align.to_s.strip.downcase
    when 'left'
      pdf_page.margin_left= self.margin_left
      pdf_page.line(line, line_height_pts)
    when 'center'
      pdf_page.line_center(line, line_height_pts)
    when 'right'
      pdf_page.line_flush_right(line, line_height_pts, self.margin_right)
    else
      raise "configuration error: invalid align value " \
            "#{self.align.inspect} for #{self.class}"
    end
  end
  if underline_broken
    warn "warning: runaway underline at paragraph:\n  #{self}"
  end
end