summaryrefslogtreecommitdiff
path: root/macros/luatex/generic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-04-21 03:01:10 +0000
committerNorbert Preining <norbert@preining.info>2021-04-21 03:01:10 +0000
commit20788e2817af7ef0b25395c161b06e7a1446b8b1 (patch)
treef559ca4cfaa8f1fa63d1f8a44f16805204001acd /macros/luatex/generic
parentd65c208b161ffee9ce5343fdfdb17d00523cecae (diff)
CTAN sync 202104210301
Diffstat (limited to 'macros/luatex/generic')
-rw-r--r--macros/luatex/generic/luatexko/ChangeLog8
-rw-r--r--macros/luatex/generic/luatexko/README2
-rw-r--r--macros/luatex/generic/luatexko/luatexko-doc.pdfbin328095 -> 326736 bytes
-rw-r--r--macros/luatex/generic/luatexko/luatexko-doc.tex52
-rw-r--r--macros/luatex/generic/luatexko/luatexko-normalize.lua4
-rw-r--r--macros/luatex/generic/luatexko/luatexko-uhc2utf8.lua4
-rw-r--r--macros/luatex/generic/luatexko/luatexko.lua651
-rw-r--r--macros/luatex/generic/luatexko/luatexko.sty55
8 files changed, 456 insertions, 320 deletions
diff --git a/macros/luatex/generic/luatexko/ChangeLog b/macros/luatex/generic/luatexko/ChangeLog
index e0dc310e65..87afc21887 100644
--- a/macros/luatex/generic/luatexko/ChangeLog
+++ b/macros/luatex/generic/luatexko/ChangeLog
@@ -1,3 +1,11 @@
+2021-04-20 Dohyun Kim <nomos at ktug org>
+
+ Version 3.1
+
+ * luatexko.lua: insert 1/4 quad after vertical colons;
+ cleverer behavior when protrusion option is given;
+ process_fonts() is now called by hyphenate callback
+
2021-03-01 Dohyun Kim <nomos at ktug org>
Version 3.0
diff --git a/macros/luatex/generic/luatexko/README b/macros/luatex/generic/luatexko/README
index 204f8183bb..1b9329ffca 100644
--- a/macros/luatex/generic/luatexko/README
+++ b/macros/luatex/generic/luatexko/README
@@ -1,4 +1,4 @@
-LuaTeX-ko Package version 3.0 (2021/03/01)
+LuaTeX-ko Package version 3.1 (2021/04/20)
===========================================
This is a Lua(La)TeX macro package that supports typesetting Korean
diff --git a/macros/luatex/generic/luatexko/luatexko-doc.pdf b/macros/luatex/generic/luatexko/luatexko-doc.pdf
index a8b7ae9d40..dc87222ab2 100644
--- a/macros/luatex/generic/luatexko/luatexko-doc.pdf
+++ b/macros/luatex/generic/luatexko/luatexko-doc.pdf
Binary files differ
diff --git a/macros/luatex/generic/luatexko/luatexko-doc.tex b/macros/luatex/generic/luatexko/luatexko-doc.tex
index ea7d4fc938..d23b010e8f 100644
--- a/macros/luatex/generic/luatexko/luatexko-doc.tex
+++ b/macros/luatex/generic/luatexko/luatexko-doc.tex
@@ -14,22 +14,31 @@
\usepackage{luacolor}
\usepackage[hangul]{luatexko}
\directlua{
- local gidoffset = 0x120000
- local notoserifcjkkr_hb = {
- [171] = { 0.5, 0 }, % «
- [187] = { 0, 0.5 }, % »
- [62253+gidoffset] = { 0.5, 0 }, % (
- [62254+gidoffset] = { 0, 0.5 }, % )
- [62255+gidoffset] = { 0, 1 }, % ,
- [62257+gidoffset] = { 0, 1 }, % .
- [62259+gidoffset] = { 0, 0.5 }, % :
- [62260+gidoffset] = { 0, 0.5 }, % ;
- [62270+gidoffset] = { 1, 0 }, % ‘
- [62271+gidoffset] = { 0, 1 }, % ’
- [62273+gidoffset] = { 0.5, 0 }, % “
- [62274+gidoffset] = { 0, 0.5 }, % ”
+ fonts.protrusions.setups.notoserifcjk = {
+ [0x28] = { 0.5, 0 }, % (
+ [0x29] = { 0, 0.5 }, % )
+ [0x2C] = { 0, 1 }, % ,
+ [0x2E] = { 0, 1 }, % .
+ [0x3A] = { 0, 0.5 }, % :
+ [0x3B] = { 0, 0.5 }, % ;
+ [0xAB] = { 0.5, 0 }, % «
+ [0xBB] = { 0, 0.5 }, % »
+ [0x2018] = { 1, 0 }, % ‘
+ [0x2019] = { 0, 1 }, % ’
+ [0x201C] = { 0.5, 0 }, % “
+ [0x201D] = { 0, 0.5 }, % ”
+ }
+ fonts.protrusions.setups.notosanscjk = {
+ % compresspunctuations 가 이미 반각을 강제했으므로 여기선 0.5만 준다.
+ % +halt, +vhal 따위의 옵션이 주어진 때에도 마찬가지
+ [0x3001] = { 0, .5 },
+ [0x3002] = { 0, .5 },
+ [0xFF0C] = { 0, .5 },
+ [0xFF0E] = { 0, .5 },
+ [0xFE10] = { 0, .5 },
+ [0xFE11] = { 0, .5 },
+ [0xFE12] = { 0, .5 },
}
- fonts.protrusions.setups.notoserifcjk = notoserifcjkkr_hb
}
\defaultfontfeatures+{Renderer=HarfBuzz}
\setmainfont{Latin Modern Roman}[Expansion] % for hb tlig
@@ -87,6 +96,7 @@
InterCharStretch=1pt,
CharRaise=1pt,
CharacterWidth=Full,
+ Protrusion=notosanscjk,
]
\newhangulfontface\rubyfont{Noto Serif CJK KR Medium}[
Script=Hangul,
@@ -124,7 +134,7 @@
\author{Dohyun Kim \normalsize |<nomos at ktug org>| \and
Soojin Nam \normalsize |<jsunam at gmail com>| \and
\normalsize <\url{http://github.com/dohyunkim/luatexko}>}
-\date{Version 3.0\quad 2021/03/01}
+\date{Version 3.1\quad 2021/04/20}
\maketitle
\begin{quote}
@@ -455,6 +465,7 @@ v2.0부터는 고문헌 조판에서 한글^^b7한자와 영문자가 붙어 나
참조.
\begin{figure}
+ \fboxsep=5pt
\framebox[\linewidth]{
\begin{vertical}{20em}
\linespread{1.5}\sffamily \verticalhangulfont
@@ -465,17 +476,21 @@ v2.0부터는 고문헌 조판에서 한글^^b7한자와 영문자가 붙어 나
\end{figure}
\begin{figure}
+ \fboxsep=5pt
\framebox[\linewidth]{
- \begin{vertical}{19em}
+ \begin{vertical}{17em}
\linespread{1.5}\sffamily \verticalhangulfont
\parindent0pt \everypar{\hangindent1em \hangafter1 }
\analectstext
\end{vertical}
}
- \caption{세로쓰기의 다른 예. 박스 높이 |19em|을 지시했다.
+ \caption{세로쓰기의 다른 예. 박스 높이 |17em|을 지시했다.
글꼴에 |CompressPunctuations|와 더불어
|InterCharStretch=1pt|를 옵션으로 주었다. 공백이 없는 문서는 자간늘이기 값을
넉넉하게 주는 것이 좋다.
+ |Protrusion| 옵션으로 구두점들이 행 끝에 매달린 것도 볼 수 있다.
+ |CompressPunctuations|로 이미 반각이 강제되고 있으므로 글자내밀기 값으로 |0.5|를
+ 주어야 전부 내밀기가 된다.
}\label{fig:vertical3}
\end{figure}
@@ -498,6 +513,7 @@ v2.0부터는 고문헌 조판에서 한글^^b7한자와 영문자가 붙어 나
가로쓰기 영역의 폰트 설정은 사용자의 몫이다.
\begin{figure}
+ \fboxsep=5pt
\framebox[\linewidth]{
\begin{vertical}{17em}
\linespread{1.5}\sffamily \verticalhangulfont
diff --git a/macros/luatex/generic/luatexko/luatexko-normalize.lua b/macros/luatex/generic/luatexko/luatexko-normalize.lua
index 2dec726fb6..a86b709390 100644
--- a/macros/luatex/generic/luatexko/luatexko-normalize.lua
+++ b/macros/luatex/generic/luatexko/luatexko-normalize.lua
@@ -13,8 +13,8 @@
luatexbase.provides_module({
name = "luatexko-normalize",
- version = "3.0",
- date = "2021/03/01",
+ version = "3.1",
+ date = "2021/04/20",
author = "Dohyun Kim, Soojin Nam",
description = "Hangul normalization",
license = "LPPL v1.3+",
diff --git a/macros/luatex/generic/luatexko/luatexko-uhc2utf8.lua b/macros/luatex/generic/luatexko/luatexko-uhc2utf8.lua
index e82bf2cdfe..d3d86fcb25 100644
--- a/macros/luatex/generic/luatexko/luatexko-uhc2utf8.lua
+++ b/macros/luatex/generic/luatexko/luatexko-uhc2utf8.lua
@@ -13,8 +13,8 @@
luatexbase.provides_module({
name = "luatexko-uhc2utf8",
- version = "3.0",
- date = "2021/03/01",
+ version = "3.1",
+ date = "2021/04/20",
author = "Dohyun Kim, Soojin Nam",
description = "UHC (CP949) input encoding",
license = "LPPL v1.3+",
diff --git a/macros/luatex/generic/luatexko/luatexko.lua b/macros/luatex/generic/luatexko/luatexko.lua
index 22fcaf54cf..d0360a8b72 100644
--- a/macros/luatex/generic/luatexko/luatexko.lua
+++ b/macros/luatex/generic/luatexko/luatexko.lua
@@ -13,8 +13,8 @@
luatexbase.provides_module {
name = 'luatexko',
- date = '2021/03/01',
- version = '3.0',
+ date = '2021/04/20',
+ version = '3.1',
description = 'typesetting Korean with LuaTeX',
author = 'Dohyun Kim, Soojin Nam',
license = 'LPPL v1.3+',
@@ -112,9 +112,6 @@ 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)
@@ -170,31 +167,79 @@ local function font_opt_dim (fd, optname)
end
end
-local function is_harf (f)
+local function has_harf_data (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 harfbuzz = luaotfload.harfbuzz
+local os2tag = harfbuzz and harfbuzz.Tag.new"OS/2"
-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 fontoptions = {
+ is_not_harf = setmetatable( {}, { __index = function (t, fid)
+ if fid then
+ local bool = has_harf_data(fid) and false or true
+ t[fid] = bool
+ return bool
+ end
+ end }),
-local os2tag = luaotfload.harfbuzz and luaotfload.harfbuzz.Tag.new"OS/2"
+ mode = setmetatable( {}, { __index = function (t, fid)
+ if fid then
+ local m = option_in_font(fid, "mode") or false
+ if m == "harf" and not has_harf_data(fid) then
+ m = "node" -- default mode when 'mode=harf' in non-luahbtex
+ end
+ t[fid] = m
+ return m
+ end
+ end }),
+
+ is_widefont = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local fontdata = get_font_data(fid)
+ local format = fontdata.format
+ local encode = fontdata.encodingbytes
+ local bool = encode == 2 or format == "opentype" or format == "truetype"
+ t[fid] = bool
+ return bool
+ end
+ end }),
+
+ is_hangulscript = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local bool = option_in_font(fid, "script") == "hang"
+ t[fid] = bool
+ return bool
+ end
+ end }),
+
+ compresspunctuations = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local bool = option_in_font(fid, "compresspunctuations") or false
+ t[fid] = bool
+ return bool
+ end
+ end }),
+
+ removeclassicspaces = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local bool = option_in_font(fid, "removeclassicspaces") or false
+ t[fid] = bool
+ return bool
+ end
+ end }),
+
+ slantvalue = setmetatable( {}, { __index = function(t, fid)
+ if fid then
+ local val = option_in_font(fid, "slant") or false
+ t[fid] = val
+ return val
+ end
+ end }),
-local font_options = {
charraise = setmetatable( {}, { __index = function(t, fid)
if fid then
local dim = font_opt_dim(fid, "charraise") or false
@@ -247,7 +292,7 @@ local font_options = {
hangulspaceskip = setmetatable( {}, { __index = function(t, fid)
if fid then
local newwd
- if is_harf(fid) then
+ if has_harf_data(fid) then
newwd = getparameters(fid) or false
if newwd then
newwd = { newwd.space, newwd.space_stretch, newwd.space_shrink }
@@ -274,29 +319,27 @@ local font_options = {
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
+ 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
t[fid] = false; return false
end
end } ),
- tonemarkwidth = setmetatable( {}, { __index = function(t, fid)
+ tonemark_xmax = setmetatable( {}, { __index = function(t, fid)
if fid then
- local hwidth
- -- check horizontal width; vertical width is mostly non-zero
+ -- check horizontal metric
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
+ local bbox = description.boundingbox or {}
+ local xmax = bbox[3] or -1
+ t[fid] = xmax
+ return xmax
end
return 0
end } ),
@@ -307,7 +350,7 @@ local font_options = {
-- 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)
+ local hb = has_harf_data(fid)
if hb and os2tag then
local hbface = hb.shared.face
local tags = hbface:get_table_tags()
@@ -348,6 +391,14 @@ local function char_in_font(fontdata, char)
end
end
+local function harf_reordered_tonemark (curr)
+ if not fontoptions.is_not_harf[curr.font] then
+ local props = getproperty(curr) or {}
+ local actualtext = props.luaotfload_startactualtext or ""
+ return actualtext:find"302[EF]$"
+ end
+end
+
local function my_node_props (n)
local t = getproperty(n)
if not t then
@@ -358,8 +409,6 @@ local function my_node_props (n)
return t.luatexko
end
-local active_processes = {}
-
local function is_hanja (c)
return c >= 0x3400 and c <= 0xA4C6
or c >= 0xF900 and c <= 0xFAD9
@@ -438,6 +487,135 @@ local function is_hangul_jamo (c)
or is_jongsong(c)
end
+local intercharclass = { [0] =
+ { [0] = nil, {1,1}, nil, {.5,.5} },
+ { [0] = nil, nil, nil, {.5,.5} }, -- openers
+ { [0] = {1,1}, {1,1}, nil, {.5,.5}, nil, {1,1}, {1,1} }, -- closers
+ { [0] = {.5,.5},{.5,.5},{.5,.5},{1,.5}, {.5,.5},{.5,.5},{.5,.5},{.5,.5} }, -- middle dots
+ { [0] = {1,0}, {1,0}, nil, {1.5,.5},nil, {1,0}, {1,0} }, -- full stops
+ { [0] = nil, {1,1}, nil, {.5,.5} }, -- leaders and ellipses
+ { [0] = {1,1}, {1,1}, nil, {.5,.5} }, -- questions and exclamations
+ { [0] = {.5,.5},{.5,.5},nil, {.5,.5} }, -- vertical colons
+}
+
+local charclass = setmetatable({
+ [0x2018] = 1, [0x201C] = 1, [0x2329] = 1, [0x3008] = 1,
+ [0x300A] = 1, [0x300C] = 1, [0x300E] = 1, [0x3010] = 1,
+ [0x3014] = 1, [0x3016] = 1, [0x3018] = 1, [0x301A] = 1,
+ [0x301D] = 1, [0xFE17] = 1, [0xFE35] = 1, [0xFE37] = 1,
+ [0xFE39] = 1, [0xFE3B] = 1, [0xFE3D] = 1, [0xFE3F] = 1,
+ [0xFE41] = 1, [0xFE43] = 1, [0xFE47] = 1, [0xFF08] = 1,
+ [0xFF3B] = 1, [0xFF5B] = 1, [0xFF5F] = 1, [0xFF62] = 1,
+ --
+ [0x2019] = 2, [0x201D] = 2, [0x232A] = 2, [0x3001] = 2,
+ [0x3009] = 2, [0x300B] = 2, [0x300D] = 2, [0x300F] = 2,
+ [0x3011] = 2, [0x3015] = 2, [0x3017] = 2, [0x3019] = 2,
+ [0x301B] = 2, [0x301E] = 2, [0x301F] = 2, [0xFE10] = 2,
+ [0xFE11] = 2, [0xFE18] = 2, [0xFE36] = 2, [0xFE38] = 2,
+ [0xFE3A] = 2, [0xFE3C] = 2, [0xFE3E] = 2, [0xFE40] = 2,
+ [0xFE42] = 2, [0xFE44] = 2, [0xFE48] = 2, [0xFF09] = 2,
+ [0xFF0C] = 2, [0xFF3D] = 2, [0xFF5D] = 2, [0xFF60] = 2,
+ [0xFF63] = 2, [0xFF64] = 2,
+ --
+ [0x00B7] = 3, [0x30FB] = 3, [0xFF1A] = 3, [0xFF1B] = 3,
+ [0xFF65] = 3,
+ --
+ [0x3002] = 4, [0xFE12] = 4, [0xFF0E] = 4, [0xFF61] = 4,
+ --
+ [0x2015] = 5, [0x2025] = 5, [0x2026] = 5, [0xFE19] = 5,
+ [0xFE30] = 5, [0xFE31] = 5,
+ --
+ [0xFE15] = 6, [0xFE16] = 6, [0xFF01] = 6, [0xFF1F] = 6,
+}, { __index = function() return 0 end })
+
+local special_classes = {
+ [0] = charclass,
+ setmetatable({ -- vert
+ [0xFF1A] = 7, [0xFF1B] = 7, -- 0xFE13, 0xFE14
+ }, { __index = charclass }),
+ setmetatable({ -- SC
+ [0xFF01] = 4, [0xFF1A] = 2, [0xFF1B] = 2, [0xFF1F] = 4,
+ }, { __index = charclass }),
+ setmetatable({ -- TC
+ [0x3001] = 3, [0x3002] = 3, [0xFF0C] = 3, [0xFF0E] = 3,
+ }, { __index = charclass }),
+ setmetatable({ -- TC vert
+ [0x3001] = 3, [0x3002] = 3, [0xFF0C] = 3, [0xFF0E] = 3,
+ [0xFF1A] = 7, [0xFF1B] = 7, -- 0xFE13, 0xFE14
+ }, { __index = charclass }),
+}
+
+local function get_char_class (c, classic)
+ return special_classes[classic or 0][c]
+end
+
+local breakable_after = setmetatable({
+ [0x21] = true, [0x22] = true, [0x25] = true, [0x27] = true,
+ [0x29] = true, [0x2C] = true, [0x2D] = true, [0x2E] = true,
+ [0x3A] = true, [0x3B] = true, [0x3E] = true, [0x3F] = true,
+ [0x5D] = true, [0x7D] = true, [0x7E] = true, [0xBB] = true,
+ [0x2013] = true, [0x2014] = true, [0x25A1] = true, [0x25CB] = true,
+ [0x2E80] = true, [0x3003] = true, [0x3005] = true, [0x3007] = true,
+ [0x301C] = true, [0x3035] = true, [0x303B] = true, [0x303C] = true,
+ [0x309D] = true, [0x309E] = true, [0x30A0] = true, [0x30FC] = true,
+ [0x30FD] = true, [0x30FE] = true, [0xFE13] = true, [0xFE14] = true,
+ [0xFE32] = true, [0xFE50] = true, [0xFE51] = true, [0xFE52] = true,
+ [0xFE54] = true, [0xFE55] = true, [0xFE57] = true, [0xFE57] = true,
+ [0xFE58] = true, [0xFE5A] = true, [0xFE5C] = true, [0xFE5E] = true,
+ [0xFF1E] = true, [0xFF5E] = true, [0xFF70] = true, [0x226B] = true, -- ≫
+},{ __index = function (_,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)
+ or is_kana(c)
+ or charclass[c] >= 2
+end })
+luatexko.breakableafter = breakable_after
+
+local breakable_before = setmetatable({
+ [0x28] = true, [0x3C] = true, [0x5B] = true, [0x60] = true,
+ [0x7B] = true, [0xAB] = true, [0x25A1] = true, [0x25CB] = true,
+ [0x3007] = true, [0xFE59] = true, [0xFE5B] = true, [0xFE5D] = true,
+ [0xFF1C] = true, [0x226A] = true, -- ≪
+ -- small kana
+ [0x3041] = 1000, [0x3043] = 1000, [0x3045] = 1000, [0x3047] = 1000,
+ [0x3049] = 1000, [0x3063] = 1000, [0x3083] = 1000, [0x3085] = 1000,
+ [0x3087] = 1000, [0x308E] = 1000, [0x3095] = 1000, [0x3096] = 1000,
+ [0x30A1] = 1000, [0x30A3] = 1000, [0x30A5] = 1000, [0x30A7] = 1000,
+ [0x30A9] = 1000, [0x30C3] = 1000, [0x30E3] = 1000, [0x30E5] = 1000,
+ [0x30E7] = 1000, [0x30EE] = 1000, [0x30F5] = 1000, [0x30F6] = 1000,
+ [0x31F0] = 1000, [0x31F1] = 1000, [0x31F2] = 1000, [0x31F3] = 1000,
+ [0x31F4] = 1000, [0x31F5] = 1000, [0x31F6] = 1000, [0x31F7] = 1000,
+ [0x31F8] = 1000, [0x31F9] = 1000, [0x31FA] = 1000, [0x31FB] = 1000,
+ [0x31FC] = 1000, [0x31FD] = 1000, [0x31FE] = 1000, [0x31FF] = 1000,
+ [0xFF67] = 1000, [0xFF68] = 1000, [0xFF69] = 1000, [0xFF6A] = 1000,
+ [0xFF6B] = 1000, [0xFF6C] = 1000, [0xFF6D] = 1000, [0xFF6E] = 1000,
+ [0xFF6F] = 1000, [0x1B150] = 1000, [0x1B151] = 1000, [0x1B152] = 1000,
+ [0x1B164] = 1000, [0x1B165] = 1000, [0x1B166] = 1000, [0x1B167] = 1000,
+},{ __index = function(_,c)
+ return is_hangul(c)
+ or is_compat_jamo(c)
+ or is_chosong(c)
+ or is_hanja(c)
+ or is_kana(c)
+ or charclass[c] == 1
+end
+})
+luatexko.breakablebefore = breakable_before
+
+local function is_cjk_char (c)
+ return is_hangul_jamo(c)
+ or is_hanja(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
+end
+
+local active_processes = {}
+
-- font fallback
local force_hangul = {
@@ -479,7 +657,7 @@ local function hangul_space_skip (curr, newfont)
-- command does the same thing), which we will bypass here
-- for alignment of CJK and Latin glyphs in verbatim environment.
-- See http://www.ktug.org/xe/index.php?document_srl=249772
- if not font_options.monospaced[curr.font] then
+ if not fontoptions.monospaced[curr.font] then
local n = getnext(curr)
if n and n.id == glueid and n.subtype == spaceskip then
local params = getparameters(curr.font)
@@ -491,7 +669,7 @@ local function hangul_space_skip (curr, newfont)
and oldsto == 0
and oldsho == 0 then -- not user's spaceskip
- local newwd = font_options.hangulspaceskip[newfont]
+ local newwd = fontoptions.hangulspaceskip[newfont]
if newwd then
setglue(n, newwd[1], newwd[2], newwd[3])
end
@@ -516,24 +694,28 @@ local function process_fonts (head)
if p.id == glyphid and curr.font ~= p.font then
hangul_space_skip(curr, p.font)
curr.font = p.font
+ curr.lang = p.lang
end
if not active_processes.reorderTM and
hangul_tonemark[c] and
- is_not_harf(curr.font) and
- option_in_font(curr.font, "script") == "hang" then
+ fontoptions.is_not_harf[curr.font] and
+ fontoptions.is_hangulscript[curr.font] then
luatexko.activate("reorderTM") -- activate reorderTM here
end
else
+ if curr.subtype == 1 and curr.lang ~= nohyphen and is_cjk_char(c) then
+ curr.lang = langkor -- suppress hyphenation of cjk chars
+ end
+
local hf = has_attribute(curr, hangulfontattr) or false
local hjf = has_attribute(curr, hanjafontattr) or false
- local fontdata = get_font_data(curr.font)
- 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 and not font_options.monospaced[curr.font] then
+ if hf and force_hangul[c]
+ and fontoptions.is_widefont[curr.font] -- exclude legacy fonts
+ and curr.lang ~= nohyphen and not fontoptions.monospaced[curr.font] -- exclude ttfamily
+ then
curr.font = hf
elseif hf and has_attribute(curr, hangulbyhangulattr) and is_hangul_jamo(c) then
hangul_space_skip(curr, hf)
@@ -541,7 +723,7 @@ local function process_fonts (head)
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
+ elseif not char_in_font(curr.font, c) then
local fbf = has_attribute(curr, fallbackfontattr) or false
for _,f in ipairs{ hf, hjf, fbf } do
if f and char_in_font(f, c) then
@@ -577,120 +759,6 @@ end
-- linebreak
-local intercharclass = { [0] =
- { [0] = nil, {1,1}, nil, {.5,.5} },
- { [0] = nil, nil, nil, {.5,.5} },
- { [0] = {1,1}, {1,1}, nil, {.5,.5}, nil, {1,1}, {1,1} },
- { [0] = {.5,.5},{.5,.5},{.5,.5},{1,.5}, {.5,.5},{.5,.5},{.5,.5} },
- { [0] = {1,0}, {1,0}, nil, {1.5,.5},nil, {1,0}, {1,0} },
- { [0] = nil, {1,1}, nil, {.5,.5} },
- { [0] = {1,1}, {1,1}, nil, {.5,.5} },
- { }, -- vertical colon
-}
-
-local charclass = setmetatable({
- [0x2018] = 1, [0x201C] = 1, [0x2329] = 1, [0x3008] = 1,
- [0x300A] = 1, [0x300C] = 1, [0x300E] = 1, [0x3010] = 1,
- [0x3014] = 1, [0x3016] = 1, [0x3018] = 1, [0x301A] = 1,
- [0x301D] = 1, [0xFE17] = 1, [0xFE35] = 1, [0xFE37] = 1,
- [0xFE39] = 1, [0xFE3B] = 1, [0xFE3D] = 1, [0xFE3F] = 1,
- [0xFE41] = 1, [0xFE43] = 1, [0xFE47] = 1, [0xFF08] = 1,
- [0xFF3B] = 1, [0xFF5B] = 1, [0xFF5F] = 1, [0xFF62] = 1,
- --
- [0x2019] = 2, [0x201D] = 2, [0x232A] = 2, [0x3001] = 2,
- [0x3009] = 2, [0x300B] = 2, [0x300D] = 2, [0x300F] = 2,
- [0x3011] = 2, [0x3015] = 2, [0x3017] = 2, [0x3019] = 2,
- [0x301B] = 2, [0x301E] = 2, [0x301F] = 2, [0xFE10] = 2,
- [0xFE11] = 2, [0xFE18] = 2, [0xFE36] = 2, [0xFE38] = 2,
- [0xFE3A] = 2, [0xFE3C] = 2, [0xFE3E] = 2, [0xFE40] = 2,
- [0xFE42] = 2, [0xFE44] = 2, [0xFE48] = 2, [0xFF09] = 2,
- [0xFF0C] = 2, [0xFF3D] = 2, [0xFF5D] = 2, [0xFF60] = 2,
- [0xFF63] = 2, [0xFF64] = 2,
- --
- [0x00B7] = 3, [0x30FB] = 3, [0xFF1A] = 3, [0xFF1B] = 3,
- [0xFF65] = 3,
- --
- [0x3002] = 4, [0xFE12] = 4, [0xFF0E] = 4, [0xFF61] = 4,
- --
- [0x2015] = 5, [0x2025] = 5, [0x2026] = 5, [0xFE19] = 5,
- [0xFE30] = 5, [0xFE31] = 5,
- --
- [0xFE15] = 6, [0xFE16] = 6, [0xFF01] = 6, [0xFF1F] = 6,
-}, { __index = function() return 0 end })
-
-local SC_charclass = setmetatable({
- [0xFF01] = 4, [0xFF1A] = 4, [0xFF1B] = 4, [0xFF1F] = 4,
-}, { __index = charclass })
-
-local vert_charclass = setmetatable({
- [0xFF1A] = 7, -- 0xFE13
- [0xFF1B] = 7, -- 0xFE14
-}, { __index = charclass })
-
-local function get_char_class (c, classic)
- if classic == vert_classic then
- return vert_charclass[c]
- elseif classic == SC_classic then
- return SC_charclass[c]
- end
- return charclass[c]
-end
-
-local breakable_after = setmetatable({
- [0x21] = true, [0x22] = true, [0x25] = true, [0x27] = true,
- [0x29] = true, [0x2C] = true, [0x2D] = true, [0x2E] = true,
- [0x3A] = true, [0x3B] = true, [0x3E] = true, [0x3F] = true,
- [0x5D] = true, [0x7D] = true, [0x7E] = true, [0xBB] = true,
- [0x2013] = true, [0x2014] = true, [0x25A1] = true, [0x25CB] = true,
- [0x2E80] = true, [0x3003] = true, [0x3005] = true, [0x3007] = true,
- [0x301C] = true, [0x3035] = true, [0x303B] = true, [0x303C] = true,
- [0x309D] = true, [0x309E] = true, [0x30A0] = true, [0x30FC] = true,
- [0x30FD] = true, [0x30FE] = true, [0xFE13] = true, [0xFE14] = true,
- [0xFE32] = true, [0xFE50] = true, [0xFE51] = true, [0xFE52] = true,
- [0xFE54] = true, [0xFE55] = true, [0xFE57] = true, [0xFE57] = true,
- [0xFE58] = true, [0xFE5A] = true, [0xFE5C] = true, [0xFE5E] = true,
- [0xFF1E] = true, [0xFF5E] = true, [0xFF70] = true,
-},{ __index = function (_,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)
- or is_kana(c)
- or charclass[c] >= 2
-end })
-luatexko.breakableafter = breakable_after
-
-local breakable_before = setmetatable({
- [0x28] = true, [0x3C] = true, [0x5B] = true, [0x60] = true,
- [0x7B] = true, [0xAB] = true, [0x25A1] = true, [0x25CB] = true,
- [0x3007] = true, [0xFE59] = true, [0xFE5B] = true, [0xFE5D] = true,
- [0xFF1C] = true,
- -- small kana
- [0x3041] = 1000, [0x3043] = 1000, [0x3045] = 1000, [0x3047] = 1000,
- [0x3049] = 1000, [0x3063] = 1000, [0x3083] = 1000, [0x3085] = 1000,
- [0x3087] = 1000, [0x308E] = 1000, [0x3095] = 1000, [0x3096] = 1000,
- [0x30A1] = 1000, [0x30A3] = 1000, [0x30A5] = 1000, [0x30A7] = 1000,
- [0x30A9] = 1000, [0x30C3] = 1000, [0x30E3] = 1000, [0x30E5] = 1000,
- [0x30E7] = 1000, [0x30EE] = 1000, [0x30F5] = 1000, [0x30F6] = 1000,
- [0x31F0] = 1000, [0x31F1] = 1000, [0x31F2] = 1000, [0x31F3] = 1000,
- [0x31F4] = 1000, [0x31F5] = 1000, [0x31F6] = 1000, [0x31F7] = 1000,
- [0x31F8] = 1000, [0x31F9] = 1000, [0x31FA] = 1000, [0x31FB] = 1000,
- [0x31FC] = 1000, [0x31FD] = 1000, [0x31FE] = 1000, [0x31FF] = 1000,
- [0xFF67] = 1000, [0xFF68] = 1000, [0xFF69] = 1000, [0xFF6A] = 1000,
- [0xFF6B] = 1000, [0xFF6C] = 1000, [0xFF6D] = 1000, [0xFF6E] = 1000,
- [0xFF6F] = 1000, [0x1B150] = 1000, [0x1B151] = 1000, [0x1B152] = 1000,
- [0x1B164] = 1000, [0x1B165] = 1000, [0x1B166] = 1000, [0x1B167] = 1000,
-},{ __index = function(_,c)
- return is_hangul(c)
- or is_compat_jamo(c)
- or is_chosong(c)
- or is_hanja(c)
- or is_kana(c)
- or charclass[c] == 1
-end
-})
-luatexko.breakablebefore = breakable_before
-
local allowbreak_false_nodes = {
[hlistid] = true,
[vlistid] = true,
@@ -758,12 +826,12 @@ local function insert_glue_before (head, curr, par, br, brb, classic, ict, dim,
dim = dim or 0
local gl = nodenew(glueid)
- local en = font_options.en_size[fid]
+ local en = fontoptions.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 = font_options.intercharstretch[fid] or stretch_f*en
+ local str = fontoptions.intercharstretch[fid] or stretch_f*en
setglue(gl, dim, str, str*0.6)
end
@@ -777,7 +845,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 = font_options.intercharacter[fid]
+ local dim = fontoptions.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
@@ -825,69 +893,13 @@ local function process_linebreak (head, par)
return head
end
--- compress punctuations
-
-local function process_glyph_width (head)
- local curr = head
- while curr do
- local id = curr.id
- if id == glyphid then
- if curr.lang ~= nohyphen
- and option_in_font(curr.font, "compresspunctuations") then
-
- local cc = my_node_props(curr).unicode or curr.char
- 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
-
- -- harf-node always puts kern after the glyph
- local gpos = class == 1 and is_not_harf(curr.font) and getprev(curr) or getnext(curr)
- gpos = gpos and gpos.id == kernid and gpos.subtype == fontkern
-
- if not gpos then
- 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
- if class == 1 then
- head = insert_before(head, curr, k)
- elseif class == 2 or class == 4 then
- head, curr = insert_after(head, curr, k)
- else
- local k2 = nodecopy(k)
- head = insert_before(head, curr, k)
- head, curr = insert_after(head, curr, k2)
- end
- end
- end
- end
- end
- elseif id == mathid then
- curr = end_of_math(curr)
- end
- curr = getnext(curr)
- end
- return head
-end
-
-- interhangul & interlatincjk
-local function is_cjk_char (c)
- return is_hangul_jamo(c)
- or is_hanja(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
-end
-
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 = font_options.interhangul[fontid]
+ local dim = fontoptions.interhangul[fontid]
if dim then
head = insert_glue_before(head, curr, par, true, true, false, false, dim, fontid)
end
@@ -944,11 +956,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 = font_options.interlatincjk[f]
+ local dim = fontoptions.interlatincjk[f]
if dim then
local ict = old and intercharclass[pcl][ccl] -- under classic env. only
if ict then
- dim = font_options.intercharacter[f] or 0
+ dim = fontoptions.intercharacter[f] or 0
end
head = insert_glue_before(head, curr, par, true, brb, old, ict, dim, f)
end
@@ -1011,10 +1023,56 @@ local function process_interlatincjk (head, par)
return head
end
+-- compress punctuations
+
+local function process_glyph_width (head)
+ local curr = head
+ while curr do
+ local id = curr.id
+ if id == glyphid then
+ if curr.lang ~= nohyphen
+ and fontoptions.compresspunctuations[curr.font] then
+
+ local cc = my_node_props(curr).unicode or curr.char
+ 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
+
+ -- harf-node always puts kern after the glyph
+ local gpos = class == 1 and fontoptions.is_not_harf[curr.font] and getprev(curr) or getnext(curr)
+ gpos = gpos and gpos.id == kernid and gpos.subtype == fontkern
+
+ if not gpos then
+ local wd = fontoptions.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
+ if class == 1 then
+ head = insert_before(head, curr, k)
+ elseif class == 2 or class == 4 then
+ head, curr = insert_after(head, curr, k)
+ else
+ local k2 = nodecopy(k)
+ head = insert_before(head, curr, k)
+ head, curr = insert_after(head, curr, k2)
+ end
+ end
+ end
+ end
+ end
+ elseif id == mathid then
+ curr = end_of_math(curr)
+ end
+ curr = getnext(curr)
+ end
+ return head
+end
+
-- remove classic spaces
local function process_remove_spaces (head)
- local curr, opt_name, to_free = head, "removeclassicspaces", {}
+ local curr, to_free = head, {}
while curr do
local id = curr.id
if id == glueid then
@@ -1037,7 +1095,7 @@ local function process_remove_spaces (head)
elseif id == hlistid and v.list then
vchar, vfont = hbox_char_font(v, k == "n")
end
- if vchar and vfont and option_in_font(vfont, opt_name) then
+ if vchar and vfont and fontoptions.removeclassicspaces[vfont] then
ok = is_cjk_char(vchar)
end
@@ -1243,7 +1301,7 @@ local function process_dotemph (head)
end
local currwd = curr.width
- if currwd >= font_options.en_size[curr.font] then
+ if currwd >= fontoptions.en_size[curr.font] then
local box = nodecopy(dotemphbox[dotattr]).list
-- bypass unwanted nodes injected by some other packages
while box.id ~= hlistid do
@@ -1289,7 +1347,7 @@ function luatexko.get_strike_out_down (box)
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])
+ local ascender, descender = tableunpack(fontoptions.asc_desc[f])
if ascender and descender then
down = descender - (ascender + descender)/2
else
@@ -1299,7 +1357,7 @@ function luatexko.get_strike_out_down (box)
down = -0.5*ex
end
- local raise = font_options.charraise[f] or 0
+ local raise = fontoptions.charraise[f] or 0
return down - raise
end
return -texsp"0.5ex"
@@ -1423,9 +1481,9 @@ luatexko.rubybox = rubybox
function luatexko.getrubystretchfactor (box)
local _, fid = hbox_char_font(box, true, true)
- local str = font_options.intercharstretch[fid]
+ local str = fontoptions.intercharstretch[fid]
if str then
- local em = font_options.en_size[fid] * 2
+ local em = fontoptions.en_size[fid] * 2
set_macro("luatexkostretchfactor", stringformat("%.4f", str/em/2))
end
end
@@ -1483,7 +1541,7 @@ local function process_ruby_post_linebreak (head)
local shift = shift_put_top(curr, ruby)
local _, f = hbox_char_font(curr, true, true)
- local ascender = tableunpack(font_options.asc_desc[f]) or curr.height
+ local ascender = tableunpack(fontoptions.asc_desc[f]) or curr.height
ruby.shift = shift - ascender - ruby.depth - ruby_t[2] -- rubysep
head = insert_before(head, curr, ruby)
end
@@ -1539,10 +1597,9 @@ local function process_reorder_tonemarks (head)
while curr do
local id = curr.id
if id == glyphid and
- is_not_harf(curr.font) and
- option_in_font(curr.font, "script") == "hang" then
+ fontoptions.is_not_harf[curr.font] and
+ fontoptions.is_hangulscript[curr.font] then
- local fontdata = get_font_data(curr.font)
local uni = my_node_props(curr).unicode or curr.char
if is_hangul(uni) or is_chosong(uni) or uni == 0x25CC then
init = curr
@@ -1559,7 +1616,7 @@ local function process_reorder_tonemarks (head)
n = getnext(n)
end
- if #syllable > 1 and font_options.tonemarkwidth[curr.font] ~= 0 then
+ if #syllable > 1 and fontoptions.tonemark_xmax[curr.font] >= 0 then
local TM = curr
local actual = pdfliteral_direct_actual(syllable)
@@ -1572,10 +1629,10 @@ local function process_reorder_tonemarks (head)
end
init = nil
- elseif char_in_font(fontdata, 0x25CC) then -- isolated tone mark
+ elseif char_in_font(curr.font, 0x25CC) then -- isolated tone mark
local dotcircle = nodecopy(curr)
dotcircle.char = 0x25CC
- if font_options.tonemarkwidth[curr.font] ~= 0 then
+ if fontoptions.tonemark_xmax[curr.font] >= 0 then
local actual = pdfliteral_direct_actual{ init = curr, uni }
local endactual = pdfliteral_direct_actual()
head = insert_before(head, curr, actual)
@@ -1845,7 +1902,7 @@ function luatexko.gethorizboxmoveright ()
if v and v > 0 then
local amount = get_font_data(v).vertcharraise
if amount then
- amount = amount + (font_options.charraise[v] or 0)
+ amount = amount + (fontoptions.charraise[v] or 0)
set_macro("luatexkohorizboxmoveright", texsp(amount).."sp")
break
end
@@ -1863,8 +1920,7 @@ local function process_charraise (head)
local id = curr.id
if id == glyphid then
if not has_attribute(curr,raiseattr) then
- local f = curr.font
- local raise = font_options.charraise[f]
+ local raise = fontoptions.charraise[curr.font]
if raise then
curr.yoffset = (curr.yoffset or 0) + raise
end
@@ -1896,7 +1952,7 @@ local function process_fake_slant_corr (head) -- for font fallback
break
end
- local slant = option_in_font(p.font, "slant")
+ local slant = fontoptions.slantvalue[p.font]
if slant and slant > 0 then
tableinsert(t, char_in_font(p.font, p.char).italic or 0)
end
@@ -1934,7 +1990,7 @@ local function process_fake_slant_font (fontdata, fsl)
local params = fontdata.parameters or {}
params.slant = (params.slant or 0) + fsl*65536 -- slant per point
- local hb = is_harf(fontdata)
+ local hb = has_harf_data(fontdata)
local scale = hb and hb.scale or params.factor or 655.36
local shared = fontdata.shared or {}
local descrs = shared.rawdata and shared.rawdata.descriptions or {}
@@ -1968,6 +2024,13 @@ end
-- wrap up
+add_to_callback ("hyphenate",
+function(head)
+ local head = process_fonts(head)
+ lang.hyphenate(head)
+end,
+"luatexko.hyphenate.fonts_and_languages")
+
local pass_fun = function(...) return ... end
create_callback("luatexko_prelinebreak_first", "data", pass_fun)
create_callback("luatexko_prelinebreak_second", "data", pass_fun)
@@ -1985,7 +2048,6 @@ add_to_callback("pre_shaping_filter", function(h, gc)
or gc == "vtop"
or gc == "insert"
or gc == "vcenter"
- h = process_fonts(h)
h = call_callback("luatexko_prelinebreak_first", h, par)
h = call_callback("luatexko_prelinebreak_second", h, par)
return process_linebreak(h, par)
@@ -2047,10 +2109,10 @@ otfregister {
description = "raise chars",
default = false,
manipulators = {
- node = function(fontdata)
+ node = function()
activate_process("post_shaping_filter", process_charraise, "charraise")
end,
- plug = function(fontdata)
+ plug = function()
activate_process("post_shaping_filter", process_charraise, "charraise")
end,
},
@@ -2123,25 +2185,23 @@ otfregister {
},
}
-local function process_protrusion (fontdata, _, value)
- local setup = fonts.protrusions.setups[value] or {}
- local quad = fontdata.parameters.quad
- for i, v in pairs(setup) do
- local chr = fontdata.characters[i]
- if chr then
- local wdq = chr.width/quad
- chr.left_protruding = chr.left_protruding or wdq*v[1]*1000
- chr.right_protruding = chr.right_protruding or wdq*v[2]*1000
- end
- end
- if tex.protrudechars == 0 then
- texset("global", "protrudechars", 2)
- end
- if option_in_font(fontdata, "compresspunctuations") then
- local fullname = fontdata.fullname
- fontdata_warning("protrude."..fullname,
- "Both `compresspunctuations' and `protrusion' are\nenabled for `%s'.\n"..
- "Beware bad justifications.", fullname)
+local dir_ltr = harfbuzz and harfbuzz.Direction.new"ltr"
+
+local function get_HB_variant_char (fontdata, charcode)
+ local hbfont = fontdata.hb.shared.font
+ local spec = fontdata.specification
+ local shaper = spec.features.raw.shaper
+ local buff = harfbuzz.Buffer.new()
+ buff:set_direction(dir_ltr)
+ buff:set_script(spec.script)
+ buff:set_language(spec.language)
+ buff:add_codepoints{charcode}
+ harfbuzz.shape_full(hbfont, buff, spec.hb_features, shaper and {shaper} or {})
+ local glyphs = buff:get_glyphs()
+ if glyphs and glyphs[1] then
+ local glyph = glyphs[1].codepoint
+ local offset = fontdata.hb.shared.gid_offset
+ return glyph + offset
end
end
@@ -2150,8 +2210,41 @@ otfregister {
description = "glyph protrusion",
default = false,
manipulators = {
- node = process_protrusion,
- plug = process_protrusion,
+ node = function(fontdata, _, value)
+ local setup = fonts.protrusions.setups[value] or {}
+ local quad = fontdata.parameters.quad
+ for i, v in pairs(fontdata.characters) do
+ local uni = v.unicode
+ if uni then
+ local lr = setup[uni]
+ if lr then
+ local wdq = v.width/quad*1000
+ v.left_protruding = wdq*lr[1]
+ v.right_protruding = wdq*lr[2]
+ end
+ end
+ end
+ if tex.protrudechars == 0 then
+ texset("global", "protrudechars", 2)
+ end
+ end,
+ plug = function(fontdata, _, value)
+ local setup = fonts.protrusions.setups[value] or {}
+ local quad = fontdata.parameters.quad
+ for i, v in pairs(setup) do
+ for _, ii in ipairs{i, get_HB_variant_char(fontdata,i)} do
+ local chr = fontdata.characters[ii]
+ if chr then
+ local wdq = chr.width/quad*1000
+ chr.left_protruding = wdq*v[1]
+ chr.right_protruding = wdq*v[2]
+ end
+ end
+ end
+ if tex.protrudechars == 0 then
+ texset("global", "protrudechars", 2)
+ end
+ end,
},
}
@@ -2181,32 +2274,6 @@ function luatexko.activate (name)
active_processes[name] = true
end
-add_to_callback ("hyphenate",
-function(head)
- local curr = head
- while curr do
- local id = curr.id
- if id == glyphid and curr.subtype == 1 and curr.lang ~= nohyphen then
- local c = curr.char
- if c then
- if is_unicode_var_sel(c) then
- local p = getprev(curr)
- if p.id == glyphid then
- curr.lang = p.lang
- end
- elseif is_cjk_char(c) then
- curr.lang = langkor
- end
- end
- elseif id == mathid then
- curr = end_of_math(curr)
- end
- curr = getnext(curr)
- end
- lang.hyphenate(head)
-end,
-"luatexko.hyphenate.prevent_disc_nodes")
-
-- aux functions
function luatexko.deactivateall (str)
diff --git a/macros/luatex/generic/luatexko/luatexko.sty b/macros/luatex/generic/luatexko/luatexko.sty
index f1e0179164..c44ccedcbe 100644
--- a/macros/luatex/generic/luatexko/luatexko.sty
+++ b/macros/luatex/generic/luatexko/luatexko.sty
@@ -14,7 +14,7 @@
\ifdefined\luatexkohangulfontattr \endinput\fi
\ifdefined\selectfont
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
- \ProvidesPackage{luatexko}[2021/03/01 v3.0 typesetting Korean with LuaTeX]
+ \ProvidesPackage{luatexko}[2021/04/20 v3.1 typesetting Korean with LuaTeX]
\RequirePackage{luatexbase}
\RequirePackage{fontspec}[2020/02/03]
\else
@@ -55,12 +55,57 @@
\DeclareHookRule{shipout/before}{.}{before}{luacolor}
\fi
% classic
-\protected\def\typesetclassic{\luatexkoclassicattr\z@\parindent1em }
-\protected\def\typesetvertical{\luatexkoclassicattr\@ne\parindent1em }
+\protected\def\typesetclassic{% 0
+ \ifnum\luatexkoclassicattr<\z@
+ \luatexkoclassicattr\z@
+ \parindent1em
+ \fi
+ }
+\protected\def\typesetvertical{% 1
+ \ifcase\luatexkoclassicattr
+ \luatexkoclassicattr\@ne
+ \parindent1em
+ \or
+ \or
+ \luatexkoclassicattr\@ne
+ \or
+ \luatexkoclassicattr=4\relax
+ \or
+ \else
+ \luatexkoclassicattr\@ne
+ \parindent1em
+ \fi
+ }
\protected\def\typesetmodern{\unsetattribute\luatexkoclassicattr}
\protected\def\inhibitglue{\hskip\z@skip}
-\protected\def\Schinese{\luatexkoclassicattr\tw@\parindent2em }
-\protected\def\Tchinese{\luatexkoclassicattr\thr@@\parindent2em } % +halt
+\protected\def\Schinese{% 2, 1
+ \ifcase\luatexkoclassicattr
+ \luatexkoclassicattr\tw@
+ \or
+ \or
+ \or
+ \luatexkoclassicattr\tw@
+ \or
+ \luatexkoclassicattr\@ne
+ \else
+ \luatexkoclassicattr\tw@
+ \fi
+ \parindent2em
+ }
+\protected\def\Tchinese{% 3, 4
+ \ifcase\luatexkoclassicattr
+ \luatexkoclassicattr\thr@@
+ \or
+ \luatexkoclassicattr=4\relax
+ \or
+ \luatexkoclassicattr\thr@@
+ \or
+ \or
+ \else
+ \luatexkoclassicattr\thr@@
+ \fi
+ \parindent2em
+ }
\let\korean\typesetmodern \let\japanese\typesetclassic \let\chinese\Schinese
% josa
\count@"AC00