From 08e3b858401b56d97ff101295a3236fc8e0d47ef Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Mon, 29 Dec 2014 23:38:05 +0100
Subject: [fontloader] sync with Context as of 2014-12-29

---
 src/fontloader/misc/fontloader-font-afm.lua |  11 ++-
 src/fontloader/misc/fontloader-font-ini.lua |   2 +-
 src/fontloader/misc/fontloader-font-otf.lua |  24 +++--
 src/fontloader/misc/fontloader-l-file.lua   | 131 +++++++++++++++-------------
 src/fontloader/misc/fontloader-l-io.lua     |   5 --
 src/fontloader/misc/fontloader-l-lua.lua    |  11 +++
 src/fontloader/misc/fontloader-l-table.lua  |  32 ++++---
 src/fontloader/misc/fontloader-util-str.lua |   4 +-
 8 files changed, 127 insertions(+), 93 deletions(-)

(limited to 'src/fontloader/misc')

diff --git a/src/fontloader/misc/fontloader-font-afm.lua b/src/fontloader/misc/fontloader-font-afm.lua
index ca5616a..a96c668 100644
--- a/src/fontloader/misc/fontloader-font-afm.lua
+++ b/src/fontloader/misc/fontloader-font-afm.lua
@@ -48,6 +48,11 @@ local definers           = fonts.definers
 local readers            = fonts.readers
 local constructors       = fonts.constructors
 
+local fontloader         = fontloader
+local font_to_table      = fontloader.to_table
+local open_font          = fontloader.open
+local close_font         = fontloader.close
+
 local afm                = constructors.newhandler("afm")
 local pfb                = constructors.newhandler("pfb")
 
@@ -222,10 +227,10 @@ end
 
 local function get_indexes(data,pfbname)
     data.resources.filename = resolvers.unresolve(pfbname) -- no shortcut
-    local pfbblob = fontloader.open(pfbname)
+    local pfbblob = open_font(pfbname)
     if pfbblob then
         local characters = data.characters
-        local pfbdata = fontloader.to_table(pfbblob)
+        local pfbdata = font_to_table(pfbblob)
         if pfbdata then
             local glyphs = pfbdata.glyphs
             if glyphs then
@@ -251,7 +256,7 @@ local function get_indexes(data,pfbname)
         elseif trace_loading then
             report_afm("no data in pfb file %a",pfbname)
         end
-        fontloader.close(pfbblob)
+        close_font(pfbblob)
     elseif trace_loading then
         report_afm("invalid pfb file %a",pfbname)
     end
diff --git a/src/fontloader/misc/fontloader-font-ini.lua b/src/fontloader/misc/fontloader-font-ini.lua
index 884b224..c547f89 100644
--- a/src/fontloader/misc/fontloader-font-ini.lua
+++ b/src/fontloader/misc/fontloader-font-ini.lua
@@ -29,4 +29,4 @@ fonts.readers       = { }
 fonts.definers      = { methods = { } }
 fonts.loggers       = { register = function() end }
 
-fontloader.totable  = fontloader.to_table
+fontloader.totable  = fontloader.to_table -- not used
diff --git a/src/fontloader/misc/fontloader-font-otf.lua b/src/fontloader/misc/fontloader-font-otf.lua
index 1bb608f..44ad893 100644
--- a/src/fontloader/misc/fontloader-font-otf.lua
+++ b/src/fontloader/misc/fontloader-font-otf.lua
@@ -56,13 +56,14 @@ otf.glists               = { "gsub", "gpos" }
 otf.version              = 2.802 -- beware: also sync font-mis.lua
 otf.cache                = containers.define("fonts", "otf", otf.version, true)
 
-local fontdata           = fonts.hashes.identifiers
-local chardata           = characters and characters.data -- not used
-
+local hashes             = fonts.hashes
 local definers           = fonts.definers
 local readers            = fonts.readers
 local constructors       = fonts.constructors
 
+local fontdata           = hashes     and hashes.identifiers
+local chardata           = characters and characters.data -- not used
+
 local otffeatures        = constructors.newfeatures("otf")
 local registerotffeature = otffeatures.register
 
@@ -84,7 +85,12 @@ local applyruntimefixes  = fonts.treatments and fonts.treatments.applyfixes
 local wildcard           = "*"
 local default            = "dflt"
 
-local fontloaderfields   = fontloader.fields
+local fontloader         = fontloader
+local open_font          = fontloader.open
+local close_font         = fontloader.close
+local font_fields        = fontloader.fields
+local apply_featurefile  = fontloader.apply_featurefile
+
 local mainfields         = nil
 local glyphfields        = nil -- not used yet
 
@@ -137,7 +143,7 @@ local function load_featurefile(raw,featurefile)
         if trace_loading then
             report_otf("using featurefile %a", featurefile)
         end
-        fontloader.apply_featurefile(raw, featurefile)
+        apply_featurefile(raw, featurefile)
     end
 end
 
@@ -437,12 +443,12 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
         report_otf("loading %a, hash %a",filename,hash)
         local fontdata, messages
         if sub then
-            fontdata, messages = fontloader.open(filename,sub)
+            fontdata, messages = open_font(filename,sub)
         else
-            fontdata, messages = fontloader.open(filename)
+            fontdata, messages = open_font(filename)
         end
         if fontdata then
-            mainfields = mainfields or (fontloaderfields and fontloaderfields(fontdata))
+            mainfields = mainfields or (font_fields and font_fields(fontdata))
         end
         if trace_loading and messages and #messages > 0 then
             if type(messages) == "string" then
@@ -526,7 +532,7 @@ function otf.load(filename,sub,featurefile) -- second argument (format) is gone
                 report_otf("preprocessing and caching time %s, packtime %s",
                     elapsedtime(data),packdata and elapsedtime(packtime) or 0)
             end
-            fontloader.close(fontdata) -- free memory
+            close_font(fontdata) -- free memory
             if cleanup > 3 then
                 collectgarbage("collect")
             end
diff --git a/src/fontloader/misc/fontloader-l-file.lua b/src/fontloader/misc/fontloader-l-file.lua
index 2742e99..2c471d7 100644
--- a/src/fontloader/misc/fontloader-l-file.lua
+++ b/src/fontloader/misc/fontloader-l-file.lua
@@ -15,51 +15,53 @@ if not lfs then
     lfs = optionalrequire("lfs")
 end
 
-if not lfs then
-
-    lfs = {
-        getcurrentdir = function()
-            return "."
-        end,
-        attributes = function()
-            return nil
-        end,
-        isfile = function(name)
-            local f = io.open(name,'rb')
-            if f then
-                f:close()
-                return true
-            end
-        end,
-        isdir = function(name)
-            print("you need to load lfs")
-            return false
-        end
-    }
-
-elseif not lfs.isfile then
-
-    local attributes = lfs.attributes
-
-    function lfs.isdir(name)
-        return attributes(name,"mode") == "directory"
-    end
-
-    function lfs.isfile(name)
-        return attributes(name,"mode") == "file"
-    end
-
- -- function lfs.isdir(name)
- --     local a = attributes(name)
- --     return a and a.mode == "directory"
- -- end
-
- -- function lfs.isfile(name)
- --     local a = attributes(name)
- --     return a and a.mode == "file"
- -- end
-
-end
+-- -- see later
+--
+-- if not lfs then
+--
+--     lfs = {
+--         getcurrentdir = function()
+--             return "."
+--         end,
+--         attributes = function()
+--             return nil
+--         end,
+--         isfile = function(name)
+--             local f = io.open(name,'rb')
+--             if f then
+--                 f:close()
+--                 return true
+--             end
+--         end,
+--         isdir = function(name)
+--             print("you need to load lfs")
+--             return false
+--         end
+--     }
+--
+-- elseif not lfs.isfile then
+--
+--     local attributes = lfs.attributes
+--
+--     function lfs.isdir(name)
+--         return attributes(name,"mode") == "directory"
+--     end
+--
+--     function lfs.isfile(name)
+--         return attributes(name,"mode") == "file"
+--     end
+--
+--  -- function lfs.isdir(name)
+--  --     local a = attributes(name)
+--  --     return a and a.mode == "directory"
+--  -- end
+--
+--  -- function lfs.isfile(name)
+--  --     local a = attributes(name)
+--  --     return a and a.mode == "file"
+--  -- end
+--
+-- end
 
 local insert, concat = table.insert, table.concat
 local match, find, gmatch = string.match, string.find, string.gmatch
@@ -72,6 +74,28 @@ local checkedsplit = string.checkedsplit
 
 local P, R, S, C, Cs, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cp, lpeg.Cc, lpeg.Ct
 
+-- better this way:
+
+local tricky     = S("/\\") * P(-1)
+local attributes = lfs.attributes
+
+if sandbox then
+    sandbox.redefine(lfs.isfile,"lfs.isfile")
+    sandbox.redefine(lfs.isdir, "lfs.isdir")
+end
+
+function lfs.isdir(name)
+    if lpegmatch(tricky,name) then
+        return attributes(name,"mode") == "directory"
+    else
+        return attributes(name.."/.","mode") == "directory"
+    end
+end
+
+function lfs.isfile(name)
+    return attributes(name,"mode") == "file"
+end
+
 local colon     = P(":")
 local period    = P(".")
 local periods   = P("..")
@@ -554,23 +578,6 @@ function file.collapsepath(str,anchor) -- anchor: false|nil, true, "."
     end
 end
 
--- better this way:
-
-local tricky     = S("/\\") * P(-1)
-local attributes = lfs.attributes
-
-function lfs.isdir(name)
-    if lpegmatch(tricky,name) then
-        return attributes(name,"mode") == "directory"
-    else
-        return attributes(name.."/.","mode") == "directory"
-    end
-end
-
-function lfs.isfile(name)
-    return attributes(name,"mode") == "file"
-end
-
 -- local function test(str,...)
 --    print(string.format("%-20s %-15s %-30s %-20s",str,file.collapsepath(str),file.collapsepath(str,true),file.collapsepath(str,".")))
 -- end
diff --git a/src/fontloader/misc/fontloader-l-io.lua b/src/fontloader/misc/fontloader-l-io.lua
index 020e811..a91d44d 100644
--- a/src/fontloader/misc/fontloader-l-io.lua
+++ b/src/fontloader/misc/fontloader-l-io.lua
@@ -339,11 +339,6 @@ function io.readstring(f,n,m)
     return str
 end
 
---
-
-if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
-if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
-
 -- This works quite ok:
 --
 -- function io.piped(command,writer)
diff --git a/src/fontloader/misc/fontloader-l-lua.lua b/src/fontloader/misc/fontloader-l-lua.lua
index 9565f48..1a2a987 100644
--- a/src/fontloader/misc/fontloader-l-lua.lua
+++ b/src/fontloader/misc/fontloader-l-lua.lua
@@ -165,3 +165,14 @@ end
 if lua then
     lua.mask = load([[τεχ = 1]]) and "utf" or "ascii"
 end
+
+local flush   = io.flush
+
+if flush then
+
+    local execute = os.execute if execute then function os.execute(...) flush() return execute(...) end end
+    local exec    = os.exec    if exec    then function os.exec   (...) flush() return exec   (...) end end
+    local spawn   = os.spawn   if spawn   then function os.spawn  (...) flush() return spawn  (...) end end
+    local popen   = io.popen   if popen   then function io.popen  (...) flush() return popen  (...) end end
+
+end
diff --git a/src/fontloader/misc/fontloader-l-table.lua b/src/fontloader/misc/fontloader-l-table.lua
index 3eb8b85..97e0441 100644
--- a/src/fontloader/misc/fontloader-l-table.lua
+++ b/src/fontloader/misc/fontloader-l-table.lua
@@ -49,9 +49,19 @@ function table.keys(t)
     end
 end
 
+-- local function compare(a,b)
+--     local ta, tb = type(a), type(b) -- needed, else 11 < 2
+--     if ta == tb then
+--         return a < b
+--     else
+--         return tostring(a) < tostring(b) -- not that efficient
+--     end
+-- end
+
 local function compare(a,b)
-    local ta, tb = type(a), type(b) -- needed, else 11 < 2
-    if ta == tb then
+    local ta = type(a) -- needed, else 11 < 2
+    local tb = type(b) -- needed, else 11 < 2
+    if ta == tb and ta == "number" then
         return a < b
     else
         return tostring(a) < tostring(b) -- not that efficient
@@ -469,7 +479,7 @@ local function do_serialize(root,name,depth,level,indexed)
         end
     end
     -- we could check for k (index) being number (cardinal)
-    if root and next(root) then
+    if root and next(root) ~= nil then
      -- local first, last = nil, 0 -- #root cannot be trusted here (will be ok in 5.2 when ipairs is gone)
      -- if compact then
      --     -- NOT: for k=1,#root do (we need to quit at nil)
@@ -513,7 +523,7 @@ local function do_serialize(root,name,depth,level,indexed)
                         handle(format("%s %q,",depth,v))
                     end
                 elseif tv == "table" then
-                    if not next(v) then
+                    if next(v) == nil then
                         handle(format("%s {},",depth))
                     elseif inline then -- and #t > 0
                         local st = simple_table(v)
@@ -597,7 +607,7 @@ local function do_serialize(root,name,depth,level,indexed)
                     end
                 end
             elseif tv == "table" then
-                if not next(v) then
+                if next(v) == nil then
                     if tk == "number" then
                         if hexify then
                             handle(format("%s [0x%X]={},",depth,k))
@@ -683,7 +693,7 @@ local function do_serialize(root,name,depth,level,indexed)
             --~ end
         end
     end
-   if level > 0 then
+    if level > 0 then
         handle(format("%s},",depth))
     end
 end
@@ -748,7 +758,7 @@ local function serialize(_handle,root,name,specification) -- handle wins
             root._w_h_a_t_e_v_e_r_ = nil
         end
         -- Let's forget about empty tables.
-        if next(root) then
+        if next(root) ~= nil then
             do_serialize(root,name,"",0)
         end
     end
@@ -928,7 +938,7 @@ local function sparse(old,nest,keeptables)
         if not (v == "" or v == false) then
             if nest and type(v) == "table" then
                 v = sparse(v,nest)
-                if keeptables or next(v) then
+                if keeptables or next(v) ~= nil then
                     new[k] = v
                 end
             else
@@ -1066,11 +1076,11 @@ end
 -- slower than #t on indexed tables (#t only returns the size of the numerically indexed slice)
 
 function table.is_empty(t)
-    return not t or not next(t)
+    return not t or next(t) == nil
 end
 
 function table.has_one_entry(t)
-    return t and not next(t,next(t))
+    return t and next(t,next(t)) == nil
 end
 
 -- new
@@ -1157,7 +1167,7 @@ function table.filtered(t,pattern,sort,cmp)
         else
             local n = next(t)
             local function iterator()
-                while n do
+                while n ~= nil do
                     local k = n
                     n = next(t,k)
                     if find(k,pattern) then
diff --git a/src/fontloader/misc/fontloader-util-str.lua b/src/fontloader/misc/fontloader-util-str.lua
index a040b01..a677a82 100644
--- a/src/fontloader/misc/fontloader-util-str.lua
+++ b/src/fontloader/misc/fontloader-util-str.lua
@@ -361,10 +361,10 @@ strings.tracers    = tracedchars
 function string.tracedchar(b)
     -- todo: table
     if type(b) == "number" then
-        return tracedchars[b] or (utfchar(b) .. " (U+" .. format('%05X',b) .. ")")
+        return tracedchars[b] or (utfchar(b) .. " (U+" .. format("%05X",b) .. ")")
     else
         local c = utfbyte(b)
-        return tracedchars[c] or (b .. " (U+" .. format('%05X',c) .. ")")
+        return tracedchars[c] or (b .. " (U+" .. (c and format("%05X",c) or "?????") .. ")")
     end
 end
 
-- 
cgit v1.2.3


From a5998cb3add3331d4e44024bae4ec3c18777ca4f Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Wed, 31 Dec 2014 18:06:47 +0100
Subject: [fontloader] sync with Context as of 2014-12-31

---
 src/fontloader/misc/fontloader-l-file.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/fontloader/misc')

diff --git a/src/fontloader/misc/fontloader-l-file.lua b/src/fontloader/misc/fontloader-l-file.lua
index 2c471d7..7ed6370 100644
--- a/src/fontloader/misc/fontloader-l-file.lua
+++ b/src/fontloader/misc/fontloader-l-file.lua
@@ -157,8 +157,8 @@ file.suffix       = suffixonly
 file.suffixesonly = suffixesonly
 file.suffixes     = suffixesonly
 
-file.dirname    = pathpart   -- obsolete
-file.extname    = suffixonly -- obsolete
+file.dirname      = pathpart   -- obsolete
+file.extname      = suffixonly -- obsolete
 
 -- actually these are schemes
 
-- 
cgit v1.2.3


From f070e8b5b193c0ce686d2e6448b53338a499aecf Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg@phi-gamma.net>
Date: Wed, 11 Mar 2015 07:46:44 +0100
Subject: [fontloader] sync with Context as of 2015-03-11

---
 src/fontloader/misc/fontloader-font-otf.lua  |   2 +-
 src/fontloader/misc/fontloader-font-tfm.lua  |   6 +-
 src/fontloader/misc/fontloader-fonts-cbk.lua |  13 +-
 src/fontloader/misc/fontloader-fonts-inj.lua | 385 +++++++++++++++------------
 src/fontloader/misc/fontloader-fonts-otn.lua |  12 +-
 5 files changed, 230 insertions(+), 188 deletions(-)

(limited to 'src/fontloader/misc')

diff --git a/src/fontloader/misc/fontloader-font-otf.lua b/src/fontloader/misc/fontloader-font-otf.lua
index 44ad893..c7e83a4 100644
--- a/src/fontloader/misc/fontloader-font-otf.lua
+++ b/src/fontloader/misc/fontloader-font-otf.lua
@@ -53,7 +53,7 @@ local otf                = fonts.handlers.otf
 
 otf.glists               = { "gsub", "gpos" }
 
-otf.version              = 2.802 -- beware: also sync font-mis.lua
+otf.version              = 2.803 -- beware: also sync font-mis.lua
 otf.cache                = containers.define("fonts", "otf", otf.version, true)
 
 local hashes             = fonts.hashes
diff --git a/src/fontloader/misc/fontloader-font-tfm.lua b/src/fontloader/misc/fontloader-font-tfm.lua
index 49df94e..ab03788 100644
--- a/src/fontloader/misc/fontloader-font-tfm.lua
+++ b/src/fontloader/misc/fontloader-font-tfm.lua
@@ -72,15 +72,15 @@ local function read_from_tfm(specification)
         properties.filename = specification.filename
         properties.format   = fonts.formats.tfm -- better than nothing
         parameters.size     = size
-        shared.rawdata      = { }
-        shared.features     = features
-        shared.processes    = next(features) and tfm.setfeatures(tfmdata,features) or nil
         --
         tfmdata.properties  = properties
         tfmdata.resources   = resources
         tfmdata.parameters  = parameters
         tfmdata.shared      = shared
         --
+        shared.rawdata      = { }
+        shared.features     = features
+        shared.processes    = next(features) and tfm.setfeatures(tfmdata,features) or nil
         parameters.slant         = parameters.slant          or parameters[1] or 0
         parameters.space         = parameters.space          or parameters[2] or 0
         parameters.space_stretch = parameters.space_stretch  or parameters[3] or 0
diff --git a/src/fontloader/misc/fontloader-fonts-cbk.lua b/src/fontloader/misc/fontloader-fonts-cbk.lua
index 414cafb..ce19c88 100644
--- a/src/fontloader/misc/fontloader-fonts-cbk.lua
+++ b/src/fontloader/misc/fontloader-fonts-cbk.lua
@@ -116,13 +116,14 @@ function nodes.handlers.nodepass(head)
         if basepass and #basefonts > 0 then
             for i=1,#basefonts do
                 local range = basefonts[i]
-                local start, stop = range[1], range[2]
+                local start = range[1]
+                local stop  = range[2]
                 if stop then
-                    ligaturing(start,stop)
-                    kerning(start,stop)
-                else
-                    ligaturing(start)
-                    kerning(start)
+                    start, stop = ligaturing(start,stop)
+                    start, stop = kerning(start,stop)
+                elseif start then
+                    start = ligaturing(start)
+                    start = kerning(start)
                 end
             end
         end
diff --git a/src/fontloader/misc/fontloader-fonts-inj.lua b/src/fontloader/misc/fontloader-fonts-inj.lua
index 3b93382..cb9ed89 100644
--- a/src/fontloader/misc/fontloader-fonts-inj.lua
+++ b/src/fontloader/misc/fontloader-fonts-inj.lua
@@ -14,13 +14,12 @@ if not nodes.properties then return end
 
 local next, rawget = next, rawget
 local utfchar = utf.char
+local fastcopy = table.fastcopy
 
 local trace_injections = false  trackers.register("fonts.injections", function(v) trace_injections = v end)
 
 local report_injections = logs.reporter("fonts","injections")
 
-report_injections("using experimental injector")
-
 local attributes, nodes, node = attributes, nodes, node
 
 fonts                    = fonts
@@ -81,19 +80,42 @@ function injections.resetcounts()
     keepregisteredcounts  = false
 end
 
+-- We need to make sure that a possible metatable will not kick in
+-- unexpectedly.
+
 function injections.reset(n)
-    local p = rawget(properties,start)
-    if p and p.injections then
-        -- todo: decrement counters? tricky as we then need to change the nof* to not increment
-        -- when we change a property
-        p.injections = nil -- should we keep the liga index?
+    local p = rawget(properties,n)
+    if p and rawget(p,"injections") then
+        p.injections = nil
+    end
+end
+
+function injections.copy(target,source)
+    local sp = rawget(properties,source)
+    if sp then
+        local tp = rawget(properties,target)
+        local si = rawget(sp,"injections")
+        if si then
+            si = fastcopy(si)
+            if tp then
+                tp.injections = si
+            else
+                propertydata[target] = {
+                    injections = si,
+                }
+            end
+        else
+            if tp then
+                tp.injections = nil
+            end
+        end
     end
 end
 
 function injections.setligaindex(n,index)
     local p = rawget(properties,n)
     if p then
-        local i = p.injections
+        local i = rawget(p,"injections")
         if i then
             i.ligaindex = index
         else
@@ -113,9 +135,9 @@ end
 function injections.getligaindex(n,default)
     local p = rawget(properties,n)
     if p then
-        p = p.injections
-        if p then
-            return p.ligaindex or default
+        local i = rawget(p,"injections")
+        if i then
+            return i.ligaindex or default
         end
     end
     return default
@@ -134,7 +156,7 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
     --
     local p = rawget(properties,start)
     if p then
-        local i = p.injections
+        local i = rawget(p,"injections")
         if i then
             i.cursiveanchor = true
         else
@@ -151,7 +173,7 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
     end
     local p = rawget(properties,nxt)
     if p then
-        local i = p.injections
+        local i = rawget(p,"injections")
         if i then
             i.cursivex = dx
             i.cursivey = dy
@@ -185,14 +207,16 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,injection) -- r2l
             end
             local p = rawget(properties,current)
             if p then
-                local i = p.injections
+                local i = rawget(p,"injections")
                 if i then
-                    if leftkern ~= 0 or rightkern ~= 0 then
-                        i.leftkern  = i.leftkern  or 0 + leftkern
-                        i.rightkern = i.rightkern or 0 + rightkern
+                    if leftkern ~= 0 then
+                        i.leftkern  = (i.leftkern  or 0) + leftkern
+                    end
+                    if rightkern ~= 0 then
+                        i.rightkern = (i.rightkern or 0) + rightkern
                     end
                     if yoffset ~= 0 then
-                        i.yoffset = i.yoffset or 0 + yoffset
+                        i.yoffset = (i.yoffset or 0) + yoffset
                     end
                 elseif leftkern ~= 0 or rightkern ~= 0 then
                     p.injections = {
@@ -240,9 +264,9 @@ function injections.setkern(current,factor,rlmode,x,injection)
             injection = "injections"
         end
         if p then
-            local i = p[injection]
+            local i = rawget(p,injection)
             if i then
-                i.leftkern = dx + i.leftkern or 0
+                i.leftkern = dx + (i.leftkern or 0)
             else
                 p[injection] = {
                     leftkern = dx,
@@ -270,7 +294,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase) -- ba=basean
     end
     local p = rawget(properties,start)
     if p then
-        local i = p.injections
+        local i = rawget(p,"injections")
         if i then
             i.markx        = dx
             i.marky        = dy
@@ -313,18 +337,18 @@ local function show(n,what,nested,symbol)
     if n then
         local p = rawget(properties,n)
         if p then
-            local p = p[what]
-            if p then
-                local leftkern  = p.leftkern  or 0
-                local rightkern = p.rightkern or 0
-                local yoffset   = p.yoffset   or 0
-                local markx     = p.markx     or 0
-                local marky     = p.marky     or 0
-                local markdir   = p.markdir   or 0
-                local markbase  = p.markbase  or 0 -- will be markbasenode
-                local cursivex  = p.cursivex  or 0
-                local cursivey  = p.cursivey  or 0
-                local ligaindex = p.ligaindex or 0
+            local i = rawget(p,what)
+            if i then
+                local leftkern  = i.leftkern  or 0
+                local rightkern = i.rightkern or 0
+                local yoffset   = i.yoffset   or 0
+                local markx     = i.markx     or 0
+                local marky     = i.marky     or 0
+                local markdir   = i.markdir   or 0
+                local markbase  = i.markbase  or 0 -- will be markbasenode
+                local cursivex  = i.cursivex  or 0
+                local cursivey  = i.cursivey  or 0
+                local ligaindex = i.ligaindex or 0
                 local margin    = nested and 4 or 2
                 --
                 if rightkern ~= 0 or yoffset ~= 0 then
@@ -355,9 +379,9 @@ local function showsub(n,what,where)
     report_injections("end subrun")
 end
 
-local function trace(head)
-    report_injections("begin run: %s kerns, %s pairs, %s marks and %s cursives registered",
-        nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
+local function trace(head,where)
+    report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered",
+        where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
     local n = head
     while n do
         local id = getid(n)
@@ -414,10 +438,6 @@ local function collect_glyphs_1(head)
     local nf, tm = nil, nil
     for n in traverse_id(glyph_code,head) do -- only needed for relevant fonts
         if getsubtype(n) < 256 then
-            local pn = rawget(properties,n)
-            if pn then
-                pn = pn.injections
-            end
             local f = getfont(n)
             if f ~= nf then
                 nf = f
@@ -431,10 +451,14 @@ local function collect_glyphs_1(head)
                 glyphs[nofglyphs] = n
             end
             -- yoffsets can influence curs steps
-            if pn then
-                local yoffset = pn.yoffset
-                if yoffset and yoffset ~= 0 then
-                    setfield(n,"yoffset",yoffset)
+            local p = rawget(properties,n)
+            if p then
+                local i = rawget(p,"injections")
+                if i then
+                    local yoffset = i.yoffset
+                    if yoffset and yoffset ~= 0 then
+                        setfield(n,"yoffset",yoffset)
+                    end
                 end
             end
         end
@@ -470,18 +494,20 @@ local function inject_marks(marks,nofmarks)
         local n = marks[i]
         local pn = rawget(properties,n)
         if pn then
-            pn = pn.injections
-        end
-        if pn then
-         -- local markbase = pn.markbase
-         -- if markbase then
-         --     local p = markanchors[markbase]
+            pn = rawget(pn,"injections")
+            if pn then
                 local p = pn.markbasenode
                 if p then
                     local px = getfield(p,"xoffset")
                     local ox = 0
+                    local rightkern = nil
                     local pp = rawget(properties,p)
-                    local rightkern = pp and pp.rightkern
+                    if pp then
+                        pp = rawget(pp,"injections")
+                        if pp then
+                            rightkern = pp.rightkern
+                        end
+                    end
                     if rightkern then -- x and w ~= 0
                         if pn.markdir < 0 then
                             -- kern(w-x) glyph(p) kern(x) mark(n)
@@ -490,8 +516,13 @@ local function inject_marks(marks,nofmarks)
                         else
                             -- kern(x) glyph(p) kern(w-x) mark(n)
                          -- ox = px - getfield(p,"width") + pn.markx - pp.leftkern
-                            ox = px - pn.markx - pp.leftkern
-                         -- report_injections("l2r case 1: %p",ox)
+                            local leftkern = pp.leftkern
+                            if leftkern then
+                                ox = px - pn.markx
+                            else
+                                ox = px - pn.markx - leftkern
+                            end
+-- report_injections("l2r case 1: %p",ox)
                         end
                     else
                         -- we need to deal with fonts that have marks with width
@@ -525,10 +556,10 @@ local function inject_marks(marks,nofmarks)
                     end
                     setfield(n,"yoffset",oy)
                 else
-                 -- normally this can't happen (only when in trace mode which is a special case anyway)
+                    -- normally this can't happen (only when in trace mode which is a special case anyway)
                  -- report_injections("missing mark anchor %i",pn.markbase or 0)
                 end
-         -- end
+            end
         end
     end
 end
@@ -540,14 +571,14 @@ local function inject_cursives(glyphs,nofglyphs)
         local n = glyphs[i]
         local pn = rawget(properties,n)
         if pn then
-            pn = pn.injections
+            pn = rawget(pn,"injections")
         end
         if pn then
             local cursivex = pn.cursivex
             if cursivex then
                 if cursiveanchor then
                     if cursivex ~= 0 then
-                        pn.leftkern = pn.leftkern or 0 + cursivex
+                        pn.leftkern = (pn.leftkern or 0) + cursivex
                     end
                     if lastanchor then
                         if maxc == 0 then
@@ -622,16 +653,16 @@ local function inject_kerns(head,glyphs,nofglyphs)
         local n = glyphs[i]
         local pn = rawget(properties,n)
         if pn then
-            pn = pn.injections
-        end
-        if pn then
-            local leftkern = pn.leftkern
-            if leftkern ~= 0 then
-                insert_node_before(head,n,newkern(leftkern)) -- type 0/2
-            end
-            local rightkern = pn.rightkern
-            if rightkern and rightkern ~= 0 then
-                insert_node_after(head,n,newkern(rightkern)) -- type 0/2
+            local i = rawget(pn,"injections")
+            if i then
+                local leftkern = i.leftkern
+                if leftkern and leftkern ~= 0 then
+                    insert_node_before(head,n,newkern(leftkern)) -- type 0/2
+                end
+                local rightkern = i.rightkern
+                if rightkern and rightkern ~= 0 then
+                    insert_node_after(head,n,newkern(rightkern)) -- type 0/2
+                end
             end
         end
     end
@@ -640,7 +671,7 @@ end
 local function inject_everything(head,where)
     head = tonut(head)
     if trace_injections then
-        trace(head)
+        trace(head,"everything")
     end
     local glyphs, nofglyphs, marks, nofmarks
     if nofregisteredpairs > 0 then
@@ -652,7 +683,7 @@ local function inject_everything(head,where)
         if nofregisteredcursives > 0 then
             inject_cursives(glyphs,nofglyphs)
         end
-        if nofregisteredmarks > 0 then
+        if nofregisteredmarks > 0 then -- and nofmarks > 0
             inject_marks(marks,nofmarks)
         end
         inject_kerns(head,glyphs,nofglyphs)
@@ -671,7 +702,7 @@ end
 local function inject_kerns_only(head,where)
     head = tonut(head)
     if trace_injections then
-        trace(head)
+        trace(head,"kerns")
     end
     local n = head
     local p = nil
@@ -684,10 +715,10 @@ local function inject_kerns_only(head,where)
                     if p then
                         local d = getfield(p,"post")
                         if d then
-                            local pn = pn.postinjections
-                            if pn then
-                                local leftkern = pn.leftkern
-                                if leftkern ~= 0 then
+                            local i = rawget(pn,"postinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
                                     local t = find_tail(d)
                                     insert_node_after(d,t,newkern(leftkern))
                                 end
@@ -695,28 +726,28 @@ local function inject_kerns_only(head,where)
                         end
                         local d = getfield(p,"replace")
                         if d then
-                            local pn = pn.replaceinjections
-                            if pn then
-                                local leftkern = pn.leftkern
-                                if leftkern ~= 0 then
+                            local i = rawget(pn,"replaceinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
                                     local t = find_tail(d)
                                     insert_node_after(d,t,newkern(leftkern))
                                 end
                             end
                         else
-                            local pn = pn.injections
-                            if pn then
-                                local leftkern = pn.leftkern
-                                if leftkern ~= 0 then
+                            local i = rawget(pn,"injections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
                                     setfield(p,"replace",newkern(leftkern))
                                 end
                             end
                         end
                     else
-                        local pn = pn.injections
-                        if pn then
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
+                        local i = rawget(pn,"injections")
+                        if i then
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
                                 head = insert_node_before(head,n,newkern(leftkern))
                             end
                         end
@@ -734,12 +765,12 @@ local function inject_kerns_only(head,where)
                     if getsubtype(n) < 256 then
                         local pn = rawget(properties,n)
                         if pn then
-                            pn = pn.preinjections
-                        end
-                        if pn then
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
-                                h = insert_node_before(h,n,newkern(leftkern))
+                            local i = rawget(pn,"preinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
+                                    h = insert_node_before(h,n,newkern(leftkern))
+                                end
                             end
                         end
                     else
@@ -757,12 +788,12 @@ local function inject_kerns_only(head,where)
                     if getsubtype(n) < 256 then
                         local pn = rawget(properties,n)
                         if pn then
-                            pn = pn.postinjections
-                        end
-                        if pn then
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
-                                h = insert_node_before(h,n,newkern(leftkern))
+                            local i = rawget(pn,"postinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
+                                    h = insert_node_before(h,n,newkern(leftkern))
+                                end
                             end
                         end
                     else
@@ -780,12 +811,12 @@ local function inject_kerns_only(head,where)
                     if getsubtype(n) < 256 then
                         local pn = rawget(properties,n) -- why can it be empty { }
                         if pn then
-                            pn = pn.replaceinjections
-                        end
-                        if pn then
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
-                                h = insert_node_before(h,n,newkern(leftkern))
+                            local i = rawget(pn,"replaceinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
+                                    h = insert_node_before(h,n,newkern(leftkern))
+                                end
                             end
                         end
                     else
@@ -814,7 +845,7 @@ end
 local function inject_pairs_only(head,where)
     head = tonut(head)
     if trace_injections then
-        trace(head)
+        trace(head,"pairs")
     end
     --
     local n = head
@@ -828,14 +859,14 @@ local function inject_pairs_only(head,where)
                     if p then
                         local d = getfield(p,"post")
                         if d then
-                            local pn = pn.postinjections
-                            if pn then
-                                local leftkern = pn.leftkern
-                                if leftkern ~= 0 then
+                            local i = rawget(pn,"postinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
                                     local t = find_tail(d)
                                     insert_node_after(d,t,newkern(leftkern))
                                 end
-                             -- local rightkern = pn.rightkern
+                             -- local rightkern = i.rightkern
                              -- if rightkern and rightkern ~= 0 then
                              --     insert_node_after(head,n,newkern(rightkern))
                              --     n = getnext(n) -- to be checked
@@ -844,27 +875,27 @@ local function inject_pairs_only(head,where)
                         end
                         local d = getfield(p,"replace")
                         if d then
-                            local pn = pn.replaceinjections
-                            if pn then
-                                local leftkern = pn.leftkern
-                                if leftkern ~= 0 then
+                            local i = rawget(pn,"replaceinjections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
                                     local t = find_tail(d)
                                     insert_node_after(d,t,newkern(leftkern))
                                 end
-                             -- local rightkern = pn.rightkern
+                             -- local rightkern = i.rightkern
                              -- if rightkern and rightkern ~= 0 then
                              --     insert_node_after(head,n,newkern(rightkern))
                              --     n = getnext(n) -- to be checked
                              -- end
                             end
                         else
-                            local pn = pn.injections
-                            if pn then
-                                local leftkern = pn.leftkern
-                                if leftkern ~= 0 then
+                            local i = rawget(pn,"injections")
+                            if i then
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
                                     setfield(p,"replace",newkern(leftkern))
                                 end
-                             -- local rightkern = pn.rightkern
+                             -- local rightkern = i.rightkern
                              -- if rightkern and rightkern ~= 0 then
                              --     insert_node_after(head,n,newkern(rightkern))
                              --     n = getnext(n) -- to be checked
@@ -873,17 +904,17 @@ local function inject_pairs_only(head,where)
                         end
                     else
                         -- this is the most common case
-                        local pn = pn.injections
-                        if pn then
-                            local yoffset = pn.yoffset
+                        local i = rawget(pn,"injections")
+                        if i then
+                            local yoffset = i.yoffset
                             if yoffset and yoffset ~= 0 then
                                 setfield(n,"yoffset",yoffset)
                             end
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
+                            local leftkern = i.leftkern
+                            if leftkern and leftkern ~= 0 then
                                 insert_node_before(head,n,newkern(leftkern))
                             end
-                            local rightkern = pn.rightkern
+                            local rightkern = i.rightkern
                             if rightkern and rightkern ~= 0 then
                                 insert_node_after(head,n,newkern(rightkern))
                                 n = getnext(n) -- to be checked
@@ -901,23 +932,23 @@ local function inject_pairs_only(head,where)
                 local h = d
                 for n in traverse_id(glyph_code,d) do
                     if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            pn = pn.preinjections
-                        end
-                        if pn then
-                            local yoffset = pn.yoffset
-                            if yoffset and yoffset ~= 0 then
-                                setfield(n,"yoffset",yoffset)
-                            end
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
-                                h = insert_node_before(h,n,newkern(leftkern))
-                            end
-                            local rightkern = pn.rightkern
-                            if rightkern and rightkern ~= 0 then
-                                insert_node_after(head,n,newkern(rightkern))
-                                n = getnext(n) -- to be checked
+                        local p = rawget(properties,n)
+                        if p then
+                            local i = rawget(p,"preinjections")
+                            if i then
+                                local yoffset = i.yoffset
+                                if yoffset and yoffset ~= 0 then
+                                    setfield(n,"yoffset",yoffset)
+                                end
+                                local leftkern = i.leftkern
+                                if leftkern ~= 0 then
+                                    h = insert_node_before(h,n,newkern(leftkern))
+                                end
+                                local rightkern = i.rightkern
+                                if rightkern and rightkern ~= 0 then
+                                    insert_node_after(head,n,newkern(rightkern))
+                                    n = getnext(n) -- to be checked
+                                end
                             end
                         end
                     else
@@ -933,23 +964,23 @@ local function inject_pairs_only(head,where)
                 local h = d
                 for n in traverse_id(glyph_code,d) do
                     if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            pn = pn.postinjections
-                        end
-                        if pn then
-                            local yoffset = pn.yoffset
-                            if yoffset and yoffset ~= 0 then
-                                setfield(n,"yoffset",yoffset)
-                            end
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
-                                h = insert_node_before(h,n,newkern(leftkern))
-                            end
-                            local rightkern = pn.rightkern
-                            if rightkern and rightkern ~= 0 then
-                                insert_node_after(head,n,newkern(rightkern))
-                                n = getnext(n) -- to be checked
+                        local p = rawget(properties,n)
+                        if p then
+                            local i = rawget(p,"postinjections")
+                            if i then
+                                local yoffset = i.yoffset
+                                if yoffset and yoffset ~= 0 then
+                                    setfield(n,"yoffset",yoffset)
+                                end
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
+                                    h = insert_node_before(h,n,newkern(leftkern))
+                                end
+                                local rightkern = i.rightkern
+                                if rightkern and rightkern ~= 0 then
+                                    insert_node_after(head,n,newkern(rightkern))
+                                    n = getnext(n) -- to be checked
+                                end
                             end
                         end
                     else
@@ -965,23 +996,23 @@ local function inject_pairs_only(head,where)
                 local h = d
                 for n in traverse_id(glyph_code,d) do
                     if getsubtype(n) < 256 then
-                        local pn = rawget(properties,n)
-                        if pn then
-                            pn = pn.replaceinjections
-                        end
-                        if pn then
-                            local yoffset = pn.yoffset
-                            if yoffset and yoffset ~= 0 then
-                                setfield(n,"yoffset",yoffset)
-                            end
-                            local leftkern = pn.leftkern
-                            if leftkern ~= 0 then
-                                h = insert_node_before(h,n,newkern(leftkern))
-                            end
-                            local rightkern = pn.rightkern
-                            if rightkern and rightkern ~= 0 then
-                                insert_node_after(head,n,newkern(rightkern))
-                                n = getnext(n) -- to be checked
+                        local p = rawget(properties,n)
+                        if p then
+                            local i = rawget(pn,"replaceinjections")
+                            if i then
+                                local yoffset = i.yoffset
+                                if yoffset and yoffset ~= 0 then
+                                    setfield(n,"yoffset",yoffset)
+                                end
+                                local leftkern = i.leftkern
+                                if leftkern and leftkern ~= 0 then
+                                    h = insert_node_before(h,n,newkern(leftkern))
+                                end
+                                local rightkern = i.rightkern
+                                if rightkern and rightkern ~= 0 then
+                                    insert_node_after(head,n,newkern(rightkern))
+                                    n = getnext(n) -- to be checked
+                                end
                             end
                         end
                     else
diff --git a/src/fontloader/misc/fontloader-fonts-otn.lua b/src/fontloader/misc/fontloader-fonts-otn.lua
index 32dc820..3f53078 100644
--- a/src/fontloader/misc/fontloader-fonts-otn.lua
+++ b/src/fontloader/misc/fontloader-fonts-otn.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['font-otn'] = {
     license   = "see context related readme files",
 }
 
+-- todo: looks like we have a leak somewhere (probably in ligatures)
+-- todo: copy attributes to disc
+
 -- this is a context version which can contain experimental code, but when we
 -- have serious patches we also need to change the other two font-otn files
 
@@ -243,6 +246,7 @@ local setcursive         = injections.setcursive
 local setkern            = injections.setkern
 local setpair            = injections.setpair
 local resetinjection     = injections.reset
+local copyinjection      = injections.copy
 local setligaindex       = injections.setligaindex
 local getligaindex       = injections.getligaindex
 
@@ -354,13 +358,19 @@ local function copy_glyph(g) -- next and prev are untouched !
     if components then
         setfield(g,"components",nil)
         local n = copy_node(g)
+        copyinjection(n,g) -- we need to preserve the lig indices
         setfield(g,"components",components)
         return n
     else
-        return copy_node(g)
+        local n = copy_node(g)
+        copyinjection(n,g) -- we need to preserve the lig indices
+        return n
     end
 end
 
+-- 
+
+
 -- start is a mark and we need to keep that one
 
 local function markstoligature(kind,lookupname,head,start,stop,char)
-- 
cgit v1.2.3