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