if not modules then modules = { } end modules ['spac-chr'] = { version = 1.001, comment = "companion to spac-chr.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } local byte = string.byte ----- trace_characters = false trackers.register("typesetters.characters", function(v) trace_characters = v end) ----- ----- report_characters = logs.reporter("typesetting","characters") local nodes, node = nodes, node local set_attribute = node.set_attribute local insert_node_after = node.insert_after local remove_node = nodes.remove -- ! nodes local nodepool = nodes.pool local tasks = nodes.tasks local new_penalty = nodepool.penalty local new_glue = nodepool.glue local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local typesetters = typesetters local characters = { } typesetters.characters = characters local fontparameters = fonts.hashes.parameters local fontcharacters = fonts.hashes.characters local a_character = attributes.private("characters") local c_zero = byte('0') local c_period = byte('.') local function inject_quad_space(unicode,head,current,fraction) local attr = current.attr if fraction ~= 0 then fraction = fraction * fontparameters[current.font].quad end head, current = insert_node_after(head,current,new_glue(fraction)) current.attr = attr set_attribute(current,a_character,unicode) return head, current end local function inject_char_space(unicode,head,current,parent) local attr = current.attr local char = fontcharacters[current.font][parent] head, current = insert_node_after(head,current,new_glue(char and char.width or fontparameters[current.font].space)) current.attr = attr set_attribute(current,a_character,unicode) return head, current end local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink) local attr = current.attr head, current = insert_node_after(head,current,new_glue(space,spacestretch,spaceshrink)) current.attr = attr set_attribute(current,a_character,unicode) head, current = insert_node_after(head,current,new_penalty(10000)) return head, current end local methods = { [0x00A0] = function(head,current) -- nobreakspace local para = fontparameters[current.font] return inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink) end, [0x2000] = function(head,current) -- enquad return inject_quad_space(0x2000,head,current,1/2) end, [0x2001] = function(head,current) -- emquad return inject_quad_space(0x2001,head,current,1) end, [0x2002] = function(head,current) -- enspace return inject_quad_space(0x2002,head,current,1/2) end, [0x2003] = function(head,current) -- emspace return inject_quad_space(0x2003,head,current,1) end, [0x2004] = function(head,current) -- threeperemspace return inject_quad_space(0x2004,head,current,1/3) end, [0x2005] = function(head,current) -- fourperemspace return inject_quad_space(0x2005,head,current,1/4) end, [0x2006] = function(head,current) -- sixperemspace return inject_quad_space(0x2006,head,current,1/6) end, [0x2007] = function(head,current) -- figurespace return inject_char_space(0x2007,head,current,c_zero) end, [0x2008] = function(head,current) -- punctuationspace return inject_char_space(0x2008,head,current,c_period) end, [0x2009] = function(head,current) -- breakablethinspace return inject_quad_space(0x2009,head,current,1/8) -- same as next end, [0x200A] = function(head,current) -- hairspace return inject_quad_space(0x200A,head,current,1/8) -- same as previous (todo) end, [0x200B] = function(head,current) -- zerowidthspace return inject_quad_space(0x200B,head,current,0) end, [0x202F] = function(head,current) -- narrownobreakspace return inject_nobreak_space(0x202F,head,current,fontparameters[current.font].space/8) end, [0x205F] = function(head,current) -- math thinspace return inject_nobreak_space(0x205F,head,current,fontparameters[current.font].space/8) end, -- [0xFEFF] = function(head,current) -- zerowidthnobreakspace -- return head, current -- end, } function characters.handler(head) local current = head local done = false while current do local next = current.next if current.id == glyph_code then local method = methods[current.char] if method then head = method(head,current) head = remove_node(head,current,true) done = true end end current = next end return head, done end