[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