rfil 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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