diff options
Diffstat (limited to 'tex/context/base/typo-spa.lua')
-rw-r--r-- | tex/context/base/typo-spa.lua | 458 |
1 files changed, 229 insertions, 229 deletions
diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua index 5eba22889..11de65f7b 100644 --- a/tex/context/base/typo-spa.lua +++ b/tex/context/base/typo-spa.lua @@ -1,229 +1,229 @@ -if not modules then modules = { } end modules ['typo-spa'] = { - version = 1.001, - comment = "companion to typo-spa.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local next, type = next, type -local utfchar = utf.char - -local trace_spacing = false trackers.register("typesetters.spacing", function(v) trace_spacing = v end) - -local report_spacing = logs.reporter("typesetting","spacing") - -local nodes, fonts, node = nodes, fonts, node - -local insert_node_before = node.insert_before -local insert_node_after = node.insert_after -local remove_node = nodes.remove -local end_of_math = node.end_of_math - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local quaddata = fonthashes.quads - -local texattribute = tex.attribute -local unsetvalue = attributes.unsetvalue - -local v_reset = interfaces.variables.reset - -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph -local math_code = nodecodes.math - -local somespace = nodes.somespace -local somepenalty = nodes.somepenalty - -local nodepool = nodes.pool -local tasks = nodes.tasks - -local new_penalty = nodepool.penalty -local new_glue = nodepool.glue - -typesetters = typesetters or { } -local typesetters = typesetters - -typesetters.spacings = typesetters.spacings or { } -local spacings = typesetters.spacings - -spacings.mapping = spacings.mapping or { } -spacings.numbers = spacings.numbers or { } - -local a_spacings = attributes.private("spacing") -spacings.attribute = a_spacings - -storage.register("typesetters/spacings/mapping", spacings.mapping, "typesetters.spacings.mapping") - -local mapping = spacings.mapping -local numbers = spacings.numbers - -for i=1,#mapping do - local m = mapping[i] - numbers[m.name] = m -end - --- todo cache lastattr - -local function process(namespace,attribute,head) - local done = false - local start = head - -- head is always begin of par (whatsit), so we have at least two prev nodes - -- penalty followed by glue - while start do - local id = start.id - if id == glyph_code then - local attr = start[attribute] - if attr and attr > 0 then - local data = mapping[attr] - if data then - local char = start.char - local map = data.characters[char] - start[attribute] = unsetvalue -- needed? - if map then - local left = map.left - local right = map.right - local alternative = map.alternative - local quad = quaddata[start.font] - local prev = start.prev - if left and left ~= 0 and prev then - local ok = false - local prevprev = prev.prev - if alternative == 1 then - local somespace = somespace(prev,true) - if somespace then - local somepenalty = somepenalty(prevprev,10000) - if somepenalty then - if trace_spacing then - report_spacing("removing penalty and space before %C (left)",char) - end - head = remove_node(head,prev,true) - head = remove_node(head,prevprev,true) - else - if trace_spacing then - report_spacing("removing space before %C (left)",char) - end - head = remove_node(head,prev,true) - end - end - ok = true - else - ok = not (somespace(prev,true) and somepenalty(prevprev,true)) or somespace(prev,true) - end - if ok then - if trace_spacing then - report_spacing("inserting penalty and space before %C (left)",char) - end - insert_node_before(head,start,new_penalty(10000)) - insert_node_before(head,start,new_glue(left*quad)) - done = true - end - end - local next = start.next - if right and right ~= 0 and next then - local ok = false - local nextnext = next.next - if alternative == 1 then - local somepenalty = somepenalty(next,10000) - if somepenalty then - local somespace = somespace(nextnext,true) - if somespace then - if trace_spacing then - report_spacing("removing penalty and space after %C right",char) - end - head = remove_node(head,next,true) - head = remove_node(head,nextnext,true) - end - else - local somespace = somespace(next,true) - if somespace then - if trace_spacing then - report_spacing("removing space after %C (right)", char) - end - head = remove_node(head,next,true) - end - end - ok = true - else - ok = not (somepenalty(next,10000) and somespace(nextnext,true)) or somespace(next,true) - end - if ok then - if trace_spacing then - report_spacing("inserting penalty and space after %C (right)",char) - end - insert_node_after(head,start,new_glue(right*quad)) - insert_node_after(head,start,new_penalty(10000)) - done = true - end - end - end - end - end - elseif id == math_code then - start = end_of_math(start) -- weird, can return nil .. no math end? - end - if start then - start = start.next - end - end - return head, done -end - -local enabled = false - -function spacings.define(name) - local data = numbers[name] - if data then - -- error - else - local number = #mapping + 1 - local data = { - name = name, - number = number, - characters = { }, - } - mapping[number] = data - numbers[name] = data - end -end - -function spacings.setup(name,char,settings) - local data = numbers[name] - if not data then - -- error - else - data.characters[char] = settings - end -end - -function spacings.set(name) - local n = unsetvalue - if name ~= v_reset then - local data = numbers[name] - if data then - if not enabled then - tasks.enableaction("processors","typesetters.spacings.handler") - enabled = true - end - n = data.number or unsetvalue - end - end - texattribute[a_spacings] = n -end - -function spacings.reset() - texattribute[a_spacings] = unsetvalue -end - -spacings.handler = nodes.installattributehandler { - name = "spacing", - namespace = spacings, - processor = process, -} - --- interface - -commands.definecharacterspacing = spacings.define -commands.setupcharacterspacing = spacings.setup -commands.setcharacterspacing = spacings.set +if not modules then modules = { } end modules ['typo-spa'] = {
+ version = 1.001,
+ comment = "companion to typo-spa.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next, type = next, type
+local utfchar = utf.char
+
+local trace_spacing = false trackers.register("typesetters.spacing", function(v) trace_spacing = v end)
+
+local report_spacing = logs.reporter("typesetting","spacing")
+
+local nodes, fonts, node = nodes, fonts, node
+
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+local remove_node = nodes.remove
+local end_of_math = node.end_of_math
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local quaddata = fonthashes.quads
+
+local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local math_code = nodecodes.math
+
+local somespace = nodes.somespace
+local somepenalty = nodes.somepenalty
+
+local nodepool = nodes.pool
+local tasks = nodes.tasks
+
+local new_penalty = nodepool.penalty
+local new_glue = nodepool.glue
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.spacings = typesetters.spacings or { }
+local spacings = typesetters.spacings
+
+spacings.mapping = spacings.mapping or { }
+spacings.numbers = spacings.numbers or { }
+
+local a_spacings = attributes.private("spacing")
+spacings.attribute = a_spacings
+
+storage.register("typesetters/spacings/mapping", spacings.mapping, "typesetters.spacings.mapping")
+
+local mapping = spacings.mapping
+local numbers = spacings.numbers
+
+for i=1,#mapping do
+ local m = mapping[i]
+ numbers[m.name] = m
+end
+
+-- todo cache lastattr
+
+local function process(namespace,attribute,head)
+ local done = false
+ local start = head
+ -- head is always begin of par (whatsit), so we have at least two prev nodes
+ -- penalty followed by glue
+ while start do
+ local id = start.id
+ if id == glyph_code then
+ local attr = start[attribute]
+ if attr and attr > 0 then
+ local data = mapping[attr]
+ if data then
+ local char = start.char
+ local map = data.characters[char]
+ start[attribute] = unsetvalue -- needed?
+ if map then
+ local left = map.left
+ local right = map.right
+ local alternative = map.alternative
+ local quad = quaddata[start.font]
+ local prev = start.prev
+ if left and left ~= 0 and prev then
+ local ok = false
+ local prevprev = prev.prev
+ if alternative == 1 then
+ local somespace = somespace(prev,true)
+ if somespace then
+ local somepenalty = somepenalty(prevprev,10000)
+ if somepenalty then
+ if trace_spacing then
+ report_spacing("removing penalty and space before %C (left)",char)
+ end
+ head = remove_node(head,prev,true)
+ head = remove_node(head,prevprev,true)
+ else
+ if trace_spacing then
+ report_spacing("removing space before %C (left)",char)
+ end
+ head = remove_node(head,prev,true)
+ end
+ end
+ ok = true
+ else
+ ok = not (somespace(prev,true) and somepenalty(prevprev,true)) or somespace(prev,true)
+ end
+ if ok then
+ if trace_spacing then
+ report_spacing("inserting penalty and space before %C (left)",char)
+ end
+ insert_node_before(head,start,new_penalty(10000))
+ insert_node_before(head,start,new_glue(left*quad))
+ done = true
+ end
+ end
+ local next = start.next
+ if right and right ~= 0 and next then
+ local ok = false
+ local nextnext = next.next
+ if alternative == 1 then
+ local somepenalty = somepenalty(next,10000)
+ if somepenalty then
+ local somespace = somespace(nextnext,true)
+ if somespace then
+ if trace_spacing then
+ report_spacing("removing penalty and space after %C right",char)
+ end
+ head = remove_node(head,next,true)
+ head = remove_node(head,nextnext,true)
+ end
+ else
+ local somespace = somespace(next,true)
+ if somespace then
+ if trace_spacing then
+ report_spacing("removing space after %C (right)", char)
+ end
+ head = remove_node(head,next,true)
+ end
+ end
+ ok = true
+ else
+ ok = not (somepenalty(next,10000) and somespace(nextnext,true)) or somespace(next,true)
+ end
+ if ok then
+ if trace_spacing then
+ report_spacing("inserting penalty and space after %C (right)",char)
+ end
+ insert_node_after(head,start,new_glue(right*quad))
+ insert_node_after(head,start,new_penalty(10000))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ elseif id == math_code then
+ start = end_of_math(start) -- weird, can return nil .. no math end?
+ end
+ if start then
+ start = start.next
+ end
+ end
+ return head, done
+end
+
+local enabled = false
+
+function spacings.define(name)
+ local data = numbers[name]
+ if data then
+ -- error
+ else
+ local number = #mapping + 1
+ local data = {
+ name = name,
+ number = number,
+ characters = { },
+ }
+ mapping[number] = data
+ numbers[name] = data
+ end
+end
+
+function spacings.setup(name,char,settings)
+ local data = numbers[name]
+ if not data then
+ -- error
+ else
+ data.characters[char] = settings
+ end
+end
+
+function spacings.set(name)
+ local n = unsetvalue
+ if name ~= v_reset then
+ local data = numbers[name]
+ if data then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.spacings.handler")
+ enabled = true
+ end
+ n = data.number or unsetvalue
+ end
+ end
+ texattribute[a_spacings] = n
+end
+
+function spacings.reset()
+ texattribute[a_spacings] = unsetvalue
+end
+
+spacings.handler = nodes.installattributehandler {
+ name = "spacing",
+ namespace = spacings,
+ processor = process,
+}
+
+-- interface
+
+commands.definecharacterspacing = spacings.define
+commands.setupcharacterspacing = spacings.setup
+commands.setcharacterspacing = spacings.set
|