From b8b264a266beed6f95e53ea1801bd96f345fc745 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Mon, 18 Apr 2016 20:24:16 +0200
Subject: [fontloader] sync with Context as of 2016-04-18

---
 src/fontloader/misc/fontloader-font-gbn.lua     | 24 ++++++++-
 src/fontloader/misc/fontloader-font-ots.lua     | 60 +++++++++++++++------
 src/fontloader/misc/fontloader-font-oup.lua     | 23 +++++---
 src/fontloader/runtime/fontloader-reference.lua | 71 +++++++++++++++++++++----
 4 files changed, 145 insertions(+), 33 deletions(-)

(limited to 'src')

diff --git a/src/fontloader/misc/fontloader-font-gbn.lua b/src/fontloader/misc/fontloader-font-gbn.lua
index a645a97..daa072b 100644
--- a/src/fontloader/misc/fontloader-font-gbn.lua
+++ b/src/fontloader/misc/fontloader-font-gbn.lua
@@ -20,6 +20,7 @@ local nuts        = nodes.nuts -- context abstraction of direct nodes
 
 local traverse_id = nuts.traverse_id
 local remove_node = nuts.remove
+local free_node   = nuts.free
 
 local glyph_code  = nodes.nodecodes.glyph
 local disc_code   = nodes.nodecodes.disc
@@ -30,11 +31,13 @@ local tonut       = nuts.tonut
 local getfont     = nuts.getfont
 local getchar     = nuts.getchar
 local getid       = nuts.getid
+local getboth     = nuts.getboth
 local getprev     = nuts.getprev
 local getnext     = nuts.getnext
 local getdisc     = nuts.getdisc
 local setchar     = nuts.setchar
 local setlink     = nuts.setlink
+local setprev     = nuts.setprev
 
 -- from now on we apply ligaturing and kerning here because it might interfere with complex
 -- opentype discretionary handling where the base ligature pass expect some weird extra
@@ -136,7 +139,26 @@ function nodes.handlers.nodepass(head)
         end
         if redundant then
             for i=1,#redundant do
-                remove_node(nuthead,redundant[i],true)
+                local r = redundant[i]
+                local p, n = getboth(r)
+                if r == nuthead then
+                    nuthead = n
+                    setprev(n)
+                else
+                    setlink(p,n)
+                end
+                if b > 0 then
+                    for i=1,b do
+                        local bi = basefonts[i]
+                        if r == bi[1] then
+                            bi[1] = n
+                        end
+                        if r == bi[2] then
+                            bi[2] = n
+                        end
+                    end
+                end
+                free_node(r)
             end
         end
         for d in traverse_id(disc_code,nuthead) do
diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua
index 0a438d5..6911872 100644
--- a/src/fontloader/misc/fontloader-font-ots.lua
+++ b/src/fontloader/misc/fontloader-font-ots.lua
@@ -696,6 +696,9 @@ end
 
 function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
     local current   = getnext(start)
+    if not current then
+        return head, start, false, nil
+    end
     local stop      = nil
     local startchar = getchar(start)
     if marks[startchar] then
@@ -756,14 +759,30 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
                 -- kind of weird
                 break
             elseif id == disc_code then
-                if getfield(current,"replace") then
-                    -- this only happens when we didn't normalize ... in a future version we will
-                    -- assume normalization of disc nodes
-                    break
-                else
-                    lastdisc=current
-                    current=getnext(current)
+                -- tricky .. we also need to do pre here
+                local replace = getfield(current,"replace")
+                if replace then
+                    -- of{f-}{}{f}e  o{f-}{}{f}fe  o{-}{}{ff}e (oe and ff ligature)
+                    -- we can end up here when we have a start run .. testruns start at a disc but
+                    -- so here we have the other case: char + disc
+                    while replace do
+                        local char, id = ischar(replace,currentfont)
+                        if char then
+                            local lg = ligature[char] -- can there be multiple in a row? maybe in a bad font
+                            if lg then
+                                ligature = lg
+                                replace  = getnext(replace)
+                            else
+                                return head, start, false, false
+                            end
+                        else
+                            return head, start, false, false
+                        end
+                    end
+                    stop = current
                 end
+                lastdisc = current
+                current  = getnext(current)
             else
                 break
             end
@@ -1287,6 +1306,7 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup
         local nofreplacements = 1
         local skipmark        = currentlookup.flags[1] -- sequence.flags?
         while current do
+            -- todo: ischar ... can there really be disc nodes here?
             local id = getid(current)
             if id == disc_code then
                 if not discfound then
@@ -2761,6 +2781,8 @@ local function kernrun(disc,k_run,font,attr,...)
         next = false
     end
     --
+    -- we need to get rid of this nest mess some day .. has to be done otherwise
+    --
     if pre then
         if k_run(pre,"injections",nil,font,attr,...) then
             done = true
@@ -2768,7 +2790,7 @@ local function kernrun(disc,k_run,font,attr,...)
         if prev then
             local nest = getprev(pre)
             setlink(prev,pre)
-            if k_run(prevmarks,"preinjections",pre,font,attr,...) then -- getnext(pre))
+            if k_run(prevmarks,"preinjections",pre,font,attr,...) then -- or prev?
                 done = true
             end
             setprev(pre,nest)
@@ -2866,7 +2888,7 @@ local function comprun(disc,c_run,...)
         setdisc(disc,pre,post,replace)
     end
     --
-    return getnext(disc), done
+    return getnext(disc), renewed
 end
 
 local function testrun(disc,t_run,c_run,...)
@@ -3006,8 +3028,9 @@ local nesting = 0
 
 local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
     local done  = false
-    local start = sweephead[head]
-    if start then
+    local sweep = sweephead[head]
+    if sweep then
+        start = sweep
         sweephead[head] = nil
     else
         start = head
@@ -3033,8 +3056,11 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
             end
         elseif char == false then
             return head, done
+        elseif sweep then
+            -- else we loose the rest
+            return head, done
         else
-            -- weird
+            -- in disc component
             start = getnext(start)
         end
     end
@@ -3119,8 +3145,9 @@ end
 
 local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
     local done  = false
-    local start = sweephead[head]
-    if start then
+    local sweep = sweephead[head]
+    if sweep then
+        start = sweep
         sweephead[head] = nil
     else
         start = head
@@ -3160,8 +3187,11 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
         elseif char == false then
             -- whatever glyph
             return head, done
+        elseif sweep then
+            -- else we loose the rest
+            return head, done
         else
-            -- very unlikely
+            -- in disc component
             start = getnext(start)
         end
     end
diff --git a/src/fontloader/misc/fontloader-font-oup.lua b/src/fontloader/misc/fontloader-font-oup.lua
index 59530af..7edaaf6 100644
--- a/src/fontloader/misc/fontloader-font-oup.lua
+++ b/src/fontloader/misc/fontloader-font-oup.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['font-oup'] = {
 local next, type = next, type
 local P, R, S = lpeg.P, lpeg.R, lpeg.S
 local lpegmatch = lpeg.match
-local insert, remove, copy = table.insert, table.remove, table.copy
+local insert, remove, copy, unpack = table.insert, table.remove, table.copy, table.unpack
 
 local formatters        = string.formatters
 local sortedkeys        = table.sortedkeys
@@ -737,8 +737,7 @@ local function stripredundant(fontdata)
 end
 
 function readers.getcomponents(fontdata) -- handy for resolving ligatures when names are missing
-    local resources    = fontdata.resources
-    local descriptions = fontdata.descriptions
+    local resources = fontdata.resources
     if resources then
         local sequences = resources.sequences
         if sequences then
@@ -761,7 +760,7 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n
                             end
                         end
                         for i=1,#steps do
-                        -- we actually had/have this in base mode
+                         -- we actually had/have this in base mode
                             local coverage = steps[i].coverage
                             if coverage then
                                 for k, v in next, coverage do
@@ -773,13 +772,25 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n
                 end
             end
             if next(collected) then
+                -- remove self referring
+             -- for k, v in next, collected do
+             --     for i=1,#v do
+             --         local vi = v[i]
+             --         if vi == k then
+             --          -- report("removing self referring ligature @ slot %5X from collected (1)",k)
+             --             collected[k] = nil
+             --         end
+             --     end
+             -- end
                 while true do
                     local done = false
                     for k, v in next, collected do
                         for i=1,#v do
                             local vi = v[i]
                             if vi == k then
+                             -- report("removing self referring ligature @ slot %5X from collected (2)",k)
                                 collected[k] = nil
+                                break
                             else
                                 local c = collected[vi]
                                 if c then
@@ -787,7 +798,7 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n
                                     local t = { }
                                     local n = i - 1
                                     for j=1,n do
-                                        t[j] = t[j]
+                                        t[j] = v[j]
                                     end
                                     for j=1,#c do
                                         n = n + 1
@@ -795,7 +806,7 @@ function readers.getcomponents(fontdata) -- handy for resolving ligatures when n
                                     end
                                     for j=i+1,#v do
                                         n = n + 1
-                                        t[n] = t[j]
+                                        t[n] = v[j]
                                     end
                                     collected[k] = t
                                     break
diff --git a/src/fontloader/runtime/fontloader-reference.lua b/src/fontloader/runtime/fontloader-reference.lua
index 0d22a73..1595733 100644
--- a/src/fontloader/runtime/fontloader-reference.lua
+++ b/src/fontloader/runtime/fontloader-reference.lua
@@ -1,6 +1,6 @@
 -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
 -- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date  : 04/17/16 11:56:26
+-- merge date  : 04/18/16 18:53:40
 
 do -- begin closure to overcome local limits and interference
 
@@ -13503,7 +13503,7 @@ if not modules then modules={} end modules ['font-oup']={
 local next,type=next,type
 local P,R,S=lpeg.P,lpeg.R,lpeg.S
 local lpegmatch=lpeg.match
-local insert,remove,copy=table.insert,table.remove,table.copy
+local insert,remove,copy,unpack=table.insert,table.remove,table.copy,table.unpack
 local formatters=string.formatters
 local sortedkeys=table.sortedkeys
 local sortedhash=table.sortedhash
@@ -14169,7 +14169,6 @@ local function stripredundant(fontdata)
 end
 function readers.getcomponents(fontdata) 
   local resources=fontdata.resources
-  local descriptions=fontdata.descriptions
   if resources then
     local sequences=resources.sequences
     if sequences then
@@ -14210,6 +14209,7 @@ function readers.getcomponents(fontdata)
               local vi=v[i]
               if vi==k then
                 collected[k]=nil
+                break
               else
                 local c=collected[vi]
                 if c then
@@ -14217,7 +14217,7 @@ function readers.getcomponents(fontdata)
                   local t={}
                   local n=i-1
                   for j=1,n do
-                    t[j]=t[j]
+                    t[j]=v[j]
                   end
                   for j=1,#c do
                     n=n+1
@@ -14225,7 +14225,7 @@ function readers.getcomponents(fontdata)
                   end
                   for j=i+1,#v do
                     n=n+1
-                    t[n]=t[j]
+                    t[n]=v[j]
                   end
                   collected[k]=t
                   break
@@ -18678,6 +18678,9 @@ function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
 end
 function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
   local current=getnext(start)
+  if not current then
+    return head,start,false,nil
+  end
   local stop=nil
   local startchar=getchar(start)
   if marks[startchar] then
@@ -18736,6 +18739,24 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
       elseif char==false then
         break
       elseif id==disc_code then
+        local replace=getfield(current,"replace")
+        if replace then
+          while replace do
+            local char,id=ischar(replace,currentfont)
+            if char then
+              local lg=ligature[char] 
+              if lg then
+                ligature=lg
+                replace=getnext(replace)
+              else
+                return head,start,false,false
+              end
+            else
+              return head,start,false,false
+            end
+          end
+          stop=current
+        end
         lastdisc=current
         current=getnext(current)
       else
@@ -20539,7 +20560,7 @@ local function comprun(disc,c_run,...)
   if renewed then
     setdisc(disc,pre,post,replace)
   end
-  return getnext(disc),done
+  return getnext(disc),renewed
 end
 local function testrun(disc,t_run,c_run,...)
   if trace_testruns then
@@ -20605,8 +20626,9 @@ end
 local nesting=0
 local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
   local done=false
-  local start=sweephead[head]
-  if start then
+  local sweep=sweephead[head]
+  if sweep then
+    start=sweep
     sweephead[head]=nil
   else
     start=head
@@ -20632,6 +20654,8 @@ local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlm
       end
     elseif char==false then
       return head,done
+    elseif sweep then
+      return head,done
     else
       start=getnext(start)
     end
@@ -20696,8 +20720,9 @@ local function k_run_single(sub,injection,last,font,attr,lookupcache,step,datase
 end
 local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
   local done=false
-  local start=sweephead[head]
-  if start then
+  local sweep=sweephead[head]
+  if sweep then
+    start=sweep
     sweephead[head]=nil
   else
     start=head
@@ -20734,6 +20759,8 @@ local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlm
       end
     elseif char==false then
       return head,done
+    elseif sweep then
+      return head,done
     else
       start=getnext(start)
     end
@@ -23867,6 +23894,7 @@ local nodes=nodes
 local nuts=nodes.nuts 
 local traverse_id=nuts.traverse_id
 local remove_node=nuts.remove
+local free_node=nuts.free
 local glyph_code=nodes.nodecodes.glyph
 local disc_code=nodes.nodecodes.disc
 local tonode=nuts.tonode
@@ -23874,11 +23902,13 @@ local tonut=nuts.tonut
 local getfont=nuts.getfont
 local getchar=nuts.getchar
 local getid=nuts.getid
+local getboth=nuts.getboth
 local getprev=nuts.getprev
 local getnext=nuts.getnext
 local getdisc=nuts.getdisc
 local setchar=nuts.setchar
 local setlink=nuts.setlink
+local setprev=nuts.setprev
 local n_ligaturing=node.ligaturing
 local n_kerning=node.kerning
 local ligaturing=nuts.ligaturing
@@ -23968,7 +23998,26 @@ function nodes.handlers.nodepass(head)
     end
     if redundant then
       for i=1,#redundant do
-        remove_node(nuthead,redundant[i],true)
+        local r=redundant[i]
+        local p,n=getboth(r)
+        if r==nuthead then
+          nuthead=n
+          setprev(n)
+        else
+          setlink(p,n)
+        end
+        if b>0 then
+          for i=1,b do
+            local bi=basefonts[i]
+            if r==bi[1] then
+              bi[1]=n
+            end
+            if r==bi[2] then
+              bi[2]=n
+            end
+          end
+        end
+        free_node(r)
       end
     end
     for d in traverse_id(disc_code,nuthead) do
-- 
cgit v1.2.3