From 58574b14679ae5796ea24a506ba27faf838c10ba Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Mon, 7 Aug 2017 12:17:12 +0200 Subject: 2017-08-07 11:35:00 --- tex/context/base/mkiv/math-noa.lua | 1403 ++++++++++++++++++------------------ 1 file changed, 719 insertions(+), 684 deletions(-) (limited to 'tex/context/base/mkiv/math-noa.lua') diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua index bd1d551e7..317b2b6f1 100644 --- a/tex/context/base/mkiv/math-noa.lua +++ b/tex/context/base/mkiv/math-noa.lua @@ -538,20 +538,20 @@ end do - local a_mathalphabet = privateattribute("mathalphabet") - local a_mathgreek = privateattribute("mathgreek") + local a_mathalphabet = privateattribute("mathalphabet") + local a_mathgreek = privateattribute("mathgreek") - processors.relocate = { } + local relocate = { } + + local remapalphabets = mathematics.remapalphabets + local fallbackstyleattr = mathematics.fallbackstyleattr + local setnodecolor = nodes.tracers.colors.set local function report_remap(tag,id,old,new,extra) report_remapping("remapping %s in font (%s,%s) from %C to %C%s", tag,id,fontdata[id].properties.fontname or "",old,new,extra) end - local remapalphabets = mathematics.remapalphabets - local fallbackstyleattr = mathematics.fallbackstyleattr - local setnodecolor = nodes.tracers.colors.set - local function checked(pointer) local char = getchar(pointer) local font = getfont(pointer) @@ -573,7 +573,7 @@ do end end - processors.relocate[math_char] = function(pointer) + relocate[math_char] = function(pointer) local g = getattr(pointer,a_mathgreek) or 0 local a = getattr(pointer,a_mathalphabet) or 0 local char = getchar(pointer) @@ -640,20 +640,20 @@ do end end - processors.relocate[math_textchar] = function(pointer) + relocate[math_textchar] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:init") end end - processors.relocate[math_delim] = function(pointer) + relocate[math_delim] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:fina") end end function handlers.relocate(head,style,penalties) - processnoads(head,processors.relocate,"relocate") + processnoads(head,relocate,"relocate") return true end @@ -661,32 +661,36 @@ end -- rendering (beware, not exported) -processors.render = { } - -local rendersets = mathematics.renderings.numbers or { } -- store +do -processors.render[math_char] = function(pointer) - local attr = getattr(pointer,a_mathrendering) - if attr and attr > 0 then - local char = getchar(pointer) - local renderset = rendersets[attr] - if renderset then - local newchar = renderset[char] - if newchar then - local font = getfont(pointer) - local characters = fontcharacters[font] - if characters and characters[newchar] then - setchar(pointer,newchar) - setattr(pointer,a_exportstatus,char) + local render = { } + + local rendersets = mathematics.renderings.numbers or { } -- store + + render[math_char] = function(pointer) + local attr = getattr(pointer,a_mathrendering) + if attr and attr > 0 then + local char = getchar(pointer) + local renderset = rendersets[attr] + if renderset then + local newchar = renderset[char] + if newchar then + local font = getfont(pointer) + local characters = fontcharacters[font] + if characters and characters[newchar] then + setchar(pointer,newchar) + setattr(pointer,a_exportstatus,char) + end end end end end -end -function handlers.render(head,style,penalties) - processnoads(head,processors.render,"render") - return true + function handlers.render(head,style,penalties) + processnoads(head,render,"render") + return true + end + end -- some resize options (this works ok because the content is @@ -699,347 +703,361 @@ end -- todo: just replace the character by an ord noad -- and remove the right delimiter as well -local a_mathsize = privateattribute("mathsize") -- this might move into other fence code -local resize = { } -processors.resize = resize +do -resize[math_fence] = function(pointer) - local subtype = getsubtype(pointer) - if subtype == left_fence_code or subtype == right_fence_code then - local a = getattr(pointer,a_mathsize) - if a and a > 0 then - local method, size = div(a,100), a % 100 - setattr(pointer,a_mathsize,0) - local delimiter = getfield(pointer,"delim") - local chr = getfield(delimiter,"small_char") - if chr > 0 then - local fam = getfield(delimiter,"small_fam") - local id = font_of_family(fam) - if id > 0 then - setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method)) + local a_mathsize = privateattribute("mathsize") -- this might move into other fence code + local resize = { } + + resize[math_fence] = function(pointer) + local subtype = getsubtype(pointer) + if subtype == left_fence_code or subtype == right_fence_code then + local a = getattr(pointer,a_mathsize) + if a and a > 0 then + local method, size = div(a,100), a % 100 + setattr(pointer,a_mathsize,0) + local delimiter = getfield(pointer,"delim") + local chr = getfield(delimiter,"small_char") + if chr > 0 then + local fam = getfield(delimiter,"small_fam") + local id = font_of_family(fam) + if id > 0 then + setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method)) + end end end end end -end -function handlers.resize(head,style,penalties) - processnoads(head,resize,"resize") - return true + function handlers.resize(head,style,penalties) + processnoads(head,resize,"resize") + return true + end + end -- still not perfect: -local a_autofence = privateattribute("mathautofence") -local autofences = { } -processors.autofences = autofences -local dummyfencechar = 0x2E - -local function makefence(what,char) - local d = new_delimiter() - local f = new_fence() - if char then - local sym = getnucleus(char) - local chr = getchar(sym) - local fam = getfield(sym,"fam") - if chr == dummyfencechar then - chr = 0 +do + + local a_autofence = privateattribute("mathautofence") + local autofences = { } + local dummyfencechar = 0x2E + + local function makefence(what,char) + local d = new_delimiter() + local f = new_fence() + if char then + local sym = getnucleus(char) + local chr = getchar(sym) + local fam = getfield(sym,"fam") + if chr == dummyfencechar then + chr = 0 + end + setfield(d,"small_char",chr) + setfield(d,"small_fam", fam) + flush_node(sym) end - setfield(d,"small_char",chr) - setfield(d,"small_fam", fam) - flush_node(sym) - end - setsubtype(f,what) - setfield(f,"delim",d) - setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what] - return f -end + setsubtype(f,what) + setfield(f,"delim",d) + setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what] + return f + end -local function makelist(noad,f_o,o_next,c_prev,f_c,middle) - local list = new_submlist() - setlist(list,f_o) - setsubtype(noad,noad_inner) - setnucleus(noad,list) - setlink(f_o,o_next) - setlink(c_prev,f_c) - if middle and next(middle) then - local prev = f_o - local current = o_next - while current ~= f_c do - local m = middle[current] - if m then - local next = getnext(current) - local fence = makefence(middle_fence_code,current) - setnucleus(current) - flush_node(current) - middle[current] = nil - -- replace_node - setlink(prev,fence,next) - prev = fence - current = next - else - prev = current - current = getnext(current) + local function makelist(noad,f_o,o_next,c_prev,f_c,middle) + local list = new_submlist() + setlist(list,f_o) + setsubtype(noad,noad_inner) + setnucleus(noad,list) + setlink(f_o,o_next) + setlink(c_prev,f_c) + if middle and next(middle) then + local prev = f_o + local current = o_next + while current ~= f_c do + local m = middle[current] + if m then + local next = getnext(current) + local fence = makefence(middle_fence_code,current) + setnucleus(current) + flush_node(current) + middle[current] = nil + -- replace_node + setlink(prev,fence,next) + prev = fence + current = next + else + prev = current + current = getnext(current) + end end end end -end -local function convert_both(open,close,middle) - local o_prev, o_next = getboth(open) - local c_prev, c_next = getboth(close) - if o_next == close then - return close - else + local function convert_both(open,close,middle) + local o_prev, o_next = getboth(open) + local c_prev, c_next = getboth(close) + if o_next == close then + return close + else + local f_o = makefence(left_fence_code,open) + local f_c = makefence(right_fence_code,close) + makelist(open,f_o,o_next,c_prev,f_c,middle) + setnucleus(close) + flush_node(close) + if c_next then + setprev(c_next,open) + end + setnext(open,c_next) + return open + end + end + + local function convert_open(open,last,middle) local f_o = makefence(left_fence_code,open) - local f_c = makefence(right_fence_code,close) - makelist(open,f_o,o_next,c_prev,f_c,middle) - setnucleus(close) - flush_node(close) - if c_next then - setprev(c_next,open) + local f_c = makefence(right_fence_code) + local o_prev, o_next = getboth(open) + local l_prev, l_next = getboth(last) + makelist(open,f_o,o_next,last,f_c,middle) + if l_next then + setprev(l_next,open) end - setnext(open,c_next) + setnext(open,l_next) return open end -end - -local function convert_open(open,last,middle) - local f_o = makefence(left_fence_code,open) - local f_c = makefence(right_fence_code) - local o_prev, o_next = getboth(open) - local l_prev, l_next = getboth(last) - makelist(open,f_o,o_next,last,f_c,middle) - if l_next then - setprev(l_next,open) - end - setnext(open,l_next) - return open -end -local function convert_close(close,first,middle) - local f_o = makefence(left_fence_code) - local f_c = makefence(right_fence_code,close) - local c_prev = getprev(close) - makelist(close,f_o,first,c_prev,f_c,middle) - return close -end + local function convert_close(close,first,middle) + local f_o = makefence(left_fence_code) + local f_c = makefence(right_fence_code,close) + local c_prev = getprev(close) + makelist(close,f_o,first,c_prev,f_c,middle) + return close + end -local stacks = setmetatableindex("table") - -local function processfences(pointer,n,parent) - local current = pointer - local last = pointer - local start = pointer - local done = false - local initial = pointer - local stack = nil - local middle = nil -- todo: use properties - while current do - local id = getid(current) - if id == math_noad then - local a = getattr(current,a_autofence) - if a and a > 0 then - local stack = stacks[n] - setattr(current,a_autofence,0) - if a == 1 or (a == 4 and (not stack or #stack == 0)) then - if trace_fences then - report_fences("%2i: pushing open on stack",n) - end - insert(stack,current) - elseif a == 2 or a == 4 then - local open = remove(stack) - if open then + local stacks = setmetatableindex("table") + + local function processfences(pointer,n,parent) + local current = pointer + local last = pointer + local start = pointer + local done = false + local initial = pointer + local stack = nil + local middle = nil -- todo: use properties + while current do + local id = getid(current) + if id == math_noad then + local a = getattr(current,a_autofence) + if a and a > 0 then + local stack = stacks[n] + setattr(current,a_autofence,0) + if a == 1 or (a == 4 and (not stack or #stack == 0)) then if trace_fences then - report_fences("%2i: handling %s, stack depth %i",n,"both",#stack+1) + report_fences("%2i: pushing open on stack",n) + end + insert(stack,current) + elseif a == 2 or a == 4 then + local open = remove(stack) + if open then + if trace_fences then + report_fences("%2i: handling %s, stack depth %i",n,"both",#stack+1) + end + current = convert_both(open,current,middle) + elseif current == start then + -- skip + else + if trace_fences then + report_fences("%2i: handling %s, stack depth %i",n,"close",#stack+1) + end + current = convert_close(current,initial,middle) + if not parent then + initial = current + end end - current = convert_both(open,current,middle) - elseif current == start then - -- skip - else if trace_fences then - report_fences("%2i: handling %s, stack depth %i",n,"close",#stack+1) + report_fences("%2i: popping close from stack",n) end - current = convert_close(current,initial,middle) - if not parent then - initial = current + elseif a == 3 then + if trace_fences then + report_fences("%2i: registering middle",n) + end + if middle then + middle[current] = last + else + middle = { [current] = last } end end - if trace_fences then - report_fences("%2i: popping close from stack",n) - end - elseif a == 3 then - if trace_fences then - report_fences("%2i: registering middle",n) - end - if middle then - middle[current] = last - else - middle = { [current] = last } - end + done = true + else + processstep(current,processfences,n+1,id) end - done = true else - processstep(current,processfences,n+1,id) + -- next at current level + processstep(current,processfences,n,id) end - else - -- next at current level - processstep(current,processfences,n,id) + last = current + current = getnext(current) end - last = current - current = getnext(current) - end - if done then - local stack = stacks[n] - local s = #stack - if s > 0 then - if trace_fences then - report_fences("%2i: handling %s stack levels",n,s) - end - for i=1,s do - local open = remove(stack) + if done then + local stack = stacks[n] + local s = #stack + if s > 0 then if trace_fences then - report_fences("%2i: handling %s, stack depth %i",n,"open",#stack) + report_fences("%2i: handling %s stack levels",n,s) + end + for i=1,s do + local open = remove(stack) + if trace_fences then + report_fences("%2i: handling %s, stack depth %i",n,"open",#stack) + end + last = convert_open(open,last,middle) end - last = convert_open(open,last,middle) end end end -end --- we can have a first changed node .. an option is to have a leading dummy node in math --- lists like the par node as it can save a lot of mess + -- we can have a first changed node .. an option is to have a leading dummy node in math + -- lists like the par node as it can save a lot of mess -local enabled = false + local enabled = false -implement { - name = "enableautofences", - onlyonce = true, - actions = function() - enableaction("math","noads.handlers.autofences") - enabled = true - end -} + implement { + name = "enableautofences", + onlyonce = true, + actions = function() + enableaction("math","noads.handlers.autofences") + enabled = true + end + } -function handlers.autofences(head,style,penalties) - if enabled then -- tex.modes.c_math_fences_auto - -- inspect(nodes.totree(head)) - processfences(tonut(head),1) - -- inspect(nodes.totree(head)) + function handlers.autofences(head,style,penalties) + if enabled then -- tex.modes.c_math_fences_auto + -- inspect(nodes.totree(head)) + processfences(tonut(head),1) + -- inspect(nodes.totree(head)) + end end + end -- normalize scripts -local unscript = { } noads.processors.unscript = unscript -local superscripts = characters.superscripts -local subscripts = characters.subscripts -local fractions = characters.fractions -local replaced = { } - -local function replace(pointer,what,n,parent) - pointer = parent -- we're following the parent list (chars trigger this) - local next = getnext(pointer) - local start_super, stop_super, start_sub, stop_sub - local mode = "unset" - while next and getid(next) == math_noad do - local nextnucleus = getnucleus(next) - if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then - local char = getchar(nextnucleus) - local s = superscripts[char] - if s then - if not start_super then - start_super = next - mode = "super" - elseif mode == "sub" then - break - end - stop_super = next - next = getnext(next) - setchar(nextnucleus,s) - replaced[char] = (replaced[char] or 0) + 1 - if trace_normalizing then - report_normalizing("superscript %C becomes %C",char,s) - end - else - local s = subscripts[char] +do + + local unscript = { } noads.processors.unscript = unscript + local superscripts = characters.superscripts + local subscripts = characters.subscripts + local fractions = characters.fractions + local replaced = { } + + local function replace(pointer,what,n,parent) + pointer = parent -- we're following the parent list (chars trigger this) + local next = getnext(pointer) + local start_super, stop_super, start_sub, stop_sub + local mode = "unset" + while next and getid(next) == math_noad do + local nextnucleus = getnucleus(next) + if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then + local char = getchar(nextnucleus) + local s = superscripts[char] if s then - if not start_sub then - start_sub = next - mode = "sub" - elseif mode == "super" then + if not start_super then + start_super = next + mode = "super" + elseif mode == "sub" then break end - stop_sub = next + stop_super = next next = getnext(next) setchar(nextnucleus,s) replaced[char] = (replaced[char] or 0) + 1 if trace_normalizing then - report_normalizing("subscript %C becomes %C",char,s) + report_normalizing("superscript %C becomes %C",char,s) end else - break + local s = subscripts[char] + if s then + if not start_sub then + start_sub = next + mode = "sub" + elseif mode == "super" then + break + end + stop_sub = next + next = getnext(next) + setchar(nextnucleus,s) + replaced[char] = (replaced[char] or 0) + 1 + if trace_normalizing then + report_normalizing("subscript %C becomes %C",char,s) + end + else + break + end end + else + break end - else - break end - end - if start_super then - if start_super == stop_super then - setsup(pointer,getnucleus(start_super)) - else - local list = new_submlist() -- todo attr - setlist(list,start_super) - setsup(pointer,list) - end - if mode == "super" then - setnext(pointer,getnext(stop_super)) - end - setnext(stop_super) - end - if start_sub then - if start_sub == stop_sub then - setsub(pointer,getnucleus(start_sub)) - else - local list = new_submlist() -- todo attr - setlist(list,start_sub) - setsub(pointer,list) + if start_super then + if start_super == stop_super then + setsup(pointer,getnucleus(start_super)) + else + local list = new_submlist() -- todo attr + setlist(list,start_super) + setsup(pointer,list) + end + if mode == "super" then + setnext(pointer,getnext(stop_super)) + end + setnext(stop_super) end - if mode == "sub" then - setnext(pointer,getnext(stop_sub)) + if start_sub then + if start_sub == stop_sub then + setsub(pointer,getnucleus(start_sub)) + else + local list = new_submlist() -- todo attr + setlist(list,start_sub) + setsub(pointer,list) + end + if mode == "sub" then + setnext(pointer,getnext(stop_sub)) + end + setnext(stop_sub) end - setnext(stop_sub) + -- we could return stop end - -- we could return stop -end -unscript[math_char] = replace -- not noads as we need to recurse + unscript[math_char] = replace -- not noads as we need to recurse + + function handlers.unscript(head,style,penalties) + processnoads(head,unscript,"unscript") + -- processnoads(head,checkers,"checkers") + return true + end -function handlers.unscript(head,style,penalties) - processnoads(head,unscript,"unscript") --- processnoads(head,checkers,"checkers") - return true end -local function collected(list) - if list and next(list) then - local n, t = 0, { } - for k, v in sortedhash(list) do - n = n + v - t[#t+1] = formatters["%C"](k) +do + + local function collected(list) + if list and next(list) then + local n, t = 0, { } + for k, v in sortedhash(list) do + n = n + v + t[#t+1] = formatters["%C"](k) + end + return formatters["% t (n=%s)"](t,n) end - return formatters["% t (n=%s)"](t,n) end -end -statistics.register("math script replacements", function() - return collected(replaced) -end) + statistics.register("math script replacements", function() + return collected(replaced) + end) -statistics.register("unknown math characters", function() - return collected(unknowns) -end) + statistics.register("unknown math characters", function() + return collected(unknowns) + end) + +end -- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$) -- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$) @@ -1083,7 +1101,7 @@ do alternates = alternates, registered = registered, presets = { }, -hashes = setmetatableindex("table") + hashes = setmetatableindex("table") } resources.mathalternates = mathalternates end @@ -1262,67 +1280,59 @@ end -- some juggling that we want to avoid but we need to do something here (in fact, we could -- better fix the width of the character -local a_mathitalics = privateattribute("mathitalics") +do -local italics = { } -local default_factor = 1/20 + local a_mathitalics = privateattribute("mathitalics") -local setcolor = nodes.tracers.colors.set -local resetcolor = nodes.tracers.colors.reset -local italic_kern = new_kern + local italics = { } + local default_factor = 1/20 -local c_positive_d = "trace:dg" -local c_negative_d = "trace:dr" + local setcolor = nodes.tracers.colors.set + local resetcolor = nodes.tracers.colors.reset + local italic_kern = new_kern -local function insert_kern(current,kern) - local sub = new_submlist() - local noad = new_noad() - setlist(sub,kern) - setnext(kern,noad) - setnucleus(noad,current) - return sub -end + local c_positive_d = "trace:dg" + local c_negative_d = "trace:dr" -registertracker("math.italics.visualize", function(v) - if v then - italic_kern = function(k) - local n = new_kern(k) - set_visual(n,"italic") - return n - end - else - italic_kern = new_kern + local function insert_kern(current,kern) + local sub = new_submlist() + local noad = new_noad() + setlist(sub,kern) + setnext(kern,noad) + setnucleus(noad,current) + return sub end -end) -local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex) + registertracker("math.italics.visualize", function(v) + if v then + italic_kern = function(k) + local n = new_kern(k) + set_visual(n,"italic") + return n + end + else + italic_kern = new_kern + end + end) - local visual = chardata[char].visual + local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex) - if method == 1 then - -- check on state - local italics = fontitalics[font] - if italics then - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual + local visual = chardata[char].visual + + if method == 1 then + -- check on state + local italics = fontitalics[font] + if italics then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end end end - end - elseif method == 2 then - -- no check - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual - end - end - elseif method == 3 then - -- check on visual - if visual == "it" or visual == "bi" then + elseif method == 2 then + -- no check local character = fontcharacters[font][char] if character then local correction = character.italic @@ -1330,109 +1340,121 @@ local function getcorrection(method,font,char) -- -- or character.italic -- (thi return correction, visual end end - end - elseif method == 4 then - -- combination of 1 and 3 - local italics = fontitalics[font] - if italics and (visual == "it" or visual == "bi") then - local character = fontcharacters[font][char] - if character then - local correction = character.italic - if correction and correction ~= 0 then - return correction, visual + elseif method == 3 then + -- check on visual + if visual == "it" or visual == "bi" then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + elseif method == 4 then + -- combination of 1 and 3 + local italics = fontitalics[font] + if italics and (visual == "it" or visual == "bi") then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end end end end - end -end + end -italics[math_char] = function(pointer,what,n,parent) - local method = getattr(pointer,a_mathitalics) - if method and method > 0 and method < 100 then - local char = getchar(pointer) - local font = getfont(pointer) - local correction, visual = getcorrection(method,font,char) - if correction and correction ~= 0 then - local next_noad = getnext(parent) - if not next_noad then - if n == 1 then - -- only at the outer level .. will become an option (always,endonly,none) - if trace_italics then - report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char) - end - if correction > 0 then - correction = correction + 100 - else - correction = correction - 100 + italics[math_char] = function(pointer,what,n,parent) + local method = getattr(pointer,a_mathitalics) + if method and method > 0 and method < 100 then + local char = getchar(pointer) + local font = getfont(pointer) + local correction, visual = getcorrection(method,font,char) + if correction and correction ~= 0 then + local next_noad = getnext(parent) + if not next_noad then + if n == 1 then + -- only at the outer level .. will become an option (always,endonly,none) + if trace_italics then + report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char) + end + if correction > 0 then + correction = correction + 100 + else + correction = correction - 100 + end + setattr(pointer,a_mathitalics,correction) + setattr(parent,a_mathitalics,correction) end - setattr(pointer,a_mathitalics,correction) - setattr(parent,a_mathitalics,correction) end end end end -end -function handlers.italics(head,style,penalties) - processnoads(head,italics,"italics") - return true -end + function handlers.italics(head,style,penalties) + processnoads(head,italics,"italics") + return true + end -local enable + local enable -enable = function() - enableaction("math", "noads.handlers.italics") - if trace_italics then - report_italics("enabling math italics") + enable = function() + enableaction("math", "noads.handlers.italics") + if trace_italics then + report_italics("enabling math italics") + end + -- we enable math (unless already enabled elsewhere) + typesetters.italics.enablemath() + enable = false end - -- we enable math (unless already enabled elsewhere) - typesetters.italics.enablemath() - enable = false -end --- best do this only on math mode (less overhead) + -- best do this only on math mode (less overhead) -function mathematics.setitalics(name) - if enable then - enable() + function mathematics.setitalics(name) + if enable then + enable() + end + texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none end - texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none -end -function mathematics.getitalics(name) - if enable then - enable() + function mathematics.getitalics(name) + if enable then + enable() + end + context(name and name ~= v_reset and tonumber(name) or unsetvalue) end - context(name and name ~= v_reset and tonumber(name) or unsetvalue) -end -function mathematics.resetitalics() - texsetattribute(a_mathitalics,unsetvalue) -end + function mathematics.resetitalics() + texsetattribute(a_mathitalics,unsetvalue) + end -implement { - name = "initializemathitalics", - actions = enable, - onlyonce = true, -} + implement { + name = "initializemathitalics", + actions = enable, + onlyonce = true, + } -implement { - name = "setmathitalics", - actions = mathematics.setitalics, - arguments = "string", -} + implement { + name = "setmathitalics", + actions = mathematics.setitalics, + arguments = "string", + } -implement { - name = "getmathitalics", - actions = mathematics.getitalics, - arguments = "string", -} + implement { + name = "getmathitalics", + actions = mathematics.getitalics, + arguments = "string", + } -implement { - name = "resetmathitalics", - actions = mathematics.resetitalics -} + implement { + name = "resetmathitalics", + actions = mathematics.resetitalics + } + +end do @@ -1512,290 +1534,301 @@ end -- primes and such -local collapse = { } processors.collapse = collapse - -local mathpairs = characters.mathpairs -- next will move to char-def - --- I should redo this: ligatures but only when attribute. Adn then the prime anchoring will --- be the only one left. Then the mathpairs definitions might go from char-def to here. - --- 0x02B9 modifier - --- mathpairs[0x2032] = { [0x2032] = 0x2033, [0x2033] = 0x2034, [0x2034] = 0x2057 } -- (prime,prime) (prime,doubleprime) (prime,tripleprime) --- mathpairs[0x2033] = { [0x2032] = 0x2034, [0x2033] = 0x2057 } -- (doubleprime,prime) (doubleprime,doubleprime) --- mathpairs[0x2034] = { [0x2032] = 0x2057 } -- (tripleprime,prime) +do --- mathpairs[0x2035] = { [0x2035] = 0x2036, [0x2036] = 0x2037 } -- (reversedprime,reversedprime) (reversedprime,doublereversedprime) --- mathpairs[0x2036] = { [0x2035] = 0x2037 } -- (doublereversedprime,reversedprime) + -- is validpair stil needed? + + local collapse = { } + local mathlists = characters.mathlists + local validpair = { + [noad_ord] = true, + [noad_rel] = true, + [noad_bin] = true, -- new + [noad_open] = true, -- new + [noad_close] = true, -- new + [noad_punct] = true, -- new + [noad_opdisplaylimits] = true, + [noad_oplimits] = true, + [noad_opnolimits] = true, + } --- mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D } -- integrals --- mathpairs[0x222C] = { [0x222B] = 0x222D } + local reported = setmetatableindex("table") + + collapse[math_char] = function(pointer,what,n,parent) + + if parent and mathlists[getchar(pointer)] then + local found, last, lucleus, lsup, lsub + local tree = mathlists + local current = parent + while current and validpair[getsubtype(current)] do + local nucleus = getnucleus(current) -- == pointer + local sub = getsub(current) + local sup = getsup(current) + local char = getchar(nucleus) + if char then + local match = tree[char] + if match then + local ligature = match.ligature + if ligature then + found = ligature + last = current + lucleus = nucleus + lsup = sup + lsub = sub + end + tree = match + if sub or sup then + break + else + current = getnext(current) + end + else + break + end + else + break + end + end + if found and last and lucleus then + local id = getfont(lucleus) + local characters = fontcharacters[id] + local replace = characters and characters[found] + if not replace then + if not reported[id][found] then + reported[id][found] = true + report_collapsing("missing ligature %C",found) + end + elseif trace_collapsing then + report_collapsing("creating ligature %C",found) + end + setchar(pointer,found) + local l = getnext(last) + local c = getnext(parent) + if lsub then + setsub(parent,lsub) + setsub(last) + end + if lsup then + setsup(parent,lsup) + setsup(last) + end + while c ~= l do + local n = getnext(c) + flush_node(c) + c = n + end + setlink(parent,l) + end + end + end --- mathpairs[0x007C] = { [0x007C] = 0x2016, [0x2016] = 0x2980 } -- bar+bar=double bar+double=triple --- mathpairs[0x2016] = { [0x007C] = 0x2980, [0x02B9] = 0x2016 } -- double+bar=triple + function noads.handlers.collapse(head,style,penalties) + processnoads(head,collapse,"collapse") + return true + end -local movesub = { - -- primes - [0x2032] = 0xFE932, - [0x2033] = 0xFE933, - [0x2034] = 0xFE934, - [0x2057] = 0xFE957, - -- reverse primes - [0x2035] = 0xFE935, - [0x2036] = 0xFE936, - [0x2037] = 0xFE937, -} +end -mathematics.virtualize(movesub) - --- local movesub = { --- -- primes --- [0x2032] = 0x2032, --- [0x2033] = 0x2033, --- [0x2034] = 0x2034, --- [0x2057] = 0x2057, --- -- reverse primes --- [0x2035] = 0x2035, --- [0x2036] = 0x2036, --- [0x2037] = 0x2037, --- } +do + -- inner under over vcenter + + local fixscripts = { } + local movesub = { + -- primes + [0x2032] = 0xFE932, + [0x2033] = 0xFE933, + [0x2034] = 0xFE934, + [0x2057] = 0xFE957, + -- reverse primes + [0x2035] = 0xFE935, + [0x2036] = 0xFE936, + [0x2037] = 0xFE937, + } --- inner under over vcenter - -local validpair = { - [noad_ord] = true, - [noad_rel] = true, - [noad_bin] = true, -- new - [noad_open] = true, -- new - [noad_close] = true, -- new - [noad_punct] = true, -- new - [noad_opdisplaylimits] = true, - [noad_oplimits] = true, - [noad_opnolimits] = true, -} + mathematics.virtualize(movesub) -local options_supported = tokens.defined("Unosuperscript") + local options_supported = tokens.defined("Unosuperscript") -local function fixsupscript(parent,current,current_char,new_char) - if new_char ~= current_char and new_char ~= true then - setchar(current,new_char) - if trace_collapsing then - report_collapsing("fixing subscript, replacing supscript %U by %U",current_char,new_char) + local function fixsupscript(parent,current,current_char,new_char) + if new_char ~= current_char and new_char ~= true then + setchar(current,new_char) + if trace_collapsing then + report_collapsing("fixing subscript, replacing supscript %U by %U",current_char,new_char) + end + else + if trace_collapsing then + report_collapsing("fixing subscript, supscript %U",current_char) + end end - else - if trace_collapsing then - report_collapsing("fixing subscript, supscript %U",current_char) + if options_supported then + setfield(parent,"options",0x08+0x22) end end - if options_supported then - setfield(parent,"options",0x08+0x22) - end -end -local function movesubscript(parent,current_nucleus,current_char,new_char) - local prev = getprev(parent) - if prev and getid(prev) == math_noad then - local psup = getsup(prev) - local psub = getsub(prev) - if not psup and not psub then - -- {f} {'}_n => f_n^' - fixsupscript(prev,current_nucleus,current_char,new_char) - local nucleus = getnucleus(parent) - local sub = getsub(parent) - setsup(prev,nucleus) - setsub(prev,sub) - local dummy = copy_node(nucleus) - setchar(dummy,0) - setnucleus(parent,dummy) - setsub(parent) - elseif not psup then - -- {f} {'}_n => f_n^' - fixsupscript(prev,current_nucleus,current_char,new_char) - local nucleus = getnucleus(parent) - setsup(prev,nucleus) - local dummy = copy_node(nucleus) - setchar(dummy,0) - setnucleus(parent,dummy) + local function movesubscript(parent,current_nucleus,current_char,new_char) + local prev = getprev(parent) + if prev and getid(prev) == math_noad then + local psup = getsup(prev) + local psub = getsub(prev) + if not psup and not psub then + -- {f} {'}_n => f_n^' + fixsupscript(prev,current_nucleus,current_char,new_char) + local nucleus = getnucleus(parent) + local sub = getsub(parent) + setsup(prev,nucleus) + setsub(prev,sub) + local dummy = copy_node(nucleus) + setchar(dummy,0) + setnucleus(parent,dummy) + setsub(parent) + elseif not psup then + -- {f} {'}_n => f_n^' + fixsupscript(prev,current_nucleus,current_char,new_char) + local nucleus = getnucleus(parent) + setsup(prev,nucleus) + local dummy = copy_node(nucleus) + setchar(dummy,0) + setnucleus(parent,dummy) + end end end -end --- this is not that efficient as we are actually doing kind of ligatures - -local function collapsepair(pointer,what,n,parent,nested) -- todo: switch to turn in on and off - if parent then - if validpair[getsubtype(parent)] then - local current_nucleus = getnucleus(parent) - if getid(current_nucleus) == math_char then - local current_char = getchar(current_nucleus) - local p_sub = getsub(parent) - local p_sup = getsup(parent) - if not p_sub and not p_sup then - local mathpair = mathpairs[current_char] - if mathpair then - local next_noad = getnext(parent) - if next_noad and getid(next_noad) == math_noad and validpair[getsubtype(next_noad)] then - local next_nucleus = getnucleus(next_noad) - if getid(next_nucleus) == math_char then - local next_char = getchar(next_nucleus) - local newchar = mathpair[next_char] - if newchar then - local id = getfont(current_nucleus) - local characters = fontcharacters[id] - local replace = characters and characters[newchar] - if replace then - if trace_collapsing then - report_collapsing("%U + %U => %U",current_char,next_char,newchar) - end - setchar(current_nucleus,newchar) - local next_next_noad = getnext(next_noad) - if next_next_noad then - setlink(parent,next_next_noad) - else - setnext(parent) - end - local nsup = getsup(next_noad) - local nsub = getsub(next_noad) - if nsup then - setsup(parent,nsup) - setsup(next_noad) - end - if nsub then - setsub(parent,nsub) - setsub(next_noad) - end - flush_node(next_noad) - collapsepair(pointer,what,n,parent,true) - end - end - end - end - end - elseif p_sup then - if getid(p_sup) == math_char then - local current_char = getchar(p_sup) - local new_char = movesub[current_char] - if new_char then - fixsupscript(parent,p_sup,current_char,new_char) - end + fixscripts[math_char] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off + if parent then + local nucleus = getnucleus(parent) + if getid(nucleus) == math_char then + local current_char = getchar(nucleus) + local sub = getsub(parent) + local sup = getsup(parent) + if sup and getid(sup) == math_char then + local oldchar = getchar(sup) + local newchar = movesub[oldchar] + if newchar then + fixsupscript(parent,sup,oldchar,newchar) end - return end - local current_char = getchar(current_nucleus) - local new_char = movesub[current_char] - if new_char then - movesubscript(parent,current_nucleus,current_char,new_char) + if sub then + local oldchar = getchar(nucleus) + local newchar = movesub[oldchar] + if newchar then + movesubscript(parent,nucleus,oldchar,newchar) + end end end end end -end -collapse[math_char] = collapsepair + function noads.handlers.fixscripts(head,style,penalties) + processnoads(head,fixscripts,"fixscripts") + return true + end -function noads.handlers.collapse(head,style,penalties) - processnoads(head,collapse,"collapse") - return true end -- variants -local variants = { } - -local validvariants = { -- fast check on valid - [0x2229] = 0xFE00, [0x222A] = 0xFE00, - [0x2268] = 0xFE00, [0x2269] = 0xFE00, - [0x2272] = 0xFE00, [0x2273] = 0xFE00, - [0x228A] = 0xFE00, [0x228B] = 0xFE00, - [0x2293] = 0xFE00, [0x2294] = 0xFE00, - [0x2295] = 0xFE00, - [0x2297] = 0xFE00, - [0x229C] = 0xFE00, - [0x22DA] = 0xFE00, [0x22DB] = 0xFE00, - [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00, - [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00, - [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00, - [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00, -} +do + + local variants = { } + local validvariants = { -- fast check on valid + [0x2229] = 0xFE00, [0x222A] = 0xFE00, + [0x2268] = 0xFE00, [0x2269] = 0xFE00, + [0x2272] = 0xFE00, [0x2273] = 0xFE00, + [0x228A] = 0xFE00, [0x228B] = 0xFE00, + [0x2293] = 0xFE00, [0x2294] = 0xFE00, + [0x2295] = 0xFE00, + [0x2297] = 0xFE00, + [0x229C] = 0xFE00, + [0x22DA] = 0xFE00, [0x22DB] = 0xFE00, + [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00, + [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00, + [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00, + [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00, + } -variants[math_char] = function(pointer,what,n,parent) -- also set export value - local char = getchar(pointer) - local selector = validvariants[char] - if selector then - local next = getnext(parent) - if next and getid(next) == math_noad then - local nucleus = getnucleus(next) - if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then - local variant - local tfmdata = fontdata[getfont(pointer)] - local mathvariants = tfmdata.resources.variants -- and variantdata - if mathvariants then - mathvariants = mathvariants[selector] + variants[math_char] = function(pointer,what,n,parent) -- also set export value + local char = getchar(pointer) + local selector = validvariants[char] + if selector then + local next = getnext(parent) + if next and getid(next) == math_noad then + local nucleus = getnucleus(next) + if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then + local variant + local tfmdata = fontdata[getfont(pointer)] + local mathvariants = tfmdata.resources.variants -- and variantdata if mathvariants then - variant = mathvariants[char] - end - end - if variant then - setchar(pointer,variant) - setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup - if trace_variants then - report_variants("variant (%U,%U) replaced by %U",char,selector,variant) + mathvariants = mathvariants[selector] + if mathvariants then + variant = mathvariants[char] + end end - else - if trace_variants then - report_variants("no variant (%U,%U)",char,selector) + if variant then + setchar(pointer,variant) + setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup + if trace_variants then + report_variants("variant (%U,%U) replaced by %U",char,selector,variant) + end + else + if trace_variants then + report_variants("no variant (%U,%U)",char,selector) + end end + setprev(next,pointer) + setnext(parent,getnext(next)) + flush_node(next) end - setprev(next,pointer) - setnext(parent,getnext(next)) - flush_node(next) end end end -end -function handlers.variants(head,style,penalties) - processnoads(head,variants,"unicode variant") - return true + function handlers.variants(head,style,penalties) + processnoads(head,variants,"unicode variant") + return true + end + end -- for manuals -local classes = { } - -local colors = { - [noad_rel] = "trace:dr", - [noad_ord] = "trace:db", - [noad_bin] = "trace:dg", - [noad_open] = "trace:dm", - [noad_close] = "trace:dm", - [noad_punct] = "trace:dc", - -- [noad_opdisplaylimits] = "", - -- [noad_oplimits] = "", - -- [noad_opnolimits] = "", - -- [noad_inner = "", - -- [noad_under = "", - -- [noad_over = "", - -- [noad_vcenter = "", -} +do -classes[math_char] = function(pointer,what,n,parent) - local color = colors[getsubtype(parent)] - if color then - setcolor(pointer,color) - else - resetcolor(pointer) + local classes = { } + local colors = { + [noad_rel] = "trace:dr", + [noad_ord] = "trace:db", + [noad_bin] = "trace:dg", + [noad_open] = "trace:dm", + [noad_close] = "trace:dm", + [noad_punct] = "trace:dc", + -- [noad_opdisplaylimits] = "", + -- [noad_oplimits] = "", + -- [noad_opnolimits] = "", + -- [noad_inner = "", + -- [noad_under = "", + -- [noad_over = "", + -- [noad_vcenter = "", + } + + classes[math_char] = function(pointer,what,n,parent) + local color = colors[getsubtype(parent)] + if color then + setcolor(pointer,color) + else + resetcolor(pointer) + end end -end -function handlers.classes(head,style,penalties) - processnoads(head,classes,"classes") - return true -end + function handlers.classes(head,style,penalties) + processnoads(head,classes,"classes") + return true + end -registertracker("math.classes",function(v) - setaction("math","noads.handlers.classes",v) -end) + registertracker("math.classes",function(v) + setaction("math","noads.handlers.classes",v) + end) + +end -- experimental @@ -1813,9 +1846,7 @@ do local categories = { } local numbers = { } local a_mathdomain = privateattribute("mathdomain") - mathematics.domains = categories - local permitted = { ordinary = noad_ord, binary = noad_bin, @@ -1968,17 +1999,21 @@ end) -- also for me -local applyvisuals = nuts.applyvisuals -local visual = false +do -function handlers.makeup(head) - applyvisuals(tonut(head),visual) -end + local applyvisuals = nuts.applyvisuals + local visual = false -registertracker("math.makeup",function(v) - visual = v - setaction("math","noads.handlers.makeup",v) -end) + function handlers.makeup(head) + applyvisuals(tonut(head),visual) + end + + registertracker("math.makeup",function(v) + visual = v + setaction("math","noads.handlers.makeup",v) + end) + +end -- the normal builder -- cgit v1.2.3