1if not modules then modules = { } end modules ['node-rul'] = {
2 version = 1.001,
3 optimize = true,
4 comment = "companion to node-rul.mkiv",
5 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10
11
12
13
14
15
16
17
18
19
20
21local tonumber = tonumber
22
23local context = context
24local attributes = attributes
25local nodes = nodes
26local properties = nodes.properties.data
27
28local enableaction = nodes.tasks.enableaction
29
30local nuts = nodes.nuts
31local tonode = nuts.tonode
32local tonut = nuts.tonut
33
34local setnext = nuts.setnext
35local setprev = nuts.setprev
36local setlink = nuts.setlink
37local getnext = nuts.getnext
38local getprev = nuts.getprev
39local getid = nuts.getid
40local getdirection = nuts.getdirection
41local getattr = nuts.getattr
42local setattr = nuts.setattr
43local setattrs = nuts.setattrs
44local getfont = nuts.getfont
45local getsubtype = nuts.getsubtype
46local setsubtype = nuts.setsubtype
47local getlist = nuts.getlist
48local setwhd = nuts.setwhd
49local setattrlist = nuts.setattrlist
50local setshift = nuts.setshift
51local getwidth = nuts.getwidth
52local setwidth = nuts.setwidth
53local setweight = nuts.setweight
54local setoffsets = nuts.setoffsets
55local setfield = nuts.setfield
56local getruledata = nuts.getruledata
57local yscaled = nuts.yscaled
58
59local isglyph = nuts.isglyph
60local firstglyphnode = nuts.firstglyphnode
61
62local flushlist = nuts.flushlist
63local effectiveglue = nuts.effectiveglue
64local insertnodeafter = nuts.insertafter
65local insertnodebefore = nuts.insertbefore
66local find_tail = nuts.tail
67local setglue = nuts.setglue
68local getrangedimensions = nuts.rangedimensions
69local hpack_nodes = nuts.hpack
70local copylist = nuts.copylist
71
72local nextlist = nuts.traversers.list
73local nextglue = nuts.traversers.glue
74local nextglyph = nuts.traversers.glyph
75
76local nodecodes = nodes.nodecodes
77local rulecodes = nodes.rulecodes
78local gluecodes = nodes.gluecodes
79local listcodes = nodes.listcodes
80
81local glyph_code <const> = nodecodes.glyph
82local par_code <const> = nodecodes.par
83local dir_code <const> = nodecodes.dir
84local glue_code <const> = nodecodes.glue
85local hlist_code <const> = nodecodes.hlist
86
87local indentlist_code <const> = listcodes.indent
88local linelist_code <const> = listcodes.line
89local container_code <const> = listcodes.container
90
91local leftskip_code <const> = gluecodes.leftskip
92local rightskip_code <const> = gluecodes.rightskip
93local parfillleftskip_code <const> = gluecodes.parfillleftskip
94local parfillrightskip_code <const> = gluecodes.parfillrightskip
95local indentskip_code <const> = gluecodes.indentskip
96
97local nodepool = nuts.pool
98
99local new_rule = nodepool.rule
100local new_userrule = nodepool.userrule
101local new_kern = nodepool.kern
102local new_leader = nodepool.leader
103
104local n_tostring = nodes.idstostring
105local n_tosequence = nodes.tosequence
106
107local variables = interfaces.variables
108local implement = interfaces.implement
109
110local privateattribute = attributes.private
111
112local a_ruled <const> = privateattribute('ruled')
113local a_runningtext <const> = privateattribute('runningtext')
114local a_color <const> = privateattribute('color')
115local a_transparency <const> = privateattribute('transparency')
116local a_colormodel <const> = privateattribute('colormodel')
117local a_linefiller <const> = privateattribute("linefiller")
118local a_viewerlayer <const> = privateattribute("viewerlayer")
119
120local registervalue = attributes.registervalue
121local getvalue = attributes.getvalue
122local texsetattribute = tex.setattribute
123
124local v_both <const> = variables.both
125local v_left <const> = variables.left
126local v_right <const> = variables.right
127local v_local <const> = variables["local"]
128local v_yes <const> = variables.yes
129local v_foreground <const> = variables.foreground
130
131local fonthashes = fonts.hashes
132local fontdata = fonthashes.identifiers
133local fontresources = fonthashes.resources
134
135local glyphdimenfactor = fonts.helpers.glyphdimenfactor
136local splitdimen = number.splitdimen
137local setmetatableindex = table.setmetatableindex
138
139local runningrule <const> = tex.magicconstants.runningrule
140
141local striprange = nuts.striprange
142local processwords = nuts.processwords
143
144local setcoloring = nuts.colors.set
145
146do
147
148 local rules = nodes.rules or { }
149 nodes.rules = rules
150
151
152 local nutrules = nuts.rules or { }
153 nuts.rules = nutrules
154
155
156
157 local function usernutrule(t,noattributes)
158 local r = new_userrule(t.width or 0,t.height or 0,t.depth or 0)
159 if noattributes == false or noattributes == nil then
160
161 else
162 setattrlist(r,true)
163 end
164 properties[r] = t
165 return r
166 end
167
168 nutrules.userrule = usernutrule
169
170 local function userrule(t,noattributes)
171 return tonode(usernutrule(t,noattributes))
172 end
173
174 rules.userrule = userrule
175 local ruleactions = { }
176
177 rules .ruleactions = ruleactions
178 nutrules.ruleactions = ruleactions
179
180 local function mathaction(n,h,v,what)
181 local font = getruledata(n)
182 local actions = fontresources[font].mathruleactions
183 if actions then
184 local action = actions[what]
185 if action then
186 action(n,h,v,font)
187 end
188 end
189 end
190
191 local function mathradical(n,h,v)
192 mathaction(n,h,v,"radicalaction")
193 end
194
195 local function mathrule(n,h,v)
196 mathaction(n,h,v,"hruleaction")
197 end
198
199 local function useraction(n,h,v)
200 local p = properties[n]
201 if p then
202 local i = p.type or "draw"
203 local a = ruleactions[i]
204 if a then
205 a(p,h,v,i,n)
206 end
207 end
208 end
209
210 local subtypeactions = {
211 [rulecodes.user] = useraction,
212 [rulecodes.over] = mathrule,
213 [rulecodes.under] = mathrule,
214 [rulecodes.fraction] = mathrule,
215 [rulecodes.radical] = mathradical,
216 }
217
218 function rules.process(n,h,v)
219 local n = tonut(n)
220 local s = getsubtype(n)
221 local a = subtypeactions[s]
222 if a then
223 a(n,h,v)
224 end
225 end
226
227 local trace_ruled = false trackers.register("nodes.rules", function(v) trace_ruled = v end)
228 local report_ruled = logs.reporter("nodes","rules")
229 local enabled = false
230
231 local texgetattribute = tex.getattribute
232
233 local unsetvalue <const> = attributes.unsetvalue
234
235
236
237
238 function rules.set(settings)
239 if not enabled then
240 enableaction("shipouts","nodes.rules.handler")
241 enabled = true
242 end
243 local text = settings.text
244 if text then
245 settings.text = tonut(text)
246
247 end
248
249 local attr = texgetattribute(a_ruled)
250 if attr ~= unsetvalue then
251 settings.nestingvalue = attr
252 settings.nestingdata = getvalue(a_ruled,attr)
253 end
254 texsetattribute(a_ruled,registervalue(a_ruled,settings))
255 end
256
257 attributes.setcleaner(a_ruled,function(t)
258 local text = t.text
259 if text then
260 flushlist(text)
261 end
262 end)
263
264
265
266 local function flush_ruled(head,f,l,d,level,parent,strip)
267 local max = d.max or 1
268 local level = d.stack or d.level or 1
269 if level > max then
270
271 return head
272 end
273
274
275
276
277
278 local font = nil
279 local glph = nil
280 local char, id = isglyph(f)
281 if char then
282 font = id
283 glph = f
284 elseif id == hlist_code then
285 font = getattr(f,a_runningtext)
286 else
287
288 if id == disc_code then
289 font = usesfont(f)
290 end
291
292 if not font then
293 local g = firstglyphnode(f,l)
294 if g then
295 font = getfont(g)
296 end
297 end
298 end
299 if not font then
300
301 return head
302 end
303 local r, m
304 if strip then
305 if trace_ruled then
306 local before = n_tosequence(f,l,true)
307 f, l = striprange(f,l)
308 local after = n_tosequence(f,l,true)
309 report_ruled("range stripper, before %a, after %a",before,after)
310 else
311 f, l = striprange(f,l)
312 end
313 end
314 if not f then
315 return head
316 end
317 local wd, ht, dp = getrangedimensions(parent,f,getnext(l))
318 local method = d.method or 0
319 local empty = d.empty == v_yes
320 local offset = d.offset or 0
321 local dy = d.dy or 0
322 local order = d.order
323 local mp = d.mp
324 local rulethickness = d.rulethickness
325 local unit = d.unit or "ex"
326 local ma = d.ma
327 local ca = d.ca
328 local ta = d.ta
329 local colorspace = ma > 0 and ma or getattr(f,a_colormodel) or 1
330 local color = ca > 0 and ca or getattr(f,a_color)
331 local transparency = ta > 0 and ta or getattr(f,a_transparency)
332 local foreground = order == v_foreground
333 local layer = getattr(f,a_viewerlayer)
334 local e = glyphdimenfactor(unit,glph,font)
335 local rt = tonumber(rulethickness)
336 if rt then
337 rulethickness = e * rulethickness / 2
338 else
339 local n, u = splitdimen(rulethickness)
340 if n and u then
341 rulethickness = n * glyphdimenfactor(u,glyph,font) / 2
342 else
343 rulethickness = 1/5
344 end
345 end
346
347
348 if level > max then
349 level = max
350 end
351 if method == 0 then
352 offset = 2*offset
353 m = (offset+(level-1)*dy)*e/2 + rulethickness/2
354 else
355 m = 0
356 end
357
358 local function inject(r,wd,ht,dp)
359 if layer then
360 setattr(r,a_viewerlayer,layer)
361 end
362 if empty then
363 head = insertnodebefore(head,f,r)
364 setlink(r,getnext(l))
365 setprev(f)
366 setnext(l)
367 flushlist(f)
368 else
369 local k = new_kern(-wd)
370 if foreground then
371 insertnodeafter(head,l,k)
372 insertnodeafter(head,k,r)
373 l = r
374 else
375 head = insertnodebefore(head,f,r)
376 insertnodeafter(head,r,k)
377 end
378 end
379 if trace_ruled then
380 report_ruled("level %a, width %p, height %p, depth %p, nodes %a, text %a",
381 level,wd,ht,dp,n_tostring(f,l),n_tosequence(f,l,true))
382 end
383 end
384
385 if mp and mp ~= "" then
386 local r = usernutrule {
387 width = wd,
388 height = ht,
389 depth = dp,
390 type = "mp",
391 factor = e,
392 offset = offset - (level-1)*dy,
393 line = rulethickness,
394 data = mp,
395 ma = colorspace,
396 ca = color,
397 ta = transparency,
398 }
399 inject(r,wd,ht,dp)
400 else
401 local tx = d.text
402 if tx then
403 local l = copylist(tx)
404 if d["repeat"] == v_yes then
405 l = new_leader(wd,l)
406 setattrlist(l,tx)
407 end
408 l = hpack_nodes(l,wd,"exactly")
409 inject(l,wd,ht,dp)
410 else
411 local rule
412 if method == 2 or method == 3 then
413 local height = d.height
414 local depth = d.depth
415 if height > ht then ht = height end
416 if depth > dp then dp = depth end
417 local of = offset
418 ht = ht + of
419 dp = dp + of
420 wd = wd + 2*of
421 if method == 2 then
422 rule = nodepool.outlinerule(wd,ht,dp,rulethickness)
423 else
424 rule = nodepool.rule(wd,ht,dp)
425 end
426 setoffsets(rule,-of,0)
427 else
428 local hd = (offset+(level-1)*dy)*e - m
429 ht = hd + rulethickness
430 dp = -hd + rulethickness
431 rule = new_rule(wd,ht,dp)
432 end
433 inject(setcoloring(rule,colorspace,color,transparency),wd,ht,dp)
434 end
435 end
436 return head
437 end
438
439 rules.handler = function(head)
440 local data = attributes.values[a_ruled]
441
442 if data then
443 head = processwords(a_ruled,data,flush_ruled,head)
444 end
445 return head
446 end
447
448 implement {
449 name = "setrule",
450 actions = rules.set,
451 arguments = {
452 {
453 { "continue" },
454 { "unit" },
455 { "order" },
456 { "level", "integer" },
457 { "stack", "integer" },
458 { "method", "integer" },
459 { "offset", "number" },
460 { "rulethickness" },
461 { "dy", "number" },
462 { "max", "number" },
463 { "ma", "integer" },
464 { "ca", "integer" },
465 { "ta", "integer" },
466 { "mp" },
467 { "empty" },
468 { "text", "box" },
469 { "repeat" },
470 { "height", "dimension" },
471 { "depth", "dimension" },
472 }
473 }
474 }
475
476end
477
478do
479
480 local trace_shifted = false trackers.register("nodes.shifting", function(v) trace_shifted = v end)
481 local report_shifted = logs.reporter("nodes","shifting")
482 local a_shifted <const> = privateattribute('shifted')
483 local enabled = false
484
485 local shifts = nodes.shifts or { }
486 nodes.shifts = shifts
487
488 function shifts.set(settings)
489 if not enabled then
490
491 enableaction("shipouts","nodes.shifts.handler")
492 enabled = true
493 end
494 texsetattribute(a_shifted,registervalue(a_shifted,settings))
495 end
496
497 local function flush_shifted(head,first,last,data,level,parent,strip)
498 if true then
499 first, last = striprange(first,last)
500 end
501 local prev = getprev(first)
502 local next = getnext(last)
503 setprev(first)
504 setnext(last)
505 local width, height, depth = getrangedimensions(parent,first,next)
506 local list = hpack_nodes(first,width,"exactly")
507 if first == head then
508 head = list
509 end
510 if prev then
511 setlink(prev,list)
512 end
513 if next then
514 setlink(list,next)
515 end
516 local raise = data.dy * glyphdimenfactor(data.unit,first)
517 setshift(list,raise)
518 setwhd(list,width,height,depth)
519 if trace_shifted then
520 report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true))
521 end
522 return head
523 end
524
525 shifts.handler = function(head)
526 local data = attributes.values[a_shifted]
527 if data then
528 head = processwords(a_shifted,data,flush_shifted,head)
529 end
530 return head
531 end
532
533 implement {
534 name = "setshift",
535 actions = shifts.set,
536 arguments = {
537 {
538 { "continue" },
539 { "unit" },
540 { "method", "integer" },
541 { "dy", "number" },
542 }
543 }
544 }
545
546end
547
548
549
550do
551
552 local linefillers = nodes.linefillers or { }
553 nodes.linefillers = linefillers
554 local enabled = false
555
556 local usernutrule = nuts.rules.userrule
557
558 function linefillers.set(settings)
559 if not enabled then
560 enableaction("finalizers","nodes.linefillers.handler")
561 enabled = true
562 end
563 texsetattribute(a_linefiller,registervalue(a_linefiller,settings))
564 end
565
566 local function linefiller(current,data,width,location)
567 local height = data.height
568 local depth = data.depth
569 local mp = data.mp
570 local ma = data.ma
571 local ca = data.ca
572 local ta = data.ta
573 if mp and mp ~= "" then
574 return usernutrule {
575 width = width,
576 height = height,
577 depth = depth,
578 type = "mp",
579 line = data.rulethickness,
580 data = mp,
581 ma = ma,
582 ca = ca,
583 ta = ta,
584 option = location,
585 direction = getdirection(current),
586 }
587 else
588 return setcoloring(new_rule(width,height,depth),ma,ca,ta)
589 end
590 end
591
592 function linefillers.filler(current,data,width,height,depth)
593 if width and width > 0 then
594 local height = height or data.height or 0
595 local depth = depth or data.depth or 0
596 if (height + depth) ~= 0 then
597 local mp = data.mp
598 local ma = data.ma
599 local ca = data.ca
600 local ta = data.ta
601 if mp and mp ~= "" then
602 return usernutrule {
603 width = width,
604 height = height,
605 depth = depth,
606 type = "mp",
607 line = data.rulethickness,
608 data = mp,
609 ma = ma,
610 ca = ca,
611 ta = ta,
612 option = location,
613 direction = getdirection(current),
614 }
615 else
616 return setcoloring(new_rule(width,height,depth),ma,ca,ta)
617 end
618 end
619 end
620 end
621
622 local function getskips(list)
623 local ls = nil
624 local rs = nil
625 local is = nil
626 local pl = nil
627 local pr = nil
628 local ok = false
629 for n, subtype in nextglue, list do
630 if subtype == rightskip_code then
631 rs = n
632 elseif subtype == parfillrightskip_code then
633 pr = n
634 elseif subtype == leftskip_code then
635 ls = n
636 elseif subtype == indentskip_code then
637 is = n
638 elseif subtype == parfillleftskip_code then
639 pl = n
640 end
641 end
642 return is, ls, pl, pr, rs
643 end
644
645 linefillers.handler = function(head)
646 local data = attributes.values[a_linefiller]
647 if data then
648
649 for current, id, subtype, list in nextlist, head do
650 if subtype == linelist_code and list then
651 local a = getattr(current,a_linefiller)
652 if a then
653 local data = data[a]
654 if data then
655 local location = data.location
656 local scope = data.scope
657 local distance = data.distance
658 local threshold = data.threshold
659 local leftlocal = false
660 local rightlocal = false
661
662 if scope == v_right then
663 leftlocal = true
664 elseif scope == v_left then
665 rightlocal = true
666 elseif scope == v_local then
667 leftlocal = true
668 rightlocal = true
669 end
670
671 local is, ls, pl, pr, rs = getskips(list)
672 if ls and rs then
673 if location == v_left or location == v_both then
674 local indentation = is and getwidth(is) or 0
675 local leftfixed = ls and getwidth(ls) or 0
676 local lefttotal = ls and effectiveglue(ls,current) or 0
677 local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance
678 if width > threshold then
679 if is then
680 setwidth(is,0)
681 end
682 setglue(ls,leftlocal and getwidth(ls) or nil)
683 if distance > 0 then
684 insertnodeafter(list,ls,new_kern(distance))
685 end
686 insertnodeafter(list,ls,linefiller(current,data,width,"left"))
687 end
688 end
689
690 if location == v_right or location == v_both then
691 local rightfixed = rs and getwidth(rs) or 0
692 local righttotal = rs and effectiveglue(rs,current) or 0
693 local parfixed = pr and getwidth(pr) or 0
694 local partotal = pr and effectiveglue(pr,current) or 0
695 local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance
696 if width > threshold then
697 if pr then
698 setglue(pr)
699 end
700 setglue(rs,rightlocal and getwidth(rs) or nil)
701 if distance > 0 then
702 insertnodebefore(list,rs,new_kern(distance))
703 end
704 insertnodebefore(list,rs,linefiller(current,data,width,"right"))
705 end
706 end
707 else
708
709 end
710 end
711 end
712 end
713 end
714 end
715 return head
716 end
717
718 implement {
719 name = "setlinefiller",
720 actions = linefillers.set,
721 arguments = {
722 {
723 { "method", "integer" },
724 { "location", "string" },
725 { "scope", "string" },
726 { "mp", "string" },
727 { "ma", "integer" },
728 { "ca", "integer" },
729 { "ta", "integer" },
730 { "depth", "dimension" },
731 { "height", "dimension" },
732 { "distance", "dimension" },
733 { "threshold", "dimension" },
734 { "rulethickness", "dimension" },
735 }
736 }
737 }
738
739end
740
741
742
743interfaces.implement {
744 name = "autorule",
745 protected = true,
746 public = true,
747 arguments = {
748 {
749 { "width", "dimension" },
750 { "height", "dimension" },
751 { "depth", "dimension" },
752 { "xoffset", "dimension" },
753 { "yoffset", "dimension" },
754 { "left", "dimension" },
755 { "right", "dimension" },
756 { "on", "dimension" },
757 { "off", "dimension" },
758 },
759 },
760 actions = function(t)
761 local n = new_rule(
762 t.width or runningrule,
763 t.height or runningrule,
764 t.depth or runningrule
765 )
766 setattrlist(n,true)
767 setoffsets(n,t.xoffset,t.yoffset,t.left,t.right,t.on,t.off)
768 context(tonode(n))
769 end
770}
771
772
773
774do
775
776 local setlistcolor = nodes.tracers.colors.setlist
777
778 local trace_shadowed = false trackers.register("nodes.shadowing", function(v) trace_shifted = v end)
779 local report_shadowed = logs.reporter("nodes","shadowing")
780 local a_shadowed <const> = privateattribute("shadowed")
781 local enabled = false
782
783 local shadows = nodes.shadows or { }
784 nodes.shadows = shadows
785
786 function shadows.set(settings)
787 if not enabled then
788
789 enableaction("shipouts","nodes.shadows.handler")
790 enabled = true
791 end
792 texsetattribute(a_shadowed,registervalue(a_shadowed,settings))
793 end
794
795 local function flush_shadowed(head,first,last,data,level,parent,strip)
796 if true then
797 first, last = striprange(first,last)
798 end
799 local next = getnext(last)
800 local copy = copylist(first,next)
801 local width = getrangedimensions(parent,first,next)
802 local list = hpack_nodes(copy,width,"exactly")
803
804 setlistcolor(copy,data.ca,data.ma,data.ta)
805
806 head = insertnodebefore(head,first,list)
807 local xoffset = data.dx * glyphdimenfactor(data.unit,first)
808 local yoffset = data.dy * glyphdimenfactor(data.unit,first)
809 local weight = data.weight or 0
810 setoffsets(list,xoffset,yoffset)
811 setwhd(list,0,0,0)
812 if weight > 0 then
813 for g in nextglyph, copy do
814 setweight(g,weight,true)
815 end
816 end
817
818
819
820 return head
821 end
822
823 shadows.handler = function(head)
824 local data = attributes.values[a_shadowed]
825 if data then
826 head = processwords(a_shadowed,data,flush_shadowed,head)
827 end
828 return head
829 end
830
831 implement {
832 name = "setshadow",
833 actions = shadows.set,
834 arguments = {
835 {
836 { "continue" },
837 { "unit" },
838 { "weight", "integer" },
839 { "method", "integer" },
840 { "dx", "number" },
841 { "dy", "number" },
842 { "ma", "integer" },
843 { "ca", "integer" },
844 { "ta", "integer" },
845 }
846 }
847 }
848
849end
850
851do
852
853 local insert, concat, sort = table.insert, table.concat, table.sort
854
855 local ctx_latelua = context.latelua
856
857 local bpfactor = number.dimenfactors.bp
858
859 local s_close <const> = "h"
860 local s_stroke <const> = "S"
861
862 local f_linewidth = string.formatters["%N w"]
863 local f_moveto = string.formatters["%N %N m"]
864 local f_lineto = string.formatters["%N %N l"]
865
866 local segments = { }
867
868
869
870
871
872 local function wrapup(t,c,x,y)
873 local n = t.n
874 local a = t.a
875 if a == 3 then
876 segments[n] = nil
877 else
878 local s = segments[n]
879 if not s then
880 s = { d = t.d }
881 segments[n] = s
882 end
883 if a == 0 then
884 insert(s,{ t.r, t.c, x, y })
885 elseif a == 1 or a == 2 then
886 insert(s,{ t.r, t.c, x, y })
887 local l = #s
888 if l > 1 then
889
890 sort(s,function(a,b)
891 if b[1] < a[1] then
892 return false
893 else
894 return a[2] > b[2]
895 end
896 end)
897 sort(s,function(a,b)
898 if b[3] < a[3] then
899 return false
900 else
901 return a[4] > b[4]
902 end
903 end)
904
905 local r = { }
906 local si = s[1]
907 local x = si[3] * bpfactor
908 local y = si[4] * bpfactor
909 local w = s.d * bpfactor
910 r[#r+1] = f_linewidth(w)
911 r[#r+1] = f_moveto(x,y)
912 for i=2,l do
913 local s = s[i]
914 local x = s[3] * bpfactor
915 local y = s[4] * bpfactor
916 r[#r+1] = f_lineto(x,y)
917 end
918 if a == 2 then
919 r[#r+1] = s_close
920 end
921 r[#r+1] = s_stroke
922 r = concat(r, " ")
923 lpdf.print("origin",r)
924 segments[n] = nil
925 end
926 end
927 end
928 end
929
930 implement {
931 name = "linesegment",
932 protected = true,
933 arguments = { "string", "integer", "integer", "integer", "dimension" },
934 actions = function(n,r,c,a,d)
935 ctx_latelua {
936 action = wrapup,
937 r = r,
938 c = c,
939 a = a,
940 n = n,
941 d = d,
942 }
943 end
944 }
945
946end
947 |