[latex3-commits] [git/LaTeX3-latex3-luaotfload] harf-dev: More plugin like (ed59eca)

Marcel Fabian Krüger tex at 2krueger.de
Tue Sep 17 15:00:18 CEST 2019


Repository : https://github.com/latex3/luaotfload
On branch  : harf-dev
Link       : https://github.com/latex3/luaotfload/commit/ed59eca50c52d61588bf1961ff79b891993e28dc

>---------------------------------------------------------------

commit ed59eca50c52d61588bf1961ff79b891993e28dc
Author: Marcel Fabian Krüger <tex at 2krueger.de>
Date:   Tue Sep 17 12:48:07 2019 +0200

    More plugin like


>---------------------------------------------------------------

ed59eca50c52d61588bf1961ff79b891993e28dc
 src/harf/harf-luaotfload.lua |   3 +
 src/harf/harf-node.lua       | 146 ++++++++++---------------------------------
 2 files changed, 36 insertions(+), 113 deletions(-)

diff --git a/src/harf/harf-luaotfload.lua b/src/harf/harf-luaotfload.lua
index 703162b..f5d87e7 100644
--- a/src/harf/harf-luaotfload.lua
+++ b/src/harf/harf-luaotfload.lua
@@ -38,6 +38,9 @@ fonts.readers.harf = function(spec)
   if rawfeatures.language then
     spec.language = harf.Language.new(rawfeatures.language)
   end
+  if rawfeatures.script then
+    spec.script = harf.Script.new(rawfeatures.script)
+  end
   for key, val in next, rawfeatures do
     if key:len() == 4 then
       -- 4-letter options are likely font features, but not always, so we do
diff --git a/src/harf/harf-node.lua b/src/harf/harf-node.lua
index d7f0ee2..abdc9b3 100644
--- a/src/harf/harf-node.lua
+++ b/src/harf/harf-node.lua
@@ -4,7 +4,6 @@ local direct       = node.direct
 local tonode       = direct.tonode
 local todirect     = direct.todirect
 local traverse     = direct.traverse
-local traverseid   = direct.traverse_id
 local insertbefore = direct.insert_before
 local insertafter  = direct.insert_after
 local protectglyph = direct.protect_glyph
@@ -41,6 +40,7 @@ local getsubtype   = direct.getsubtype
 local setsubtype   = direct.setsubtype
 local getwidth     = direct.getwidth
 local setwidth     = direct.setwidth
+local uses_font    = direct.uses_font
 
 local getpre       = function (n) return getfield(n, "pre")        end
 local setpre       = function (n, v)     setfield(n, "pre", v)     end
@@ -63,15 +63,16 @@ local italiccorrection = 3
 local explicitdisc     = 1
 local regulardisc      = 3
 
-local getscript    = hb.unicode.script
-local sc_common    = hb.Script.new("Zyyy")
-local sc_inherited = hb.Script.new("Zinh")
-local sc_unknown   = hb.Script.new("Zzzz")
-local sc_latn      = hb.Script.new("Latn")
-local dir_ltr      = hb.Direction.new("ltr")
-local dir_rtl      = hb.Direction.new("rtl")
-local lang_invalid = hb.Language.new()
-local fl_unsafe    = hb.Buffer.GLYPH_FLAG_UNSAFE_TO_BREAK
+local getscript      = hb.unicode.script
+local sc_common      = hb.Script.new("Zyyy")
+local sc_inherited   = hb.Script.new("Zinh")
+local sc_unknown     = hb.Script.new("Zzzz")
+local sc_latn        = hb.Script.new("Latn")
+local dir_ltr        = hb.Direction.new("ltr")
+local dir_rtl        = hb.Direction.new("rtl")
+local lang_invalid   = hb.Language.new()
+local script_invalid = hb.Script.new()
+local fl_unsafe      = hb.Buffer.GLYPH_FLAG_UNSAFE_TO_BREAK
 
 local p_startactual = "startactualtext"
 local p_endactual   = "endactualtext"
@@ -158,30 +159,30 @@ local process
 
 local trep = hb.texrep
 
-local function itemize(head, direction)
-  -- Collect character properties (font, direction, script) and resolve common
-  -- and inherited scripts. Pre-requisite for itemization into smaller runs.
+local function itemize(head, fontid, direction)
+  local fontdata = font.getfont(fontid)
+  local hbdata   = fontdata and fontdata.hb
+  local spec     = fontdata and fontdata.specification
+  local options  = spec and spec.features.raw
+  local texlig   = options and options.tlig
+
   local props, nodes, codes = {}, {}, {}
-  local dirstack, pairstack = {}, {}
+  local dirstack = {}
   local currdir = direction or "TLT"
-  local currfontid = nil
 
   for n, id, subtype in direct.traverse(head) do
     local code = 0xFFFC -- OBJECT REPLACEMENT CHARACTER
-    local script = sc_common
     local skip = false
 
     if id == glyphid then
-      currfontid = getfont(n)
-      if subtype > 255 then
+      if subtype > 255 or not uses_font(n, fontid) then
         skip = true
       else
         code = getchar(n)
-        script = getscript(code)
       end
     elseif id == glueid and subtype == spaceskip then
       code = 0x0020 -- SPACE
-    elseif id == discid
+    elseif id == discid -- FIXME
       and (subtype == explicitdisc  -- \-
         or subtype == regulardisc)  -- \discretionary
     then
@@ -201,84 +202,37 @@ local function itemize(head, direction)
       currdir = getdir(n)
     end
 
-    local fontdata = currfontid and font.getfont(currfontid)
-    local hbdata   = fontdata and fontdata.hb
-    local spec     = fontdata and fontdata.specification
-    local options  = spec and spec.features.raw
-    local texlig   = options and options.tlig
-    if texlig then
+    if not skip and texlig then
       local replacement = trep[code]
       if replacement then
         code = replacement
       end
     end
 
-    if not hbdata then skip = true end
-
-    -- Resolve common and inherited scripts. Inherited takes the script of the
-    -- previous character. Common almost the same, but we tray to make paired
-    -- characters (e.g. parentheses) to take the same script.
-    if #props > 0 and (script == sc_common or script == sc_inherited) then
-      script = props[#props].script
-      -- Paired punctuation characters
-      if paired_open[code] then
-        table.insert(pairstack, { code, script })
-      elseif paired_close[code] then
-        while #pairstack > 0 do
-          local c = table.remove(pairstack)
-          if c[1] == paired_close[code] then
-            script = c[2]
-            break
-          end
-        end
-      end
-    end
-
-    -- If script is not resolved yet, and the font has a "script" option, use
-    -- it.
-    if (script == sc_common or script == sc_inherited) and hbdata then
-      script = options.script and hb.Script.new(options.script) or script
-    end
-
     codes[#codes + 1] = code
     nodes[#nodes + 1] = n
     props[#props + 1] = {
-      font = currfontid,
       -- XXX handle RTT and LTL.
       dir = currdir == "TRT" and dir_rtl or dir_ltr,
-      script = script,
       skip = skip,
     }
   end
 
-  for i = #props - 1, 1, -1 do
-    -- If script is not resolved yet, use that of the next character.
-    if props[i].script == sc_common or props[i].script == sc_inherited then
-      props[i].script = props[i + 1].script
-    end
-  end
-
-  -- Split into a list of runs, each has the same font, direction and script.
-  -- TODO: itemize by language as well.
+  -- Split into a list of runs, each has the same font and direction
   local runs = {}
-  local currfontid, currdir, currscript, currskip = nil, nil, nil, nil
+  local currdir, currskip
   for i, prop in next, props do
-    local fontid = prop.font
     local dir = prop.dir
-    local script = prop.script
     local skip = prop.skip
 
     -- Start a new run if there is a change in properties.
-    if fontid ~= currfontid or
-       dir ~= currdir or
-       script ~= currscript or
+    if dir ~= currdir or
        skip ~= currskip then
       runs[#runs + 1] = {
         start = i,
         len = 0,
         font = fontid,
         dir = dir,
-        script = script,
         skip = skip,
         nodes = nodes,
         codes = codes,
@@ -287,7 +241,6 @@ local function itemize(head, direction)
 
     runs[#runs].len = runs[#runs].len + 1
 
-    currfontid = fontid
     currdir = dir
     currscript = script
     currskip = skip
@@ -380,8 +333,6 @@ shape = function(run)
   local len = run.len
   local fontid = run.font
   local dir = run.dir
-  local script = run.script
-  local lang = run.lang
   local fordisc = run.fordisc
 
   local fontdata = font.getfont(fontid)
@@ -394,7 +345,8 @@ shape = function(run)
   local hbfont = hbshared.font
   local hbface = hbshared.face
 
-  local lang = lang or options.language or lang_invalid
+  local lang = options.language or lang_invalid
+  local script = options.script or script_invalid
   local shapers = options.shaper and { options.shaper } or {}
 
   local buf = hb.Buffer.new()
@@ -760,9 +712,9 @@ local function tonodes(head, current, run, glyphs, color)
           head, current = removenode(head, current)
         end
         local pre, post, rep = getpre(n), getpost(n), getrep(n)
-        setfield(n, "pre", process(pre, direction))
-        setfield(n, "post", process(post, direction))
-        setfield(n, "replace", process(rep, direction))
+        setfield(n, "pre", process(pre, fontid, direction))
+        setfield(n, "post", process(post, fontid, direction))
+        setfield(n, "replace", process(rep, fontid, direction))
 
         head, current = insertafter(head, current, n)
       else
@@ -774,18 +726,6 @@ local function tonodes(head, current, run, glyphs, color)
   return head, current
 end
 
-local function validate_color(s)
-  local r = tonumber(s:sub(1, 2), 16)
-  local g = tonumber(s:sub(3, 4), 16)
-  local b = tonumber(s:sub(5, 6), 16)
-  if not (r and g and b) then return end
-  if #s == 8 then
-    local a = tonumber(s:sub(7, 8), 16)
-    if not a then return end
-  end
-  return s
-end
-
 local hex_to_rgba do
   local hex = lpeg.R'09' + lpeg.R'AF' + lpeg.R'af'
   local twohex = hex * hex / function(s) return tonumber(s, 16) / 255 end
@@ -822,9 +762,9 @@ local function shape_run(head, current, run)
   return head, current
 end
 
-process = function(head, direction)
+process = function(head, font, direction)
   local newhead, current = nil, nil
-  local runs = itemize(head, direction)
+  local runs = itemize(head, font, direction)
 
   for _, run in next, runs do
     newhead, current = shape_run(newhead, current, run)
@@ -833,26 +773,6 @@ process = function(head, direction)
   return newhead or head
 end
 
-local function process_nodes(head, font, _, direction)
-  local head = todirect(head)
-
-  -- Check if any fonts are loaded by us and then process the whole node list,
-  -- we will take care of skipping fonts we did not load later, otherwise
-  -- return unmodified head.
-  for n in traverseid(glyphid, head) do
-    local fontid = getfont(n)
-    local fontdata = font.getfont(fontid)
-    local hbdata = fontdata and fontdata.hb
-    if hbdata then
-      head = process(head, direction)
-      break
-    end
-  end
-
-  -- Nothing to do; no glyphs or no HarfBuzz fonts.
-  return tonode(head)
-end
-
 local function pdfdirect(data)
   local n = newnode("whatsit", "pdf_literal")
   setfield(n, "mode", directmode)
@@ -940,7 +860,7 @@ local function get_glyph_string(n)
   return props and props[p_string] or nil
 end
 
-fonts.handlers.otf.registerplugin('harf', process_nodes)
+fonts.handlers.otf.registerplugin('harf', process)
 
 return {
   -- process = process_nodes,





More information about the latex3-commits mailing list