import type { StyledSegment } from './text.js';
import { type TextElementLike } from './text-types.js';
import { type LineRect } from './background-shape.js';
/** One styled run on a line, in logical order. */
export interface RtRun {
/** The run as svg-export's emitter wants it (`segmentsToTspans`). */
seg: StyledSegment;
/** How far the run advances the pen — a tab's own advance included. */
width: number;
}
/**
* A list marker, positioned by render-tag rather than re-derived here.
*
* `x` is the marker's INLINE-START edge, which is its left edge in an LTR run
* and its right edge in an RTL one — exactly what SVG's `text-anchor: start`
* anchors, so the number goes straight onto the tspan in both directions.
*/
export interface RtMarker {
text: string;
x: number;
y: number;
/** Bullets carry render-tag's synthetic-disc scale already applied. */
fontSize: number;
letterSpacing: number;
rtl: boolean;
}
/** The block box a line is laid out in — a `
`, an `
`, or the root. */
export interface RtBox {
left: number;
right: number;
isRtl: boolean;
}
export interface RtLine {
runs: RtRun[];
/** Exact baseline, straight off the runs — never the rounded `lines[].y`. */
baseline: number;
/** Line-box top and height, for backgrounds and vertical stacking. */
top: number;
height: number;
box: RtBox;
/** Present only on the first line of a list item. */
marker: RtMarker | null;
/**
* True when this line ENDS a paragraph — the last line of a block, or a line
* a forced break (`
`) ended mid-block. CSS leaves both at their natural
* spacing under `text-align: justify`, and the text-background polygon keys
* off the same flag. The name is core's (`TextBackgroundLine`).
*/
lastInParagraph: boolean;
}
export interface RtText {
lines: RtLine[];
/** Content height render-tag measured — the authority for shrink-to-fit. */
height: number;
/** The size the fit loop settled on, and the size the lines were laid at. */
fontSize: number;
}
/**
* The element this module lays out. `TextElementLike` is core's own shape for
* "enough of a text element to render", bound to the schema so a field that
* changes there fails to compile here; only `fontSize` is narrowed, because the
* fit loop always has one in hand.
*/
export type RtElement = TextElementLike & {
fontSize: number;
};
/**
* Lay `element` out through render-tag, shrinking to fit when asked.
*
* Fitting goes through `fitByLayout`, which pdf-export also calls: both draw
* from render-tag, so both fit with the same loop and only inject their own
* `layoutAt`. It is height-only — render-tag wraps and breaks words itself, so a
* line cannot overflow the width it was laid out in.
*
* `align: justify` is laid out as `left` on purpose. render-tag would hand back
* already-stretched space runs, and svg-export justifies by emitting a
* `word-spacing` the SVG renderer applies — so it needs each line's NATURAL
* advance to know how much slack to distribute. Line breaking is identical
* either way: CSS justifies after breaking, never during.
*/
export declare function layoutText(element: RtElement, { shrink }: {
shrink: boolean;
}): RtText;
/**
* A line's runs without the trailing whitespace ones. Emission trims trailing
* whitespace, so every width derived from a line trims it too — a trailing TAB
* is worth up to a whole stop interval and would stretch a background box far
* past the glyphs.
*/
export declare function trimRuns(runs: RtRun[]): RtRun[];
/** How far the runs advance the pen together. */
export declare const advanceOf: (runs: RtRun[]) => number;
/**
* The per-line boxes a text background is built from
* (`generateBackgroundShapeFromRects`), from the same line boxes the text is
* placed by — so the polygon can never drift from its text. `textLinesToRects`
* handles alignment and drops zero-width (blank) lines, so the gap-filler
* treats them as blank paragraphs, which is what the canvas does. Each line is
* trimmed of its trailing letter-space, as the canvas and pdf-export trim
* theirs (`trimTrailingLetterSpace`) — where the measure context applied one.
*/
export declare function backgroundLineRects({ lines, fontSize }: RtText, element: Pick & {
width: number;
}): LineRect[];