diff options
| -rw-r--r-- | otfl-font-def.lua | 17 | ||||
| -rw-r--r-- | otfl-font-dum.lua | 175 | ||||
| -rw-r--r-- | otfl-font-map.lua | 12 | ||||
| -rw-r--r-- | otfl-font-otf.lua | 91 | ||||
| -rw-r--r-- | otfl-font-otn.lua | 50 | ||||
| -rw-r--r-- | otfl-font-ott.lua | 21 | ||||
| -rw-r--r-- | otfl-font-tfm.lua | 8 | ||||
| -rw-r--r-- | otfl-node-inj.lua | 14 | 
8 files changed, 141 insertions, 247 deletions
| diff --git a/otfl-font-def.lua b/otfl-font-def.lua index aac69ed..e87fee4 100644 --- a/otfl-font-def.lua +++ b/otfl-font-def.lua @@ -170,14 +170,15 @@ local sortedhashkeys = table.sortedhashkeys  function tfm.hashfeatures(specification)      local features = specification.features      if features then -        local t = { } +        local t, tn = { }, 0          local normal = features.normal          if normal and next(normal) then              local f = sortedhashkeys(normal)              for i=1,#f do                  local v = f[i]                  if v ~= "number" and v ~= "features" then -- i need to figure this out, features -                    t[#t+1] = v .. '=' .. tostring(normal[v]) +                    tn = tn + 1 +                    t[tn] = v .. '=' .. tostring(normal[v])                  end              end          end @@ -186,13 +187,15 @@ function tfm.hashfeatures(specification)              local f = sortedhashkeys(vtf)              for i=1,#f do                  local v = f[i] -                t[#t+1] = v .. '=' .. tostring(vtf[v]) +                tn = tn + 1 +                t[tn] = v .. '=' .. tostring(vtf[v])              end          end ---~ if specification.mathsize then ---~     t[#t+1] = "mathsize=" .. specification.mathsize ---~ end -        if #t > 0 then +    --~ if specification.mathsize then +    --~     tn = tn + 1 +    --~     t[tn] = "mathsize=" .. specification.mathsize +    --~ end +        if tn > 0 then              return concat(t,"+")          end      end diff --git a/otfl-font-dum.lua b/otfl-font-dum.lua index 1577b71..14d155a 100644 --- a/otfl-font-dum.lua +++ b/otfl-font-dum.lua @@ -163,173 +163,20 @@ fonts.protrusions.setups = fonts.protrusions.setups or { }  local setups  = fonts.protrusions.setups --- As this is experimental code, users should not depend on it. The --- implications are still discussed on the ConTeXt Dev List and we're --- not sure yet what exactly the spec is (the next code is tested with --- a gyre font patched by / fea file made by Khaled Hosny). The double --- trick should not be needed it proper hanging punctuation is used in --- which case values < 1 can be used. --- --- preferred (in context, usine vectors): --- --- \definefontfeature[whatever][default][mode=node,protrusion=quality] --- --- using lfbd and rtbd, with possibibility to enable only one side : --- --- \definefontfeature[whocares][default][mode=node,protrusion=yes,  opbd=yes,script=latn] --- \definefontfeature[whocares][default][mode=node,protrusion=right,opbd=yes,script=latn] --- --- idem, using multiplier --- --- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn] --- \definefontfeature[whocares][default][mode=node,protrusion=double,opbd=yes,script=latn] --- --- idem, using named feature file (less frozen): --- --- \definefontfeature[whocares][default][mode=node,protrusion=2,opbd=yes,script=latn,featurefile=texgyrepagella-regularxx.fea] - -local function get_class_and_vector(tfmdata,value,where) -- "expansions" -    local g_where = tfmdata.goodies and tfmdata.goodies[where] -    local f_where = fonts[where] -    local g_classes = g_where and g_where.classes -    local f_classes = f_where and f_where.classes -    local class = (g_classes and g_classes[value]) or (f_classes and f_classes[value]) ---~ print(value,class,f_where,f_classes) -    if class then -        local class_vector = class.vector -        local g_vectors = g_where and g_where.vectors -        local f_vectors = f_where and f_where.vectors -        local vector = (g_vectors and g_vectors[class_vector]) or (f_vectors and f_vectors[class_vector]) -        return class, vector -    end -end - -setups['double'] = { -- for testing opbd -    factor = 2, left = 1, right = 1, -} - -local function map_opbd_onto_protrusion(tfmdata,value,opbd) -    local characters, descriptions = tfmdata.characters, tfmdata.descriptions -    local otfdata = tfmdata.shared.otfdata -    local singles = otfdata.shared.featuredata.gpos_single -    local script, language = tfmdata.script, tfmdata.language -    local done, factor, left, right = false, 1, 1, 1 -    local class = setups[value] -    if class then -        factor = class.factor or 1 -        left   = class.left   or 1 -        right  = class.right  or 1 -    else -        factor = tonumber(value) or 1 -    end -    if opbd ~= "right" then -        local validlookups, lookuplist = fonts.otf.collectlookups(otfdata,"lfbd",script,language) -        if validlookups then -            for i=1,#lookuplist do -                local lookup = lookuplist[i] -                local data = singles[lookup] -                if data then -                    if trace_protrusion then -                        report_fonts("set left protrusion using lfbd lookup '%s'",lookup) -                    end -                    for k, v in next, data do -                    --  local p = - v[3] / descriptions[k].width-- or 1 ~= 0 too but the same -                        local p = - (v[1] / 1000) * factor * left -                        characters[k].left_protruding = p -                        if trace_protrusion then -                            report_protrusions("lfbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," ")) -                        end -                    end -                    done = true -                end -            end -        end -    end -    if opbd ~= "left" then -        local validlookups, lookuplist = fonts.otf.collectlookups(otfdata,"rtbd",script,language) -        if validlookups then -            for i=1,#lookuplist do -                local lookup = lookuplist[i] -                local data = singles[lookup] -                if data then -                    if trace_protrusion then -                        report_fonts("set right protrusion using rtbd lookup '%s'",lookup) -                    end -                    for k, v in next, data do -                    --  local p = v[3] / descriptions[k].width -- or 3 -                        local p = (v[1] / 1000) * factor * right -                        characters[k].right_protruding = p -                        if trace_protrusion then -                            report_protrusions("rtbd -> %s -> 0x%05X (%s) -> %0.03f (%s)",lookup,k,utfchar(k),p,concat(v," ")) -                        end -                    end -                end -                done = true -            end -        end -    end -    tfmdata.auto_protrude = done -end - --- The opbd test is just there because it was discussed on the --- context development list. However, the mentioned fxlbi.otf font --- only has some kerns for digits. So, consider this feature not --- supported till we have a proper test font. -  function fonts.initializers.common.protrusion(tfmdata,value)      if value then -        local opbd = tfmdata.shared.features.opbd -        if opbd then -            -- possible values: left right both yes no (experimental) -            map_opbd_onto_protrusion(tfmdata,value,opbd) -        else -            local class, vector = get_class_and_vector(tfmdata,value,"protrusions") -            if class then -                if vector then -                    local factor = class.factor or 1 -                    local left   = class.left   or 1 -                    local right  = class.right  or 1 -                    if trace_protrusion then -                        report_fonts("set protrusion class %s, vector: %s, factor: %s, left: %s, right: %s", -                            value,class.vector,factor,left,right) -                    end -                    local data = characters.data -                    local emwidth = tfmdata.parameters.quad -                    tfmdata.auto_protrude = true -                    for i, chr in next, tfmdata.characters do -                        local v, pl, pr = vector[i], nil, nil -                        if v then -                            pl, pr = v[1], v[2] -                        else -                            local d = data[i] -                            if d then -                                local s = d.shcode -                                if not s then -                                    -- sorry -                                elseif type(s) == "table" then -                                    local vl, vr = vector[s[1]], vector[s[#s]] -                                    if vl then pl = vl[1] end -                                    if vr then pr = vr[2] end -                                else -                                    v = vector[s] -                                    if v then -                                        pl, pr = v[1], v[2] -                                    end -                                end -                            end -                        end -                        if pl and pl ~= 0 then -                            chr.left_protruding  = left *pl*factor -                        end -                        if pr and pr ~= 0 then -                            chr.right_protruding = right*pr*factor -                        end -                    end -                elseif trace_protrusion then -                    report_fonts("unknown protrusion vector '%s' in class '%s",class.vector,value) +        local setup = setups[value] +        if setup then +            local factor, left, right = setup.factor or 1, setup.left or 1, setup.right or 1 +            local emwidth = tfmdata.parameters.quad +            tfmdata.auto_protrude = true +            for i, chr in next, tfmdata.characters do +                local v, pl, pr = setup[i], nil, nil +                if v then +                    pl, pr = v[1], v[2]                  end -            elseif trace_protrusion then -                report_fonts("unknown protrusion class '%s'",value) +                if pl and pl ~= 0 then chr.left_protruding  = left *pl*factor end +                if pr and pr ~= 0 then chr.right_protruding = right*pr*factor end              end          end      end diff --git a/otfl-font-map.lua b/otfl-font-map.lua index 46e84ad..569f3df 100644 --- a/otfl-font-map.lua +++ b/otfl-font-map.lua @@ -219,21 +219,23 @@ fonts.map.addtounicode = function(data,filename)                          originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1                      end                  else -                    local t = { } +                    local t, n = { }, 0                      for l=1,nplit do                          local base = split[l]                          local u = unicodes[base] or (aglmap and aglmap[base])                          if not u then                              break                          elseif type(u) == "table" then -                            t[#t+1] = u[1] +                            n = n + 1 +                            t[n] = u[1]                          else -                            t[#t+1] = u +                            n = n + 1 +                            t[n] = u                          end                      end -                    if #t == 0 then -- done then +                    if n == 0 then -- done then                          -- nothing -                    elseif #t == 1 then +                    elseif n == 1 then                          originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true                      else                          originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true diff --git a/otfl-font-otf.lua b/otfl-font-otf.lua index 5b788d6..12a489f 100644 --- a/otfl-font-otf.lua +++ b/otfl-font-otf.lua @@ -13,13 +13,13 @@ if not modules then modules = { } end modules ['font-otf'] = {  local utf = unicode.utf8 -local concat, utfbyte = table.concat, utf.byte +local utfbyte = utf.byte  local format, gmatch, gsub, find, match, lower, strip = string.format, string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip  local type, next, tonumber, tostring = type, next, tonumber, tostring  local abs = math.abs  local getn = table.getn  local lpegmatch = lpeg.match -local reverse = table.reverse +local reversed, concat = table.reversed, table.concat  local ioflush = io.flush  local allocate = utilities.storage.allocate @@ -43,7 +43,6 @@ local otf            = fonts.otf  local tfm            = fonts.tfm  local fontdata       = fonts.ids ---local chardata       = characters.data  otf.features         = otf.features         or { }  otf.features.list    = otf.features.list    or { } @@ -57,7 +56,7 @@ local definers       = fonts.definers  otf.glists           = { "gsub", "gpos" } -otf.version          = 2.705 -- beware: also sync font-mis.lua +otf.version          = 2.706 -- beware: also sync font-mis.lua  otf.cache            = containers.define("fonts", "otf", otf.version, true)  local loadmethod     = "table" -- table, mixed, sparse @@ -968,6 +967,7 @@ actions["prepare unicodes"] = function(data,filename,raw)      local luatex = data.luatex      local indices, unicodes, multiples, internals = { }, { }, { }, { }      local mapmap = data.map or raw.map +    local mapenc = nil -- will go away      if not mapmap then          report_otf("no map in %s",filename)          mapmap = { } @@ -977,11 +977,13 @@ actions["prepare unicodes"] = function(data,filename,raw)          mapmap = { }          data.map.map = mapmap      else +        mapenc = mapmap.enc -- will go away          mapmap = mapmap.map      end      local criterium = fonts.privateoffset      local private = criterium      local glyphs = data.glyphs +    -- todo: nofmultiples      for index, glyph in next, glyphs do          if index > 0 then              local name = glyph.name -- really needed ? @@ -1000,41 +1002,68 @@ actions["prepare unicodes"] = function(data,filename,raw)                      indices[unicode] = index                      unicodes[name] = unicode                  end +                -- maybe deal with altuni here in the future but first we need +                -- to encounter a proper font that sets them; we have to wait till +                -- a next luatex binary as currently the unicode numbers can be out +                -- of bounds +                if false then +                    local altuni = glyph.altuni +                    if altuni then +                        local un = { unicodes[name] } +                        for i=1,#altuni do +                            local unicode = altuni[i].unicode +                            multiples[#multiples+1] = name +                            un[i+1] = unicode +                            indices[unicode] = index -- maybe check for duplicates +                        end +                        unicodes[name] = un +                    end +                end              else                  -- message that something is wrong              end          end      end      -- beware: the indices table is used to initialize the tfm table -    for unicode, index in next, mapmap do -        if not internals[index] then -            local name = glyphs[index].name -            if name then -                local un = unicodes[name] -                if not un then -                    unicodes[name] = unicode -- or 0 -                elseif type(un) == "number" then -- tonumber(un) -                    if un ~= unicode then -                        multiples[#multiples+1] = name -                        unicodes[name] = { un, unicode } -                        indices[unicode] = index -                    end -                else -                    local ok = false -                    for u=1,#un do -                        if un[u] == unicode then -                            ok = true -                            break +    local encname = lower(data.enc_name or (mapenc and mapenc[1] and mapenc[1].enc_name) or "") -- mapenc will go away + -- will become: local encname = lower(data.enc_name or "") +    if encname == "" or encname == "unicodebmp" or encname == "unicodefull" then -- maybe find(encname,"unicode") +        if trace_loading then +            report_otf("using extra unicode map") +        end +        -- ok -- we can also consider using the altuni +        for unicode, index in next, mapmap do +            if not internals[index] then +                local name = glyphs[index].name +                if name then +                    local un = unicodes[name] +                    if not un then +                        unicodes[name] = unicode -- or 0 +                    elseif type(un) == "number" then -- tonumber(un) +                        if un ~= unicode then +                            multiples[#multiples+1] = name +                            unicodes[name] = { un, unicode } +                            indices[unicode] = index +                        end +                    else +                        local ok = false +                        for u=1,#un do +                            if un[u] == unicode then +                                ok = true +                                break +                            end +                        end +                        if not ok then +                            multiples[#multiples+1] = name +                            un[#un+1] = unicode +                            indices[unicode] = index                          end -                    end -                    if not ok then -                        multiples[#multiples+1] = name -                        un[#un+1] = unicode -                        indices[unicode] = index                      end                  end              end          end +    else +        report_otf("warning: non unicode map '%s', only using glyph unicode data",encname or "whatever")      end      if trace_loading then          if #multiples > 0 then @@ -1063,7 +1092,7 @@ actions["reorganize lookups"] = function(data,filename,raw)                  for _, vv in next, v.rules do                      local c = vv.coverage                      if c and c.before then -                        c.before = reverse(c.before) +                        c.before = reversed(c.before)                      end                  end              end @@ -1582,8 +1611,8 @@ local function copytotfm(data,cache_id) -- we can save a copy when we reorder th          local glyphs, pfminfo, metadata = data.glyphs or { }, data.pfminfo or { }, data.metadata or { }          local luatex = data.luatex          local unicodes = luatex.unicodes -- names to unicodes -        local indices = luatex.indices        local mode = data.mode or "base" - +        local indices = luatex.indices +        local mode = data.mode or "base"          local characters, parameters, math_parameters, descriptions = { }, { }, { }, { }          local designsize = metadata.designsize or metadata.design_size or 100          if designsize == 0 then diff --git a/otfl-font-otn.lua b/otfl-font-otn.lua index 2bccc3c..ec246d2 100644 --- a/otfl-font-otn.lua +++ b/otfl-font-otn.lua @@ -176,7 +176,7 @@ local zwj      = 0x200D  local wildcard = "*"  local default  = "dflt" -local split_at_space = lpeg.splitters[" "] or lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway +local split_at_space = lpeg.Ct(lpeg.splitat(" ")) -- no trailing or multiple spaces anyway  local nodecodes     = nodes.nodecodes  local whatcodes     = nodes.whatcodes @@ -282,9 +282,9 @@ local function gref(n)          local num, nam = { }, { }          for i=1,#n do              local ni = n[i] -            num[#num+1] = format("U+%04X",ni) -            local dni = descriptions[ni] -            nam[#num] = (dni and dni.name) or "?" +            local di = descriptions[ni] +            num[i] = format("U+%04X",ni) +            nam[i] = di and di.name or "?"          end          return format("%s (%s)",concat(num," "), concat(nam," "))      end @@ -2254,13 +2254,14 @@ otf.features.prepare = { }  local function split(replacement,original,cache,unicodes)      -- we can cache this too, but not the same (although unicode is a unique enough hash) -    local o, t, n = { }, { }, 0 +    local o, t, n, no = { }, { }, 0, 0      for s in gmatch(original,"[^ ]+") do          local us = unicodes[s] +        no = no + 1          if type(us) == "number" then -- tonumber(us) -            o[#o+1] = us +            o[no] = us          else -            o[#o+1] = us[1] +            o[no] = us[1]          end      end      for s in gmatch(replacement,"[^ ]+") do @@ -2277,9 +2278,11 @@ end  local function uncover(covers,result,cache,unicodes)      -- lpeg hardly faster (.005 sec on mk) +    local nofresults = #result      for n=1,#covers do          local c = covers[n]          local cc = cache[c] +        nofresults = nofresults + 1          if not cc then              local t = { }              for s in gmatch(c,"[^ ]+") do @@ -2293,9 +2296,9 @@ local function uncover(covers,result,cache,unicodes)                  end              end              cache[c] = t -            result[#result+1] = t +            result[nofresults] = t          else -            result[#result+1] = cc +            result[nofresults] = cc          end      end  end @@ -2337,16 +2340,17 @@ local function prepare_lookups(tfmdata)          --~ end          end,          multiple = function (p,lookup,glyph,unicode) -            local old, new = unicode, { } +            local old, new, nnew = unicode, { }, 0              local m = multiple[lookup]              if not m then m = { } multiple[lookup] = m end              m[old] = new              for pc in gmatch(p[2],"[^ ]+") do                  local upc = unicodes[pc] +                nnew = nnew + 1                  if type(upc) == "number" then -                    new[#new+1] = upc +                    new[nnew] = upc                  else -                    new[#new+1] = upc[1] +                    new[nnew] = upc[1]                  end              end          --~ if trace_lookups then @@ -2354,16 +2358,17 @@ local function prepare_lookups(tfmdata)          --~ end          end,          alternate = function(p,lookup,glyph,unicode) -            local old, new = unicode, { } +            local old, new, nnew = unicode, { }, 0              local a = alternate[lookup]              if not a then a = { } alternate[lookup] = a end              a[old] = new              for pc in gmatch(p[2],"[^ ]+") do                  local upc = unicodes[pc] +                nnew = nnew + 1                  if type(upc) == "number" then -                    new[#new+1] = upc +                    new[nnew] = upc                  else -                    new[#new+1] = upc[1] +                    new[nnew] = upc[1]                  end              end          --~ if trace_lookups then @@ -2557,7 +2562,7 @@ local function prepare_contextchains(tfmdata)                                  contexts = { }                                  contextchain[lookupname] = contexts                              end -                            local t = { } +                            local t, nt = { }, 0                              for nofrules=1,#rules do -- does #rules>1 happen often?                                  local rule = rules[nofrules]                                  local coverage = rule.coverage @@ -2573,7 +2578,8 @@ local function prepare_contextchains(tfmdata)                                          uncover(after,sequence,cache,unicodes)                                      end                                      if sequence[1] then -                                        t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups } +                                        nt = nt + 1 +                                        t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }                                          for unic, _ in next, sequence[start] do                                              local cu = contexts[unic]                                              if not cu then @@ -2593,7 +2599,7 @@ local function prepare_contextchains(tfmdata)                                  contexts = { }                                  reversecontextchain[lookupname] = contexts                              end -                            local t = { } +                            local t, nt = { }, 0                              for nofrules=1,#rules do                                  local rule = rules[nofrules]                                  local reversecoverage = rule.reversecoverage @@ -2613,7 +2619,8 @@ local function prepare_contextchains(tfmdata)                                      end                                      if sequence[1] then                                          -- this is different from normal coverage, we assume only replacements -                                        t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements } +                                        nt = nt + 1 +                                        t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements }                                          for unic, _ in next, sequence[start] do                                              local cu = contexts[unic]                                              if not cu then @@ -2633,7 +2640,7 @@ local function prepare_contextchains(tfmdata)                                  contexts = { }                                  contextchain[lookupname] = contexts                              end -                            local t = { } +                            local t, nt = { }, 0                              for nofrules=1,#rules do                                  -- nearly the same as coverage so we could as well rename it                                  local rule = rules[nofrules] @@ -2653,7 +2660,8 @@ local function prepare_contextchains(tfmdata)                                          uncover(back,sequence,cache,unicodes)                                      end                                      if sequence[1] then -                                        t[#t+1] = { nofrules, lookuptype, sequence, start, stop, rule.lookups } +                                        nt = nt + 1 +                                        t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups }                                          for unic, _ in next, sequence[start] do                                              local cu = contexts[unic]                                              if not cu then diff --git a/otfl-font-ott.lua b/otfl-font-ott.lua index a5a0df3..ec915b8 100644 --- a/otfl-font-ott.lua +++ b/otfl-font-ott.lua @@ -638,9 +638,18 @@ local baselines = allocate {      ['romn'] = 'Roman baseline'  } -local verbosescripts    = allocate(table.swaphash(scripts  )) -local verboselanguages  = allocate(table.swaphash(languages)) -local verbosefeatures   = allocate(table.swaphash(features )) + +local function swap(h) -- can be a tables.swap when we get a better name +    local r = { } +    for k, v in next, h do +        r[v] = lower(gsub(k," ","")) +    end +    return r +end + +local verbosescripts    = allocate(swap(scripts  )) +local verboselanguages  = allocate(swap(languages)) +local verbosefeatures   = allocate(swap(features ))  tables.scripts          = scripts  tables.languages        = languages @@ -661,12 +670,6 @@ for k, v in next, verbosefeatures do      verbosefeatures[lower(k)] = v  end --- can be sped up by local tables - -function tables.totag(id) -- not used -    return format("%4s",lower(id)) -end -  local function resolve(tab,id)      if tab and id then          id = lower(id) diff --git a/otfl-font-tfm.lua b/otfl-font-tfm.lua index 4d80f07..7a16b28 100644 --- a/otfl-font-tfm.lua +++ b/otfl-font-tfm.lua @@ -564,13 +564,13 @@ function tfm.scale(tfmtable, scaledpoints, relativeid)                          local ivc = vc[i]                          local key = ivc[1]                          if key == "right" then -                            tt[#tt+1] = { key, ivc[2]*hdelta } +                            tt[i] = { key, ivc[2]*hdelta }                          elseif key == "down" then -                            tt[#tt+1] = { key, ivc[2]*vdelta } +                            tt[i] = { key, ivc[2]*vdelta }                          elseif key == "rule" then -                            tt[#tt+1] = { key, ivc[2]*vdelta, ivc[3]*hdelta } +                            tt[i] = { key, ivc[2]*vdelta, ivc[3]*hdelta }                          else -- not comment -                            tt[#tt+1] = ivc -- shared since in cache and untouched +                            tt[i] = ivc -- shared since in cache and untouched                          end                      end                      chr.commands = tt diff --git a/otfl-node-inj.lua b/otfl-node-inj.lua index f576c7e..e4380a4 100644 --- a/otfl-node-inj.lua +++ b/otfl-node-inj.lua @@ -188,12 +188,13 @@ function injections.handler(head,where,keep)              trace(head)          end          -- in the future variant we will not copy items but refs to tables -        local done, ky, rl, valid, cx, wx, mk = false, { }, { }, { }, { }, { }, { } +        local done, ky, rl, valid, cx, wx, mk, nofvalid = false, { }, { }, { }, { }, { }, { }, 0          if has_kerns then -- move outside loop              local nf, tm = nil, nil              for n in traverse_id(glyph_code,head) do                  if n.subtype < 256 then -                    valid[#valid+1] = n +                    nofvalid = nofvalid + 1 +                    valid[nofvalid] = n                      if n.font ~= nf then                          nf = n.font                          tm = fontdata[nf].marks @@ -221,7 +222,8 @@ function injections.handler(head,where,keep)              local nf, tm = nil, nil              for n in traverse_id(glyph_code,head) do                  if n.subtype < 256 then -                    valid[#valid+1] = n +                    nofvalid = nofvalid + 1 +                    valid[nofvalid] = n                      if n.font ~= nf then                          nf = n.font                          tm = fontdata[nf].marks @@ -230,7 +232,7 @@ function injections.handler(head,where,keep)                  end              end          end -        if #valid > 0 then +        if nofvalid > 0 then              -- we can assume done == true because we have cursives and marks              local cx = { }              if has_kerns and next(ky) then @@ -243,7 +245,7 @@ function injections.handler(head,where,keep)                  local p_cursbase, p = nil, nil                  -- since we need valid[n+1] we can also use a "while true do"                  local t, d, maxt = { }, { }, 0 -                for i=1,#valid do -- valid == glyphs +                for i=1,nofvalid do -- valid == glyphs                      local n = valid[i]                      if not mk[n] then                          local n_cursbase = has_attribute(n,cursbase) @@ -307,7 +309,7 @@ function injections.handler(head,where,keep)                  end              end              if has_marks then -                for i=1,#valid do +                for i=1,nofvalid do                      local p = valid[i]                      local p_markbase = has_attribute(p,markbase)                      if p_markbase then | 
