import { Fonts, SFNT } from 'modern-font';
import { NormalizedStyle, NormalizedFill, NormalizedOutline, FullStyle, TextObject, EventEmitter, PropertyDeclaration, ReactiveObject, NormalizedText } from 'modern-idoc';
import { BoundingBox, Path2D, Vector2, VectorLike, Path2DSet } from 'modern-path2d';

declare class Fragment {
    content: string;
    style: NormalizedStyle;
    parent: Paragraph;
    inlineBox: BoundingBox;
    fill?: NormalizedFill;
    outline?: NormalizedOutline;
    characters: Character[];
    computedStyle: FullStyle;
    get computedFill(): NormalizedFill | undefined;
    get computedOutline(): NormalizedOutline | undefined;
    get computedContent(): string;
    constructor(content: string, style: NormalizedStyle | undefined, parent: Paragraph);
    updateComputedStyle(): this;
    initCharacters(): this;
}

declare class Character {
    content: string;
    index: number;
    parent: Fragment;
    path: Path2D;
    lineBox: BoundingBox;
    inlineBox: BoundingBox;
    glyphBox?: BoundingBox;
    advanceWidth: number;
    advanceHeight: number;
    underlinePosition: number;
    underlineThickness: number;
    strikeoutPosition: number;
    strikeoutSize: number;
    ascender: number;
    descender: number;
    typoAscender: number;
    typoDescender: number;
    typoLineGap: number;
    winAscent: number;
    winDescent: number;
    xHeight: number;
    capHeight: number;
    baseline: number;
    centerDiviation: number;
    fontStyle?: 'bold' | 'italic';
    get compatibleGlyphBox(): BoundingBox;
    get center(): Vector2;
    get computedFill(): NormalizedFill | undefined;
    get computedOutline(): NormalizedOutline | undefined;
    get computedStyle(): FullStyle;
    get isVertical(): boolean;
    get fontSize(): number;
    get fontHeight(): number;
    constructor(content: string, index: number, parent: Fragment);
    protected _getFontSFNT(fonts?: Fonts): SFNT | undefined;
    updateGlyph(sfnt?: SFNT | undefined): this;
    update(fonts?: Fonts): this;
    protected _italic(path: Path2D, startPoint?: VectorLike): void;
    getGlyphMinMax(min?: Vector2, max?: Vector2, withStyle?: boolean): {
        min: Vector2;
        max: Vector2;
    } | undefined;
    getGlyphBoundingBox(withStyle?: boolean): BoundingBox | undefined;
    drawTo(ctx: CanvasRenderingContext2D, config?: NormalizedStyle): void;
}

declare class Paragraph {
    style: NormalizedStyle;
    parent: Text$1;
    lineBox: BoundingBox;
    fragments: Fragment[];
    fill?: NormalizedFill;
    outline?: NormalizedOutline;
    computedStyle: FullStyle;
    get computedFill(): NormalizedFill | undefined;
    get computedOutline(): NormalizedOutline | undefined;
    constructor(style: NormalizedStyle, parent: Text$1);
    updateComputedStyle(): this;
    addFragment(content: string, style?: NormalizedStyle): Fragment;
}

interface TextPlugin {
    name: string;
    pathSet?: Path2DSet;
    getBoundingBox?: (text: Text$1) => BoundingBox | undefined;
    update?: (text: Text$1) => void;
    updateOrder?: number;
    render?: (ctx: CanvasRenderingContext2D, text: Text$1) => void;
    renderOrder?: number;
    load?: (text: Text$1) => Promise<void>;
}
interface TextOptions extends TextObject {
    debug?: boolean;
    measureDom?: HTMLElement;
    fonts?: Fonts;
    plugins?: TextPlugin[];
}

interface MeasuredParagraph {
    paragraphIndex: number;
    left: number;
    top: number;
    width: number;
    height: number;
}
interface MeasuredFragment {
    paragraphIndex: number;
    fragmentIndex: number;
    left: number;
    top: number;
    width: number;
    height: number;
}
interface MeasuredCharacter {
    paragraphIndex: number;
    fragmentIndex: number;
    characterIndex: number;
    newParagraphIndex: number;
    content: string;
    left: number;
    top: number;
    width: number;
    height: number;
    textHeight: number;
    textWidth: number;
}
interface measureDOMResult {
    paragraphs: Paragraph[];
    boundingBox: BoundingBox;
}
declare class Measurer {
    static notZeroStyles: Set<string>;
    static pxStyles: Set<string>;
    protected _toDomStyle(style: Record<string, any>): Record<string, any>;
    /**
     * <section style="...">
     *   <ul>
     *     <li style="...">
     *       <span style="...">...</span>
     *       <span>...</span>
     *     </li>
     *   </ul>
     * </section>
     */
    createDom(paragraphs: Paragraph[], rootStyle: FullStyle): HTMLElement;
    measureDOMText(text: Text): {
        content: string;
        top: number;
        left: number;
        width: number;
        height: number;
    }[];
    measureDOM(dom: HTMLElement): {
        paragraphs: MeasuredParagraph[];
        fragments: MeasuredFragment[];
        characters: MeasuredCharacter[];
    };
    measureParagraphDOM(paragraphs: Paragraph[], dom: HTMLElement): measureDOMResult;
    measure(paragraphs: Paragraph[], rootStyle: FullStyle, dom?: HTMLElement): measureDOMResult;
}

interface TextRenderOptions {
    view: HTMLCanvasElement;
    pixelRatio?: number;
    onContext?: (context: CanvasRenderingContext2D) => void;
}
interface MeasureResult {
    paragraphs: Paragraph[];
    lineBox: BoundingBox;
    rawGlyphBox: BoundingBox;
    glyphBox: BoundingBox;
    pathBox: BoundingBox;
    boundingBox: BoundingBox;
}
declare const textDefaultStyle: FullStyle;
interface TextEventMap {
    updateProperty: [
        key: string,
        newValue: unknown,
        oldValue: unknown,
        declaration: PropertyDeclaration
    ];
    update: [{
        text: Text$1;
    }];
    measure: [{
        text: Text$1;
        result: MeasureResult;
    }];
    render: [{
        text: Text$1;
        view: HTMLCanvasElement;
        pixelRatio: number;
    }];
}
declare class Text$1 extends EventEmitter<TextEventMap> implements ReactiveObject {
    debug: boolean;
    content: NormalizedText['content'];
    style?: NormalizedText['style'];
    effects?: NormalizedText['effects'];
    fill?: NormalizedText['fill'];
    outline?: NormalizedText['outline'];
    measureDom?: HTMLElement;
    fonts?: Fonts;
    needsUpdate: boolean;
    computedStyle: FullStyle;
    paragraphs: Paragraph[];
    lineBox: BoundingBox;
    rawGlyphBox: BoundingBox;
    glyphBox: BoundingBox;
    pathBox: BoundingBox;
    boundingBox: BoundingBox;
    measurer: Measurer;
    plugins: Map<string, TextPlugin>;
    pathSets: Path2DSet[];
    get fontSize(): number;
    get isVertical(): boolean;
    get characters(): Character[];
    constructor(options?: TextOptions);
    set(options?: TextOptions): void;
    onUpdateProperty(key: string, newValue: unknown, oldValue: unknown, declaration: PropertyDeclaration): void;
    use(plugin: TextPlugin): this;
    forEachCharacter(handle: (character: Character, ctx: {
        paragraphIndex: number;
        fragmentIndex: number;
        characterIndex: number;
    }) => void): this;
    load(): Promise<void>;
    updateParagraphs(): this;
    createDom(): HTMLElement;
    measure(dom?: HTMLElement | undefined): MeasureResult;
    getGlyphBox(): BoundingBox;
    updatePathBox(): this;
    updateBoundingBox(): this;
    requestUpdate(): this;
    update(dom?: HTMLElement | undefined): this;
    render(options: TextRenderOptions): void;
    toString(): string;
}

export { Character as C, Fragment as F, Paragraph as P, Text$1 as T, Measurer as g, textDefaultStyle as t };
export type { MeasureResult as M, TextPlugin as a, TextOptions as b, TextRenderOptions as c, MeasuredParagraph as d, MeasuredFragment as e, MeasuredCharacter as f, TextEventMap as h, measureDOMResult as m };
