add dump.rb to dump out Vietnamese glyphs
[terpinus.git] / bdf.rb
blob3aa3e615a425a6eb4b9d2c64328225c95ecf3df1
1 def open_bdf(file)
2   f = File.open(file,'r')
3   buf = f.readlines.map {|x| x.chomp}
4   f.close
5   class << buf
6     def init
7       @line = 0
8     end
9   
10     def line
11       self[@line]
12     end
13   
14     def swallow
15       @line += 1
16     end
17   
18     def empty
19       @line == self.length
20     end
21   end
22   buf.init
23   buf
24 end
26 class BDF
27   attr_reader :glyphs, :header, :glyph_ref
28   def initialize(filename = false)
29     @glyphs = []
30     @glyph_ref = {}
31     @header = []
32     @footer = []
33     if filename.is_a? String
34       buf = open_bdf(filename)
35       glyph_processing = false
36       while (!buf.empty) do
37         items = buf.line.split(/ /)
38         if items[0] == 'STARTCHAR'
39         glyph_processing = true
40           g = Glyph.new(buf)
41         @glyphs << g
42         @glyph_ref[g.name] = g
43         else
44         glyph_processing ? @footer << buf.line : @header << buf.line
45         buf.swallow
46         end
47       end
48     end
49     self
50   end
52   def write(io)
53     if io.is_a? String
54       f = File.open(io,'w')
55       ret = self.write(f)
56       f.close
57       return ret
58     end
59     glyphs = @glyph_ref.values.sort {|x,y| x.encoding <=> y.encoding}
60     @header.each {|h| io.puts h =~ /^CHARS / ? "CHARS #{glyphs.length}" : h}
61     glyphs.each {|g| g.write(io) }
62     @footer.each {|h| io.puts h}
63     true
64   end
66   NAMES = {
67     0x01A0 => 'Ohorn',
68     0x01A1 => 'ohorn',
69     0x01AF => 'Uhorn',
70     0x01B0 => 'uhorn',
71     0x1EF2 => 'Ygrave',
72     0x1EF3 => 'ygrave',
73   }
74   REFS = {
75     0x01A0 => 'O',
76     0x01A1 => 'o',
77     0x01AF => 'U',
78     0x01B0 => 'u',
79   
80     0x1EA0 => 'A',
81     0x1EA1 => 'a',
82     0x1EA2 => 'A',
83     0x1EA3 => 'a',
84     
85     0x1EA4 => 'Acircumflex',
86     0x1EA5 => 'acircumflex',
87     0x1EA6 => 'Acircumflex',
88     0x1EA7 => 'acircumflex',
89     0x1EA8 => 'Acircumflex',
90     0x1EA9 => 'acircumflex',
91     0x1EAA => 'Acircumflex',
92     0x1EAB => 'acircumflex',
93     0x1EAC => 'Acircumflex',
94     0x1EAD => 'acircumflex',
95     
96     0x1EAE => 'Abreve',
97     0x1EAF => 'abreve',
98     0x1EB0 => 'Abreve',
99     0x1EB1 => 'abreve',
100     0x1EB2 => 'Abreve',
101     0x1EB3 => 'abreve',
102     0x1EB4 => 'Abreve',
103     0x1EB5 => 'abreve',
104     0x1EB6 => 'Abreve',
105     0x1EB7 => 'abreve',
106     
107     0x1EBA => 'E',
108     0x1EBB => 'e',
109     
110     0x1EBE => 'Ecircumflex',
111     0x1EBF => 'ecircumflex',
112     0x1EC0 => 'Ecircumflex',
113     0x1EC1 => 'ecircumflex',
114     0x1EC2 => 'Ecircumflex',
115     0x1EC3 => 'ecircumflex',
116     0x1EC4 => 'Ecircumflex',
117     0x1EC5 => 'ecircumflex',
118     0x1EC6 => 'Ecircumflex',
119     0x1EC7 => 'ecircumflex',
120     
121     0x1EC8 => 'I',
122     0x1EC9 => 'i',
123     0x1ECA => 'I',
124     0x1ECB => 'i',
125     
126     0x1ECE => 'O',
127     0x1ECF => 'o',
128     
129     0x1ED0 => 'Ocircumflex',
130     0x1ED1 => 'ocircumflex',
131     0x1ED2 => 'Ocircumflex',
132     0x1ED3 => 'ocircumflex',
133     0x1ED4 => 'Ocircumflex',
134     0x1ED5 => 'ocircumflex',
135     0x1ED6 => 'Ocircumflex',
136     0x1ED7 => 'ocircumflex',
137     0x1ED8 => 'Ocircumflex',
138     0x1ED9 => 'ocircumflex',
139     
140     0x1EDA => 'O',
141     0x1EDB => 'o',
142     0x1EDC => 'O',
143     0x1EDD => 'o',
144     0x1EDE => 'O',
145     0x1EDF => 'o',
146     0x1EE0 => 'O',
147     0x1EE1 => 'o',
148     0x1EE2 => 'O',
149     0x1EE3 => 'o',
150     
151     0x1EE4 => 'U',
152     0x1EE5 => 'u',
153     0x1EE6 => 'U',
154     0x1EE7 => 'u',
155     
156     0x1EE8 => 'U',
157     0x1EE9 => 'u',
158     0x1EEA => 'U',
159     0x1EEB => 'u',
160     0x1EEC => 'U',
161     0x1EED => 'u',
162     0x1EEE => 'U',
163     0x1EEF => 'u',
164     0x1EF0 => 'U',
165     0x1EF1 => 'u',
166     
167     0x1EF2 => 'Y',
168     0x1EF3 => 'y',
170     0x1EF4 => 'Y',
171     0x1EF5 => 'y',
172     0x1EF6 => 'Y',
173     0x1EF7 => 'y',
174   }
176   def copy_glyph(name,bdf)
177     if bdf.glyph_ref[name].nil?
178       STDERR.puts "Glyph #{name} not found"
179     else
180       g = bdf.glyph_ref[name].dup
181       @glyph_ref[g.name] = g
182     end
183   end
185   def copy_glyph_by_id(name,bdf)
186     if name.is_a? String
187       self.copy_glyph(name,bdf)
188     end
189     if name.is_a? Array
190       name.each {|x| self.copy_glyph_by_id(x,bdf) }
191     end
192     nil
193   end
195   def dup_glyph(name,newname,newencoding,bdf = nil)
196     g = bdf.nil? ? @glyph_ref[name].dup : bdf.glyph_ref[name].dup
197     g.name = newname
198     g.encoding = newencoding
199     @glyph_ref[g.name] = g
200   end
202   def dup_glyph_by_id(id,bdf = nil)
203     if id.is_a? Fixnum
204       return unless REFS.key? id
205       name = NAMES[id] || "uni#{id.to_s(16).upcase}"
206       self.dup_glyph(REFS[id],name,id,bdf)
207     end
208     if id.is_a? Array
209       id.each {|x| self.dup_glyph_by_id(x,bdf) }
210     end
211     nil
212   end
214   def copy_all(bdf)
215     self.copy_glyph_by_id(REFS.keys.map {|x| NAMES[x] || "uni#{x.to_s(16).upcase}"} ,bdf)
216   end
218   def dup_all(bdf = nil)
219     #$bdf.dup_glyph_by_id([416, 417, 431, 432, 7922, 7923,
220     #0x1EA0, 0x1EA1, 0x1EA2, 0x1EA3,
221     #0x1EA4, 0x1EA5, 0x1EA6, 0x1EA7, 0x1EA8, 0x1EA9, 0x1EAA, 0x1EAB, 0x1EAC, 0x1EAD,
222     #0x1EAE, 0x1EAF, 0x1EB0, 0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4, 0x1EB5, 0x1EB6, 0x1EB7,
223     #0x1EBA, 0x1EBB,
224     #0x1EBE, 0x1EBF, 0x1EC0, 0x1EC1, 0x1EC2, 0x1EC3, 0x1EC4, 0x1EC5, 0x1EC6, 0x1EC7,
225     #0x1EC8, 0x1EC9, 0x1ECA, 0x1ECB, 
226     #0x1ECE, 0x1ECF,
227     #0x1ED0, 0x1ED1, 0x1ED2, 0x1ED3, 0x1ED4, 0x1ED5, 0x1ED6, 0x1ED7, 0x1ED8, 0x1ED9,
228     #0x1EDA, 0x1EDB, 0x1EDC, 0x1EDD, 0x1EDE, 0x1EDF, 0x1EE0, 0x1EE1, 0x1EE2, 0x1EE3,
229     #0x1EE4, 0x1EE5, 0x1EE6, 0x1EE7,
230     #0x1EE8, 0x1EE9, 0x1EEA, 0x1EEB, 0x1EEC, 0x1EED, 0x1EEE, 0x1EEF, 0x1EF0, 0x1EF1,
231     #0x1EF4, 0x1EF5, 0x1EF6, 0x1EF7])
232     self.dup_glyph_by_id(REFS.keys,bdf)
233   end
236 class Glyph
237   attr_reader :swidth, :dwidth, :bbx, :bitmap
238   attr_accessor :encoding, :name
239   def initialize(buf)
240     done = false
241     bitmap_phase = false
242     @bitmap = []
243     while (!buf.empty && !done) do
244       items = buf.line.split(/ /)
245       if bitmap_phase
246         if items[0] == 'ENDCHAR'
247           done = true
248         else
249           @bitmap << buf.line
250         end
251       else
252         @name = items[1].dup if items[0] == 'STARTCHAR'
253         @encoding = items[1].to_i if items[0] == 'ENCODING'
254         @swidth = items.dup if items[0] == 'SWIDTH'
255         @dwidth = items.dup if items[0] == 'DWIDTH'
256         @bbx = items.dup if items[0] == 'BBX'
257         bitmap_phase = true if buf.line == 'BITMAP'
258       end 
259       buf.swallow
260     end
261     self
262   end
264   def write(io)
265     io.puts "STARTCHAR #@name"
266     io.puts "ENCODING #@encoding"
267     io.puts @swidth.join(' ')
268     io.puts @dwidth.join(' ')
269     io.puts @bbx.join(' ')
270     io.puts "BITMAP"
271     @bitmap.each {|b| io.puts b}
272     io.puts "ENDCHAR"
273   end
276 #$buf = open_bdf('ter-u16n.bdf')
277 #$bdf = BDF.new($buf)
278 #require 'pp'
279 #$bdf.write(STDOUT)
280 #a = BDF.new('zz')
281 #b = BDF.new('ter-u12n.bdf')
282 #a.copy_all(b)
283 #c = File.open('zzo','w')
284 #a.write(c)
285 #c.close