3 local stderr = io.stderr
4 local function show_usage(s)
5 stderr:write('Error: ' .. s .. '\n');
6 stderr:write('Usage: texlua jfm-convert [-J|-U] <ptex_jfm>\n');
7 stderr:write('-J: JIS mode, -U: UCS mode \n');
8 stderr:write(' * The output will be written to stdout.\n');
9 stderr:write(' * I do not read virtual fonts which corresponded to <ptex_jfm>.\n');
10 stderr:write(" You will need to adjust 'align', 'left', 'down' entries by hand.\n");
11 stderr:write(" * In JIS mode, characters which are not included in JIS X 0208\n");
12 stderr:write(" (e.g., 0x2257) are written as 0x202577.\n");
16 kpse.set_program_name('luatex')
17 require('lualibs'); local uchar = utf.char
18 jisx0208 = require('ltj-jisx0208.lua').table_jisx0208_uptex
19 local function pass_ucs(s)
20 return "'" .. uchar(s) .. "'"
22 local function jis_to_ucs(s)
24 local a = jisx0208[math.floor(i/256)*94+(i%256)-94] or 0
25 return a and pass_ucs(a) or string.format('0x%X',s+0x200000)
28 -------- 引数解釈 --------
35 if arg[i]=='-u' or arg[i]=='-U' then
37 elseif arg[i]=='-j' or arg[i]=='-J' then
40 show_usage('Multiple JFM files.')
46 if not filename then show_usage('Missing JFM file argument.') end
47 kpse.set_program_name('ptex')
48 local nf = kpse.find_file(filename, 'tfm')
49 if not nf then show_usage("JFM file can't be opened: " .. filename) end
51 -------- OPEN --------
53 local jfm_ptex = io.open(nf, 'rb')
54 local function get_word()
55 local d = table.pack(string.byte(jfm_ptex:read(4),1,4))
56 return d[1]*16777216+d[2]*65536+d[3]*256+d[4]
58 local function get_signed_word()
60 return (d>=2147483648) and -(4294967296-d) or d
62 local extract = bit32.extract
63 local function get_two()
65 return extract(d,16,16), extract(d,0,16)
67 local function get_four()
69 return extract(d,24,8), extract(d,16,8), extract(d,8,8), extract(d,0,8)
72 local id, nt = get_two()
73 local lf, lh = get_two()
74 local bc, ec = get_two()
75 local nw, nh = get_two()
76 local nd, ni = get_two()
77 local nl, nk = get_two()
78 local ng, np = get_two()
81 lf~= 7 + lh + nt + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ng + np or
82 (id~=11 and id~=9) then
83 stderr:write('Bad JFM "' .. filename .. '".\n'); jfm_ptex:close(); os.exit(1)
87 result.dir = (id==11) and 'yoko' or 'tate'
89 -------- HEADER --------
91 _ = get_word() -- checksum, unused
92 local designsize = get_word()/1048576 -- ignored
97 for i=1,math.min(10,lh-2) do encoding = encoding .. jfm_ptex:read(4) end
98 encoding = encoding:sub(2, 1+string.byte(encoding))
100 if not encoding then encoding = 'UNSPECIFIED' end
104 for i=1,math.min(5,lh-12) do family = family .. jfm_ptex:read(4) end
105 family = family:sub(2, 1+string.byte(family))
110 _, _, _, face = get_four()
111 for i=1,lh-19 do jfm_ptex:read(4) end -- ignored
114 -------- CHAR_TYPE --------
118 local ccode, ctype = get_two()
120 all_ctype[#all_ctype+1] = ccode
123 if not result[ctype] then result[ctype] = {} end
124 if not result[ctype].chars then result[ctype].chars = {} end
125 local t = result[ctype].chars
130 -------- CHAR_INFO --------
132 if not result[i] then result[i] = {} end
133 local t, info = result[i], get_word()
134 t.align, t.left, t.down = 'left', 0, 0
135 t.width = extract(info, 24, 8)
136 t.height = extract(info, 20, 4)
137 t.depth = extract(info, 16, 4)
138 t.italic = extract(info, 10, 6)
139 t.tag = extract(info, 8, 2)
140 t.rem = extract(info, 0, 8)
143 local wi, hi, di, ii = {}, {}, {}, {}
144 for i=0,nw-1 do wi[i] = get_signed_word() end
145 for i=0,nh-1 do hi[i] = get_signed_word() end
146 for i=0,nd-1 do di[i] = get_signed_word() end
147 for i=0,ni-1 do ii[i] = get_signed_word() end
150 -------- GLUE/KERN --------
153 for i=0,nl-1 do gk_table[i] = table.pack(get_four()) end
156 for i=0,nk-1 do kerns[i] = get_signed_word() end
159 for i=0,ng/3-1 do glues[i] = { get_signed_word(), get_signed_word(), get_signed_word() } end
162 -------- PARAM --------
164 for i=1,math.min(9, np) do param[i] = get_word() end
167 param[2]/zw, param[3]/zw, param[4]/zw
169 result.xkanjiskip = {
170 param[7]/zw, param[8]/zw, param[9]/zw
172 result.zw, result.zh = 1.0, param[5]/zw
176 -------- 各種 index の解決 --------
179 t.width = wi[t.width]/zw
180 t.height = hi[t.height]/zw
181 t.depth = di[t.depth]/zw
182 t.italic = ii[t.italic]/zw
186 local gkp = gk_table[j]
187 j = (gkp[1]<128) and j+gkp[1]+1 or nil
189 if not t.glue then t.glue = {} end
196 if not t.kern then t.kern = {} end
197 t.kern[gkp[2]] = kerns[gkp[4]]/zw
201 t.tag, t.rem = nil, nil
207 -------- モード判定 --------
210 for i=1, #all_ctype do
211 local i = all_ctype[i]-0x2020
212 if not jisx0208[math.floor(i/256)*94+(i%256)-94] then
213 mode = pass_ucs; break
220 if type(a)=='number' then
221 return tostring(math.floor(a*1000000+0.5)/1000000)
222 elseif type(a)=='table' then -- glue
223 return '{ ' .. S(a[1]) .. ', ' .. S(a[2]) .. ', ' .. S(a[3]) .. '},'
224 elseif type(a)=='string' then
225 return "'" .. a .. "'"
231 print('-- -*- coding: utf-8 -*-')
232 print('-- converted from ' .. filename .. ' by jfm_convert.lua')
233 print('-- assumed encoding: ' .. (mode==jis_to_ucs and 'JIS' or 'UCS') .. '\n')
234 print('luatexja.jfont.define_jfm {')
235 print(' -- original design size = ' .. S(designsize))
236 print(' -- original encoding = (' .. encoding .. ')')
237 print(' -- original family = (' .. family .. ')')
238 print(" dir = " .. S(result.dir) .. ",")
239 print(' zw = ' .. S(result.zw) .. ', zh = ' .. S(result.zh) .. ', ')
240 print(' kanjiskip = ' .. S(result.kanjiskip))
241 print(' xkanjiskip = ' .. S(result.xkanjiskip))
244 print(' [' .. tostring(i) .. '] = {')
248 for j=1,#(t.chars) do
249 d = d .. mode(t.chars[j]) .. ', '
250 if j%8==0 and j<#(t.chars) then
257 print(' align = ' .. S(t.align) .. ', left = ' .. S(0.0)
258 .. ', down = ' .. S(0.0) .. ', ')
259 print(' width = ' .. S(t.width) .. ', height = ' .. S(t.height)
260 .. ', depth = ' .. S(t.depth) .. ', italic = ' .. S(t.italic) .. ',')
264 for m,_ in pairs(t.glue) do gi[#gi+1]=m end
266 for _,m in ipairs(gi) do
267 print(' [' .. tostring(m) .. '] = ' .. S(t.glue[m]))
274 for m,_ in pairs(t.kern) do gi[#gi+1]=m end
276 for _,m in ipairs(gi) do
277 print(' [' .. tostring(m) .. '] = ' .. S(t.kern[m]) .. ',')