1if not modules then modules = { } end modules ['trac-riv'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to trac-riv.mkxl",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10local concat = table.concat
11local floor, ceiling = math.floor, math.ceiling
12local newindex = lua.newindex
13
14local nuts = nodes.nuts
15
16local getbox = nuts.getbox
17
18local getid = nuts.getid
19local getsubtype = nuts.getsubtype
20local getnext = nuts.getnext
21local getwhd = nuts.getwhd
22local getwidth = nuts.getwidth
23local getkern = nuts.getkern
24local getlist = nuts.getlist
25local getleader = nuts.getleader
26local getreplace = nuts.getreplace
27local getheight = nuts.getheight
28local getdepth = nuts.getdepth
29
30local setlink = nuts.setlink
31local setlist = nuts.setlist
32local setoffsets = nuts.setoffsets
33local setkern = nuts.setkern
34
35local effectiveglue = nuts.effectiveglue
36
37local setcolor = nodes.tracers.colors.set
38
39local newrule = nuts.pool.rule
40local newkern = nuts.pool.kern
41
42local nextnode = nuts.traversers.node
43
44local nodecodes = nodes.nodecodes
45local gluecodes = nodes.gluecodes
46
47local glyph_code <const> = nodecodes.glyph
48local disc_code <const> = nodecodes.disc
49local penalty_code <const> = nodecodes.penalty
50local kern_code <const> = nodecodes.kern
51local glue_code <const> = nodecodes.glue
52local hlist_code <const> = nodecodes.hlist
53local vlist_code <const> = nodecodes.vlist
54local math_code <const> = nodecodes.math
55local rule_code <const> = nodecodes.rule
56
57local spaceskip_code <const> = gluecodes.spaceskip
58local xspaceskip_code <const> = gluecodes.xspaceskip
59local lineskip_code <const> = gluecodes.lineskip
60local baselineskip_code <const> = gluecodes.baselineskip
61
62local fontkern_code <const> = nodes.kerncodes.fontkern
63local linelist_code <const> = nodes.listcodes.line
64
65local unit = 65536
66local step = 2 * unit
67local margin = -1 * unit
68local skip = 10 * unit
69local height = 2 * unit
70local depth = 2 * unit
71
72local function analyze(line,max)
73
74 local width = 0
75 local position = 0
76 local profile = newindex(max+2,0)
77 local wd = 0
78 local state = 0
79
80 local function process(current)
81 for current, id, subtype in nextnode, current do
82 if id == glyph_code then
83
84 local w, h, d = getwhd(current)
85 wd = w
86 if d <= depth and h <= height then
87 local n = getnext(current)
88 if n and getid(n) == glue_code then
89 local s = getsubtype(n)
90 if s == spaceskip_code or s == xspaceskip_code then
91 state = 1
92 end
93 end
94 end
95 elseif id == kern_code then
96 wd = getkern(current)
97 if wd > 0 and subtype ~= fontkern_code then
98 state = 1
99 end
100 elseif id == disc_code then
101 local replace = getreplace(current)
102 if replace then
103 process(replace)
104 end
105 goto done
106 elseif id == glue_code then
107 wd = effectiveglue(current,line)
108 if wd > 0 and subtype == spaceskip_code or subtype == xspaceskip_code then
109 state = 1
110 end
111 elseif id == hlist_code then
112 wd = getwidth(current)
113 elseif id == vlist_code then
114 wd = getwidth(current)
115 elseif id == rule_code then
116 wd = getwidth(current)
117 elseif id == math_code then
118 wd = getkern(current) + getwidth(current)
119 state = 1
120 else
121 goto done
122 end
123
124 position = width
125 width = position + wd
126 p = floor((position - margin)/step + 0.5)
127 w = floor((width + margin)/step - 0.5)
128 if p < 0 then
129 p = 0
130 end
131 if w < 0 then
132 w = 0
133 end
134 if p > w then
135 w, p = p, w
136 end
137 if state == 1 then
138 for i=p+1,w+1 do
139 profile[i] = state
140 end
141 state = 0
142 end
143 ::done::
144 end
145 end
146
147 process(getlist(line))
148
149 return profile
150
151end
152
153function builders.profiling.getrivers(specification)
154 local box = getbox(specification.box)
155 local head = getlist(box)
156 if head then
157
158 step = (specification.step or 2 * unit)
159 margin = (specification.margin or -1 * unit)
160 skip = (specification.gluethreshold or 10 * unit)
161 height = (specification.height or 2 * unit)
162 depth = (specification.depth or 2 * unit)
163
164 local profiles = { }
165 local max = ceiling(getwidth(box)/step) + 1
166
167 local p = 0
168
169 p = p + 1 ; profiles[p] = newindex(max+2,1)
170 p = p + 1 ; profiles[p] = newindex(max+2,0)
171
172 for current, id, subtype in nextnode, head do
173 if id == hlist_code then
174 local amount = getwidth(current)
175 if amount > 0 then
176 p = p + 1 ; profiles[p] = analyze(current,max)
177 end
178 elseif id == glue_code then
179 if subtype == baselineskip_code or subtype == lineskip_code then
180
181 elseif getwidth(current) > skip then
182 p = p + 1 ; profiles[p] = newindex(max+2,0)
183 end
184 elseif id == vlist_code then
185 p = p + 1 ; profiles[p] = newindex(max+2,0)
186 end
187 end
188
189 p = p + 1 ; profiles[p] = newindex(max+2,0)
190 p = p + 1 ; profiles[p] = newindex(max+2,1)
191
192 for i=1,p do
193 local pi = profiles[i]
194 pi[0] = 1 ; pi[max ] = 1
195 pi[1] = 1 ; pi[max+1] = 1
196 profiles[i] = concat(pi,"",0,max+1)
197 end
198 profiles = concat(profiles,"\n")
199 potrace.setbitmap("profile", profiles)
200 end
201end
202
203function builders.profiling.addrivers(specification)
204 local box = getbox(specification.box)
205 local head = getlist(box)
206 if head then
207
208 step = (specification.step or 2 * unit)
209 margin = (specification.margin or -1 * unit)
210 skip = (specification.gluethreshold or 10 * unit)
211 height = (specification.height or 2 * unit)
212 depth = (specification.depth or 2 * unit)
213
214 local profiles = { }
215 local max = ceiling(getwidth(box)/step) + 1
216
217 local previous = false
218 local spacing = 0
219
220 local topline = false
221 local botline = false
222
223 local list = newindex(max+2,false)
224
225 for current, id, subtype in nextnode, head do
226 if id == hlist_code then
227 local amount = getwidth(current)
228 if amount > 0 then
229 botline = analyze(current,max)
230 if topline then
231 local head = false
232 local tail = false
233 for i=1,max do
234 if topline[i] ~= 0 and botline[i] ~= 0 then
235 local _, hp, dp = getwhd(previous)
236 local _, hc, dc = getwhd(previous)
237 local rule = newrule(step,hp + dp + spacing + hc,dc)
238 local kern = newkern()
239 setkern(kern,-step)
240 setoffsets(rule,i*step,0)
241 setlink(rule,kern)
242 if tail then
243 setlink(tail,rule)
244 else
245 head = rule
246 end
247 tail = kern
248 local li = list[i]
249 if li then
250 li[#li+1] = rule
251 for i=1,#li do
252 setcolor(li[i],"darkred")
253 end
254 else
255 list[i] = { rule }
256 setcolor(rule,"darkblue")
257 end
258 else
259 list[i] = false
260 end
261 end
262 if head then
263 setlink(tail,getlist(current))
264 setlist(current,head)
265 end
266 end
267 topline = botline
268 botline = false
269 previous = current
270 end
271 elseif id == glue_code then
272 local width = getwidth(current)
273 if subtype == baselineskip_code or subtype == lineskip_code then
274 spacing = width
275 elseif width > skip then
276 topline = false
277 botline = false
278 end
279 elseif id == vlist_code then
280 topline = false
281 botline = false
282 end
283 end
284
285 end
286end
287
288interfaces.implement {
289 name = "getrivers",
290 protected = true,
291 actions = builders.profiling.getrivers,
292 arguments = {
293 {
294 { "box", "integer" },
295 { "height", "dimension" },
296 { "depth", "dimension" },
297 { "step", "dimension" },
298 { "margin", "dimension" },
299 { "skip", "dimension" },
300 }
301 }
302}
303
304
305
306interfaces.implement {
307 name = "addrivers",
308 protected = true,
309 actions = builders.profiling.addrivers,
310 arguments = {
311 {
312 { "box", "integer" },
313 { "height", "dimension" },
314 { "depth", "dimension" },
315 { "step", "dimension" },
316 { "margin", "dimension" },
317 { "skip", "dimension" },
318 }
319 }
320}
321 |