import { GetHtmlOptions } from './text-html.js';
import type { TextElementLike } from './text-types.js';
/**
* The shared shrink-to-fit loop for `textOverflow: 'change-font-size'`, used
* by the editor canvas and html-export so their fit results can't drift.
* svg-export and pdf-export deliberately keep their own LOOPS, on their own
* layout engines — see "Deliberate divergences" in ../DESIGN_NOTES.md before
* trying to converge them. The `FIT_*` values below are NOT part of that
* divergence: a renderer that steps on a different schedule lands on a
* different font size than the canvas, which is the one thing every converter
* has to match. They are exported for those loops to import, never to restate.
*
* What stays private is everything that only makes sense PER PASS. This loop
* is not the whole fit: the editor writes each result back onto the element
* and fits again, so `MAX_STEPS` and the relative `MIN_SCALE_FACTOR` are rate
* limits the next pass resumes past — a single-pass renderer that imported
* them would stop early and call it converged. ../DESIGN_NOTES.md has the case.
*
* Callers inject environment specifics as plain parameters (this module is
* flag/mobx-free): the editor wraps it with its live flags and the render-tag
* measurer; html-export calls it with the defaults (DOM `detectSize`
* measurement — under jsdom heights come back 0 so the fit is a no-op; in
* plain Node without a DOM it throws, which callers catch).
*/
export type FitResult = {
fontSize: number;
text?: string;
};
export type MeasureHeight = (html: string) => number;
export interface FitTextOptions {
/** Options forwarded to `getHtml` when building each measured candidate. */
getHtmlOptions?: GetHtmlOptions;
measureHeight?: MeasureHeight;
/**
* Allow mid-word wrapping. When false (the default, mirroring the editor's
* `flags.textSplitAllowed`), a mid-word wrap counts as overflow and shrinks
* the font even when the height fits.
*/
textSplitAllowed?: boolean;
}
/** The plain-JSON snapshot of a text element the fit loop reads: the same
* shape `getHtml` consumes, with the fields the loop scales required. */
export type FitTextElement = TextElementLike & {
fontSize: number;
fontFamily: string;
};
export declare const FIT_SCALE_STEP = 0.02;
export declare const FIT_FONT_SIZE_STEP = 0.5;
export declare const FIT_HEIGHT_EPSILON = 0.02;
export declare const FIT_MIN_FONT_SIZE = 1;
export declare function findFitFontSize(element: FitTextElement, options?: FitTextOptions): FitResult;
/**
* The shrink-to-fit loop for a converter that lays its text out with
* **render-tag** — svg-export and pdf-export both do, and drawing from the same
* layout is what lets them share one loop.
*
* This is NOT `findFitFontSize` above, and the two are not convergeable: that
* one measures rendered HTML and carries the editor's overflow VERDICT (a
* mid-word wrap counts as overflow unless `textSplitAllowed`), while a
* converter fits on HEIGHT alone — polotno-node leaves `textSplitAllowed` at
* its default and still breaks the long word rather than shrinking, so
* height-only is what matches the render every converter is measured against.
* See "Deliberate divergences" in ../DESIGN_NOTES.md.
*
* What the two share is the SCHEDULE — `FIT_*` above — because a renderer that
* steps differently lands on a different font size than the canvas.
*
* `layoutAt` is the caller's own layout call, so each converter keeps measuring
* with the engine it draws with. `R` is whatever that returns; the loop reads
* only `height`.
*/
export declare function fitByLayout({ element, shrink, layoutAt, }: {
element: TextElementLike & {
fontSize: number;
};
/** False for `textOverflow: 'resize'`, which renders at natural height. */
shrink: boolean;
layoutAt: (fontSize: number, text?: string, textIsNormalized?: boolean) => R;
}): {
result: R;
fontSize: number;
};