summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-dig.lua
diff options
context:
space:
mode:
authorContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2016-01-12 17:15:07 +0100
commit8d8d528d2ad52599f11250cfc567fea4f37f2a8b (patch)
tree94286bc131ef7d994f9432febaf03fe23d10eef8 /tex/context/base/mkiv/typo-dig.lua
parentf5aed2e51223c36c84c5f25a6cad238b2af59087 (diff)
downloadcontext-8d8d528d2ad52599f11250cfc567fea4f37f2a8b.tar.gz
2016-01-12 16:26:00
Diffstat (limited to 'tex/context/base/mkiv/typo-dig.lua')
-rw-r--r--tex/context/base/mkiv/typo-dig.lua181
1 files changed, 181 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/typo-dig.lua b/tex/context/base/mkiv/typo-dig.lua
new file mode 100644
index 000000000..09c2f64ee
--- /dev/null
+++ b/tex/context/base/mkiv/typo-dig.lua
@@ -0,0 +1,181 @@
+if not modules then modules = { } end modules ['typo-dig'] = {
+ version = 1.001,
+ comment = "companion to typo-dig.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- we might consider doing this after the otf pass because now osf do not work
+-- out well in node mode.
+
+local next, type = next, type
+local format, insert = string.format, table.insert
+local round, div = math.round, math.div
+
+local trace_digits = false trackers.register("typesetters.digits", function(v) trace_digits = v end)
+
+local report_digits = logs.reporter("typesetting","digits")
+
+local nodes, node = nodes, node
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+local getid = nuts.getid
+local getfield = nuts.getfield
+local getattr = nuts.getattr
+
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+local setattr = nuts.setattr
+
+local hpack_node = nuts.hpack
+local traverse_id = nuts.traverse_id
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local nodepool = nuts.pool
+local tasks = nodes.tasks
+
+local new_glue = nodepool.glue
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local chardata = fonthashes.characters
+local quaddata = fonthashes.quads
+
+local v_reset = interfaces.variables.reset
+
+local charbase = characters.data
+local getdigitwidth = fonts.helpers.getdigitwidth
+
+typesetters = typesetters or { }
+local typesetters = typesetters
+
+typesetters.digits = typesetters.digits or { }
+local digits = typesetters.digits
+
+digits.actions = { }
+local actions = digits.actions
+
+local a_digits = attributes.private("digits")
+
+-- at some point we can manipulate the glyph node so then i need
+-- to rewrite this then
+
+function nodes.aligned(head,start,stop,width,how)
+ if how == "flushright" or how == "middle" then
+ head, start = insert_node_before(head,start,new_glue(0,65536,65536))
+ end
+ if how == "flushleft" or how == "middle" then
+ head, stop = insert_node_after(head,stop,new_glue(0,65536,65536))
+ end
+ local prv = getprev(start)
+ local nxt = getnext(stop)
+ setprev(start)
+ setnext(stop)
+ local packed = hpack_node(start,width,"exactly") -- no directional mess here, just lr
+ if prv then
+ setlink(prv,packed)
+ end
+ if nxt then
+ setlink(packed,nxt)
+ end
+ if getprev(packed) then
+ return head, packed
+ else
+ return packed, packed
+ end
+end
+
+actions[1] = function(head,start,attr)
+ local font = getfont(start)
+ local char = getchar(start)
+ local unic = chardata[font][char].unicode or char
+ if charbase[unic].category == "nd" then -- ignore unic tables
+ local oldwidth = getfield(start,"width")
+ local newwidth = getdigitwidth(font)
+ if newwidth ~= oldwidth then
+ if trace_digits then
+ report_digits("digit trigger %a, instance %a, char %C, unicode %U, delta %s",
+ attr%100,div(attr,100),char,unic,newwidth-oldwidth)
+ end
+ head, start = nodes.aligned(head,start,start,newwidth,"middle")
+ return head, start, true
+ end
+ end
+ return head, start, false
+end
+
+function digits.handler(head)
+ head = tonut(head)
+ local done, current, ok = false, head, false
+ while current do
+ if getid(current) == glyph_code then
+ local attr = getattr(current,a_digits)
+ if attr and attr > 0 then
+ setattr(current,a_digits,unsetvalue)
+ local action = actions[attr%100] -- map back to low number
+ if action then
+ head, current, ok = action(head,current,attr)
+ done = done and ok
+ elseif trace_digits then
+ report_digits("unknown digit trigger %a",attr)
+ end
+ end
+ end
+ if current then
+ current = getnext(current)
+ end
+ end
+ return tonode(head), done
+end
+
+local m, enabled = 0, false -- a trick to make neighbouring ranges work
+
+function digits.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = tonumber(n)
+ if n then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.digits.handler")
+ if trace_digits then
+ report_digits("enabling digit handler")
+ end
+ enabled = true
+ end
+ if m == 100 then
+ m = 1
+ else
+ m = m + 1
+ end
+ n = m * 100 + n
+ else
+ n = unsetvalue
+ end
+ end
+ texsetattribute(a_digits,n)
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setdigitsmanipulation",
+ actions = digits.set,
+ arguments = "string"
+}