Dear Colleagues, the following code fails assertion (luafont.c, line 1950). But it is enough to transpone last two lines of lua code to avoid it. Could someone explain why the order of node linking matters here? \nokerns=1 \noligs=1 \setbox100=\hbox{ab\-xx} \directlua{% here we move glyph b into disc node local a = tex.box[100].list % glyph a local b = a.next % glyph b local d = b.next % discretionary local _ = d.pre % prebreak dash a.next = d d.prev = a % couple glyph a with disc d.pre = b % let glyph b be prebreak b.next = _ _.prev = b % couple glyph b with dash } \hsize0pt \overfullrule0pt \hfuzz\maxdimen % force hyphenation \unhbox100 % flush the list \end Apparently the assigment discretionary.pre = someglyph someglyph.next = someother and someglyph.next = someother discretionary.pre = someglyph is not the same. Why? Warm greets to u all, Paweł -- Pawe/l Jackowski P.Jackowski@gust.org.pl
Paweł Jackowski wrote:
someglyph.next = someother discretionary.pre = someglyph
is not the same. Why?
Because a discretionary's pre, post, and replace lists are a bit special: internally the discretionary does not just have a next and a prev link for each of the head nodes, but also a 'tail' link. That last one points to the last node in the list for each of the three fields. That extra link is used during hyphenation and at end-of-line situations (those parts of the code would be much more complex == slower without it). So, when in lua you assign to <disc>.pre, that assingment also has to fix up that tail link (it does so by running the C equivalent of the node.tail() function). If the list you are assigning is well-formed, this is transparent. But yours isn't yet at that point in the code, because 'b.next' still points to 'd' at the moment the 'd.pre = b' is seen; and that confuses the internal code into an assertion failure. I admit this is obscure, but the general rule is simple: never assign a list to a node field until you are sure its internal link structure is correct. (a warning to this effect will be added to the manual). Best wishes, Taco
Taco Hoekwater wrote:
Paweł Jackowski wrote:
someglyph.next = someother discretionary.pre = someglyph
is not the same. Why?
Hans:
indeed strange ... a quick hack is to use node.copy on b
Copying the node works in that case, thanks. Taco:
Because a discretionary's pre, post, and replace lists are a bit special: internally the discretionary does not just have a next and a prev link for each of the head nodes, but also a 'tail' link. That last one points to the last node in the list for each of the three fields. That extra link is used during hyphenation and at end-of-line situations (those parts of the code would be much more complex == slower without it).
Agh, having the disc.tail link(s) at lua level would simplify processing discretionaries a lot! Why you decided not to interface tails?
So, when in lua you assign to <disc>.pre, that assingment also has to fix up that tail link (it does so by running the C equivalent of the node.tail() function).
If the list you are assigning is well-formed, this is transparent. But yours isn't yet at that point in the code, because 'b.next' still points to 'd' at the moment the 'd.pre = b' is seen; and that confuses the internal code into an assertion failure.
Clear.
I admit this is obscure, but the general rule is simple: never assign a list to a node field until you are sure its internal link structure is correct. (a warning to this effect will be added to the manual).
Sounds neat. I also noticed that assigning disc sublists introduces nested_list nodes: someglyph.prev = nil disc.pre = someglyph assert(someglyph.prev.id==node.id"nested_list") Is this related here? Is the user supposed to take care about nested_list nodes (to create them, to destroy them)? -- Pawe/l Jackowski P.Jackowski@gust.org.pl
On 23-12-2009 18:29, Paweł Jackowski wrote:
Taco Hoekwater wrote:
Paweł Jackowski wrote:
someglyph.next = someother discretionary.pre = someglyph
is not the same. Why?
Hans:
indeed strange ... a quick hack is to use node.copy on b
Copying the node works in that case, thanks.
Taco:
Because a discretionary's pre, post, and replace lists are a bit special: internally the discretionary does not just have a next and a prev link for each of the head nodes, but also a 'tail' link. That last one points to the last node in the list for each of the three fields. That extra link is used during hyphenation and at end-of-line situations (those parts of the code would be much more complex == slower without it).
Agh, having the disc.tail link(s) at lua level would simplify processing discretionaries a lot! Why you decided not to interface tails?
we had node.slide (for making two way linked node lists) and now also have node.tail so you can find the tail if needed tail = node.tail(n.pre)
I also noticed that assigning disc sublists introduces nested_list nodes:
someglyph.prev = nil disc.pre = someglyph assert(someglyph.prev.id==node.id"nested_list")
Is this related here? Is the user supposed to take care about nested_list nodes (to create them, to destroy them)?
normally not ; similar effects can occur when messing around with boxes (.list) ... it is often best to work with a copy and assign the result of messing with the copy ... the speed penalty is neglectable Hans ----------------------------------------------------------------- Hans Hagen | PRAGMA ADE Ridderstraat 27 | 8061 GH Hasselt | The Netherlands tel: 038 477 53 69 | fax: 038 477 53 74 | www.pragma-ade.com | www.pragma-pod.nl -----------------------------------------------------------------
Paweł Jackowski wrote:
Taco Hoekwater wrote:
Paweł Jackowski wrote:
someglyph.next = someother discretionary.pre = someglyph
is not the same. Why?
Hans:
indeed strange ... a quick hack is to use node.copy on b
Copying the node works in that case, thanks.
Taco:
Because a discretionary's pre, post, and replace lists are a bit special: internally the discretionary does not just have a next and a prev link for each of the head nodes, but also a 'tail' link. That last one points to the last node in the list for each of the three fields. That extra link is used during hyphenation and at end-of-line situations (those parts of the code would be much more complex == slower without it).
Agh, having the disc.tail link(s) at lua level would simplify processing discretionaries a lot! Why you decided not to interface tails?
Because having them would be even more confusing than not having them. At least, that was Nanning and my feeling about it.
participants (3)
-
Hans Hagen
-
Paweł Jackowski
-
Taco Hoekwater