How to get a minimal content (text) width?

From How can I robustly make (unknown) tables span the full page width? - #2 by Andrew

and How can I robustly make (unknown) tables span the full page width? - #8 by bluss, a solution could be something like this:

/// Get index of partition point
/// - func (function): Return true if less or equal, false if greater than partition point
/// based on rust libcore partition point
#let partition-point(range, func) = {
  let size = range.len()
  if size == 0 { panic("Empty range in partition-point") }
  let base = 0
  while size > 1 {
    let half = calc.div-euclid(size, 2)
    let mid = base + half
    let lte = func(range.at(mid))
    base = if lte { mid } else { base }
    size -= half
  }
  let lte = func(range.at(base))
  base + int(lte)
}

#let estimate-min-width(body) = {
  let nominal-length = measure(body).width
  let ceil = calc.ceil(nominal-length.pt())
  let widths = range(ceil, step: 1)
  let pp = partition-point(widths, w => {
    let max-width = w * 1pt
    let actual-width = measure(body, width: max-width).width
    not (actual-width < max-width)
  })
  let best-guess-max-width = widths.at(pp, default: ceil) * 1pt
  measure(body, width: best-guess-max-width).width
}

Then pass any content, e.g., text, to get its min width. But context is required.

#context estimate-min-width(lorem(50))

This is still an estimation, but it’s better than nothing. You can modify the step part to increase or decrease precision, which in turn can change the compilation time.

2 Likes