[NTG-context] Count (and limit) glyphs per line?
Benjamin Buchmuller
benjamin.buchmuller at gmail.com
Sat Jun 25 22:25:09 CEST 2022
Dear list,
A brief follow-up for (1) itemizations [resolved; but question on ConTeXt hsize defaults] and (2) hyphenation [troubles].
(1) To deal with itemizations and other situation where texts are indented such as:
\setuppapersize[landscape,letter]
\showframe
\starttext
\samplefile{knuth}
\ctxlua{context(tex.dimen["textwidth"])} % 37213340
\ctxlua{context(tex.dimen["localhsize"])} % 0
\startitemize[width=5em]
\item \samplefile{knuth}
\ctxlua{context(tex.dimen["textwidth"])} % 37213340
\ctxlua{context(tex.dimen["localhsize"])} % 33283340
\stopitemize
\stoptext
The following part in the script must be adapted to the local horizontal size, I guess:
if chars >= max_length or width > tex.hsize then
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
Maybe someone finds this useful in the future.
(2) I'm (now?) running into trouble with hyphenation. With the example above, I get
"
The separation of any of these four components would have hurt TEX significantly. If I had not particĀ-
i-
pated fully in all these activities, literally hundreds of improvements would never have been made,
"
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.
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?
Thank you!
Benjamin
> On Jun 25, 2022, at 11:38, Benjamin Buchmuller <Benjamin.Buchmuller at gmail.com> wrote:
>
> Wow, that works like a charm! Thank you, Max!
>
> It's also a very insightful example of how to use and inject Lua code in the TeX output routine. Do you mind if I add it to the wiki? (Probably under "Wrapping".)
>
> Many thanks again!
>
>
> Benjamin
>
>> On Jun 24, 2022, at 01:44, Max Chernoff <mseven at telus.net> wrote:
>>
>>> 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
>>
>> \setuplayout[width=80\averagecharwidth]
>>
>> 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
>>
>> \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 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)
>> 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
>>
>> \setuppapersize[landscape,letter]
>> \showframe
>>
>> \starttext
>> \setupalign[flushleft]
>>
>> \setupbodyfont[14pt]
>> \samplefile{knuth}
>>
>> \setupbodyfont[12pt]
>> \samplefile{knuth}
>>
>> \setupbodyfont[10pt]
>> \samplefile{knuth}
>>
>> \page
>> \setupalign[normal]
>>
>> \setupbodyfont[14pt]
>> \samplefile{knuth}
>>
>> \setupbodyfont[12pt]
>> \samplefile{knuth}
>>
>> \setupbodyfont[10pt]
>> \samplefile{knuth}
>> \stoptext
>>
>> 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.
>>
>> -- Max
>
More information about the ntg-context
mailing list