summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/typo-dig.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkxl/typo-dig.lmt')
-rw-r--r--tex/context/base/mkxl/typo-dig.lmt181
1 files changed, 181 insertions, 0 deletions
diff --git a/tex/context/base/mkxl/typo-dig.lmt b/tex/context/base/mkxl/typo-dig.lmt
new file mode 100644
index 000000000..7f6663db9
--- /dev/null
+++ b/tex/context/base/mkxl/typo-dig.lmt
@@ -0,0 +1,181 @@
+if not modules then modules = { } end modules ['typo-dig'] = {
+ version = 1.001,
+ optimize = true,
+ 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, tonumber = next, type, tonumber
+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 getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getwidth = nuts.getwidth
+local isglyph = nuts.isglyph
+local getattr = nuts.getattr
+
+local setlink = nuts.setlink
+local setnext = nuts.setnext
+local setprev = nuts.setprev
+
+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 find_attribute = nuts.find_attribute
+local unset_attributes = nuts.unset_attributes
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local nodepool = nuts.pool
+local enableaction = nodes.tasks.enableaction
+
+local new_glue = nodepool.glue
+
+local fonthashes = fonts.hashes
+local chardata = fonthashes.characters
+
+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 char, font = isglyph(start)
+ local unic = chardata[font][char].unicode or char
+ if charbase[unic].category == "nd" then -- ignore unic tables
+ local oldwidth = getwidth(start)
+ 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
+ end
+ end
+ return head, start
+end
+
+function digits.handler(head)
+ local _, start = find_attribute(head, a_digits)
+ if start then
+ local current = head
+ while current do
+ if getid(current) == glyph_code then
+ local attr = getattr(current,a_digits)
+ if attr and attr > 0 then
+ local action = actions[attr%100] -- map back to low number
+ if action then
+ head, current = action(head,current,attr)
+ elseif trace_digits then
+ report_digits("unknown digit trigger %a",attr)
+ end
+ done = true
+ end
+ end
+ if current then
+ current = getnext(current)
+ end
+ end
+ if done then
+ unset_attributes(a_digits, head)
+ end
+ end
+ return head
+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
+ 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"
+}