import { FloatingObjectManager } from './floating-objects.js';
import { PageState } from './paginator.js';
import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure } from '../../contracts/src/index.js';
/**
 * SD-2656: ordered footnote anchor entry. The body slicer reads the candidate
 * anchors for a given PM range and pushes them onto `PageState.footnoteAnchorsThisPage`
 * after committing the slice; the demand formula consumes the resulting list.
 */
export type FootnoteAnchorRef = {
    pmPos: number;
    refId: string;
    fullHeight: number;
    firstLineHeight: number;
};
export type ParagraphLayoutContext = {
    block: ParagraphBlock;
    measure: ParagraphMeasure;
    columnWidth: number;
    ensurePage: () => PageState;
    advanceColumn: (state: PageState) => PageState;
    columnX: (columnIndex: number) => number;
    floatManager: FloatingObjectManager;
    remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure;
    /**
     * Override the paragraph's spacing-after value. Used when contextual spacing
     * should suppress spacing between this paragraph and the next (same-style) paragraph.
     * When undefined, uses the value from block.attrs.spacing.after.
     */
    overrideSpacingAfter?: number;
    /**
     * SD-3049 / SD-2656: footnote demand under the ordered-cluster rule.
     *
     *   demand = sum(fullHeight of cluster[0..N-1]) + firstLineHeight(cluster[N-1])
     *
     * where `cluster` is the ordered list of footnote anchors on the page. The
     * caller passes the already-committed anchors (from PageState) plus the
     * candidate range; this returns the demand assuming the candidate range is
     * appended to the page's cluster.
     *
     * With no committed list, the in-range anchors are treated as the full
     * cluster. With no range, returns the whole-block demand.
     */
    getFootnoteDemandForBlockId?: (blockId: string, pmStart?: number, pmEnd?: number, committed?: ReadonlyArray<FootnoteAnchorRef>) => number;
    /**
     * SD-2656: returns the ordered anchor entries in `[pmStart, pmEnd]` so the
     * slicer can push them onto PageState after accepting a candidate line.
     */
    getFootnoteAnchorsForBlockId?: (blockId: string, pmStart?: number, pmEnd?: number) => ReadonlyArray<FootnoteAnchorRef>;
    /**
     * SD-2656: companion to getFootnoteDemandForBlockId — returns the number
     * of footnote refs anchored in a given PM range of this block. Used to
     * compute band overhead (separator + per-extra-ref gap + safety margin)
     * for the candidate slice.
     */
    getFootnoteRefCountForBlockId?: (blockId: string, pmStart?: number, pmEnd?: number) => number;
    /**
     * SD-2656: per-page footnote-band overhead in pixels for a given number of
     * anchored refs. The slicer's `effectiveBottom` budget must match the
     * planner's, otherwise body packs onto a page whose band cannot fit the
     * refs. Source of truth lives in the planner (incrementalLayout.ts) and
     * derives from `topPadding + dividerHeight + separatorSpacingBefore +
     * (refs-1)*gap`. When not provided, the slicer falls back to a default
     * formula that matches the planner's default values.
     */
    getFootnoteBandOverhead?: (refsTotal: number) => number;
};
export type AnchoredDrawingEntry = {
    block: ImageBlock | DrawingBlock;
    measure: ImageMeasure | DrawingMeasure;
};
export type ParagraphAnchorsContext = {
    anchoredDrawings?: AnchoredDrawingEntry[];
    pageWidth: number;
    pageMargins: PageMargins;
    columns: {
        width: number;
        gap: number;
        count: number;
    };
    placedAnchoredIds: Set<string>;
};
export declare function layoutParagraphBlock(ctx: ParagraphLayoutContext, anchors?: ParagraphAnchorsContext): void;
//# sourceMappingURL=layout-paragraph.d.ts.map