summaryrefslogtreecommitdiff
path: root/tex/context/base/typo-spa.lua
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
committerMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
commit85b7bc695629926641c7cb752fd478adfdf374f3 (patch)
tree80293f5aaa7b95a500a78392c39688d8ee7a32fc /tex/context/base/typo-spa.lua
downloadcontext-85b7bc695629926641c7cb752fd478adfdf374f3.tar.gz
stable 2010-05-24 13:10
Diffstat (limited to 'tex/context/base/typo-spa.lua')
-rw-r--r--tex/context/base/typo-spa.lua167
1 files changed, 167 insertions, 0 deletions
diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua
new file mode 100644
index 000000000..48c7263c7
--- /dev/null
+++ b/tex/context/base/typo-spa.lua
@@ -0,0 +1,167 @@
+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"
+}
+
+-- get rid of tex.scale here
+
+local utf = unicode.utf8
+
+local next, type = next, type
+local utfchar = utf.char
+
+local trace_hspacing = false trackers.register("nodes.hspacing", function(v) trace_hspacing = v end)
+
+local has_attribute = node.has_attribute
+local unset_attribute = node.unset_attribute
+local insert_node_before = node.insert_before
+local insert_node_after = node.insert_after
+local remove_node = nodes.remove
+local make_penalty_node = nodes.penalty
+local make_glue_node = nodes.glue
+local glyph = node.id("glyph")
+
+local fontdata = fonts.identifiers
+local quaddata = fonts.quads
+
+spacings = spacings or { }
+spacings.mapping = spacings.mapping or { }
+spacings.attribute = attributes.private("spacing")
+
+storage.register("spacings/mapping", spacings.mapping, "spacings.mapping")
+
+function spacings.setspacing(id,char,left,right,alternative)
+ local mapping = spacings.mapping[id]
+ if not mapping then
+ mapping = { }
+ spacings.mapping[id] = mapping
+ end
+ local map = mapping[char]
+ if not map then
+ map = { }
+ mapping[char] = map
+ end
+ map.left, map.right, map.alternative = left, right, alternative
+end
+
+function spacings.process(namespace,attribute,head)
+ local done, mapping = false, spacings.mapping
+ 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
+ if start.id == glyph then
+ local attr = has_attribute(start,attribute)
+ if attr and attr > 0 then
+ local map = mapping[attr]
+ if map then
+ map = map[start.char]
+ unset_attribute(start,attribute) -- needed?
+ if map then
+ local left, right, alternative = map.left, map.right, map.alternative
+ local quad = quaddata[start.font]
+ local prev = start.prev
+ if left and left ~= 0 and prev then
+ local ok = false
+ if alternative == 1 then
+ local somespace = nodes.somespace(prev,true)
+ if somespace then
+ local prevprev = prev.prev
+ local somepenalty = nodes.somepenalty(prevprev,10000)
+ if somepenalty then
+ if trace_hspacing then
+ logs.report("spacing","removing penalty and space before %s", utfchar(start.char))
+ end
+ head, _ = remove_node(head,prev,true)
+ head, _ = remove_node(head,prevprev,true)
+ else
+ local somespace = nodes.somespace(prev,true)
+ if somespace then
+ if trace_hspacing then
+ logs.report("spacing","removing space before %s", utfchar(start.char))
+ end
+ head, _ = remove_node(head,prev,true)
+ end
+ end
+ end
+ ok = true
+ else
+ ok = not (nodes.somespace(prev,true) and nodes.somepenalty(prev.prev,true)) or nodes.somespace(prev,true)
+ end
+ if ok then
+ if trace_hspacing then
+ logs.report("spacing","inserting penalty and space before %s", utfchar(start.char))
+ end
+ insert_node_before(head,start,make_penalty_node(10000))
+ insert_node_before(head,start,make_glue_node(tex.scale(quad,left)))
+ done = true
+ end
+ end
+ local next = start.next
+ if right and right ~= 0 and next then
+ local ok = false
+ if alternative == 1 then
+ local somepenalty = nodes.somepenalty(next,10000)
+ if somepenalty then
+ local nextnext = next.next
+ local somespace = nodes.somespace(nextnext,true)
+ if somespace then
+ if trace_hspacing then
+ logs.report("spacing","removing penalty and space after %s", utfchar(start.char))
+ end
+ head, _ = remove_node(head,next,true)
+ head, _ = remove_node(head,nextnext,true)
+ end
+ else
+ local somespace = nodes.somespace(next,true)
+ if somespace then
+ if trace_hspacing then
+ logs.report("spacing","removing space after %s", utfchar(start.char))
+ end
+ head, _ = remove_node(head,next,true)
+ end
+ end
+ ok = true
+ else
+ ok = not (nodes.somepenalty(next,10000) and nodes.somespace(next.next,true)) or nodes.somespace(next,true)
+ end
+ if ok then
+ if trace_hspacing then
+ logs.report("spacing","inserting penalty and space after %s", utfchar(start.char))
+ end
+ insert_node_after(head,start,make_glue_node(tex.scale(quad,right)))
+ insert_node_after(head,start,make_penalty_node(10000))
+ done = true
+ end
+ end
+ end
+ end
+ end
+ end
+ start = start.next
+ end
+ return head, done
+end
+
+lists.handle_spacing = nodes.install_attribute_handler {
+ name = "spacing",
+ namespace = spacings,
+ processor = spacings.process,
+}
+
+function spacings.enable()
+ tasks.enableaction("processors","lists.handle_spacing")
+end
+
+--~ local data = {
+--~ name = "spacing",
+--~ namespace = spacings,
+--~ processor = spacings.process,
+--~ }
+--~ nodes.process_attribute = process_attribute
+--~ function lists.handle_spacing(head)
+--~ return process_attribute(head,data)
+--~ end