1if not modules then modules = { } end modules ['typo-dig'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to typo-dig.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10
11
12
13local next, type, tonumber = next, type, tonumber
14local format, insert = string.format, table.insert
15local round, div = math.round, math.div
16
17local trace_digits = false trackers.register("typesetters.digits", function(v) trace_digits = v end)
18
19local report_digits = logs.reporter("typesetting","digits")
20
21local nodes, node = nodes, node
22
23local nuts = nodes.nuts
24
25local getnext = nuts.getnext
26local getprev = nuts.getprev
27local getid = nuts.getid
28local getwidth = nuts.getwidth
29local isglyph = nuts.isglyph
30local takeattr = nuts.takeattr
31
32local setlink = nuts.setlink
33local setnext = nuts.setnext
34local setprev = nuts.setprev
35
36local hpacknode = nuts.hpack
37local insertnodebefore = nuts.insertbefore
38local insertnodeafter = nuts.insertafter
39
40local texsetattribute = tex.setattribute
41local unsetvalue = attributes.unsetvalue
42
43local nodecodes = nodes.nodecodes
44local glyph_code = nodecodes.glyph
45
46local nodepool = nuts.pool
47local enableaction = nodes.tasks.enableaction
48
49local new_glue = nodepool.glue
50
51local fonthashes = fonts.hashes
52local chardata = fonthashes.characters
53
54local v_reset = interfaces.variables.reset
55
56local charbase = characters.data
57local getdigitwidth = fonts.helpers.getdigitwidth
58
59typesetters = typesetters or { }
60local typesetters = typesetters
61
62typesetters.digits = typesetters.digits or { }
63local digits = typesetters.digits
64
65digits.actions = { }
66local actions = digits.actions
67
68local a_digits = attributes.private("digits")
69
70
71
72
73function nodes.aligned(head,start,stop,width,how)
74 if how == "flushright" or how == "middle" then
75 head, start = insertnodebefore(head,start,new_glue(0,65536,65536))
76 end
77 if how == "flushleft" or how == "middle" then
78 head, stop = insertnodeafter(head,stop,new_glue(0,65536,65536))
79 end
80 local prv = getprev(start)
81 local nxt = getnext(stop)
82 setprev(start)
83 setnext(stop)
84 local packed = hpacknode(start,width,"exactly")
85 if prv then
86 setlink(prv,packed)
87 end
88 if nxt then
89 setlink(packed,nxt)
90 end
91 if getprev(packed) then
92 return head, packed
93 else
94 return packed, packed
95 end
96end
97
98actions[1] = function(head,start,attr)
99 local char, font = isglyph(start)
100 local unic = chardata[font][char].unicode or char
101 if charbase[unic].category == "nd" then
102 local oldwidth = getwidth(start)
103 local newwidth = getdigitwidth(font)
104 if newwidth ~= oldwidth then
105 if trace_digits then
106 report_digits("digit trigger %a, instance %a, char %C, unicode %U, delta %s",
107 attr%100,div(attr,100),char,unic,newwidth-oldwidth)
108 end
109 head, start = nodes.aligned(head,start,start,newwidth,"middle")
110 return head, start
111 end
112 end
113 return head, start
114end
115
116function digits.handler(head)
117 local current = head
118 while current do
119 if getid(current) == glyph_code then
120 local attr = takeattr(current,a_digits)
121 if attr and attr > 0 then
122 local action = actions[attr%100]
123 if action then
124 head, current = action(head,current,attr)
125 elseif trace_digits then
126 report_digits("unknown digit trigger %a",attr)
127 end
128 end
129 end
130 if current then
131 current = getnext(current)
132 end
133 end
134 return head
135end
136
137local m, enabled = 0, false
138
139function digits.set(n)
140 if n == v_reset then
141 n = unsetvalue
142 else
143 n = tonumber(n)
144 if n then
145 if not enabled then
146 enableaction("processors","typesetters.digits.handler")
147 if trace_digits then
148 report_digits("enabling digit handler")
149 end
150 enabled = true
151 end
152 if m == 100 then
153 m = 1
154 else
155 m = m + 1
156 end
157 n = m * 100 + n
158 else
159 n = unsetvalue
160 end
161 end
162 texsetattribute(a_digits,n)
163end
164
165
166
167interfaces.implement {
168 name = "setdigitsmanipulation",
169 actions = digits.set,
170 arguments = "string"
171}
172 |