Class: PDF::Writer::FontMetrics
- Inherits:
-
Object
- Object
- PDF::Writer::FontMetrics
- Defined in:
- lib/pdf/writer/fontmetrics.rb
Overview
– PDF::Writer for Ruby.
http://rubyforge.org/projects/ruby-pdf/
Copyright 2003 - 2005 Austin Ziegler.
Licensed under a MIT-style licence. See LICENCE in the main distribution
for full licensing information.
$Id: fontmetrics.rb 168 2007-11-08 19:04:08Z sandal $ ++
Constant Summary collapse
- METRICS_PATH =
[ File.join(File.dirname(File.(__FILE__)), 'fonts') ]
- KEYS =
%w{FontName FullName FamilyName Weight ItalicAngle IsFixedPitch CharacterSet UnderlinePosition UnderlineThickness Version EncodingScheme CapHeight XHeight Ascender Descender StdHW StdVW StartCharMetrics FontBBox C KPX}
- NUMBER =
/^[+\-0-9.]+$/o
Instance Attribute Summary collapse
-
#differences ⇒ Object
Returns the value of attribute differences.
-
#encoding ⇒ Object
Returns the value of attribute encoding.
-
#font_num ⇒ Object
Returns the value of attribute font_num.
-
#path ⇒ Object
Returns the value of attribute path.
Class Method Summary collapse
-
.open(font_name) ⇒ Object
Open the font file and return a PDF::Writer::FontMetrics object containing it.
Instance Method Summary collapse
-
#initialize ⇒ FontMetrics
constructor
A new instance of FontMetrics.
-
#save_as_rfm ⇒ Object
Save the loaded font metrics file as a binary marshaled value.
Constructor Details
#initialize ⇒ FontMetrics
Returns a new instance of FontMetrics.
21 22 23 24 25 26 |
# File 'lib/pdf/writer/fontmetrics.rb', line 21 def initialize @kpx = {} @c = {} @version = 1 @font_num = nil end |
Instance Attribute Details
#differences ⇒ Object
Returns the value of attribute differences.
30 31 32 |
# File 'lib/pdf/writer/fontmetrics.rb', line 30 def differences @differences end |
#encoding ⇒ Object
Returns the value of attribute encoding.
31 32 33 |
# File 'lib/pdf/writer/fontmetrics.rb', line 31 def encoding @encoding end |
#font_num ⇒ Object
Returns the value of attribute font_num.
28 29 30 |
# File 'lib/pdf/writer/fontmetrics.rb', line 28 def font_num @font_num end |
#path ⇒ Object
Returns the value of attribute path.
29 30 31 |
# File 'lib/pdf/writer/fontmetrics.rb', line 29 def path @path end |
Class Method Details
.open(font_name) ⇒ Object
Open the font file and return a PDF::Writer::FontMetrics object containing it. The font_name
may specify just a font file or a full path. If a path is specified, that is the only place where the font file will be looked for.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/pdf/writer/fontmetrics.rb', line 39 def self.open(font_name) file = font_name.gsub(/\\/o, "/") dir = File.dirname(file) name = File.basename(file) metrics_path = [] # Check to see if the directory is "." or a non-path if dir == "." metrics_path << dir << METRICS_PATH << $LOAD_PATH elsif dir !~ %r{^(\w:|/)}o and dir.index("/") METRICS_PATH.each { |path| metrics_path << File.join(path, dir) } $LOAD_PATH.each { |path| metrics_path << File.join(path, dir) } else metric_path = [ dir ] end metrics_path.flatten! font = nil afm = nil metrics_path.each do |path| afm_file = File.join(path, "#{name}.afm").gsub(/\.afm\.afm$/o, ".afm") rfm_file = "#{afm_file}.rfm" # Attempt to unmarshal an .afm.rfm file first. If it is loaded, # we're in good shape. begin if File.exists?(rfm_file) data = File.open(rfm_file, "rb") { |file| file.read } font = Marshal.load(data) return font end rescue nil end # Attempt to open and process the font. File.open(afm_file, "rb") do |file| font = PDF::Writer::FontMetrics.new # An AFM file contains key names followed by valuees. file.each do |line| line.chomp! line.strip! key, *values = line.split next if key.nil? op = "#{key.downcase}=".to_sym # I probably need to deal with MetricsSet. The default value is # 0, which is writing direction 0 (W0X). If MetricsSet 1 is # specified, then only writing direction 1 is present (W1X). If # MetricsSet 2 is specified, then both W0X and W1X are present. # Measurements are always 1/1000th of a scale factor (point # size). So a 12pt character with a width of 222 is going to be # 222 * 12 / 1000 or 2.664 points wide. case key when 'FontName', 'FullName', 'FamilyName', 'Weight', 'IsFixedPitch', 'CharacterSet', 'Version', 'EncodingScheme' # These values are string values. font.__send__(op, values.join(" ")) when 'ItalicAngle', 'UnderlinePosition', 'UnderlineThickness', 'CapHeight', 'XHeight', 'Ascender', 'Descender', 'StdHW', 'StdVW', 'StartCharMetrics' # These values are floating point values. font.__send__(op, values.join(" ").to_f) when 'FontBBox' # These values are an array of floating point values font.fontbbox = values.map { |el| el.to_f } when 'C', 'CH' # Individual Character Metrics Values: # C <character number> # CH <hex character number> # One of C or CH must be provided. Specifies the encoding # number for the character. -1 if the character is not # encoded in the font. # # WX <x width number> # W0X <x0 width number> # W1X <x1 width number> # Character width in x for writing direction 0 (WX, W0X) # or 1 (W1X) where y is 0. Optional. # # WY <y width number> # W0Y <y0 width number> # W1Y <y1 width number> # Character width in y for writing direction 0 (WY, W0Y) # or 1 (W1Y) where x is 0. Optional. # # W <x width> <y width> # W0 <x0 width> <y0 width> # W1 <x1 width> <y1 width> # Character width in x, y for writing direction 0 (W, W0) # or 1 (W1). Optional. # # VV <x number> <y number> # Same as VVector in the global font definition, but for # this single character. Optional. # # N <name> # The PostScript name of the font. Optional. # # B <llx> <lly> <urx> <ury> # Character bounding box for the lower left corner and the # upper right corner. Optional. # # L <sucessor> <ligature> # Ligature sequence where both <successor> and <ligature> # are N <names>. For the fragment "N f; L i fi; L l fl", # two ligatures are defined: fi and fl. Optional, # multiples permitted. # # C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ; bits = line.chomp.strip.split(/;/).collect { |r| r.strip } dtmp = {} bits.each do |bit| b = bit.split if b.size > 2 dtmp[b[0]] = [] b[1..-1].each do |z| if z =~ NUMBER dtmp[b[0]] << z.to_f else dtmp[b[0]] << z end end elsif b.size == 2 if b[0] == 'C' and b[1] =~ NUMBER dtmp[b[0]] = b[1].to_i elsif b[0] == 'CH' dtmp['C'] = b[1].to_i(16) elsif b[1] =~ NUMBER dtmp[b[0]] = b[1].to_f else dtmp[b[0]] = b[1] end end end font.c[dtmp['N']] = dtmp font.c[dtmp['C']] = dtmp unless dtmp['C'].nil? when 'KPX' # KPX Adieresis yacute -40 # KPX: Kerning Pair font.kpx[values[0]] = { } font.kpx[values[0]][values[1]] = values[2].to_f end end font.path = afm_file end rescue nil # Ignore file errors break unless font.nil? end raise ArgumentError, "Font #{font_name} not found." if font.nil? font end |
Instance Method Details
#save_as_rfm ⇒ Object
Save the loaded font metrics file as a binary marshaled value.
198 199 200 201 202 |
# File 'lib/pdf/writer/fontmetrics.rb', line 198 def save_as_rfm rfm = File.basename(@path).gsub(/\.afm.*$/, '') rfm << ".afm.rfm" File.open(rfm, "wb") { |file| file.write Marshal.dump(self) } end |