On Sun, 27 Nov 2022 at 14:59, Marcel Fabian Krüger <t...@2krueger.de> wrote:
> Hi, > > in LuaTeX node.ligaturing should return the head and the tail of the > list after ligatures got applied. But in the case that the tail of the new > list is a discretionary the current code returns the passed in tail > instead, assuming that it didn't change. This breaks if the > discretionary node wasn't the tail before the ligature pass:. > > Take for example > > \directlua{ > local b = token.scan_list() > local h = b.head > local t = node.tail(h) > local post_h, post_t = node.ligaturing(h, node.tail(t)) > print(node.tail(post_h), post_t) > }\hpack{a\discretionary{}{f}{f}f} > \bye > > Here the `f`s in the discretionary form ligatures with the `f` after the > discretionary, so after node.ligaturing the list if effectively > `a\discretionary{}{ff}{ff}` and therefore `post_t` should point to the > discretionary node. But as the output shows, post_t instead is a glyph > node while node.tail(post_h) is the expected disc node. > > This is caused by `handle_lig_word` in luafont.c. `handle_lig_word` is > used in `handle_ligaturing` as > > while (cur != null) { > if (type(cur) == glyph_node || (type(cur) == boundary_node)) { > cur = handle_lig_word(cur); > } > prev = cur; > cur = vlink(cur); > } > > so it is expected that handle_lig_word returns the last node already > handled > so that afterwards the loop can continue at vlink(cur). But if the handled > segment ends with a discretionary `handle_lig_word` returns the node > `after` > the last already handled node instead. This is fine if the last node is a > non glyph/non boundary node, but if the discretionary ends the segment > passed > to handle_ligaturing than this means that `handle_lig_word` returns null, > therefore settings `prev` to `null` instead of tracking the tail. > Also this relies on `vlink(null)` being null, causing issues if this > ever gets corrupted (see my next mail for an example...). > > It can be fixed by making sure that handle_lig_word always returns the > last handled node, e.g. using > > diff --git a/source/texk/web2c/luatexdir/font/luafont.c > b/source/texk/web2c/luatexdir/font/luafont.c > index 2e08facb1..c33037244 100644 > --- a/source/texk/web2c/luatexdir/font/luafont.c > +++ b/source/texk/web2c/luatexdir/font/luafont.c > @@ -2242,6 +2242,7 @@ static halfword handle_lig_nest(halfword root, > halfword cur) > static halfword handle_lig_word(halfword cur) > { > halfword right = null; > + halfword last = null; > if (type(cur) == boundary_node) { > halfword prev = alink(cur); > halfword fwd = vlink(cur); > @@ -2481,9 +2482,10 @@ static halfword handle_lig_word(halfword cur) > > } else { > /*tex We have glyph nor disc. */ > - return cur; > + return last; > } > /*tex Goto the next node, where |\par| allows |vlink(cur)| to be > NULL. */ > + last = cur; > cur = vlink(cur); > } > return cur; > -- > Sorry for the delay, I will check it this evening . -- luigi
_______________________________________________ dev-luatex mailing list dev-luatex@ntg.nl https://mailman.ntg.nl/mailman/listinfo/dev-luatex