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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
if not modules then modules = { } end modules ['math-dir'] = {
version = 1.001,
comment = "companion to typo-dir.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
-- As I'm wrapping up the updated math support (for CTX/TUG 2013) I wondered about numbers in
-- r2l math mode. Googling lead me to TUGboat, Volume 25 (2004), No. 2 where I see numbers
-- running from left to right. Makes me wonder how far we should go. And as I was looking
-- into bidi anyway, it's a nice distraction.
--
-- I first tried to hook something into noads but that gets pretty messy due to indirectness
-- char noads. If needed, I'll do it that way. With regards to spacing: as we can assume that
-- only numbers are involved we can safely swap them and the same is true for mirroring. But
-- anyway, I'm not too happy with this solution so eventually I'll do something with noads (as
-- an alternative method). Yet another heuristic approach.
local nodes, node = nodes, node
local trace_directions = false trackers.register("typesetters.directions.math", function(v) trace_directions = v end)
local report_directions = logs.reporter("typesetting","math directions")
local nuts = nodes.nuts
local tonut = nuts.tonut
local tonode = nuts.tonode
local getnext = nuts.getnext
local getchar = nuts.getchar
local getid = nuts.getid
local getlist = nuts.getlist
local setfield = nuts.setfield
local getattr = nuts.getattr
local insert_node_before = nuts.insert_before
local insert_node_after = nuts.insert_after
local nodecodes = nodes.nodecodes
local tasks = nodes.tasks
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local nodepool = nuts.pool
local new_textdir = nodepool.textdir
local chardirections = characters.directions
local charmirrors = characters.mirrors
local charclasses = characters.textclasses
local directions = typesetters.directions or { }
local a_mathbidi = attributes.private('mathbidi')
local function processmath(head)
local current = head
local done = false
local start = nil
local stop = nil
local function capsulate()
head = insert_node_before(head,start,new_textdir("+TLT"))
insert_node_after(head,stop,new_textdir("-TLT"))
if trace_directions then
report_directions("reversed: %s",nodes.listtoutf(start,false,false,stop))
end
done = true
start = false
stop = nil
end
while current do
local id = getid(current)
if id == glyph_code then
local char = getchar(current)
local cdir = chardirections[char]
if cdir == "en" or cdir == "an" then -- we could check for mathclass punctuation
if not start then
start = current
end
stop = current
else
if not start then
-- nothing
elseif start == stop then
start = nil
else
capsulate()
end
if cdir == "on" then
local mirror = charmirrors[char]
if mirror then
local class = charclasses[char]
if class == "open" or class == "close" then
setfield(current,"char",mirror)
if trace_directions then
report_directions("mirrored: %C to %C",char,mirror)
end
done = true
end
end
end
end
elseif not start then
-- nothing
if id == hlist_code or id == vlist_code then
local list, d = processmath(getlist(current))
setfield(current,"list",list)
if d then
done = true
end
end
elseif start == stop then
start = nil
else
capsulate(head,start,stop)
-- math can pack things into hlists .. we need to make sure we don't process
-- too often: needs checking
if id == hlist_code or id == vlist_code then
local list, d = processmath(getlist(current))
setfield(current,"list",list)
if d then
done = true
end
end
end
current = getnext(current)
end
if not start then
-- nothing
elseif start == stop then
-- nothing
else
capsulate()
end
return head, done
end
local enabled = false
function directions.processmath(head) -- style, penalties
if enabled then
local h = tonut(head)
local a = getattr(h,a_mathbidi)
if a and a > 0 then
local head, done = processmath(h)
return tonode(head), done
end
end
return head, false
end
function directions.setmath(n)
if not enabled and n and n > 0 then
if trace_directions then
report_directions("enabling directions handler")
end
tasks.enableaction("math","typesetters.directions.processmath")
enabled = true
end
end
interfaces.implement {
name = "setmathdirection",
actions = directions.setmath,
arguments = "integer"
}
|