summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2019-05-26 21:24:59 +0000
committerKarl Berry <karl@freefriends.org>2019-05-26 21:24:59 +0000
commit2014750e7bcf55bab5c430e3d98d8a11430eb979 (patch)
treebef9a778b3b51cea29fefadfbbf930a261791875 /Master/texmf-dist/tex/luatex/luatexko/luatexko.lua
parent5a993557f8f849481525f4d473d6c9f1da51981d (diff)
luatexko (26may19)
git-svn-id: svn://tug.org/texlive/trunk@51228 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/luatexko/luatexko.lua')
-rw-r--r--Master/texmf-dist/tex/luatex/luatexko/luatexko.lua268
1 files changed, 152 insertions, 116 deletions
diff --git a/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua b/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua
index 01a274bfeda..87478153ada 100644
--- a/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua
+++ b/Master/texmf-dist/tex/luatex/luatexko/luatexko.lua
@@ -13,8 +13,8 @@
luatexbase.provides_module {
name = 'luatexko',
- date = '2019/05/01',
- version = '2.0',
+ date = '2019/05/25',
+ version = '2.1',
description = 'typesetting Korean with LuaTeX',
author = 'Dohyun Kim, Soojin Nam',
license = 'LPPL v1.3+',
@@ -61,6 +61,7 @@ local stringformat = string.format
local tableconcat = table.concat
local tableinsert = table.insert
+local tableunpack = table.unpack
local add_to_callback = luatexbase.add_to_callback
local attributes = luatexbase.attributes
@@ -95,7 +96,6 @@ local italcorr = 3
local lua_number = 100
local lua_value = 108
local spaceskip = 13
-local xleaders = 102
local nohyphen = registernumber"l@nohyphenation" or -1 -- verbatim
local hangulfontattr = attributes.luatexkohangulfontattr
@@ -110,69 +110,69 @@ local vert_classic = 1
local SC_classic = 2
local function is_hanja (c)
- return (c >= 0x3400 and c <= 0xA4C6)
- or (c >= 0xF900 and c <= 0xFAD9)
- or (c >= 0x20000 and c <= 0x2FFFD)
- or (c >= 0x2E81 and c <= 0x2FD5)
+ return c >= 0x3400 and c <= 0xA4C6
+ or c >= 0xF900 and c <= 0xFAD9
+ or c >= 0x20000 and c <= 0x2FFFD
+ or c >= 0x2E81 and c <= 0x2FD5
end
local function is_hangul (c)
- return (c >= 0xAC00 and c <= 0xD7A3)
+ return c >= 0xAC00 and c <= 0xD7A3
end
local function is_chosong (c)
- return (c >= 0x1100 and c <= 0x115F)
- or (c >= 0xA960 and c <= 0xA97C)
+ return c >= 0x1100 and c <= 0x115F
+ or c >= 0xA960 and c <= 0xA97C
end
local function is_jungsong (c)
- return (c >= 0x1160 and c <= 0x11A7)
- or (c >= 0xD7B0 and c <= 0xD7C6)
+ return c >= 0x1160 and c <= 0x11A7
+ or c >= 0xD7B0 and c <= 0xD7C6
end
local function is_jongsong (c)
- return (c >= 0x11A8 and c <= 0x11FF)
- or (c >= 0xD7CB and c <= 0xD7FB)
+ return c >= 0x11A8 and c <= 0x11FF
+ or c >= 0xD7CB and c <= 0xD7FB
end
local hangul_tonemark = {
[0x302E] = true, [0x302F] = true,
}
-local function is_unicode_vs (c)
- return (c >= 0xFE00 and c <= 0xFE0F)
- or (c >= 0xE0100 and c <= 0xE01EF)
+local function is_unicode_var_sel (c)
+ return c >= 0xFE00 and c <= 0xFE0F
+ or c >= 0xE0100 and c <= 0xE01EF
end
local function is_cjk_combining (c)
- return (c >= 0x302A and c <= 0x302F)
- or (c >= 0x3099 and c <= 0x309C)
- or (c >= 0xFF9E and c <= 0xFF9F)
- or is_unicode_vs(c)
+ return c >= 0x302A and c <= 0x302F
+ or c >= 0x3099 and c <= 0x309C
+ or c >= 0xFF9E and c <= 0xFF9F
+ or is_unicode_var_sel(c)
end
local function is_noncjkletter (c)
- return (c >= 0x30 and c <= 0x39)
- or (c >= 0x41 and c <= 0x5A)
- or (c >= 0x61 and c <= 0x7A)
- or (c >= 0xC0 and c <= 0xD6)
- or (c >= 0xD8 and c <= 0xF6)
- or (c >= 0xF8 and c <= 0x10FC)
- or (c >= 0x1200 and c <= 0x1FFE)
- or (c >= 0xA4D0 and c <= 0xA877)
- or (c >= 0xAB01 and c <= 0xABBF)
- or (c >= 0xFB00 and c <= 0xFDFD)
- or (c >= 0xFE70 and c <= 0xFEFC)
+ return c >= 0x30 and c <= 0x39
+ or c >= 0x41 and c <= 0x5A
+ or c >= 0x61 and c <= 0x7A
+ or c >= 0xC0 and c <= 0xD6
+ or c >= 0xD8 and c <= 0xF6
+ or c >= 0xF8 and c <= 0x10FC
+ or c >= 0x1200 and c <= 0x1FFE
+ or c >= 0xA4D0 and c <= 0xA877
+ or c >= 0xAB01 and c <= 0xABBF
+ or c >= 0xFB00 and c <= 0xFDFD
+ or c >= 0xFE70 and c <= 0xFEFC
end
local function is_kana (c)
- return (c >= 0x3041 and c <= 0x3096)
- or (c >= 0x30A1 and c <= 0x30FA)
- or (c >= 0x31F0 and c <= 0x31FF)
- or (c >= 0xFF66 and c <= 0xFF6F)
- or (c >= 0xFF71 and c <= 0xFF9D)
- or c == 0x309F or c == 0x30FF
- or (c >= 0x1B000 and c <= 0x1B16F)
+ return c >= 0x3041 and c <= 0x3096
+ or c >= 0x30A1 and c <= 0x30FA
+ or c >= 0x31F0 and c <= 0x31FF
+ or c >= 0xFF66 and c <= 0xFF6F
+ or c >= 0xFF71 and c <= 0xFF9D
+ or c == 0x309F or c == 0x30FF
+ or c >= 0x1B000 and c <= 0x1B16F
end
local function is_hangul_jamo (c)
@@ -180,7 +180,7 @@ local function is_hangul_jamo (c)
or is_chosong(c)
or is_jungsong(c)
or is_jongsong(c)
- or (c >= 0x3131 and c <= 0x318E)
+ or c >= 0x3131 and c <= 0x318E
end
local stretch_f, shrink_f = 5/100, 3/100 -- should be consistent for ruby
@@ -189,14 +189,24 @@ local function get_font_data (fontid)
return fontgetfont(fontid) or fontfonts[fontid] or {}
end
-local function get_en_size (f)
- local pm
+local function get_font_param (f, key)
+ local t
if type(f) == "number" then
- pm = getparameters(f)
- elseif type(f) == "table" then
- pm = f.parameters
+ 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
- return pm and pm.quad and pm.quad/2 or 327680
+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)
@@ -264,7 +274,7 @@ luatexko.updateforcehangul = update_force_hangul
local active_processes = {}
-local char_font_options ={
+local char_font_options = {
interhangul = {},
interlatincjk = {},
intercharacter = {},
@@ -278,7 +288,8 @@ local function hangul_space_skip (curr, newfont)
if n and n.id == glueid and n.subtype == spaceskip then
local params = getparameters(curr.font)
local oldwd, oldst, oldsh, oldsto, oldsho = getglue(n)
- if oldwd == params.space
+ if params
+ and oldwd == params.space
and oldst == params.space_stretch
and oldsh == params.space_shrink
and oldsto == 0
@@ -316,13 +327,12 @@ local function process_fonts (head)
local c = curr.char
- if is_unicode_vs(c) then
+ if is_unicode_var_sel(c) then
local p = getprev(curr)
if p.id == glyphid and curr.font ~= p.font then
hangul_space_skip(curr, p.font)
curr.font = p.font
end
-
else
local hf = has_attribute(curr, hangulfontattr) or false
local hjf = has_attribute(curr, hanjafontattr) or false
@@ -358,6 +368,10 @@ local function process_fonts (head)
props.unicode = c
end
+ elseif id == discid then
+ curr.pre = process_fonts(curr.pre)
+ curr.post = process_fonts(curr.post)
+ curr.replace = process_fonts(curr.replace)
elseif id == mathid then
curr = end_of_math(curr)
elseif id == whatsitid
@@ -450,7 +464,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) and not is_chosong(c)
or is_noncjkletter(c)
or is_hanja(c)
or is_cjk_combining(c)
@@ -480,7 +494,7 @@ local breakable_before = setmetatable({
[0xFF6F] = 1000, [0x1B150] = 1000, [0x1B151] = 1000, [0x1B152] = 1000,
[0x1B164] = 1000, [0x1B165] = 1000, [0x1B166] = 1000, [0x1B167] = 1000,
},{ __index = function(_,c)
- return (is_hangul_jamo(c) and not is_jungsong(c) and not is_jongsong(c))
+ return is_hangul_jamo(c) and not is_jungsong(c) and not is_jongsong(c)
or is_hanja(c)
or is_kana(c)
or charclass[c] == 1
@@ -499,7 +513,7 @@ local allowbreak_false_nodes = {
local function is_blocking_node (curr)
local id, subtype = curr.id, curr.subtype
- return allowbreak_false_nodes[id] or (id == kernid and subtype == userkern)
+ return allowbreak_false_nodes[id] or id == kernid and subtype == userkern
end
local function ruby_char_font (rb)
@@ -551,17 +565,13 @@ local function fontdata_opt_dim (fd, optname)
end
end
-local function get_font_opt_dimen (fontid, option_name)
- local fop_t = char_font_options[option_name]
- local dim = fop_t and fop_t[fontid]
+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, option_name)
- if dim then
- fop_t[fontid] = dim -- cache
- else
- fop_t[fontid] = false
- end
+ dim = fontdata_opt_dim(fd, optionname)
+ t[fontid] = dim or false -- cache
end
return dim
end
@@ -592,15 +602,15 @@ local function insert_glue_before (head, curr, par, br, brb, classic, ict, dim)
return insert_before(head, curr, gl)
end
-local function maybe_linebreak (head, curr, pc, pcl, cc, gomun, fid, par)
- local ccl = get_char_class(cc, gomun)
+local function maybe_linebreak (head, curr, pc, pcl, cc, old, fid, par)
+ local ccl = get_char_class(cc, old)
if pc and cc and curr.lang ~= nohyphen then
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")
if ict or br or dim and (pcl >= 1 or ccl >= 1) then
- head = insert_glue_before(head, curr, par, br, brb, gomun, ict, dim)
+ head = insert_glue_before(head, curr, par, br, brb, old, ict, dim)
end
end
return head, cc, ccl
@@ -612,20 +622,19 @@ local function process_linebreak (head, par)
local id = curr.id
if id == glyphid then
local cc = my_node_props(curr).unicode or curr.char
- local gomun = has_attribute(curr, classicattr)
-
- head, pc, pcl = maybe_linebreak(head, curr, pc, pcl, cc, gomun, curr.font, par)
+ local old = has_attribute(curr, classicattr)
+ head, pc, pcl = maybe_linebreak(head, curr, pc, pcl, cc, old, curr.font, par)
elseif id == hlistid and has_attribute(curr, rubyattr) then
local cc, fi = ruby_char_font(curr) -- rubybase
- local gomun = has_attribute(curr, classicattr)
- head, pc, pcl = maybe_linebreak(head, curr, pc, pcl, cc, gomun, fi, par)
+ local old = has_attribute(curr, classicattr)
+ head, pc, pcl = maybe_linebreak(head, curr, pc, pcl, cc, old, fi, par)
elseif id == whatsitid and curr.mode == directmode then
local glyf, cc, fin = get_actualtext(curr)
if cc and fin and glyf then
- local gomun = has_attribute(glyf, classicattr)
- head = maybe_linebreak(head, curr, pc, pcl, cc, gomun, glyf.font, par)
+ local old = has_attribute(glyf, classicattr)
+ head = maybe_linebreak(head, curr, pc, pcl, cc, old, glyf.font, par)
pc, pcl, curr = fin, 0, goto_end_actualtext(curr)
end
@@ -652,17 +661,12 @@ local function process_glyph_width (head)
and option_in_font(curr.font, "compresspunctuations") then
local cc = my_node_props(curr).unicode or curr.char
- local gomun = has_attribute(curr, classicattr)
- local class = get_char_class(cc, gomun)
- if (gomun or cc < 0x2000 or cc > 0x202F) -- exclude general puncts
- and class >= 1 and class <= 4 then
-
- local gpos
- if class ~= 1 then
- gpos = getnext(curr)
- else
- gpos = getprev(curr)
- end
+ local old = has_attribute(curr, classicattr)
+ local class = get_char_class(cc, old)
+ if class >= 1 and class <= 4 and
+ (old or cc < 0x2000 or cc > 0x202F) then -- exclude general puncts
+
+ local gpos = class == 1 and getprev(curr) or getnext(curr)
gpos = gpos and gpos.id == kernid and gpos.subtype == fontkern
if not gpos then
@@ -699,8 +703,8 @@ local function is_cjk (c)
or is_cjk_combining(c)
or is_kana(c)
or charclass[c] >= 1
- or (rawget(breakable_before, c) and c >= 0x2000)
- or (rawget(breakable_after, c) and c >= 0x2000)
+ or rawget(breakable_before, c) and c >= 0x2000
+ or rawget(breakable_after, c) and c >= 0x2000
end
local function do_interhangul_option (head, curr, pc, c, fontid, par)
@@ -752,7 +756,7 @@ local function process_interhangul (head, par)
end
local function do_interlatincjk_option (head, curr, pc, pf, c, cf, par)
- local cc = (is_cjk(c) and 1) or (is_noncjkletter(c) and 2) or 0
+ local cc = is_cjk(c) and 1 or is_noncjkletter(c) and 2 or 0
local brb = cc == 2 or breakable_before[c] -- numletter != br_before
if brb and cc*pc == 2 and curr.lang ~= nohyphen then
@@ -899,19 +903,19 @@ local josa_code = setmetatable({
return c ~= 0x1160 and 2
elseif is_jongsong(c) then
return c == 0x11AF and 1 or 3
- elseif (is_noncjkletter(c) and c <= 0x7A )
- or (c >= 0x2160 and c <= 0x217F) -- roman
- or (c >= 0x2460 and c <= 0x24E9) -- ①
- or (c >= 0x314F and c <= 0x3163) or (c >= 0x3187 and c <= 0x318E) -- ㅏ
- or (c >= 0x320E and c <= 0x321E) -- ㈎
- or (c >= 0x326E and c <= 0x327F) -- ㉮
- or (c >= 0xFF10 and c <= 0xFF19) -- 0
- or (c >= 0xFF21 and c <= 0xFF3A) -- A
- or (c >= 0xFF41 and c <= 0xFF5A) -- a
+ elseif is_noncjkletter(c) and c <= 0x7A
+ or c >= 0x2160 and c <= 0x217F -- roman
+ or c >= 0x2460 and c <= 0x24E9 -- ①
+ or c >= 0x314F and c <= 0x3163 or c >= 0x3187 and c <= 0x318E -- ㅏ
+ or c >= 0x320E and c <= 0x321E -- ㈎
+ or c >= 0x326E and c <= 0x327F -- ㉮
+ or c >= 0xFF10 and c <= 0xFF19 -- 0
+ or c >= 0xFF21 and c <= 0xFF3A -- A
+ or c >= 0xFF41 and c <= 0xFF5A -- a
then return 2
- elseif (c >= 0x3131 and c <= 0x314E) or (c >= 0x3165 and c <= 0x3186) -- ㄱ
- or (c >= 0x3200 and c <= 0x320D) -- ㈀
- or (c >= 0x3260 and c <= 0x326D) -- ㉠
+ elseif c >= 0x3131 and c <= 0x314E or c >= 0x3165 and c <= 0x3186 -- ㄱ
+ or c >= 0x3200 and c <= 0x320D -- ㈀
+ or c >= 0x3260 and c <= 0x326D -- ㉠
then return 3
end
end })
@@ -1031,11 +1035,11 @@ end
local uline_f, uline_id = new_user_whatsit("uline","luatexko")
local no_uline_id = new_user_whatsit_id("no_uline","luatexko")
-local function ulboundary (i, n)
+local function ulboundary (i, n, subtype)
local what = uline_f()
if n then
what.type = lua_value -- table
- what.value = { i, nodecopy(n) }
+ what.value = { i, nodecopy(n), subtype }
else
what.type = lua_number
what.value = i
@@ -1061,17 +1065,19 @@ function skip_white_nodes (n, ltr)
end
local function draw_uline (head, curr, parent, t, final)
- local start, list = t.start or head, t.list
+ local start, list, subtype = t.start or head, t.list, t.subtype
start = skip_white_nodes(start, true)
- nodeslide(start) -- to get correct getprev.
+ if final then
+ nodeslide(start) -- to get correct getprev.
+ end
curr = skip_white_nodes(curr)
- if getnext(curr) then curr = getnext(curr) end
+ curr = getnext(curr) or curr
local len = parent and rangedimensions(parent, start, curr)
or dimensions(start, curr) -- it works?!
if len and len ~= 0 then
local g = nodenew(glueid)
setglue(g, len)
- g.subtype = xleaders
+ g.subtype = subtype
g.leader = final and list or nodecopy(list)
local k = nodenew(kernid)
k.kern = -len
@@ -1081,8 +1087,8 @@ local function draw_uline (head, curr, parent, t, final)
return head
end
-local function process_uline (head, parent, ulitems, level)
- local curr, ulitems, level = head, ulitems or {}, level or 0
+local function process_uline (head, parent, items, level)
+ local curr, items, level = head, items or {}, level or 0
while curr do
local id = curr.id
if id == whatsitid
@@ -1091,31 +1097,36 @@ local function process_uline (head, parent, ulitems, level)
local value = curr.value
if curr.type == lua_value then
- local count, list = value[1], value[2]
- ulitems[count] = { start = curr, list = list, level = level }
- elseif ulitems[value] then
- head = draw_uline(head, curr, parent, ulitems[value], true)
- ulitems[value] = nil
+ local count, list, subtype = tableunpack(value)
+ items[count] = {
+ start = curr,
+ list = list,
+ subtype = subtype,
+ level = level,
+ }
+ elseif items[value] then
+ head = draw_uline(head, curr, parent, items[value], true)
+ items[value] = nil
end
curr.user_id = no_uline_id -- avoid multiple run
elseif id == hlistid then
local list = curr.list
if list then
- curr.list, ulitems = process_uline(list, curr, ulitems, level+1)
+ curr.list, items = process_uline(list, curr, items, level+1)
end
end
curr = getnext(curr)
end
curr = nodeslide(head)
- for i, t in pairs(ulitems) do
+ for i, t in pairs(items) do
if level == t.level then
head = draw_uline(head, curr, parent, t)
t.start = nil
end
end
- return head, ulitems
+ return head, items
end
-- ruby
@@ -1171,7 +1182,9 @@ local function process_ruby_post_linebreak (head)
ruby.list = insert_before(list, list, k)
end
ruby.width = 0
- ruby.shift = -(curr.height + ruby_t[2]) -- rubysep
+ local _, f = ruby_char_font(curr)
+ local ascender = get_font_param(f, "ascender") or curr.height
+ ruby.shift = -ascender - ruby.depth - ruby_t[2] -- rubysep
head = insert_before(head, curr, ruby)
end
ruby_t = nil
@@ -1740,9 +1753,32 @@ local function activate (name)
end
luatexko.activate = activate
--- default hangul font
+-- aux functions
local function current_has_hangul_chars (cnt)
texcount[cnt] = char_in_font(fontcurrent(), 0xAC00) and 1 or 0
end
luatexko.currenthashangulchars = current_has_hangul_chars
+
+local function get_gid_of_charslot (fd, slot)
+ if type(fd) == "number" then
+ fd = get_font_data(fd)
+ end
+ local character = fd.characters[slot]
+ return character and character.index
+end
+luatexko.get_gid_of_charslot = get_gid_of_charslot
+
+local function get_charslots_of_gid (fd, gid)
+ if type(fd) == "number" then
+ fd = get_font_data(fd)
+ end
+ local t = {}
+ for i, v in pairs(fd.characters) do
+ if v.index == gid then
+ table.insert(t, i)
+ end
+ end
+ return t
+end
+luatexko.get_charslots_of_gid = get_charslots_of_gid