/** * The box typesetter (#855): lay a run of content blocks out as a box of a * callout style at a width, and cut it at a height, resumably. * * Factored out of `placeDocumentPass` (`build.ts`) with an explicit pass * context so callouts and the frames of composed pages (DESIGN §5.1) share * it: a callout's fragments (`keepTogether: false`) and a frame's content * cut at the frame's foot are the same operation. Nothing here reads the * page or the cursor; the pass context hands in what the layout needs. */ import type { ContentBlock } from '../parse/index.js'; import type { ResolvedCalloutStyleConfig } from '../types.js'; import type { ResolvedConfig, VDTBlock } from '../vdt.js'; import type { BlockMeasureContext } from './measureContentBlock.js'; import type { ParagraphContainerPlan } from './paragraphContainers.js'; import type { MeasureMemo } from './measureMemo.js'; import { type LayoutMemo } from './layoutMemo.js'; import { type BoxDesign, type BoxHeadingDesign, type CalloutLayoutInput, type CalloutLayoutResult, type CalloutLineWidth, type PlannedCallout } from './calloutLayout.js'; import type { CalloutCut } from './cutTypes.js'; export type { CalloutCut } from './cutTypes.js'; /** What a frame of a composed page (#855) adds to a box's layout: its exact * height, where content shorter than it sits, the rectangles its text * runs round, and the scale of its pictures (#858). Absent for callouts. */ export type FrameBoxOptions = Pick; /** What the box typesetter reads of a layout pass. */ export interface FrameLayoutPass { /** The pass's content blocks (after every block transform). */ readonly contentBlocks: readonly ContentBlock[]; /** The pass's configuration (`layout.flowColumns`, * `layout.boxChildSplitMinLines`). */ readonly resolved: ResolvedConfig; /** The configuration boxes are laid out with: `resolved` plus the * synthetic box styles of the pass. */ readonly calloutResolved: ResolvedConfig; readonly paragraphContainers: ParagraphContainerPlan; /** The measure context the children of the box that opens at `startIdx` * are set with (a main-flow group's box sets its blocks as the text * around it is set). */ measureCtxFor(startIdx: number, style: ResolvedCalloutStyleConfig): BlockMeasureContext; /** Lays out a comic strip among a box's children (see * `CalloutLayoutInput.stripBlock`). */ stripBlock(raw: ContentBlock, idx: number, width: number): VDTBlock | undefined; /** The height of an empty, full-height column of the current page (see * {@link tallerThanColumn}). */ columnHeight(): number; /** The room a heading's own design takes in a box (#906; see * `CalloutLayoutInput.headingDesign`). */ headingDesign?: BoxHeadingDesign; /** A box style's design (#1014; see `CalloutLayoutInput.boxDesign`). */ boxDesign?: BoxDesign; /** The measurements of one layout of a composed page (#953), dropped * with it. */ measureMemo?: MeasureMemo; /** The whole layouts of one layout of a composed page (#972), dropped * with it. */ layoutMemo?: LayoutMemo; } /** The widths a child's lines are counted at in a fragment `width` wide * that opens `from` (see `CalloutCut.widths`). */ export declare const cutWidths: (from: CalloutCut, width: number) => readonly CalloutLineWidth[]; export declare const CUT_START: CalloutCut; export interface CalloutLayouter { /** Content blocks between the fence markers. */ children: readonly ContentBlock[]; /** Content index of `children[0]`. */ childBase: number; /** Positions in `children` of the blocks the box lays out (marker * blocks of nested containers and directives are skipped). */ realAt: readonly number[]; /** The cut past the last child (the end of the box). */ end: CalloutCut; /** `:::columns` groups among the children ([start, end] marker * positions): only the cuts the group itself offers fall inside one * (#634), and none inside a group of a nested box. */ groups: readonly [number, number][]; /** Lay out the children from cut `from` to cut `to` at `width` as one * box — a `continuation` (every fragment after the head) without * title / icon. A cut inside a child keeps only the lines on its side. */ layoutRange: (from: CalloutCut, to: CalloutCut, width: number, frameId: string, continuation: boolean, mirrored?: boolean, frame?: FrameBoxOptions) => CalloutLayoutResult; /** `layoutRange` for a caller that only reads the result (the split * probes): with a layout memo (#972) the stored layout itself, never to * be moved or changed. */ peekRange: (from: CalloutCut, to: CalloutCut, width: number, frameId: string, continuation: boolean, mirrored?: boolean, frame?: FrameBoxOptions) => CalloutLayoutResult; } export declare const makeCalloutLayouter: (pass: FrameLayoutPass, startIdx: number, plan: PlannedCallout, style: ResolvedCalloutStyleConfig) => CalloutLayouter; /** The cut a page break between the parts of a contents puts in a box * (`toc.parts.breakBefore`, #996): the head of the first part row after * `from` that opens a page of its own, when something stands before it in * the fragment. A box ignores the `:::pagebreak` rows; the rows carry the * break (`TocBlockInfo.breakBefore`). Undefined when there is none. */ export declare const partBreakCut: (pass: FrameLayoutPass, L: CalloutLayouter, from: CalloutCut) => CalloutCut | undefined; /** What a cut of a composed page's frame keeps together besides * `splitMinLines` (#913), as the running text does: a heading with what * follows it, and the items of a list, at least `listOrphans` before the * cut and `listWidows` after it (a short list under `shortListSplit: * 'avoid'` none: it moves whole). A list that cannot be cut so is cut * before it, or inside one of its items. */ export interface FrameCutRules { keepHeadings: boolean; listOrphans: number; listWidows: number; /** Lists of at most this many items are never cut between items. */ wholeListMaxItems: number; } /** The cut rules of a frame under `resolved` (#913). */ export declare const frameCutRules: (resolved: ResolvedConfig) => FrameCutRules; export interface CalloutFragment { /** The cut the rest of the box starts at. */ to: CalloutCut; result: CalloutLayoutResult; } /** The longest leading fragment of the box from cut `from` on whose box * is at most `roomPx` tall. Cuts fall between children or between the * lines of a text child. `splitMinLines` guards text: a cut between * children leaves on each side at least that many text lines or at least * one indivisible block (a figure, table, display formula or nested * box); a cut inside a text child counts every line on its side, a block * as one line, and leaves at least `layout.boxChildSplitMinLines` lines * of that child on each side (two by default, `splitMinLines` when that * is lower; EF-115). A nested box that may split * itself (`keepTogether: false`, or taller than a full column) offers the cuts * inside it too, by its own `splitMinLines` over its own children; the * fragments on both sides redraw its frame. The full layout's geometry * ranks the candidates (box bottom = content bottom at the cut + the * tails of the boxes closed below it); the deepest candidate that fits * is laid out for real and taken when it truly fits. `null` when none * does. */ export declare const splitCalloutFragment: (pass: FrameLayoutPass, L: CalloutLayouter, from: CalloutCut, width: number, roomPx: number, frameId: string, continuation: boolean, minLines: number, mirrored?: boolean, frame?: FrameBoxOptions, rules?: FrameCutRules, /** Cut where a part of a contents opens a page of its own, when that * cut fits (#996). */ partBreaks?: boolean) => CalloutFragment | null; /** Absolute content indices of the children a fragment from cut `from` * to cut `to` of `L` touches, for the fragment's source range. */ export declare const fragmentRange: (L: CalloutLayouter, from: CalloutCut, to: CalloutCut) => { firstChildIdx: number; lastChildIdx: number; }; /** The (rest of the) box is taller than an empty, full-height column — * a whole page's content area for a page-span box: no column could * hold it, so even a keep-together box splits (with the rules of a * `keepTogether: false` one) rather than overflow. */ export declare const tallerThanColumn: (pass: FrameLayoutPass, result: CalloutLayoutResult) => boolean; //# sourceMappingURL=frameLayout.d.ts.map