rfil 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
@@ -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