import { F as FontFamily, I as InlineAnnotation } from './types-DnPOMbQV.js'; /** * Exclusion zone — a rectangular region that text must flow around. * * In vertical writing mode (`writing-mode: vertical-rl`): * - The **block direction** is horizontal (right-to-left), where each line is a column. * - The **inline direction** is vertical (top-to-bottom), which is the `lineWidth` axis. * - `blockStart` / `blockEnd` map to line indices. * - `inlineSize` is how much of the line's width the exclusion occupies. */ interface ExclusionZone { /** First affected line index (0-based, inclusive). */ blockStart: number; /** Last affected line index (exclusive). */ blockEnd: number; /** Amount of inline space consumed by the exclusion (px). Subtracted from `lineWidth`. */ inlineSize: number; } /** * Computes per-line widths by subtracting exclusion zones from the base line width. * * Multiple exclusion zones may overlap; their inline sizes are summed per line. * A line whose exclusions consume its whole inline size is clamped to a small * positive width rather than to 0, so the result is always a valid `lineWidths` * input for `computeBreaks()`. * * @param baseLineWidth - Default line width in pixels. * @param lineCount - Number of lines to generate widths for. * @param exclusions - Exclusion zones that reduce available line width. * @returns A `Float32Array` of per-line widths, every entry strictly positive. */ declare function computeLineWidths(baseLineWidth: number, lineCount: number, exclusions: readonly ExclusionZone[]): Float32Array; /** * A rectangle in content-area coordinates representing an image or obstacle. * * In vertical writing mode: * - `x` / `w` are in the block direction (horizontal, columns flow right-to-left). * - `y` / `h` are in the inline direction (vertical, text flows top-to-bottom). * * Coordinates are relative to the content area origin (top-left of the * area where text is rendered, after padding). * * This is the layout-side shape: it adds the margins the exclusion engine * reserves around the image. The bare `{ x, y, w, h }` shape a host drags * around in its UI is `ImageOverlayRect`. */ interface ImageRect { /** Horizontal offset from the left edge of the content area (px). */ x: number; /** Vertical offset from the top of the content area (px). */ y: number; /** Width in the block direction (px). */ w: number; /** Height in the inline direction (px). */ h: number; /** Margin in the inline direction (top/bottom in vertical-rl) in pixels. Applied to both sides. @defaultValue 0 */ inlineMargin?: number; /** Margin in the block direction (left/right in vertical-rl) in pixels. Applied to both sides. @defaultValue 0 */ blockMargin?: number; } /** * Rendering slot computed from image exclusions. * * Each slot describes where text should be placed and how much vertical space * is available there. A single physical column may produce several slots (e.g. * one above and one below an image) or none at all, and slots are emitted in * reading order rather than in column order — so a slot's position in the array * is a line index, not a column index. The physical column a slot belongs to is * given by `columnIndex`. */ interface ColumnSlot { /** Horizontal offset from the right edge of the content area (px). */ xPos: number; /** Vertical offset from the top of the content area (px). */ yStart: number; /** Available height for text in this column (px). */ height: number; /** * Physical column this slot belongs to (0 = the column nearest the right * content edge). Several slots share a `columnIndex` when an image splits a * column into multiple gaps. Every slot produced by this package carries it; * it is optional only so hand-built slot arrays stay assignable. */ columnIndex?: number; } /** * Page geometry for exclusion computation. */ interface ExclusionPageGeometry { /** Base line width (inline size of a full column) in pixels. */ lineWidth: number; /** Number of columns on the page. */ lineCount: number; /** Column pitch (fontSize × lineHeight) in pixels. */ linePitch: number; /** Total content width in the block direction (px). */ contentWidth: number; /** Minimum vertical gap height usable for text. Defaults to `linePitch`. */ minGapHeight?: number; } /** * Manages image exclusion zones for text layout on a page. * * Computes per-column text placement by finding all contiguous * vertical gaps not occupied by any image. Each gap becomes a * layout slot with its own line width and rendering position. * * For a column partially blocked by an image, the engine produces * multiple slots (e.g. one above and one below the image), each with * its own line width entry. Slots are emitted in reading order: a run * of adjacent columns split the same way by an image forms a band * group, and text fills the band above the image across the whole * group before wrapping back to the band below it. * * @example * ```ts * const engine = new ExclusionEngine({ * lineWidth: 600, * lineCount: 12, * linePitch: 30.4, * contentWidth: 380, * }); * * engine.addImage({ x: 100, y: 50, w: 120, h: 160 }); * * const { slots, lineWidths } = engine.compute(); * const result = computeBreaks({ text, advances, lineWidth: 600, lineWidths }); * // Render each line at slots[i].xPos, slots[i].yStart * ``` */ declare class ExclusionEngine { private geometry; private images; /** * Creates an engine for one page's geometry with an empty image set. The * geometry is retained by reference until {@link ExclusionEngine.setGeometry} * replaces it, so pass a value the caller will not mutate afterwards. * * @param geometry - Column count, pitch and content extent of the page. */ constructor(geometry: ExclusionPageGeometry); /** Replaces page geometry (e.g. on resize). */ setGeometry(geometry: ExclusionPageGeometry): void; /** Returns the current page geometry. */ getGeometry(): Readonly; /** Adds an image to the exclusion set. Returns `this` for chaining. */ addImage(rect: ImageRect): this; /** Removes a previously added image by reference equality. */ removeImage(rect: ImageRect): boolean; /** Removes all images. */ clearImages(): void; /** Returns the current list of images (read-only). */ getImages(): readonly ImageRect[]; /** Returns the number of images. */ get imageCount(): number; /** * Computes slots and line widths for the current images. * * For each physical column, finds **all** contiguous vertical gaps * not occupied by any image. Each gap becomes a separate slot. * Affected columns may produce several slots (and thus several * entries in `lineWidths`), or none at all when an image blocks the * whole column, so `slots.length` may be above or below `lineCount` * and a slot cannot be looked up by column index — read * {@link ColumnSlot.columnIndex} to recover the physical column. * * Slots come out in reading order, not column order: adjacent columns * split identically by an image form a band group whose upper band is * filled across every column of the group before the band below it. * * Every `lineWidths` entry is strictly positive: a gap with no usable * height produces no slot rather than a zero-width one. * * @returns Slots for rendering, line widths for `computeBreaks()`, * and whether any column's slot coverage differs from the unobstructed * layout (one full-height slot per column). */ compute(): { slots: ColumnSlot[]; lineWidths: Float32Array; affected: boolean; }; } /** * Computes per-column text placement slots for images on a page. * * Convenience function equivalent to creating an {@link ExclusionEngine}, * adding all images, and calling `compute()`. Prefer the class when * images are added/removed incrementally. * * @param options - Page geometry and image placements. * @returns Column slots for rendering, line widths for layout, and whether * any column's slot coverage differs from the unobstructed layout. */ declare function computeExclusionSlots(options: ExclusionPageGeometry & { /** Image rectangles in content-area coordinates. */ images: readonly ImageRect[]; }): { slots: ColumnSlot[]; lineWidths: Float32Array; affected: boolean; }; /** * Geometry for a two-page spread in vertical writing mode. * * Both pages are assumed to have the same dimensions. * In `writing-mode: vertical-rl`, the right page comes first * (columns flow right-to-left), then the left page continues. */ interface SpreadGeometry { /** Width of each page in pixels (both pages are the same width). */ pageWidth: number; /** Horizontal padding on each side of each page (px). */ pagePaddingX: number; /** Vertical padding at the top of each page (px). */ pagePaddingY: number; /** Base line width (inline size of a full column) in pixels. */ lineWidth: number; /** Column pitch (fontSize × lineHeight) in pixels. */ linePitch: number; } /** * An image rectangle positioned relative to the **right page's top-left corner**. * * Negative `x` values indicate the image extends into the left page. * The engine handles the gutter (padding between pages) automatically. */ type SpreadImageRect = ImageRect; /** * Result of spread exclusion computation. */ interface SpreadExclusionResult { /** Slots for the right page. */ rightSlots: ColumnSlot[]; /** Slots for the left page. */ leftSlots: ColumnSlot[]; /** Combined lineWidths for a single `computeBreaks()` call (right page then left page). */ lineWidths: Float32Array; /** Number of layout lines (slots) allocated to the right page. */ rightSlotCount: number; /** * Whether any right-page column's slot coverage differs from the * unobstructed layout (one full-height slot per column). True also when a * column is blocked entirely and therefore produces no slot at all. */ rightAffected: boolean; /** Same as {@link SpreadExclusionResult.rightAffected} for the left page. */ leftAffected: boolean; } /** * Manages image exclusion across a two-page spread. * * Images are positioned relative to the right page's top-left corner. * The engine automatically converts coordinates for the left page, * accounting for the gutter (page padding on inner edges). * * Text flows continuously from the right page to the left page. * The combined `lineWidths` can be passed directly to `computeBreaks()` * for a single layout pass across both pages. * * @example * ```ts * const spread = new SpreadExclusionEngine({ * pageWidth: 537, * pagePaddingX: 52, * pagePaddingY: 56, * lineWidth: 676, * linePitch: 30.4, * }); * * // Image on the right page * spread.addImage({ x: 200, y: 100, w: 120, h: 160, inlineMargin: 16 }); * * // Image straddling the gutter (negative x = left page) * spread.addImage({ x: -100, y: 300, w: 200, h: 100 }); * * const { rightSlots, leftSlots, lineWidths, rightSlotCount } = spread.compute(); * const result = computeBreaks({ text, advances, lineWidth: 676, lineWidths }); * * // Split lines for rendering: * // Lines 0..rightSlotCount-1 → right page using rightSlots * // Lines rightSlotCount.. → left page using leftSlots * ``` */ declare class SpreadExclusionEngine { private geometry; private images; /** * Creates an engine for one spread's geometry with an empty image set. Column * counts are derived from the geometry on every {@link * SpreadExclusionEngine.compute} call, so only the geometry needs replacing on * resize. The value is retained by reference until * {@link SpreadExclusionEngine.setGeometry} replaces it. * * @param geometry - Page extent, padding and column pitch of the spread. */ constructor(geometry: SpreadGeometry); /** Replaces spread geometry (e.g. on resize). */ setGeometry(geometry: SpreadGeometry): void; /** Returns the current spread geometry. */ getGeometry(): Readonly; /** * Adds an image positioned relative to the right page's top-left corner. * Negative `x` values indicate the image extends into the left page. * Returns `this` for chaining. */ addImage(rect: ImageRect): this; /** Removes a previously added image by reference equality. */ removeImage(rect: ImageRect): boolean; /** Removes all images. */ clearImages(): void; /** Returns the current list of images (read-only). */ getImages(): readonly ImageRect[]; /** Returns the number of images. */ get imageCount(): number; /** * Computes exclusion slots and line widths for the full spread. * * Internally creates two {@link ExclusionEngine} instances (right and left page), * distributes images to the correct page with proper coordinate conversion * (accounting for page padding / gutter), and concatenates the results into * a single continuous `lineWidths` array. * * Each page also reports whether its slot coverage was changed by the images, * so callers can tell "no image effect" from "image effect that happens to * leave every surviving slot at full height". */ compute(): SpreadExclusionResult; } /** * Extracts line ranges (character start/end pairs) from break points. * * Converts the compact `breakPoints` array from a `BreakResult` into * an array of `[startIndex, endIndex)` pairs, one per line. * * @param breakPoints - Break point indices from `BreakResult`. * @param charCount - Total number of characters in the text. * @returns Array of `[start, end)` index pairs for each line. */ declare function getLineRanges(breakPoints: Uint32Array, charCount: number): [number, number][]; /** * Measurement for a single paragraph used in pagination. */ interface ParagraphMeasure { /** * Number of lines (columns in vertical-rl) in this paragraph. A paragraph * with no lines contributes no {@link PageSlice}; only its `gapBefore` is * consumed. */ lineCount: number; /** Size of each line in the block direction (px). Typically fontSize * lineHeight. */ linePitch: number; /** Gap before this paragraph in the block direction (px). Ignored when paragraph starts a page. */ gapBefore: number; } /** * A slice of a paragraph assigned to a page. */ interface PageSlice { /** Index of the paragraph in the input array. */ paragraphIndex: number; /** First line index within the paragraph (0-based). */ lineStart: number; /** End line index within the paragraph (exclusive). */ lineEnd: number; } /** * Computes page assignments for a sequence of paragraphs. * * Distributes paragraph lines across pages of fixed block size, * splitting paragraphs at page boundaries when necessary. * Each line consumes its paragraph's `linePitch` in the block direction, * and inter-paragraph gaps are added before the first line of each * paragraph (except at page start). * * A paragraph with `lineCount: 0` has nothing to place, so it produces no * slice; its `gapBefore` is still consumed, which keeps a spacer paragraph * separating the paragraphs around it. Consequently not every input paragraph * is guaranteed to appear in the output. * * @param pageBlockSize - Available size in the block direction per page (px). * @param paragraphs - Measurements for each paragraph. * @returns Array of pages, each containing an array of paragraph slices. * Always at least one page, empty when nothing could be placed. */ declare function paginate(pageBlockSize: number, paragraphs: ParagraphMeasure[]): PageSlice[][]; /** Configuration for {@link MejiroBook}. */ interface BookOptions { /** * CSS font family. Either a CSS-ready string (e.g. `'"Noto Serif JP", serif'`) * or an array of family names (e.g. `['Noto Serif JP', 'serif']`). Arrays are * escaped + joined per CSS rules. */ fontFamily: FontFamily; /** Base font size in pixels. */ fontSize: number; /** * Line spacing multiplier. Controls the pitch between adjacent columns * in vertical writing mode (equivalent to CSS `line-height`). * @defaultValue 1.8 */ lineSpacing?: number; /** Kinsoku processing mode. @defaultValue 'strict' */ mode?: 'strict' | 'loose'; /** Whether to enable hanging punctuation. @defaultValue true */ enableHanging?: boolean; /** * Per-level heading style overrides. Keys are heading levels (1–6). * Each level can override `scale` and `gapAfterEm`. */ headingStyles?: Record; /** * Default scale factor for heading font sizes when no per-level * style is defined in `headingStyles`. * @defaultValue 1.4 */ headingScale?: number; } /** Page geometry configuration. */ interface PageSize { /** Page width in pixels (block direction extent of one page). */ pageWidth: number; /** Line width in pixels (inline direction extent — vertical height of text columns). */ lineWidth: number; /** Horizontal padding on each side of a page in pixels. @defaultValue 0 */ pagePaddingX?: number; /** Vertical padding at the top of a page in pixels. @defaultValue 0 */ pagePaddingY?: number; } /** Overrides for {@link MejiroBook.computePageSize}. */ interface ComputePageSizeOptions { /** * Per-page padding overrides applied via {@link MejiroBook.setPageSize}. * Defaults to {@link DEFAULT_PAGE_PADDING}. */ padding?: { x?: number; y?: number; bottom?: number; }; /** Page aspect ratio (height / width). @defaultValue 1.45 */ aspect?: number; /** Minimum page width in pixels. @defaultValue 280 */ minWidth?: number; /** Minimum page height in pixels. @defaultValue 400 */ minHeight?: number; /** Maximum page height in pixels. @defaultValue 780 */ maxHeight?: number; /** * Pixels reserved at the top of the container for header chrome. * @defaultValue 56 */ headerOffset?: number; /** * Horizontal pixels reserved across the container (gutter between/around the two pages). * @defaultValue 48 */ gutterOffset?: number; /** * Number of page columns the spread occupies horizontally. Use `1` for a * single-page reader so the page width is derived from the full container * width instead of being halved for a two-page spread. `2` is the * two-page-spread default. * @defaultValue 2 */ columns?: 1 | 2; } /** * Structural classification of a {@link BookParagraph}. * * - `'body'` — ordinary body text (the default when `kind` is omitted). * - `'heading'` — heading paragraph; pair with {@link BookParagraph.headingLevel}. * - `'blockquote'` — quoted block. * - `'sceneBreak'` — visible scene divider (e.g. `* * *`); typically rendered * without body text. * - `'pre'` — preformatted text (no automatic line breaks). Reserved. * - `'figure'` — figure container (image + optional caption). Reserved. */ type ParagraphKind = 'body' | 'heading' | 'blockquote' | 'sceneBreak' | 'pre' | 'figure'; /** A paragraph to lay out, compatible with EPUB chapter paragraphs. */ interface BookParagraph { /** Text string to lay out. */ text: string; /** * Structural kind of the paragraph. Defaults to `'heading'` if * {@link BookParagraph.headingLevel} is set, otherwise `'body'`. */ kind?: ParagraphKind; /** Inline annotations (ruby, emphasis, tcy, em/strong, link, footnote). */ inlineAnnotations?: readonly InlineAnnotation[]; /** Heading level (1–6), or undefined for body text. */ headingLevel?: number; } /** An image rectangle for exclusion layout. Coordinates are relative to the right page's top-left corner. */ interface BookImage { /** Horizontal offset from the left edge of the right page (px). */ x: number; /** Vertical offset from the top of the right page (px). */ y: number; /** Width in pixels. */ w: number; /** Height in pixels. */ h: number; /** Margin around the image in pixels (applied on both inline sides). Defaults to base `fontSize`. */ margin?: number; } /** Result for a two-page spread. */ interface SpreadResult { /** Right page (first page in vertical-rl reading order). */ readonly right: PageResult; /** Left page (second page in the spread). */ readonly left: PageResult; /** Total number of pages in the layout. */ readonly totalPages: number; } /** Result for a single page. */ interface PageResult { /** Paragraph-structured page data (for CSS `writing-mode: vertical-rl` rendering). */ readonly page: RenderPage; /** Flat line list with per-line positioning (for slot-based absolute rendering). */ readonly lines: readonly PageLine[]; /** Per-line column slots with position and dimensions. */ readonly slots: readonly ColumnSlot[]; /** Whether this page has image exclusions affecting line widths. */ readonly hasImages: boolean; } /** A single line for slot-based rendering. */ interface PageLine { /** Segments (text and ruby) that make up this line. */ readonly segments: readonly RenderSegment[]; /** Heading level if this line belongs to a heading paragraph. */ readonly headingLevel?: number; /** Computed font size in pixels for this line (accounts for heading scale). */ readonly fontSize: number; } /** A text segment within a rendered line. */ type RenderSegment = { type: 'text'; text: string; } | { type: 'ruby'; base: string; rubyText: string; children?: readonly RenderSegment[]; } | { type: 'emphasis'; text: string; style: 'sesame' | 'dot' | 'circle'; children?: readonly RenderSegment[]; } | { type: 'tcy'; text: string; children?: readonly RenderSegment[]; } | { type: 'em'; text: string; children?: readonly RenderSegment[]; } | { type: 'strong'; text: string; children?: readonly RenderSegment[]; } | { type: 'link'; text: string; href: string; title?: string; children?: readonly RenderSegment[]; } | { type: 'footnote-ref'; text: string; noteId: string; children?: readonly RenderSegment[]; }; /** A single rendered line containing text and ruby segments. */ interface RenderLine { /** Segments that make up this line. */ readonly segments: readonly RenderSegment[]; } /** A rendered paragraph containing multiple lines. */ interface RenderParagraph { /** Lines in this paragraph. */ readonly lines: readonly RenderLine[]; /** Whether this paragraph is a heading (true if headingLevel is set). */ readonly isHeading: boolean; /** Heading level (1–6), or undefined for body text. */ readonly headingLevel?: number; /** * Structural classification carried over from the source paragraph, mapped to * the `mejiro-paragraph--*` class the bundled stylesheets expect. */ readonly kind?: ParagraphKind; } /** A full rendered page containing paragraphs. */ interface RenderPage { /** Paragraphs on this page. */ readonly paragraphs: readonly RenderParagraph[]; } /** Per-line layout metric for exclusion-mode column positioning. */ interface LineMetric { /** Horizontal pitch this line occupies (heading lines are wider than body). */ pitch: number; /** Gap before this line in pixels (paragraph or heading gap; 0 for mid-paragraph lines). */ gapBefore: number; /** Heading level if this line belongs to a heading paragraph. */ headingLevel?: number; } /** Result of {@link buildLineMetrics}. */ interface LineMetricsResult { /** One LineMetric per flattened line across all paragraphs. */ metrics: LineMetric[]; /** Cumulative x-offset at each line index, accounting for heading pitch excess and paragraph gaps. */ offsets: Float32Array; /** Base body line pitch (fontSize × lineSpacing). */ linePitch: number; } /** Input entry for render functions, combining layout results with annotations. */ interface RenderEntry { /** Character array of the paragraph text, indexed by Unicode code point. */ chars: string[]; /** Break points from the line breaking algorithm. */ breakPoints: Uint32Array; /** Inline annotations for this paragraph (ruby, emphasis, tcy, etc.). */ inlineAnnotations: readonly InlineAnnotation[]; /** * Whether this paragraph is a heading. * @deprecated Use `headingLevel` instead. When `headingLevel` is set, this field is ignored. */ isHeading?: boolean; /** Heading level (1–6), or undefined for body text. */ headingLevel?: number; /** Structural classification of the source paragraph. @defaultValue 'body' */ kind?: ParagraphKind; } /** Style overrides for a specific heading level. */ interface HeadingStyle { /** Scale factor for heading font size relative to base fontSize. */ scale?: number; /** Gap after this heading in em units (based on base fontSize). */ gapAfterEm?: number; } /** Options for computing paragraph measures. */ interface MeasureOptions { /** Base font size in pixels. */ fontSize: number; /** Line spacing multiplier. */ lineSpacing?: number; /** * Line spacing multiplier. * @deprecated Use `lineSpacing`; retained as a v0.x compatibility alias. */ lineHeight?: number; /** * Scale factor for heading font size (applies to all heading levels * unless overridden by `headingStyles`). * @defaultValue 1.4 */ headingScale?: number; /** Gap before body paragraphs in em units. @defaultValue 0.4 */ paragraphGapEm?: number; /** * Gap after a heading paragraph in em units (applies to all heading levels * unless overridden by `headingStyles`). * @defaultValue 1.2 */ headingGapEm?: number; /** * Per-level heading style overrides. Keys are heading levels (1–6). * Each level can override `scale` and `gapAfterEm`. */ headingStyles?: Record; } /** * Builds paragraph measures from render entries for use with `paginate()`. * * Computes line pitch (font size x line spacing) and inter-paragraph gaps * based on whether each paragraph is a heading or body text. * * @param entries - Render entries for each paragraph. * @param options - Font size, line spacing, and paragraph gap configuration. * @returns Array of paragraph measures suitable for `paginate()`. */ declare function buildParagraphMeasures(entries: RenderEntry[], options: MeasureOptions): ParagraphMeasure[]; /** * Computes per-line layout metrics and cumulative x-offsets from render entries. * * Used for exclusion-mode rendering where column positions must account for * heading pitch differences and paragraph gaps. The cumulative offsets enable * adjusting image coordinates before passing them to the exclusion engine. * * @param entries - Render entries for each paragraph. * @param options - Font size, line spacing, and paragraph gap configuration. * @returns Per-line metrics array, cumulative offsets, and base line pitch. */ declare function buildLineMetrics(entries: RenderEntry[], options: MeasureOptions): LineMetricsResult; /** * Counts how many lines fit within a page width, accounting for per-line pitch * and paragraph gaps. The first line on a page uses only its pitch (no gap). * * @param metrics - Per-line metrics from {@link buildLineMetrics}. * @param startIdx - Index of the first line to pack. * @param pageWidth - Available page width in pixels. * @returns Number of lines that fit. */ declare function packPageLines(metrics: LineMetric[], startIdx: number, pageWidth: number): number; /** * Builds column slots for a normal (non-image) page with per-line pitch and * paragraph gap offsets baked into each slot's `xPos`. * * @param metrics - Per-line metrics from {@link buildLineMetrics}. * @param startIdx - Index of the first line on this page. * @param count - Number of lines to include. * @param columnHeight - Height of each column (vertical content height). * @returns Array of column slots suitable for absolute positioning. */ declare function buildColumnSlots(metrics: LineMetric[], startIdx: number, count: number, columnHeight: number): ColumnSlot[]; /** * Adjusts exclusion engine slots by adding heading pitch excess and paragraph * gaps. The exclusion engine assumes uniform line pitch; this function corrects * the slot positions to account for heading lines being wider and inter-paragraph * spacing. * * Slots arrive in reading order, so a column split into several gaps by an * image is revisited later in the array rather than occupying a contiguous run. * The offset of a column is therefore established the first time that column is * seen and replayed on every later slot of the same column, keeping all gaps of * one column on a single physical x position. * * The exclusion engine also derives its column count from the uniform base * pitch (`floor(contentWidth / basePitch)`), so a spread with a wider-than-body * heading produces more columns than physically fit once the heading excess is * re-added here. When `contentWidth` is supplied, a column whose adjusted * physical extent (`xPos + pitch`) would overflow the content box is dropped — * including its gaps further along the reading order — so the caller can reflow * those lines onto the following page/spread instead of letting them clip past * the page's leading edge. Trimming is decided per column, at that column's * first gap, so a column is kept whole or not at all. At least one slot is * always kept so layout makes progress. * * @param slots - Column slots from the exclusion engine. * @param metrics - Per-line metrics from {@link buildLineMetrics}. * @param startIdx - Global line index of the first slot. * @param basePitch - Base body line pitch (from {@link LineMetricsResult.linePitch}). * @param contentWidth - Page content-box width (px). When set, overflowing * columns are dropped. When omitted, no trimming is applied. * @returns New array of adjusted slots (input is not mutated). */ declare function adjustExclusionSlots(slots: ColumnSlot[], metrics: LineMetric[], startIdx: number, basePitch: number, contentWidth?: number): ColumnSlot[]; /** * Returns the cumulative x-offset at a given column within a spread. * Used to adjust image x-coordinates before passing them to the exclusion engine, * compensating for heading pitch differences and paragraph gaps. * * @param offsets - Cumulative offsets from {@link LineMetricsResult.offsets}. * @param spreadStartLine - Global line index of the spread's first line. * @param col - Column index within the spread (0 = rightmost). * @returns Relative x-offset in pixels. */ declare function getImageXOffset(offsets: Float32Array, spreadStartLine: number, col: number): number; /** * Finds the column index at a given physical distance from the right content edge, * accounting for heading pitch differences and paragraph gaps. * * The physical position of column `col` is `col * basePitch + offset(col)`. * A naive `floor(fromRight / basePitch)` overestimates the column index when * heading lines are wider than body lines. This function refines the estimate * downward until the physical position fits within `fromRight`. * * Degenerate inputs resolve to the first column: a `basePitch` that is not a * positive finite number carries no scale to search along, and a non-finite * `fromRight` has no column to point at. * * @param offsets - Cumulative offsets from {@link LineMetricsResult.offsets}. * @param spreadStartLine - Global line index of the spread's first line. * @param fromRight - Physical distance from the right content edge (px). * @param basePitch - Base body line pitch (px). * @returns Column index at that physical distance, always a finite integer in * `[0, offsets.length - spreadStartLine - 1]`. */ declare function findPhysicalColumn(offsets: Float32Array, spreadStartLine: number, fromRight: number, basePitch: number): number; export { buildParagraphMeasures as A, type BookOptions as B, type ColumnSlot as C, findPhysicalColumn as D, ExclusionEngine as E, getImageXOffset as F, packPageLines as G, type HeadingStyle as H, type ImageRect as I, type LineMetric as L, type MeasureOptions as M, type PageSlice as P, type RenderEntry as R, SpreadExclusionEngine as S, type ExclusionPageGeometry as a, type ExclusionZone as b, type ParagraphMeasure as c, type SpreadExclusionResult as d, type SpreadGeometry as e, type SpreadImageRect as f, computeExclusionSlots as g, computeLineWidths as h, getLineRanges as i, type PageSize as j, type ParagraphKind as k, type BookImage as l, type SpreadResult as m, type PageResult as n, type ComputePageSizeOptions as o, paginate as p, type BookParagraph as q, type PageLine as r, type RenderPage as s, type RenderSegment as t, type LineMetricsResult as u, type RenderLine as v, type RenderParagraph as w, adjustExclusionSlots as x, buildColumnSlots as y, buildLineMetrics as z };