diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/rfil/examples |
Initial commit
Diffstat (limited to 'support/rfil/examples')
-rwxr-xr-x | support/rfil/examples/afm2tfm.rb | 204 | ||||
-rwxr-xr-x | support/rfil/examples/afminfo | 249 | ||||
-rwxr-xr-x | support/rfil/examples/encodingtable | 67 | ||||
-rwxr-xr-x | support/rfil/examples/pldiff | 297 | ||||
-rwxr-xr-x | support/rfil/examples/plinfo | 109 | ||||
-rwxr-xr-x | support/rfil/examples/rfii | 257 | ||||
-rwxr-xr-x | support/rfil/examples/rfont | 185 |
7 files changed, 1368 insertions, 0 deletions
diff --git a/support/rfil/examples/afm2tfm.rb b/support/rfil/examples/afm2tfm.rb new file mode 100755 index 0000000000..8bdc654548 --- /dev/null +++ b/support/rfil/examples/afm2tfm.rb @@ -0,0 +1,204 @@ +#!/usr/bin/env ruby +#-- +# Last Change: Tue May 16 18:10:52 2006 +#++ +=begin rdoc +== afm2tfm using the ruby font installer library +This is a re-implementation of afm2tfm that is part of dvips. This +does not aim for a 100% compatible output. There are some differences +in the calculation of the font metrics, which, in my opinion, are +reasonable. The -u and -o switch are missing from this implementation. + + Usage: afm2tfm.rb [options] FILE[.afm,.ttf] ... [FILE[.tfm]] + -c REAL use REAL for height of small caps made with -V [0.8] + -d DIRNAME Set the base output directory to DIRNAME + -e REAL widen (extend) characters by a factor of REAL + -l Include ligature and kerning information in tfm file + -p ENCFILE read/download ENCFILE for the PostScript encoding + -s REAL oblique (slant) characters by REAL, generally <<1 + -t ENCFILE read ENCFILE for the encoding of the vf file + -T ENCFILE equivalent to -p ENCFILE -t ENCFILE + -v [FILE] make a VF file with filename FILE + -V [SCFILE] like -v, but synthesize smallcaps as lowercase + --help print this message and exit. + --version print version number and exit. + += Usage +See the documentation of the original afm2tfm for an explanation of +the parameters -c, -e, -s, -p, -t, -T, -v and -V. + +afm2tfm.rb creates a tfm (tex font metric) file from the font given as +the first argument. This font can be a Postscript Type 1 font metric +file (afm) or a TrueType font. (So the name of the program is a bit +misleading, it is not restricted to Type 1 font metric files.) The tfm +file is written assuming that the underlying TeX text is encoded in +the encoding given with the -p parameter. + +[<tt>-d</tt> DIRNAME] Set the base directory to DIRNAME. All files are written to the base directory. If unset, use the current directory. +[<tt>-l</tt>] Don't discard the ligature and kerning information when writing the tfm file. +[<tt>-v</tt>, <tt>-V</tt> FILE] The filename of the virtual fonts is optional. When unset, construct a name such as <tt>ec-savorg__-capitalized-800</tt>. +--- +Remark: this is not the reimplementation I mentioned at the 35th NTG meeting. + +Author:: Patrick Gundlach <patrick@gundla.ch> +License:: Copyright (c) 2005 Patrick Gundlach. + Released under the terms of the GNU General Public License +=end + + +# :enddoc: + +# font metric differences between afm2tfm and afm2tfm.rb +# tfm: fix_height is applied before writing out the tfm file, so the height +# of the glpyphs are different. +# slant: charic calculation in the vpl file is not affected by the +# texheight in afm2tfm.c, but in afm2tfm.rb the height is changed +# before cahric calculation +# other: +# in my testfont, the hyphen has a different height in the tfm +# file: 732 (afm2tfm.c) vs. 240 (afm2tfm.rb) + +require 'optparse' +require 'ostruct' +require 'rfil/font' + +include RFIL +options=OpenStruct.new + +ARGV.options { |opt| + opt.banner = "Usage: #{File.basename($0)} [options] FILE[.afm] ... [FILE[.tfm]]" + opt.on("-c REAL", Float, + "use REAL for height of small caps made with -V [0.8]") {|c| + if c and c >= 0.01 + options.capheight=c + else + puts "! Bad small caps height" + exit -1 + end + } + opt.on("-d DIRNAME", String, "Set the base output directory to DIRNAME") {|d| + if File.exists?(d) and File.directory?(d) + options.dirname=d + else + puts "! #{d} does not exist or is not a directory" + exit -1 + end + } + opt.on("-e REAL", Float, "widen (extend) characters by a factor of REAL") {|e| + # this test should be in class AFM + if e and e >= 0.01 + options.efactor=e + else + puts "! Bad extension factor" + exit -1 + end + } + + opt.on("-l", "Include ligature and kerning information in tfm file") { + options.ligkern=true + } + + opt.on("-p ENCFILE", "read/download ENCFILE for the PostScript encoding") {|e| + options.mapenc = e + } + opt.on("-s REAL",Float,"oblique (slant) characters by REAL, generally <<1") {|s| + if s + options.slant=s + else + puts "! Bad slant parameter" + exit -1 + end + } + + opt.on("-t ENCFILE", "read ENCFILE for the encoding of the vf file") {|e| + options.texenc = e + } + opt.on("-T ENCFILE",String,"equivalent to -p ENCFILE -t ENCFILE") {|e| + options.mapenc = e + options.texenc = e + } + opt.on("-v [FILE]", String, "make a VF file with filename FILE") { |v| + options.write_vf=true + options.vffile=v + } + opt.on("-V [SCFILE]","like -v, but synthesize smallcaps as lowercase") { |v| + options.vffile=v + options.write_vf=true + options.fakecaps=true + } + opt.on("--help","print this message and exit.") { puts opt; exit 0 } + opt.on("--version","print version number and exit.") { + puts "#{File.basename($0)}: Version 0.9" + puts "Uses RFI Library (https://foundry.supelec.fr/projects/rfil)" + puts "[Based on afm2tfm(k) (dvips(k) 5.95a) 8.1 (C) 2005 Radical Eye Software.]" + exit + } + opt.parse! +} + +if ARGV.size == 0 + puts "#{File.basename($0)}: Need at least one file argument." + puts "Try `#{File.basename($0)} --help' for more information." + exit 0 +end + +inputfile=ARGV.shift + +if ARGV.size >0 + options.outputfilename=ARGV.shift +end + +font = RFI::Font.new +font.write_vf = options.write_vf + +if options.dirname + font.set_dirs(options.dirname) +end + +begin + font.load_variant(inputfile) +rescue Errno::ENOENT + puts "! Cannot find file #{inputfile}" + exit -1 +end + + +font.texenc=options.texenc || "8a.enc" +font.mapenc=options.mapenc || "8a.enc" + +font.apply_ligkern_instructions(RFI::STDLIGKERN) + +font.efactor=options.efactor || 1.0 +font.slant =options.slant || 0.0 + +ploptions=options.ligkern==true ? {:noligs=>false} : {:noligs=>true} + +fn=font.map_fontname(font.mapenc) + ".tfm" +f=font.to_tfm(font.mapenc,ploptions) +f.tfmpathname=File.join(font.get_dir(:tfm),fn) +f.save(true) + +if options.fakecaps + fc = font.load_variant(inputfile) + font.fake_caps(fc,options.capheight || 0.8) + font.copy(fc,:lowercase,:ligkern=>true) +end + +if options.write_vf + vffilename=if options.vffile + options.vffile + else + font.tex_fontname(font.texenc[0]) + end + vf= File.join(font.get_dir(:vf) ,vffilename+".vf") + tfm=File.join(font.get_dir(:tfm),vffilename+ ".tfm") + vpl=font.to_vf(font.mapenc,font.texenc[0]) + vpl.tfmpathname=File.join(font.get_dir(:tfm) ,vffilename + ".tfm") + vpl.vfpathname=File.join(font.get_dir(:vpl) ,vffilename + ".vf") + vpl.save(true) + # vplfile= File.join(font.get_dir(:vpl) ,vffilename + ".vpl") + # vpl.write_vpl(vplfile) + # vpl.write_vf(vf,tfm) +end +puts font.maplines + diff --git a/support/rfil/examples/afminfo b/support/rfil/examples/afminfo new file mode 100755 index 0000000000..b0f279a3ac --- /dev/null +++ b/support/rfil/examples/afminfo @@ -0,0 +1,249 @@ +#!/usr/bin/env ruby +#-- +# Last Change: Tue May 16 18:09:09 2006 +#++ +=begin rdoc + +== afminfo - print out information about an afm or truetype font file + + Usage: afminfo [options] afm-file.afm | truetypefont.ttf + -m, --metrics show global metrics information + -v, --verbose verbose output + --[no-]info list general information (default) + -l, --list-glyphs list all available glyphs + -g, --glyphinfo g information about a specific glyph + -h, --help Show this help + +--- +Author:: Patrick Gundlach <patrick@gundla.ch> +License:: Copyright (c) 2005 Patrick Gundlach. + Released under the terms of the GNU General Public License +=end + +# :enddoc: + +require 'optparse' +require 'ostruct' +require 'rfil/font/afm' + + +# sorry for german - one day I'll change that into engish. --pg +class TextTable # :nodoc: + def initialize (data,maxchars=80) + raise "Data must be an array of strings" unless data.kind_of? Array + @data = data + + @maxchars = 90 + @maxwidth = 0 + @data.each { |elt| + @maxwidth = @maxwidth > elt.length ? @maxwidth : elt.length + } + @spalten = (@maxchars/(@maxwidth + 1)).floor + end + + def zeilenweise + (0...@data.size).each { |x| + print sprintf("%-" + @maxwidth.to_s + "s",@data[x]) + + if (x+1) % @spalten == 0 + "\n" + else + " " + end + } + puts + end + + def spaltenweise + zeilenmin = (@data.size * 1.0 / @spalten).floor + zeilenmax = (@data.size * 1.0 / @spalten).ceil + anz_volle_spalten = @data.size % @spalten + + verteilung=Array.new() + verteilung[0]=0 + count = 0 + (0...@spalten).each { |col| + if col < anz_volle_spalten + count += zeilenmax + else + count += zeilenmin + end + verteilung[col]= count + } + verteilung.unshift 0 + (0...zeilenmax).each { |zeile| + puts((0...@spalten).collect { |spalte| + w = @data[verteilung[spalte] + zeile] + if (spalte >= anz_volle_spalten) and (zeile >= zeilenmin) + w = "" + end + sprintf("%-" + @maxwidth.to_s + "s",w) + }.join(' ')) + } + end +end + +class AFMinfo # :nodoc: + def initialize (afm) + @afm = afm + @uppercase_letters = ('A'..'Z').collect { |l| l } + @lowercase_letters = ('a'..'z').collect { |l| l } + @digits = %w(one two three four five six seven eight nine zero) + end + def stdformat + "%-18s " + end + def printout (str,value) + puts sprintf(stdformat + "%s", str + ":" ,value.to_s) + end + + def num_to_string (num,reservespace=true) + formatstring = "%" + formatstring << " " if reservespace + formatstring << (num.to_i == num ? "d" : "f") + # output "integer" if value after decimal point is 0 + sprintf(formatstring,num) + end + + def dump_maininfo + puts "General font information:" + puts "=========================" + printout("Filename",@afm.filename) + [ + ["Fontname",:fontname], + ["FullName",:fullname], + ["Family name",:familyname], + ["Weight",:weight], + ["EncodingScheme",:encodingscheme], +# ["·","·"], + ].each { |s,m| + printout(s,@afm.send(m)) + } + puts sprintf(stdformat,'Number of gylphs:') + @afm.count_charmetrics.to_s + + " (encoded: " + @afm.count_charmetrics_encoded.to_s + ", unencoded: " + @afm.count_charmetrics_unencoded.to_s + ")" + + end + def dump_metrics + puts "\n\nGlobal metrics information:" + puts "==========================" + puts sprintf(stdformat,"FontBBox:") + @afm.fontbbox.collect { |f| + num_to_string(f) + }.join(' ') + ' (llx,lly,urx,ury)' + printout('IsFixedPitch',@afm.isfixedpitch) + + [ + ["ItalicAngle", :italicangle], + ["UnderlinePosition", :underlineposition], + ["UnderlineThickness", :underlinethickness], + ["CapHeight", :capheight], + ["XHeight", :xheight], + ["Ascender", :ascender], + ["Descender", :descender] + ].each { |s,m| + puts sprintf(stdformat,s) + num_to_string(@afm.send(m)) + } + end + def dump_glyphinfo (glyph) + chars=@afm.chars[glyph] + puts "\n\nGlyph information (" + glyph + ")" + puts "====================" + puts sprintf(stdformat,"Encoding pos:") + + if chars.c == -1 + "--" + else + sprintf("%d (dec), %x (hex), %o (oct)",chars.c,chars.c,chars.c) + end + puts sprintf(stdformat,"Width x (wx)") + chars.wx.to_s + puts sprintf(stdformat,"Bounding box") + chars.b.collect { |f| + num_to_string(f,false) + }.join(' ') + ' (llx,lly,urx,ury)' + puts "Kerning pairs: (x,y)" + puts "--------------------" + chars.kern_data.each { |k,v| + puts sprintf(stdformat," " + k) + num_to_string(v[0]) + "," + + num_to_string(v[1]) + } + end + def dump_glyphs + chars=@afm.chars + puts "\n\nList of glyphs" + puts "================" + removefromlist=[] + if @uppercase_letters.all? { |glyph| + chars[glyph] + } + puts sprintf(stdformat,"A-Z") + "available" + removefromlist += @uppercase_letters + else + puts sprintf(stdformat,"A-Z") + "some missing" + end + if @lowercase_letters.all? { |glyph| + chars[glyph] + } + puts sprintf(stdformat,"a-z") + "available" + removefromlist += @lowercase_letters + else + puts sprintf(stdformat,"a-z") + "some missing" + end + if @digits.all? { |glyph| + chars[glyph] + } + puts sprintf(stdformat,"one, two, .., zero") + "available" + removefromlist += @digits + else + puts sprintf(stdformat,"one, two, .., zero") + "some missing" + end + puts + glyphlist=[] + chars.each { |glyph,h| + glyphlist.push(glyph + (h.c == -1 ? "*" : "")) + } + glyphlist = glyphlist - removefromlist + glyphlist.sort! { |a,b| + a.casecmp b + } + t = TextTable.new(glyphlist - removefromlist) + t.spaltenweise + puts "\n* = unencoded - only glyphs not mentioned above listed" + end + +end + +options=OpenStruct.new +options.verbose = false +options.metrics = false +options.glyph = nil +options.listglyphs = false +options.generalinfo = true + +ARGV.options { |opt| + opt.banner = "Usage: #{File.basename($0)} [options] afm-file[.afm]" + opt.on("--metrics", "-m", "show global metrics information") { options.metrics=true} + opt.on("--verbose", "-v", "verbose output") { options.verbose=true } + opt.on("--[no-]info", "list general information (default)") { |x| + options.generalinfo=x } + opt.on("--list-glyphs", "-l", "list all available glyphs") { options.listglyphs=true } + opt.on("--glyphinfo g" , "-g", + "information about a specific glyph") { |arg| + options.glyph = arg + } + + opt.on("--help", "-h", "Show this help") { puts opt; exit 0 } + opt.separator "" + opt.separator "Copyright (c) 2005 Patrick Gundlach" + opt.parse! +} + +unless ARGV.size==1 + puts "Please specify one afm-file to read" if ARGV + exit 1 +end + + +# afm=Font::AFM.new(:verbose => options.verbose) +afm=RFIL::Font::Metric.read(ARGV[0],:verbose => options.verbose) + +ai = AFMinfo.new(afm) +ai.dump_maininfo if options.generalinfo +ai.dump_metrics if options.metrics +options.glyph && ai.dump_glyphinfo(options.glyph) +ai.dump_glyphs if options.listglyphs diff --git a/support/rfil/examples/encodingtable b/support/rfil/examples/encodingtable new file mode 100755 index 0000000000..59c12d459d --- /dev/null +++ b/support/rfil/examples/encodingtable @@ -0,0 +1,67 @@ +#!/usr/bin/env ruby -w +#-- +# Last Change: Tue May 16 18:11:49 2006 +#++ +=begin rdoc += encodingtable -- print out a table with different encodings in colums + +This is mainly an example how to use the ENC and Kpathsea class. + +== Usage + encodingtable encoding[.enc] [encoding[.enc] ...] + + +== Example + + $ ./encodingtable ec texnansi 8r 8a + + dec | oct |hex | ECEncoding | TeXnANSIEncoding | TeXBase1Encoding | StandardEncoding | + -------------------------------------------------------------------------------------------- + 0 | 0 | 0 | grave | --- | --- | --- | + 1 | 1 | 1 | acute | Euro | dotaccent | --- | + 2 | 2 | 2 | circumflex | --- | fi | --- | + 3 | 3 | 3 | tilde | --- | fl | --- | + 4 | 4 | 4 | dieresis | fraction | fraction | --- | + 5 | 5 | 5 | hungarumlaut | dotaccent | hungarumlaut | --- | + ... +--- +Author:: Patrick Gundlach <patrick@gundla.ch> +=end + +# :enddoc: + +require 'rfil/tex/enc' +require 'rfil/tex/kpathsea' + +include RFIL +include TeX + +unless ARGV.size > 0 + puts "Usage: #{File.basename($0)} encoding[.enc] ..." + exit +end + +fmt=" %-16.16s |" + +encodings=[] +kpse=Kpathsea.new +ARGV.each { |e| + kpse.open_file(e.chomp('.enc')+'.enc','enc') { |f| + encodings.push(ENC.new(f)) + } +} + + +print "dec | oct |hex |" +encodings.each { |e| print sprintf(fmt,e.encname) } + + +0.upto(255) { |slot| + print "\n"+"-"*(16 + encodings.size * 19 ) if slot % 32 == 0 + + print sprintf("\n%3d | %3o | %2x |", slot,slot,slot) + encodings.each { |e| + print sprintf(fmt, e[slot]==".notdef" ? "---" : e[slot]) + } +} +puts diff --git a/support/rfil/examples/pldiff b/support/rfil/examples/pldiff new file mode 100755 index 0000000000..0cad686667 --- /dev/null +++ b/support/rfil/examples/pldiff @@ -0,0 +1,297 @@ +#!/usr/bin/env ruby +#-- +# Last Change: Tue May 16 18:13:36 2006 +#++ +=begin rdoc + +== pldiff -- show the differences between two (v)pl files. + + Usage: pldiff [options] file file + file can be tfm, pl, vpl or vf files. + -d, --delta DELTA Don't report differences whithin +/- DELTA percent + -c, --ignore-comments ignore comments + -k, --ignore-kern ignore difference in kerning information + -m, --mapenc ENC assume encoding ENC for destination encoding + -t, --texenc ENC assume encoding ENC for source encoding (TeX side) + -e, --encoding ENC assume encoding ENC for both in and out + -s, --skip-characters only look at fontdimen and main data + + -h, --help Show this help + + +--- +Author:: Patrick Gundlach <patrick@gundla.ch> +License:: Copyright (c) 2005 Patrick Gundlach. + Released under the terms of the GNU General Public License + +=end + +# :enddoc: + +require 'optparse' +require 'ostruct' + +require 'rfil/tex/kpathsea' +require 'rfil/tex/enc' +require 'rfil/tex/tfm' +require 'rfil/tex/vf' + +include RFIL + + +def showmap(mapary) + str = "" + if mapary + mapary.each { |entry| + str << " | " << entry.join(" ") << "\n" + } + end + str +end + +def plopen(filename) + case filename + when /\.tfm$/ + return TFM.new.read_tfm(filename) + when /\.vf$/ + # change to that dir first + currentdir=Dir.getwd + dirname=File.dirname(filename) + Dir.chdir(dirname) + fn=File.basename(filename) + vf=VF.new.read_vf(filename) + Dir.chdir(currentdir) + return vf + when /\.pl$/ + return TFM.new.read_pl(filename) + when /\.vpl$/ + return TFM.new.read_pl(filename) + else + puts "Unknown format: #{filename}" + exit 1 + end +end + +include TeX +options=OpenStruct.new +kpse=Kpathsea.new + +ARGV.options { |opts| + opts.banner = "Usage: #{File.basename($0)} [options] file file" + opts.separator "file can be tfm, pl, vpl or vf files." + + opts.on("--delta","-d DELTA", Float, + "Don't report differences whithin +/- DELTA percent") { |d| + options.delta=d + } + opts.on("--ignore-comments", "-c", "ignore comments") { |i| + options.ignore_comments=true + } + opts.on("--ignore-kern", "-k", "ignore difference in kerning information") { |k| + options.ignore_kern=true + } + + opts.on("--mapenc", "-m ENC", + "assume encoding ENC for destination encoding") {|e| + options.mapencoding=e + } + + opts.on("--texenc", "-t ENC", + "assume encoding ENC for source encoding (TeX side)") {|e| + options.texencoding=e + } + + opts.on("--encoding", "-e ENC", + "assume encoding ENC for both in and out") {|e| + options.encoding=e + } + opts.on("--skip-characters", "-s", "only look at fontdimen and main data") {|s| + options.skip=true + } + opts.on_tail("--help", "-h", "Show this help") { puts opts; exit 0 } + opts.separator "" + opts.parse! +} + +# untested: +if options.encoding + kpse.open_file(options.encoding,"enc") { |f| + options.encoding = ENC.new(f) + } + options.mapencoding=options.encoding + options.texencoding=options.encoding +end + +if options.mapencoding.instance_of?(String) + kpse.open_file(options.mapencoding,"enc") { |f| + options.mapencoding = ENC.new(f) + } +end + +if options.texencoding.instance_of?(String) + kpse.open_file(options.texencoding,"enc") { |f| + options.texencoding = ENC.new(f) + } +end + +if ARGV.size != 2 + puts "#{File.basename($0)}: Need exactly two file arguments." + puts "Try `#{File.basename($0)} --help' for more information." + exit 0 +end + + +p1 = plopen(ARGV[0]) +p2 = plopen(ARGV[1]) + +percent = options.delta ? options.delta/50.0 : 0 + +[:fontfamily,:codingscheme,:designsize].each { |sym| + if p1.send(sym) != p2.send(sym) + puts "#{sym} differ: #{p1.send(sym)} vs #{p2.send(sym)}" + end +} + + +fd1 = p1.params +fd2 = p2.params +str = "" +if fd1.size != fd2.size + str << "Difference in number of parameters (fontdimen)" +end + +paramname=%w( X SLANT SPACE STRETCH SHRINK XHEIGHT QUAD EXTRASPACE ) +if p1.codingscheme=="TeX math symbols" + paramname += %w(NUM1 NUM2 NUM3 DENOM1 DENOM2 SUP1 SUP2 SUP3 + SUB1 SUB2 SUPDROP) +elsif p1.codingscheme=="TeX math extension" + paramname += %w(DEFAULT_RULE_THICKNESS BIG_OP_SPACING1 + BIG_OP_SPACING2 BIG_OP_SPACING3 BIG_OP_SPACING4 BIG_OP_SPACING5) +end + +for i in 1..fd1.size + next if fd1[i] == fd2[i] + if fd1[i]==nil + str << "Difference in #{paramname[i]}: nil vs. #{fd2[i]}" << "\n" + elsif + fd2[i]==nil + str << "Difference in #{paramname[i]}: #{fd1[i]} vs. nil" << "\n" + elsif (fd1[i] - fd2[i] ).abs > fd1[i] * percent + str << "Difference in #{paramname[i]}: #{fd1[i]} vs. #{fd2[i]}" << "\n" + end +end + +if str.size > 0 + puts "--------------------" + puts "fondimen difference:" + puts str + puts "--------------------" +end + +exit if options.skip==true +str= "" +0.upto(255) do |i| + a=p1.chars[i] + b=p2.chars[i] + next unless a and b + l1=a[:lig_kern] ? p1.lig_kern[a[:lig_kern]] : nil + l2=b[:lig_kern] ? p2.lig_kern[b[:lig_kern]] : nil + + next if a==b and l1==l2 + + if a==nil + str << "#{i}: no character at this slot in font 1" << "\n" + elsif b==nil + str << "#{i}: no character at this slot in font 2" << "\n" + else + chr="" + [:charwd, :charht, :chardp, :charic].each { |dim| + next if a[dim].to_f==b[dim].to_f + if a[dim]==nil + chr << " Difference in #{dim}: nil vs. #{b[dim]}" << "\n" + elsif b[dim]==nil + chr << " Difference in #{dim}: #{b[dim]} vs. nil" << "\n" + elsif (a[dim] - b[dim]).abs > a[dim] * percent + chr << " Difference in #{dim}: #{a[dim]} vs. #{b[dim]}" << "\n" + end + } + if l1 != l2 and options.ignore_kern != true + chr << " Difference in kern information" << "\n" + if l1==nil + str << " no lig/kern information for first font \n" + elsif l2==nil + str << " no lig/kern information for second font \n" + else + chr << " in font1 but not in font 2:" << (l1 - l2).join(" ").to_s << "\n" + chr << " in font2 but not in font 1:" << (l2 - l1).join(" ").to_s << "\n" + end + end + +# if a[:ligkern] and b[:ligkern] +# if a[:ligkern][:lig] != b[:ligkern][:lig] +# chr << " Difference in lig information" << "\n" +# if a[:ligkern][:lig] +# a[:ligkern][:lig].each { |lig| +# chr << " | " << lig.inspect << "\n" +# } +# else +# chr << "nil" +# end +# chr << " vs.\n" +# if b[:ligkern][:lig] +# b[:ligkern][:lig].each { |lig| +# chr << " | " << lig.inspect << "\n" +# } +# else +# chr << "nil" +# end +# end +# if a[:ligkern][:krn] +# (a[:ligkern][:krn] - b[:ligkern][:krn]).each { |lig| +# if options.mapencoding +# chr << " | [#{options.mapencoding[lig[0]]} #{lig[1]}]\n" +# else +# chr << " | " << lig.inspect << "\n" +# end +# } +# else +# chr << "nil" +# end +# chr << " vs.\n" +# if b[:ligkern][:krn] +# (b[:ligkern][:krn] - a[:ligkern][:krn]).each { |lig| +# if options.mapencoding +# chr << " | [#{options.mapencoding[lig[0]]} #{lig[1]}]\n" +# else +# chr << " | " << lig.inspect << "\n" +# end +# } +# else +# chr << "nil" +# end + #end +# end + if a[:dvi] != b[:dvi] + chr << " Difference in map\n" + chr << showmap(a[:map]) + chr << " vs.\n" + chr << showmap(b[:map]) + end + + if chr.length > 0 + str << "#{i}: " + if options.texencoding + str << options.texencoding[i] + end + str << "\n" + str << chr + end + end +end +if str.length > 0 + puts "Character entries:" + puts "------------------" + puts str +end + + diff --git a/support/rfil/examples/plinfo b/support/rfil/examples/plinfo new file mode 100755 index 0000000000..1ceda6c5cb --- /dev/null +++ b/support/rfil/examples/plinfo @@ -0,0 +1,109 @@ +#!/usr/bin/env ruby +#-- +# Last Change: Tue May 16 18:14:38 2006 +#++ +=begin rdoc +== plinfo -- output information about a pl file. + + Usage: plinfo [options] tfmfile.pl [file...] + -e, --encoding enc set the encoding for the file + -l, --list-chars list all available characters + -h, --help Show this help + + +--- +Author:: Patrick Gundlach <patrick@gundla.ch> +License:: Copyright (c) 2005 Patrick Gundlach. + Released under the terms of the GNU General Public License +=end + + +# :enddoc: + +require 'optparse' +require 'ostruct' + +require 'rfil/tex/tfm' +require 'rfil/tex/kpathsea' +require 'rfil/tex/enc' + +include RFIL +include TeX + +kpse=Kpathsea.new + +@options=OpenStruct.new + +ARGV.options { |opt| + opt.banner = "Usage: #{File.basename($0)} [options] tfmfile.pl [file...]" + opt.on("--encoding enc", "-e", "set the encoding for the file") { |e| + kpse.open_file(e,"enc") { |f| + @options.encoding = ENC.new(f) + } + } + opt.on("--list-chars", "-l", "list all available characters") { + @options.listchars=true } + opt.on("--help", "-h", "Show this help") { puts opt; exit 0 } + opt.separator "" + opt.parse! +} + +if ARGV.size < 1 + puts "#{File.basename($0)}: Need at least one file argument." + puts "Try `#{File.basename($0)} --help' for more information." + exit 0 +end + + +def dump_maininfo(filename) + puts "General font information:" + puts "=========================" + print "filename=#{File.basename(filename)} " + # puts @isvpl ? "(vpl)" : "(pl)" + puts "Family: #{@tfm.fontfamily}" + puts "Designsize: #{@tfm.designsize}" + puts "Codingscheme: #{@tfm.codingscheme}" + puts "Fontdimen:" + paramname=%w( SLANT SPACE STRETCH SHRINK XHEIGHT QUAD EXTRASPACE ) + if @tfm.codingscheme=="TeX math symbols" + paramname += %w(NUM1 NUM2 NUM3 DENOM1 DENOM2 SUP1 SUP2 SUP3 + SUB1 SUB2 SUPDROP) + elsif @tfm.codingscheme=="TeX math extension" + paramname += %w(DEFAULT_RULE_THICKNESS BIG_OP_SPACING1 + BIG_OP_SPACING2 BIG_OP_SPACING3 BIG_OP_SPACING4 BIG_OP_SPACING5) + end + + (1..@tfm.params.size-1).each {|i| + puts " #{paramname[i-1]} = #{@tfm.params[i]}" + } +end + +def dump_charsinfo + stdformat="%9s|" + count=0 + 0.upto(255) { |i| + if c=@tfm.chars[i] + if count % 32 == 0 + puts "\n slot| width | height | depth | ic |lig/kern?| extra | char" + puts "-----|---------|---------|---------|---------|---------|---------|-------" + end + + has_krn= c[:lig_kern] ? "yes" : "" + extra = "" + char = @options.encoding ? @options.encoding[i] : "" + puts sprintf("%5s|"+stdformat*6+" %s", "#{i}","#{c[:charwd]}","#{c[:charht]}","#{c[:chardp]}","#{c[:charic]}", has_krn,"",char) + count += 1 + + end + + } +end + +ARGV.each { |plfilename| + @tfm=TFM.new() + @tfm.read_pl(plfilename) + dump_maininfo(plfilename) + if @options.listchars + dump_charsinfo + end +} diff --git a/support/rfil/examples/rfii b/support/rfil/examples/rfii new file mode 100755 index 0000000000..2e80a2ef86 --- /dev/null +++ b/support/rfil/examples/rfii @@ -0,0 +1,257 @@ +#!/usr/bin/env ruby + +# :enddoc: + +require 'pp' +require 'ostruct' +require 'fileutils' + + +require 'rfil/fontcollection' +require 'rfil/tex/kpathsea' + +$:.unshift File.dirname($0) +require 'rfii.tab' + + +class RFII # :nodoc: + include RFIL + include TeX + + def initialize + @instructions=[] + @known_encodings=Hash.new + @fontset=nil + @kpse=Kpathsea.new + @known_outputfiles=[:vf,:sty,:tfm,:typescript,:fd,:map] + @fontfiles_copied=nil + @vendor=nil + @texencodings=[] + @psencoding=[] + @fontroot=File.expand_path(Dir.pwd) + @options=OpenStruct.new + @options.verbose=false + @options.dryrun=false + @options.tds=true + @fc=nil + end + + def parse_file(filename) + f=File.open(filename) + @s=StringScanner.new(f.read) + f.close + @mode=:normal + @line=1 + yyparse(self,:scan) + end + + def on_error(error_token_id,error_value,value_stack) + # puts "error" + error=token_to_str(error_token_id) + p error_value,value_stack + puts "parse error near line #@line, exiting, next string: '#{error_value}#{@s.rest[0..20]}...'" + exit 1 + # the default action would be: + # raise ParseError + end + + def ensure_encoding(enc) + unless @known_encodings.has_key?(enc) + puts "Unknown encoding #{enc} in line #{@line}" + exit 1 + end + end + + def get_encodings(symbols) + symbols.collect { |encoding| + ensure_encoding(encoding) + @known_encodings[encoding] + } + end + def get_encoding(symbol) + return :none if symbol==:none or symbol==:same_as_texencoding + ensure_encoding(symbol) + @known_encodings[symbol] + end + + def get_fonts(ident) + towrite=[] + case ident + when [:all],nil + towrite=@fontset.keys + else + towrite=ident + end + fontlist=[] + towrite.each{ |font| + if @fontset.has_key?(font) + fontlist << @fontset[font] + else + puts "Font for #{ident} in line #{@line} unknown, ignoring" + end + } + fontlist + end + def run_instructions + @instructions.each { |line,i| + @line=line + instr,*rest=i + case instr + when :useencoding + # this should be in parser: + if rest[1]==:none or rest[1]==:same_as_texencoding + puts "invalid encoding name" + exit 1 + end + @kpse.open_file(rest[0],"enc") { |encfile| + @known_encodings[rest[1]]=ENC.new(encfile) + } + when :psencoding + @psencoding=get_encoding(rest[0]) + when :texencoding + @texencodings=get_encodings(rest[0]) + when :fontroot + @fontroot=File.expand_path(rest[0]) + unless File.exists?(@fontroot) and File.directory?(@fontroot) + puts "fontroot (#{@fontroot})is not a valid directory" + exit 1 + end + when :fontsource + @fontsource=File.expand_path(rest[0]) + unless File.exists?(@fontsource) and File.directory?(@fontsource) + puts "fontsource (#{@fontsource})is not a valid directory" + exit 1 + end + when :newfont + @fontset={} + @fontfiles_copied={} + @fc=RFI::FontCollection.new + @fc.options[:dryrun]=@options.dryrun + @fc.options[:verbose]=@options.verbose + @fc.vendor=@vendor + @fc.name=rest[0] + @fc.set_dirs({:base=>@fontroot, :tds=>@options.tds}) + @fc.mapenc=@psencoding + @fc.texenc=@texencodings + @fc.style=rest[1] + when :useafm + fontfilename=rest[0] + ident=rest[1] + srcpath=File.join(@fontsource,fontfilename) + unless @fontfiles_copied.has_key?(fontfilename) and @options.copyfonts + @fontfiles_copied[fontfilename]=true # dummy value, used as Set + + if @options.verbose + puts "copy #{srcpath} to #{@fc.dirs[:afm]}" + end + unless @options.dryrun + @fc.ensure_dir(@fc.dirs[:afm]) + FileUtils.cp(srcpath,@fc.dirs[:afm]) + end + if @options.verbose + puts "copy #{srcpath.chomp(".afm")}.pfb to #{@fc.dirs[:type1]}" + end + unless @options.dryrun + @fc.ensure_dir(@fc.dirs[:type1]) + FileUtils.cp(srcpath.chomp(".afm")+".pfb",@fc.dirs[:type1]) + end + end + f=RFI::Font.new(@fc) + i=f.load_variant(File.join(@fontsource,fontfilename)) + @fontset[ident]=f + case ident + when :italic + f.variant=:italic + when :slanted + f.variant=:slanted + when :bold + f.weight=:bold + when :bolditalic + f.variant=:italic + f.weight=:bold + when :boldslanted + f.variant=:slanted + f.weight=:bold + when :smallcaps + f.variant=:smallcaps + end + when :write + # p rest + texencodings = if rest[2] + get_encodings(rest[2]) + else + @texencodings + end + + psencoding = rest[3] ? get_encoding(rest[3]) : @psencoding + rest[0].each { |filetype| + case filetype + when :vf + get_fonts(rest[1]).each { |font| + font.texenc=texencodings + font.mapenc=psencoding + font.write_files({:mapfile=>false}) + } + when :map + m = get_fonts(rest[1]).collect { |font| + font.texenc=texencodings + font.mapenc=psencoding + font.maplines + } + mapdir=@fc.get_dir(:map); @fc.ensure_dir(mapdir) + mapfilename=File.join(mapdir,@fc.name+".map") + if @options.verbose + puts "writing mapfile to #{mapfilename}" + end + unless @options.dryrun + File.open(mapfilename, "w") {|file| + file.puts m + } + end + when :fd + @fc.run_temps(:latex) + when :typescript + @fc.run_temps(:context) + else + puts "unknown filetype: #{filetype}, ignoring" + end + } + when :vendor + @vendor=rest[0] + if @fc and @fc.respond_to?(:vendor=) + @fc.vendor=@vendor + end + when :set + kw,values=rest + case kw + when :verbose,:dryrun,:tds,:copyfonts + if [:true,:false].member?(values) + @options.send(kw.to_s+"=",values==:true) + else + puts "Warning: unkown value for '#{kw}' in line #{@line}, must be one of 'true' or 'false'" + end + end + when :apply + instr=rest[0] + case instr + when :slant + font=rest[1] + # p @fontset.has_key?(font) + @fontset[font].slant=0.167 + else + puts "Unknown instruction (#{instr}) for apply in line #{@line}. Exiting." + end + else + puts "Unknown instruction (#{instr}) in line #{@line}. Exiting." + exit 1 + end + } + # p @psencoding + # p @texencodings + # pp @fc + end +end + +parser = RFII.new +parser.parse_file("test/inputfile") +parser.run_instructions diff --git a/support/rfil/examples/rfont b/support/rfil/examples/rfont new file mode 100755 index 0000000000..a49b667053 --- /dev/null +++ b/support/rfil/examples/rfont @@ -0,0 +1,185 @@ +#!/usr/bin/env ruby +#-- +# Last Change: Tue May 16 21:01:40 2006 +#++ +=begin rdoc += rfont -- An example font installer + +rfont uses the RFI Library for installing a family of fonts. + +== Command line parameters +Usage: rfont [options] vendor/fontname FILE1 FILE2 ... + -c, --copy-fonts Also copy the font outlines + -d, --directory DIR Set base directory to DIR + --dry-run dry run, don't create any files + -m, --list-plugin list available macro support methods + -p ENCFILE read/download ENCFILE for the PostScript encoding + -s, --style STYLE Style of the font, eg. sans, roman, typewriter + --tds Put files in a TDS compliant directory hierarchy + -t ENCFILE read ENCFILE for the encoding of the vf file + multiple encodings can be given (seperated by ',') + -T ENCFILE equivalent to -p ENCFILE -t ENCFILE + -u, --use-plugin PLUGIN use plugin files PLUGIN, multiple files seperated by ',' + -v, --no-vf Do not create virtual fonts for reencoding + --verbose Print more then needed on stdout + --help print this message and exit. + --version print version number and exit. + +== Example usage +This is the command line I used to install the Bitstream variant of the font 'Syntax' (from the Corel Draw CD) + + ./rfont bitstream/syntax ../corel/hum531*afm -t ec,ts1 -p 8r -d ~/rfitexmf/ -u latex -s sans --verbose --tds -c + +It works, but the <tt>.fd</tt>-file is not perfect yet. +--- +Author:: Patrick Gundlach <patrick@gundla.ch> +License:: Copyright (c) 2005 Patrick Gundlach. + Released under the terms of the GNU General Public License + +=end + +# :enddoc: + +require 'optparse' +require 'ostruct' +require 'fileutils' + +require 'rfil/fontcollection' + +include RFIL + +options=OpenStruct.new +optionswritevf=true +fc=RFI::FontCollection.new + +ret= ARGV.options { |opts| + opts.banner = "Usage: #{File.basename($0)} [options] vendor/fontname FILE1 FILE2 ..." + opts.on("-c", "--copy-fonts", "Also copy the font outlines") { + options.copyfonts=true + } + + opts.on("-d DIR", "--directory", "Set base directory to DIR") { |d| + fc.set_dirs(d) + } + opts.on("--dry-run", "dry run, don't create any files") { + fc.options[:dryrun]=true + options.dryrun=true + } + opts.on("-m", "--list-plugin", "list available plugins") { + puts "The following plugins are known:" + puts fc.plugins + exit 0; + } + opts.on("-p ENCFILE", String, + "read/download ENCFILE for the PostScript encoding") {|e| + fc.mapenc = e + } + opts.on("-s STYLE", "--style", String, "Style of the font, eg. sans, roman, typewriter") { |s| + fc.style=s.to_sym + } + opts.on("--tds", "Put files in a TDS compliant directory hierarchy") { + options.tds=true + } + opts.on("-t ENCFILE",Array, "read ENCFILE for the encoding of the vf file", + "multiple encodings can be given (seperated by ',')") {|e| + fc.texenc = e + } + opts.on("-T ENCFILE",String,"equivalent to -p ENCFILE -t ENCFILE") {|e| + fc.mapenc = e + fc.texenc = e + } + opts.on("-u PLUGIN","--use-plugin",Array, "use plugin PLUGIN, multiple files seperated by ','") { |m| + options.plugin=m + } + opts.on("-v", "--no-vf", "Do not create virtual fonts for reencoding") { + fc.write_vf=false + } + opts.on("--verbose","Print more then needed on stdout") { + options.verbose=true + fc.options[:verbose]=true + } + opts.on_tail("--help","print this message and exit.") { puts opts; exit 0 } + opts.on_tail("--version","print version number and exit.") { + puts "#{File.basename($0)}: Version 0.1" + exit 0 + } + opts.parse! +} +unless ret + puts "See --help for usage information" + exit(-1) +end + + +vendor_fontname=ARGV.shift + +if vendor_fontname + options.vendor,options.fontname=vendor_fontname.split('/') +end +if options.vendor==nil or options.fontname==nil + puts "You must name vendor and fontname this way: vendor/fontname" + puts "See --help for usage information" + exit(-1) +end + + + +fc.name=options.fontname +fc.vendor=options.vendor + +fc.set_dirs(:tds=>true) if options.tds + +fonts=[] +maplines="" + + +fontoutlinedir=File.dirname(ARGV[0]) + +ARGV.each { |fontname| + # puts "reading font #{File.basename(fontname)}" + f=RFI::Font.new(fc) + f.load_variant(fontname) + fonts.push f +} + +fc.fonts.each { |font| + puts "Processing font #{font.defaultfm.fontname}" + font.guess_weight_variant + font.apply_ligkern_instructions(RFI::STDLIGKERN) + font.write_files(:dryrun=>options.dryrun==true, + :verbose=>false, :mapfile=>false + ) + maplines << font.maplines.to_s +} + + +if options.copyfonts + fc.fonts.each { |font| + font.find_used_fonts.each {|varnumber| + fontmetric=font.variants[varnumber] + destdir=font.get_dir(fontmetric.outlinetype) + sourcefile=File.join(fontoutlinedir,fontmetric.fontfilename) + destfile=File.join(destdir,fontmetric.fontfilename) + puts "Copying #{sourcefile} to #{destfile}" if options.verbose + fc.ensure_dir(destdir) + unless options.dryrun + FileUtils.cp(sourcefile,destfile) + end + } + } +end + +mapdir=fc.get_dir(:map) +mapfile=File.join(mapdir,options.fontname) +puts "Writing mapfile #{mapfile}" if options.verbose +unless fc.options[:dryrun] + fc.ensure_dir(mapdir) + File.open(mapfile + ".map", "w") { |f| + f << maplines + } +end + +if options.plugin + options.plugin.each { |m| fc.run_plugin(m.to_sym) } +end + |