summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/math-noa.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/math-noa.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/math-noa.lua454
1 files changed, 281 insertions, 173 deletions
diff --git a/Master/texmf-dist/tex/context/base/math-noa.lua b/Master/texmf-dist/tex/context/base/math-noa.lua
index 3a0af01cc9e..893ee6f48d3 100644
--- a/Master/texmf-dist/tex/context/base/math-noa.lua
+++ b/Master/texmf-dist/tex/context/base/math-noa.lua
@@ -28,31 +28,38 @@ local otf = fonts.handlers.otf
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
-local trace_remapping = false trackers.register("math.remapping", function(v) trace_remapping = v end)
-local trace_processing = false trackers.register("math.processing", function(v) trace_processing = v end)
-local trace_analyzing = false trackers.register("math.analyzing", function(v) trace_analyzing = v end)
-local trace_normalizing = false trackers.register("math.normalizing", function(v) trace_normalizing = v end)
-local trace_collapsing = false trackers.register("math.collapsing", function(v) trace_collapsing = v end)
-local trace_goodies = false trackers.register("math.goodies", function(v) trace_goodies = v end)
-local trace_variants = false trackers.register("math.variants", function(v) trace_variants = v end)
-local trace_alternates = false trackers.register("math.alternates", function(v) trace_alternates = v end)
-local trace_italics = false trackers.register("math.italics", function(v) trace_italics = v end)
-local trace_families = false trackers.register("math.families", function(v) trace_families = v end)
-
-local check_coverage = true directives.register("math.checkcoverage", function(v) check_coverage = v end)
-
-local report_processing = logs.reporter("mathematics","processing")
-local report_remapping = logs.reporter("mathematics","remapping")
-local report_normalizing = logs.reporter("mathematics","normalizing")
-local report_collapsing = logs.reporter("mathematics","collapsing")
-local report_goodies = logs.reporter("mathematics","goodies")
-local report_variants = logs.reporter("mathematics","variants")
-local report_alternates = logs.reporter("mathematics","alternates")
-local report_italics = logs.reporter("mathematics","italics")
-local report_families = logs.reporter("mathematics","families")
-
-local a_mathrendering = attributes.private("mathrendering")
-local a_exportstatus = attributes.private("exportstatus")
+local privateattribute = attributes.private
+local registertracker = trackers.register
+local registerdirective = directives.register
+local logreporter = logs.reporter
+
+local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end)
+local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end)
+local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end)
+local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end)
+local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end)
+local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end)
+local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end)
+local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end)
+local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end)
+local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end)
+local trace_families = false registertracker("math.families", function(v) trace_families = v end)
+
+local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end)
+
+local report_processing = logreporter("mathematics","processing")
+local report_remapping = logreporter("mathematics","remapping")
+local report_normalizing = logreporter("mathematics","normalizing")
+local report_collapsing = logreporter("mathematics","collapsing")
+local report_patching = logreporter("mathematics","patching")
+local report_goodies = logreporter("mathematics","goodies")
+local report_variants = logreporter("mathematics","variants")
+local report_alternates = logreporter("mathematics","alternates")
+local report_italics = logreporter("mathematics","italics")
+local report_families = logreporter("mathematics","families")
+
+local a_mathrendering = privateattribute("mathrendering")
+local a_exportstatus = privateattribute("exportstatus")
local nuts = nodes.nuts
local nodepool = nuts.pool
@@ -83,8 +90,6 @@ local font_of_family = node.family_font
local new_kern = nodepool.kern
local new_rule = nodepool.rule
-local topoints = number.points
-
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
local fontcharacters = fonthashes.characters
@@ -236,7 +241,7 @@ noads.process = processnoads
-- might as well do this
local families = { }
-local a_mathfamily = attributes.private("mathfamily")
+local a_mathfamily = privateattribute("mathfamily")
local boldmap = mathematics.boldmap
local familymap = { [0] =
@@ -336,8 +341,8 @@ end
-- character remapping
-local a_mathalphabet = attributes.private("mathalphabet")
-local a_mathgreek = attributes.private("mathgreek")
+local a_mathalphabet = privateattribute("mathalphabet")
+local a_mathgreek = privateattribute("mathgreek")
processors.relocate = { }
@@ -488,7 +493,7 @@ end
-- todo: just replace the character by an ord noad
-- and remove the right delimiter as well
-local mathsize = attributes.private("mathsize")
+local mathsize = privateattribute("mathsize")
local resize = { } processors.resize = resize
@@ -517,137 +522,17 @@ function handlers.resize(head,style,penalties)
return true
end
-local collapse = { } processors.collapse = collapse
-
-local mathpairs = characters.mathpairs
-
-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)
-
-mathpairs[0x2035] = { [0x2035] = 0x2036, [0x2036] = 0x2037 } -- (reversedprime,reversedprime) (reversedprime,doublereversedprime)
-mathpairs[0x2036] = { [0x2035] = 0x2037 } -- (doublereversedprime,reversedprime)
-
-mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D }
-mathpairs[0x222C] = { [0x222B] = 0x222D }
-
-mathpairs[0x007C] = { [0x007C] = 0x2016, [0x2016] = 0x2980 } -- bar+bar=double bar+double=triple
-mathpairs[0x2016] = { [0x007C] = 0x2980 } -- double+bar=triple
-
-local movesub = {
- -- primes
- [0x2032] = 0xFE932,
- [0x2033] = 0xFE933,
- [0x2034] = 0xFE934,
- [0x2057] = 0xFE957,
- -- reverse primes
- [0x2035] = 0xFE935,
- [0x2036] = 0xFE936,
- [0x2037] = 0xFE937,
-}
-
-local validpair = {
- [noad_rel] = true,
- [noad_ord] = true,
- [noad_opdisplaylimits] = true,
- [noad_oplimits] = true,
- [noad_opnolimits] = true,
-}
-
-local function movesubscript(parent,current_nucleus,current_char)
- local prev = getfield(parent,"prev")
- if prev and getid(prev) == math_noad then
- if not getfield(prev,"sup") and not getfield(prev,"sub") then
- setfield(current_nucleus,"char",movesub[current_char or getchar(current_nucleus)])
- -- {f} {'}_n => f_n^'
- local nucleus = getfield(parent,"nucleus")
- local sub = getfield(parent,"sub")
- local sup = getfield(parent,"sup")
- setfield(prev,"sup",nucleus)
- setfield(prev,"sub",sub)
- local dummy = copy_node(nucleus)
- setfield(dummy,"char",0)
- setfield(parent,"nucleus",dummy)
- setfield(parent,"sub",nil)
- if trace_collapsing then
- report_collapsing("fixing subscript")
- end
- end
- end
-end
-
-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 = getfield(parent,"nucleus")
- if getid(current_nucleus) == math_char then
- local current_char = getchar(current_nucleus)
- if not getfield(parent,"sub") and not getfield(parent,"sup") then
- local mathpair = mathpairs[current_char]
- if mathpair then
- local next_noad = getnext(parent)
- if next_noad and getid(next_noad) == math_noad then
- if validpair[getsubtype(next_noad)] then
- local next_nucleus = getfield(next_noad,"nucleus")
- if getid(next_nucleus) == math_char then
- local next_char = getchar(next_nucleus)
- local newchar = mathpair[next_char]
- if newchar then
- local fam = getfield(current_nucleus,"fam")
- local id = font_of_family(fam)
- local characters = fontcharacters[id]
- if characters and characters[newchar] then
- if trace_collapsing then
- report_collapsing("%U + %U => %U",current_char,next_char,newchar)
- end
- setfield(current_nucleus,"char",newchar)
- local next_next_noad = getnext(next_noad)
- if next_next_noad then
- setfield(parent,"next",next_next_noad)
- setfield(next_next_noad,"prev",parent)
- else
- setfield(parent,"next",nil)
- end
- setfield(parent,"sup",getfield(next_noad,"sup"))
- setfield(parent,"sub",getfield(next_noad,"sub"))
- setfield(next_noad,"sup",nil)
- setfield(next_noad,"sub",nil)
- free_node(next_noad)
- collapsepair(pointer,what,n,parent,true)
- if not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus)
- end
- end
- end
- end
- end
- end
- elseif not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus,current_char)
- end
- elseif not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus,current_char)
- end
- end
- end
- end
-end
-
-collapse[math_char] = collapsepair
-
-function noads.handlers.collapse(head,style,penalties)
- processnoads(head,collapse,"collapse")
- return true
-end
-
-- normalize scripts
local unscript = { } noads.processors.unscript = unscript
+local checkers = { } noads.processors.checkers = checkers
local superscripts = characters.superscripts
local subscripts = characters.subscripts
+local fractions = characters.fractions
local replaced = { }
+local unknowns = { }
local function replace(pointer,what,n,parent)
pointer = parent -- we're following the parent list (chars trigger this)
@@ -726,22 +611,83 @@ local function replace(pointer,what,n,parent)
-- we could return stop
end
+local tracked = false trackers.register("fonts.missing", function(v) tracked = v end)
+local checked = { } -- simple case
+local cached = table.setmetatableindex("table") -- complex case
+
+local function check(pointer,what,n,parent)
+ if tracked then
+ -- slower as we check each font too and we always replace as math has
+ -- more demands than text
+ local char = getchar(pointer)
+ local font = font_of_family(getfield(pointer,"fam"))
+ local fake = cached[font][char]
+ if fake then
+ unknowns[char] = unknowns[char] + 1
+ setfield(pointer,"char",fake)
+ else
+ local chars = fontcharacters[font]
+ if not chars[char] then
+ unknowns[char] = 1
+ local kind, fake = fonts.checkers.placeholder(font,char)
+ if kind == "char" then
+ cached[font][char] = fake
+ setfield(pointer,"char",fake)
+ else
+ cached[font][char] = 0x3F
+ end
+ end
+ end
+ else
+ -- only simple checking, report at the end so one should take
+ -- action anyway ... we can miss a few checks but that is ok
+ -- as there is at least one reported
+ local char = getchar(pointer)
+ local done = unknowns[char]
+ if done then
+ unknowns[char] = done + 1
+ setfield(pointer,"char",0x3F)
+ elseif not checked[char] then
+ local font = font_of_family(getfield(pointer,"fam"))
+ local chars = fontcharacters[font]
+ if not chars[char] then
+ unknowns[char] = 1
+ setfield(pointer,"char",0x3F)
+ if trace_normalizing then
+ report_normalizing("character %C is not available",char)
+ end
+ end
+ end
+ checked[char] = true
+ end
+end
+
unscript[math_char] = replace -- not noads as we need to recurse
+checkers[math_char] = check -- not noads as we need to recurse
function handlers.unscript(head,style,penalties)
processnoads(head,unscript,"unscript")
+ processnoads(head,checkers,"checkers")
return true
end
-statistics.register("math script replacements", function()
- if next(replaced) then
+local function collected(list)
+ if list and next(list) then
local n, t = 0, { }
- for k, v in table.sortedpairs(replaced) do
+ for k, v in table.sortedpairs(list) do
n = n + v
t[#t+1] = formatters["%C"](k)
end
return formatters["% t (n=%s)"](t,n)
end
+end
+
+statistics.register("math script replacements", function()
+ return collected(replaced)
+end)
+
+statistics.register("unknown math characters", function()
+ return collected(unknowns)
end)
-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
@@ -787,7 +733,7 @@ registerotffeature {
local getalternate = otf.getalternate
-local a_mathalternate = attributes.private("mathalternate")
+local a_mathalternate = privateattribute("mathalternate")
local alternate = { } -- processors.alternate = alternate
@@ -831,7 +777,12 @@ end
-- = we check for correction first because accessing nodes is slower
-- = the actual glyph is not that important (we can control it with numbers)
-local a_mathitalics = attributes.private("mathitalics")
+-- Italic correction in luatex math is a mess. There are all kind of assumptions based on
+-- old fonts and new font. Eventually there should be a flag that can signal to ignore all
+-- those heuristics. We want to deal with it ourselves also in the perspective of mxed math
+-- and text.
+
+local a_mathitalics = privateattribute("mathitalics")
local italics = { }
local default_factor = 1/20
@@ -899,6 +850,12 @@ local function getcorrection(method,font,char) -- -- or character.italic -- (thi
end
+local setcolor = nodes.tracers.colors.set
+local resetcolor = nodes.tracers.colors.reset
+local italic_kern = new_kern
+local c_positive_d = "trace:db"
+local c_negative_d = "trace:dr"
+
local function insert_kern(current,kern)
local sub = new_node(math_sub) -- todo: pool
local noad = new_node(math_noad) -- todo: pool
@@ -908,13 +865,7 @@ local function insert_kern(current,kern)
return sub
end
-local setcolor = nodes.tracers.colors.set
-local resetcolor = nodes.tracers.colors.reset
-local italic_kern = new_kern
-local c_positive_d = "trace:db"
-local c_negative_d = "trace:dr"
-
-trackers.register("math.italics", function(v)
+registertracker("math.italics.visualize", function(v)
if v then
italic_kern = function(k,font)
local ex = 1.5 * fontexheights[font]
@@ -959,12 +910,14 @@ italics[math_char] = function(pointer,what,n,parent)
report_italics("method %a, adding %p italic correction for lower limit of %C",method,correction,char)
end
end
- else
- if sup then
+ elseif sup then
+ if pointer ~= sub then
setfield(parent,"sup",insert_kern(sup,italic_kern(correction,font)))
if trace_italics then
report_italics("method %a, adding %p italic correction before superscript after %C",method,correction,char)
end
+ else
+ -- otherwise we inject twice
end
end
else
@@ -1044,6 +997,147 @@ function mathematics.resetitalics()
texsetattribute(a_mathitalics,unsetvalue)
end
+-- primes and such
+
+local collapse = { } processors.collapse = collapse
+
+local mathpairs = characters.mathpairs
+
+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)
+
+mathpairs[0x2035] = { [0x2035] = 0x2036, [0x2036] = 0x2037 } -- (reversedprime,reversedprime) (reversedprime,doublereversedprime)
+mathpairs[0x2036] = { [0x2035] = 0x2037 } -- (doublereversedprime,reversedprime)
+
+mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D }
+mathpairs[0x222C] = { [0x222B] = 0x222D }
+
+mathpairs[0x007C] = { [0x007C] = 0x2016, [0x2016] = 0x2980 } -- bar+bar=double bar+double=triple
+mathpairs[0x2016] = { [0x007C] = 0x2980 } -- double+bar=triple
+
+local movesub = {
+ -- primes
+ [0x2032] = 0xFE932,
+ [0x2033] = 0xFE933,
+ [0x2034] = 0xFE934,
+ [0x2057] = 0xFE957,
+ -- reverse primes
+ [0x2035] = 0xFE935,
+ [0x2036] = 0xFE936,
+ [0x2037] = 0xFE937,
+}
+
+local validpair = {
+ [noad_rel] = true,
+ [noad_ord] = true,
+ [noad_opdisplaylimits] = true,
+ [noad_oplimits] = true,
+ [noad_opnolimits] = true,
+}
+
+local function movesubscript(parent,current_nucleus,current_char)
+ local prev = getfield(parent,"prev")
+ if prev and getid(prev) == math_noad then
+ if not getfield(prev,"sup") and not getfield(prev,"sub") then
+ -- {f} {'}_n => f_n^'
+ setfield(current_nucleus,"char",movesub[current_char or getchar(current_nucleus)])
+ local nucleus = getfield(parent,"nucleus")
+ local sub = getfield(parent,"sub")
+ local sup = getfield(parent,"sup")
+ setfield(prev,"sup",nucleus)
+ setfield(prev,"sub",sub)
+ local dummy = copy_node(nucleus)
+ setfield(dummy,"char",0)
+ setfield(parent,"nucleus",dummy)
+ setfield(parent,"sub",nil)
+ if trace_collapsing then
+ report_collapsing("fixing subscript")
+ end
+ elseif not getfield(prev,"sup") then
+ -- {f} {'}_n => f_n^'
+ setfield(current_nucleus,"char",movesub[current_char or getchar(current_nucleus)])
+ local nucleus = getfield(parent,"nucleus")
+ local sup = getfield(parent,"sup")
+ setfield(prev,"sup",nucleus)
+ local dummy = copy_node(nucleus)
+ setfield(dummy,"char",0)
+ setfield(parent,"nucleus",dummy)
+ if trace_collapsing then
+ report_collapsing("fixing subscript")
+ end
+ end
+ end
+end
+
+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 = getfield(parent,"nucleus")
+ if getid(current_nucleus) == math_char then
+ local current_char = getchar(current_nucleus)
+ if not getfield(parent,"sub") and not getfield(parent,"sup") then
+ local mathpair = mathpairs[current_char]
+ if mathpair then
+ local next_noad = getnext(parent)
+ if next_noad and getid(next_noad) == math_noad then
+ if validpair[getsubtype(next_noad)] then
+ local next_nucleus = getfield(next_noad,"nucleus")
+ local next_char = getchar(next_nucleus)
+ if getid(next_nucleus) == math_char then
+ local newchar = mathpair[next_char]
+ if newchar then
+ local fam = getfield(current_nucleus,"fam")
+ local id = font_of_family(fam)
+ local characters = fontcharacters[id]
+ if characters and characters[newchar] then
+ if trace_collapsing then
+ report_collapsing("%U + %U => %U",current_char,next_char,newchar)
+ end
+ setfield(current_nucleus,"char",newchar)
+ local next_next_noad = getnext(next_noad)
+ if next_next_noad then
+ setfield(parent,"next",next_next_noad)
+ setfield(next_next_noad,"prev",parent)
+ else
+ setfield(parent,"next",nil)
+ end
+ setfield(parent,"sup",getfield(next_noad,"sup"))
+ setfield(parent,"sub",getfield(next_noad,"sub"))
+ setfield(next_noad,"sup",nil)
+ setfield(next_noad,"sub",nil)
+ free_node(next_noad)
+ collapsepair(pointer,what,n,parent,true)
+ -- if not nested and movesub[current_char] then
+ -- movesubscript(parent,current_nucleus,current_char)
+ -- end
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ end
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ elseif not nested and movesub[current_char] then
+ movesubscript(parent,current_nucleus,current_char)
+ end
+ end
+ end
+ end
+end
+
+collapse[math_char] = collapsepair
+
+function noads.handlers.collapse(head,style,penalties)
+ processnoads(head,collapse,"collapse")
+ return true
+end
+
-- variants
local variants = { }
@@ -1139,7 +1233,7 @@ function handlers.classes(head,style,penalties)
return true
end
-trackers.register("math.classes",function(v) tasks.setaction("math","noads.handlers.classes",v) end)
+registertracker("math.classes",function(v) tasks.setaction("math","noads.handlers.classes",v) end)
-- just for me
@@ -1147,7 +1241,7 @@ function handlers.showtree(head,style,penalties)
inspect(nodes.totree(head))
end
-trackers.register("math.showtree",function(v) tasks.setaction("math","noads.handlers.showtree",v) end)
+registertracker("math.showtree",function(v) tasks.setaction("math","noads.handlers.showtree",v) end)
-- the normal builder
@@ -1202,6 +1296,20 @@ end)
-- interface
-commands.setmathalternate = mathematics.setalternate
-commands.setmathitalics = mathematics.setitalics
-commands.resetmathitalics = mathematics.resetitalics
+local implement = interfaces.implement
+
+implement {
+ name = "setmathalternate",
+ actions = mathematics.setalternate,
+ arguments = { "integer", "string" }
+}
+
+implement {
+ name = "setmathitalics",
+ actions = mathematics.setitalics
+}
+
+implement {
+ name = "resetmathitalics",
+ actions = mathematics.resetitalics
+}