[latex3-commits] [git/LaTeX3-latex3-luaotfload] bidi-dev: Fixes, less debugging, ... (4fd930e)
Marcel Fabian Krüger
tex at 2krueger.de
Tue Aug 13 13:39:21 CEST 2019
Repository : https://github.com/latex3/luaotfload
On branch : bidi-dev
Link : https://github.com/latex3/luaotfload/commit/4fd930efd820da31d2efdad38bb00787fee72507
>---------------------------------------------------------------
commit 4fd930efd820da31d2efdad38bb00787fee72507
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date: Tue Aug 13 13:39:21 2019 +0200
Fixes, less debugging, ...
>---------------------------------------------------------------
4fd930efd820da31d2efdad38bb00787fee72507
src/luaotfload-bidi.lua | 104 ++++++++++++---------
src/luaotfload-init.lua | 2 +-
.../tex/luatex/luaotfload}/luaotfload-bidi.lua | 104 ++++++++++++---------
texmf/tex/luatex/luaotfload/luaotfload-init.lua | 2 +-
4 files changed, 118 insertions(+), 94 deletions(-)
diff --git a/src/luaotfload-bidi.lua b/src/luaotfload-bidi.lua
index e8f0374..02d3659 100644
--- a/src/luaotfload-bidi.lua
+++ b/src/luaotfload-bidi.lua
@@ -18,6 +18,8 @@ end
local nodenew = node.direct.new
local nodecopy = node.direct.copy
+local nodeflush = node.direct.flush_node
+local free = node.direct.free
local setsubtype = node.direct.setsubtype
local setchar = node.direct.setchar
local getchar = node.direct.getchar
@@ -361,29 +363,26 @@ local node_class, node_origclass, node_level = {}, {}, {} -- Making these local
-- keys, requiring relativly big allocations
function dobidi(head, a, b, c, par_direction)
head = node.direct.todirect(head)
- -- for cur in traverse(head) do
- -- print(node.direct.tonode(cur))
- -- end
local node_class, node_origclass, node_level = node_class, node_origclass, node_level
local dir_matches = {}
par_direction = par_direction == "TRT" and "R" or "L" -- We hope to only encounter TRT/TLT
local parlevel, level, oldlevel, overwrite, isolate = par_direction == "R" and 1 or 0
level, oldlevel = parlevel, -1
local stack = {}
- local function push(dir, new_overwrite, new_isolate)
+ local function push(dir, new_overwrite)
stack[#stack+1] = {level, overwrite, isolate}
- level, overwrite, isolate = level + (level + dir + 1)%2 + 1, new_overwrite, new_isolate
+ level, overwrite, isolate = level + (level + dir + 1)%2 + 1, new_overwrite, nil
end
local function pop()
local last = stack[#stack]
stack[#stack] = nil
level, overwrite, isolate = last[1], last[2], last[3]
end
- local starttime = gettime()
local isolating_level_runs = {}
local current_run
+ local old_dir
for cur, tcur, scur in traverse(head) do
- local class, curlevel
+ local class, curlevel, isolate_flag
if tcur == glyph_id and bidi_fonts[getfont(cur)] then
class = bidi_classes[getchar(cur)]
if class == "RLE" then
@@ -425,22 +424,24 @@ function dobidi(head, a, b, c, par_direction)
pop()
end
if isolate then
- dir_matches[isolate] = false
- dir_matches[cur] = isolate
+ isolate_flag = isolate
pop()
else
-- Unmatched reset. LuaTeX inserts them sometimes, just
-- dropping them normally works fine. But deleting is
-- difficult here because the loop needs the next pointer.
- -- FIXME: We will leak them for now
+ if old_dir then nodeflush(old_dir) end
head = remove(head, cur)
+ old_dir = cur
+ goto SKIP
end
class = overwrite or "PDI"
else
curlevel = level
dir = dir == 1 and 1 or 0
class = overwrite or (dir == 1 and "LRI" or "RLI")
- push(dir, nil, cur)
+ push(dir, nil)
+ isolate_flag = false
end
elseif tcur == glue_id or tcur == kern_id then -- Not sure about kerns
class = "WS"
@@ -458,15 +459,11 @@ function dobidi(head, a, b, c, par_direction)
current_run[5] = os
current_run = nil
end
- if dir_matches[cur] then
- local beg = dir_matches[cur]
- current_run = dir_matches[beg]
- local remember = {getnext(beg), getprev(cur)}
- dir_matches[cur] = nil
- if getnext(beg) == cur then -- Handle stupid input
- dir_matches[beg] = nil
- else
- dir_matches[beg] = remember
+ if isolate_flag then
+ current_run = isolate_flag
+ local beg = current_run.remember
+ if getnext(beg) ~= cur then -- Handle stupid input
+ dir_matches[beg] = {getnext(beg), getprev(cur)}
setprev(getnext(beg), nil)
setnext(getprev(cur), nil)
setnext(beg, cur)
@@ -477,34 +474,59 @@ function dobidi(head, a, b, c, par_direction)
isolating_level_runs[#isolating_level_runs+1] = current_run
end
end
- if dir_matches[cur] == false then
- dir_matches[cur] = current_run
+ if isolate_flag == false then
+ current_run.remember = cur
+ isolate = current_run
current_run = nil
end
+ ::SKIP::
+ end
+ local t = tail(head)
+ do
+ local tid = getid(t)
+ while t and tid > dir_id and tid ~= glyph_id do t = getprev(t) tid = getid(t) end
+ if not t then return head end -- Everything is discardable, so ignore it
end
- for i = 1,#stack do pop() end
if current_run then
- current_run[3] = tail(head)
+ current_run[3] = t
current_run[5] = (oldlevel > parlevel and oldlevel or parlevel) % 2 == 1 and 'R' or 'L'
-- Should always be level IINM, but let's us the offical check
current_run = nil
end
- fulltime2 = fulltime2 + gettime() - starttime
+ for i = 1,#stack do
+ if isolate then
+ local beg = isolate.remember
+ local n
+ if beg == t then
+ n = getprev(t)
+ if not n then return head end
+ setnext(n, free(t))
+ else
+ dir_matches[beg] = {getnext(beg), t}
+ if old_dir then
+ n = old_dir
+ setdirection(n, getdirection(beg), 1)
+ old_dir = nil
+ else
+ n = nodecopy(beg)
+ setsubtype(n, 1)
+ end
+ node_class[n], node_origclass[n] = "PDI", "PDI"
+ setnext(n, getnext(t))
+ setprev(getnext(beg), nil)
+ setnext(t, nil)
+ setnext(beg, n)
+ setprev(n, beg)
+ end
+ t = n
+ isolate[3], isolate[5] = n, isolate[2] % 2 == 1 and 'R' or 'L'
+ end
+ pop()
+ end
for i = 1, #isolating_level_runs do
local run = isolating_level_runs[i]
do_wni(run[1], run[2], run[3], run[4], run[5], node_class, node_level, node_origclass)
end
- starttime = gettime()
- -- for cur in traverse(head) do
- -- local curtype = node_type[cur]
- -- local curclass, curlevel, origtype = curtype[1], curtype[2], curtype[3]
- -- -- print('?', node.direct.tonode(cur), curclass, curlevel, origtype)
- -- end
- -- for cur in traverse(head) do
- -- local curtype = node_type[cur]
- -- local curclass, curlevel, origtype = curtype[1], curtype[2], curtype[3]
- -- print('!', node.direct.tonode(cur), curclass, curlevel, origtype)
- -- end
level = parlevel
local curdir = level
function push(n, newlevel)
@@ -561,19 +583,9 @@ function dobidi(head, a, b, c, par_direction)
end
end
end
- -- for cur in traverse(head) do
- -- local curtype = node_type[cur]
- -- local curlevel = curtype and curtype[2]
- -- local dir = not curtype and getdirection(cur)
- -- print('_', node.direct.tonode(cur), curlevel, curtype and curtype[1], dir)
- -- end
- fulltime3 = fulltime3 + gettime() - starttime
return node.direct.tonode(head)
end
-luatexbase.add_to_callback("stop_run", function()
- print('fulltime', fulltime1, fulltime2, fulltime3)
-end, "mytimer")
otffeatures.register {
name = "bidi",
description = "Apply Unicode bidi algorithm",
diff --git a/src/luaotfload-init.lua b/src/luaotfload-init.lua
index 66f83e0..49ec74b 100644
--- a/src/luaotfload-init.lua
+++ b/src/luaotfload-init.lua
@@ -649,7 +649,7 @@ local init_post_install_callbacks = function ()
local handler = nodes.simple_font_handler
local callback = function(head, groupcode, _, _, direction)
if not direction then
- direction = tex.get'textdir'
+ direction = head.dir or tex.textdir
end
head = dobidi(head, nil, nil, nil, direction)
return handler(head, groupcode, nil, nil, direction)
diff --git a/src/luaotfload-bidi.lua b/texmf/tex/luatex/luaotfload/luaotfload-bidi.lua
similarity index 90%
copy from src/luaotfload-bidi.lua
copy to texmf/tex/luatex/luaotfload/luaotfload-bidi.lua
index e8f0374..02d3659 100644
--- a/src/luaotfload-bidi.lua
+++ b/texmf/tex/luatex/luaotfload/luaotfload-bidi.lua
@@ -18,6 +18,8 @@ end
local nodenew = node.direct.new
local nodecopy = node.direct.copy
+local nodeflush = node.direct.flush_node
+local free = node.direct.free
local setsubtype = node.direct.setsubtype
local setchar = node.direct.setchar
local getchar = node.direct.getchar
@@ -361,29 +363,26 @@ local node_class, node_origclass, node_level = {}, {}, {} -- Making these local
-- keys, requiring relativly big allocations
function dobidi(head, a, b, c, par_direction)
head = node.direct.todirect(head)
- -- for cur in traverse(head) do
- -- print(node.direct.tonode(cur))
- -- end
local node_class, node_origclass, node_level = node_class, node_origclass, node_level
local dir_matches = {}
par_direction = par_direction == "TRT" and "R" or "L" -- We hope to only encounter TRT/TLT
local parlevel, level, oldlevel, overwrite, isolate = par_direction == "R" and 1 or 0
level, oldlevel = parlevel, -1
local stack = {}
- local function push(dir, new_overwrite, new_isolate)
+ local function push(dir, new_overwrite)
stack[#stack+1] = {level, overwrite, isolate}
- level, overwrite, isolate = level + (level + dir + 1)%2 + 1, new_overwrite, new_isolate
+ level, overwrite, isolate = level + (level + dir + 1)%2 + 1, new_overwrite, nil
end
local function pop()
local last = stack[#stack]
stack[#stack] = nil
level, overwrite, isolate = last[1], last[2], last[3]
end
- local starttime = gettime()
local isolating_level_runs = {}
local current_run
+ local old_dir
for cur, tcur, scur in traverse(head) do
- local class, curlevel
+ local class, curlevel, isolate_flag
if tcur == glyph_id and bidi_fonts[getfont(cur)] then
class = bidi_classes[getchar(cur)]
if class == "RLE" then
@@ -425,22 +424,24 @@ function dobidi(head, a, b, c, par_direction)
pop()
end
if isolate then
- dir_matches[isolate] = false
- dir_matches[cur] = isolate
+ isolate_flag = isolate
pop()
else
-- Unmatched reset. LuaTeX inserts them sometimes, just
-- dropping them normally works fine. But deleting is
-- difficult here because the loop needs the next pointer.
- -- FIXME: We will leak them for now
+ if old_dir then nodeflush(old_dir) end
head = remove(head, cur)
+ old_dir = cur
+ goto SKIP
end
class = overwrite or "PDI"
else
curlevel = level
dir = dir == 1 and 1 or 0
class = overwrite or (dir == 1 and "LRI" or "RLI")
- push(dir, nil, cur)
+ push(dir, nil)
+ isolate_flag = false
end
elseif tcur == glue_id or tcur == kern_id then -- Not sure about kerns
class = "WS"
@@ -458,15 +459,11 @@ function dobidi(head, a, b, c, par_direction)
current_run[5] = os
current_run = nil
end
- if dir_matches[cur] then
- local beg = dir_matches[cur]
- current_run = dir_matches[beg]
- local remember = {getnext(beg), getprev(cur)}
- dir_matches[cur] = nil
- if getnext(beg) == cur then -- Handle stupid input
- dir_matches[beg] = nil
- else
- dir_matches[beg] = remember
+ if isolate_flag then
+ current_run = isolate_flag
+ local beg = current_run.remember
+ if getnext(beg) ~= cur then -- Handle stupid input
+ dir_matches[beg] = {getnext(beg), getprev(cur)}
setprev(getnext(beg), nil)
setnext(getprev(cur), nil)
setnext(beg, cur)
@@ -477,34 +474,59 @@ function dobidi(head, a, b, c, par_direction)
isolating_level_runs[#isolating_level_runs+1] = current_run
end
end
- if dir_matches[cur] == false then
- dir_matches[cur] = current_run
+ if isolate_flag == false then
+ current_run.remember = cur
+ isolate = current_run
current_run = nil
end
+ ::SKIP::
+ end
+ local t = tail(head)
+ do
+ local tid = getid(t)
+ while t and tid > dir_id and tid ~= glyph_id do t = getprev(t) tid = getid(t) end
+ if not t then return head end -- Everything is discardable, so ignore it
end
- for i = 1,#stack do pop() end
if current_run then
- current_run[3] = tail(head)
+ current_run[3] = t
current_run[5] = (oldlevel > parlevel and oldlevel or parlevel) % 2 == 1 and 'R' or 'L'
-- Should always be level IINM, but let's us the offical check
current_run = nil
end
- fulltime2 = fulltime2 + gettime() - starttime
+ for i = 1,#stack do
+ if isolate then
+ local beg = isolate.remember
+ local n
+ if beg == t then
+ n = getprev(t)
+ if not n then return head end
+ setnext(n, free(t))
+ else
+ dir_matches[beg] = {getnext(beg), t}
+ if old_dir then
+ n = old_dir
+ setdirection(n, getdirection(beg), 1)
+ old_dir = nil
+ else
+ n = nodecopy(beg)
+ setsubtype(n, 1)
+ end
+ node_class[n], node_origclass[n] = "PDI", "PDI"
+ setnext(n, getnext(t))
+ setprev(getnext(beg), nil)
+ setnext(t, nil)
+ setnext(beg, n)
+ setprev(n, beg)
+ end
+ t = n
+ isolate[3], isolate[5] = n, isolate[2] % 2 == 1 and 'R' or 'L'
+ end
+ pop()
+ end
for i = 1, #isolating_level_runs do
local run = isolating_level_runs[i]
do_wni(run[1], run[2], run[3], run[4], run[5], node_class, node_level, node_origclass)
end
- starttime = gettime()
- -- for cur in traverse(head) do
- -- local curtype = node_type[cur]
- -- local curclass, curlevel, origtype = curtype[1], curtype[2], curtype[3]
- -- -- print('?', node.direct.tonode(cur), curclass, curlevel, origtype)
- -- end
- -- for cur in traverse(head) do
- -- local curtype = node_type[cur]
- -- local curclass, curlevel, origtype = curtype[1], curtype[2], curtype[3]
- -- print('!', node.direct.tonode(cur), curclass, curlevel, origtype)
- -- end
level = parlevel
local curdir = level
function push(n, newlevel)
@@ -561,19 +583,9 @@ function dobidi(head, a, b, c, par_direction)
end
end
end
- -- for cur in traverse(head) do
- -- local curtype = node_type[cur]
- -- local curlevel = curtype and curtype[2]
- -- local dir = not curtype and getdirection(cur)
- -- print('_', node.direct.tonode(cur), curlevel, curtype and curtype[1], dir)
- -- end
- fulltime3 = fulltime3 + gettime() - starttime
return node.direct.tonode(head)
end
-luatexbase.add_to_callback("stop_run", function()
- print('fulltime', fulltime1, fulltime2, fulltime3)
-end, "mytimer")
otffeatures.register {
name = "bidi",
description = "Apply Unicode bidi algorithm",
diff --git a/texmf/tex/luatex/luaotfload/luaotfload-init.lua b/texmf/tex/luatex/luaotfload/luaotfload-init.lua
index 66f83e0..49ec74b 100644
--- a/texmf/tex/luatex/luaotfload/luaotfload-init.lua
+++ b/texmf/tex/luatex/luaotfload/luaotfload-init.lua
@@ -649,7 +649,7 @@ local init_post_install_callbacks = function ()
local handler = nodes.simple_font_handler
local callback = function(head, groupcode, _, _, direction)
if not direction then
- direction = tex.get'textdir'
+ direction = head.dir or tex.textdir
end
head = dobidi(head, nil, nil, nil, direction)
return handler(head, groupcode, nil, nil, direction)
More information about the latex3-commits
mailing list