Open peng1999 opened 2 months ago
No proper solution exists under current leading model.
Allow different elements on the line to have different values of leading, with the largest "element height + leading" determining the line height. Inline equations could have zero or minimal leading.
That being said, I'm not convinced that the current model is better either. Just saying that there are (at least partial) solutions within the current framework.
with the largest "element height + leading" determining the line height.
i think it is how current model works? the problem is that, once the "largest element" becomes too large, you no longer want to use the original leading(which is designed for not-so-large cases), but a much smaller value, like 1pt. And that is why inline math are pretending if they are actually smaller.
with the largest "element height + leading" determining the line height.
i think it is how current model works? the problem is that, once the "largest element" becomes too large, you no longer want to use the original leading(which is designed for not-so-large cases), but a much smaller value, like 1pt. And that is why inline math are pretending if they are actually smaller.
Why couldn't it just always be 1 pt for inline math then? (Disregarding lines solely composed of inline math)
Why couldn't it just always be 1 pt for inline math then?
i havent think in detail and im not sure if it is a good idea. i personally perfer @peng1999 's because the idea behind is backed by *TeX and is battle tested.
One thing to notice is that "changing the spacing model" sounds difficult but actually doesnt need change a lot of code, at least for the demo in https://github.com/typst/typst/issues/1028#issuecomment-2124864812, the changeset is very small and straight forward. I've also search all occurance of "leading" and found that there isnt too much usage.
Sorry i didn't read this yesterday.
Allow different elements on the line to have different values of leading
This sounds even more complicated than any model mentioned here. IIUC spacing models mentioned here(apart from in design) all have a single leading/line-height within a paragraph. And the one you mentioned, can set different leading for every element.
But i'm not sure what it will looks like in typst. Currently leading
is only defined in par
. Should we add leading
to all other elements like text
, equation
(and set leading automatically depending on if it's inline/block)? I feel like it is not a good user interface.
Another thing to notice is that leading
in InDesign actually means line-height
Will leave a comment here once I've had the chance to discuss this with @reknih. I'll try to recover the original reasoning for the current model.
Related: #159, #1221.
The (good-enough) solution I currently use everywhere: https://github.com/typst/typst/issues/159#issuecomment-1609939896.
Let me first lay out our original thoughts behind the thoughts behind our original design:
Text and its surrounding containers should interact in a nice, evenly-spaced manner: If you write #rect(fill: aqua, inset: 5pt)[Hello]
in Typst today, you get a rectangle with a very even inset. In contrast, if you take CSS for instance, a <span style="padding: 5px; background: aqua">Hello</span>
is not evenly spaced. The left inset looks smaller than top and bottom, and even these two aren't perfectly even.
The reason why Typst's output is evenly spaced is because of the way top- and bottom-edge work. Rather than using ascender
and descender
(plus half-leading in CSS), we picked the default edges cap-height
and baseline
because they most closely reflect the real extent of normal uppercase letters in a font.
Even default spacing: Since cap-height
& baseline
are closely related to visual edges and the spacing between them (leading
) is even, the current leading model gives very even looking spacing independently of the font. With a line-height based model, changing the font without changing the line-height can give a widely varying look.
Correspondence between metrics for line and paragraph spacing: The line leading and block spacing work in very similar ways and are therefore metrically compatible: Specifying twice the amount for block.spacing
as for par.leading
will lead to twice the visual spacing.
With the existence of top-edge and bottom-edge, leading was a natural and simple way to define the spacing, so we didn't see reason to complicate things further. This means it's also easy to have a stack, grid, or any other things (like list spacing) spaced the same as paragraphs. Notably, handling math equations well was not a design goal at the time because Typst didn't have support for equations at the time. :P
The obvious main benefit of the proposed change is that it handles equations more nicely. But it's also nice that not only font size, but also font change (e.g. raw block) doesn't lead to almost unnoticable shifts in line layout. So that's a big plus.
That the line height doesn't react to font change is both a benefit and a downside at the same time, in my opinion. It leads to a less even look when changing fonts, but leads to more predictable behaviour and less layout shifting when changing fonts.
For the spacing between lines, I believe the proposed change is good. I think what's still important to discuss is how all of this affects the remaining metrics: The bounding box of first and last line and the spacing between paragraphs:
I assume, since the proposal doesn't say anything special about the first and last line, that they should remain as-is. This means we would retain the nice even spacing interaction with containers, which is good.
At the same time, this raises the question of how equations are handled in the first and last line. If we remove the current equation slack hack, then almost all equations will have a non-zero descent, and as a result a final line with an equation in it will lead to different container bounds than one with an equation.
Moreover, the question is how paragraph spacing interacts with this. Right now, the spacing between paragraphs is defined as block.spacing
(though I'm considering to move it to par.spacing
for discoverability and also since paragraphs are not blocks per se). With a line-height
-based model, should this stay as-is? This would mean no metrical correspondence between the values specified for paragraph spacing and line height.
This is only slightly related, but still somewhat relevant: https://github.com/typst/typst/pull/4390
When implementing this in #4236. I found it hard to deal with spacing between paragraphs. Especially for a tight list/enum/term.
This leads to another difference in typst and LaTeX. In typst, the spacing between paragraphs is defined as the distance between the bottom edge of previous paragraph and the top edge of current paragraph. If you set it to 0, these 2 paragraph will be very close. (Actually, they are too close, look at the h
and g
. Maybe this is bacause the font metrics.)
However, in LaTeX, it layouts text line by line, and each line always has a minimal spacing with the first line. If we set \parskip
to zero, it will make the distance between paragraphs looks like the distance between lines within a paragraph.
\usepackage{parskip}
\setlength{\parskip}{0pt}
Back to the tight list implementation issue. In LaTeX, each list item is a paragraph. To make a list look tight, simply remove all extra inserted spaces, like setting \parskip
, \itemskip
to 0.
In typst, the implemetation is similar (at least for term list). The distance between paragraphs should be carefully calculated. In the previous model, it should equals to leading
: the distance between lines' top/bottom edge.
However this make it very hard when it comes to the line height model. In this way, we don't know "the distance between lines' top edge and bottom edge" unless we can see the ascent and descent of lines. And currently I cannot get it when it cross the boundary of paragraphs.
I don't know if there is a way to robustly get "the descent of the last line in previous par" and "the ascent of the first line in current par". Or how hard it would be to implement this mechenism? If this is possible, we can do this and get a nice tight list. Otherwise we might need to consider how to deal with paragraph spacing in this proposal cc @peng1999
@peng1999 do you have any thoughts on my response?
@laurmaedje These are some of my thoughts.
- That the line height doesn't react to font change is both a benefit and a downside at the same time, in my opinion.
Actually it can react to font change. Just set the line-height to em's.
- Moreover, the question is how paragraph spacing interacts with this.
The core idea of the proposal is to consider baseline when calculating spacing. In line spacing, we maintain the equation:
$$\text{space between baselines} = \texttt{par.line-height}$$
In paragraph spacing, we effectively deal with baseline distance between last line of the previous prargraph and the first line of the current:
$$\text{space between baselines} = \texttt{par.line-height} + \texttt{par.spacing}$$
The similar calculation happens at tight list/enum/term. See https://github.com/typst/typst/issues/4224#issuecomment-2171089296 for implementation details.
Reguarding to the spacing related to surrounding containers, I don't think there is anything that need to be changed.
Actually it can react to font change. Just set the line-height to em's.
Then it reacts to font size change, but not to font change. 1em == text.size
independently of the font.
In paragraph spacing, we effectively deal with baseline distance between last line of the previous prargraph and the first line of the current ...
That's definitely possible, but would definitely require further changes as paragraphs cannot be considered as isolated frames. Still doable.
Reguarding to the spacing related to surrounding containers, I don't think there is anything that need to be changed.
Then, then equation problem remains for the ascent of the first line and descent of the last line.
Then it reacts to font size change, but not to font change.
1em == text.size
independently of the font.
Then it's actually a good thing. Because it's intuitive for anyone who used professional typography tools (LaTeX/InDesign/Affinity Publisher) before. The current model is quite unfamiliar, especially for those accustomed with the concept of text baseline.
Then, then equation problem remains for the ascent of the first line and descent of the last line.
It depend on your definition of the equation problem. In my opinion, the problem is "Inline formula causes uneven line spacing in text flow". This problem does not affect the first line and last line, because there is no such thing as "line spacing" before the first line and after the last line.
The first and last line is related to "text inside a container" problem you mentioned, but I think the problem is orthogonal.
That's definitely possible, but would definitely require further changes as paragraphs cannot be considered as isolated frames. Still doable.
I'm aware of the complexity of the spacing model change, and @Enter-tainer's hard work on #4236 clearly demonstrates this. Maybe @Enivex's solution (https://github.com/typst/typst/issues/4224#issuecomment-2125126270) is easier to implement.
The first and last line is related to "text inside a container" problem you mentioned, but I think the problem is orthogonal.
That's fair to an extent (both solutions don't fix it), but I think the various problems with equations still need to be considered holistically.
@laurmaedje Could you elaborate more about the "equation problem"? (And maybe especially about the first line and last line) I hope we are on the same page. I suppose you mean that current line height PR only fixed #1028 within a paragraph. But the distance between paragraph will become too much(or is it? I think it should still be par spacing?) in that PR if inline equation appears in the first/last line of a paragraph.
What I mean with "equation problem" is that, if we get rid of the slack / reduced height of equations, add line-height, but keep top-edge and bottom-edge as they are now, then the first and last lines will fully expand much more due to equations than they do currently.
For instance, in a two-column layout, where an equation happens to be in the first line of the second column, the whole second column will have slightly shifted lines. In absence of grid-based typesetting, the same can of course always happen due to a quite large equation, but I think with the current proposal, it would happen quite quickly since many equations have a top edge exceeding the text top edge.
if we get rid of the slack / reduced height of equations, add line-height, but keep top-edge and bottom-edge as they are now, then the first and last lines will fully expand much more due to equations than they do currently.
For me I think it is like we need to employ similar method in this proposal. Maybe, instead of using "distance between bbox" to measure paragraph spacing, we need use something like \parskip
and do similar max(...)
calculations. But I'm really not sure about this at this moment. I need checkout how LaTeX handles this.
it would happen quite quickly since many equations have a top edge exceeding the text top edge.
BTW, what's expected behavior? I'm afraid it will never look like previous slackness hack since it manually fake the bbox of equations so it is... not correct. For me, the ideal result is that the distance between paragraphs will get bigger but shouldnt be too much.
BTW, what's expected behavior?
I'm honestly not sure.
Maybe, instead of using "distance between bbox" to measure paragraph spacing, we need use something like \parskip and do similar max(...) calculations.
Perhaps. I am not just wondering about the spacing between paragraphs though, but also about the one from the top of the page / container to the first baseline. And similarly from the last baseline to the bottom of a container.
I propose deprecating the
par.leading
option, and add apar.line-height
option instead.Motivation
The current leading model do not persist baseline distance
Current leading model specifies the space between bottom edge of last line and top edge of the next line. This is fine when every line frame is of the same height but becomes undesirable when some lines become taller. See https://github.com/typst/typst/issues/1028#issuecomment-2029983751 for example. To alleviate the problem, currently Typst hacks into the bounding box of inline formula. However, this workaround is not ideal as it leads to the exact issues described in #1028 and lacks a straightforward solution.
Furthermore, line spacing becomes uneven when text with different size appeared in paragraph. No proper solution exists under current leading model.
Typst:
LaTeX:
The current leading model is confusing and inconsistent with precedence
Typst define leading as “The spacing between lines”. However, other typesetting software such as Adobe InDesign and Affinity Publisher use the term “leading” to refer to the distance between text baselines. Other typesetting systems like CSS, LaTeX, and Microsoft Word do not employ the term “leading”, yet they all relate line spacing to the distance between baselines.
Typography guidelines (example) consider line spacing in terms of baseline distance too.
Proposal
Deprecate the
leading
option and introduce a new option calledline-height
, which represents the basic distance between baselines.leading
can be removed in the future version along withlocate
function.For each line frame $L_i$, define $H_i$ as the distance from the top edge to the baseline (height), and $D_i$ as the distance from the baseline to the bottom edge (depth). During layout processes, Typst should insert a blank frame of height $x$ between two lines, $L_1$ and $L_2$. The height of this frame is determined by: $$x = \max(0, s - D_1 - H_2)$$ where $s$ represents the
line-height
value. Essentially, we maintain consistent baseline spacing unless there is an collision.In the future, an additional option
min-line-gap
$=g$ can be added, changing the above formula to $$x = \max(g, s - D_1 - H_2).$$ See below for the explanation of $g$.Alternative
The TeX model
(Reference: The TeXBook, p.77-80)
TeX employs the following formula:
$$x = \begin{cases}s - D_1 - H_2, &s - D_1 - H_2 \geq l\\g, &\text{otherwise}\end{cases}$$
where $x$ is the space inserted between lines, and $s$, $l$, $g$ corresponds to
\baselineskip
,\lineskiplimit
and\lineskip
respectively. Notably the first formula presented in Proposal section is a special case where $l = g = 0$. So the proposed formula is compatible to the LaTeX algorithm.https://github.com/typst/typst/issues/1028#issuecomment-2124864812 demonstrated an instance of the model in Typst where $s=14\text{pt}, l=0,$ and $g=1\text{pt}$.
The InDesign model
From InDesign's document:
This model is not suitable for Typst because it do not play well with inline formulas.