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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
--
-- luatexja/rmlgbm.lua
--
luatexbase.provides_module({
name = 'luatexja.rmlgbm',
date = '2013/05/14',
description = 'Definitions of non-embedded Japanese (or other CJK) fonts',
})
module('luatexja.rmlgbm', package.seeall)
local err, warn, info, log = luatexbase.errwarinf(_NAME)
luatexja.load_module('base'); local ltjb = luatexja.base
cidfont_data = {}
local cidfont_data = cidfont_data
local cache_chars = {}
local path = {
localdir = file.join(kpse.expand_var("$TEXMFVAR"), aux_dir),
systemdir = file.join(kpse.expand_var("$TEXMFSYSVAR"), aux_dir),
}
local cid_reg, cid_order, cid_supp, cid_name
local taux_dir = 'luatex-cache/luatexja'
local cid_replace = {
["Adobe-Japan1"] = {"UniJIS2004-UTF32", 23057, 6,
function (i)
if (231<=i and i<=632) or (8718<=i and i<=8719)
or (12063<=i and i<=12087) then
return 327680 -- 655360/2
elseif 9758<=i and i<=9778 then
return 218453 -- 655360/3
elseif 9738<=i and i<=9757 then
return 163840 -- 655360/4
end
end},
-- 基本的には JIS X 0213:2004 に沿ったマッピング
["Adobe-Korea1"] = {"UniKS-UTF32", 18351, 2,
function (i)
if 8094<=i and i<=8100 then
return 327680 -- 655360/2
end
end},
["Adobe-GB1"] = {"UniGB-UTF32", 30283, 5,
function (i)
if (814<=i and i<=939) or (i==7716)
or (22355<=i and i<=22357) then
return 327680 -- 655360/2
end
end},
["Adobe-CNS1"] = {"UniCNS-UTF32", 19155, 6,
function (i)
if (13648<=i and i<=13742) or (i==17603) then
return 327680 -- 655360/2
end
end},
}
-- reading CID maps
do
local line, fh -- line, file handler
local tt,cidm -- characters, cid->(Unicode)
local function load_cid_char(cid_dec, mke)
local cid, ucs, ucsa
line = fh:read("*l")
while line do
if string.find(line, "end...?char") then
line = fh:read("*l"); return
else -- WMA l is in the form "<%x+>%s%d+"
ucs, cid = string.match(line, "<(%x+)>%s+<?(%x+)>?")
cid = cid_dec(cid); ucs = tonumber(ucs, 16);
if not tt[ucs] then
tt[ucs] = mke(cid); cidm[cid]=ucs
end
end
line = fh:read("*l")
end
end
local function load_cid_range(inc, cid_dec, mke)
local bucs, eucs, cid
line = fh:read("*l")
while line do
if string.find(line, "end...?range") then
line = fh:read("*l"); return
else -- WMA l is in the form "<%x+>%s+<%x+>"
bucs, eucs, cid = string.match(line, "<(%x+)>%s+<(%x+)>%s+<?(%x+)>?")
cid = cid_dec(cid);
bucs = tonumber(bucs, 16); eucs = tonumber(eucs, 16)
for ucs = bucs, eucs do
if not tt[ucs] then
tt[ucs] = mke(cid); cidm[cid]=ucs
end
cid = inc(cid)
end
end
line = fh:read("*l")
end
end
local function open_cmap_file(name, inc, cid_dec, mke)
fh = io.open(kpse.find_file(name, 'cmap files'), "r")
line = fh:read("*l")
while line do
if string.find(line, "%x+%s+begin...?char") then
load_cid_char(cid_dec, mke)
elseif string.find(line, "%x+%s+begin...?range") then
load_cid_range(inc, cid_dec, mke)
else
line = fh:read("*l")
end
end
fh:close();
end
local function increment(a) return a+1 end
local function entry(a)
return {index = a}
end
function make_cid_font()
local kx = cid_replace[cid_name]
if not kx then return end
local k = {
cidinfo = { ordering=cid_order, registry=cid_reg, supplement=kx[3] },
encodingbytes = 2, extend=1000, format = 'opentype',
direction = 0, characters = {}, parameters = {}, embedding = "no", cache = "yes",
ascender = 0, descender = 0, factor = 0, hfactor = 0, vfactor = 0,
tounicode = 1,
}
cidfont_data[cid_name] = k
-- CID => Unicode 符号空間
-- TODO: vertical fonts?
tt, cidm = {}, {}
for i = 0,kx[2] do cidm[i] = -1 end
open_cmap_file(kx[1] .. "-H", increment, tonumber, entry)
k.characters = tt
-- Unicode にマップされなかった文字の処理
-- これらは TrueType フォントを使って表示するときはおかしくなる
local ttu, pricode = {}, 0xF0000
for i,v in ipairs(cidm) do
if v==-1 then
tt[pricode], cidm[i], pricode
= { index = i }, pricode, pricode+1;
end
ttu[cid_order .. '.' .. i] = cidm[i]
end
-- shared
k.shared = {
otfdata = {
cidinfo= k.cidinfo, verbose = false,
shared = { featuredata = {}, },
luatex = { features = {},
defaultwidth=1000,
sequences = { }, },
},
dynamics = {}, features = {}, processes = {},
}
k.resources = { unicodes = ttu, }
k.descriptions = {}
cache_chars[cid_name] = { [655360] = k.characters }
-- tounicode エントリ
local cidp = {nil, nil}; local cidmo = cidm
tt, ttu, cidm = {}, {}, {}
open_cmap_file(cid_name .. "-UCS2",
function(a)
a[2] = a[2] +1 ; return a
end,
function(a)
cidp[1] = string.upper(string.sub(a,1,string.len(a)-4))
cidp[2] = tonumber(string.sub(a,-4),16)
return cidp
end,
function(a) return a[1] ..string.format('%04X',a[2]) end)
-- tt は cid -> tounicode になっているので cidm -> tounicode に変換
local kxf = kx[4]
for i,v in ipairs(cidmo) do
k.characters[v].width = kxf(i)
if v>=0xF0000 then
k.characters[v].tounicode = tt[i]
end
end
-- Save
local savepath = path.localdir .. '/luatexja/'
if not lfs.isdir(savepath) then
dir.mkdirs(savepath)
end
savepath = file.join(savepath, "ltj-cid-auto-"
.. string.lower(cid_name) .. ".lua")
if file.iswritable(savepath) then
k.characters[46].width = math.floor(655360/14);
-- Standard fonts are ``seriffed''.
table.tofile(savepath, k,'return', false, true, false )
ltjb.package_info_no_line('luatexja', "saved :'" .. savepath .. "'", '')
else
ltjb.package_warning_no_line('luatexja', "failed to save to '" .. savepath .. "'", '')
end
end
end
local make_cid_font = make_cid_font
--
local function cid_cache_load(fullpath)
cidfont_data[cid_name] = require(fullpath)
cache_chars[cid_name] = { [655360] = cidfont_data[cid_name].characters }
end
local function read_cid_font()
-- local v = "ltj-cid-" .. string.lower(cid_name) .. ".lua"
local v = "ltj-cid-auto-" .. string.lower(cid_name) .. ".lua"
local localpath = file.join(path.localdir .. '/luatexja', v)
local systempath = file.join(path.systemdir .. '/luatexja' , v)
local kpsefound = kpse.find_file(v)
if kpsefound and file.isreadable(kpsefound) then
cid_cache_load(kpsefound)
elseif file.isreadable(localpath) then
cid_cache_load(localpath)
elseif file.isreadable(systempath) then
cid_cache_load(systempath)
else
-- Now we must create the virtual metrics from CMap.
make_cid_font()
end
if cidfont_data[cid_name] then
for i,v in pairs(cidfont_data[cid_name].characters) do
if not v.width then v.width = 655360 end
v.height, v.depth = 576716.8, 78643.2 -- optimized for jfm-ujis.lua
end
end
end
-- High-level
local definers = fonts.definers
local function mk_rml(name, size, id)
local specification = definers.analyze(name,size)
specification = definers.resolve(specification)
specification.detail = specification.detail or ''
local fontdata = {}
local cachedata = {}
local s = cidfont_data[cid_name]
for k, v in pairs(s) do
fontdata[k] = v
cachedata[k] = v
end
fontdata.characters = nil
cachedata.characters = nil
fontdata.shared = nil
cachedata.shared = nil
if s.shared then
cachedata.shared = {}
local shared = cachedata.shared
for k, v in pairs(s.shared) do
shared[k] = v
end
end
-- characters & scaling
if size < 0 then size = -size * 655.36 end
local scale = size / 655360
do
local def_height = 0.88 * size
-- character's default height (optimized for jfm-ujis.lua)
local def_depth = 0.12 * size -- and depth.
if not cache_chars[cid_name][size] then
cache_chars[cid_name][size] = {}
for k, v in pairs(cache_chars[cid_name][655360]) do
cache_chars[cid_name][size][k] = {
index = v.index, width = v.width * scale,
height = def_height, depth = def_depth, tounicode = v.tounicode,
}
end
end
fontdata.characters = cache_chars[cid_name][size]
cachedata.characters = cache_chars[cid_name][size]
end
-- other parameters
do
local parameters = {}
for k, v in pairs(s.parameters) do
parameters[k] = v * scale
end
fontdata.parameters = parameters
fontdata.ascender = fontdata.ascender * scale
fontdata.descender = fontdata.descender * scale
fontdata.factor = fontdata.factor * scale
fontdata.hfactor = fontdata.hfactor * scale
fontdata.vfactor = fontdata.vfactor * scale
fontdata.size = size
fontdata.resources = s.resources
cachedata.parameters = parameters
cachedata.ascender = fontdata.ascender
cachedata.descender = fontdata.descender
cachedata.factor = fontdata.factor
cachedata.hfactor = fontdata.hfactor
cachedata.vfactor = fontdata.vfactor
cachedata.size = size
cachedata.resources = s.resources
end
-- no embedding
local var = ''
local s = string.match(specification.detail, 'slant=([+-]*%d*%.?%d)')
if s and e~=0 then
s = s * 1000
var, fontdata.slant = var .. 's' .. tostring(s), s
end
local e = string.match(specification.detail, 'extend=([+-]*%d*%.?%d)')
if e and e~=1 then
e = e * 1000
var, fontdata.extend = var .. 'x' .. tostring(e), e
end
fontdata.name = specification.name .. size .. var; cachedata.name = fontdata.name
fontdata.fullname = specification.name .. var; cachedata.fullname = fontdata.fullname
fontdata.psname = specification.name; cachedata.psname = fontdata.psname
fonts.ids[id] = cachedata
return fontdata
end
function font_callback(name, size, id, fallback)
local p = utf.find(name, ":") or utf.len(name)+1
if utf.sub(name, 1, p-1) == 'psft' then
local s = "Adobe-Japan1-6"
local basename = utf.sub(name,p+1)
local p = utf.find(basename, ":")
local q = utf.find(basename, "/[BI][BI]?")
if q and p and q<=p then
basename = utf.gsub(basename, '/[BI][BI]?', '', 1)
p = utf.find(basename, ":")
end
if p then
local xname = utf.sub(basename, p+1)
p = 1
while p do
local q = utf.find(xname, ";", p+1) or utf.len(xname)+1
if utf.sub(xname, p, p+3)=='cid=' and q>p+4 then
s = utf.sub(xname, p+4, q-1)
end
if utf.len(xname)+1==q then p = nil else p = q + 1 end
end
end
cid_reg, cid_order = string.match(s, "^(.-)%-(.-)%-(%d-)$")
if not cid_reg then
cid_reg, cid_order = string.match(s, "^(.-)%-(.-)$")
end
cid_name = cid_reg .. '-' .. cid_order
if not cidfont_data[cid_name] then
read_cid_font()
if not cidfont_data[cid_name] then
ltjb.package_error('luatexja',
"bad cid key `" .. s .. "'",
"I couldn't find any non-embedded font information for the CID\n" ..
'`' .. s .. "'. For now, I'll use `Adobe-Japan1-6'.\n"..
'Please contact the LuaTeX-ja project team.')
cid_name = "Adobe-Japan1"
end
end
return mk_rml(basename, size, id)
else
return fallback(name, size, id)
end
end
cid_reg, cid_order, cid_name, cid_supp = 'Adobe', 'Japan1', 'Adobe-Japan1'
read_cid_font()
|