1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
--
-- luatexja/jfont.lua
--
luatexbase.provides_module({
name = 'luatexja.jfont',
date = '2011/06/27',
version = '0.1',
description = 'Loader for Japanese fonts',
})
module('luatexja.jfont', package.seeall)
luatexja.load_module('base'); local ltjb = luatexja.base
luatexja.load_module('charrange'); local ltjc = luatexja.charrange
local node_new = node.new
local has_attr = node.has_attribute
local round = tex.round
local attr_icflag = luatexbase.attributes['ltj@icflag']
local attr_curjfnt = luatexbase.attributes['ltj@curjfnt']
local id_glyph = node.id('glyph')
local id_kern = node.id('kern')
local cat_lp = luatexbase.catcodetables['latex-package']
local ITALIC = 1
------------------------------------------------------------------------
-- LOADING JFM
------------------------------------------------------------------------
metrics={} -- this table stores all metric informations
font_metric_table={} -- [font number] -> jfm_name, jfm_var, size
luatexbase.create_callback("luatexja.load_jfm", "data", function (ft, jn) return ft end)
local jfm_file_name, jfm_var
local defjfm_res
function define_jfm(t)
local real_char -- Does current character class have the 'real' character?
if t.dir~='yoko' then
defjfm_res= nil; return
elseif type(t.zw)~='number' or type(t.zh)~='number' then
defjfm_res= nil; return
end
t.char_type = {}; t.chars = {}
for i,v in pairs(t) do
if type(i) == 'number' then -- char_type
if not v.chars then
if i ~= 0 then defjfm_res= nil; return end
real_char = true
else
real_char = false
for j,w in pairs(v.chars) do
if w == 'lineend' then
if #v.chars ~= 1 then defjfm_res= nil; return end
elseif type(w) == 'number' then
real_char = true;
elseif type(w) == 'string' and utf.len(w)==1 then
real_char = true; w = utf.byte(w)
end
if not t.chars[w] then
t.chars[w] = i
else
defjfm_res= nil; return
end
end
if real_char then
if not (type(v.width)=='number' or v.width~='prop') then
defjfm_res= nil; return
else
if type(v.height)~='number' then
v.height = 0.0
end
if type(v.depth)~='number' then
v.depth = 0.0
end
if type(v.italic)~='number' then
v.italic = 0.0
end
if type(v.left)~='number' then
v.left = 0.0
end
if type(v.down)~='number' then
v.down = 0.0
end
if type(v.align)=='nil' then
v.align = 'left'
end
end
end
v.chars = nil
end
if v.kern and v.glue then
for j,w in pairs(v.glue) do
if v.kern[j] then defjfm_res= nil; return end
end
end
t.char_type[i] = v
t[i] = nil
end
end
t = luatexbase.call_callback("luatexja.load_jfm", t, jfm_file_name)
t.size_cache = {}
defjfm_res = t
end
local function mult_table(old,scale) -- modified from table.fastcopy
if old then
local new = { }
for k,v in next, old do
if type(v) == "table" then
new[k] = mult_table(v,scale)
elseif type(v) == "number" then
new[k] = round(v*scale)
else
new[k] = v
end
end
return new
else return nil end
end
local function update_jfm_cache(j,sz)
if metrics[j].size_cache[sz] then return end
metrics[j].size_cache[sz] = {}
metrics[j].size_cache[sz].char_type = mult_table(metrics[j].char_type, sz)
metrics[j].size_cache[sz].kanjijskip = mult_table(metrics[j].kanjiskip, sz)
metrics[j].size_cache[sz].xkanjiskip = mult_table(metrics[j].xkanjiskip,sz)
metrics[j].size_cache[sz].zw = round(metrics[j].zw*sz)
metrics[j].size_cache[sz].zh = round(metrics[j].zh*sz)
end
luatexbase.create_callback("luatexja.find_char_class", "data",
function (arg, fmtable, char)
return 0
end)
function find_char_class(c,m)
-- c: character code, m: index in font_metric table
if not metrics[m.jfm] then return 0 end
return metrics[m.jfm].chars[c] or
luatexbase.call_callback("luatexja.find_char_class", 0, m, c)
end
local function load_jfont_metric()
if jfm_file_name=='' then
ltjb.package_error('luatexja',
'no JFM specified',
'To load and define a Japanese font, a JFM must be specified.'..
"The JFM 'ujis' will be used for now.")
jfm_file_name='ujis'
end
for j,v in ipairs(metrics) do
if v.name==jfm_file_name then return j end
end
luatexja.load_lua('jfm-' .. jfm_file_name .. '.lua')
if defjfm_res then
defjfm_res.name = jfm_file_name
table.insert(metrics, defjfm_res)
return #metrics
else
return nil
end
end
------------------------------------------------------------------------
-- LOADING JAPANESE FONTS
------------------------------------------------------------------------
local cstemp
-- EXT
function jfontdefX(g)
local t = token.get_next()
cstemp=token.csname_name(t)
if g then luatexja.is_global = '\\global' else luatexja.is_global = '' end
tex.sprint(cat_lp, '\\expandafter\\font\\csname ' .. cstemp .. '\\endcsname')
end
luatexbase.create_callback("luatexja.define_jfont", "data", function (ft, fn) return ft end)
-- EXT
function jfontdefY() -- for horizontal font
local j = load_jfont_metric()
local fn = font.id(cstemp)
local f = font.fonts[fn]
if not j then
ltjb.package_error('luatexja',
"bad JFM `" .. jfm_file_name .. "'",
'The JFM file you specified is not valid JFM file.\n'..
'So defining Japanese font is cancelled.')
tex.sprint(cat_lp, luatexja.is_global .. '\\expandafter\\let\\csname ' ..cstemp
.. '\\endcsname=\\relax')
return
end
update_jfm_cache(j, f.size)
local fmtable = { jfm = j, size = f.size, var = jfm_var }
fmtable = luatexbase.call_callback("luatexja.define_jfont", fmtable, fn)
font_metric_table[fn]=fmtable
tex.sprint(cat_lp, luatexja.is_global .. '\\protected\\expandafter\\def\\csname '
.. cstemp .. '\\endcsname{\\ltj@curjfnt=' .. fn .. '\\relax}')
end
-- zw, zh
function load_zw()
local a = font_metric_table[tex.attribute[attr_curjfnt]]
if a then
tex.setdimen('ltj@zw', metrics[a.jfm].size_cache[a.size].zw)
else
tex.setdimen('ltj@zw',0)
end
end
function load_zh()
local a = font_metric_table[tex.attribute[attr_curjfnt]]
if a then
tex.setdimen('ltj@zh', metrics[a.jfm].size_cache[a.size].zh)
else
tex.setdimen('ltj@zh',0)
end
end
-- extract jfm_file_name and jfm_var
local function extract_metric(name)
local basename=name
local tmp = utf.sub(basename, 1, 5)
jfm_file_name = ''; jfm_var = ''
if tmp == 'file:' or tmp == 'name:' or tmp == 'psft:' then
basename = utf.sub(basename, 6)
end
local p = utf.find(basename, ":")
if p then
basename = utf.sub(basename, p+1)
else return
end
-- now basename contains 'features' only.
p=1
while p do
local q = utf.find(basename, ";", p+1) or utf.len(basename)+1
if utf.sub(basename, p, p+3)=='jfm=' and q>p+4 then
jfm_file_name = utf.sub(basename, p+4, q-1)
elseif utf.sub(basename, p, p+6)=='jfmvar=' and q>p+6 then
jfm_var = utf.sub(basename, p+7, q-1)
end
if utf.len(basename)+1==q then p = nil else p = q + 1 end
end
return
end
-- replace fonts.define.read()
local ljft_dr_orig = fonts.define.read
function fonts.define.read(name, size, id)
extract_metric(name)
-- In the present imple., we don't remove "jfm=..." from name.
return ljft_dr_orig(name, size, id)
end
------------------------------------------------------------------------
-- MISC
------------------------------------------------------------------------
-- EXT: italic correction
function append_italic()
local p = tex.nest[tex.nest.ptr].tail
if p and p.id==id_glyph then
local f = p.font
local g = node_new(id_kern)
g.subtype = 1; node.set_attribute(g, attr_icflag, ITALIC)
if ltjc.is_ucs_in_japanese_char(p) then
f = has_attr(p, attr_curjfnt)
local j = font_metric_table[f]
local c = find_char_class(p.char, j)
g.kern = metrics[j.jfm].size_cache[j.size].char_type[c].italic
else
g.kern = font.fonts[f].characters[p.char].italic
end
node.write(g)
tex.attribute[attr_icflag] = -(0x7FFFFFFF)
end
end
|