summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/math-noa.lua
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2013-04-08 00:43:40 +0000
committerKarl Berry <karl@freefriends.org>2013-04-08 00:43:40 +0000
commit824f7b0903de8ad7f6ee3d7656005e4c59155e06 (patch)
treeabfc8673ef9916f3ab7074e811207384c301492b /Master/texmf-dist/tex/context/base/math-noa.lua
parent689aefb0727676ed3cddf331337b4be226495e72 (diff)
context import for TL13, from www.pragma-ade.com/context/beta/cont-tmf.zip
git-svn-id: svn://tug.org/texlive/trunk@29731 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/math-noa.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/math-noa.lua748
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",