39: def self.open(font_name)
40: file = font_name.gsub(/\\/o, "/")
41: dir = File.dirname(file)
42: name = File.basename(file)
43:
44: metrics_path = []
45:
46:
47: if dir == "."
48: metrics_path << dir << METRICS_PATH << $LOAD_PATH
49: elsif dir !~ %r{^(\w:|/)}o and dir.index("/")
50: METRICS_PATH.each { |path| metrics_path << File.join(path, dir) }
51: $LOAD_PATH.each { |path| metrics_path << File.join(path, dir) }
52: else
53: metric_path = [ dir ]
54: end
55: metrics_path.flatten!
56:
57: font = nil
58: afm = nil
59:
60: metrics_path.each do |path|
61: afm_file = File.join(path, "#{name}.afm").gsub(/\.afm\.afm$/o, ".afm")
62: rfm_file = "#{afm_file}.rfm"
63:
64:
65:
66: begin
67: if File.exists?(rfm_file)
68: data = File.open(rfm_file, "rb") { |file| file.read }
69: font = Marshal.load(data)
70: return font
71: end
72: rescue
73: nil
74: end
75:
76:
77: File.open(afm_file, "rb") do |file|
78: font = PDF::Writer::FontMetrics.new
79:
80:
81: file.each do |line|
82: line.chomp!
83: line.strip!
84: key, *values = line.split
85: next if key.nil?
86: op = "#{key.downcase}=".to_sym
87:
88:
89:
90:
91:
92:
93:
94:
95:
96: case key
97: when 'FontName', 'FullName', 'FamilyName', 'Weight',
98: 'IsFixedPitch', 'CharacterSet', 'Version', 'EncodingScheme'
99:
100: font.__send__(op, values.join(" "))
101: when 'ItalicAngle', 'UnderlinePosition', 'UnderlineThickness',
102: 'CapHeight', 'XHeight', 'Ascender', 'Descender', 'StdHW',
103: 'StdVW', 'StartCharMetrics'
104:
105: font.__send__(op, values.join(" ").to_f)
106: when 'FontBBox'
107:
108: font.fontbbox = values.map { |el| el.to_f }
109: when 'C', 'CH'
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: bits = line.chomp.strip.split(/;/).collect { |r| r.strip }
154: dtmp = {}
155:
156: bits.each do |bit|
157: b = bit.split
158: if b.size > 2
159: dtmp[b[0]] = []
160: b[1..-1].each do |z|
161: if z =~ NUMBER
162: dtmp[b[0]] << z.to_f
163: else
164: dtmp[b[0]] << z
165: end
166: end
167: elsif b.size == 2
168: if b[0] == 'C' and b[1] =~ NUMBER
169: dtmp[b[0]] = b[1].to_i
170: elsif b[0] == 'CH'
171: dtmp['C'] = b[1].to_i(16)
172: elsif b[1] =~ NUMBER
173: dtmp[b[0]] = b[1].to_f
174: else
175: dtmp[b[0]] = b[1]
176: end
177: end
178: end
179:
180: font.c[dtmp['N']] = dtmp
181: font.c[dtmp['C']] = dtmp unless dtmp['C'].nil?
182: when 'KPX'
183:
184: font.kpx[values[0]] = { }
185: font.kpx[values[0]][values[1]] = values[2].to_f
186: end
187: end
188: font.path = afm_file
189: end rescue nil
190: break unless font.nil?
191: end
192:
193: raise ArgumentError, "Font #{font_name} not found." if font.nil?
194: font
195: end