[NTG-context] Count (and limit) glyphs per line?
mseven at telus.net
Fri Jun 24 07:44:44 CEST 2022
> I've been confronted with the following 'intriguing' formatting requirement for a document:
"Intriguing" is definitely right here. I suspect these guidelines were
made for typewriters and haven't been updated since.
> to limit the number of glyphs per line to 112.
112 characters per line sounds much too long anyways.
From "The Elements of Typographic Style":
> Anything from 45 to 75 characters is widely regarded as a satisfactory
> length of line for a single-column page set in a serifed text face
> in a text size. The 66-character line (counting both letters and
> spaces) is widely regarded as ideal. For multiple-column work, a
> better average is 40 to 50 characters.
> If the type is well set and printed, lines of 85 or 90 characters
> will pose no problem in discontinuous texts, such as bibliographies,
> or, with generous leading, in footnotes. But even with generous
> leading, a line that averages more than 75 or so characters is likely
> to be too long for continuous reading.
If you use something like
then your lines will for sure have fewer than 112 characters and will
probably be more readable too.
> I'm nevertheless curious if there is a Lua/TeX solution to this "problem"?
Option 1: Use a monospaced font. Then 112 characters per line <=> page
width = 112em.
Option 2: A hacky Lua solution
local max_length = 112
local glyph_id = node.id "glyph"
local disc_id = node.id "disc"
local glue_id = node.id "glue"
local chars = 0
local width = 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)
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)
if not end_disc and n.id == disc_id then
end_disc = n
if end_disc and back_chars >= 5 then
end_disc.penalty = -10000
if n.id == glyph_id then
back_chars = back_chars + 1
n = n.prev
width = 0
chars = 0
n = n.next
This code will ensure that no line ever exceeds "max_length" characters.
It uses a greedy algorithm instead of the standard TeX algorithm for
line breaking, but it still produces mostly decent results.
More information about the ntg-context