1if not modules then modules = { } end modules ['typo-stc'] = {
2 version = 1.001,
3 comment = "companion to typo-stc.mkxl",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local tonumber, next = tonumber, next
10local gmatch = string.gmatch
11local stepper = utilities.parsers.stepper
12
13
14
15
16
17local nodes, node = nodes, node
18local nuts = nodes.nuts
19local tonut = nuts.tonut
20
21local nodecodes = nodes.nodecodes
22
23local glyph_code <const> = nodecodes.glyph
24local disc_code <const> = nodecodes.disc
25local hlist_code <const> = nodecodes.hlist
26local vlist_code <const> = nodecodes.vlist
27local whatsit_code <const> = nodecodes.whatsit
28local rule_code <const> = nodecodes.rule
29local glue_code <const> = nodecodes.glue
30
31local emptyrule_code <const> = nodes.rulecodes.empty
32
33local a_stacking <const> = attributes.private("stacking")
34
35local getattr = nuts.getattr
36local getwhd = nuts.getwhd
37local getlist = nuts.getlist
38local setlist = nuts.setlist
39local setleader = nuts.setleader
40local getsubtype = nuts.getsubtype
41local setsubtype = nuts.setsubtype
42local isnextglyph = nuts.isnextglyph
43
44local replace_node = nuts.replace
45local remove_node = nuts.remove
46
47local nextcontent = nuts.traversers.content
48
49local new_emptyrule = nuts.pool.emptyrule
50
51
52local unblocked = {
53 savepos = true,
54 save = true,
55 restore = true,
56 setmatrix = true,
57 startmatrix = true,
58 stopmatrix = true,
59 startscaling = true,
60 stopscaling = true,
61 startrotation = true,
62 stoprotation = true,
63 startmirroring = true,
64 stopmirroring = true,
65 startclipping = true,
66 stopclipping = true,
67}
68
69local stacking = typesetters.stacking or { }
70typesetters.stacking = stacking
71
72local nofstacking = 0xFFFF
73local registered = { }
74local currentset = { }
75local enabled = false
76
77local function getselection(str)
78 local t = { }
79 stepper(str,function(s)
80 local r = registered[s] or tonumber(s)
81 if r then
82 t[r] = true
83 end
84 end)
85 return t
86end
87
88local function getindex(str)
89 return registered[str] or tonumber(str) or 0
90end
91
92typesetters.stacking.getselection = getselection
93typesetters.stacking.getindex = getindex
94
95local report = logs.reporter("stacking")
96local trace = false
97
98interfaces.implement {
99 name = "newstacking",
100 arguments = "2 strings",
101 usage = "value",
102 actions = function(s,n)
103 n = n and tonumber(n)
104 if not n then
105 nofstacking = nofstacking + 1
106 n = nofstacking
107 end
108 registered[s] = n
109 if trace then
110 report("define %a as index %i",s,n)
111 end
112 return tokens.values.integer, n
113 end,
114}
115
116interfaces.implement {
117 name = "enablestacking",
118 actions = function()
119 if not enabled then
120 nodes.tasks.enableaction("shipouts", "typesetters.stacking.handler")
121 enabled = true
122 end
123 end,
124}
125
126interfaces.implement {
127 name = "setstacking",
128 arguments = "string",
129 actions = function(str)
130 currentset = getselection(str)
131 if not enabled and next(currentset) then
132 if trace then
133 report("selecting %a",str)
134 end
135 nodes.tasks.enableaction("shipouts", "typesetters.stacking.handler")
136 enabled = true
137 end
138 end,
139}
140
141local function process(head)
142 local current = head
143 while current do
144 local nxt, chr, id = isnextglyph(current)
145 if chr then
146 local a = getattr(current,a_stacking)
147 if a and (a == 0 or not currentset[a]) then
148 local w, h, d = getwhd(current)
149 local r = new_emptyrule(w,h,d)
150 head, current = replace_node(head,current,r)
151 end
152 elseif id == glue_code then
153 local a = getattr(current,a_stacking)
154 if a and (a == 0 or not currentset[a]) then
155 setleader(current)
156 end
157 elseif id == hlist_code or id == vlist_code then
158 local a = getattr(current,a_stacking)
159 if a and (a == 0 or not currentset[a]) then
160 setlist(current)
161 else
162 local list = getlist(current)
163 if list then
164 local l = process(list)
165 if l ~= list then
166 setlist(current,l)
167 end
168 end
169 end
170 elseif id == rule_code then
171 local a = getattr(current,a_stacking)
172 if a and not currentset[a] then
173 setsubtype(current,emptyrule_code)
174 end
175 elseif id == whatsit_code then
176 local a = getattr(current,a_stacking)
177 if a and (a == 0 or not currentset[a]) and not unblocked[getsubtype(current)] then
178 head, current = remove_node(head,current,true)
179 end
180 elseif id == disc_code then
181
182 local a = getattr(current,a_stacking)
183 if a and (a == 0 or not currentset[a]) then
184 local w, h, d = getwhd(current)
185 local r = new_emptyrule(w,h,d)
186 head, current = replace_node(head,current,r)
187 end
188 end
189 current = nxt
190 end
191 return head
192end
193
194stacking.handler = process
195 |