[NTG-context] Count (and limit) glyphs per line?
Max Chernoff
mseven at telus.net
Sat Jun 25 23:40:31 CEST 2022
> It's also a very insightful example of how to use and inject Lua code in the TeX output routine.
This is injecting Lua code before the paragraph builder, not in the
output routine. Something like
https://tex.stackexchange.com/a/644613/270600 or my module
"lua-widow-control" would be an example of Lua code in the output routine.
> Do you mind if I add it to the wiki? (Probably under "Wrapping".)
Sure
> However, tex.localhsize (or tex.dimen["localhsize"]) is 0 when the document is initialized. (Maybe a more sensible default would be textwidth rather than 0?)
>
> So, I added:
>
> local localhsize = tex.dimen["textwidth"]
>
> if tex.dimen["localhsize"] > 0 then
> localhsize = tex.dimen["localhsize"]
> end
>
> if chars >= max_length or width > localhsize then
I don't think that's necessary. \hsize is a primitive TeX parameter that
sets the width of the paragraph. It may be zero at the start of the
document, but it is definitely non-zero by the end of every paragraph.
The Lua function gets the current value of \hsize at the end of every
paragraph, so it should be using the exact same value that TeX's
paragraph builder uses, meaning that it should account for itemizations
and such. I'm not really sure what \localhsize is, but it's probably
similar to \hsize.
> (2) I'm (now?) running into trouble with hyphenation.
>
> In my own document, I also get lines with only a single character or hboxed group. I assume, this is because the hyphen is not counted and pushes the remainder to a new line where the intended breakpoint again starts another one.
Try this:
\startluacode
local max_length = 112
local glyph_id = node.id "glyph"
local disc_id = node.id "disc"
local glue_id = node.id "glue"
function userdata.limiter(head)
language.hyphenate(head)
local hyphen = node.new "glyph"
hyphen.char = language.prehyphenchar(0)
hyphen.font = font.current()
local width = hyphen.width
node.free(hyphen)
local chars = 0
local n = head
while n do
if n.id == glyph_id or n.id == glue_id then
chars = chars + 1
width = width + n.width - (n.shrink or 0)
end
if chars >= max_length or width > tex.hsize then
local back_chars = 0
local end_disc = nil
while n do
if n.id == glue_id then
local penalty = node.new "penalty"
penalty.penalty = -10000
node.insertbefore(head, n, penalty)
break
end
if not end_disc and n.id == disc_id then
end_disc = n
end
if end_disc and back_chars >= 5 then
end_disc.penalty = -10000
break
end
if n.id == glyph_id then
back_chars = back_chars + 1
end
n = n.prev
end
width = 0
chars = 0
end
n = n.next
end
return head
end
nodes.tasks.appendaction(
"processors",
"before",
"userdata.limiter"
)
\stopluacode
I've just added the width of a hyphen to the accumulated width. Let me
know if this works; if not, there's a more complex fix that I can try.
> Unfortunately, I don't know what to change; I know a bit about "glyph" and "glue", but what is "disc" and would it help here?
"disc" nodes are "discretionaries", which are usually potential hyphens.
See "The TeXbook" (page 95) or "TeX by Topic"
(https://texdoc.org/serve/texbytopic/0#subsection.19.3.1) for details on
the TeX side, or the LuaMetaTeX manual
(https://www.pragma-ade.com/general/manuals/luametatex.pdf#%231205) for
details on the Lua side.
-- Max
More information about the ntg-context
mailing list