diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/math-tag.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/math-tag.lua | 437 |
1 files changed, 205 insertions, 232 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua b/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua index 03f9e70bbbb..d1ed90d389b 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/math-tag.lua @@ -14,92 +14,90 @@ if not modules then modules = { } end modules ['math-tag'] = { local find, match = string.find, string.match local insert, remove, concat = table.insert, table.remove, table.concat -local attributes = attributes -local nodes = nodes - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getid = nuts.getid -local getchar = nuts.getchar -local getfont = nuts.getfont -local getlist = nuts.getlist -local getfield = nuts.getfield -local getdisc = nuts.getdisc -local getsubtype = nuts.getsubtype -local getattr = nuts.getattr -local getattrlist = nuts.getattrlist -local setattr = nuts.setattr -local getcomponents = nuts.getcomponents -- not really needed -local getwidth = nuts.getwidth - -local getnucleus = nuts.getnucleus -local getsub = nuts.getsub -local getsup = nuts.getsup - -local set_attributes = nuts.setattributes - -local nextnode = nuts.traversers.node - -local nodecodes = nodes.nodecodes - -local noad_code = nodecodes.noad -- attr nucleus sub sup -local accent_code = nodecodes.accent -- attr nucleus sub sup accent -local radical_code = nodecodes.radical -- attr nucleus sub sup left degree -local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right -local subbox_code = nodecodes.subbox -- attr list -local submlist_code = nodecodes.submlist -- attr list -local mathchar_code = nodecodes.mathchar -- attr fam char -local mathtextchar_code = nodecodes.mathtextchar -- attr fam char -local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char -local style_code = nodecodes.style -- attr style -local choice_code = nodecodes.choice -- attr display text script scriptscript -local fence_code = nodecodes.fence -- attr subtype - -local accentcodes = nodes.accentcodes - -local fixedtopaccent_code = accentcodes.fixedtop -local fixedbottomaccent_code = accentcodes.fixedbottom -local fixedbothaccent_code = accentcodes.fixedboth - -local kerncodes = nodes.kerncodes - -local fontkern_code = kerncodes.fontkern -local italickern_code = kerncodes.italickern - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern -local math_code = nodecodes.math - -local processnoads = noads.process - -local a_tagged = attributes.private('tagged') -local a_mathcategory = attributes.private('mathcategory') -local a_mathmode = attributes.private('mathmode') - -local tags = structures.tags - -local start_tagged = tags.start -local restart_tagged = tags.restart -local stop_tagged = tags.stop -local taglist = tags.taglist - -local chardata = characters.data - -local getmathcodes = tex.getmathcodes -local mathcodes = mathematics.codes -local ordinary_mathcode = mathcodes.ordinary -local variable_mathcode = mathcodes.variable - -local fromunicode16 = fonts.mappings.fromunicode16 -local fontcharacters = fonts.hashes.characters - -local report_tags = logs.reporter("structure","tags") +local attributes = attributes +local nodes = nodes + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local getid = nuts.getid +local getchar = nuts.getchar +local getfont = nuts.getfont +local getlist = nuts.getlist +local getfield = nuts.getfield +local getdisc = nuts.getdisc +local getsubtype = nuts.getsubtype +local getattr = nuts.getattr +local setattr = nuts.setattr +local getcomponents = nuts.getcomponents +local getwidth = nuts.getwidth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup + +local set_attributes = nuts.setattributes +local traverse_nodes = nuts.traverse + +local nodecodes = nodes.nodecodes + +local math_noad_code = nodecodes.noad -- attr nucleus sub sup +local math_accent_code = nodecodes.accent -- attr nucleus sub sup accent +local math_radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local math_fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local math_box_code = nodecodes.subbox -- attr list +local math_sub_code = nodecodes.submlist -- attr list +local math_char_code = nodecodes.mathchar -- attr fam char +local math_textchar_code = nodecodes.mathtextchar -- attr fam char +local math_delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char +local math_style_code = nodecodes.style -- attr style +local math_choice_code = nodecodes.choice -- attr display text script scriptscript +local math_fence_code = nodecodes.fence -- attr subtype + +local accentcodes = nodes.accentcodes + +local math_fixed_top = accentcodes.fixedtop +local math_fixed_bottom = accentcodes.fixedbottom +local math_fixed_both = accentcodes.fixedboth + +local kerncodes = nodes.kerncodes + +local fontkern_code = kerncodes.fontkern +local italickern_code = kerncodes.italickern + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local math_code = nodecodes.math + +local processnoads = noads.process + +local a_tagged = attributes.private('tagged') +local a_mathcategory = attributes.private('mathcategory') +local a_mathmode = attributes.private('mathmode') + +local tags = structures.tags + +local start_tagged = tags.start +local restart_tagged = tags.restart +local stop_tagged = tags.stop +local taglist = tags.taglist + +local chardata = characters.data + +local getmathcodes = tex.getmathcodes +local mathcodes = mathematics.codes +local ordinary_code = mathcodes.ordinary +local variable_code = mathcodes.variable + +local fromunicode16 = fonts.mappings.fromunicode16 +local fontcharacters = fonts.hashes.characters + +local report_tags = logs.reporter("structure","tags") local process @@ -156,19 +154,12 @@ local fencesstack = { } -- glyph nodes and such can happen in under and over stuff --- local function getunicode(n) -- instead of getchar --- local char = getchar(n) --- -- local font = font_of_family(getfield(n,"fam")) -- font_of_family --- local font = getfont(n) --- local data = fontcharacters[font][char] --- return data.unicode or char --- end - local function getunicode(n) -- instead of getchar - -- local char, font = isglyph(n) -- no, we have a mathchar - local char, font = getchar(n), getfont(n) + local char = getchar(n) + -- local font = font_of_family(getfield(n,"fam")) -- font_of_family + local font = getfont(n) local data = fontcharacters[font][char] - return data.unicode or char -- can be a table but unlikely for math characters + return data.unicode or char end ------------------- @@ -176,7 +167,7 @@ end local content = { } local found = false -content[mathchar_code] = function() found = true end +content[math_char_code] = function() found = true end local function hascontent(head) found = false @@ -186,25 +177,18 @@ end -------------------- --- todo: use properties - --- local function showtag(n,id,old) --- local attr = getattr(n,a_tagged) --- local curr = tags.current() --- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)", --- old and "before" or "after ", --- nodecodes[id], --- getattrlist(n), --- attr or "?",attr and taglist[attr].tagname or "?", --- curr or "?",curr and taglist[curr].tagname or "?" --- ) --- end +local function showtag(n,id) + local attr = getattr(n,a_tagged) + report_tags("%s = %s",nodecodes[id or getid(n)],attr and taglist[attr].tagname or "?") +end process = function(start) -- we cannot use the processor as we have no finalizers (yet) local mtexttag = nil while start do local id = getid(start) - -- showtag(start,id,true) + +-- showtag(start,id) + if id == glyph_code or id == disc_code then if not mtexttag then mtexttag = start_tagged("mtext") @@ -217,11 +201,11 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() mtexttag = nil end - if id == mathchar_code then + if id == math_char_code then local char = getchar(start) local code = getmathcodes(char) local tag - if code == ordinary_mathcode or code == variable_mathcode then + if code == ordinary_code or code == variable_code then local ch = chardata[char] local mc = ch and ch.mathclass if mc == "number" then @@ -241,9 +225,8 @@ process = function(start) -- we cannot use the processor as we have no finalizer setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory end stop_tagged() - -- showtag(start,id,false) break -- okay? - elseif id == mathtextchar_code then -- or id == glyph_code + elseif id == math_textchar_code then -- or id == glyph_code -- check for code local a = getattr(start,a_mathcategory) if a then @@ -252,127 +235,116 @@ process = function(start) -- we cannot use the processor as we have no finalizer setattr(start,a_tagged,start_tagged("ms")) -- mtext end stop_tagged() - -- showtag(start,id,false) break - elseif id == delim_code then + elseif id == math_delim_code then -- check for code setattr(start,a_tagged,start_tagged("mo")) stop_tagged() - -- showtag(start,id,false) break - elseif id == style_code then + elseif id == math_style_code then -- has a next - elseif id == noad_code then - -- setattr(start,a_tagged,tags.current()) + elseif id == math_noad_code then processsubsup(start) - elseif id == dubbox_code or id == hlist_code or id == vlist_code then - -- keep an eye on subbox_code and see what ends up in there + elseif id == math_box_code or id == hlist_code or id == vlist_code then + -- keep an eye on math_box_code and see what ends up in there local attr = getattr(start,a_tagged) - if not attr then - -- just skip - else - local specification = taglist[attr] - if specification then - local tag = specification.tagname - if tag == "formulacaption" then - -- skip - elseif tag == "mstacker" then - local list = getlist(start) - if list then - process(list) - end +if not attr then + -- just skip +else + local specification = taglist[attr] + if specification then + local tag = specification.tagname + if tag == "formulacaption" then + -- skip + elseif tag == "mstacker" then + local list = getlist(start) + if list then + process(list) + end + else + if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then + tag = "mtext" + end + local text = start_tagged(tag) + setattr(start,a_tagged,text) + local list = getlist(start) + if not list then + -- empty list + elseif not attr then + -- box comes from strange place + set_attributes(list,a_tagged,text) -- only the first node ? else - if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then - tag = "mtext" - end - local text = start_tagged(tag) - setattr(start,a_tagged,text) - local list = getlist(start) - if not list then - -- empty list - elseif not attr then - -- box comes from strange place - set_attributes(list,a_tagged,text) -- only the first node ? - else - -- Beware, the first node in list is the actual list so we definitely - -- need to nest. This approach is a hack, maybe I'll make a proper - -- nesting feature to deal with this at another level. Here we just - -- fake structure by enforcing the inner one. - -- - -- todo: have a local list with local tags that then get appended - -- - local tagdata = specification.taglist - local common = #tagdata + 1 - local function runner(list,depth) -- quite inefficient - local cache = { } -- we can have nested unboxed mess so best local to runner - local keep = nil - -- local keep = { } -- win case we might need to move keep outside - for n, id, subtype in nextnode, list do - local mth = id == math_code and subtype - if mth == 0 then -- hm left_code - -- insert(keep,text) - keep = text - text = start_tagged("mrow") - common = common + 1 - end - local aa = getattr(n,a_tagged) - if aa then - local ac = cache[aa] - if not ac then - local tagdata = taglist[aa].taglist - local extra = #tagdata - if common <= extra then - for i=common,extra do - ac = restart_tagged(tagdata[i]) -- can be made faster - end - for i=common,extra do - stop_tagged() -- can be made faster - end - else - ac = text + -- Beware, the first node in list is the actual list so we definitely + -- need to nest. This approach is a hack, maybe I'll make a proper + -- nesting feature to deal with this at another level. Here we just + -- fake structure by enforcing the inner one. + -- + -- todo: have a local list with local tags that then get appended + -- + local tagdata = specification.taglist + local common = #tagdata + 1 + local function runner(list,depth) -- quite inefficient + local cache = { } -- we can have nested unboxed mess so best local to runner + local keep = nil + -- local keep = { } -- win case we might need to move keep outside + for n in traverse_nodes(list) do + local id = getid(n) + local mth = id == math_code and getsubtype(n) + if mth == 0 then + -- insert(keep,text) + keep = text + text = start_tagged("mrow") + common = common + 1 + end + local aa = getattr(n,a_tagged) + if aa then + local ac = cache[aa] + if not ac then + local tagdata = taglist[aa].taglist + local extra = #tagdata + if common <= extra then + for i=common,extra do + ac = restart_tagged(tagdata[i]) -- can be made faster end - cache[aa] = ac - end - setattr(n,a_tagged,ac) - else - setattr(n,a_tagged,text) - end - if id == hlist_code or id == vlist_code then - runner(getlist(n),depth+1) - elseif id == glyph_code then - -- this should not be needed - local components = getcomponents(n) -- unlikely set - if components then - runner(getcomponent,depth+1) - end - elseif id == disc_code then - -- this should not be needed - local pre, post, replace = getdisc(n) - if pre then - runner(pre,depth+1) - end - if post then - runner(post,depth+1) - end - if replace then - runner(replace,depth+1) + for i=common,extra do + stop_tagged() -- can be made faster + end + else + ac = text end + cache[aa] = ac end - if mth == 1 then - stop_tagged() - -- text = remove(keep) - text = keep - common = common - 1 - end + setattr(n,a_tagged,ac) + else + setattr(n,a_tagged,text) + end + + if id == hlist_code or id == vlist_code then + runner(getlist(n),depth+1) + elseif id == glyph_code then + -- this should not be needed (todo: use tounicode info) + runner(getcomponents(n),depth+1) + elseif id == disc_code then + local pre, post, replace = getdisc(n) + runner(pre,depth+1) -- idem + runner(post,depth+1) -- idem + runner(replace,depth+1) -- idem + end + if mth == 1 then + stop_tagged() + -- text = remove(keep) + text = keep + common = common - 1 end end - runner(list,0) end - stop_tagged() + runner(list,0) end + stop_tagged() end end - elseif id == submlistcode then -- normally a hbox +end + elseif id == math_sub_code then -- normally a hbox local list = getlist(start) if list then local attr = getattr(start,a_tagged) @@ -398,7 +370,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer end elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then -- looks like it gets processed twice - -- do we still end up here ? +-- do we still end up here ? setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute process(list) stop_tagged() @@ -413,7 +385,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() end end - elseif id == fraction_code then + elseif id == math_fraction_code then local num = getfield(start,"num") local denom = getfield(start,"denom") local left = getfield(start,"left") @@ -432,7 +404,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer process(right) stop_tagged() end - elseif id == choice_code then + elseif id == math_choice_code then local display = getfield(start,"display") local text = getfield(start,"text") local script = getfield(start,"script") @@ -449,7 +421,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer if scriptscript then process(scriptscript) end - elseif id == fence_code then + elseif id == math_fence_code then local delim = getfield(start,"delim") local subtype = getfield(start,"subtype") if subtype == 1 then @@ -506,7 +478,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer else -- can't happen end - elseif id == radical_code then + elseif id == math_radical_code then local left = getfield(start,"left") local degree = getfield(start,"degree") if left then @@ -524,7 +496,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) stop_tagged() end - elseif id == accent_code then + elseif id == math_accent_code then local accent = getfield(start,"accent") local bot_accent = getfield(start,"bot_accent") local subtype = getsubtype(start) @@ -534,8 +506,8 @@ process = function(start) -- we cannot use the processor as we have no finalizer accent = true, top = getunicode(accent), bottom = getunicode(bot_accent), - topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, - bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, + topfixed = subtype == math_fixed_top or subtype == math_fixed_both, + bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both, })) processsubsup(start) process(bot_accent) @@ -545,7 +517,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer setattr(start,a_tagged,start_tagged("munder", { accent = true, bottom = getunicode(bot_accent), - bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, + bottomfixed = subtype == math_fixed_bottom or subtype == math_fixed_both, })) processsubsup(start) process(bot_accent) @@ -555,7 +527,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer setattr(start,a_tagged,start_tagged("mover", { accent = true, top = getunicode(accent), - topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, + topfixed = subtype == math_fixed_top or subtype == math_fixed_both, })) processsubsup(start) process(accent) @@ -572,7 +544,6 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() end end --- showtag(start,id,false) start = getnext(start) end if mtexttag then @@ -581,10 +552,12 @@ process = function(start) -- we cannot use the processor as we have no finalizer end function noads.handlers.tags(head,style,penalties) - start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" }) --- start_tagged("mrow") + head = tonut(head) + local v_mode = getattr(head,a_mathmode) + local v_math = start_tagged("math", { mode = v_mode == 1 and "display" or "inline" }) setattr(head,a_tagged,start_tagged("mrow")) process(head) stop_tagged() stop_tagged() + return true end |