How to setup the interlinespacing parameters as function of x-height

I recommend this:

#show: rest => context {
  let x-height = measure({
    set text(bottom-edge: "baseline", top-edge: "x-height")
    [x]
  }).height
  let ex = x-height / 1em.to-absolute() * 1em

  set text(
    top-edge: 2.8 * ex * 0.72,
    bottom-edge: 2.8 * ex * 0.28,
  )
  set par(leading: 2.8 * ex * 0.28)

  rest
}


#lorem(10)

Explanation:

  1. The x-height will depend on the font, so it’s context-sensitive. Therefore, we have to put everything that depends on x-height in a context {…}.

    To simplify later writing, I use a show: rest => … rule to transform the whole document afterwards.

  2. let x-height = measure(…).height is your original idea. I use "x-height" instead of "bounds" for the top-edge parameter, because it is the metric defined by the font designer, and does not depend on the specific character.

  3. x-height is an absolute length (in points), and let ex = x-height / 1em.to-absolute() * 1em will make it to relative to the font size. Doing so will make your leading settings look better for headings, where have larger font size.

    For Libertinus Serif, ex is about 0.43em.

Besides, you can go to ```ex``` as a unit · Issue #2405 · typst/typst · GitHub and click :+1: to express the wish for this to be natively supported by typst.