summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luatexko/luatexko.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/generic/luatexko/luatexko.lua')
-rw-r--r--macros/luatex/generic/luatexko/luatexko.lua629
1 files changed, 323 insertions, 306 deletions
diff --git a/macros/luatex/generic/luatexko/luatexko.lua b/macros/luatex/generic/luatexko/luatexko.lua
index f7819aec89..3f21e7c970 100644
--- a/macros/luatex/generic/luatexko/luatexko.lua
+++ b/macros/luatex/generic/luatexko/luatexko.lua
@@ -1,6 +1,6 @@
-- luatexko.lua
--
--- Copyright (c) 2013-2019 Dohyun Kim <nomos at ktug org>
+-- Copyright (c) 2013-2020 Dohyun Kim <nomos at ktug org>
-- Soojin Nam <jsunam at gmail com>
--
-- This work may be distributed and/or modified under the
@@ -13,8 +13,8 @@
luatexbase.provides_module {
name = 'luatexko',
- date = '2019/12/01',
- version = '2.5',
+ date = '2020/02/17',
+ version = '2.6',
description = 'typesetting Korean with LuaTeX',
author = 'Dohyun Kim, Soojin Nam',
license = 'LPPL v1.3+',
@@ -113,10 +113,255 @@ local autojosaattr = attributes.luatexkoautojosaattr
local classicattr = attributes.luatexkoclassicattr
local dotemphattr = attributes.luatexkodotemphattr
local rubyattr = attributes.luatexkorubyattr
+local hangulbyhangulattr = attributes.luatexkohangulbyhangulattr
+local hanjabyhanjaattr = attributes.luatexkohanjabyhanjaattr
local vert_classic = 1
local SC_classic = 2
+local stretch_f = 5/100 -- should be consistent for ruby
+
+local function get_font_data (fontid)
+ return fontgetfont(fontid) or fontfonts[fontid] or {}
+end
+
+local function get_font_param (f, key)
+ local t
+ if type(f) == "number" then
+ t = getparameters(f)
+ if t and t[key] then
+ return t[key]
+ end
+ f = get_font_data(f)
+ end
+ if type(f) == "table" then
+ t = f.parameters
+ return t and t[key]
+ end
+end
+
+local function option_in_font (fontdata, optionname)
+ if type(fontdata) == "number" then
+ fontdata = get_font_data(fontdata)
+ end
+ if fontdata.specification then
+ return fontdata.specification.features.normal[optionname]
+ end
+end
+
+local function font_opt_dim (fd, optname)
+ local dim = option_in_font(fd, optname)
+ if dim then
+ local params
+ if type(fd) == "number" then
+ params = getparameters(fd)
+ else
+ params = fd.parameters
+ end
+ local m, u = dim:match"^(.+)(e[mx])%s*$"
+ if m and u and params then
+ if u == "em" then
+ dim = m * params.quad
+ else
+ dim = m * params.x_height
+ end
+ else
+ dim = texsp(dim)
+ end
+ return dim
+ end
+end
+
+local function is_harf (f)
+ if type(f) == "number" then
+ f = get_font_data(f)
+ end
+ return f.hb
+end
+
+local function is_not_harf (f)
+ if option_in_font(f, "mode") == "harf" then -- mode=harf with non-luahbtex
+ return false
+ end
+ return not is_harf(f)
+end
+
+local function harf_reordered_tonemark (curr)
+ if is_harf(curr.font) then
+ local props = getproperty(curr) or {}
+ local actualtext = props.luaotfload_startactualtext or ""
+ return actualtext:find"302[EF]$"
+ end
+end
+
+local os2tag = luaotfload.harfbuzz and luaotfload.harfbuzz.Tag.new"OS/2"
+
+local font_options = {
+ charraise = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local dim = font_opt_dim(fid, "charraise") or false
+ t[fid] = dim
+ return dim
+ end
+ end }),
+
+ intercharacter = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local dim = font_opt_dim(fid, "intercharacter") or false
+ t[fid] = dim
+ return dim
+ end
+ end }),
+
+ intercharstretch = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local dim = font_opt_dim(fid, "intercharstretch") or false
+ t[fid] = dim
+ return dim
+ end
+ end }),
+
+ interhangul = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local dim = font_opt_dim(fid, "interhangul") or false
+ t[fid] = dim
+ return dim
+ end
+ end }),
+
+ interlatincjk = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local dim = font_opt_dim(fid, "interlatincjk") or false
+ t[fid] = dim
+ return dim
+ end
+ end }),
+
+ en_size = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ val = (get_font_param(fid, "quad") or 655360)/2
+ t[fid] = val
+ return val
+ end
+ return 327680
+ end } ),
+
+ hangulspaceskip = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local newwd
+ if is_harf(fid) then
+ newwd = getparameters(fid) or false
+ if newwd then
+ newwd = { newwd.space, newwd.space_stretch, newwd.space_shrink }
+ end
+ else
+ local newsp = nodenew(glyphid)
+ newsp.char, newsp.font = 32, fid
+ newsp = nodes.simple_font_handler(newsp)
+ newwd = newsp and newsp.width or false
+ if newwd then
+ newwd = { texsp(newwd), texsp(newwd/2), texsp(newwd/3) }
+ end
+ if newsp then nodefree(newsp) end
+ end
+ t[fid] = newwd
+ return newwd
+ end
+ end } ),
+
+ monospaced = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ -- space_stretch has been set to zero by fontloader
+ if get_font_param(fid, "space_stretch") == 0 then
+ t[fid] = true; return true
+ end
+ -- but not in harf mode; so we simply test widths of some glyphs
+ if is_harf(fid) then
+ local chars = get_font_data(fid).characters or {}
+ local i, M = chars[0x69], chars[0x4D]
+ if i and M and i.width == M.width then
+ t[fid] = true; return true
+ end
+ end
+ t[fid] = false; return false
+ end
+ end } ),
+
+ tonemarkwidth = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local hwidth
+ -- check horizontal width; vertical width is mostly non-zero
+ local fontdata = get_font_data(fid)
+ local shared = fontdata.shared or {}
+ local rawdata = shared.rawdata or {}
+ local descriptions = rawdata.descriptions or {}
+ local description = descriptions[0x302E] or {}
+ hwidth = description.width or 0
+ t[fid] = hwidth
+ return hwidth
+ end
+ return 0
+ end } ),
+
+ asc_desc = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local asc, desc
+ -- luaharfbuzz's Font:get_h_extents() gets ascender value from hhea table;
+ -- Node mode's parameters.ascender is gotten from OS/2 table.
+ -- TypoAscender in OS/2 table seems to be more suitable for our purpose.
+ local hb = is_harf(fid)
+ if hb and os2tag then
+ local hbface = hb.shared.face
+ local tags = hbface:get_table_tags()
+ local hasos2 = false
+ for _,v in ipairs(tags) do
+ if v == os2tag then
+ hasos2 = true
+ break
+ end
+ end
+ if hasos2 then
+ local os2 = hbface:get_table(os2tag)
+ local length = os2:get_length()
+ if length > 69 then -- sTypoAscender (int16)
+ local data = os2:get_data()
+ local typoascender = stringunpack(">h", data, 69)
+ local typodescender = stringunpack(">h", data, 71)
+ asc = typoascender * hb.scale
+ desc = -typodescender * hb.scale
+ end
+ end
+ end
+ asc = asc or get_font_param(fid, "ascender") or false
+ desc = desc or get_font_param(fid, "descender") or false
+ t[fid] = { asc, desc }
+ return { asc, desc }
+ end
+ return { }
+ end } ),
+}
+
+local function char_in_font(fontdata, char)
+ if type(fontdata) == "number" then
+ fontdata = get_font_data(fontdata)
+ end
+ if fontdata.characters then
+ return fontdata.characters[char]
+ end
+end
+
+local function my_node_props (n)
+ local t = getproperty(n)
+ if not t then
+ t = {}
+ setproperty(n, t)
+ end
+ t.luatexko = t.luatexko or {}
+ return t.luatexko
+end
+
+local active_processes = {}
+
local function is_hanja (c)
return c >= 0x3400 and c <= 0xA4C6
or c >= 0xF900 and c <= 0xFAD9
@@ -195,82 +440,6 @@ local function is_hangul_jamo (c)
or is_jongsong(c)
end
-local stretch_f = 5/100 -- should be consistent for ruby
-
-local function get_font_data (fontid)
- return fontgetfont(fontid) or fontfonts[fontid] or {}
-end
-
-local function get_font_param (f, key)
- local t
- if type(f) == "number" then
- t = getparameters(f)
- if t and t[key] then
- return t[key]
- end
- f = get_font_data(f)
- end
- if type(f) == "table" then
- t = f.parameters
- return t and t[key]
- end
-end
-
-local function get_en_size (f)
- local quad = get_font_param(f, "quad")
- return quad and quad/2 or 327680
-end
-
-local function char_in_font(fontdata, char)
- if type(fontdata) == "number" then
- fontdata = get_font_data(fontdata)
- end
- if fontdata.characters then
- return fontdata.characters[char]
- end
-end
-
-local function option_in_font (fontdata, optionname)
- if type(fontdata) == "number" then
- fontdata = get_font_data(fontdata)
- end
- if fontdata.specification then
- return fontdata.specification.features.normal[optionname]
- end
-end
-
-local function my_node_props (n)
- local t = getproperty(n)
- if not t then
- t = {}
- setproperty(n, t)
- end
- t.luatexko = t.luatexko or {}
- return t.luatexko
-end
-
-local function is_harf (f)
- if type(f) == "number" then
- f = get_font_data(f)
- end
- return f.hb
-end
-
-local function is_not_harf (f)
- if option_in_font(f, "mode") == "harf" then -- mode=harf with non-luahbtex
- return false
- end
- return not is_harf(f)
-end
-
-local function harf_reordered_tonemark (curr)
- if is_harf(curr.font) then
- local props = getproperty(curr) or {}
- local actualtext = props.luaotfload_startactualtext or ""
- return actualtext:find"302[EF]$"
- end
-end
-
-- font fallback
local force_hangul = {
@@ -306,19 +475,6 @@ local function update_force_hangul (value)
end
luatexko.updateforcehangul = update_force_hangul
-local active_processes = {}
-
-local char_font_options = {
- ascender = {},
- charraise = {},
- hangulspaceskip = {},
- intercharacter = {},
- intercharstretch = {},
- interhangul = {},
- interlatincjk = {},
- tonemarkwidth = {},
-}
-
local function hangul_space_skip (curr, newfont)
if curr.lang ~= nohyphen and curr.font ~= newfont then
local n = getnext(curr)
@@ -332,27 +488,7 @@ local function hangul_space_skip (curr, newfont)
and oldsto == 0
and oldsho == 0 then -- not user's spaceskip
- local newwd = char_font_options.hangulspaceskip[newfont]
- if newwd == nil then
- if is_harf(newfont) then
- newwd = getparameters(newfont) or false
- if newwd then
- newwd = { newwd.space, newwd.space_stretch, newwd.space_shrink }
- end
- else
- local newsp = nodecopy(curr)
- newsp.char, newsp.font = 32, newfont
- newsp = nodes.simple_font_handler(newsp)
- newwd = newsp and newsp.width or false
- if newwd then
- newwd = { texsp(newwd), texsp(newwd/2), texsp(newwd/3) }
- end
- if newsp then
- nodefree(newsp)
- end
- end
- char_font_options.hangulspaceskip[newfont] = newwd
- end
+ local newwd = font_options.hangulspaceskip[newfont]
if newwd then
setglue(n, newwd[1], newwd[2], newwd[3])
end
@@ -393,12 +529,13 @@ local function process_fonts (head)
local format = fontdata.format
local encode = fontdata.encodingbytes
local widefont = encode == 2 or format == "opentype" or format == "truetype"
- if hf and widefont and force_hangul[c] and curr.lang ~= nohyphen then
+
+ if hf and widefont and force_hangul[c] and curr.lang ~= nohyphen and not font_options.monospaced[curr.font] then
curr.font = hf
- elseif hf and luatexko.hangulbyhangulfont and is_hangul_jamo(c) then
+ elseif hf and has_attribute(curr, hangulbyhangulattr) and is_hangul_jamo(c) then
hangul_space_skip(curr, hf)
curr.font = hf
- elseif hjf and luatexko.hanjabyhanjafont and is_hanja(c) then
+ elseif hjf and has_attribute(curr, hanjabyhanjaattr) and is_hanja(c) then
hangul_space_skip(curr, hjf)
curr.font = hjf
elseif not char_in_font(fontdata, c) then
@@ -512,7 +649,7 @@ local breakable_after = setmetatable({
[0xFE58] = true, [0xFE5A] = true, [0xFE5C] = true, [0xFE5E] = true,
[0xFF1E] = true, [0xFF5E] = true, [0xFF70] = true,
},{ __index = function (_,c)
- return is_hangul_jamo(c) and not is_chosong(c)
+ return is_hangul_jamo(c) -- chosong also is breakable_after
or is_noncjk_char(c)
or is_hanja(c)
or is_cjk_combining(c)
@@ -566,19 +703,9 @@ local function is_blocking_node (curr)
return allowbreak_false_nodes[id] or id == kernid and subtype == userkern
end
-local function ruby_char_font (rb)
- local n = has_glyph(rb.list)
- if n then
- local c, f = my_node_props(n).unicode or n.char, n.font
- if is_chosong(c) or hangul_tonemark[c] then
- c = 0xAC00
- end
- return c, f
- end
-end
-
-local function hbox_ini_char_font (box)
- local curr = box.list
+local function hbox_char_font (box, init, glyfonly)
+ local mynext = init and getnext or getprev
+ local curr = init and box.list or nodeslide(box.list)
while curr do
local id = curr.id
if id == glyphid then
@@ -587,29 +714,11 @@ local function hbox_ini_char_font (box)
return c, curr.font
end
elseif id == hlistid and curr.list then
- return hbox_ini_char_font(curr)
- elseif is_blocking_node(curr) then
- return
- end
- curr = getnext(curr)
- end
-end
-
-local function hbox_fin_char_font (box)
- local curr = nodeslide(box.list)
- while curr do
- local id = curr.id
- if id == glyphid then
- local c = my_node_props(curr).unicode or curr.char
- if c and not is_cjk_combining(c) then
- return c, curr.font
- end
- elseif id == hlistid and curr.list then
- return hbox_fin_char_font(curr)
- elseif is_blocking_node(curr) then
+ return hbox_char_font(curr, init, glyfonly)
+ elseif not glyfonly and is_blocking_node(curr) then
return
end
- curr = getprev(curr)
+ curr = mynext(curr)
end
end
@@ -633,34 +742,6 @@ local function goto_end_actualtext (curr)
return curr
end
-local function fontdata_opt_dim (fd, optname)
- local dim = option_in_font(fd, optname)
- if dim then
- local m, u = dim:match"^(.+)(e[mx])%s*$"
- if m and u then
- if u == "em" then
- dim = m * fd.parameters.quad
- else
- dim = m * fd.parameters.x_height
- end
- else
- dim = texsp(dim)
- end
- return dim
- end
-end
-
-local function get_font_opt_dimen (fontid, optionname)
- local t = char_font_options[optionname]
- local dim = t and t[fontid]
- if dim == nil then
- local fd = get_font_data(fontid)
- dim = fontdata_opt_dim(fd, optionname)
- t[fontid] = dim or false -- cache
- end
- return dim
-end
-
local function insert_glue_before (head, curr, par, br, brb, classic, ict, dim, fid)
local pn = nodenew(penaltyid)
if not br then
@@ -675,12 +756,12 @@ local function insert_glue_before (head, curr, par, br, brb, classic, ict, dim,
dim = dim or 0
local gl = nodenew(glueid)
- local en = get_en_size(fid)
+ local en = font_options.en_size[fid]
if ict then
en = classic and en or en/4
setglue(gl, en * ict[1] + dim, nil, en * ict[2])
else
- local str = get_font_opt_dimen(fid, "intercharstretch") or stretch_f*en
+ local str = font_options.intercharstretch[fid] or stretch_f*en
setglue(gl, dim, str, str*0.6)
end
@@ -694,7 +775,7 @@ local function maybe_linebreak (head, curr, pc, pcl, cc, old, fid, par)
local ict = intercharclass[pcl][ccl]
local brb = breakable_before[cc]
local br = brb and breakable_after[pc]
- local dim = get_font_opt_dimen(fid, "intercharacter")
+ local dim = font_options.intercharacter[fid]
if ict or br or dim and (pcl >= 1 or ccl >= 1) then
head = insert_glue_before(head, curr, par, br, brb, old, ict, dim, fid)
end
@@ -715,21 +796,12 @@ local function process_linebreak (head, par)
elseif id == hlistid and curr.list then
local old = has_attribute(curr, classicattr)
- if has_attribute(curr, rubyattr) then
- local c, f = ruby_char_font(curr) -- rubybase
- if c and f then
- head, pc, pcl = maybe_linebreak(head, curr, pc, pcl, c, old, f, par)
- else
- pc, pcl = false, 0
- end
- else
- local c, f = hbox_ini_char_font(curr)
- if c and f then
- head = maybe_linebreak(head, curr, pc, pcl, c, old, f, par)
- end
- pc = hbox_fin_char_font(curr)
- pcl = pc and get_char_class(pc, old) or 0
+ local c, f = hbox_char_font(curr, true)
+ if c and f then
+ head = maybe_linebreak(head, curr, pc, pcl, c, old, f, par)
end
+ pc = hbox_char_font(curr)
+ pcl = pc and get_char_class(pc, old) or 0
elseif id == whatsitid and curr.mode == directmode then
local glyf, c, fin = get_actualtext(curr)
@@ -772,7 +844,7 @@ local function process_glyph_width (head)
gpos = gpos and gpos.id == kernid and gpos.subtype == fontkern
if not gpos then
- local wd = get_en_size(curr.font) - curr.width
+ local wd = font_options.en_size[curr.font] - curr.width
if wd ~= 0 then
local k = nodenew(kernid) -- fontkern (subtype 0) is default
k.kern = class == 3 and wd/2 or wd
@@ -813,7 +885,7 @@ local function do_interhangul_option (head, curr, pc, c, fontid, par)
local cc = (is_hangul(c) or is_compat_jamo(c) or is_chosong(c)) and 1 or 0
if cc*pc == 1 and curr.lang ~= nohyphen then
- local dim = get_font_opt_dimen(fontid, "interhangul")
+ local dim = font_options.interhangul[fontid]
if dim then
head = insert_glue_before(head, curr, par, true, true, false, false, dim, fontid)
end
@@ -839,21 +911,12 @@ local function process_interhangul (head, par)
end
elseif id == hlistid and curr.list then
- if has_attribute(curr, rubyattr) then
- local c, f = ruby_char_font(curr)
- if c and f then
- head, pc = do_interhangul_option(head, curr, pc, c, f, par)
- else
- pc = 0
- end
- else
- local c, f = hbox_ini_char_font(curr)
- if c and f then
- head = do_interhangul_option(head, curr, pc, c, f, par)
- end
- c = hbox_fin_char_font(curr)
- pc = c and is_hangul_jamo(c) and 1 or 0
+ local c, f = hbox_char_font(curr, true)
+ if c and f then
+ head = do_interhangul_option(head, curr, pc, c, f, par)
end
+ c = hbox_char_font(curr)
+ pc = c and is_hangul_jamo(c) and 1 or 0
elseif id == whatsitid and curr.mode == directmode then
local glyf, c = get_actualtext(curr)
@@ -881,11 +944,11 @@ local function do_interlatincjk_option (head, curr, pc, pf, pcl, c, cf, par)
local brb = cc == 2 or breakable_before[c] -- numletter != br_before
if brb then
local f = cc == 1 and cf or pf
- local dim = get_font_opt_dimen(f, "interlatincjk")
+ local dim = font_options.interlatincjk[f]
if dim then
local ict = old and intercharclass[pcl][ccl] -- under classic env. only
if ict then
- dim = get_font_opt_dimen(f, "intercharacter") or 0
+ dim = font_options.intercharacter[f] or 0
end
head = insert_glue_before(head, curr, par, true, brb, old, ict, dim, f)
end
@@ -907,27 +970,18 @@ local function process_interlatincjk (head, par)
end
elseif id == hlistid and curr.list then
- if has_attribute(curr, rubyattr) then
- local c, f = ruby_char_font(curr)
- if c and f then
- head, pc, pf, pcl = do_interlatincjk_option(head, curr, pc, pf, pcl, c, f, par)
- else
- pc, pf, pcl = 0, 0, 0
- end
+ local c, f = hbox_char_font(curr, true)
+ if c and f then
+ head = do_interlatincjk_option(head, curr, pc, pf, pcl, c, f, par)
+ end
+ c, f = hbox_char_font(curr)
+ if c and breakable_after[c] then
+ pc = is_cjk_char(c) and 1 or is_noncjk_char(c) and 2 or 0
else
- local c, f = hbox_ini_char_font(curr)
- if c and f then
- head = do_interlatincjk_option(head, curr, pc, pf, pcl, c, f, par)
- end
- c, f = hbox_fin_char_font(curr)
- if c and breakable_after[c] then
- pc = is_cjk_char(c) and 1 or is_noncjk_char(c) and 2 or 0
- else
- pc = 0
- end
- pcl = c and get_char_class(c, has_attribute(curr, classicattr)) or 0
- pf = f or 0
+ pc = 0
end
+ pcl = c and get_char_class(c, has_attribute(curr, classicattr)) or 0
+ pf = f or 0
elseif id == whatsitid and curr.mode == directmode then
local glyf, c = get_actualtext(curr)
@@ -935,6 +989,7 @@ local function process_interlatincjk (head, par)
head, pc, pf, pcl = do_interlatincjk_option(head, curr, pc, pf, pcl, c, glyf.font, par)
curr = goto_end_actualtext(curr)
end
+
elseif id == mathid then
if pc == 1 then
head = do_interlatincjk_option(head, curr, pc, pf, pcl, 0x30, pf, par)
@@ -980,13 +1035,7 @@ local function process_remove_spaces (head)
end
vchar, vfont = my_node_props(v).unicode or v.char, v.font
elseif id == hlistid and v.list then
- if has_attribute(v, rubyattr) then
- vchar, vfont = ruby_char_font(v)
- elseif k == "p" then
- vchar, vfont = hbox_fin_char_font(v)
- else
- vchar, vfont = hbox_ini_char_font(v)
- end
+ vchar, vfont = hbox_char_font(v, k == "n")
end
if vchar and vfont and option_in_font(vfont, opt_name) then
ok = is_cjk_char(vchar)
@@ -1186,7 +1235,7 @@ local function process_dotemph (head, tofree)
end
local currwd = curr.width
- if currwd >= get_en_size(curr.font) then
+ if currwd >= font_options.en_size[curr.font] then
local box = nodecopy(dotemphbox[dotattr])
local shift = (currwd - box.width)/2
if shift ~= 0 then
@@ -1222,6 +1271,28 @@ end
-- uline
+local function get_strike_out_down (box)
+ local c, f = hbox_char_font(box, true, true) -- ignore blocking nodes
+ if c and f then
+ local down
+ local ex = get_font_param(f, "x_height") or texsp"1ex"
+ if is_cjk_char(c) then
+ local ascender, descender = tableunpack(font_options.asc_desc[f])
+ if ascender and descender then
+ down = descender - (ascender + descender)/2
+ else
+ down = -0.667*ex
+ end
+ else
+ down = -0.5*ex
+ end
+ local raise = font_options.charraise[f] or 0
+ return down - raise
+ end
+ return -texsp"0.5ex"
+end
+luatexko.get_strike_out_down = get_strike_out_down
+
local uline_f, uline_id = new_user_whatsit("uline","luatexko")
local no_uline_id = new_user_whatsit_id("no_uline","luatexko")
@@ -1325,10 +1396,10 @@ local rubybox = {}
luatexko.rubybox = rubybox
local function getrubystretchfactor (box)
- local _, fid = ruby_char_font(box)
- local str = get_font_opt_dimen(fid, "intercharstretch")
+ local _, fid = hbox_char_font(box, true, true)
+ local str = font_options.intercharstretch[fid]
if str then
- local em = get_en_size(fid) * 2
+ local em = font_options.en_size[fid] * 2
set_macro("luatexkostretchfactor", stringformat("%.4f", str/em/2))
end
end
@@ -1365,42 +1436,6 @@ local function process_ruby_pre_linebreak (head)
return head
end
-local os2tag = luaotfload.harfbuzz and luaotfload.harfbuzz.Tag.new"OS/2"
-
--- luaharfbuzz's Font:get_h_extents() gets ascender value from hhea table;
--- Node mode's parameters.ascender is gotten from OS/2 table.
--- TypoAscender in OS/2 table seems to be more suitable for our purpose.
-local function get_font_ascender (f)
- local ascender = char_font_options.ascender
- local ascend = ascender[f]
- if ascend == nil then
- local hb = is_harf(f)
- if hb and os2tag then
- local hbface = hb.shared.face
- local tags = hbface:get_table_tags()
- local hasos2 = false
- for _,v in ipairs(tags) do
- if v == os2tag then
- hasos2 = true
- break
- end
- end
- if hasos2 then
- local os2 = hbface:get_table(os2tag)
- local length = os2:get_length()
- if length > 69 then -- sTypoAscender (int16)
- local data = os2:get_data()
- local typoascender = stringunpack(">h", data, 69)
- ascend = typoascender * hb.scale
- end
- end
- end
- ascend = ascend or get_font_param(f, "ascender") or false
- ascender[f] = ascend
- end
- return ascend
-end
-
local function process_ruby_post_linebreak (head)
local curr = head
while curr do
@@ -1422,8 +1457,8 @@ local function process_ruby_post_linebreak (head)
-- consider charraise
local shift = shift_put_top(curr, ruby)
- local _, f = ruby_char_font(curr)
- local ascender = get_font_ascender(f) or curr.height
+ local _, f = hbox_char_font(curr, true, true)
+ local ascender = tableunpack(font_options.asc_desc[f]) or curr.height
ruby.shift = shift - ascender - ruby.depth - ruby_t[2] -- rubysep
head = insert_before(head, curr, ruby)
end
@@ -1476,22 +1511,6 @@ local function pdfliteral_direct_actual (syllable)
return what
end
-local function get_tonemark_width (curr, uni)
- local fontid = curr.font
- local hwidth = char_font_options.tonemarkwidth[fontid]
- if not hwidth then
- -- check horizontal width; vertical width is mostly non-zero
- local fontdata = get_font_data(fontid)
- local shared = fontdata.shared or {}
- local rawdata = shared.rawdata or {}
- local descriptions = rawdata.descriptions or {}
- local description = descriptions[uni] or {}
- hwidth = description.width or 0
- char_font_options.tonemarkwidth[fontid] = hwidth
- end
- return hwidth
-end
-
local function process_reorder_tonemarks (head)
local curr, init = head
while curr do
@@ -1517,7 +1536,7 @@ local function process_reorder_tonemarks (head)
n = getnext(n)
end
- if #syllable > 1 and get_tonemark_width(curr, uni) ~= 0 then
+ if #syllable > 1 and font_options.tonemarkwidth[curr.font] ~= 0 then
local TM = curr
local actual = pdfliteral_direct_actual(syllable)
@@ -1533,7 +1552,7 @@ local function process_reorder_tonemarks (head)
elseif char_in_font(fontdata, 0x25CC) then -- isolated tone mark
local dotcircle = nodecopy(curr)
dotcircle.char = 0x25CC
- if get_tonemark_width(curr, uni) ~= 0 then
+ if font_options.tonemarkwidth[curr.font] ~= 0 then
local actual = pdfliteral_direct_actual{ init = curr, uni }
local endactual = pdfliteral_direct_actual()
head = insert_before(head, curr, actual)
@@ -1714,7 +1733,7 @@ local function process_vertical_font (fontdata)
local quad = parameters.quad or 655360
local ascender = parameters.ascender or quad*0.8
- local goffset = fontdata_opt_dim(fontdata, "charraise") or
+ local goffset = font_opt_dim(fontdata, "charraise") or
(parameters.x_height or quad/2)/2
-- declare shift amount of horizontal box inside vertical env.
fontdata.horizboxmoveleftamount = quad/2-goffset
@@ -1806,7 +1825,7 @@ local function process_charraise (head)
while curr do
if curr.id == glyphid then
local f = curr.font
- local raise = get_font_opt_dimen(f, "charraise")
+ local raise = font_options.charraise[f]
if raise and not option_in_font(f, "vertical") then
local props = my_node_props(curr)
if not props.charraised then
@@ -1958,16 +1977,14 @@ local font_opt_procs = {
local font_opt_procs_single = {
expansion = function()
- if not active_processes.expansion then
+ if tex.adjustspacing == 0 then
texset("global", "adjustspacing", 2)
- active_processes.expansion = true
end
end,
protrusion = function(fontdata)
- if not active_processes.protrusion then
+ if tex.protrudechars == 0 then
texset("global", "protrudechars", 2)
- active_processes.protrusion = true
end
if option_in_font(fontdata, "compresspunctuations") then
local fullname = fontdata.fullname