From d1c8ea4d4e53f7304a768048b1c718a30bd9e7f4 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 8 Jul 2016 08:19:44 +0200 Subject: [fontloader] sync with Context as of 2016-07-14 --- src/fontloader/misc/fontloader-font-ots.lua | 137 ++++++++++++++++------------ 1 file changed, 81 insertions(+), 56 deletions(-) (limited to 'src/fontloader/misc/fontloader-font-ots.lua') diff --git a/src/fontloader/misc/fontloader-font-ots.lua b/src/fontloader/misc/fontloader-font-ots.lua index d63d524..0f38508 100644 --- a/src/fontloader/misc/fontloader-font-ots.lua +++ b/src/fontloader/misc/fontloader-font-ots.lua @@ -134,12 +134,8 @@ local trace_discruns = false registertracker("otf.discruns", function(v local trace_compruns = false registertracker("otf.compruns", function(v) trace_compruns = v end) local trace_testruns = false registertracker("otf.testruns", function(v) trace_testruns = v end) -local quit_on_no_replacement = true -- maybe per font -local zwnjruns = true -local optimizekerns = true - -registerdirective("otf.zwnjruns", function(v) zwnjruns = v end) -registerdirective("otf.chain.quitonnoreplacement",function(value) quit_on_no_replacement = value end) +----- zwnjruns = true registerdirective("otf.zwnjruns", function(v) zwnjruns = v end) +local optimizekerns = true local report_direct = logs.reporter("fonts","otf direct") local report_subchain = logs.reporter("fonts","otf subchain") @@ -239,6 +235,7 @@ local cursonce = true local fonthashes = fonts.hashes local fontdata = fonthashes.identifiers +local fontfeatures = fonthashes.features local otffeatures = fonts.constructors.features.otf local registerotffeature = otffeatures.register @@ -269,16 +266,8 @@ local notmatchreplace = { } local handlers = { } --- helper - -local function isspace(n) - if getid(n) == glue_code then - local w = getfield(n,"width") - if w >= threshold then - return 32 - end - end -end +local isspace = injections.isspace +local getthreshold = injections.getthreshold -- we use this for special testing and documentation @@ -605,7 +594,7 @@ end return head, base end -local function multiple_glyphs(head,start,multiple,ignoremarks) +local function multiple_glyphs(head,start,multiple,ignoremarks,what) local nofmultiples = #multiple if nofmultiples > 0 then resetinjection(start) @@ -613,17 +602,29 @@ local function multiple_glyphs(head,start,multiple,ignoremarks) if nofmultiples > 1 then local sn = getnext(start) for k=2,nofmultiples do --- untested: --- --- while ignoremarks and marks[getchar(sn)] then --- local sn = getnext(sn) --- end + -- untested: + -- + -- while ignoremarks and marks[getchar(sn)] then + -- local sn = getnext(sn) + -- end local n = copy_node(start) -- ignore components resetinjection(n) setchar(n,multiple[k]) insert_node_after(head,start,n) start = n end + if what == true then + -- we're ok + elseif what > 1 then + local m = multiple[nofmultiples] + for i=2,what do + local n = copy_node(start) -- ignore components + resetinjection(n) + setchar(n,m) + insert_node_after(head,start,n) + start = n + end + end end return head, start, true else @@ -705,7 +706,7 @@ function handlers.gsub_multiple(head,start,dataset,sequence,multiple) if trace_multiples then logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple)) end - return multiple_glyphs(head,start,multiple,sequence.flags[1]) + return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1]) end function handlers.gsub_ligature(head,start,dataset,sequence,ligature) @@ -1237,7 +1238,7 @@ function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup if trace_multiples then logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement)) end - return multiple_glyphs(head,start,replacement,sequence.flags[1]) + return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1]) end return head, start, false end @@ -1262,7 +1263,7 @@ function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlooku end local kind = dataset[4] local what = dataset[1] - local value = what == true and tfmdata.shared.features[kind] or what + local value = what == true and tfmdata.shared.features[kind] or what -- todo: optimize in ctx local current = start while current do local currentchar = ischar(current) @@ -2295,16 +2296,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) end -- maybe only if match prev = getprev(prev) - elseif seq[n][32] then + elseif seq[n][32] and isspace(prev,threshold) then n = n - 1 prev = getprev(prev) else match = false break end - elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces - n = n - 1 - prev = getprev(prev) -- was absent else match = false break @@ -2424,15 +2422,13 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) end -- maybe only if match current = getnext(current) - elseif seq[n][32] then -- brrr + elseif seq[n][32] and isspace(current,threshold) then n = n + 1 + current = getnext(current) else match = false break end - elseif seq[n][32] then - n = n + 1 - current = getnext(current) else match = false break @@ -2545,7 +2541,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode) if replacements then head, start, done = reversesub(head,start,last,dataset,sequence,replacements,rlmode) else - done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts + done = true if trace_contexts then logprocess("%s: skipping match",cref(dataset,sequence)) end @@ -2728,10 +2724,10 @@ local function kernrun(disc,k_run,font,attr,...) end end -- - if prev and (pre or replace) and not ischar(prev,font) then + if prev and not ischar(prev,font) then -- and (pre or replace) prev = false end - if next and (post or replace) and not ischar(next,font) then + if next and not ischar(next,font) then -- and (post or replace) next = false end -- @@ -3306,13 +3302,13 @@ local function featuresprocessor(head,font,attr) if nesting == 1 then - currentfont = font - tfmdata = fontdata[font] - descriptions = tfmdata.descriptions - characters = tfmdata.characters - marks = tfmdata.resources.marks - factor = tfmdata.parameters.factor - threshold = tfmdata.parameters.spacing.width or 65536*10 + currentfont = font + tfmdata = fontdata[font] + descriptions = tfmdata.descriptions + characters = tfmdata.characters + marks = tfmdata.resources.marks + threshold, + factor = getthreshold(font) elseif currentfont ~= font then @@ -3371,15 +3367,12 @@ local function featuresprocessor(head,font,attr) local nofsteps = sequence.nofsteps if not steps then -- this permits injection, watch the different arguments - local h, d, ok = handler(head,start,dataset,sequence,nil,nil,nil,0,font,attr) + local h, d, ok = handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr) if ok then success = true if h then head = h end - if d then - start = d - end end elseif typ == "gsub_reversecontextchain" then -- this is a limited case, no special treatments like 'init' etc @@ -3596,12 +3589,29 @@ otf.handlers = handlers -- used in devanagari local setspacekerns = nodes.injections.setspacekerns if not setspacekerns then os.exit() end -function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) - -- if not setspacekerns then - -- setspacekerns = nodes.injections.setspacekerns - -- end - setspacekerns(font,sequence) - return head, start, true +if fontfeatures then + + function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) + local features = fontfeatures[font] + local enabled = features.spacekern == true and features.kern == true + if enabled then + setspacekerns(font,sequence) + end + return head, start, enabled + end + +else -- generic (no hashes) + + function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr) + local shared = fontdata[font].shared + local features = shared and shared.features + local enabled = features and features.spacekern == true and features.kern == true + if enabled then + setspacekerns(font,sequence) + end + return head, start, enabled + end + end local function hasspacekerns(data) @@ -3636,11 +3646,13 @@ otf.readers.registerextender { end } +-- we merge the lookups but we still honor the language / script + local function spaceinitializer(tfmdata,value) -- attr local resources = tfmdata.resources local spacekerns = resources and resources.spacekerns - if spacekerns == nil then - local properties = tfmdata.properties + local properties = tfmdata.properties + if value and spacekerns == nil then if properties and properties.hasspacekerns then local sequences = resources.sequences local left = { } @@ -3653,7 +3665,20 @@ local function spaceinitializer(tfmdata,value) -- attr if steps then local kern = sequence.features.kern if kern then - feat = feat or kern -- or maybe merge + if feat then + for script, languages in next, kern do + local f = feat[k] + if f then + for l in next, languages do + f[l] = true + end + else + feat[script] = languages + end + end + else + feat = kern + end for i=1,#steps do local step = steps[i] local coverage = step.coverage -- cgit v1.2.3