- if not v.chars then
- if i ~= 0 then defjfm_res= nil; return end
- else
- for j,w in pairs(v.chars) do
- if type(w) == 'number' and w~=-1 then
- elseif type(w) == 'string' and utf.len(w)==1 then
- w = utf.byte(w)
- elseif type(w) == 'string' and utf.len(w)==2 and utf.sub(w,2) == '*' then
- w = utf.byte(utf.sub(w,1,1))
- end
- if not t.chars[w] then
- t.chars[w] = i
- else
- defjfm_res= nil; return
- end
- end
- v.chars = nil
- end
- if type(v.align)~='string' then
- v.align = 'left' -- left
- end
- if type(v.width)~='number' then
- v.width = nil
- end
- if type(v.height)~='number' then
- v.height = (jfm_dir=='tate') and 0.0
- end
- if type(v.depth)~='number' then
- v.depth = (jfm_dir=='tate') and 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 t.version>=2 then
- if v.end_stretch then defjfm_res= nil; return end
- if v.end_shrink then defjfm_res= nil; return end
- if v.end_adjust then
- if type(v.end_adjust)~='table' then
- v.end_adjust = nil
- elseif #(v.end_adjust)==0 then
- v.end_adjust = nil
- else
- table.sort(v.end_adjust)
- end
- end
- else
- v.end_adjust = nil
- if v.end_stretch and v.end_stretch~=0.0 then
- v.end_adjust = (v.end_adjust or {})
- v.end_adjust[#(v.end_adjust)+1] = v.end_stretch
- end
- if v.end_shrink and v.end_ahrink~=0.0 then
- v.end_adjust = (v.end_adjust or {})
- v.end_adjust[#(v.end_adjust)+1] = -v.end_shrink
- end
- if v.end_adjust then v.end_adjust[#(v.end_adjust)+1] = 0.0 end
- end
- v.kern = v.kern or {}; v.glue = v.glue or {}
- for j,x in pairs(v.glue) do
- if v.kern[j] then defjfm_res= nil; return end
- x.ratio, x[5] = (x.ratio or (x[5] and 0.5*(1+x[5]) or 0.5)), nil
- do
- local xp
- xp, x[4] = (x.priority or x[4]), nil
- if type(xp)=='table' and t.version>=2 then
- if type(xp[1])~='number' or xp[1]<-4 or xp[1]>3 then defjfm_res=nil end -- stretch
- if type(xp[2])~='number' or xp[2]<-4 or xp[2]>3 then defjfm_res=nil end -- shrink
- xp = (xp[1]+4)*8+(xp[2]+4)
- elseif xp and type(xp)~='number' then
- defjfm_res = nil
- else
- xp = (xp or 0)*9+36
- if xp<0 or xp>=64 then defjfm_res=nil end
- end
- x.priority = xp
- end
- x.kanjiskip_natural = norm_val(x.kanjiskip_natural)
- x.kanjiskip_stretch = norm_val(x.kanjiskip_stretch)
- x.kanjiskip_shrink = norm_val(x.kanjiskip_shrink)
- end
- for j,x in pairs(v.kern) do
- if type(x)=='number' then
+ if not v.chars then
+ if i ~= 0 then defjfm_res= nil; return end
+ else
+ for j,w in pairs(v.chars) do
+ if type(w) == 'number' and w~=-1 then
+ elseif type(w) == 'string' and utf.len(w)==1 then
+ w = utf.byte(w)
+ elseif type(w) == 'string' and utf.len(w)==2 and utf.sub(w,2) == '*' then
+ w = utf.byte(utf.sub(w,1,1))
+ end
+ if not t.chars[w] then
+ t.chars[w] = i
+ else
+ defjfm_res= nil; return
+ end
+ end
+ v.chars = nil
+ end
+ if type(v.align)~='string' then
+ v.align = 'left' -- left
+ end
+ if type(v.width)~='number' then
+ v.width = nil
+ end
+ if type(v.height)~='number' then
+ v.height = (jfm_dir=='tate') and 0.0
+ end
+ if type(v.depth)~='number' then
+ v.depth = (jfm_dir=='tate') and 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 t.version>=2 then
+ if v.end_stretch then defjfm_res= nil; return end
+ if v.end_shrink then defjfm_res= nil; return end
+ if v.end_adjust then
+ if type(v.end_adjust)~='table' then
+ v.end_adjust = nil
+ elseif #(v.end_adjust)==0 then
+ v.end_adjust = nil
+ else
+ table.sort(v.end_adjust)
+ end
+ end
+ else
+ v.end_adjust = nil
+ if v.end_stretch and v.end_stretch~=0.0 then
+ v.end_adjust = (v.end_adjust or {})
+ v.end_adjust[#(v.end_adjust)+1] = v.end_stretch
+ end
+ if v.end_shrink and v.end_ahrink~=0.0 then
+ v.end_adjust = (v.end_adjust or {})
+ v.end_adjust[#(v.end_adjust)+1] = -v.end_shrink
+ end
+ if v.end_adjust then v.end_adjust[#(v.end_adjust)+1] = 0.0 end
+ end
+ v.kern = v.kern or {}; v.glue = v.glue or {}
+ for j,x in pairs(v.glue) do
+ if v.kern[j] then defjfm_res= nil; return end
+ x.ratio, x[5] = (x.ratio or (x[5] and 0.5*(1+x[5]) or 0.5)), nil
+ do
+ local xp
+ xp, x[4] = (x.priority or x[4]), nil
+ if type(xp)=='table' and t.version>=2 then
+ if type(xp[1])~='number' or xp[1]<-4 or xp[1]>3 then defjfm_res=nil end -- stretch
+ if type(xp[2])~='number' or xp[2]<-4 or xp[2]>3 then defjfm_res=nil end -- shrink
+ xp = (xp[1]+4)*8+(xp[2]+4)
+ elseif xp and type(xp)~='number' then
+ defjfm_res = nil
+ else
+ xp = (xp or 0)*9+36
+ if xp<0 or xp>=64 then defjfm_res=nil end
+ end
+ x.priority = xp
+ end
+ x.kanjiskip_natural = norm_val(x.kanjiskip_natural)
+ x.kanjiskip_stretch = norm_val(x.kanjiskip_stretch)
+ x.kanjiskip_shrink = norm_val(x.kanjiskip_shrink)
+ end
+ for j,x in pairs(v.kern) do
+ if type(x)=='number' then
- v.align = (v.align=='left') and 0 or
- ((v.align=='right') and 1 or 0.5)
- if type(i) == 'number' then -- char_type
- for k,w in pairs(v.glue) do
- v[k] = {
- nil,
- ratio=w.ratio/sz,
- priority=FROM_JFM + w.priority/sz,
- width = w[1], stretch = w[2], shrink = w[3],
- kanjiskip_natural = w.kanjiskip_natural and w.kanjiskip_natural/sz,
- kanjiskip_stretch = w.kanjiskip_stretch and w.kanjiskip_stretch/sz,
- kanjiskip_shrink = w.kanjiskip_shrink and w.kanjiskip_shrink/sz,
- }
- end
- for k,w in pairs(v.kern) do
- local g = node_new(id_kern, 1)
- setfield(g, 'kern', w[1])
- set_attr(g, attr_icflag, FROM_JFM)
- v[k] = {g, ratio=w[2]/sz}
- end
- end
- v.glue, v.kern = nil, nil
+ v.align = (v.align=='left') and 0 or
+ ((v.align=='right') and 1 or 0.5)
+ if type(i) == 'number' then -- char_type
+ for k,w in pairs(v.glue) do
+ v[k] = {
+ nil,
+ ratio=w.ratio/sz,
+ priority=FROM_JFM + w.priority/sz,
+ width = w[1], stretch = w[2], shrink = w[3],
+ kanjiskip_natural = w.kanjiskip_natural and w.kanjiskip_natural/sz,
+ kanjiskip_stretch = w.kanjiskip_stretch and w.kanjiskip_stretch/sz,
+ kanjiskip_shrink = w.kanjiskip_shrink and w.kanjiskip_shrink/sz,
+ }
+ end
+ for k,w in pairs(v.kern) do
+ local g = node_new(id_kern, 1)
+ setfield(g, 'kern', w[1])
+ set_attr(g, attr_icflag, FROM_JFM)
+ v[k] = {g, ratio=w[2]/sz}
+ end
+ end
+ v.glue, v.kern = nil, nil
jfm_dir, is_def_jfont = dir, true
cstemp = csname:sub( (utf8.byte(csname,1,1) == tex.escapechar) and 2 or 1, -1)
cstemp = cstemp:sub(1, ((cstemp:sub(-1,-1)==' ') and (cstemp:len()>=2)) and -2 or -1)
global_flag = g and '\\global' or ''
tex.sprint(cat_lp, '\\expandafter\\font\\csname ',
jfm_dir, is_def_jfont = dir, true
cstemp = csname:sub( (utf8.byte(csname,1,1) == tex.escapechar) and 2 or 1, -1)
cstemp = cstemp:sub(1, ((cstemp:sub(-1,-1)==' ') and (cstemp:len()>=2)) and -2 or -1)
global_flag = g and '\\global' or ''
tex.sprint(cat_lp, '\\expandafter\\font\\csname ',
- 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, global_flag, '\\expandafter\\let\\csname ',
- (cstemp==' ') and '\\space' or cstemp,
- '\\endcsname=\\relax')
- return
+ 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, global_flag, '\\expandafter\\let\\csname ',
+ (cstemp==' ') and '\\space' or cstemp,
+ '\\endcsname=\\relax')
+ return
- local l = name:len()+1
- local q = name:find(";", index+1) or l
- if name:sub(index, index+3)=='jfm=' and q>index+4 then
- jfm_file_name = name:sub(index+4, q-1)
- if l~=q then
- name = name:sub(1,index-1) .. name:sub(q+1)
- else
- name = name:sub(1,index-1)
- index = nil
- end
- elseif name:sub(index, index+6)=='jfmvar=' and q>index+6 then
- jfm_var = name:sub(index+7, q-1)
- if l~=q then
- name = name:sub(1,index-1) .. name:sub(q+1)
- else
- name = name:sub(1,index-1)
- index = nil
- end
- else
- index = (l~=q) and (q+1) or nil
- end
+ local l = name:len()+1
+ local q = name:find(";", index) or l
+ if name:sub(index, index+3)=='jfm=' and q>index+4 then
+ jfm_file_name = name:sub(index+4, q-1)
+ if l~=q then
+ name = name:sub(1,index-1) .. name:sub(q+1)
+ else
+ name = name:sub(1,index-1)
+ index = nil
+ end
+ elseif name:sub(index, index+6)=='jfmvar=' and q>index+6 then
+ jfm_var = name:sub(index+7, q-1)
+ if l~=q then
+ name = name:sub(1,index-1) .. name:sub(q+1)
+ else
+ name = name:sub(1,index-1)
+ index = nil
+ end
+ else
+ index = (l~=q) and (q+1) or nil
+ end
- for i,_ in pairs(kyenc_list) do
- if kpse.find_file(string.lower(i)..fam..'.fd') then
- tex.sprint(cat_lp, '\\let\\ifin@\\iftrue '); return
- end
- end
- for i,_ in pairs(ktenc_list) do
- if kpse.find_file(string.lower(i)..fam..'.fd') then
- tex.sprint(cat_lp, '\\let\\ifin@\\iftrue '); return
- end
- end
- Nkfam_list[fam]=true; tex.sprint(cat_lp, '\\let\\ifin@\\iffalse '); return
+ for i,_ in pairs(kyenc_list) do
+ if kpse.find_file(string.lower(i)..fam..'.fd') then
+ tex.sprint(cat_lp, '\\let\\ifin@\\iftrue '); return
+ end
+ end
+ for i,_ in pairs(ktenc_list) do
+ if kpse.find_file(string.lower(i)..fam..'.fd') then
+ tex.sprint(cat_lp, '\\let\\ifin@\\iftrue '); return
+ end
+ end
+ Nkfam_list[fam]=true; tex.sprint(cat_lp, '\\let\\ifin@\\iffalse '); return
- for _,i in pairs(id.resources.sequences) do
- if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
- for _,j in pairs(i.steps) do
- if type(j)=='table' then
- if type(j,coverage)=='table' then
- for i,_ in pairs(j.coverage) do rot[i]=nil end
- end
- end
- end
- end
- end; end
- -- コードポイントが共有されているグリフについて
+ for _,i in pairs(id.resources.sequences) do
+ if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
+ for _,j in pairs(i.steps) do
+ if type(j)=='table' then
+ if type(j.coverage)=='table' then
+ for i,_ in pairs(j.coverage) do rot[i]=nil end
+ end
+ end
+ end
+ end
+ end; end
+ -- コードポイントが共有されているグリフについて
- if uniq_flag then
- dest = dest or {}; dest[bu] = dest[bu] or {}
- dest[bu][vsel] = unitable[gv.name]
- end
- end
- end
- end
- -- vertical metric
- local vw, tsb, vk = glyph_vmetric(gv)
- local gi = unitable[gv.name]
- if gi and vw and vw~=asc_des then
- -- We do not use tsidebearing, since (1) fontloader does not read VORG table
- -- and (2) 'tsidebearing' doea not appear in the returned table by fontloader.fields.
- -- Hence, we assume that vertical origin == ascender
- -- (see capsule_glyph_tate in ltj-setwidth.lua)
- dest = dest or {}; dest[gi] = dest[gi] or {}
- dest[gi].vwidth = vw/units
- end
- -- vertical kern
- if gi and vk then
- dest = dest or {};
- local dest_vk = dest.vkerns or {}; dest.vkerns = dest_vk
- for _,v in pairs(vk) do
- if unitable[v.char] then
- local vl = v.lookup
- if type(vl)=='table' then
- for _,vlt in pairs(vl) do
- dest_vk[vlt] = dest_vk[vlt] or {}
- dest_vk[vlt][gi] = dest_vk[vlt][gi] or {}
- dest_vk[vlt][gi][unitable[v.char]] = v.off
- end
- else
- dest_vk[vl] = dest_vk[vl] or {}
- dest_vk[vl][gi] = dest_vk[vl][gi] or {}
- dest_vk[vl][gi][unitable[v.char]] = v.off
- end
- end
- end
- end
- end
+ end
+ end
+ end
+ -- vertical metric
+ local vw, tsb, vk = glyph_vmetric(gv)
+ local gi = unitable[gv.name]
+ if gi and vw and vw~=asc_des then
+ -- We do not use tsidebearing, since (1) fontloader does not read VORG table
+ -- and (2) 'tsidebearing' doea not appear in the returned table by fontloader.fields.
+ -- Hence, we assume that vertical origin == ascender
+ -- (see capsule_glyph_tate in ltj-setwidth.lua)
+ dest = dest or {}; dest[gi] = dest[gi] or {}
+ dest[gi].vwidth = vw/units
+ end
+ -- vertical kern
+ if gi and vk then
+ dest = dest or {};
+ local dest_vk = dest.vkerns or {}; dest.vkerns = dest_vk
+ for _,v in pairs(vk) do
+ if unitable[v.char] then
+ local vl = v.lookup
+ if type(vl)=='table' then
+ for _,vlt in pairs(vl) do
+ dest_vk[vlt] = dest_vk[vlt] or {}
+ dest_vk[vlt][gi] = dest_vk[vlt][gi] or {}
+ dest_vk[vlt][gi][unitable[v.char]] = v.off
+ end
+ else
+ dest_vk[vl] = dest_vk[vl] or {}
+ dest_vk[vl][gi] = dest_vk[vl][gi] or {}
+ dest_vk[vl][gi][unitable[v.char]] = v.off
+ end
+ end
+ end
+ end
+ end
- -- if the cache is present, read it
- local newsum = checksum(id.filename) -- MD5 checksum of the fontfile
- local v = "extra_" .. string.lower(bname)
- local dat = ltjb.load_cache(
- v,
- function (t) return (t.version~=cache_ver) or (t.chksum~=newsum) end
- )
- -- if the cache is not found or outdated, save the cache
- if dat then
- font_extra_basename[bname] = dat[1] or {}
- else
- local dat = nil
- dat = prepare_fl_data(dat, id)
- dat = list_rotate_glyphs(dat, id)
- font_extra_basename[bname] = dat or {}
- ltjb.save_cache( v,
- {
- chksum = checksum(id.filename),
- version = cache_ver,
- dat,
- })
- end
- return bname
+ -- if the cache is present, read it
+ if not lfs then lfs=require"lfs" end
+ local newtime = lfs.attributes(id.filename,"modification")
+ local v = "extra_" .. string.lower(bname)
+ local dat = ltjb.load_cache(
+ v,
+ function (t) return (t.version~=cache_ver) or (t.modtime~=newtime) end
+ )
+ -- if the cache is not found or outdated, save the cache
+ if dat then
+ font_extra_basename[bname] = dat[1] or {}
+ else
+ local dat = nil
+ dat = prepare_fl_data(dat, id)
+ dat = list_rotate_glyphs(dat, id)
+ font_extra_basename[bname] = dat or {}
+ ltjb.save_cache( v,
+ {
+ modtime = newtime,
+ version = cache_ver,
+ dat,
+ })
+ end
+ return bname
- for feat_name,v in pairs(ft.specification.features.normal) do
- if v==true and ft.resources then
- for _,i in pairs(ft.resources.sequences) do
- if i.order[1]== feat_name and i.type == 'gpos_single' and type(i.subtables)=='table' then
- for _,st in pairs(i.subtables) do
- subtables[st] = true
- end
- end
- end
- end
- end
- acc_feature(vadv, vorg, subtables, ft,
- ft.specification.features.normal.vrt2 or ft.specification.features.normal.vert)
- for i,v in pairs(vadv) do
- vadv[i]=vadv[i]/ft.units_per_em*fmtable.size
- end
- for i,v in pairs(vorg) do
- vorg[i]=vorg[i]/ft.units_per_em*fmtable.size
- end
+ for feat_name,v in pairs(ft.specification.features.normal) do
+ if v==true and ft.resources then
+ for _,i in pairs(ft.resources.sequences) do
+ if i.order[1]== feat_name and i.type == 'gpos_single' and type(i.subtables)=='table' then
+ for _,st in pairs(i.subtables) do
+ subtables[st] = true
+ end
+ end
+ end
+ end
+ end
+ acc_feature(vadv, vorg, subtables, ft,
+ ft.specification.features.normal.vrt2 or ft.specification.features.normal.vert)
+ for i,v in pairs(vadv) do
+ vadv[i]=vadv[i]/ft.units_per_em*fmtable.size
+ end
+ for i,v in pairs(vorg) do
+ vorg[i]=vorg[i]/ft.units_per_em*fmtable.size
+ end
- local ft = font_getfont(fnum)
- if ft.specification and ft.resources then
- for _,i in pairs(ft.resources.sequences) do
- if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
- for _,j in pairs(i.steps) do
- if type(j)=='table' then add_vform(j.coverage,vform, ft) end
- end
- end
- end
+ local t = font_getfont(fnum)
+ if t.specification and t.resources then
+ local add_vert
+ = not (provides_feature(fnum, t.properties.script, t.properties.language, 'vert'))
+ and not (provides_feature(fnum, t.properties.script, t.properties.language, 'vrt2'))
+ -- 現在の language, script で vert もvrt2 も有効にできない場合,強制的に vert 適用
+ for _,i in pairs(t.resources.sequences) do
+ if i.order[1]== 'vert' and i.type == 'gsub_single' and i.steps then
+ for _,j in pairs(i.steps) do
+ if type(j)=='table' then add_vform(j.coverage,vform, t, add_vert) end
+ end
+ end
+ end
- local cidinfo = tfmdata.cidinfo or tfmdata.resources.cidinfo
- if cidinfo and cidinfo.registry and cidinfo.ordering then
- local rd = ltjr_prepare_cid_font(cidinfo.registry, cidinfo.ordering)
- if rd then
- local ru, rc = rd.resources.unicodes, rd.characters
- for i,v in pairs(tfmdata.characters) do
- local w = ru["Japan1." .. tostring(v.index)]
- if w then
- v.tounicode = v.tounicode or rc[w]. tounicode
- end
- end
- end
- end
+ local cidinfo = tfmdata.cidinfo or tfmdata.resources.cidinfo
+ if cidinfo and cidinfo.registry and cidinfo.ordering then
+ local rd = ltjr_prepare_cid_font(cidinfo.registry, cidinfo.ordering)
+ if rd then
+ local ru, rc = rd.resources.unicodes, rd.characters
+ for i,v in pairs(tfmdata.characters) do
+ local w = ru["Japan1." .. tostring(v.index)]
+ if w then
+ v.tounicode = v.tounicode or rc[w]. tounicode
+ end
+ end
+ end
+ end
- if is_ucs_in_japanese_char(p) then
- local j = font_metric_table[
- has_attr(p, (get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)
- ]
- local g = new_ic_kern()
- setfield(g, 'kern', j.char_type[find_char_class(getchar(p), j)].italic)
- node_write(g); ensure_tex_attr(attr_icflag, 0)
- else
- local f = getfont(p)
- local h = font_getfont(f) or font.fonts[f]
- if h then
- local g = new_ic_kern()
- if h.characters[getchar(p)] and h.characters[getchar(p)].italic then
- setfield(g, 'kern', h.characters[getchar(p)].italic)
- node_write(g); ensure_tex_attr(attr_icflag, 0)
- end
- end
- end
+ if is_ucs_in_japanese_char(p) then
+ local j = font_metric_table[
+ has_attr(p, (get_dir_count()==dir_tate) and attr_curtfnt or attr_curjfnt)
+ ]
+ local g = new_ic_kern()
+ setfield(g, 'kern', j.char_type[find_char_class(getchar(p), j)].italic)
+ node_write(g); ensure_tex_attr(attr_icflag, 0)
+ else
+ local f = getfont(p)
+ local h = font_getfont(f) or font.fonts[f]
+ if h then
+ local g = new_ic_kern()
+ if h.characters[getchar(p)] and h.characters[getchar(p)].italic then
+ setfield(g, 'kern', h.characters[getchar(p)].italic)
+ node_write(g); ensure_tex_attr(attr_icflag, 0)
+ end
+ end
+ end