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