1if not modules then modules = { } end modules ['node-res'] = {
2 version = 1.001,
3 comment = "companion to node-ini.mkiv",
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 type, next, rawset = type, next, rawset
10local gmatch, format = string.gmatch, string.format
11
12
16
17local nodes, node = nodes, node
18
19local report_nodes = logs.reporter("nodes","housekeeping")
20
21nodes.pool = nodes.pool or { }
22local nodepool = nodes.pool
23
24local gluecodes = nodes.gluecodes
25local kerncodes = nodes.kerncodes
26local rulecodes = nodes.rulecodes
27local nodecodes = nodes.nodecodes
28local boundarycodes = nodes.boundarycodes
29local usercodes = nodes.usercodes
30
31local nodeproperties = nodes.properties.data
32
33local glyph_code = nodecodes.glyph
34local rule_code = nodecodes.rule
35local kern_code = nodecodes.kern
36local glue_code = nodecodes.glue
37local gluespec_code = nodecodes.gluespec
38
39local currentfont = font.current
40local texgetcount = tex.getcount
41
42local allocate = utilities.storage.allocate
43
44local reserved = { }
45local nofreserved = 0
46
47
48
49local nuts = nodes.nuts
50local nutpool = { }
51nuts.pool = nutpool
52
53local tonut = nuts.tonut
54local tonode = nuts.tonode
55
56local getbox = nuts.getbox
57local getid = nuts.getid
58local getlist = nuts.getlist
59local getglue = nuts.getglue
60
61local setfield = nuts.setfield
62local setchar = nuts.setchar
63local setlist = nuts.setlist
64local setwhd = nuts.setwhd
65local setglue = nuts.setglue
66local setdisc = nuts.setdisc
67local setfont = nuts.setfont
68local setkern = nuts.setkern
69local setpenalty = nuts.setpenalty
70local setdir = nuts.setdir
71local setdirection = nuts.setdirection
72local setshift = nuts.setshift
73local setwidth = nuts.setwidth
74local setsubtype = nuts.setsubtype
75local setleader = nuts.setleader
76
77local setdata = nuts.setdata
78local setruledata = nuts.setruledata
79local setvalue = nuts.setvalue
80
81local copy_nut = nuts.copyonly
82local new_nut = nuts.new
83local flush_nut = nuts.flush
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101table.setmetatableindex(nodepool,function(t,k,v)
102
103 local v = function(...)
104 local f = nutpool[k]
105 local v = function(...)
106 return tonode(f(...))
107 end
108 t[k] = v
109 return v(...)
110 end
111 t[k] = v
112 return v
113end)
114
115local function register_nut(n)
116 nofreserved = nofreserved + 1
117 reserved[nofreserved] = n
118 return n
119end
120
121local function register_node(n)
122 nofreserved = nofreserved + 1
123 if type(n) == "number" then
124 reserved[nofreserved] = n
125 else
126 reserved[nofreserved] = tonut(n)
127 end
128 return n
129end
130
131nodepool.register = register_node
132nutpool.register = register_node
133
134
135
136local disc = register_nut(new_nut(nodecodes.disc))
137local kern = register_nut(new_nut(kern_code,kerncodes.userkern))
138local fontkern = register_nut(new_nut(kern_code,kerncodes.fontkern))
139local italickern = register_nut(new_nut(kern_code,kerncodes.italiccorrection))
140local penalty = register_nut(new_nut(nodecodes.penalty))
141local glue = register_nut(new_nut(glue_code))
142local gluespec = register_nut(new_nut(gluespec_code))
143local glyph = register_nut(new_nut(glyph_code,0))
144
145local textdir = register_nut(new_nut(nodecodes.dir))
146
147local left_margin_kern = register_nut(new_nut(kern_code,kerncodes.leftmargincode))
148local right_margin_kern = register_nut(new_nut(kern_code,kerncodes.rightmargincode))
149
150local lineskip = register_nut(new_nut(glue_code,gluecodes.lineskip))
151local baselineskip = register_nut(new_nut(glue_code,gluecodes.baselineskip))
152local leftskip = register_nut(new_nut(glue_code,gluecodes.leftskip))
153local rightskip = register_nut(new_nut(glue_code,gluecodes.rightskip))
154local lefthangskip = register_nut(new_nut(glue_code,gluecodes.lefthangskip))
155local righthangskip = register_nut(new_nut(glue_code,gluecodes.righthangskip))
156local indentskip = register_nut(new_nut(glue_code,gluecodes.indentskip))
157local correctionskip = register_nut(new_nut(glue_code,gluecodes.correctionskip))
158
159local temp = register_nut(new_nut(nodecodes.temp,0))
160
161local noad = register_nut(new_nut(nodecodes.noad))
162local delimiter = register_nut(new_nut(nodecodes.delimiter))
163local fence = register_nut(new_nut(nodecodes.fence))
164local submlist = register_nut(new_nut(nodecodes.submlist))
165local accent = register_nut(new_nut(nodecodes.accent))
166local radical = register_nut(new_nut(nodecodes.radical))
167local fraction = register_nut(new_nut(nodecodes.fraction))
168local subbox = register_nut(new_nut(nodecodes.subbox))
169local mathchar = register_nut(new_nut(nodecodes.mathchar))
170local mathtextchar = register_nut(new_nut(nodecodes.mathtextchar))
171local choice = register_nut(new_nut(nodecodes.choice))
172
173local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user))
174local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word))
175
176local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0)
177
178
179
180local lefttoright_code = nodes.dirvalues.lefttoright
181
182local rule = register_nut(new_nut(rule_code))
183local emptyrule = register_nut(new_nut(rule_code,rulecodes.empty))
184local userrule = register_nut(new_nut(rule_code,rulecodes.user))
185local outlinerule = register_nut(new_nut(rule_code,rulecodes.outline))
186local imagerule = register_nut(new_nut(rule_code,rulecodes.image))
187local boxrule = register_nut(new_nut(rule_code,rulecodes.box))
188local hlist = register_nut(new_nut(nodecodes.hlist)) setdirection(hlist,lefttoright_code)
189local vlist = register_nut(new_nut(nodecodes.vlist)) setdirection(vlist,lefttoright_code)
190
191function nutpool.glyph(fnt,chr)
192 local n = copy_nut(glyph)
193 if fnt then
194 setfont(n,fnt == true and currentfont() or fnt,chr)
195 elseif chr then
196 setchar(n,chr)
197 end
198 return n
199end
200
201function nutpool.penalty(p)
202 local n = copy_nut(penalty)
203 if p and p ~= 0 then
204 setpenalty(n,p)
205 end
206 return n
207end
208
209function nutpool.kern(k)
210 local n = copy_nut(kern)
211 if k and k ~= 0 then
212 setkern(n,k)
213 end
214 return n
215end
216
217function nutpool.boundary(v)
218 local n = copy_nut(boundary)
219 if v and v ~= 0 then
220 setvalue(n,v)
221 end
222 return n
223end
224
225function nutpool.wordboundary(v)
226 local n = copy_nut(wordboundary)
227 if v and v ~= 0 then
228 setvalue(n,v)
229 end
230 return n
231end
232
233function nutpool.fontkern(k)
234 local n = copy_nut(fontkern)
235 if k and k ~= 0 then
236 setkern(n,k)
237 end
238 return n
239end
240
241function nutpool.italickern(k)
242 local n = copy_nut(italickern)
243 if k and k ~= 0 then
244 setkern(n,k)
245 end
246 return n
247end
248
249function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
250 local n = copy_nut(gluespec)
251 if width or stretch or shrink or stretch_order or shrink_order then
252 setglue(n,width,stretch,shrink,stretch_order,shrink_order)
253 end
254 return n
255end
256
257local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order)
258
259 local n = copy_nut(skip)
260 if width or stretch or shrink or stretch_order or shrink_order then
261 setglue(n,width,stretch,shrink,stretch_order,shrink_order)
262 end
263 return n
264end
265
266function nutpool.stretch(a,b)
267
268 local n = copy_nut(glue)
269 if not b then
270 a, b = 1, a or 1
271 end
272 setglue(n,0,a,0,b,0)
273 return n
274end
275
276function nutpool.shrink(a,b)
277 local n = copy_nut(glue)
278 if not b then
279 a, b = 1, a or 1
280 end
281 setglue(n,0,0,a,0,0,b)
282 return n
283end
284
285function nutpool.glue(width,stretch,shrink,stretch_order,shrink_order)
286 return someskip(glue,width,stretch,shrink,stretch_order,shrink_order)
287end
288
289function nutpool.negatedglue(glue)
290 local n = copy_nut(glue)
291 local width, stretch, shrink = getglue(n)
292 setglue(n,-width,-stretch,-shrink)
293 return n
294end
295
296function nutpool.leftskip(width,stretch,shrink,stretch_order,shrink_order)
297 return someskip(leftskip,width,stretch,shrink,stretch_order,shrink_order)
298end
299
300function nutpool.rightskip(width,stretch,shrink,stretch_order,shrink_order)
301 return someskip(rightskip,width,stretch,shrink,stretch_order,shrink_order)
302end
303
304function nutpool.lefthangskip(width,stretch,shrink,stretch_order,shrink_order)
305 return someskip(lefthangskip,width,stretch,shrink,stretch_order,shrink_order)
306end
307
308function nutpool.righthangskip(width,stretch,shrink,stretch_order,shrink_order)
309 return someskip(righthangskip,width,stretch,shrink,stretch_order,shrink_order)
310end
311
312function nutpool.indentskip(width,stretch,shrink,stretch_order,shrink_order)
313 return someskip(indentskip,width,stretch,shrink,stretch_order,shrink_order)
314end
315
316function nutpool.lineskip(width,stretch,shrink,stretch_order,shrink_order)
317 return someskip(lineskip,width,stretch,shrink,stretch_order,shrink_order)
318end
319
320function nutpool.baselineskip(width,stretch,shrink)
321 return someskip(baselineskip,width,stretch,shrink)
322end
323
324function nutpool.disc(pre,post,replace)
325 local d = copy_nut(disc)
326 if pre or post or replace then
327 setdisc(d,pre,post,replace)
328 end
329 return d
330end
331
332function nutpool.direction(dir,swap)
333 local t = copy_nut(textdir)
334 if not dir then
335
336 elseif swap then
337 setdirection(t,dir,true)
338 else
339 setdirection(t,dir,false)
340 end
341 return t
342end
343
344function nutpool.rule(width,height,depth)
345 local n = copy_nut(rule)
346 if width or height or depth then
347 setwhd(n,width,height,depth)
348 end
349 return n
350end
351
352function nutpool.emptyrule(width,height,depth)
353 local n = copy_nut(emptyrule)
354 if width or height or depth then
355 setwhd(n,width,height,depth)
356 end
357 return n
358end
359
360function nutpool.userrule(width,height,depth)
361 local n = copy_nut(userrule)
362 if width or height or depth then
363 setwhd(n,width,height,depth)
364 end
365 return n
366end
367
368function nutpool.outlinerule(width,height,depth,line)
369 local n = copy_nut(outlinerule)
370 if width or height or depth then
371 setwhd(n,width,height,depth)
372 end
373 if line then
374 setruledata(n,line)
375 end
376 return n
377end
378
379function nutpool.imagerule(width,height,depth)
380 local n = copy_nut(imagerule)
381 if width or height or depth then
382 setwhd(n,width,height,depth)
383 end
384 return n
385end
386
387function nutpool.boxrule(width,height,depth)
388 local n = copy_nut(boxrule)
389 if width or height or depth then
390 setwhd(n,width,height,depth)
391 end
392 return n
393end
394
395function nutpool.leader(width,list)
396 local n = copy_nut(cleader)
397 if width then
398 setwidth(n,width)
399 end
400 if list then
401 setleader(n,list)
402 end
403 return n
404end
405
406function nutpool.leftmarginkern(glyph,width)
407 local n = copy_nut(left_margin_kern)
408 if not glyph then
409 report_nodes("invalid pointer to left margin glyph node")
410 elseif getid(glyph) ~= glyph_code then
411 report_nodes("invalid node type %a for %s margin glyph node",nodecodes[glyph],"left")
412 else
413 setfield(n,"glyph",glyph)
414 end
415 if width and width ~= 0 then
416 setwidth(n,width)
417 end
418 return n
419end
420
421function nutpool.rightmarginkern(glyph,width)
422 local n = copy_nut(right_margin_kern)
423 if not glyph then
424 report_nodes("invalid pointer to right margin glyph node")
425 elseif getid(glyph) ~= glyph_code then
426 report_nodes("invalid node type %a for %s margin glyph node",nodecodes[p],"right")
427 else
428 setfield(n,"glyph",glyph)
429 end
430 if width and width ~= 0 then
431 setwidth(n,width)
432 end
433 return n
434end
435
436function nutpool.temp()
437 return copy_nut(temp)
438end
439
440function nutpool.noad() return copy_nut(noad) end
441function nutpool.delimiter() return copy_nut(delimiter) end nutpool.delim = nutpool.delimiter
442function nutpool.fence() return copy_nut(fence) end
443function nutpool.submlist() return copy_nut(submlist) end
444function nutpool.noad() return copy_nut(noad) end
445function nutpool.fence() return copy_nut(fence) end
446function nutpool.accent() return copy_nut(accent) end
447function nutpool.radical() return copy_nut(radical) end
448function nutpool.fraction() return copy_nut(fraction) end
449function nutpool.subbox() return copy_nut(subbox) end
450function nutpool.mathchar() return copy_nut(mathchar) end
451function nutpool.mathtextchar() return copy_nut(mathtextchar) end
452function nutpool.choice() return copy_nut(choice) end
453
454local function new_hlist(list,width,height,depth,shift)
455 local n = copy_nut(hlist)
456 if list then
457 setlist(n,list)
458 end
459 if width or height or depth then
460 setwhd(n,width,height,depth)
461 end
462 if shift and shift ~= 0 then
463 setshift(n,shift)
464 end
465 return n
466end
467
468local function new_vlist(list,width,height,depth,shift)
469 local n = copy_nut(vlist)
470 if list then
471 setlist(n,list)
472 end
473 if width or height or depth then
474 setwhd(n,width,height,depth)
475 end
476 if shift and shift ~= 0 then
477 setshift(n,shift)
478 end
479 return n
480end
481
482nutpool.hlist = new_hlist
483nutpool.vlist = new_vlist
484
485function nodepool.hlist(list,width,height,depth,shift)
486 return tonode(new_hlist(list and tonut(list),width,height,depth,shift))
487end
488
489function nodepool.vlist(list,width,height,depth,shift)
490 return tonode(new_vlist(list and tonut(list),width,height,depth,shift))
491end
492
493function nutpool.usernode(id,data)
494 local n = copy_nut(user_node)
495 nodeproperties[n] = {
496 id = id,
497 data = data,
498 }
499 return n
500end
501
502
503
504local function cleanup(nofboxes)
505
506 local tracers = nodes.tracers
507 if tracers and tracers.steppers then
508 tracers.steppers.reset()
509 end
510 local nl = 0
511 local nr = nofreserved
512 for i=1,nofreserved do
513 local ri = reserved[i]
514 flush_nut(reserved[i])
515 end
516 if nofboxes then
517 for i=0,nofboxes do
518 local l = getbox(i)
519 if l then
520 flush_nut(l)
521 nl = nl + 1
522 end
523 end
524 end
525 reserved = { }
526 nofreserved = 0
527 return nr, nl, nofboxes
528end
529
530local usage = node.inuse
531local stock = node.instock
532
533nutpool .cleanup = cleanup
534nodepool.cleanup = cleanup
535
536nutpool .usage = usage
537nodepool.usage = usage
538
539nutpool .stock = stock
540nodepool.stock = stock
541
542
543
544statistics.register("cleaned up reserved nodes", function()
545 return format("%s nodes, %s lists of %s", cleanup(texgetcount("c_syst_last_allocated_box")))
546end)
547
548statistics.register("node memory usage", function()
549 local used = usage()
550 if next(used) then
551 local t, n = { }, 0
552 for k, v in table.sortedhash(used) do
553 n = n + 1 ; t[n] = format("%s %s",v,k)
554 end
555 return table.concat(t,", ")
556 end
557end)
558
559lua.registerinitexfinalizer(cleanup, "cleanup reserved nodes")
560
561do
562
563 local glyph = glyph
564 local traverseid = nuts.traverseid
565
566 local traversers = table.setmetatableindex(function(t,k)
567 local v = traverseid(type(k) == "number" and k or nodecodes[k],glyph)
568 t[k] = v
569 return v
570 end)
571
572 local treversers = table.setmetatableindex(function(t,k)
573 local v = traverseid(type(k) == "number" and k or nodecodes[k],glyph,true)
574 t[k] = v
575 return v
576 end)
577
578
579
580 traversers.node = nuts.traverse (glyph)
581 traversers.char = nuts.traversechar (glyph)
582 traversers.glyph = nuts.traverseglyph (glyph)
583 traversers.list = nuts.traverselist (glyph)
584 traversers.content = nuts.traversecontent(glyph)
585
586 treversers.node = nuts.traverse (glyph,true)
587 treversers.char = nuts.traversechar (glyph,true)
588 treversers.glyph = nuts.traverseglyph (glyph,true)
589 treversers.list = nuts.traverselist (glyph,true)
590 treversers.content = nuts.traversecontent(glyph,true)
591
592 nuts.traversers = traversers
593 nuts.treversers = treversers
594
595end
596 |