Class: EideticPDF::PdfText::RichText

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

Constant Summary collapse

TOKEN_RE =
/\n|\t|[ ]|[\S]+-+|[\S]+/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text = nil, font = nil, options = {}) ⇒ RichText

Returns a new instance of RichText.



51
52
53
54
# File 'lib/epdft.rb', line 51

def initialize(text=nil, font=nil, options={})
  @words = []
  add(text, font, options) unless text.nil?
end

Instance Attribute Details

#wordsObject (readonly)

Returns the value of attribute words.



49
50
51
# File 'lib/epdft.rb', line 49

def words
  @words
end

Instance Method Details

#add(text, font, options = {}) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/epdft.rb', line 60

def add(text, font, options={})
  fsize = font.size * 0.001
  char_spacing, word_spacing = options[:char_spacing] || 0, options[:word_spacing] || 0
  color, underlined = options[:color] || 0, options[:underline] || false
  words = text.scan(TOKEN_RE).map do |token|
    width = 0.0
    token.each_byte do |b|
      width += fsize * font.widths[b] + char_spacing
      width += word_spacing if b == 32 # space
    end
    TextPiece.new(token, width, font, color, underlined, token.length, 1)
  end
  @words.concat(words)
end

#ascent(width = nil) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/epdft.rb', line 120

def ascent(width=nil)
  return 0 if @words.empty?
  if width.nil?
    @words.clone.extend(TextLine).ascent
  else
    self.clone.next(width).ascent
  end
end

#empty?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/epdft.rb', line 116

def empty?
  @words.empty?
end

#height(width = nil) ⇒ Object



129
130
131
132
133
134
135
136
137
138
# File 'lib/epdft.rb', line 129

def height(width=nil)
  return 0 if @words.empty?
  if width.nil?
    @words.clone.extend(TextLine).height
    # f = @words.first.font
    # 0.001 * f.height * f.size
  else
    lines(width).inject(0) { |total, line| total + line.height }
  end
end

#initialize_copy(other) ⇒ Object



56
57
58
# File 'lib/epdft.rb', line 56

def initialize_copy(other)
  @words = @words.map { |word| word.clone }
end

#lines(width) ⇒ Object



107
108
109
110
111
112
113
114
# File 'lib/epdft.rb', line 107

def lines(width)
  rich_text = self.clone
  result = []
  while line = rich_text.next(width)
    result << line
  end
  result
end

#merge(text_pieces) ⇒ Object

merge pieces with identical characteristics



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/epdft.rb', line 76

def merge(text_pieces)
  while !text_pieces.empty? and text_pieces.last.text == ' '
    text_pieces.pop
  end
  text_pieces.inject([]) do |pieces, piece|
    if pieces.empty? or [pieces.last.font, pieces.last.color, pieces.last.underline] != [piece.font, piece.color, piece.underline]
      pieces << piece
    else
      pieces.last.text << piece.text
      pieces.last.width += piece.width
      pieces.last.chars += piece.chars
      pieces.last.tokens += piece.tokens
    end
    pieces
  end
end

#next(width) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/epdft.rb', line 93

def next(width)
  # remove leading spaces
  @words.shift while !@words.empty? and @words.first.text == ' '
  return nil if @words.empty?
  # measure how many words will fit
  i, phrase_width = 0, 0.0
  while i < @words.size and phrase_width + @words[i].width < width
    phrase_width += @words[i].width
    i += 1
    break if @words[i-1].text == "\n"
  end
  merge(@words.slice!(0, [i,1].max)).extend(TextLine)
end

#width(max_width) ⇒ Object



140
141
142
# File 'lib/epdft.rb', line 140

def width(max_width)
  lines(max_width).map { |line| line.width }.max
end