diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/math-noa.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/math-noa.lua | 748 |
1 files changed, 504 insertions, 244 deletions
diff --git a/Master/texmf-dist/tex/context/base/math-noa.lua b/Master/texmf-dist/tex/context/base/math-noa.lua index 8caf21cc2cf..2371110c14e 100644 --- a/Master/texmf-dist/tex/context/base/math-noa.lua +++ b/Master/texmf-dist/tex/context/base/math-noa.lua @@ -18,11 +18,8 @@ if not modules then modules = { } end modules ['math-noa'] = { -- 20D6 -> 2190 -- 20D7 -> 2192 -local utf = unicode.utf8 - local utfchar, utfbyte = utf.char, utf.byte -local format, rep = string.format, string.rep -local concat = table.concat +local formatters = string.formatters local fonts, nodes, node, mathematics = fonts, nodes, node, mathematics @@ -37,6 +34,7 @@ local trace_normalizing = false trackers.register("math.normalizing", functio 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) @@ -48,30 +46,40 @@ 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 set_attribute = node.set_attribute -local has_attribute = node.has_attribute +local a_mathrendering = attributes.private("mathrendering") +local a_exportstatus = attributes.private("exportstatus") + local mlist_to_hlist = node.mlist_to_hlist local font_of_family = node.family_font local insert_node_after = node.insert_after +local insert_node_before = node.insert_before local free_node = node.free local new_node = node.new -- todo: pool: math_noad math_sub local new_kern = nodes.pool.kern +local new_rule = nodes.pool.rule +local concat_nodes = nodes.concat + +local topoints = number.points local fonthashes = fonts.hashes local fontdata = fonthashes.identifiers local fontcharacters = fonthashes.characters local fontproperties = fonthashes.properties local fontitalics = fonthashes.italics -local fontquads = fonthashes.quads +local fontemwidths = fonthashes.emwidths +local fontexheights = fonthashes.exheights local variables = interfaces.variables local texattribute = tex.attribute local unsetvalue = attributes.unsetvalue +local chardata = characters.data + noads = noads or { } -- todo: only here local noads = noads @@ -89,6 +97,9 @@ local noadcodes = nodes.noadcodes local noad_ord = noadcodes.ord local noad_rel = noadcodes.rel local noad_punct = noadcodes.punct +local noad_opdisplaylimits= noadcodes.opdisplaylimits +local noad_oplimits = noadcodes.oplimits +local noad_opnolimits = noadcodes.opnolimits local math_noad = nodecodes.noad -- attr nucleus sub sup local math_accent = nodecodes.accent -- attr nucleus sub sup accent @@ -103,6 +114,9 @@ local math_style = nodecodes.style -- attr style local math_choice = nodecodes.choice -- attr display text script scriptscript local math_fence = nodecodes.fence -- attr subtype +local hlist_code = nodecodes.hlist +local glyph_code = nodecodes.glyph + local left_fence_code = 1 local function process(start,what,n,parent) @@ -110,17 +124,15 @@ local function process(start,what,n,parent) while start do local id = start.id if trace_processing then - local margin = rep(" ",n or 0) - local detail = tostring(start) if id == math_noad then - report_processing("%s%s (class: %s)",margin,detail,noadcodes[start.subtype] or "?") + report_processing("%w%S, class %a",n*2,start,noadcodes[start.subtype]) elseif id == math_char then local char = start.char local fam = start.fam local font = font_of_family(fam) - report_processing("%s%s (family: %s, font: %s, char: %s, shape: %s)",margin,detail,fam,font,char,utfchar(char)) + report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,start,fam,font,char,char) else - report_processing("%s%s",margin,detail) + report_processing("%w%S",n*2,start) end end local proc = what[id] @@ -135,8 +147,6 @@ local function process(start,what,n,parent) end elseif id == math_char or id == math_textchar or id == math_delim then break - elseif id == math_style then - -- has a next elseif id == math_noad then local noad = start.nucleus if noad then process(noad,what,n,start) end -- list noad = start.sup if noad then process(noad,what,n,start) end -- list @@ -168,6 +178,8 @@ local function process(start,what,n,parent) noad = start.sub if noad then process(noad,what,n,start) end -- list noad = start.accent if noad then process(noad,what,n,start) end -- list noad = start.bot_accent if noad then process(noad,what,n,start) end -- list + elseif id == math_style then + -- has a next else -- glue, penalty, etc end @@ -177,9 +189,9 @@ end local function processnoads(head,actions,banner) if trace_processing then - report_processing("start '%s'",banner) + report_processing("start %a",banner) process(head,actions) - report_processing("stop '%s'",banner) + report_processing("stop %a",banner) else process(head,actions) end @@ -187,19 +199,101 @@ end noads.process = processnoads +-- experiment (when not present fall back to fam 0) -- needs documentation + +-- 0-2 regular +-- 3-5 bold +-- 6-8 pseudobold + +local families = { } +local a_mathfamily = attributes.private("mathfamily") +local boldmap = mathematics.boldmap + +local familymap = { [0] = + "regular", + "regular", + "regular", + "bold", + "bold", + "bold", + "pseudobold", + "pseudobold", + "pseudobold", +} + +families[math_char] = function(pointer) + if pointer.fam == 0 then + local a = pointer[a_mathfamily] + if a and a > 0 then + pointer[a_mathfamily] = 0 + if a > 5 then + local char = pointer.char + local bold = boldmap[char] + local newa = a - 3 + if bold then + pointer[a_exportstatus] = char + pointer.char = bold + if trace_families then + report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa]) + end + else + if trace_families then + report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) + end + end + pointer.fam = newa + else + if trace_families then + local char = pointer.char + report_families("family of %C becomes %s with remap %s",char,a,familymap[a]) + end + pointer.fam = a + end + else + -- pointer.fam = 0 + end + end +end + +families[math_delim] = function(pointer) + if pointer.small_fam == 0 then + local a = pointer[a_mathfamily] + if a and a > 0 then + pointer[a_mathfamily] = 0 + if a > 5 then + -- no bold delimiters in unicode + a = a - 3 + end + pointer.small_fam = a + pointer.large_fam = a + else + pointer.small_fam = 0 + pointer.large_fam = 0 + end + end +end + +families[math_textchar] = families[math_char] + +function handlers.families(head,style,penalties) + processnoads(head,families,"families") + return true +end + -- character remapping -local mathalphabet = attributes.private("mathalphabet") -local mathgreek = attributes.private("mathgreek") +local a_mathalphabet = attributes.private("mathalphabet") +local a_mathgreek = attributes.private("mathgreek") processors.relocate = { } local function report_remap(tag,id,old,new,extra) - report_remapping("remapping %s in font %s from U+%05X (%s) to U+%05X (%s)%s",tag,id,old,utfchar(old),new,utfchar(new),extra or "") + report_remapping("remapping %s in font %s from %C to %C%s",tag,id,old,new,extra) end -local remapalphabets = mathematics.remapalphabets -local setnodecolor = nodes.tracers.colors.set +local remapalphabets = mathematics.remapalphabets +local fallbackstyleattr = mathematics.fallbackstyleattr +local setnodecolor = nodes.tracers.colors.set --~ This does not work out well, as there are no fallbacks. Ok, we could --~ define a poor mans simplify mechanism. @@ -219,22 +313,62 @@ local function checked(pointer) if trace_analyzing then setnodecolor(pointer,"font:isol") end - set_attribute(pointer,exportstatus,char) -- testcase: exponentiale + pointer[a_exportstatus] = char -- testcase: exponentiale pointer.char = newchar return true end end end +-- processors.relocate[math_char] = function(pointer) +-- local g = pointer[a_mathgreek] or 0 +-- local a = pointer[a_mathalphabet] or 0 +-- if a > 0 or g > 0 then +-- if a > 0 then +-- pointer[a_mathgreek] = 0 +-- end +-- if g > 0 then +-- pointer[a_mathalphabet] = 0 +-- end +-- local char = pointer.char +-- local newchar = remapalphabets(char,a,g) +-- if newchar then +-- local fam = pointer.fam +-- local id = font_of_family(fam) +-- local characters = fontcharacters[id] +-- if characters and characters[newchar] then +-- if trace_remapping then +-- report_remap("char",id,char,newchar) +-- end +-- if trace_analyzing then +-- setnodecolor(pointer,"font:isol") +-- end +-- pointer.char = newchar +-- return true +-- else +-- if trace_remapping then +-- report_remap("char",id,char,newchar," fails") +-- end +-- end +-- end +-- end +-- if trace_analyzing then +-- setnodecolor(pointer,"font:medi") +-- end +-- if check_coverage then +-- return checked(pointer) +-- end +-- end + processors.relocate[math_char] = function(pointer) - local g = has_attribute(pointer,mathgreek) or 0 - local a = has_attribute(pointer,mathalphabet) or 0 + local g = pointer[a_mathgreek] or 0 + local a = pointer[a_mathalphabet] or 0 if a > 0 or g > 0 then if a > 0 then - set_attribute(pointer,mathgreek,0) + pointer[a_mathgreek] = 0 end if g > 0 then - set_attribute(pointer,mathalphabet,0) + pointer[a_mathalphabet] = 0 end local char = pointer.char local newchar = remapalphabets(char,a,g) @@ -242,7 +376,7 @@ processors.relocate[math_char] = function(pointer) local fam = pointer.fam local id = font_of_family(fam) local characters = fontcharacters[id] - if characters and characters[newchar] then + if characters[newchar] then if trace_remapping then report_remap("char",id,char,newchar) end @@ -252,8 +386,27 @@ processors.relocate[math_char] = function(pointer) pointer.char = newchar return true else - if trace_remapping then - report_remap("char",id,char,newchar," fails") + local fallback = fallbackstyleattr(a) + if fallback then + local newchar = remapalphabets(char,fallback,g) + if newchar then + if characters[newchar] then + if trace_remapping then + report_remap("char",id,char,newchar," (fallback remapping used)") + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + pointer.char = newchar + return true + elseif trace_remapping then + report_remap("char",id,char,newchar," fails (no fallback character)") + end + elseif trace_remapping then + report_remap("char",id,char,newchar," fails (no fallback remap character)") + end + elseif trace_remapping then + report_remap("char",id,char,newchar," fails (no fallback style)") end end end @@ -285,15 +438,12 @@ end -- rendering (beware, not exported) -local a_mathrendering = attributes.private("mathrendering") -local a_exportstatus = attributes.private("exportstatus") - processors.render = { } local rendersets = mathematics.renderings.numbers or { } -- store processors.render[math_char] = function(pointer) - local attr = has_attribute(pointer,a_mathrendering) + local attr = pointer[a_mathrendering] if attr and attr > 0 then local char = pointer.char local renderset = rendersets[attr] @@ -305,7 +455,7 @@ processors.render[math_char] = function(pointer) local characters = fontcharacters[id] if characters and characters[newchar] then pointer.char = newchar - set_attribute(pointer,a_exportstatus,char) + pointer[a_exportstatus] = char end end end @@ -333,9 +483,9 @@ local resize = { } processors.resize = resize resize[math_fence] = function(pointer) if pointer.subtype == left_fence_code then - local a = has_attribute(pointer,mathsize) + local a = pointer[mathsize] if a and a > 0 then - set_attribute(pointer,mathsize,0) + pointer[mathsize] = 0 local d = pointer.delim local df = d.small_fam local id = font_of_family(df) @@ -354,72 +504,133 @@ end -- respacing -local mathpunctuation = attributes.private("mathpunctuation") - -local respace = { } processors.respace = respace - -local chardata = characters.data +-- local mathpunctuation = attributes.private("mathpunctuation") +-- +-- local respace = { } processors.respace = respace -- only [nd,ll,ul][po][nd,ll,ul] -respace[math_char] = function(pointer,what,n,parent) -- not math_noad .. math_char ... and then parent - pointer = parent - if pointer and pointer.subtype == noad_ord then - local a = has_attribute(pointer,mathpunctuation) - if a and a > 0 then - set_attribute(pointer,mathpunctuation,0) - local current_nucleus = pointer.nucleus - if current_nucleus.id == math_char then - local current_char = current_nucleus.char - local fc = chardata[current_char] - fc = fc and fc.category - if fc == "nd" or fc == "ll" or fc == "lu" then - local next_noad = pointer.next - if next_noad and next_noad.id == math_noad and next_noad.subtype == noad_punct then - local next_nucleus = next_noad.nucleus - if next_nucleus.id == math_char then - local next_char = next_nucleus.char - local nc = chardata[next_char] - nc = nc and nc.category - if nc == "po" then - local last_noad = next_noad.next - if last_noad and last_noad.id == math_noad and last_noad.subtype == noad_ord then - local last_nucleus = last_noad.nucleus - if last_nucleus.id == math_char then - local last_char = last_nucleus.char - local lc = chardata[last_char] - lc = lc and lc.category - if lc == "nd" or lc == "ll" or lc == "lu" then - local ord = new_node(math_noad) -- todo: pool - ord.subtype, ord.nucleus, ord.sub, ord.sup, ord.attr = noad_ord, next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr - -- next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr = nil, nil, nil, nil - next_noad.nucleus, next_noad.sub, next_noad.sup = nil, nil, nil -- else crash with attributes ref count - --~ next_noad.attr = nil - ord.next = last_noad - pointer.next = ord - free_node(next_noad) - end - end - end - end - end - end - end - end - end - end -end - -function handlers.respace(head,style,penalties) - processnoads(head,respace,"respace") - return true -end +-- respace[math_char] = function(pointer,what,n,parent) -- not math_noad .. math_char ... and then parent +-- pointer = parent +-- if pointer and pointer.subtype == noad_ord then +-- local a = pointer[mathpunctuation] +-- if a and a > 0 then +-- pointer[mathpunctuation] = 0 +-- local current_nucleus = pointer.nucleus +-- if current_nucleus.id == math_char then +-- local current_char = current_nucleus.char +-- local fc = chardata[current_char] +-- fc = fc and fc.category +-- if fc == "nd" or fc == "ll" or fc == "lu" then +-- local next_noad = pointer.next +-- if next_noad and next_noad.id == math_noad and next_noad.subtype == noad_punct then +-- local next_nucleus = next_noad.nucleus +-- if next_nucleus.id == math_char then +-- local next_char = next_nucleus.char +-- local nc = chardata[next_char] +-- nc = nc and nc.category +-- if nc == "po" then +-- local last_noad = next_noad.next +-- if last_noad and last_noad.id == math_noad and last_noad.subtype == noad_ord then +-- local last_nucleus = last_noad.nucleus +-- if last_nucleus.id == math_char then +-- local last_char = last_nucleus.char +-- local lc = chardata[last_char] +-- lc = lc and lc.category +-- if lc == "nd" or lc == "ll" or lc == "lu" then +-- local ord = new_node(math_noad) -- todo: pool +-- ord.subtype, ord.nucleus, ord.sub, ord.sup, ord.attr = noad_ord, next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr +-- -- next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr = nil, nil, nil, nil +-- next_noad.nucleus, next_noad.sub, next_noad.sup = nil, nil, nil -- else crash with attributes ref count +-- --~ next_noad.attr = nil +-- ord.next = last_noad +-- pointer.next = ord +-- free_node(next_noad) +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- end + +-- local comma = 0x002C +-- local period = 0x002E +-- +-- respace[math_char] = function(pointer,what,n,parent) +-- pointer = parent +-- if pointer and pointer.subtype == noad_punct then +-- local current_nucleus = pointer.nucleus +-- if current_nucleus.id == math_char then +-- local current_nucleus = pointer.nucleus +-- if current_nucleus.id == math_char then +-- local current_char = current_nucleus.char +-- local a = pointer[mathpunctuation] +-- if not a or a == 0 then +-- if current_char == comma then +-- -- default tex: 2,5 or 2, 5 --> 2, 5 +-- elseif current_char == period then +-- -- default tex: 2.5 or 2. 5 --> 2.5 +-- pointer.subtype = noad_ord +-- end +-- elseif a == 1 then +-- local next_noad = pointer.next +-- if next_noad and next_noad.id == math_noad then +-- local next_nucleus = next_noad.nucleus +-- if next_nucleus.id == math_char and next_nucleus.char == 0 then +-- nodes.remove(pointer,next_noad,true) +-- end +-- if current_char == comma then +-- -- default tex: 2,5 or 2, 5 --> 2, 5 +-- elseif current_char == period then +-- -- default tex: 2.5 or 2. 5 --> 2.5 +-- pointer.subtype = noad_ord +-- end +-- end +-- elseif a == 2 then +-- if current_char == comma or current_char == period then +-- local next_noad = pointer.next +-- if next_noad and next_noad.id == math_noad then +-- local next_nucleus = next_noad.nucleus +-- if next_nucleus.id == math_char and next_nucleus.char == 0 then +-- if current_char == comma then +-- -- adaptive: 2, 5 --> 2, 5 +-- elseif current_char == period then +-- -- adaptive: 2. 5 --> 2. 5 +-- end +-- nodes.remove(pointer,next_noad,true) +-- else +-- if current_char == comma then +-- -- adaptive: 2,5 --> 2,5 +-- pointer.subtype = noad_ord +-- elseif current_char == period then +-- -- adaptive: 2.5 --> 2.5 +-- pointer.subtype = noad_ord +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- end +-- +-- function handlers.respace(head,style,penalties) +-- processnoads(head,respace,"respace") +-- return true +-- end -- The following code is dedicated to Luigi Scarso who pointed me -- to the fact that \not= is not producing valid pdf-a code. -- The code does not solve this for virtual characters but it does -- a decent job on collapsing so that fonts that have the right --- glyph will have a decent unicode point. +-- glyph will have a decent unicode point. In the meantime this code +-- has been moved elsewhere. local collapse = { } processors.collapse = collapse @@ -428,10 +639,22 @@ local mathpairs = characters.mathpairs mathpairs[0x2032] = { [0x2032] = 0x2033, [0x2033] = 0x2034 } -- (prime,prime) (prime,doubleprime) mathpairs[0x2033] = { [0x2032] = 0x2034 } -- (doubleprime,prime) +mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D } +mathpairs[0x222C] = { [0x222B] = 0x222D } + +mathpairs[0x007C] = { [0x007C] = 0x2016 } -- double bars + +local validpair = { + [noad_rel] = true, + [noad_ord] = true, + [noad_opdisplaylimits] = true, + [noad_oplimits] = true, + [noad_opnolimits] = true, +} + local function collapsepair(pointer,what,n,parent) -- todo: switch to turn in on and off if parent then - local subtype = parent.subtype - if subtype == noad_rel or subtype == noad_ord then -- ord is new + if validpair[parent.subtype] then local current_nucleus = parent.nucleus if not parent.sub and not parent.sup and current_nucleus.id == math_char then local current_char = current_nucleus.char @@ -439,8 +662,7 @@ local function collapsepair(pointer,what,n,parent) -- todo: switch to turn in on if mathpair then local next_noad = parent.next if next_noad and next_noad.id == math_noad then - local next_subtype = next_noad.subtype - if next_subtype == noad_rel or next_subtype == noad_ord then -- ord is new + if validpair[next_noad.subtype] then local next_nucleus = next_noad.nucleus if next_nucleus.id == math_char then local next_char = next_nucleus.char @@ -451,7 +673,7 @@ local function collapsepair(pointer,what,n,parent) -- todo: switch to turn in on local characters = fontcharacters[id] if characters and characters[newchar] then if trace_collapsing then - report_collapsing("U+%05X + U+%05X => U+%05X",current_char,next_char,newchar) + report_collapsing("%U + %U => %U",current_char,next_char,newchar) end current_nucleus.char = newchar local next_next_noad = next_noad.next @@ -516,7 +738,7 @@ local function replace(pointer,what,n,parent) nextnucleus.char = s replaced[char] = (replaced[char] or 0) + 1 if trace_normalizing then - report_normalizing("superscript: U+05X (%s) => U+05X (%s)",char,utfchar(char),s,utfchar(s)) + report_normalizing("superscript %C becomes %C",char,s) end else local s = subscripts[char] @@ -532,7 +754,7 @@ local function replace(pointer,what,n,parent) nextnucleus.char = s replaced[char] = (replaced[char] or 0) + 1 if trace_normalizing then - report_normalizing("subscript: U+05X (%s) => U+05X (%s)",char,utfchar(char),s,utfchar(s)) + report_normalizing("subscript %C becomes %C",char,s) end else break @@ -583,15 +805,17 @@ statistics.register("math script replacements", function() local n, t = 0, { } for k, v in table.sortedpairs(replaced) do n = n + v - t[#t+1] = format("U+%05X:%s",k,utfchar(k)) + t[#t+1] = formatters["%C"](k) end - return format("%s (n=%s)",concat(t," "),n) + return formatters["% t (n=%s)"](t,n) end end) -- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$) -- math alternates: (in lucidanova lgf: $ABC \mathalternate{italic} ABC$) +-- todo: set alternate for specific symbols + local function initializemathalternates(tfmdata) local goodies = tfmdata.goodies if goodies then @@ -603,7 +827,7 @@ local function initializemathalternates(tfmdata) local alternates = mathgoodies and mathgoodies.alternates if alternates then if trace_goodies then - report_goodies("loading alternates for font '%s'",tfmdata.properties.name) + report_goodies("loading alternates for font %a",tfmdata.properties.name) end local lastattribute, attributes = 0, { } for k, v in next, alternates do @@ -645,15 +869,19 @@ function mathematics.setalternate(fam,tag) end alternate[math_char] = function(pointer) - local a = has_attribute(pointer,a_mathalternate) + local a = pointer[a_mathalternate] if a and a > 0 then - set_attribute(pointer,a_mathalternate,0) + pointer[a_mathalternate] = 0 local tfmdata = fontdata[font_of_family(pointer.fam)] -- we can also have a famdata local mathalternatesattributes = tfmdata.shared.mathalternatesattributes if mathalternatesattributes then local what = mathalternatesattributes[a] local alt = getalternate(tfmdata,pointer.char,what.feature,what.value) if alt then + if trace_alternates then + report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U", + tostring(what.feature),tostring(what.value),pointer.char,alt) + end pointer.char = alt end end @@ -665,154 +893,186 @@ function handlers.check(head,style,penalties) return true end --- experiment (when not present fall back to fam 0) -- needs documentation +-- italics: we assume that only characters matter +-- +-- = we check for correction first because accessing nodes is slower +-- = the actual glyph is not that important (we can control it with numbers) --- 0-2 regular --- 3-5 bold --- 6-8 pseudobold +local a_mathitalics = attributes.private("mathitalics") -local families = { } -local a_mathfamily = attributes.private("mathfamily") -local boldmap = mathematics.boldmap +local italics = { } +local default_factor = 1/20 -local tracemap = { [0] = - "regular", - "regular", - "regular", - "bold", - "bold", - "bold", - "pseudobold", - "pseudobold", - "pseudobold", -} +local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex) -families[math_char] = function(pointer) - if pointer.fam == 0 then - local a = has_attribute(pointer,a_mathfamily) - if a and a > 0 then - set_attribute(pointer,a_mathfamily,0) - if a > 5 then - local char = pointer.char - local bold = boldmap[char] - local newa = a - 3 - if bold then - set_attribute(pointer,exportstatus,char) - pointer.char = bold - if trace_families then - report_families("replacing U+%05X by bold U+%05X, family %s (%s) becomes %s (%s)", - char,bold,a,tracemap[a],newa,tracemap[newa]) - end - else - if trace_families then - report_families("no bold replacement for U+%05X, family %s (%s) becomes %s (%s)", - char,a,tracemap[a],newa,tracemap[newa]) - end + local correction, fromvisual + + if method == 1 then + -- only font data triggered by fontitalics + local italics = fontitalics[font] + if italics then + local character = fontcharacters[font][char] + if character then + correction = character.italic_correction + if correction and correction ~= 0 then + return correction, false end - pointer.fam = newa - else - if trace_families then - report_families("family of U+%05X becomes %s (%s)", - pointer.char,a,tracemap[a]) + end + end + elseif method == 2 then + -- only font data triggered by fontdata + local character = fontcharacters[font][char] + if character then + correction = character.italic_correction + if correction and correction ~= 0 then + return correction, false + end + end + elseif method == 3 then + -- only quad based by selective + local visual = chardata[char].visual + if not visual then + -- skip + elseif visual == "it" or visual == "bi" then + correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontemwidths[font] + if correction and correction ~= 0 then + return correction, true + end + end + elseif method == 4 then + -- combination of 1 and 3 + local italics = fontitalics[font] + if italics then + local character = fontcharacters[font][char] + if character then + correction = character.italic_correction + if correction and correction ~= 0 then + return correction, false end - pointer.fam = a end - else - -- pointer.fam = 0 end - end -end - -families[math_delim] = function(pointer) - if pointer.small_fam == 0 then - local a = has_attribute(pointer,a_mathfamily) - if a and a > 0 then - set_attribute(pointer,a_mathfamily,0) - if a > 5 then - -- no bold delimiters in unicode - a = a - 3 + if not correction then + local visual = chardata[char].visual + if not visual then + -- skip + elseif visual == "it" or visual == "bi" then + correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontemwidths[font] + if correction and correction ~= 0 then + return correction, true + end end - pointer.small_fam = a - pointer.large_fam = a - else - pointer.small_fam = 0 - pointer.large_fam = 0 end end -end -families[math_textchar] = families[math_char] - -function handlers.families(head,style,penalties) - processnoads(head,families,"families") - return true end --- italics: we assume that only characters matter --- --- = 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") +local function insert_kern(current,kern) + local sub = new_node(math_sub) -- todo: pool + local noad = new_node(math_noad) -- todo: pool + sub.head = kern + kern.next = noad + noad.nucleus = current + return sub +end -local italics = { } -local default_factor = 1/20 +local setcolor = nodes.tracers.colors.set +local italic_kern = new_kern +local c_positive_d = "trace:db" +local c_negative_d = "trace:dr" + +trackers.register("math.italics", function(v) + if v then + italic_kern = function(k,font) + local ex = 1.5 * fontexheights[font] + if k > 0 then + return setcolor(new_rule(k,ex,ex),c_positive_d) + else + return concat_nodes { + old_kern(k), + setcolor(new_rule(-k,ex,ex),c_negative_d), + old_kern(k), + } + end + end + else + italic_kern = new_kern + end +end) italics[math_char] = function(pointer,what,n,parent) - local method = has_attribute(pointer,a_mathitalics) + local method = pointer[a_mathitalics] if method and method > 0 then local char = pointer.char local font = font_of_family(pointer.fam) -- todo: table - local correction - if method == 1 then - -- only font data triggered by fontitalics - local italics = fontitalics[font] - if italics then - local character = fontcharacters[font][char] - correction = character and character.italic_correction -- or character.italic (this one is for tex) + local correction, visual = getcorrection(method,font,char) + if correction then + local pid = parent.id + local sub, sup + if pid == math_noad then + sup = parent.sup + sub = parent.sub end - elseif method == 2 then - -- only font data triggered by fontdata - local character = fontcharacters[font][char] - correction = character and character.italic_correction -- or character.italic (this one is for tex) - elseif method == 3 then - -- only quad based by selective - local visual = chardata[char].visual - if not visual then - -- skip - elseif visual == "it" or visual == "bi" then - correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font] - end - elseif method == 4 then - -- combination of 1 and 3 - local italics = fontitalics[font] - if italics then - local character = fontcharacters[font][char] - correction = character and character.italic_correction -- or character.italic (this one is for tex) - end - if not correction then - local visual = chardata[char].visual - if not visual then - -- skip - elseif visual == "it" or visual == "bi" then - correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font] + if sup or sub then + local subtype = parent.subtype + if subtype == noad_oplimits then + if sup then + parent.sup = insert_kern(sup,italic_kern(correction,font)) + if trace_italics then + report_italics("method %a, adding %p italic correction for upper limit of %C",method,correction,char) + end + end + if sub then + local correction = - correction + parent.sub = insert_kern(sub,italic_kern(correction,font)) + if trace_italics then + report_italics("method %a, adding %p italic correction for lower limit of %C",method,correction,char) + end + end + else + if sup then + 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 + end end - end - end - if correction and correction ~= 0 then - local next_noad = parent.next - if next_noad and next_noad.id == math_noad then - local next_subtype = next_noad.subtype - if next_subtype == noad_punct or next_subtype == noad_ord then - local next_nucleus = next_noad.nucleus - if next_nucleus.id == math_char then - local next_char = next_nucleus.char - if not chardata[next_char].italic then -- or category - if trace_italics then - report_italics("method %s: adding %s italic correction between %s (0x%05X) and %s (0x%05X)", - method,number.points(correction),utfchar(char),char,utfchar(next_char),next_char) + else + local next_noad = parent.next + 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, adding %p italic correction between %C and end math",method,correctio,char) + end + insert_node_after(parent,parent,italic_kern(correction,font)) + end + elseif next_noad.id == math_noad then + local next_subtype = next_noad.subtype + if next_subtype == noad_punct or next_subtype == noad_ord then + local next_nucleus = next_noad.nucleus + if next_nucleus.id == math_char then + local next_char = next_nucleus.char + local next_data = chardata[next_char] + local visual = next_data.visual + if visual == "it" or visual == "bi" then + -- if trace_italics then + -- report_italics("method %a, skipping %p italic correction between italic %C and italic %C",method,correction,char,next_char) + -- end + else + local category = next_data.category + if category == "nd" or category == "ll" or category == "lu" then + if trace_italics then + report_italics("method %a, adding %p italic correction between italic %C and non italic %C",method,correction,char,next_char) + end + insert_node_after(parent,parent,italic_kern(correction,font)) + -- elseif next_data.height > (fontexheights[font]/2) then + -- if trace_italics then + -- report_italics("method %a, adding %p italic correction between %C and ascending %C",method,correction,char,next_char) + -- end + -- insert_node_after(parent,parent,italic_kern(correction,font)) + -- elseif trace_italics then + -- -- report_italics("method %a, skipping %p italic correction between %C and %C",method,correction,char,next_char) + end end - insert_node_after(parent,parent,new_kern(correction)) end end end @@ -892,13 +1152,13 @@ variants[math_char] = function(pointer,what,n,parent) -- also set export value end if variant then pointer.char = variant - set_attribute(pointer,exportstatus,char) -- we don't export the variant as it's visual markup + pointer[a_exportstatus] = char -- we don't export the variant as it's visual markup if trace_variants then - report_variants("variant (U+%05X,U+%05X) replaced by U+%05X",char,selector,variant) + report_variants("variant (%U,%U) replaced by %U",char,selector,variant) end else if trace_variants then - report_variants("no variant (U+%05X,U+%05X)",char,selector) + report_variants("no variant (%U,%U)",char,selector) end end next.prev = pointer @@ -920,16 +1180,16 @@ function builders.kernel.mlist_to_hlist(head,style,penalties) return mlist_to_hlist(head,style,penalties), true end ---~ function builders.kernel.mlist_to_hlist(head,style,penalties) ---~ print("!!!!!!! BEFORE",penalties) ---~ for n in node.traverse(head) do print(n) end ---~ print("!!!!!!!") ---~ head = mlist_to_hlist(head,style,penalties) ---~ print("!!!!!!! AFTER") ---~ for n in node.traverse(head) do print(n) end ---~ print("!!!!!!!") ---~ return head, true ---~ end +-- function builders.kernel.mlist_to_hlist(head,style,penalties) +-- print("!!!!!!! BEFORE",penalties) +-- for n in node.traverse(head) do print(n) end +-- print("!!!!!!!") +-- head = mlist_to_hlist(head,style,penalties) +-- print("!!!!!!! AFTER") +-- for n in node.traverse(head) do print(n) end +-- print("!!!!!!!") +-- return head, true +-- end tasks.new { name = "math", |