UNPKG

@lightningtv/renderer

Version:
371 lines (370 loc) 11.2 kB
import type { EventEmitter } from '../../../common/EventEmitter.js'; import type { CoreTextNode } from '../../CoreTextNode.js'; import type { Stage } from '../../Stage.js'; import type { TrFontFace, TrFontFaceDescriptors } from '../font-face-types/TrFontFace.js'; import type { TextBaseline, TextVerticalAlign } from './LightningTextTextureRenderer.js'; /** * Augmentable map of text renderer type IDs to text renderer types. * * @example * ```ts * declare module './TextRenderer' { * interface TextRendererMap { * canvas: CanvasTextRenderer; * } * } * ``` */ export interface TextRendererMap { } export interface TextRendererState { props: TrProps; /** * Whether or not the text renderer state is scheduled to be updated * via queueMicrotask. */ updateScheduled: boolean; status: 'initialState' | 'loading' | 'loaded' | 'failed' | 'destroyed'; /** * Event emitter for the text renderer */ emitter: EventEmitter; /** * Force a full layout pass for the calculation of the * total dimensions of the text */ forceFullLayoutCalc: boolean; textW: number | undefined; textH: number | undefined; isRenderable: boolean; debugData: { updateCount: number; layoutCount: number; drawCount: number; lastLayoutNumCharacters: number; layoutSum: number; drawSum: number; bufferSize: number; }; } export interface TextRendererDebugProps { showRenderWindow: boolean; showVisibleRect: boolean; showElementRect: boolean; disableScissor: boolean; printLayoutTime: boolean; } /** * Text renderer properties that are used in resolving appropriate font faces * * @remarks * Extended by {@link TrProps} */ export interface TrFontProps { /** * Font Family * * @internalRemarks * `fontFamily` is defined currently as single string, but in the future we may want to * support multiple font family fallbacks, as this is supported by CSS / Canvas2d. We can * do this in a backwards compatible way by unioning an array of strings to the * `fontFamily` property. */ fontFamily: string; /** * Font Weight * * @remarks * The font weight to use when looking up the font face. This can be a numeric * value between 1 and 1000, or one of the following strings: * - `'normal'` - same as 400 * - `'bold'` - same as 700 * - `'bolder'` - (Not yet properly supported) */ fontWeight: TrFontFaceDescriptors['weight'] | 'bolder' | 'lighter'; /** * Font Style * * @remarks * The font style to use when looking up the font face. This can be one of the * following strings: * - `'normal'` * - `'italic'` * - `'oblique'` */ fontStyle: TrFontFaceDescriptors['style']; /** * Font Stretch * * @remarks * The font stretch to use when looking up the font face. This can be one of the * following strings: * - `'normal'` * - `'ultra-condensed'` * - `'extra-condensed'` * - `'condensed'` * - `'semi-condensed'` * - `'semi-expanded'` * - `'expanded'` * - `'extra-expanded'` * - `'ultra-expanded'` * * @default 'normal' */ fontStretch: TrFontFaceDescriptors['stretch']; /** * Font Size * * @remarks * The font size to use when looking up the font face. * * The font size is specified in pixels and is the height of the font's * em-square. The em-square is essentially the height of the capital letters * for the font. The actual height of the text can be larger than the * specified font size, as the font may have ascenders and descenders that * extend beyond the em-square. * * @default 16 */ fontSize: number; } export interface TrProps extends TrFontProps { /** * Text to display * * @default '' */ text: string; /** * Text alignment * * @remarks * Alignment of the text relative to it's contained bounds. For best results, * use {@link contain} mode `'width'` or `'both'` and a set an explicit * {@link width} for the text to be aligned within. * * @default 'left' */ textAlign: 'left' | 'center' | 'right'; /** * Color of text * * @remarks * The color value is a number in the format 0xRRGGBBAA, where RR is the red * component, GG is the green component, BB is the blue component, and AA is * the alpha component. * * @default 0xffffffff (opaque white) */ color: number; x: number; y: number; /** * Contain mode for text * * @remarks * The contain mode determines how the text is contained within the bounds * of the Text Node. The default value is `'none'`, which means that the * Text Renderer will not constrain the text in any way. `'width'` mode will * constrain the text to the set width wrapping lines as necessary, and * `'both'` mode will constrain the text to both the set width and height * wrapping lines and truncating text as necessary. * * ## Text Auto-size Behavior * Depending on the set contain mode, after the text 'loaded' event is emitted, * the text node may have either its {@link width} and {@link height} updated * to match the rendered size of the text. * * When contain mode is 'none', both the {@link width} and {@link height} * properties are updated. * * When contain mode is 'width', only the {@link height} property is updated. * * When contain mode is 'both', neither property is updated. * * @default 'none' */ contain: 'none' | 'width' | 'both'; width: number; height: number; /** * Whether or not the text is scrollable * * @remarks * If `scrollable` is `true`, the text can be scrolled vertically within the * bounds of the Text Node. You can set the scroll position using the * {@link scrollY} property. * * @default false */ scrollable: boolean; /** * Vertical scroll position for text * * @remarks * The vertical scroll position of the text. This property is only used if * {@link scrollable} is `true`. * * @default 0 */ scrollY: number; /** * Vertical offset for text * * @remarks * The vertical offset of the text. This property is only used if * {@link scrollable} is `true`. * * @default 0 */ offsetY: number; /** * Letter spacing for text (in pixels) * * @remarks * This property sets additional (or reduced, if value is negative) spacing * between characters in the text. * * @default 0 */ letterSpacing: number; /** * Line height for text (in pixels) * * @remarks * This property sets the height of each line. If set to `undefined`, the * line height will be calculated based on the font and font size to be the * minimal height required to completely contain a line of text. * * See: https://github.com/lightning-js/renderer/issues/170 * * @default `undefined` */ lineHeight: number | undefined; /** * Max lines for text * * @remarks * This property sets max number of lines of a text paragraph. * Not yet implemented in the SDF renderer. * * @default 0 */ maxLines: number; /** * Baseline for text * * @remarks * This property sets the text baseline used when drawing text. * Not yet implemented in the SDF renderer. * * @default alphabetic */ textBaseline: TextBaseline; /** * Vertical Align for text when lineHeight > fontSize * * @remarks * This property sets the vertical align of the text. * Not yet implemented in the SDF renderer. * * @default middle */ verticalAlign: TextVerticalAlign; /** * Overflow Suffix for text * * @remarks * The suffix to be added when text is cropped due to overflow. * Not yet implemented in the SDF renderer. * * @default "..." */ overflowSuffix: string; zIndex: number; debug: Partial<TextRendererDebugProps>; } export type TrPropSetters<StateT = TextRendererState> = { [key in keyof TrProps]: (state: StateT, value: TrProps[key]) => void; }; /** * Event handler for when text is loaded * * @remarks * Emitted by state.emitter */ export type TrLoadedEventHandler = (target: any) => void; /** * Event handler for when text failed to load * * @remarks * Emitted by state.emitter */ export type TrFailedEventHandler = (target: any, error: Error) => void; export declare abstract class TextRenderer<StateT extends TextRendererState = TextRendererState> { protected stage: Stage; readonly set: Readonly<TrPropSetters<StateT>>; abstract type: 'canvas' | 'sdf'; constructor(stage: Stage); setStatus(state: StateT, status: StateT['status'], error?: Error): void; /** * Allows the CoreTextNode to communicate changes to the isRenderable state of * the itself. * * @param state * @param renderable */ setIsRenderable(state: StateT, renderable: boolean): void; /** * Called by constructor to get a map of property setter functions for this renderer. */ abstract getPropertySetters(): Partial<TrPropSetters<StateT>>; /** * Given text renderer properties (particularly the specific properties related to font selection) * returns whether or not the renderer can render it. * * @param props */ abstract canRenderFont(props: TrFontProps): boolean; /** * Called by the TrFontManager to find out if a newly added font face is supported * by this renderer. * * @param fontFace */ abstract isFontFaceSupported(fontFace: TrFontFace): boolean; /** * Called by the TrFontManager to add a font face to the renderer's font registry. * * @remarks * This method MUST ONLY be called for a fontFace that previously passed the * {@link isFontFaceSupported} check. * * @param fontFace */ abstract addFontFace(fontFace: TrFontFace): void; abstract createState(props: TrProps, node: CoreTextNode): StateT; /** * Destroy/Clean up the state object * * @remarks * Opposite of createState(). Frees any event listeners / resources held by * the state that may not reliably get garbage collected. * * @param state */ destroyState(state: StateT): void; /** * Schedule a state update via queueMicrotask * * @remarks * This method is used to schedule a state update via queueMicrotask. This * method should be called whenever a state update is needed, and it will * ensure that the state is only updated once per microtask. * @param state * @returns */ scheduleUpdateState(state: StateT): void; abstract updateState(state: StateT): void; renderQuads?(node: CoreTextNode): void; }