modern-text
Version:
Measure and render text in a way that describes the DOM.
245 lines (237 loc) • 7.62 kB
TypeScript
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 };