1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
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 has_attribute = node.has_attribute
local unset_attribute = node.unset_attribute
local set_attribute = node.set_attribute
local hpack_node = node.hpack
local traverse_id = node.traverse_id
local insert_before = node.insert_before
local insert_after = node.insert_after
local texattribute = tex.attribute
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
local nodepool = nodes.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 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")
digits.attribute = a_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_before(head,start,new_glue(0,65536,65536))
end
if how == "flushleft" or how == "middle" then
head, stop = insert_after(head,stop,new_glue(0,65536,65536))
end
local prv, nxt = start.prev, stop.next
start.prev, stop.next = nil, nil
local packed = hpack_node(start,width,"exactly") -- no directional mess here, just lr
if prv then
prv.next, packed.prev = packed, prv
end
if nxt then
nxt.prev, packed.next = packed, nxt
end
if packed.prev then
return head, packed
else
return packed, packed
end
end
actions[1] = function(head,start,attribute,attr)
local font = start.font
local char = start.char
local unic = chardata[font][char].tounicode
local what = unic and tonumber(unic,16) or char
if charbase[what].category == "nd" then
local oldwidth, newwidth = start.width, getdigitwidth(font)
if newwidth ~= oldwidth then
if trace_digits then
report_digits("digit trigger %s, instance %s, char 0x%05X, unicode 0x%05X, delta %s",
attr%100,div(attr,100),char,what,newwidth-oldwidth)
end
head, start = nodes.aligned(head,start,start,newwidth,"middle")
return head, start, true
end
end
return head, start, false
end
local function process(namespace,attribute,head)
local done, current, ok = false, head, false
while current do
if current.id == glyph_code then
local attr = has_attribute(current,attribute)
if attr and attr > 0 then
unset_attribute(current,attribute)
local action = actions[attr%100] -- map back to low number
if action then
head, current, ok = action(head,current,attribute,attr)
done = done and ok
elseif trace_digits then
report_digits("unknown digit trigger %s",attr)
end
end
end
current = current and current.next
end
return head, done
end
local m, enabled = 0, false -- a trick to make neighbouring ranges work
function digits.set(n)
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
texattribute[a_digits] = m * 100 + n
end
digits.handler = nodes.installattributehandler {
name = "digits",
namespace = digits,
processor = process,
}
|