# File lib/prawn/font/afm.rb, line 23 def self.metrics_path if m = ENV['METRICS'] @metrics_path ||= m.split(':') else @metrics_path ||= [ ".", "/usr/lib/afm", "/usr/local/lib/afm", "/usr/openwin/lib/fonts/afm", Prawn::DATADIR+'/fonts'] end end
The font bbox, as an array of integers
# File lib/prawn/font/afm.rb, line 64 def bbox @bbox ||= @attributes['FontBBox'].split(/\s+/).map { |e| Integer(e) } end
Returns the number of characters in str
(a WinAnsi-encoded
string).
# File lib/prawn/font/afm.rb, line 101 def character_count(str) str.length end
Perform any changes to the string that need to happen before it is rendered to the canvas. Returns an array of subset “chunks”, where each chunk is an array of two elements. The first element is the font subset number, and the second is either a string or an array (for kerned text).
For Adobe fonts, there is only ever a single subset, so the first element of the array is “0”, and the second is the string itself (or an array, if kerning is performed).
The text
parameter must be in WinAnsi encoding (cp1252).
# File lib/prawn/font/afm.rb, line 117 def encode_text(text, options={}) [[0, options[:kerning] ? kern(text) : text]] end
# File lib/prawn/font/afm.rb, line 121 def glyph_present?(char) if char == "_" true else normalize_encoding(char) != "_" end end
Returns true if the font has kerning data, false otherwise
# File lib/prawn/font/afm.rb, line 83 def has_kerning_data? @kern_pairs.any? end
built-in fonts only work with winansi encoding, so translate the string. Changes the encoding in-place, so the argument itself is replaced with a string in WinAnsi encoding.
# File lib/prawn/font/afm.rb, line 91 def normalize_encoding(text) enc = @@winansi text.unpack("U*").collect { |i| enc[i] }.pack("C*") rescue ArgumentError raise Prawn::Errors::IncompatibleStringEncoding, "Arguments to text methods must be UTF-8 encoded" end
# File lib/prawn/font/afm.rb, line 19 def unicode? false end
# File lib/prawn/font/afm.rb, line 188 def build_glyph_table(font_data) (0..255).map do |char| metrics = font_data.metrics_for(char) metrics ? metrics[:wx] : 0 end end
# File lib/prawn/font/afm.rb, line 178 def build_kern_pair_table(kern_pairs) character_hash = Hash[Encoding::WinAnsi::CHARACTERS.zip((0..Encoding::WinAnsi::CHARACTERS.size).to_a)] kern_pairs.inject({}) do |h,p| h[ [character_hash[p[0]], character_hash[p[1]]] ] = p[2] h end end
# File lib/prawn/font/afm.rb, line 146 def find_font(file) self.class.metrics_path.find { |f| File.exist? "#{f}/#{file}" } + "/#{file}" rescue NoMethodError raise Prawn::Errors::UnknownFont, "Couldn't find the font: #{file} in any of:\n" + self.class.metrics_path.join("\n") end
converts a string into an array with spacing offsets bewteen characters that need to be kerned
String must be encoded as WinAnsi
# File lib/prawn/font/afm.rb, line 159 def kern(string) kerned = [[]] last_byte = nil string.bytes do |byte| if k = last_byte && @kern_pair_table[[last_byte, byte]] kerned << -k << [byte] else kerned.last << byte end last_byte = byte end kerned.map { |e| e = (Array === e ? e.pack("C*") : e) e.respond_to?(:force_encoding) ? e.force_encoding("Windows-1252") : e } end
# File lib/prawn/font/afm.rb, line 131 def register(subset) font_dict = {:Type => :Font, :Subtype => :Type1, :BaseFont => name.to_sym} # Symbolic AFM fonts (Symbol, ZapfDingbats) have their own encodings font_dict.merge!(:Encoding => :WinAnsiEncoding) unless symbolic? @document.ref!(font_dict) end
# File lib/prawn/font/afm.rb, line 142 def symbolic? attributes["CharacterSet"] == "Special" end
# File lib/prawn/font/afm.rb, line 195 def unscaled_width_of(string) string.bytes.inject(0) do |s,r| s + @glyph_table[r] end end