Skip to main content
layoutWithLines() lays out a paragraph at a fixed max width and returns the text and measured width of each line, along with the total line count and height. Use it when you need the actual line contents for rendering.
import { prepareWithSegments, layoutWithLines } from '@chenglou/pretext'

const prepared = prepareWithSegments('AGI 春天到了. بدأت الرحلة 🚀', '18px "Helvetica Neue"')
const { lines } = layoutWithLines(prepared, 320, 26) // 320px max width, 26px line height
for (let i = 0; i < lines.length; i++) ctx.fillText(lines[i].text, 0, i * 26)

Signature

layoutWithLines(
  prepared: PreparedTextWithSegments,
  maxWidth: number,
  lineHeight: number
): LayoutLinesResult

Parameters

prepared
PreparedTextWithSegments
required
The handle returned by prepareWithSegments(). Must be the segment-aware variant — the plain PreparedText from prepare() is not accepted here.
maxWidth
number
required
Maximum line width in pixels. All lines use the same width. Use layoutNextLine() if you need variable widths per line.
lineHeight
number
required
Line height in pixels. Must match the CSS line-height for the element. The returned height is lineCount * lineHeight.

Returns

lineCount
number
required
Number of wrapped lines.
height
number
required
Total block height in pixels. Equal to lineCount * lineHeight.
lines
LayoutLine[]
required
Array of per-line objects, one per wrapped line.

layout() vs layoutWithLines()

layout()layoutWithLines()
InputPreparedTextPreparedTextWithSegments
Returns line textNoYes
Returns line widthsNoYes
Returns cursorsNoYes
Resize hot pathYesNo — keep off the hot path
Use layout() when you only need the height. Use layoutWithLines() when you need to render the line contents.
For shrinkwrap layouts or binary-search over widths, prefer walkLineRanges() — it avoids building the line text strings and is faster for geometry-only work.

Build docs developers (and LLMs) love