Tags: alg, typography
See this nice blog post
for a comparison between the layout models of TeX and Typst.
.
Let’s forget about typography and focus on the algorithmic part of
line-breaking problems.
1 line-breaking
Problem1line breaking
Given a sequence
and a cost function
mapping from contiguous subsequences (substrings) of
to
,
divide the sequence
(the paragraph) into substrings
(lines) such that
is minimized.
We over-simplify things here. In real typography world the cost function
not only depends on the line
but also other things like the length of the line.
The input size
is the number of elements in
and for now the cost function
is assumed to be given in an oracle.
This line breaking admits a
dynamic programming algorithm:
2 SMAWK algorithm
Wikipedia says that this problem can be solve in linear time using SMAWK algorithm, which finds the minimum in each row of a totally monotone matrix inThis is a footnote. See section 6.5 in Jeff
Erickson’s lecture notes).
.
The matrix here would be
.
The dynamic programming algorithm is in fact finding the minimum for
each row. If we can show this matrix
is totally monotone, then we can make optimal line breaking decisions in
linear time. A matrix is totally monotone, if each row’s minimum value
occurs in a column which is equal to or greater than the column of the
previous row’s minimum. A special case of totally monotone is Monge array which
requires
for all
and
.
Now we focus on checking Monge property of
.
Doing some easy math, one can see that the Monge property depends on the
following inequality on the cost function
:
This looks like some intersecting supermodular property on set
functions, but our domain here is the collection of substrings.
As cited on wiki, this paper
stated that the problem of optimally breaking up text of a paragraph
into lines can be done in linear time. The cost function is
,
where
is the sum of character width in
and
is the width of the paragraph. This cost function does generate a Monge
array, but this is not the cost in the original
paper of Knuth and Plass.
They introduced several cost functions: “first-fit”, “best-fit” and
“demerits”, with increasing complexity. For simplicity of analysis, we
consider the “best-fit” case, where the cost function is the sum of
badness and penalty.
Penalty relates to the ending character of each line. For example, we
want as few number of hyphens as possible, then the penalty for ending
hyphen should be large. Badness meansures how much do we need to
stretch/shrink the white spaces in a line to make it fit. More formally,
badness is
where
is the sum of default length of all characters in this line,
is the total length of stretchable/shrinkable whitespaces and
is some universal constant factor.
Note that penalties do not affect Monge property, since the number of
occurence of ending characters
(
and
)
in the same on LHS and RHS. However, for badness, one can verify that
is not always a Monge array. I think total monotonicity is violated too
but don’t have a counterexample now…
3 character-level operations
Assume the cost function is still a parabola on line width and we further add some character-level operations.- We can break all ligatures in one line. The cost function becomes .
- Stretch/shrink font glyphs and adjust kerning. $c(X)=\min_{\theta}(\theta {\rm len}_1(X)+{\rm len}_2(X)-parlength)^2$, where ${\rm len}_{1,2}$ are the total length of whitespaces and other characters in and is the stretching factor.