rfil 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +340 -0
- data/README +77 -0
- data/examples/afm2tfm.rb +204 -0
- data/examples/afminfo +305 -0
- data/examples/encodingtable +65 -0
- data/examples/pldiff +295 -0
- data/examples/plinfo +108 -0
- data/examples/rfii +257 -0
- data/examples/rfont +188 -0
- data/lib/rfil/font.rb +722 -0
- data/lib/rfil/font/afm.rb +414 -0
- data/lib/rfil/font/glyph.rb +198 -0
- data/lib/rfil/font/metric.rb +135 -0
- data/lib/rfil/font/truetype.rb +35 -0
- data/lib/rfil/fontcollection.rb +182 -0
- data/lib/rfil/helper.rb +155 -0
- data/lib/rfil/rfi.rb +472 -0
- data/lib/rfil/rfi_plugin_context.rb +90 -0
- data/lib/rfil/rfi_plugin_latex.rb +95 -0
- data/lib/rfil/version.rb +3 -0
- data/lib/tex/enc.rb +223 -0
- data/lib/tex/kpathsea.rb +63 -0
- data/lib/tex/tfm.rb +1198 -0
- data/lib/tex/vf.rb +846 -0
- metadata +86 -0
data/examples/afminfo
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Last Change: Mon May 22 12:38:42 2006
|
4
|
+
#++
|
5
|
+
=begin rdoc
|
6
|
+
|
7
|
+
== afminfo - print out information about an afm or truetype font file
|
8
|
+
|
9
|
+
Usage: afminfo [options] afm-file[.afm]
|
10
|
+
-m, --metrics show global metrics information
|
11
|
+
-v, --verbose verbose output
|
12
|
+
--[no-]info list general information (default)
|
13
|
+
-l, --list-glyphs list all available glyphs
|
14
|
+
-g, --glyphinfo g information about a specific glyph
|
15
|
+
-h, --help Show this help
|
16
|
+
--version Show version information
|
17
|
+
|
18
|
+
---
|
19
|
+
Author:: Patrick Gundlach <patrick@gundla.ch>
|
20
|
+
License:: Copyright (c) 2006 Patrick Gundlach.
|
21
|
+
Released under the terms of the GNU General Public License
|
22
|
+
=end
|
23
|
+
|
24
|
+
# :enddoc:
|
25
|
+
|
26
|
+
AFMINFO_VERSION="0.1"
|
27
|
+
|
28
|
+
require 'optparse'
|
29
|
+
require 'ostruct'
|
30
|
+
require 'rfil/font/afm'
|
31
|
+
require 'rfil/version'
|
32
|
+
|
33
|
+
################################################## texttable.rb follows
|
34
|
+
|
35
|
+
# Render a list of data column-wise or row-wise. TextTable is used to
|
36
|
+
# print a table to the console, without a GUI.
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
# data=%w(one two three four five six seven eight nine ten)
|
40
|
+
# puts TextTable.do_columns(data)
|
41
|
+
#
|
42
|
+
# This will print out this table:
|
43
|
+
# one five eight
|
44
|
+
# two six nine
|
45
|
+
# three seven ten
|
46
|
+
# four
|
47
|
+
# see that the order is column one first, then second column ...
|
48
|
+
#
|
49
|
+
# Another posibility would be:
|
50
|
+
# puts TextTable.do_rows(data)
|
51
|
+
# which outputs
|
52
|
+
# one two three
|
53
|
+
# four five six
|
54
|
+
# seven eight nine
|
55
|
+
# ten
|
56
|
+
|
57
|
+
|
58
|
+
class TextTable
|
59
|
+
class << self
|
60
|
+
# def columns(data,maxchars=80)
|
61
|
+
# m,c=count_columns=calculate_maxwidth_columns(data,maxchars)
|
62
|
+
# return c
|
63
|
+
# end
|
64
|
+
|
65
|
+
# def maxwidth(data,maxchars=80)
|
66
|
+
# m,c=count_columns=calculate_maxwidth_columns(data,maxchars)
|
67
|
+
# return m
|
68
|
+
# end
|
69
|
+
|
70
|
+
# Arrange the data in columns. The total width is <= maxchars.
|
71
|
+
def do_columns(data,maxchars=80)
|
72
|
+
maxwidth,count_columns=calculate_maxwidth_columns(data,maxchars)
|
73
|
+
|
74
|
+
tmp=""
|
75
|
+
# amount of data(rows) in each column. The first
|
76
|
+
# count_full_columns columns might have more rows then the last
|
77
|
+
# columns.
|
78
|
+
rowsmin = (data.size * 1.0 / count_columns).floor
|
79
|
+
rowsmax = (data.size * 1.0 / count_columns).ceil
|
80
|
+
count_full_columns = data.size % count_columns
|
81
|
+
|
82
|
+
distribution=Array.new()
|
83
|
+
distribution[0]=0
|
84
|
+
count = 0
|
85
|
+
(0...count_columns).each { |col|
|
86
|
+
if col < count_full_columns
|
87
|
+
count += rowsmax
|
88
|
+
else
|
89
|
+
count += rowsmin
|
90
|
+
end
|
91
|
+
distribution[col]= count
|
92
|
+
}
|
93
|
+
|
94
|
+
distribution.unshift 0
|
95
|
+
(0...rowsmax).each { |row|
|
96
|
+
tmp <<((0...count_columns).collect { |column|
|
97
|
+
w = data[distribution[column] + row]
|
98
|
+
if (column >= count_full_columns) and (row >= rowsmin)
|
99
|
+
w = ""
|
100
|
+
end
|
101
|
+
sprintf("%-#{maxwidth}s",w)
|
102
|
+
}.join(' '))
|
103
|
+
tmp << "\n"
|
104
|
+
}
|
105
|
+
tmp
|
106
|
+
end
|
107
|
+
|
108
|
+
# Arrange the data in rows.
|
109
|
+
def do_rows(data,maxchars=80)
|
110
|
+
maxwidth,count_columns=calculate_maxwidth_columns(data,maxchars)
|
111
|
+
tmp=""
|
112
|
+
(0...data.size).each { |x|
|
113
|
+
tmp << sprintf("%-#{maxwidth}s",data[x]) +
|
114
|
+
if (x+1) % count_columns == 0
|
115
|
+
"\n"
|
116
|
+
else
|
117
|
+
" "
|
118
|
+
end
|
119
|
+
}
|
120
|
+
tmp << "\n"
|
121
|
+
tmp
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def calculate_maxwidth_columns(data,maxchars)
|
127
|
+
maxwidth = 0
|
128
|
+
data.each { |elt|
|
129
|
+
maxwidth = maxwidth > elt.length ? maxwidth : elt.length
|
130
|
+
}
|
131
|
+
columns = (maxchars/(maxwidth + 1)).floor
|
132
|
+
raise ArgumentError,"calculated columns == 0, need wider table" if columns==0
|
133
|
+
return maxwidth,columns
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
################################################## texttable.rb ends here
|
139
|
+
|
140
|
+
class AFMinfo # :nodoc:
|
141
|
+
def initialize (afm)
|
142
|
+
@afm = afm
|
143
|
+
@uppercase_letters = ('A'..'Z').collect { |l| l }
|
144
|
+
@lowercase_letters = ('a'..'z').collect { |l| l }
|
145
|
+
@digits = %w(one two three four five six seven eight nine zero)
|
146
|
+
end
|
147
|
+
def stdformat
|
148
|
+
"%-18s "
|
149
|
+
end
|
150
|
+
def printout (str,value)
|
151
|
+
puts sprintf(stdformat + "%s", str + ":" ,value.to_s)
|
152
|
+
end
|
153
|
+
|
154
|
+
def num_to_string (num,reservespace=true)
|
155
|
+
formatstring = "%"
|
156
|
+
formatstring << " " if reservespace
|
157
|
+
formatstring << (num.to_i == num ? "d" : "f")
|
158
|
+
# output "integer" if value after decimal point is 0
|
159
|
+
sprintf(formatstring,num)
|
160
|
+
end
|
161
|
+
|
162
|
+
def dump_maininfo
|
163
|
+
puts "General font information:"
|
164
|
+
puts "========================="
|
165
|
+
printout("Filename",@afm.filename)
|
166
|
+
[
|
167
|
+
["Fontname",:fontname],
|
168
|
+
["FullName",:fullname],
|
169
|
+
["Family name",:familyname],
|
170
|
+
["Weight",:weight],
|
171
|
+
["EncodingScheme",:encodingscheme],
|
172
|
+
# ["�","�"],
|
173
|
+
].each { |s,m|
|
174
|
+
printout(s,@afm.send(m))
|
175
|
+
}
|
176
|
+
puts sprintf(stdformat,'Number of gylphs:') + @afm.count_charmetrics.to_s +
|
177
|
+
" (encoded: " + @afm.count_charmetrics_encoded.to_s + ", unencoded: " + @afm.count_charmetrics_unencoded.to_s + ")"
|
178
|
+
|
179
|
+
end
|
180
|
+
def dump_metrics
|
181
|
+
puts "\n\nGlobal metrics information:"
|
182
|
+
puts "=========================="
|
183
|
+
puts sprintf(stdformat,"FontBBox:") + @afm.fontbbox.collect { |f|
|
184
|
+
num_to_string(f)
|
185
|
+
}.join(' ') + ' (llx,lly,urx,ury)'
|
186
|
+
printout('IsFixedPitch',@afm.isfixedpitch)
|
187
|
+
|
188
|
+
[
|
189
|
+
["ItalicAngle", :italicangle],
|
190
|
+
["UnderlinePosition", :underlineposition],
|
191
|
+
["UnderlineThickness", :underlinethickness],
|
192
|
+
["CapHeight", :capheight],
|
193
|
+
["XHeight", :xheight],
|
194
|
+
["Ascender", :ascender],
|
195
|
+
["Descender", :descender]
|
196
|
+
].each { |s,m|
|
197
|
+
puts sprintf(stdformat,s) + num_to_string(@afm.send(m))
|
198
|
+
}
|
199
|
+
end
|
200
|
+
def dump_glyphinfo (glyph)
|
201
|
+
chars=@afm.chars[glyph]
|
202
|
+
puts "\n\nGlyph information (" + glyph + ")"
|
203
|
+
puts "===================="
|
204
|
+
puts sprintf(stdformat,"Encoding pos:") +
|
205
|
+
if chars.c == -1
|
206
|
+
"--"
|
207
|
+
else
|
208
|
+
sprintf("%d (dec), %x (hex), %o (oct)",chars.c,chars.c,chars.c)
|
209
|
+
end
|
210
|
+
puts sprintf(stdformat,"Width x (wx)") + chars.wx.to_s
|
211
|
+
puts sprintf(stdformat,"Bounding box") + chars.b.collect { |f|
|
212
|
+
num_to_string(f,false)
|
213
|
+
}.join(' ') + ' (llx,lly,urx,ury)'
|
214
|
+
puts "Kerning pairs: (x,y)"
|
215
|
+
puts "--------------------"
|
216
|
+
chars.kern_data.each { |k,v|
|
217
|
+
puts sprintf(stdformat," " + k) + num_to_string(v[0]) + "," +
|
218
|
+
num_to_string(v[1])
|
219
|
+
}
|
220
|
+
end
|
221
|
+
def dump_glyphs
|
222
|
+
chars=@afm.chars
|
223
|
+
puts "\n\nList of glyphs"
|
224
|
+
puts "================"
|
225
|
+
removefromlist=[]
|
226
|
+
if @uppercase_letters.all? { |glyph|
|
227
|
+
chars[glyph]
|
228
|
+
}
|
229
|
+
puts sprintf(stdformat,"A-Z") + "available"
|
230
|
+
removefromlist += @uppercase_letters
|
231
|
+
else
|
232
|
+
puts sprintf(stdformat,"A-Z") + "some missing"
|
233
|
+
end
|
234
|
+
if @lowercase_letters.all? { |glyph|
|
235
|
+
chars[glyph]
|
236
|
+
}
|
237
|
+
puts sprintf(stdformat,"a-z") + "available"
|
238
|
+
removefromlist += @lowercase_letters
|
239
|
+
else
|
240
|
+
puts sprintf(stdformat,"a-z") + "some missing"
|
241
|
+
end
|
242
|
+
if @digits.all? { |glyph|
|
243
|
+
chars[glyph]
|
244
|
+
}
|
245
|
+
puts sprintf(stdformat,"one, two, .., zero") + "available"
|
246
|
+
removefromlist += @digits
|
247
|
+
else
|
248
|
+
puts sprintf(stdformat,"one, two, .., zero") + "some missing"
|
249
|
+
end
|
250
|
+
puts
|
251
|
+
glyphlist=[]
|
252
|
+
chars.each { |glyph,h|
|
253
|
+
glyphlist.push(glyph + (h.c == -1 ? "*" : ""))
|
254
|
+
}
|
255
|
+
glyphlist = glyphlist - removefromlist
|
256
|
+
glyphlist.sort! { |a,b|
|
257
|
+
a.casecmp b
|
258
|
+
}
|
259
|
+
puts TextTable.do_columns(glyphlist)
|
260
|
+
puts "\n* = unencoded - only glyphs not mentioned above listed"
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
264
|
+
|
265
|
+
options=OpenStruct.new
|
266
|
+
options.verbose = false
|
267
|
+
options.metrics = false
|
268
|
+
options.glyph = nil
|
269
|
+
options.listglyphs = false
|
270
|
+
options.generalinfo = true
|
271
|
+
|
272
|
+
ARGV.options { |opt|
|
273
|
+
opt.banner = "Usage: #{File.basename($0)} [options] afm-file[.afm]"
|
274
|
+
opt.on("--metrics", "-m", "show global metrics information") { options.metrics=true}
|
275
|
+
opt.on("--verbose", "-v", "verbose output") { options.verbose=true }
|
276
|
+
opt.on("--[no-]info", "list general information (default)") { |x|
|
277
|
+
options.generalinfo=x }
|
278
|
+
opt.on("--list-glyphs", "-l", "list all available glyphs") { options.listglyphs=true }
|
279
|
+
opt.on("--glyphinfo g" , "-g",
|
280
|
+
"information about a specific glyph") { |arg|
|
281
|
+
options.glyph = arg
|
282
|
+
}
|
283
|
+
|
284
|
+
opt.on("--help", "-h", "Show this help") { puts opt; exit 0 }
|
285
|
+
opt.on("--version", "Show version information") {
|
286
|
+
puts %Q{This is afminfo version #{AFMINFO_VERSION}, based on rfil version #{RFIL_VERSION}\n#{COPYRIGHT}\nMore information: #{HOMEPAGE}}; exit 0 }
|
287
|
+
opt.separator ""
|
288
|
+
opt.separator COPYRIGHT
|
289
|
+
opt.parse!
|
290
|
+
}
|
291
|
+
|
292
|
+
unless ARGV.size==1
|
293
|
+
puts "Please specify one afm-file to read" if ARGV
|
294
|
+
exit 1
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
# afm=Font::AFM.new(:verbose => options.verbose)
|
299
|
+
afm=RFIL::Font::Metric.read(ARGV[0],:verbose => options.verbose)
|
300
|
+
|
301
|
+
ai = AFMinfo.new(afm)
|
302
|
+
ai.dump_maininfo if options.generalinfo
|
303
|
+
ai.dump_metrics if options.metrics
|
304
|
+
options.glyph && ai.dump_glyphinfo(options.glyph)
|
305
|
+
ai.dump_glyphs if options.listglyphs
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
#--
|
3
|
+
# Last Change: Tue May 16 18:11:49 2006
|
4
|
+
#++
|
5
|
+
=begin rdoc
|
6
|
+
= encodingtable -- print out a table with different encodings in colums
|
7
|
+
|
8
|
+
This is mainly an example how to use the ENC and Kpathsea class.
|
9
|
+
|
10
|
+
== Usage
|
11
|
+
encodingtable encoding[.enc] [encoding[.enc] ...]
|
12
|
+
|
13
|
+
|
14
|
+
== Example
|
15
|
+
|
16
|
+
$ ./encodingtable ec texnansi 8r 8a
|
17
|
+
|
18
|
+
dec | oct |hex | ECEncoding | TeXnANSIEncoding | TeXBase1Encoding | StandardEncoding |
|
19
|
+
--------------------------------------------------------------------------------------------
|
20
|
+
0 | 0 | 0 | grave | --- | --- | --- |
|
21
|
+
1 | 1 | 1 | acute | Euro | dotaccent | --- |
|
22
|
+
2 | 2 | 2 | circumflex | --- | fi | --- |
|
23
|
+
3 | 3 | 3 | tilde | --- | fl | --- |
|
24
|
+
4 | 4 | 4 | dieresis | fraction | fraction | --- |
|
25
|
+
5 | 5 | 5 | hungarumlaut | dotaccent | hungarumlaut | --- |
|
26
|
+
...
|
27
|
+
---
|
28
|
+
Author:: Patrick Gundlach <patrick@gundla.ch>
|
29
|
+
=end
|
30
|
+
|
31
|
+
# :enddoc:
|
32
|
+
|
33
|
+
require 'tex/enc'
|
34
|
+
require 'tex/kpathsea'
|
35
|
+
|
36
|
+
|
37
|
+
unless ARGV.size > 0
|
38
|
+
puts "Usage: #{File.basename($0)} encoding[.enc] ..."
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
fmt=" %-16.16s |"
|
43
|
+
|
44
|
+
encodings=[]
|
45
|
+
kpse=Kpathsea.new
|
46
|
+
ARGV.each { |e|
|
47
|
+
kpse.open_file(e.chomp('.enc')+'.enc','enc') { |f|
|
48
|
+
encodings.push(ENC.new(f))
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
|
53
|
+
print "dec | oct |hex |"
|
54
|
+
encodings.each { |e| print sprintf(fmt,e.encname) }
|
55
|
+
|
56
|
+
|
57
|
+
0.upto(255) { |slot|
|
58
|
+
print "\n"+"-"*(16 + encodings.size * 19 ) if slot % 32 == 0
|
59
|
+
|
60
|
+
print sprintf("\n%3d | %3o | %2x |", slot,slot,slot)
|
61
|
+
encodings.each { |e|
|
62
|
+
print sprintf(fmt, e[slot]==".notdef" ? "---" : e[slot])
|
63
|
+
}
|
64
|
+
}
|
65
|
+
puts
|
data/examples/pldiff
ADDED
@@ -0,0 +1,295 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Last Change: Tue May 16 18:13:36 2006
|
4
|
+
#++
|
5
|
+
=begin rdoc
|
6
|
+
|
7
|
+
== pldiff -- show the differences between two (v)pl files.
|
8
|
+
|
9
|
+
Usage: pldiff [options] file file
|
10
|
+
file can be tfm, pl, vpl or vf files.
|
11
|
+
-d, --delta DELTA Don't report differences whithin +/- DELTA percent
|
12
|
+
-c, --ignore-comments ignore comments
|
13
|
+
-k, --ignore-kern ignore difference in kerning information
|
14
|
+
-m, --mapenc ENC assume encoding ENC for destination encoding
|
15
|
+
-t, --texenc ENC assume encoding ENC for source encoding (TeX side)
|
16
|
+
-e, --encoding ENC assume encoding ENC for both in and out
|
17
|
+
-s, --skip-characters only look at fontdimen and main data
|
18
|
+
|
19
|
+
-h, --help Show this help
|
20
|
+
|
21
|
+
|
22
|
+
---
|
23
|
+
Author:: Patrick Gundlach <patrick@gundla.ch>
|
24
|
+
License:: Copyright (c) 2005 Patrick Gundlach.
|
25
|
+
Released under the terms of the GNU General Public License
|
26
|
+
|
27
|
+
=end
|
28
|
+
|
29
|
+
# :enddoc:
|
30
|
+
|
31
|
+
require 'optparse'
|
32
|
+
require 'ostruct'
|
33
|
+
|
34
|
+
require 'tex/kpathsea'
|
35
|
+
require 'tex/enc'
|
36
|
+
require 'tex/tfm'
|
37
|
+
require 'tex/vf'
|
38
|
+
|
39
|
+
|
40
|
+
def showmap(mapary)
|
41
|
+
str = ""
|
42
|
+
if mapary
|
43
|
+
mapary.each { |entry|
|
44
|
+
str << " | " << entry.join(" ") << "\n"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
str
|
48
|
+
end
|
49
|
+
|
50
|
+
def plopen(filename)
|
51
|
+
case filename
|
52
|
+
when /\.tfm$/
|
53
|
+
return TFM.new.read_tfm(filename)
|
54
|
+
when /\.vf$/
|
55
|
+
# change to that dir first
|
56
|
+
currentdir=Dir.getwd
|
57
|
+
dirname=File.dirname(filename)
|
58
|
+
Dir.chdir(dirname)
|
59
|
+
fn=File.basename(filename)
|
60
|
+
vf=VF.new.read_vf(filename)
|
61
|
+
Dir.chdir(currentdir)
|
62
|
+
return vf
|
63
|
+
when /\.pl$/
|
64
|
+
return TFM.new.read_pl(filename)
|
65
|
+
when /\.vpl$/
|
66
|
+
return TFM.new.read_pl(filename)
|
67
|
+
else
|
68
|
+
puts "Unknown format: #{filename}"
|
69
|
+
exit 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
include TeX
|
74
|
+
options=OpenStruct.new
|
75
|
+
kpse=Kpathsea.new
|
76
|
+
|
77
|
+
ARGV.options { |opts|
|
78
|
+
opts.banner = "Usage: #{File.basename($0)} [options] file file"
|
79
|
+
opts.separator "file can be tfm, pl, vpl or vf files."
|
80
|
+
|
81
|
+
opts.on("--delta","-d DELTA", Float,
|
82
|
+
"Don't report differences whithin +/- DELTA percent") { |d|
|
83
|
+
options.delta=d
|
84
|
+
}
|
85
|
+
opts.on("--ignore-comments", "-c", "ignore comments") { |i|
|
86
|
+
options.ignore_comments=true
|
87
|
+
}
|
88
|
+
opts.on("--ignore-kern", "-k", "ignore difference in kerning information") { |k|
|
89
|
+
options.ignore_kern=true
|
90
|
+
}
|
91
|
+
|
92
|
+
opts.on("--mapenc", "-m ENC",
|
93
|
+
"assume encoding ENC for destination encoding") {|e|
|
94
|
+
options.mapencoding=e
|
95
|
+
}
|
96
|
+
|
97
|
+
opts.on("--texenc", "-t ENC",
|
98
|
+
"assume encoding ENC for source encoding (TeX side)") {|e|
|
99
|
+
options.texencoding=e
|
100
|
+
}
|
101
|
+
|
102
|
+
opts.on("--encoding", "-e ENC",
|
103
|
+
"assume encoding ENC for both in and out") {|e|
|
104
|
+
options.encoding=e
|
105
|
+
}
|
106
|
+
opts.on("--skip-characters", "-s", "only look at fontdimen and main data") {|s|
|
107
|
+
options.skip=true
|
108
|
+
}
|
109
|
+
opts.on_tail("--help", "-h", "Show this help") { puts opts; exit 0 }
|
110
|
+
opts.separator ""
|
111
|
+
opts.parse!
|
112
|
+
}
|
113
|
+
|
114
|
+
# untested:
|
115
|
+
if options.encoding
|
116
|
+
kpse.open_file(options.encoding,"enc") { |f|
|
117
|
+
options.encoding = ENC.new(f)
|
118
|
+
}
|
119
|
+
options.mapencoding=options.encoding
|
120
|
+
options.texencoding=options.encoding
|
121
|
+
end
|
122
|
+
|
123
|
+
if options.mapencoding.instance_of?(String)
|
124
|
+
kpse.open_file(options.mapencoding,"enc") { |f|
|
125
|
+
options.mapencoding = ENC.new(f)
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
if options.texencoding.instance_of?(String)
|
130
|
+
kpse.open_file(options.texencoding,"enc") { |f|
|
131
|
+
options.texencoding = ENC.new(f)
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
if ARGV.size != 2
|
136
|
+
puts "#{File.basename($0)}: Need exactly two file arguments."
|
137
|
+
puts "Try `#{File.basename($0)} --help' for more information."
|
138
|
+
exit 0
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
p1 = plopen(ARGV[0])
|
143
|
+
p2 = plopen(ARGV[1])
|
144
|
+
|
145
|
+
percent = options.delta ? options.delta/50.0 : 0
|
146
|
+
|
147
|
+
[:fontfamily,:codingscheme,:designsize].each { |sym|
|
148
|
+
if p1.send(sym) != p2.send(sym)
|
149
|
+
puts "#{sym} differ: #{p1.send(sym)} vs #{p2.send(sym)}"
|
150
|
+
end
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
fd1 = p1.params
|
155
|
+
fd2 = p2.params
|
156
|
+
str = ""
|
157
|
+
if fd1.size != fd2.size
|
158
|
+
str << "Difference in number of parameters (fontdimen)"
|
159
|
+
end
|
160
|
+
|
161
|
+
paramname=%w( X SLANT SPACE STRETCH SHRINK XHEIGHT QUAD EXTRASPACE )
|
162
|
+
if p1.codingscheme=="TeX math symbols"
|
163
|
+
paramname += %w(NUM1 NUM2 NUM3 DENOM1 DENOM2 SUP1 SUP2 SUP3
|
164
|
+
SUB1 SUB2 SUPDROP)
|
165
|
+
elsif p1.codingscheme=="TeX math extension"
|
166
|
+
paramname += %w(DEFAULT_RULE_THICKNESS BIG_OP_SPACING1
|
167
|
+
BIG_OP_SPACING2 BIG_OP_SPACING3 BIG_OP_SPACING4 BIG_OP_SPACING5)
|
168
|
+
end
|
169
|
+
|
170
|
+
for i in 1..fd1.size
|
171
|
+
next if fd1[i] == fd2[i]
|
172
|
+
if fd1[i]==nil
|
173
|
+
str << "Difference in #{paramname[i]}: nil vs. #{fd2[i]}" << "\n"
|
174
|
+
elsif
|
175
|
+
fd2[i]==nil
|
176
|
+
str << "Difference in #{paramname[i]}: #{fd1[i]} vs. nil" << "\n"
|
177
|
+
elsif (fd1[i] - fd2[i] ).abs > fd1[i] * percent
|
178
|
+
str << "Difference in #{paramname[i]}: #{fd1[i]} vs. #{fd2[i]}" << "\n"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
if str.size > 0
|
183
|
+
puts "--------------------"
|
184
|
+
puts "fondimen difference:"
|
185
|
+
puts str
|
186
|
+
puts "--------------------"
|
187
|
+
end
|
188
|
+
|
189
|
+
exit if options.skip==true
|
190
|
+
str= ""
|
191
|
+
0.upto(255) do |i|
|
192
|
+
a=p1.chars[i]
|
193
|
+
b=p2.chars[i]
|
194
|
+
next unless a and b
|
195
|
+
l1=a[:lig_kern] ? p1.lig_kern[a[:lig_kern]] : nil
|
196
|
+
l2=b[:lig_kern] ? p2.lig_kern[b[:lig_kern]] : nil
|
197
|
+
|
198
|
+
next if a==b and l1==l2
|
199
|
+
|
200
|
+
if a==nil
|
201
|
+
str << "#{i}: no character at this slot in font 1" << "\n"
|
202
|
+
elsif b==nil
|
203
|
+
str << "#{i}: no character at this slot in font 2" << "\n"
|
204
|
+
else
|
205
|
+
chr=""
|
206
|
+
[:charwd, :charht, :chardp, :charic].each { |dim|
|
207
|
+
next if a[dim].to_f==b[dim].to_f
|
208
|
+
if a[dim]==nil
|
209
|
+
chr << " Difference in #{dim}: nil vs. #{b[dim]}" << "\n"
|
210
|
+
elsif b[dim]==nil
|
211
|
+
chr << " Difference in #{dim}: #{b[dim]} vs. nil" << "\n"
|
212
|
+
elsif (a[dim] - b[dim]).abs > a[dim] * percent
|
213
|
+
chr << " Difference in #{dim}: #{a[dim]} vs. #{b[dim]}" << "\n"
|
214
|
+
end
|
215
|
+
}
|
216
|
+
if l1 != l2 and options.ignore_kern != true
|
217
|
+
chr << " Difference in kern information" << "\n"
|
218
|
+
if l1==nil
|
219
|
+
str << " no lig/kern information for first font \n"
|
220
|
+
elsif l2==nil
|
221
|
+
str << " no lig/kern information for second font \n"
|
222
|
+
else
|
223
|
+
chr << " in font1 but not in font 2:" << (l1 - l2).join(" ").to_s << "\n"
|
224
|
+
chr << " in font2 but not in font 1:" << (l2 - l1).join(" ").to_s << "\n"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# if a[:ligkern] and b[:ligkern]
|
229
|
+
# if a[:ligkern][:lig] != b[:ligkern][:lig]
|
230
|
+
# chr << " Difference in lig information" << "\n"
|
231
|
+
# if a[:ligkern][:lig]
|
232
|
+
# a[:ligkern][:lig].each { |lig|
|
233
|
+
# chr << " | " << lig.inspect << "\n"
|
234
|
+
# }
|
235
|
+
# else
|
236
|
+
# chr << "nil"
|
237
|
+
# end
|
238
|
+
# chr << " vs.\n"
|
239
|
+
# if b[:ligkern][:lig]
|
240
|
+
# b[:ligkern][:lig].each { |lig|
|
241
|
+
# chr << " | " << lig.inspect << "\n"
|
242
|
+
# }
|
243
|
+
# else
|
244
|
+
# chr << "nil"
|
245
|
+
# end
|
246
|
+
# end
|
247
|
+
# if a[:ligkern][:krn]
|
248
|
+
# (a[:ligkern][:krn] - b[:ligkern][:krn]).each { |lig|
|
249
|
+
# if options.mapencoding
|
250
|
+
# chr << " | [#{options.mapencoding[lig[0]]} #{lig[1]}]\n"
|
251
|
+
# else
|
252
|
+
# chr << " | " << lig.inspect << "\n"
|
253
|
+
# end
|
254
|
+
# }
|
255
|
+
# else
|
256
|
+
# chr << "nil"
|
257
|
+
# end
|
258
|
+
# chr << " vs.\n"
|
259
|
+
# if b[:ligkern][:krn]
|
260
|
+
# (b[:ligkern][:krn] - a[:ligkern][:krn]).each { |lig|
|
261
|
+
# if options.mapencoding
|
262
|
+
# chr << " | [#{options.mapencoding[lig[0]]} #{lig[1]}]\n"
|
263
|
+
# else
|
264
|
+
# chr << " | " << lig.inspect << "\n"
|
265
|
+
# end
|
266
|
+
# }
|
267
|
+
# else
|
268
|
+
# chr << "nil"
|
269
|
+
# end
|
270
|
+
#end
|
271
|
+
# end
|
272
|
+
if a[:dvi] != b[:dvi]
|
273
|
+
chr << " Difference in map\n"
|
274
|
+
chr << showmap(a[:map])
|
275
|
+
chr << " vs.\n"
|
276
|
+
chr << showmap(b[:map])
|
277
|
+
end
|
278
|
+
|
279
|
+
if chr.length > 0
|
280
|
+
str << "#{i}: "
|
281
|
+
if options.texencoding
|
282
|
+
str << options.texencoding[i]
|
283
|
+
end
|
284
|
+
str << "\n"
|
285
|
+
str << chr
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
if str.length > 0
|
290
|
+
puts "Character entries:"
|
291
|
+
puts "------------------"
|
292
|
+
puts str
|
293
|
+
end
|
294
|
+
|
295
|
+
|