From 430e36b5a723b307678070fd5b8597ab7c57a935 Mon Sep 17 00:00:00 2001 From: Khaled Hosny Date: Wed, 3 Nov 2010 03:45:20 +0200 Subject: Sync with context 2010.11.01 Not tested, yet. --- otfl-font-def.lua | 17 +++--- otfl-font-dum.lua | 175 ++++-------------------------------------------------- otfl-font-map.lua | 12 ++-- otfl-font-otf.lua | 91 ++++++++++++++++++---------- otfl-font-otn.lua | 50 +++++++++------- otfl-font-ott.lua | 21 ++++--- otfl-font-tfm.lua | 8 +-- 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 -- cgit v1.2.3