/** * Float slots — the pure geometry half of first-available-slot placement. * * A pending float (a figure / table incorporated by its first reference) is * offered the slots of the CURRENT page in reading order after the cursor: * the top of the referencing column when it is still empty, its bottom, then * the top and bottom of every later empty text column of the same band. The * column a page-span opener was set in counts as empty at its head while it * holds nothing but the opener: its head is the first line under the * opener's band (#639). A * page-span float on a multi-column band gets one slot: the band's bottom. * What does not fit on the current page waits for the next page opened by * the flow (`flushFloatsIntoPage` in `build.ts`). `'top'` / `'bottom'` * positions restrict the search to that kind of slot; `'auto'` takes both. * * The build pipeline owns the mutation (shrinking columns, pushing the block * into `page.floats`); this module only enumerates and measures. */ import type { BoundingBox, VDTColumn, VDTPage } from '../vdt.js'; import type { PlannedFloat } from './floatPlacement.js'; export type FloatSlotPosition = 'top' | 'bottom'; /** One candidate slot: the columns whose band it reserves (one column for a * column-span float, every text column of the band for a page-span one). */ export interface FloatSlot { cols: VDTColumn[]; position: FloatSlotPosition; pageSpan: boolean; /** The slot is the float-only side column (`span: 'side'`): the float * stacks under what the column already holds, no lower than `refY` * (the top of the text that cites it), and consumes the column's * `availableHeight` instead of cutting a band. */ side?: boolean; refY?: number; } /** Kind of band cap a column is currently under, if any (`undefined` when * uncapped). A `'span'` cap means a page-span block will cut the band at * the cap, so the column's bottom is not a slot; a `'trailing'` cap only * levels the closing band and leaves the true bottom free. */ export type ColumnCapKind = 'span' | 'trailing' | undefined; /** Candidate slots on the current page, in reading order after the cursor. * `openerHeadOf` gives, for the column that holds a page-span opener and * nothing after it, the y of its head under the opener's band (#639); * `undefined` for any other column. */ export declare function enumerateCurrentPageSlots(page: VDTPage, cursorColumnIndex: number, f: PlannedFloat, capKindOf: (col: VDTColumn) => ColumnCapKind, openerHeadOf?: (col: VDTColumn) => number | undefined): FloatSlot[]; /** What `measureFloatBand` needs to know about the laid-out float. */ export interface FloatMeasure { height: number; /** Block-relative baseline of the caption's last line, when captioned. */ lastCaptionBaseline?: number; /** For a rotated block: the width it takes on the page (its upright * height), which must fit the band's width. */ rotatedWidth?: number; /** Height of a caption band set beside the body (`placement.captionSide`). */ asideHeight?: number; /** A floated box's `marginBottom` (px), when it is wider than the float * gap: the space a top band keeps under the box (EF-144). */ gapBelow?: number; /** A floated box's `marginTop` (px), when it is wider than the float * gap: the space a bottom band keeps above the box. */ gapAbove?: number; /** For a picture (bitmap, SVG, video poster): the height of its body * and the scale it is set at (1 unless scaled to its slot), which * `placement.shrink` reads (#626). */ body?: { height: number; scale: number; }; } /** The space a top band keeps under `built`: the float gap, or a floated * box's wider `marginBottom`. */ export declare function floatGapBelow(built: FloatMeasure, gapPx: number): number; /** The space a bottom band keeps above `built`: the float gap, or a * floated box's wider `marginTop`. */ export declare function floatGapAbove(built: FloatMeasure, gapPx: number): number; /** A band of a side column that a heading design paints over (absolute y): * a chapter numeral hung in the outer margin column, say. What the side * stack sets there keeps clear of it (EF-78). */ export interface SideObstacle { top: number; bottom: number; } /** The first position at or below `y` where an item `height` tall clears * every obstacle by `gapPx` above and below it. `snap` rounds a candidate * up to the baseline grid. An item that fits above an obstacle stays there: * a numeral beside a heading further down the page does not push the * figures stacked at the head of the column. */ export declare function clearSideObstacles(y: number, height: number, obstacles: readonly SideObstacle[] | undefined, gapPx: number, snap: (v: number) => number): number; /** Geometry of a float stacked in the side column: it starts at the foot of * what the column holds, or at `refY` (the top of the citing text) when * that is lower, snapped up to the baseline grid of the content area — * moved on under any heading-design element (`obstacles`) it would * overlap there — and consumes the column's free height from the stack's * foot to its own foot plus `gapPx`. */ export declare function measureSideStack(built: FloatMeasure, col: VDTColumn, refY: number | undefined, contentArea: BoundingBox, baselineGrid: number, gapPx: number, obstacles?: readonly SideObstacle[]): { need: number; y: number; }; /** Band geometry for one slot. Both kinds are corrected against the baseline * grid so the surrounding text — and the facing page — keeps the rhythm: * - top: the band height is rounded up to a grid multiple (growing the gap * below the float), so every line of the displaced column stays on grid; * - bottom: the float is anchored so its visual bottom sits on the grid — * the caption's last baseline shares the last text baseline of the other * columns (captionless content aligns its bottom edge to the last slot). * Returns the band height to reserve (`need`) and the float's `y`. */ export declare function measureFloatBand(position: FloatSlotPosition, built: FloatMeasure, cols: readonly VDTColumn[], contentArea: BoundingBox, baselineGrid: number, gapPx: number, trueBottomOf: (col: VDTColumn) => number): { need: number; y: number; }; /** Whether `col` already holds a float band (x-overlap with a float on the * page). Used to keep a minimum of text room when stacking bands. */ export declare function columnHasFloatBand(page: VDTPage, col: VDTColumn): boolean; /** Strict fit for a slot on the current page: the band must fit in the * column's remaining height, keeping `minTextPx` of text room when the * column already holds another float band. */ export declare function fitsStrict(need: number, col: VDTColumn, hasBand: boolean, minTextPx: number): boolean; /** True bottom of a column for slot geometry: the remembered one while a * band cap trims it. */ export declare function trueBottom(col: VDTColumn, uncappedBottoms: ReadonlyMap): number; //# sourceMappingURL=floatSlots.d.ts.map