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
@@ -0,0 +1,135 @@
|
|
1
|
+
# font/metric.rb - superclass for different font metric formats
|
2
|
+
# Last Change: Mi 24 Mai 2006 16:13:14 CEST
|
3
|
+
|
4
|
+
require 'rfil/font/glyph'
|
5
|
+
#require 'font/afm'
|
6
|
+
#require 'font/truetype'
|
7
|
+
|
8
|
+
module RFIL
|
9
|
+
module Font
|
10
|
+
# FontMetric is the superclass for font metrics. All information that
|
11
|
+
# is not specific to a certain kind of file format is accessible via
|
12
|
+
# this class.
|
13
|
+
|
14
|
+
class Metric
|
15
|
+
# to make Rdoc and Ruby happy: [ruby-talk:147778]
|
16
|
+
def self.documented_as_accessor(*args) # :nodoc:
|
17
|
+
end
|
18
|
+
def self.documented_as_reader(*args) # :nodoc:
|
19
|
+
end
|
20
|
+
|
21
|
+
# :type1, :truetype
|
22
|
+
attr_accessor :outlinetype
|
23
|
+
|
24
|
+
# Hash of glyphs in the font.
|
25
|
+
attr_accessor :chars
|
26
|
+
|
27
|
+
# The filename of the just read metric file. Does not contain the
|
28
|
+
# path. To set, change the pathname
|
29
|
+
documented_as_reader :filename
|
30
|
+
|
31
|
+
# Absolute pathname of the metric file. Not checked when set.
|
32
|
+
attr_accessor :pathname
|
33
|
+
|
34
|
+
# File name of the font containing the outlines (the file that needs
|
35
|
+
# to be put into the pdf-file). The .tt or the .pfb file. If unset
|
36
|
+
# use the value of filename, but changed to the correct extension in
|
37
|
+
# case of Type 1 fonts.
|
38
|
+
documented_as_accessor :fontfilename
|
39
|
+
|
40
|
+
# Some unique name of the font. Use the filename of the font or a
|
41
|
+
# name after the KB naming schema. Do not add an extension such as
|
42
|
+
# afm or tt.
|
43
|
+
attr_accessor :name
|
44
|
+
|
45
|
+
# family name of the font
|
46
|
+
attr_accessor :familyname
|
47
|
+
|
48
|
+
# xheight in 1/1000 of an em
|
49
|
+
attr_accessor :xheight
|
50
|
+
|
51
|
+
attr_accessor :weight
|
52
|
+
|
53
|
+
# natural width of a space
|
54
|
+
documented_as_reader :space
|
55
|
+
|
56
|
+
attr_accessor :italicangle
|
57
|
+
|
58
|
+
# True if the font is a monospaced font (courier for example).
|
59
|
+
attr_accessor :isfixedpitch
|
60
|
+
|
61
|
+
# The official name of the font as supplied by the vendor. Written
|
62
|
+
# as FontName in the afm file.
|
63
|
+
attr_accessor :fontname
|
64
|
+
|
65
|
+
# The full name of the font, whatever this means. Written as
|
66
|
+
# FullName in the afm file.
|
67
|
+
attr_accessor :fullname
|
68
|
+
|
69
|
+
# Class for new glyphs. Default is Glyph
|
70
|
+
attr_accessor :glyph_class
|
71
|
+
|
72
|
+
def Metric.read(filename,options={})
|
73
|
+
case File.extname(filename)
|
74
|
+
when ".afm"
|
75
|
+
require 'rfil/font/afm'
|
76
|
+
return AFM.new(options).read(filename)
|
77
|
+
when ".ttf"
|
78
|
+
require 'rfil/font/truetype'
|
79
|
+
return TrueType.new(options).read(filename)
|
80
|
+
else
|
81
|
+
raise ArgumentError, "Unknown filetype: #{File.basename(filename)}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def initialize
|
86
|
+
@chars=Hash.new
|
87
|
+
@xheight=nil
|
88
|
+
@glyph_class=Glyph
|
89
|
+
@outlinetype=nil
|
90
|
+
@info={}
|
91
|
+
@fontfilename=nil
|
92
|
+
@efactor=1.0
|
93
|
+
@slantfactor=0.0
|
94
|
+
@pathname=nil
|
95
|
+
end
|
96
|
+
|
97
|
+
# Factory for new glyphs. Return new instance of glyph_class (see
|
98
|
+
# Attributes).
|
99
|
+
def new_glyph
|
100
|
+
@glyph_class.new
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
def space # :nodoc:
|
105
|
+
chars['space'].wx
|
106
|
+
end
|
107
|
+
|
108
|
+
def filename # :nodoc:
|
109
|
+
File.basename(@pathname)
|
110
|
+
end
|
111
|
+
|
112
|
+
def fontfilename= (obj) # :nodoc:
|
113
|
+
@fontfilename=obj
|
114
|
+
end
|
115
|
+
|
116
|
+
# This one is documented in the 'attributes' section. If the global
|
117
|
+
# variable is unset, just use @filename, perhaps change afm to pfb
|
118
|
+
def fontfilename # :nodoc:
|
119
|
+
return @fontfilename if @fontfilename
|
120
|
+
case filename
|
121
|
+
when /\.afm$/
|
122
|
+
return filename.chomp(".afm") + ".pfb"
|
123
|
+
when /\.tt$/
|
124
|
+
return filename
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Return all relevant part of pyhsical font. May be used for
|
129
|
+
# copying all files.
|
130
|
+
def fontfilenames
|
131
|
+
raise ScriptError, "not implemented"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# truetype.rb -- read truetype font metrics
|
2
|
+
#--
|
3
|
+
# Last Change: Mi 24 Mai 2006 16:42:47 CEST
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'rfil/font/afm'
|
7
|
+
|
8
|
+
module RFIL
|
9
|
+
module Font
|
10
|
+
# Read TrueType fonts. Use like the AFM class.
|
11
|
+
class TrueType < AFM
|
12
|
+
def initialize(options={})
|
13
|
+
super
|
14
|
+
@outlinetype=:truetype
|
15
|
+
end
|
16
|
+
|
17
|
+
# all relevant filenames of the font
|
18
|
+
def fontfilenames
|
19
|
+
return {:truetype => File.basename( @fontfilename || filename) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def read(filename)
|
23
|
+
@filename=File.basename(filename)
|
24
|
+
@fontfilename=filename
|
25
|
+
@name=@filename.chomp(".ttf")
|
26
|
+
self.pathname=Pathname.new(filename).realpath.to_s
|
27
|
+
a=`ttf2afm #{@fontfilename}`
|
28
|
+
parse(a)
|
29
|
+
# ttf2afm does not give an xheight!?
|
30
|
+
@xheight=@chars['x'].ury unless @xheight
|
31
|
+
self
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
#--
|
2
|
+
# fontcollection.rb
|
3
|
+
# Last Change: Tue May 16 19:02:11 2006
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'rfil/rfi'
|
7
|
+
require 'rfil/font'
|
8
|
+
require 'rfil/helper'
|
9
|
+
|
10
|
+
module RFIL # :nodoc:
|
11
|
+
class RFI
|
12
|
+
# A set of fonts (regular,bold,italic). Used to write an fd-file for
|
13
|
+
# LaTeX or a typescript for ConTeXt. Register different fonts and set
|
14
|
+
# encodings, so you dont't have to specify them in each font.
|
15
|
+
|
16
|
+
class FontCollection
|
17
|
+
include Helper
|
18
|
+
def self.documented_as_accessor(*args) # :nodoc:
|
19
|
+
end
|
20
|
+
def self.documented_as_reader(*args) # :nodoc:
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :vendor
|
24
|
+
|
25
|
+
# attr_accessor :fontname
|
26
|
+
|
27
|
+
# Name of the font (collection)
|
28
|
+
attr_accessor :name
|
29
|
+
|
30
|
+
# One object or one or more objects in an array that describe the
|
31
|
+
# encoding of the postscript font. Object can either be a string
|
32
|
+
# that represents the filename of the encoding ("8r.enc", "8r") or
|
33
|
+
# an ENC object that already contains the encoding
|
34
|
+
documented_as_accessor :mapenc
|
35
|
+
|
36
|
+
# One object or one ore more objects in an array that describe the
|
37
|
+
# encoding of the font TeX expects. Object can either be a string
|
38
|
+
# that represents the filename of the encoding ("8r.enc", "8r") or
|
39
|
+
# an ENC object that already contains the encoding
|
40
|
+
documented_as_accessor :texenc
|
41
|
+
|
42
|
+
# hash of directories for writing files. Default to current working
|
43
|
+
# directory. The setting in the Font object overrides the setting here.
|
44
|
+
attr_accessor :dirs
|
45
|
+
|
46
|
+
attr_accessor :fonts
|
47
|
+
|
48
|
+
# sans, roman, typewriter
|
49
|
+
attr_accessor :style
|
50
|
+
|
51
|
+
attr_accessor :write_vf
|
52
|
+
|
53
|
+
attr_accessor :options
|
54
|
+
|
55
|
+
# list of temps
|
56
|
+
documented_as_reader :plugins
|
57
|
+
|
58
|
+
def initialize()
|
59
|
+
@kpse=Kpathsea.new
|
60
|
+
@basedir=nil
|
61
|
+
@name=nil
|
62
|
+
@texenc=nil
|
63
|
+
@mapenc=nil
|
64
|
+
@write_vf=true
|
65
|
+
@fonts=[]
|
66
|
+
@options={:verbose=>false,:dryrun=>false}
|
67
|
+
@style=nil
|
68
|
+
@dirs={}
|
69
|
+
@vendor=nil
|
70
|
+
@fontname=nil
|
71
|
+
set_dirs(Dir.getwd)
|
72
|
+
@plugins={}
|
73
|
+
# find temps-plugins
|
74
|
+
$:.each{ |d|
|
75
|
+
a=Dir.glob(d+"/rfil/rfi_plugin_*.rb")
|
76
|
+
a.each{ |f|
|
77
|
+
require f
|
78
|
+
}
|
79
|
+
}
|
80
|
+
ObjectSpace.each_object(Class){ |x|
|
81
|
+
if Plugin > x
|
82
|
+
t = x.new(self)
|
83
|
+
n = t.name
|
84
|
+
if @plugins.has_key?(n)
|
85
|
+
raise "Name already registered"
|
86
|
+
end
|
87
|
+
@plugins[n]=t
|
88
|
+
end
|
89
|
+
}
|
90
|
+
# done initializing plugins
|
91
|
+
end
|
92
|
+
|
93
|
+
# Add a font to the collection. Return the number of the font.
|
94
|
+
def register_font (font)
|
95
|
+
unless font.respond_to?(:maplines)
|
96
|
+
raise ArgumentError, "parameter does not look like a font"
|
97
|
+
end
|
98
|
+
fontnumber=@fonts.size
|
99
|
+
@fonts << font
|
100
|
+
return fontnumber
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_plugin(name)
|
104
|
+
|
105
|
+
raise "don't know plugin #{name}" unless @plugins.has_key?(name)
|
106
|
+
|
107
|
+
# doc for run_plugin
|
108
|
+
# Return the contents of the file that should be used by the TeX
|
109
|
+
# macro package, i.e a typescript for ConTeXt or an fd-file for
|
110
|
+
# Context. Return value is an Array of Hashes. The Hash has three
|
111
|
+
# different keys:
|
112
|
+
# [<tt>:type</tt>] The type of the file, should be either <tt>:fd</tt> or <tt>:typescript</tt>.
|
113
|
+
# [<tt>:filename</tt>] the filename (without a path) of the file
|
114
|
+
# [<tt>:contents</tt>] the contents of the file.
|
115
|
+
|
116
|
+
files=@plugins[name].run_plugin
|
117
|
+
if files.respond_to?(:each)
|
118
|
+
files.each { |fh|
|
119
|
+
dir=get_dir(fh[:type])
|
120
|
+
filename=File.join(dir,fh[:filename])
|
121
|
+
puts "writing file #{filename}" if @options[:verbose]
|
122
|
+
|
123
|
+
unless @options[:dryrun]
|
124
|
+
ensure_dir(dir)
|
125
|
+
File.open(filename,"w") { |f| f << fh[:contents] }
|
126
|
+
end
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
def plugins #:nodoc:
|
131
|
+
@plugins.keys
|
132
|
+
end
|
133
|
+
def mapfile
|
134
|
+
mapfile=[]
|
135
|
+
@fonts.each {|font|
|
136
|
+
mapfile << font.maplines
|
137
|
+
}
|
138
|
+
mapfile.flatten
|
139
|
+
end
|
140
|
+
def mapenc # :nodoc:
|
141
|
+
return nil if @mapenc==:none
|
142
|
+
@mapenc
|
143
|
+
end
|
144
|
+
def mapenc= (enc) # :nodoc:
|
145
|
+
set_mapenc(enc)
|
146
|
+
end
|
147
|
+
def texenc # :nodoc:
|
148
|
+
if @texenc
|
149
|
+
@texenc
|
150
|
+
else
|
151
|
+
# @texenc not set
|
152
|
+
ret=nil
|
153
|
+
@kpse.open_file("8a.enc","enc") { |f|
|
154
|
+
ret = [ENC.new(f)]
|
155
|
+
}
|
156
|
+
return ret
|
157
|
+
end
|
158
|
+
end
|
159
|
+
def texenc= (enc) # :nodoc:
|
160
|
+
@texenc=[]
|
161
|
+
set_encarray(enc,@texenc)
|
162
|
+
end
|
163
|
+
def get_dir(type)
|
164
|
+
@dirs[type]
|
165
|
+
end
|
166
|
+
def write_files(options={})
|
167
|
+
mapdir=get_dir(:map); ensure_dir(mapdir)
|
168
|
+
|
169
|
+
@fonts.each {|font|
|
170
|
+
font.write_files(:mapfile => false)
|
171
|
+
mapfile << font.maplines
|
172
|
+
}
|
173
|
+
mapfilename=File.join(mapdir,@name+".map")
|
174
|
+
unless options[:dryrun]==true
|
175
|
+
File.open(mapfilename, "w") {|file|
|
176
|
+
file << mapfile.to_s
|
177
|
+
}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end # class RFI
|
182
|
+
end # module RFIL
|
data/lib/rfil/helper.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
#--
|
2
|
+
# helper.rb Last Change: Fri Jul 1 14:29:09 2005
|
3
|
+
#++
|
4
|
+
# Helper module for Font and FontCollection.
|
5
|
+
|
6
|
+
# Here we define methods that are used in Font and FontCollection.
|
7
|
+
|
8
|
+
require 'fileutils'
|
9
|
+
require 'tex/kpathsea'
|
10
|
+
|
11
|
+
module RFIL # :nodoc:
|
12
|
+
class RFI
|
13
|
+
module Helper
|
14
|
+
include TeX
|
15
|
+
def set_encarray(enc,where) #:nodoc:
|
16
|
+
if enc.instance_of?(TeX::ENC)
|
17
|
+
where.push(enc)
|
18
|
+
else
|
19
|
+
enc.each { |e|
|
20
|
+
if e.instance_of?(String)
|
21
|
+
e = e.chomp(".enc") + ".enc"
|
22
|
+
f=@kpse.open_file(e,"enc")
|
23
|
+
where.push(TeX::ENC.new(f))
|
24
|
+
f.close
|
25
|
+
elsif e.instance_of?(TeX::ENC)
|
26
|
+
where.push(e)
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
def set_mapenc(enc) # :nodoc:
|
32
|
+
@mapenc=enc
|
33
|
+
|
34
|
+
# nil/:none is perfectly valid
|
35
|
+
return if enc==nil or enc==:none
|
36
|
+
|
37
|
+
if enc.instance_of?(TeX::ENC)
|
38
|
+
@mapenc = enc
|
39
|
+
else
|
40
|
+
enc.find { |e|
|
41
|
+
if e.instance_of?(String)
|
42
|
+
e = e.chomp(".enc") + ".enc"
|
43
|
+
@kpse.open_file(e,"enc") { |f|
|
44
|
+
@mapenc = TeX::ENC.new(f)
|
45
|
+
}
|
46
|
+
elsif e.instance_of?(TeX::ENC)
|
47
|
+
@mapenc = e
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# call-seq:
|
53
|
+
# set_dirs(string)
|
54
|
+
# set_dirs(hash)
|
55
|
+
#
|
56
|
+
# Set the base dir of all font related files. Acts only as a storage
|
57
|
+
# for the information. The automatic font installation method in
|
58
|
+
# Font#write_files uses this information. When a _string_ is passed,
|
59
|
+
# use this as the base dir for all files, when a hash is given, the
|
60
|
+
# keys must be one of <tt>:afm</tt>, <tt>:tfm</tt>,
|
61
|
+
# <tt>:vf</tt>,<tt>:map</tt>, <tt>:pfb</tt>, <tt>:tt</tt>, <tt>:tds</tt>.
|
62
|
+
def set_dirs(arg)
|
63
|
+
# tds needs testing! set vendor/fonname before/after set_dirs
|
64
|
+
types=[:afm, :tfm, :vpl, :vf, :pl, :map, :type1,:truetype, :fd, :typescript]
|
65
|
+
if arg.instance_of? String
|
66
|
+
@basedir=arg
|
67
|
+
types.each { |sym|
|
68
|
+
@dirs[sym]=arg
|
69
|
+
}
|
70
|
+
elsif arg.instance_of? Hash
|
71
|
+
if arg[:base]
|
72
|
+
@basedir=arg[:base]
|
73
|
+
end
|
74
|
+
if arg[:tds]==true
|
75
|
+
suffix = if @vendor and @name
|
76
|
+
File.join(@vendor,@name)
|
77
|
+
else
|
78
|
+
""
|
79
|
+
end
|
80
|
+
types.each { |t|
|
81
|
+
subdir= case t
|
82
|
+
when :afm
|
83
|
+
File.join("fonts/afm",suffix)
|
84
|
+
when :tfm
|
85
|
+
File.join("fonts/tfm",suffix)
|
86
|
+
when :vpl
|
87
|
+
File.join("fonts/source/vpl",suffix)
|
88
|
+
when :vf
|
89
|
+
File.join("fonts/vf",suffix)
|
90
|
+
when :pl
|
91
|
+
File.join("fonts/source/pl",suffix)
|
92
|
+
when :map
|
93
|
+
"fonts/map/dvips"
|
94
|
+
when :type1
|
95
|
+
File.join("fonts/type1",suffix)
|
96
|
+
when :truetype
|
97
|
+
File.join("fonts/truetype",suffix)
|
98
|
+
when :fd
|
99
|
+
File.join("tex/latex",suffix)
|
100
|
+
when :typescript
|
101
|
+
File.join("tex/context",suffix)
|
102
|
+
else
|
103
|
+
raise "unknown type"
|
104
|
+
end
|
105
|
+
@dirs[t] = File.join(@basedir,subdir)
|
106
|
+
}
|
107
|
+
else
|
108
|
+
arg.each { |key,value|
|
109
|
+
@dirs[key] = value
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
def ensure_dir(dirname) # :nodoc:
|
115
|
+
if File.exists?(dirname)
|
116
|
+
if File.directory?(dirname)
|
117
|
+
# nothing to do
|
118
|
+
else
|
119
|
+
# exists, but not dir
|
120
|
+
raise "File exists, but is not a directory: #{dirname}"
|
121
|
+
end
|
122
|
+
else
|
123
|
+
# file does not exist, we can create a directory (hopefully)
|
124
|
+
|
125
|
+
puts "Creating directory hierarchy #{dirname}" if @options[:verbose]
|
126
|
+
|
127
|
+
unless @options[:dryrun]
|
128
|
+
FileUtils.mkdir_p(dirname)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end #ensure_dir
|
132
|
+
end # helper
|
133
|
+
# options is a hash, but with lookup to a fontcollection
|
134
|
+
class Options # :nodoc:
|
135
|
+
def initialize(fontcollection)
|
136
|
+
@fc=fontcollection
|
137
|
+
@options={}
|
138
|
+
end
|
139
|
+
def [](idx)
|
140
|
+
if @options[idx]
|
141
|
+
return @options[idx]
|
142
|
+
end
|
143
|
+
if @fc
|
144
|
+
@fc.options[idx]
|
145
|
+
else
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
def []=(idx,obj)
|
150
|
+
@options[idx]=obj
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end # RFI
|
155
|
+
end
|