diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/typo-itc.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/typo-itc.lua | 406 |
1 files changed, 327 insertions, 79 deletions
diff --git a/Master/texmf-dist/tex/context/base/typo-itc.lua b/Master/texmf-dist/tex/context/base/typo-itc.lua index 7373c0321fb..f37549dc830 100644 --- a/Master/texmf-dist/tex/context/base/typo-itc.lua +++ b/Master/texmf-dist/tex/context/base/typo-itc.lua @@ -32,6 +32,7 @@ local tonode = nuts.tonode local tonut = nuts.tonut local getfield = nuts.getfield +local getprev = nuts.getprev local getnext = nuts.getnext local getid = nuts.getid local getfont = nuts.getfont @@ -42,6 +43,7 @@ local setattr = nuts.setattr local insert_node_after = nuts.insert_after local delete_node = nuts.delete local end_of_math = nuts.end_of_math +local find_tail = nuts.tail local texgetattribute = tex.getattribute local texsetattribute = tex.setattribute @@ -56,6 +58,8 @@ local fontdata = fonthashes.identifiers local italicsdata = fonthashes.italics local exheights = fonthashes.exheights +local implement = interfaces.implement + local forcedvariant = false function typesetters.italics.forcevariant(variant) @@ -98,16 +102,55 @@ end -- todo: clear attribute +local function okay(data,current,font,prevchar,previtalic,char,what) + if not data then + if trace_italics then + report_italics("ignoring %p between %s italic %C and italic %C",previtalic,what,prevchar,char) + end + return false + end + if threshold then + local ht = getfield(current,"height") + local ex = exheights[font] + local th = threshold * ex + if ht <= th then + if trace_italics then + report_italics("ignoring correction between %s italic %C and regular %C, height %p less than threshold %p",prevchar,what,char,ht,th) + end + return false + end + end + if trace_italics then + report_italics("inserting %p between %s italic %C and regular %C",previtalic,what,prevchar,char) + end + return true +end + function italics.handler(head) - head = tonut(head) - local done = false - local italic = 0 - local lastfont = nil - local lastattr = nil - local previous = nil - local prevchar = nil - local current = head - local inserted = nil + + local prev = nil + local prevchar = nil + local prevhead = tonut(head) + local previtalic = 0 + local previnserted = nil + + local replace = nil + local replacechar = nil + local replacehead = nil + local replaceitalic = 0 + local replaceinserted = nil + + local post = nil + local postchar = nil + local posthead = nil + local postitalic = 0 + local postinserted = nil + + local current = prevhead + local done = false + local lastfont = nil + local lastattr = nil + while current do local id = getid(current) if id == glyph_code then @@ -115,40 +158,45 @@ function italics.handler(head) local char = getchar(current) local data = italicsdata[font] if font ~= lastfont then - if italic ~= 0 then - if data then - if trace_italics then - report_italics("ignoring %p between italic %C and italic %C",italic,prevchar,char) + if previtalic ~= 0 then + if okay(data,current,font,prevchar,previtalic,char,"glyph") then + insert_node_after(prevhead,prev,new_correction_kern(previtalic)) + done = true + end + elseif previnserted and data then + if trace_italics then + report_italics("deleting last correction before %s %C",char,"glyph") + end + delete_node(prevhead,previnserted) + else + -- + if replaceitalic ~= 0 then + if okay(data,replace,font,replacechar,replaceitalic,char,"replace") then + insert_node_after(replacehead,replace,new_correction_kern(replaceitalic)) + done = true end - else - local okay = true - if threshold then - local ht = getfield(current,"height") - local ex = exheights[font] - local th = threshold * ex - if ht <= th then - if trace_italics then - report_italics("ignoring correction between italic %C and regular %C, height %p less than threshold %p",prevchar,char,ht,th) - end - okay = false - end + replaceitalic = 0 + elseif replaceinserted and data then + if trace_italics then + report_italics("deleting last correction before %s %C","replace",char) end - if okay then - if trace_italics then - report_italics("inserting %p between italic %C and regular %C",italic,prevchar,char) - end - insert_node_after(head,previous,new_correction_kern(italic)) + delete_node(replacehead,replaceinserted) + end + -- + if postitalic ~= 0 then + if okay(data,post,font,postchar,postitalic,char,"post") then + insert_node_after(posthead,post,new_correction_kern(postitalic)) done = true end + postitalic = 0 + elseif postinserted and data then + if trace_italics then + report_italics("deleting last correction before %s %C","post",char) + end + delete_node(posthead,postinserted) end - elseif inserted and data then - if trace_italics then - report_italics("deleting last correction before %C",char) - end - delete_node(head,inserted) - else - -- nothing end + -- lastfont = font end if data then @@ -157,63 +205,240 @@ function italics.handler(head) local cd = data[char] if not cd then -- this really can happen - italic = 0 + previtalic = 0 else - italic = cd.italic or cd.italic_correction - if not italic then - italic = setitalicinfont(font,char) -- calculated once - -- italic = 0 + previtalic = cd.italic or cd.italic_correction + if not previtalic then + previtalic = setitalicinfont(font,char) -- calculated once + -- previtalic = 0 end - if italic ~= 0 then + if previtalic ~= 0 then lastfont = font lastattr = attr - previous = current + prev = current + -- prevhead = head prevchar = char end end else - italic = 0 + previtalic = 0 end else - italic = 0 + previtalic = 0 end - inserted = nil + previnserted = nil + replaceinserted = nil + postinserted = nil elseif id == disc_code then - -- skip - elseif id == kern_code then - inserted = nil - italic = 0 + previnserted = nil + previtalic = 0 + replaceinserted = nil + replaceitalic = 0 + postinserted = nil + postitalic = 0 + replace = getfield(current,"replace") + if replace then + local current = find_tail(replace) + if getid(current) ~= glyph_code then + current = getprev(current) + end + if current and getid(current) == glyph_code then + local font = getfont(current) + local char = getchar(current) + local data = italicsdata[font] + if data then + local attr = forcedvariant or getattr(current,a_italics) + if attr and attr > 0 then + local cd = data[char] + if not cd then + -- this really can happen + replaceitalic = 0 + else + replaceitalic = cd.italic or cd.italic_correction + if not replaceitalic then + replaceitalic = setitalicinfont(font,char) -- calculated once + -- replaceitalic = 0 + end + if replaceitalic ~= 0 then + lastfont = font + lastattr = attr + replacechar = char + replacehead = replace + replace = current + end + end +-- else +-- replaceitalic = 0 + end +-- else +-- replaceitalic = 0 + end +-- else +-- replaceitalic = 0 + end +-- replaceinserted = nil +-- else +-- replaceitalic = 0 +-- replaceinserted = nil + end + post = getfield(current,"post") + if post then + local current = find_tail(post) + if getid(current) ~= glyph_code then + current = getprev(current) + end + if current and getid(current) == glyph_code then + local font = getfont(current) + local char = getchar(current) + local data = italicsdata[font] + if data then + local attr = forcedvariant or getattr(current,a_italics) + if attr and attr > 0 then + local cd = data[char] + if not cd then + -- this really can happen +-- postitalic = 0 + else + postitalic = cd.italic or cd.italic_correction + if not postitalic then + postitalic = setitalicinfont(font,char) -- calculated once + -- postitalic = 0 + end + if postitalic ~= 0 then + lastfont = font + lastattr = attr + postchar = char + posthead = post + post = current + end + end +-- else +-- postitalic = 0 + end +-- else +-- postitalic = 0 + end +-- else +-- postitalic = 0 + end +-- postinserted = nil +-- else +-- postitalic = 0 +-- postinserted = nil + end + elseif id == kern_code then -- how about fontkern ? + previnserted = nil + previtalic = 0 + replaceinserted = nil + replaceitalic = 0 + postinserted = nil + postitalic = 0 elseif id == glue_code then - if italic ~= 0 then + if previtalic ~= 0 then if trace_italics then - report_italics("inserting %p between italic %C and glue",italic,prevchar) + report_italics("inserting %p between %s italic %C and glue",previtalic,"glyph",prevchar) + end + previnserted = new_correction_glue(previtalic) -- maybe just add ? else problem with penalties + previtalic = 0 + done = true + insert_node_after(prevhead,prev,previnserted) + else + if replaceitalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and glue",replaceitalic,"replace",replacechar) + end + replaceinserted = new_correction_kern(replaceitalic) -- needs to be a kern + replaceitalic = 0 + done = true + insert_node_after(replacehead,replace,replaceinserted) + end + if postitalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and glue",postitalic,"post",postchar) + end + postinserted = new_correction_kern(postitalic) -- needs to be a kern + postitalic = 0 + done = true + insert_node_after(posthead,post,postinserted) end - inserted = new_correction_glue(italic) -- maybe just add ? else problem with penalties - insert_node_after(head,previous,inserted) - italic = 0 - done = true end elseif id == math_code then current = end_of_math(current) - elseif italic ~= 0 then - if trace_italics then - report_italics("inserting %p between italic %C and whatever",italic,prevchar) + previnserted = nil + previtalic = 0 + replaceinserted = nil + replaceitalic = 0 + postinserted = nil + postitalic = 0 + else + if previtalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and whatever",previtalic,"glyph",prevchar) + end + insert_node_after(prevhead,prev,new_correction_kern(previtalic)) + previnserted = nil + previtalic = 0 + replaceinserted = nil + replaceitalic = 0 + postinserted = nil + postitalic = 0 + done = true + else + if replaceitalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and whatever",replaceritalic,"replace",replacechar) + end + insert_node_after(replacehead,replace,new_correction_kern(replaceitalic)) + previnserted = nil + previtalic = 0 + replaceinserted = nil + replaceitalic = 0 + postinserted = nil + postitalic = 0 + done = true + end + if postitalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and whatever",postitalic,"post",postchar) + end + insert_node_after(posthead,post,new_correction_kern(postitalic)) + previnserted = nil + previtalic = 0 + replaceinserted = nil + replaceitalic = 0 + postinserted = nil + postitalic = 0 + done = true + end end - inserted = nil - insert_node_after(head,previous,new_correction_kern(italic)) - italic = 0 - done = true end current = getnext(current) end - if italic ~= 0 and lastattr > 1 then -- more control is needed here - if trace_italics then - report_italics("inserting %p between italic %C and end of list",italic,prevchar) + if lastattr and lastattr > 1 then -- more control is needed here + if previtalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and end of list",previtalic,"glyph",prevchar) + end + insert_node_after(prevhead,prev,new_correction_kern(previtalic)) + done = true + else + if replaceitalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and end of list",replaceitalic,"replace",replacechar) + end + insert_node_after(replacehead,replace,new_correction_kern(replaceitalic)) + done = true + end + if postitalic ~= 0 then + if trace_italics then + report_italics("inserting %p between %s italic %C and end of list",postitalic,"post",postchar) + end + insert_node_after(posthead,post,new_correction_kern(postitalic)) + done = true + end end - insert_node_after(head,previous,new_correction_kern(italic)) - done = true end - return tonode(head), done + return head, done end local enable @@ -241,10 +466,21 @@ function italics.reset() texsetattribute(a_italics,unsetvalue) end +implement { + name = "setitaliccorrection", + actions = italics.set, + arguments = "string" +} + +implement { + name = "resetitaliccorrection", + actions = italics.reset, +} + local variables = interfaces.variables local settings_to_hash = utilities.parsers.settings_to_hash -function commands.setupitaliccorrection(option) -- no grouping ! +local function setupitaliccorrection(option) -- no grouping ! if enable then enable() end @@ -268,16 +504,28 @@ function commands.setupitaliccorrection(option) -- no grouping ! end end +implement { + name = "setupitaliccorrection", + actions = setupitaliccorrection, + arguments = "string" +} + -- for manuals: local stack = { } -function commands.pushitaliccorrection() - table.insert(stack,{forcedvariant, texgetattribute(a_italics) }) -end +implement { + name = "pushitaliccorrection", + actions = function() + table.insert(stack,{forcedvariant, texgetattribute(a_italics) }) + end +} -function commands.popitaliccorrection() - local top = table.remove(stack) - forcedvariant = top[1] - texsetattribute(a_italics,top[2]) -end +implement { + name = "popitaliccorrection", + actions = function() + local top = table.remove(stack) + forcedvariant = top[1] + texsetattribute(a_italics,top[2]) + end +} |