chat-layout 1.2.0-2 → 1.2.0-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#children","#inner","clampToConstraints","#top","#bottom","#left","#right","#writeLayout","readLruValue","writeLruValue","measurePreparedMinContentWidth","readLruValue","writeLruValue","measureInlinePreparedMinContentWidth","getFirstLineRange","walkLines","collectVisibleLines","measurePreparedMinContentWidth","#ctx","#lastWidth","#cache","#layoutCache","#textLayoutCache","#clearAllCaches","#syncCachesToViewportWidth","#items","clamp","#handleListStateChange","#cancelJumpAnimation","#jumpAnimation","#controlledState","#prepareReplacementAnimations","#readReplacementAnimation","#sampleReplacementHeight","#sampleLayerAlpha","#drawReplacementLayers","#nextReplacementLayerKey","#replacementAnimations","#isLayerComplete","#handleReplace","#createReplacementLayer","clamp","clamp","#resolveVisibleWindow","#resolveVisibleWindow"],"sources":["../src/internal/node-registry.ts","../src/utils.ts","../src/nodes/base.ts","../src/layout.ts","../src/nodes/shared.ts","../src/nodes/box.ts","../src/nodes/flex.ts","../src/nodes/place.ts","../src/nodes/shrinkwrap.ts","../src/text/core.ts","../src/text/inline-engine.ts","../src/text/plain-core.ts","../src/text/plain.ts","../src/text/rich.ts","../src/text/justify.ts","../src/nodes/text.ts","../src/renderer/base.ts","../src/renderer/weak-listeners.ts","../src/renderer/list-state.ts","../src/renderer/memo.ts","../src/renderer/virtualized/base.ts","../src/renderer/virtualized/solver.ts","../src/renderer/virtualized/chat.ts","../src/renderer/virtualized/timeline.ts"],"sourcesContent":["import type { Node } from \"../types\";\n\nconst registry = new WeakMap<Node<any>, Node<any>>();\nconst revisions = new WeakMap<Node<any>, number>();\n\nfunction getOwnershipError(): Error {\n return new Error(\"A node can only be attached to one parent. Shared nodes are not supported.\");\n}\n\nfunction getDetachOwnershipError(): Error {\n return new Error(\"Cannot detach or replace a node from a parent that does not own it.\");\n}\n\nfunction bumpRevision(node: Node<any>): void {\n revisions.set(node, (revisions.get(node) ?? 0) + 1);\n}\n\nexport function getNodeRevision<C extends CanvasRenderingContext2D>(node: Node<C>): number {\n return revisions.get(node) ?? 0;\n}\n\nexport function attachNodeToParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n if (registry.has(node)) {\n throw getOwnershipError();\n }\n registry.set(node, parent);\n bumpRevision(parent);\n}\n\nexport function attachNodesToParent<C extends CanvasRenderingContext2D>(\n nodes: Iterable<Node<C>>,\n parent: Node<C>,\n): void {\n for (const node of nodes) {\n attachNodeToParent(node, parent);\n }\n}\n\nexport function detachNodeFromParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent?: Node<C>,\n): void {\n const currentParent = registry.get(node);\n if (currentParent == null) {\n return;\n }\n if (parent != null && currentParent !== parent) {\n throw getDetachOwnershipError();\n }\n registry.delete(node);\n bumpRevision(currentParent);\n}\n\nexport function replaceNodeParent<C extends CanvasRenderingContext2D>(\n previousNode: Node<C>,\n nextNode: Node<C>,\n parent: Node<C>,\n): void {\n if (previousNode === nextNode) {\n return;\n }\n const currentParent = registry.get(previousNode);\n if (currentParent !== parent) {\n throw getDetachOwnershipError();\n }\n if (registry.has(nextNode)) {\n throw getOwnershipError();\n }\n registry.delete(previousNode);\n registry.set(nextNode, parent);\n bumpRevision(parent);\n}\n\nexport function replaceNodesParent<C extends CanvasRenderingContext2D>(\n previousNodes: Iterable<Node<C>>,\n nextNodes: Iterable<Node<C>>,\n parent: Node<C>,\n): void {\n const previousSnapshot = Array.from(previousNodes);\n const nextSnapshot = Array.from(nextNodes);\n if (\n previousSnapshot.length === nextSnapshot.length &&\n previousSnapshot.every((node, index) => node === nextSnapshot[index])\n ) {\n return;\n }\n\n const previousSet = new Set(previousSnapshot);\n const nextSet = new Set<Node<C>>();\n for (const node of nextSnapshot) {\n if (nextSet.has(node)) {\n throw getOwnershipError();\n }\n nextSet.add(node);\n const currentParent = registry.get(node);\n if (currentParent != null && currentParent !== parent) {\n throw getOwnershipError();\n }\n }\n\n for (const node of previousSnapshot) {\n if (!nextSet.has(node)) {\n const currentParent = registry.get(node);\n if (currentParent !== parent) {\n throw getDetachOwnershipError();\n }\n registry.delete(node);\n }\n }\n\n for (const node of nextSnapshot) {\n if (!previousSet.has(node)) {\n registry.set(node, parent);\n }\n }\n\n bumpRevision(parent);\n}\n\nexport function forEachNodeAncestor<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n visitor: (ancestor: Node<C>) => void,\n): void {\n let current: Node<C> | undefined = node;\n while ((current = registry.get(current))) {\n visitor(current);\n }\n}\n\nexport function registerNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n attachNodeToParent(node, parent);\n}\n\nexport function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>, parent?: Node<C>): void {\n detachNodeFromParent(node, parent);\n}\n\nexport function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined {\n return registry.get(node);\n}\n","export function shallow<T extends object>(object: T): T {\n return Object.create(object) as T;\n}\n","import { attachNodeToParent, replaceNodeParent, replaceNodesParent } from \"../internal/node-registry\";\nimport type { Box, Context, HitTest, LayoutConstraints, Node } from \"../types\";\nimport { shallow } from \"../utils\";\n\nexport function withNodeConstraints<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n constraints: LayoutConstraints | undefined,\n): Context<C> {\n if (constraints === ctx.constraints) {\n return ctx;\n }\n const next = shallow(ctx);\n next.constraints = constraints;\n return next;\n}\n\nexport function measureNodeMinContent<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n node: Node<C>,\n constraints: LayoutConstraints | undefined = ctx.constraints,\n): Box {\n const nextCtx = withNodeConstraints(ctx, constraints);\n if (node.measureMinContent != null) {\n return node.measureMinContent(nextCtx);\n }\n return node.measure(nextCtx);\n}\n\n/**\n * A node that owns an ordered list of child nodes.\n */\nexport abstract class Group<C extends CanvasRenderingContext2D> implements Node<C> {\n #children: Node<C>[];\n\n /**\n * @param children Initial child nodes, in layout order.\n */\n constructor(children: Node<C>[]) {\n this.#children = [...children];\n replaceNodesParent([], this.#children, this);\n }\n\n /** Child nodes managed by this group. */\n get children(): readonly Node<C>[] {\n return this.#children;\n }\n\n /**\n * Replaces the full child list while updating parent links.\n */\n replaceChildren(nextChildren: Node<C>[]): void {\n const nextSnapshot = [...nextChildren];\n replaceNodesParent(this.#children, nextSnapshot, this);\n this.#children = nextSnapshot;\n }\n\n abstract measure(ctx: Context<C>): Box;\n abstract draw(ctx: Context<C>, x: number, y: number): boolean;\n abstract hittest(ctx: Context<C>, test: HitTest): boolean;\n}\n\n/**\n * A node that forwards layout and drawing to a single inner node.\n */\nexport class Wrapper<C extends CanvasRenderingContext2D> implements Node<C> {\n #inner: Node<C>;\n\n /**\n * @param inner Wrapped child node.\n */\n constructor(inner: Node<C>) {\n this.#inner = inner;\n attachNodeToParent(this.#inner, this);\n }\n\n /** The wrapped child node. */\n get inner(): Node<C> {\n return this.#inner;\n }\n\n /** Replaces the wrapped child node. */\n set inner(newNode: Node<C>) {\n if (newNode === this.#inner) {\n return;\n }\n replaceNodeParent(this.#inner, newNode, this);\n this.#inner = newNode;\n }\n\n measure(ctx: Context<C>): Box {\n return this.inner.measure(ctx);\n }\n\n measureMinContent(ctx: Context<C>): Box {\n return measureNodeMinContent(ctx, this.inner);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return this.inner.draw(ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return this.inner.hittest(ctx, test);\n }\n}\n","import type { Box, ChildLayoutResult, FlexLayoutResult, LayoutConstraints, LayoutRect } from \"./types\";\n\n/**\n * 创建 LayoutRect 的辅助函数\n */\nexport function createRect(x: number, y: number, width: number, height: number): LayoutRect {\n return { x, y, width, height };\n}\n\n/**\n * 合并多个 rect 得到包含所有 rect 的最小外接矩形\n */\nexport function mergeRects(rects: LayoutRect[]): LayoutRect {\n if (rects.length === 0) {\n return createRect(0, 0, 0, 0);\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const rect of rects) {\n minX = Math.min(minX, rect.x);\n minY = Math.min(minY, rect.y);\n maxX = Math.max(maxX, rect.x + rect.width);\n maxY = Math.max(maxY, rect.y + rect.height);\n }\n\n return createRect(minX, minY, maxX - minX, maxY - minY);\n}\n\n/**\n * 从子节点布局结果计算容器的 contentBox\n */\nexport function computeContentBox<C extends CanvasRenderingContext2D>(\n children: ChildLayoutResult<C>[],\n): LayoutRect {\n return mergeRects(children.map((child) => child.contentBox));\n}\n\n/**\n * 根据约束和实际内容计算最终的 containerBox\n */\nexport function computeContainerBox(\n contentBox: LayoutRect,\n constraints?: LayoutConstraints,\n): LayoutRect {\n let width = contentBox.width;\n let height = contentBox.height;\n\n if (constraints?.minWidth != null) {\n width = Math.max(width, constraints.minWidth);\n }\n if (constraints?.maxWidth != null) {\n width = Math.min(width, constraints.maxWidth);\n }\n if (constraints?.minHeight != null) {\n height = Math.max(height, constraints.minHeight);\n }\n if (constraints?.maxHeight != null) {\n height = Math.min(height, constraints.maxHeight);\n }\n\n return createRect(contentBox.x, contentBox.y, width, height);\n}\n\n/**\n * 将 Box 转换为 LayoutRect(位置为 0,0)\n */\nexport function boxToRect(box: Box): LayoutRect {\n return createRect(0, 0, box.width, box.height);\n}\n\n/**\n * 检查点是否在 rect 内\n */\nexport function pointInRect(x: number, y: number, rect: LayoutRect): boolean {\n return x >= rect.x && x < rect.x + rect.width && y >= rect.y && y < rect.y + rect.height;\n}\n\n/**\n * 平移 rect 的位置\n */\nexport function offsetRect(rect: LayoutRect, dx: number, dy: number): LayoutRect {\n return createRect(rect.x + dx, rect.y + dy, rect.width, rect.height);\n}\n\n/**\n * 读取单子节点布局结果中的唯一 child。\n */\nexport function getSingleChildLayout<C extends CanvasRenderingContext2D>(\n layout: FlexLayoutResult<C>,\n): ChildLayoutResult<C> | undefined {\n return layout.children[0];\n}\n\n/**\n * 在布局结果中按指定盒模型查找命中的 child,并返回局部坐标。\n */\nexport function findChildAtPoint<C extends CanvasRenderingContext2D>(\n children: ChildLayoutResult<C>[],\n x: number,\n y: number,\n box: \"rect\" | \"contentBox\" = \"contentBox\",\n):\n | {\n child: ChildLayoutResult<C>;\n localX: number;\n localY: number;\n }\n | undefined {\n for (let i = children.length - 1; i >= 0; i -= 1) {\n const child = children[i]!;\n const target = box === \"rect\" ? child.rect : child.contentBox;\n if (!pointInRect(x, y, target)) {\n continue;\n }\n return {\n child,\n localX: x - target.x,\n localY: y - target.y,\n };\n }\n return undefined;\n}\n","import { findChildAtPoint } from \"../layout\";\nimport type { Context, FlexLayoutResult, HitTest, LayoutConstraints, Node } from \"../types\";\nimport { shallow } from \"../utils\";\n\ntype LayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getLayoutResult(node: Node<C>, constraints?: LayoutConstraints): FlexLayoutResult<C> | undefined;\n setLayoutResult(node: Node<C>, result: FlexLayoutResult<C>, constraints?: LayoutConstraints): void;\n};\n\ntype LayoutContext<C extends CanvasRenderingContext2D> = Context<C> & LayoutCacheAccess<C>;\n\nexport function withConstraints<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n constraints: LayoutConstraints | undefined,\n): Context<C> {\n const next = shallow(ctx);\n next.constraints = constraints;\n return next;\n}\n\nfunction getLayoutContext<C extends CanvasRenderingContext2D>(ctx: Context<C>): LayoutContext<C> {\n return ctx as LayoutContext<C>;\n}\n\nexport function readLayoutResult<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n): FlexLayoutResult<C> | undefined {\n return getLayoutContext(ctx).getLayoutResult(node, ctx.constraints);\n}\n\nexport function writeLayoutResult<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n result: FlexLayoutResult<C>,\n): void {\n getLayoutContext(ctx).setLayoutResult(node, result, ctx.constraints);\n}\n\nfunction ensureLayoutResult<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n): FlexLayoutResult<C> | undefined {\n return readLayoutResult(node, ctx);\n}\n\nexport function drawLayoutChildren<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n x: number,\n y: number,\n): boolean {\n const layoutResult = ensureLayoutResult(node, ctx);\n if (!layoutResult) {\n return false;\n }\n\n let result = false;\n for (const childResult of layoutResult.children) {\n const childDrawn = childResult.node.draw(\n withConstraints(ctx, childResult.constraints),\n x + childResult.contentBox.x,\n y + childResult.contentBox.y,\n );\n result = childDrawn || result;\n }\n return result;\n}\n\nexport function hittestLayoutChildren<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n test: HitTest,\n box: \"rect\" | \"contentBox\" = \"contentBox\",\n): boolean {\n const layoutResult = ensureLayoutResult(node, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, box);\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(\n withConstraints(ctx, hit.child.constraints),\n {\n ...test,\n x: hit.localX,\n y: hit.localY,\n },\n );\n}\n","import { createRect, findChildAtPoint, getSingleChildLayout } from \"../layout\";\nimport type { Box, Context, HitTest, Node } from \"../types\";\nimport { measureNodeMinContent } from \"./base\";\nimport { Wrapper } from \"./base\";\nimport { readLayoutResult, withConstraints, writeLayoutResult } from \"./shared\";\n\nfunction clampToConstraints(value: number, min?: number, max?: number): number {\n let result = value;\n if (min != null) {\n result = Math.max(result, min);\n }\n if (max != null) {\n result = Math.min(result, max);\n }\n return result;\n}\n\nfunction shrinkConstraint(value: number | undefined, padding: number): number | undefined {\n if (value == null) {\n return undefined;\n }\n return Math.max(0, value - padding);\n}\n\n/**\n * Adds padding around a single child node.\n */\nexport class PaddingBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n /**\n * @param inner Wrapped child node.\n * @param padding Padding in CSS pixels on each side.\n */\n constructor(\n inner: Node<C>,\n readonly padding: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n } = {},\n ) {\n super(inner);\n }\n\n get #top(): number {\n return this.padding.top ?? 0;\n }\n\n get #bottom(): number {\n return this.padding.bottom ?? 0;\n }\n\n get #left(): number {\n return this.padding.left ?? 0;\n }\n\n get #right(): number {\n return this.padding.right ?? 0;\n }\n\n measure(ctx: Context<C>): Box {\n const paddingLeft = this.#left;\n const paddingRight = this.#right;\n const paddingTop = this.#top;\n const paddingBottom = this.#bottom;\n const horizontalPadding = paddingLeft + paddingRight;\n const verticalPadding = paddingTop + paddingBottom;\n const childConstraints = ctx.constraints\n ? {\n ...ctx.constraints,\n minWidth: shrinkConstraint(ctx.constraints.minWidth, horizontalPadding),\n maxWidth: shrinkConstraint(ctx.constraints.maxWidth, horizontalPadding),\n minHeight: shrinkConstraint(ctx.constraints.minHeight, verticalPadding),\n maxHeight: shrinkConstraint(ctx.constraints.maxHeight, verticalPadding),\n }\n : undefined;\n const { width, height } = ctx.measureNode(this.inner, childConstraints);\n const containerBox = createRect(\n 0,\n 0,\n clampToConstraints(width + horizontalPadding, ctx.constraints?.minWidth, ctx.constraints?.maxWidth),\n clampToConstraints(height + verticalPadding, ctx.constraints?.minHeight, ctx.constraints?.maxHeight),\n );\n const childRect = createRect(paddingLeft, paddingTop, width, height);\n writeLayoutResult(this, ctx, {\n containerBox,\n contentBox: childRect,\n children: [\n {\n node: this.inner,\n rect: childRect,\n contentBox: childRect,\n constraints: childConstraints,\n },\n ],\n constraints: ctx.constraints,\n });\n return {\n width: containerBox.width,\n height: containerBox.height,\n };\n }\n\n measureMinContent(ctx: Context<C>): Box {\n const paddingLeft = this.#left;\n const paddingRight = this.#right;\n const paddingTop = this.#top;\n const paddingBottom = this.#bottom;\n const horizontalPadding = paddingLeft + paddingRight;\n const verticalPadding = paddingTop + paddingBottom;\n const childConstraints = ctx.constraints\n ? {\n ...ctx.constraints,\n minWidth: shrinkConstraint(ctx.constraints.minWidth, horizontalPadding),\n maxWidth: shrinkConstraint(ctx.constraints.maxWidth, horizontalPadding),\n minHeight: shrinkConstraint(ctx.constraints.minHeight, verticalPadding),\n maxHeight: shrinkConstraint(ctx.constraints.maxHeight, verticalPadding),\n }\n : undefined;\n const { width, height } = measureNodeMinContent(ctx, this.inner, childConstraints);\n return {\n width: width + horizontalPadding,\n height: height + verticalPadding,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return this.inner.draw(ctx, x + this.#left, y + this.#top);\n }\n\n const childResult = getSingleChildLayout(layoutResult);\n if (!childResult) {\n return false;\n }\n\n return childResult.node.draw(\n withConstraints(ctx, childResult.constraints),\n x + childResult.rect.x,\n y + childResult.rect.y,\n );\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, \"rect\");\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(\n withConstraints(ctx, hit.child.constraints),\n {\n ...test,\n x: hit.localX,\n y: hit.localY,\n },\n );\n }\n}\n\n/**\n * A leaf node with a fixed size and no drawing behavior.\n */\nexport class Fixed<C extends CanvasRenderingContext2D> implements Node<C> {\n /**\n * @param width Fixed width in CSS pixels.\n * @param height Fixed height in CSS pixels.\n */\n constructor(\n readonly width: number,\n readonly height: number,\n ) {}\n\n measure(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n measureMinContent(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n draw(_ctx: Context<C>, _x: number, _y: number): boolean {\n return false;\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n","import { computeContentBox, createRect } from \"../layout\";\nimport type {\n Axis,\n Box,\n ChildLayoutResult,\n Context,\n CrossAxisAlignment,\n FlexContainerOptions,\n FlexItemOptions,\n HitTest,\n LayoutConstraints,\n Node,\n} from \"../types\";\nimport { Group, measureNodeMinContent, Wrapper } from \"./base\";\nimport { drawLayoutChildren, hittestLayoutChildren, writeLayoutResult } from \"./shared\";\n\nfunction getMainSize(axis: Axis, box: Box): number {\n return axis === \"row\" ? box.width : box.height;\n}\n\nfunction getCrossSize(axis: Axis, box: Box): number {\n return axis === \"row\" ? box.height : box.width;\n}\n\nfunction getMinMain(axis: Axis, constraints?: LayoutConstraints): number | undefined {\n return axis === \"row\" ? constraints?.minWidth : constraints?.minHeight;\n}\n\nfunction getMaxMain(axis: Axis, constraints?: LayoutConstraints): number | undefined {\n return axis === \"row\" ? constraints?.maxWidth : constraints?.maxHeight;\n}\n\nfunction getMinCross(axis: Axis, constraints?: LayoutConstraints): number | undefined {\n return axis === \"row\" ? constraints?.minHeight : constraints?.minWidth;\n}\n\nfunction getMaxCross(axis: Axis, constraints?: LayoutConstraints): number | undefined {\n return axis === \"row\" ? constraints?.maxHeight : constraints?.maxWidth;\n}\n\nfunction createAxisConstraints(\n axis: Axis,\n constraints: LayoutConstraints | undefined,\n main: { min?: number; max?: number },\n cross: { min?: number; max?: number } = {},\n): LayoutConstraints | undefined {\n if (\n constraints == null &&\n main.min == null &&\n main.max == null &&\n cross.min == null &&\n cross.max == null\n ) {\n return undefined;\n }\n\n const next: LayoutConstraints = {\n ...constraints,\n };\n if (axis === \"row\") {\n next.minWidth = main.min;\n next.maxWidth = main.max;\n next.minHeight = cross.min;\n next.maxHeight = cross.max;\n } else {\n next.minHeight = main.min;\n next.maxHeight = main.max;\n next.minWidth = cross.min;\n next.maxWidth = cross.max;\n }\n return next;\n}\n\nfunction clampToConstraints(value: number, min?: number, max?: number): number {\n let result = value;\n if (min != null) {\n result = Math.max(result, min);\n }\n if (max != null) {\n result = Math.min(result, max);\n }\n return result;\n}\n\nfunction constraintsEqual(left: LayoutConstraints | undefined, right: LayoutConstraints | undefined): boolean {\n if (left === right) {\n return true;\n }\n if (left == null || right == null) {\n return left == null && right == null;\n }\n return left.minWidth === right.minWidth\n && left.maxWidth === right.maxWidth\n && left.minHeight === right.minHeight\n && left.maxHeight === right.maxHeight;\n}\n\nfunction getCrossAlignment(alignSelf: CrossAxisAlignment | \"auto\" | undefined, alignItems: CrossAxisAlignment): CrossAxisAlignment {\n if (alignSelf == null || alignSelf === \"auto\") {\n return alignItems;\n }\n return alignSelf;\n}\n\nfunction getJustifySpacing(\n justifyContent: NonNullable<FlexContainerOptions[\"justifyContent\"]>,\n freeSpace: number,\n itemCount: number,\n gap: number,\n): { leading: number; between: number } {\n switch (justifyContent) {\n case \"center\":\n return { leading: freeSpace / 2, between: gap };\n case \"end\":\n return { leading: freeSpace, between: gap };\n case \"space-between\":\n return {\n leading: 0,\n between: itemCount > 1 ? gap + freeSpace / (itemCount - 1) : gap,\n };\n case \"space-around\":\n return {\n leading: itemCount > 0 ? freeSpace / itemCount / 2 : 0,\n between: itemCount > 0 ? gap + freeSpace / itemCount : gap,\n };\n case \"space-evenly\":\n return {\n leading: itemCount > 0 ? freeSpace / (itemCount + 1) : 0,\n between: itemCount > 0 ? gap + freeSpace / (itemCount + 1) : gap,\n };\n case \"start\":\n default:\n return { leading: 0, between: gap };\n }\n}\n\nfunction getCrossOffset(align: CrossAxisAlignment, frameCross: number, contentCross: number): number {\n switch (align) {\n case \"center\":\n return (frameCross - contentCross) / 2;\n case \"end\":\n return frameCross - contentCross;\n case \"stretch\":\n case \"start\":\n default:\n return 0;\n }\n}\n\nfunction createRectFromAxis(axis: Axis, main: number, cross: number, mainSize: number, crossSize: number) {\n return axis === \"row\"\n ? createRect(main, cross, mainSize, crossSize)\n : createRect(cross, main, crossSize, mainSize);\n}\n\nconst SHRINK_EPSILON = 1e-6;\n\ntype FlexMeasurement<C extends CanvasRenderingContext2D> = {\n child: Node<C>;\n item: FlexItemOptions;\n basisMeasured: Box;\n measured: Box;\n basisConstraints?: LayoutConstraints;\n initialConstraints?: LayoutConstraints;\n finalConstraints?: LayoutConstraints;\n allocatedMain?: number;\n grow: number;\n shrink: number;\n effectiveAlign: CrossAxisAlignment;\n stretch: boolean;\n basis: number;\n minContentMain: number;\n finalMain: number;\n frozen: boolean;\n frameMain: number;\n frameCross: number;\n};\n\ntype MeasuredLayout<C extends CanvasRenderingContext2D> = {\n box: Box;\n layout: {\n containerBox: ChildLayoutResult<C>[\"rect\"];\n contentBox: ChildLayoutResult<C>[\"contentBox\"];\n children: ChildLayoutResult<C>[];\n constraints?: LayoutConstraints;\n };\n};\n\nfunction readFlexItemOptions<C extends CanvasRenderingContext2D>(child: Node<C>): FlexItemOptions {\n if (child instanceof FlexItem) {\n return child.item;\n }\n return {};\n}\n\nexport function computeFlexLayout<C extends CanvasRenderingContext2D>(\n children: readonly Node<C>[],\n options: FlexContainerOptions,\n constraints: LayoutConstraints | undefined,\n measureChild: (node: Node<C>, constraints?: LayoutConstraints) => Box,\n measureChildMinContent: (node: Node<C>, constraints?: LayoutConstraints) => Box,\n): MeasuredLayout<C> {\n const axis = options.direction ?? \"row\";\n const gap = options.gap ?? 0;\n const justifyContent = options.justifyContent ?? \"start\";\n const alignItems = options.alignItems ?? \"start\";\n const reverse = options.reverse ?? false;\n const mainAxisSize = options.mainAxisSize ?? \"fill\";\n const orderedChildren = reverse ? [...children].reverse() : children;\n const maxMain = getMaxMain(axis, constraints);\n const minMain = getMinMain(axis, constraints);\n const maxCross = getMaxCross(axis, constraints);\n const minCross = getMinCross(axis, constraints);\n const gapTotal = orderedChildren.length > 1 ? gap * (orderedChildren.length - 1) : 0;\n const finiteMain = maxMain != null;\n const finiteCross = maxCross != null;\n const availableMain = finiteMain ? Math.max(0, maxMain - gapTotal) : undefined;\n let totalGrow = 0;\n let totalBasis = 0;\n let nonGrowBasis = 0;\n const measurements = new Map<Node<C>, FlexMeasurement<C>>();\n const basisConstraints = createAxisConstraints(\n axis,\n constraints,\n {\n min: undefined,\n max: undefined,\n },\n {\n min: undefined,\n max: maxCross,\n },\n );\n\n for (const child of orderedChildren) {\n const item = readFlexItemOptions(child);\n const grow = item.grow ?? 0;\n const shrink = item.shrink ?? 0;\n totalGrow += grow;\n const effectiveAlign = getCrossAlignment(item.alignSelf, alignItems);\n const stretch = effectiveAlign === \"stretch\";\n const basisMeasured = measureChild(child, basisConstraints);\n const basis = getMainSize(axis, basisMeasured);\n\n totalBasis += basis;\n if (grow <= 0) {\n nonGrowBasis += basis;\n }\n\n measurements.set(child, {\n child,\n item,\n basisMeasured,\n measured: basisMeasured,\n basisConstraints,\n initialConstraints: basisConstraints,\n finalConstraints: basisConstraints,\n allocatedMain: undefined,\n grow,\n shrink,\n effectiveAlign,\n stretch,\n basis,\n minContentMain: basis,\n finalMain: basis,\n frozen: false,\n frameMain: basis,\n frameCross: getCrossSize(axis, basisMeasured),\n });\n }\n\n const entersShrinkPath = finiteMain && availableMain != null && totalBasis - availableMain > SHRINK_EPSILON;\n\n if (entersShrinkPath) {\n const totalDeficit = totalBasis - availableMain!;\n let remainingDeficit = totalDeficit;\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n const minContentMeasured = measureChildMinContent(child, measurement.basisConstraints);\n measurement.minContentMain = Math.min(measurement.basis, getMainSize(axis, minContentMeasured));\n measurement.finalMain = measurement.basis;\n measurement.frozen = measurement.shrink <= 0 || measurement.basis - measurement.minContentMain <= SHRINK_EPSILON;\n }\n\n while (remainingDeficit > SHRINK_EPSILON) {\n const active = orderedChildren\n .map((child) => measurements.get(child)!)\n .filter((measurement) => !measurement.frozen && measurement.shrink > 0);\n const totalScaled = active.reduce((sum, measurement) => sum + measurement.shrink * measurement.basis, 0);\n\n if (active.length === 0 || totalScaled <= SHRINK_EPSILON) {\n break;\n }\n\n let frozeAny = false;\n for (const measurement of active) {\n const tentative = measurement.basis - remainingDeficit * ((measurement.shrink * measurement.basis) / totalScaled);\n if (tentative <= measurement.minContentMain + SHRINK_EPSILON) {\n measurement.finalMain = measurement.minContentMain;\n measurement.frozen = true;\n frozeAny = true;\n } else {\n measurement.finalMain = tentative;\n }\n }\n\n if (!frozeAny) {\n remainingDeficit = 0;\n break;\n }\n\n let absorbedDeficit = 0;\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (measurement.frozen) {\n absorbedDeficit += Math.max(0, measurement.basis - measurement.finalMain);\n }\n }\n remainingDeficit = Math.max(0, totalDeficit - absorbedDeficit);\n }\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n measurement.measured = measurement.basisMeasured;\n measurement.initialConstraints = measurement.basisConstraints;\n measurement.finalConstraints = createAxisConstraints(\n axis,\n constraints,\n {\n min: undefined,\n max: measurement.finalMain,\n },\n {\n min: undefined,\n max: maxCross,\n },\n );\n measurement.allocatedMain = undefined;\n measurement.frameMain = measurement.finalMain;\n measurement.frameCross = getCrossSize(axis, measurement.measured);\n }\n } else {\n const remainingMain = finiteMain && availableMain != null ? Math.max(0, availableMain - nonGrowBasis) : undefined;\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (!(measurement.grow > 0 && finiteMain && remainingMain != null && totalGrow > 0)) {\n measurement.measured = measurement.basisMeasured;\n measurement.initialConstraints = measurement.basisConstraints;\n measurement.finalConstraints = finiteMain\n ? createAxisConstraints(\n axis,\n constraints,\n {\n min: undefined,\n max: measurement.finalMain,\n },\n {\n min: undefined,\n max: maxCross,\n },\n )\n : measurement.basisConstraints;\n measurement.allocatedMain = undefined;\n measurement.finalMain = measurement.basis;\n measurement.frameMain = measurement.basis;\n measurement.frameCross = getCrossSize(axis, measurement.measured);\n continue;\n }\n\n const allocatedMain = (remainingMain * measurement.grow) / totalGrow;\n const childConstraints = createAxisConstraints(\n axis,\n constraints,\n {\n max: allocatedMain,\n },\n {\n min: undefined,\n max: maxCross,\n },\n );\n const measured = measureChild(child, childConstraints);\n measurement.measured = measured;\n measurement.initialConstraints = childConstraints;\n measurement.finalConstraints = childConstraints;\n measurement.allocatedMain = allocatedMain;\n measurement.finalMain = allocatedMain;\n measurement.frameMain = allocatedMain;\n measurement.frameCross = getCrossSize(axis, measured);\n }\n }\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (!constraintsEqual(measurement.initialConstraints, measurement.finalConstraints)) {\n measurement.measured = measureChild(child, measurement.finalConstraints);\n }\n measurement.frameMain = measurement.finalMain;\n measurement.frameCross = getCrossSize(axis, measurement.measured);\n }\n\n let contentMain = gapTotal;\n let contentCross = 0;\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n contentMain += measurement.frameMain;\n contentCross = Math.max(contentCross, measurement.frameCross);\n }\n\n const containerMain = finiteMain && mainAxisSize === \"fill\"\n ? Math.max(maxMain!, contentMain)\n : clampToConstraints(contentMain, minMain, maxMain);\n const containerCross = clampToConstraints(contentCross, minCross, maxCross);\n if (finiteCross) {\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (!measurement.stretch) {\n continue;\n }\n\n const finalConstraints = createAxisConstraints(\n axis,\n measurement.finalConstraints,\n {\n min: getMinMain(axis, measurement.finalConstraints),\n max: getMaxMain(axis, measurement.finalConstraints),\n },\n {\n min: containerCross,\n max: containerCross,\n },\n );\n const remeasured = measureChild(child, finalConstraints);\n measurement.measured = remeasured;\n measurement.finalConstraints = finalConstraints;\n measurement.frameCross = containerCross;\n measurement.frameMain = measurement.allocatedMain ?? getMainSize(axis, remeasured);\n }\n\n contentMain = gapTotal;\n contentCross = 0;\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n contentMain += measurement.frameMain;\n contentCross = Math.max(contentCross, getCrossSize(axis, measurement.measured));\n }\n }\n\n const finalContainerMain = finiteMain && mainAxisSize === \"fill\"\n ? Math.max(maxMain!, contentMain)\n : clampToConstraints(contentMain, minMain, maxMain);\n const freeSpace = Math.max(0, finalContainerMain - contentMain);\n const spacing = getJustifySpacing(justifyContent, freeSpace, orderedChildren.length, gap);\n const childResults: ChildLayoutResult<C>[] = [];\n let cursor = spacing.leading;\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n const frameCross = measurement.stretch && finiteCross ? containerCross : measurement.frameCross;\n const contentMainSize = getMainSize(axis, measurement.measured);\n const contentCrossSize = getCrossSize(axis, measurement.measured);\n const rectCross = measurement.stretch ? 0 : getCrossOffset(measurement.effectiveAlign, containerCross, frameCross);\n const contentCrossOffset = rectCross + getCrossOffset(measurement.effectiveAlign, frameCross, contentCrossSize);\n const rect = createRectFromAxis(axis, cursor, rectCross, measurement.frameMain, frameCross);\n const contentBox = createRectFromAxis(axis, cursor, contentCrossOffset, contentMainSize, contentCrossSize);\n\n childResults.push({\n node: child,\n rect,\n contentBox,\n constraints: measurement.finalConstraints,\n });\n cursor += measurement.frameMain + spacing.between;\n }\n\n const containerBox = axis === \"row\"\n ? createRect(0, 0, finalContainerMain, containerCross)\n : createRect(0, 0, containerCross, finalContainerMain);\n const finalContentBox = childResults.length > 0\n ? computeContentBox(childResults)\n : createRect(0, 0, 0, 0);\n\n return {\n box: {\n width: containerBox.width,\n height: containerBox.height,\n },\n layout: {\n containerBox,\n contentBox: finalContentBox,\n children: childResults,\n constraints,\n },\n };\n}\n\n/**\n * Wraps a child node with per-item flex options.\n */\nexport class FlexItem<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n /**\n * @param inner Wrapped child node.\n * @param item Flex behavior overrides for the child.\n */\n constructor(\n inner: Node<C>,\n readonly item: FlexItemOptions = {},\n ) {\n super(inner);\n }\n}\n\n/**\n * Lays out children in a single flex row or column.\n */\nexport class Flex<C extends CanvasRenderingContext2D> extends Group<C> {\n /**\n * @param children Child nodes in visual order.\n * @param options Flex container configuration.\n */\n constructor(\n children: Node<C>[],\n readonly options: FlexContainerOptions = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n const result = computeFlexLayout(\n this.children,\n this.options,\n ctx.constraints,\n (node, constraints) => ctx.measureNode(node, constraints),\n (node, constraints) => measureNodeMinContent(ctx, node, constraints),\n );\n writeLayoutResult(this, ctx, result.layout);\n return result.box;\n }\n\n measureMinContent(ctx: Context<C>): Box {\n const axis = this.options.direction ?? \"row\";\n const gap = this.options.gap ?? 0;\n const orderedChildren = this.options.reverse ? [...this.children].reverse() : this.children;\n const gapTotal = orderedChildren.length > 1 ? gap * (orderedChildren.length - 1) : 0;\n const childConstraints = createAxisConstraints(\n axis,\n ctx.constraints,\n {\n min: undefined,\n max: undefined,\n },\n {\n min: undefined,\n max: getMaxCross(axis, ctx.constraints),\n },\n );\n\n let width = axis === \"row\" ? gapTotal : 0;\n let height = axis === \"column\" ? gapTotal : 0;\n\n for (const child of orderedChildren) {\n const measured = measureNodeMinContent(ctx, child, childConstraints);\n if (axis === \"row\") {\n width += measured.width;\n height = Math.max(height, measured.height);\n } else {\n width = Math.max(width, measured.width);\n height += measured.height;\n }\n }\n\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return drawLayoutChildren(this, ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return hittestLayoutChildren(this, ctx, test, \"contentBox\");\n }\n}\n","import { createRect, findChildAtPoint, getSingleChildLayout } from \"../layout\";\nimport type { Box, Context, HitTest, Node, TextAlign } from \"../types\";\nimport { measureNodeMinContent, Wrapper } from \"./base\";\nimport { readLayoutResult, withConstraints, writeLayoutResult } from \"./shared\";\n\nfunction resolveHorizontalOffset(align: TextAlign, availableWidth: number, childWidth: number): number {\n switch (align) {\n case \"center\":\n return (availableWidth - childWidth) / 2;\n case \"end\":\n return availableWidth - childWidth;\n case \"start\":\n return 0;\n }\n}\n\n/**\n * Aligns a single child horizontally within the available width.\n */\nexport class Place<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n /**\n * @param inner Wrapped child node.\n * @param options Alignment behavior for the child.\n */\n constructor(\n inner: Node<C>,\n readonly options: {\n align?: TextAlign;\n expand?: boolean;\n } = {},\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n const availableWidth = ctx.constraints?.maxWidth;\n const expand = this.options.expand ?? true;\n const childConstraints = ctx.constraints\n ? {\n ...ctx.constraints,\n }\n : undefined;\n const childBox = ctx.measureNode(this.inner, childConstraints);\n let width = expand && availableWidth != null ? availableWidth : childBox.width;\n if (ctx.constraints?.minWidth != null) {\n width = Math.max(width, ctx.constraints.minWidth);\n }\n if (ctx.constraints?.maxWidth != null) {\n width = Math.min(width, ctx.constraints.maxWidth);\n }\n\n const align = this.options.align ?? \"start\";\n const childRect = createRect(resolveHorizontalOffset(align, width, childBox.width), 0, childBox.width, childBox.height);\n\n writeLayoutResult(this, ctx, {\n containerBox: createRect(0, 0, width, childBox.height),\n contentBox: childRect,\n children: [\n {\n node: this.inner,\n rect: childRect,\n contentBox: createRect(0, 0, childBox.width, childBox.height),\n constraints: childConstraints,\n },\n ],\n constraints: ctx.constraints,\n });\n\n return {\n width,\n height: childBox.height,\n };\n }\n\n measureMinContent(ctx: Context<C>): Box {\n return measureNodeMinContent(ctx, this.inner);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return this.inner.draw(ctx, x, y);\n }\n\n const childResult = getSingleChildLayout(layoutResult);\n if (!childResult) {\n return false;\n }\n const childCtx = withConstraints(ctx, childResult.constraints);\n return childResult.node.draw(childCtx, x + childResult.rect.x, y + childResult.rect.y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, \"rect\");\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(\n withConstraints(ctx, hit.child.constraints),\n {\n ...test,\n x: hit.localX,\n y: hit.localY,\n },\n );\n }\n}\n","import { createRect, findChildAtPoint, getSingleChildLayout } from \"../layout\";\nimport type { Box, Context, HitTest, LayoutConstraints, Node } from \"../types\";\nimport { measureNodeMinContent, Wrapper } from \"./base\";\nimport { readLayoutResult, withConstraints, writeLayoutResult } from \"./shared\";\n\nexport interface ShrinkWrapOptions {\n tolerance?: number;\n preferredMinWidth?: number;\n}\n\nconst DEFAULT_TOLERANCE = 0.5;\nconst HEIGHT_EPSILON = 1e-6;\n\ntype ShrinkwrapProbeResult = {\n maxWidth: number;\n box: Box;\n};\n\nfunction withMaxWidth(\n constraints: LayoutConstraints | undefined,\n maxWidth: number,\n): LayoutConstraints {\n return {\n ...constraints,\n maxWidth,\n };\n}\n\nfunction computeShrinkwrapWidth(\n measure: (maxWidth: number) => Box,\n lowerBound: number,\n upperBound: number,\n referenceHeight: number,\n tolerance = DEFAULT_TOLERANCE,\n): ShrinkwrapProbeResult {\n const minWidth = Math.min(lowerBound, upperBound);\n const maxWidth = Math.max(lowerBound, upperBound);\n const effectiveTolerance = Math.max(tolerance, HEIGHT_EPSILON);\n const lowerBoundBox = measure(minWidth);\n if (lowerBoundBox.height <= referenceHeight + HEIGHT_EPSILON) {\n return {\n maxWidth: minWidth,\n box: lowerBoundBox,\n };\n }\n\n let lo = minWidth;\n let hi = maxWidth;\n let hiBox = measure(maxWidth);\n\n while (hi - lo > effectiveTolerance) {\n const probeWidth = (lo + hi) / 2;\n const probeBox = measure(probeWidth);\n if (probeBox.height <= referenceHeight + HEIGHT_EPSILON) {\n hi = probeWidth;\n hiBox = probeBox;\n continue;\n }\n lo = probeWidth;\n }\n\n return {\n maxWidth: hi,\n box: hiBox,\n };\n}\n\n/**\n * Shrinks a single child to the narrowest width that does not increase its reference height.\n */\nexport class ShrinkWrap<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n constructor(\n inner: Node<C>,\n readonly options: ShrinkWrapOptions = {},\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n const constraints = ctx.constraints;\n const availableWidth = constraints?.maxWidth;\n if (availableWidth == null) {\n const childConstraints = constraints == null ? undefined : { ...constraints };\n const childBox = ctx.measureNode(this.inner, childConstraints);\n this.#writeLayout(ctx, childBox, childConstraints);\n return childBox;\n }\n\n const boundedConstraints = constraints == null ? { maxWidth: availableWidth } : constraints;\n const referenceConstraints = { ...boundedConstraints };\n const referenceBox = ctx.measureNode(this.inner, referenceConstraints);\n let lowerBound = measureNodeMinContent(ctx, this.inner, boundedConstraints).width;\n const preferredMinWidth = this.options.preferredMinWidth == null\n ? undefined\n : Math.max(0, this.options.preferredMinWidth);\n if (preferredMinWidth != null && preferredMinWidth <= availableWidth) {\n lowerBound = Math.max(lowerBound, preferredMinWidth);\n }\n if (boundedConstraints.minWidth != null) {\n lowerBound = Math.max(lowerBound, boundedConstraints.minWidth);\n }\n if (lowerBound >= availableWidth) {\n this.#writeLayout(ctx, referenceBox, referenceConstraints);\n return referenceBox;\n }\n\n const finalProbe = computeShrinkwrapWidth(\n (maxWidth) => ctx.measureNode(this.inner, withMaxWidth(boundedConstraints, maxWidth)),\n lowerBound,\n availableWidth,\n referenceBox.height,\n this.options.tolerance ?? DEFAULT_TOLERANCE,\n );\n const finalConstraints = withMaxWidth(boundedConstraints, finalProbe.maxWidth);\n const finalBox = ctx.measureNode(this.inner, finalConstraints);\n this.#writeLayout(ctx, finalBox, finalConstraints);\n return finalBox;\n }\n\n measureMinContent(ctx: Context<C>): Box {\n return measureNodeMinContent(ctx, this.inner);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return this.inner.draw(ctx, x, y);\n }\n\n const childResult = getSingleChildLayout(layoutResult);\n if (!childResult) {\n return false;\n }\n\n return childResult.node.draw(\n withConstraints(ctx, childResult.constraints),\n x + childResult.rect.x,\n y + childResult.rect.y,\n );\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, \"rect\");\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(\n withConstraints(ctx, hit.child.constraints),\n {\n ...test,\n x: hit.localX,\n y: hit.localY,\n },\n );\n }\n\n #writeLayout(ctx: Context<C>, childBox: Box, childConstraints: LayoutConstraints | undefined): void {\n const childRect = createRect(0, 0, childBox.width, childBox.height);\n writeLayoutResult(this, ctx, {\n containerBox: childRect,\n contentBox: childRect,\n children: [\n {\n node: this.inner,\n rect: childRect,\n contentBox: childRect,\n constraints: childConstraints,\n },\n ],\n constraints: ctx.constraints,\n });\n }\n}\n","import type { Context, TextEllipsisPosition } from \"../types\";\n\nexport const FONT_SHIFT_PROBE = \"M\";\nexport const ELLIPSIS_GLYPH = \"…\";\nexport const INTRINSIC_MAX_WIDTH = Number.POSITIVE_INFINITY;\nexport const MIN_CONTENT_WIDTH_EPSILON = 0.001;\n\nlet sharedGraphemeSegmenter: Intl.Segmenter | null | undefined;\nconst fontShiftCache = new Map<string, number>();\nconst ellipsisWidthCache = new Map<string, number>();\n\nexport function readLruValue<T>(cache: Map<string, T>, key: string): T | undefined {\n const cached = cache.get(key);\n if (cached == null) {\n return undefined;\n }\n cache.delete(key);\n cache.set(key, cached);\n return cached;\n}\n\nexport function writeLruValue<T>(cache: Map<string, T>, key: string, value: T, capacity: number): T {\n if (cache.has(key)) {\n cache.delete(key);\n } else if (cache.size >= capacity) {\n const firstKey = cache.keys().next().value;\n if (firstKey != null) {\n cache.delete(firstKey);\n }\n }\n cache.set(key, value);\n return value;\n}\n\nexport function measureFontShift<C extends CanvasRenderingContext2D>(ctx: Context<C>): number {\n const font = ctx.graphics.font;\n const cached = fontShiftCache.get(font);\n if (cached != null) {\n return cached;\n }\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(FONT_SHIFT_PROBE);\n const shift = ascent - descent;\n fontShiftCache.set(font, shift);\n return shift;\n}\n\nexport function measureEllipsisWidth<C extends CanvasRenderingContext2D>(ctx: Context<C>): number {\n const font = ctx.graphics.font;\n const cached = ellipsisWidthCache.get(font);\n if (cached != null) {\n return cached;\n }\n const width = ctx.graphics.measureText(ELLIPSIS_GLYPH).width;\n ellipsisWidthCache.set(font, width);\n return width;\n}\n\nfunction getGraphemeSegmenter(): Intl.Segmenter | null {\n if (sharedGraphemeSegmenter !== undefined) {\n return sharedGraphemeSegmenter;\n }\n sharedGraphemeSegmenter = typeof Intl.Segmenter === \"function\"\n ? new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n : null;\n return sharedGraphemeSegmenter;\n}\n\nexport function splitGraphemes(text: string): string[] {\n const segmenter = getGraphemeSegmenter();\n if (segmenter == null) {\n return Array.from(text);\n }\n const graphemes: string[] = [];\n for (const part of segmenter.segment(text)) {\n graphemes.push(part.segment);\n }\n return graphemes;\n}\n\nexport function buildPrefixWidths(widths: readonly number[]): number[] {\n const cumulativeWidths = [0];\n let total = 0;\n for (const width of widths) {\n total += width;\n cumulativeWidths.push(total);\n }\n return cumulativeWidths;\n}\n\nexport function buildSuffixWidths(widths: readonly number[]): number[] {\n const cumulativeWidths = [0];\n let total = 0;\n for (let index = widths.length - 1; index >= 0; index -= 1) {\n total += widths[index] ?? 0;\n cumulativeWidths.push(total);\n }\n return cumulativeWidths;\n}\n\nexport function findMaxFittingCount(cumulativeWidths: readonly number[], maxWidth: number): number {\n if (maxWidth <= 0) {\n return 0;\n }\n let low = 0;\n let high = cumulativeWidths.length - 1;\n while (low < high) {\n const mid = Math.floor((low + high + 1) / 2);\n if ((cumulativeWidths[mid] ?? 0) <= maxWidth) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return low;\n}\n\nexport function normalizeMaxLines(maxLines: number | undefined): number | undefined {\n if (maxLines == null || !Number.isFinite(maxLines)) {\n return undefined;\n }\n return Math.max(1, Math.trunc(maxLines));\n}\n\nexport function selectEllipsisUnitCounts({\n position,\n prefixWidths,\n suffixWidths,\n unitCount,\n availableWidth,\n getMaxSuffixCount = (prefixCount) => unitCount - prefixCount,\n}: {\n position: TextEllipsisPosition;\n prefixWidths: readonly number[];\n suffixWidths: readonly number[];\n unitCount: number;\n availableWidth: number;\n getMaxSuffixCount?: (prefixCount: number) => number;\n}): { prefixCount: number; suffixCount: number } {\n let prefixCount = 0;\n let suffixCount = 0;\n\n switch (position) {\n case \"start\":\n suffixCount = Math.min(unitCount, findMaxFittingCount(suffixWidths, availableWidth));\n break;\n case \"middle\": {\n let bestVisibleUnits = -1;\n let bestBalanceScore = Number.NEGATIVE_INFINITY;\n for (let nextPrefixCount = 0; nextPrefixCount <= unitCount; nextPrefixCount += 1) {\n const prefixWidth = prefixWidths[nextPrefixCount] ?? 0;\n if (prefixWidth > availableWidth) {\n break;\n }\n const remainingWidth = availableWidth - prefixWidth;\n const maxSuffixCount = Math.max(0, getMaxSuffixCount(nextPrefixCount));\n const nextSuffixCount = Math.min(maxSuffixCount, findMaxFittingCount(suffixWidths, remainingWidth));\n const visibleUnits = nextPrefixCount + nextSuffixCount;\n const balanceScore = -Math.abs(nextPrefixCount - nextSuffixCount);\n if (\n visibleUnits > bestVisibleUnits ||\n (visibleUnits === bestVisibleUnits && balanceScore > bestBalanceScore) ||\n (visibleUnits === bestVisibleUnits && balanceScore === bestBalanceScore && nextPrefixCount > prefixCount)\n ) {\n prefixCount = nextPrefixCount;\n suffixCount = nextSuffixCount;\n bestVisibleUnits = visibleUnits;\n bestBalanceScore = balanceScore;\n }\n }\n break;\n }\n case \"end\":\n prefixCount = Math.min(unitCount, findMaxFittingCount(prefixWidths, availableWidth));\n break;\n }\n\n return { prefixCount, suffixCount };\n}\n\nexport function resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position,\n}: {\n widths: readonly number[];\n ellipsisWidth: number;\n maxWidth: number;\n position: TextEllipsisPosition;\n}): { prefixCount: number; suffixCount: number; width: number } | undefined {\n if (ellipsisWidth > maxWidth) {\n return undefined;\n }\n\n const prefixWidths = buildPrefixWidths(widths);\n const suffixWidths = buildSuffixWidths(widths);\n const { prefixCount, suffixCount } = selectEllipsisUnitCounts({\n position,\n prefixWidths,\n suffixWidths,\n unitCount: widths.length,\n availableWidth: Math.max(0, maxWidth - ellipsisWidth),\n });\n\n const width = position === \"start\"\n ? ellipsisWidth + (suffixWidths[suffixCount] ?? 0)\n : position === \"middle\"\n ? (prefixWidths[prefixCount] ?? 0) + ellipsisWidth + (suffixWidths[suffixCount] ?? 0)\n : (prefixWidths[prefixCount] ?? 0) + ellipsisWidth;\n\n return { prefixCount, suffixCount, width };\n}\n","import type {\n Context,\n InlineSpan,\n TextEllipsisPosition,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n buildPrefixWidths,\n buildSuffixWidths,\n measureEllipsisWidth,\n readLruValue,\n selectEllipsisUnitCounts,\n splitGraphemes,\n writeLruValue,\n} from \"./core\";\n\nconst LINE_FIT_EPSILON = 0.005;\nconst PREPARED_INLINE_CACHE_CAPACITY = 512;\nconst PREPARED_LINE_STATS_CACHE_CAPACITY = 16;\n\ntype MeasureContext = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n\ntype SourceItem = {\n text: string;\n font: string;\n itemIndex: number;\n breakMode: \"normal\" | \"never\";\n extraWidth: number;\n};\n\nexport type InlineAtom = {\n text: string;\n font: string;\n itemIndex: number;\n width: number;\n extraWidthAfter: number;\n kind: \"text\" | \"space\";\n preservesLineEnd: boolean;\n atomicGroupId: number | null;\n};\n\nexport type PreparedInlineUnit = {\n kind: \"text\" | \"space\";\n atoms: InlineAtom[];\n width: number;\n fitEndWidth: number;\n paintEndWidth: number;\n breakAfter: boolean;\n breakable: boolean;\n atomic: boolean;\n};\n\nexport type PreparedInlineChunk = {\n startUnit: number;\n endUnit: number;\n};\n\nexport type PreparedInlineLayout = {\n units: PreparedInlineUnit[];\n chunks: PreparedInlineChunk[];\n whiteSpace: TextWhiteSpaceMode;\n wordBreak: TextWordBreakMode;\n lineStatsCache: Map<number, PreparedInlineStats>;\n minContentWidthCache: Map<TextOverflowWrapMode, number>;\n};\n\nexport type PreparedInlineCursor = {\n chunkIndex: number;\n unitIndex: number;\n atomIndex: number;\n};\n\nexport type PreparedInlineLineRange = {\n width: number;\n start: PreparedInlineCursor;\n end: PreparedInlineCursor;\n next: PreparedInlineCursor;\n};\n\nexport type PreparedInlineStats = {\n lineCount: number;\n maxLineWidth: number;\n};\n\nexport type PreparedInlineAtomSlice = {\n atoms: InlineAtom[];\n width: number;\n};\n\nconst kinsokuStart = new Set([\n \"\\uFF0C\",\n \"\\uFF0E\",\n \"\\uFF01\",\n \"\\uFF1A\",\n \"\\uFF1B\",\n \"\\uFF1F\",\n \"\\u3001\",\n \"\\u3002\",\n \"\\u30FB\",\n \"\\uFF09\",\n \"\\u3015\",\n \"\\u3009\",\n \"\\u300B\",\n \"\\u300D\",\n \"\\u300F\",\n \"\\u3011\",\n \"\\u3017\",\n \"\\u3019\",\n \"\\u301B\",\n \"\\u30FC\",\n \"\\u3005\",\n \"\\u303B\",\n \"\\u309D\",\n \"\\u309E\",\n \"\\u30FD\",\n \"\\u30FE\",\n]);\n\nconst kinsokuEnd = new Set([\n \"\\\"\",\n \"(\",\n \"[\",\n \"{\",\n \"“\",\n \"‘\",\n \"«\",\n \"‹\",\n \"\\uFF08\",\n \"\\u3014\",\n \"\\u3008\",\n \"\\u300A\",\n \"\\u300C\",\n \"\\u300E\",\n \"\\u3010\",\n \"\\u3016\",\n \"\\u3018\",\n \"\\u301A\",\n]);\n\nconst leftStickyPunctuation = new Set([\n \".\",\n \",\",\n \"!\",\n \"?\",\n \":\",\n \";\",\n \"\\u060C\",\n \"\\u061B\",\n \"\\u061F\",\n \"\\u0964\",\n \"\\u0965\",\n \"\\u104A\",\n \"\\u104B\",\n \"\\u104C\",\n \"\\u104D\",\n \"\\u104F\",\n \")\",\n \"]\",\n \"}\",\n \"%\",\n \"\\\"\",\n \"”\",\n \"’\",\n \"»\",\n \"›\",\n \"…\",\n]);\n\nconst keepAllGlueChars = new Set([\n \"\\u00A0\",\n \"\\u202F\",\n \"\\u2060\",\n \"\\uFEFF\",\n]);\n\nconst closingQuoteChars = new Set([\n \"”\",\n \"’\",\n \"»\",\n \"›\",\n \"\\u300D\",\n \"\\u300F\",\n \"\\u3011\",\n]);\n\nconst cjkCodePointRanges: Array<[number, number]> = [\n [0x4E00, 0x9FFF],\n [0x3400, 0x4DBF],\n [0x20000, 0x2A6DF],\n [0x2A700, 0x2B73F],\n [0x2B740, 0x2B81F],\n [0x2B820, 0x2CEAF],\n [0x2CEB0, 0x2EBEF],\n [0x2EBF0, 0x2EE5D],\n [0x2F800, 0x2FA1F],\n [0x30000, 0x3134F],\n [0x31350, 0x323AF],\n [0x323B0, 0x33479],\n [0xF900, 0xFAFF],\n [0x3000, 0x303F],\n [0x3040, 0x309F],\n [0x30A0, 0x30FF],\n [0xAC00, 0xD7AF],\n [0xFF00, 0xFFEF],\n];\n\nlet sharedMeasureContext: MeasureContext | null = null;\nlet sharedWordSegmenter: Intl.Segmenter | null | undefined;\nconst textWidthCache = new Map<string, Map<string, number>>();\nconst preparedInlineCache = new Map<string, PreparedInlineLayout>();\n\nfunction getMeasureContext(): MeasureContext {\n if (sharedMeasureContext != null) {\n return sharedMeasureContext;\n }\n if (typeof OffscreenCanvas !== \"undefined\") {\n const ctx = new OffscreenCanvas(1, 1).getContext(\"2d\");\n if (ctx != null) {\n sharedMeasureContext = ctx;\n return ctx;\n }\n }\n if (typeof document !== \"undefined\") {\n const ctx = document.createElement(\"canvas\").getContext(\"2d\");\n if (ctx != null) {\n sharedMeasureContext = ctx;\n return ctx;\n }\n }\n throw new Error(\"Text measurement requires OffscreenCanvas or a DOM canvas context.\");\n}\n\nfunction getTextWidthCache(font: string): Map<string, number> {\n let cache = textWidthCache.get(font);\n if (cache == null) {\n cache = new Map<string, number>();\n textWidthCache.set(font, cache);\n }\n return cache;\n}\n\nfunction measureTextWidth(font: string, text: string): number {\n const cache = getTextWidthCache(font);\n const cached = cache.get(text);\n if (cached != null) {\n return cached;\n }\n const ctx = getMeasureContext();\n ctx.font = font;\n const width = ctx.measureText(text).width;\n cache.set(text, width);\n return width;\n}\n\nfunction isCollapsibleWhitespace(text: string): boolean {\n return /^[ \\t\\n\\f\\r]+$/u.test(text);\n}\n\nfunction isPreservedWhitespaceGrapheme(text: string): boolean {\n return text === \" \" || text === \"\\t\";\n}\n\nfunction normalizePreWrapText(text: string): string {\n if (!/[\\r\\f]/.test(text)) {\n return text.replace(/\\r\\n/g, \"\\n\");\n }\n return text.replace(/\\r\\n/g, \"\\n\").replace(/[\\r\\f]/g, \"\\n\");\n}\n\nfunction getLastCodePoint(text: string): string | null {\n if (text.length === 0) {\n return null;\n }\n const codePoints = Array.from(text);\n return codePoints[codePoints.length - 1] ?? null;\n}\n\nfunction isCJKCodePoint(codePoint: number): boolean {\n for (const [start, end] of cjkCodePointRanges) {\n if (codePoint >= start && codePoint <= end) {\n return true;\n }\n }\n return false;\n}\n\nexport function isCJK(text: string): boolean {\n for (const char of text) {\n const codePoint = char.codePointAt(0);\n if (codePoint != null && isCJKCodePoint(codePoint)) {\n return true;\n }\n }\n return false;\n}\n\nfunction endsWithClosingQuote(text: string): boolean {\n const last = getLastCodePoint(text);\n return last != null && closingQuoteChars.has(last);\n}\n\nfunction endsWithKeepAllGlueText(text: string): boolean {\n const last = getLastCodePoint(text);\n return last != null && keepAllGlueChars.has(last);\n}\n\nfunction endsWithLineStartProhibitedText(text: string): boolean {\n const last = getLastCodePoint(text);\n return last != null && (kinsokuStart.has(last) || leftStickyPunctuation.has(last));\n}\n\nfunction canContinueKeepAllTextRun(text: string): boolean {\n return !endsWithLineStartProhibitedText(text) && !endsWithKeepAllGlueText(text);\n}\n\nfunction getSharedWordSegmenter(): Intl.Segmenter | null {\n if (sharedWordSegmenter !== undefined) {\n return sharedWordSegmenter;\n }\n sharedWordSegmenter = typeof Intl.Segmenter === \"function\"\n ? new Intl.Segmenter(undefined, { granularity: \"word\" })\n : null;\n return sharedWordSegmenter;\n}\n\nfunction sumAtomWidths(atoms: readonly InlineAtom[], start = 0, end = atoms.length): number {\n let width = 0;\n for (let index = start; index < end; index += 1) {\n const atom = atoms[index];\n if (atom != null) {\n width += atom.width + atom.extraWidthAfter;\n }\n }\n return width;\n}\n\nfunction joinAtomText(atoms: readonly InlineAtom[], start = 0, end = atoms.length): string {\n let text = \"\";\n for (let index = start; index < end; index += 1) {\n const atom = atoms[index];\n if (atom != null) {\n text += atom.text;\n }\n }\n return text;\n}\n\nfunction measureAtomSequenceWidth(atoms: readonly InlineAtom[]): number {\n if (atoms.length === 0) {\n return 0;\n }\n let width = 0;\n let currentFont = atoms[0]!.font;\n let currentText = \"\";\n for (const atom of atoms) {\n if (atom.font !== currentFont && currentText.length > 0) {\n width += measureTextWidth(currentFont, currentText);\n currentFont = atom.font;\n currentText = \"\";\n }\n currentText += atom.text;\n width += atom.extraWidthAfter;\n }\n if (currentText.length > 0) {\n width += measureTextWidth(currentFont, currentText);\n }\n return width;\n}\n\nfunction pushTextPartAtoms(\n target: InlineAtom[],\n text: string,\n font: string,\n itemIndex: number,\n atomicGroupId: number | null,\n extraWidth: number,\n): void {\n const graphemes = splitGraphemes(text);\n for (let index = 0; index < graphemes.length; index += 1) {\n const grapheme = graphemes[index] ?? \"\";\n target.push({\n text: grapheme,\n font,\n itemIndex,\n width: measureTextWidth(font, grapheme),\n extraWidthAfter: index === graphemes.length - 1 ? extraWidth : 0,\n kind: \"text\",\n preservesLineEnd: false,\n atomicGroupId,\n });\n }\n}\n\nfunction buildCollapsedWhitespaceAtoms(items: readonly SourceItem[]): InlineAtom[][] {\n const chunks: InlineAtom[][] = [[]];\n const atoms = chunks[0]!;\n let pendingSpace:\n | {\n font: string;\n itemIndex: number;\n atomicGroupId: number | null;\n }\n | null = null;\n let lastVisible:\n | {\n font: string;\n itemIndex: number;\n atomicGroupId: number | null;\n }\n | null = null;\n\n for (const item of items) {\n const atomicGroupId = item.breakMode === \"never\" ? item.itemIndex + 1 : null;\n const parts = item.text.match(/[ \\t\\n\\f\\r]+|[^ \\t\\n\\f\\r]+/gu) ?? [];\n for (let partIndex = 0; partIndex < parts.length; partIndex += 1) {\n const part = parts[partIndex] ?? \"\";\n if (isCollapsibleWhitespace(part)) {\n if (lastVisible != null) {\n pendingSpace = {\n font: lastVisible.font,\n itemIndex: lastVisible.itemIndex,\n atomicGroupId,\n };\n }\n continue;\n }\n\n if (pendingSpace != null) {\n atoms.push({\n text: \" \",\n font: pendingSpace.font,\n itemIndex: pendingSpace.itemIndex,\n width: measureTextWidth(pendingSpace.font, \" \"),\n extraWidthAfter: 0,\n kind: \"space\",\n preservesLineEnd: false,\n atomicGroupId: pendingSpace.atomicGroupId,\n });\n pendingSpace = null;\n }\n\n pushTextPartAtoms(\n atoms,\n part,\n item.font,\n item.itemIndex,\n atomicGroupId,\n partIndex === parts.length - 1 ? item.extraWidth : 0,\n );\n lastVisible = {\n font: item.font,\n itemIndex: item.itemIndex,\n atomicGroupId,\n };\n }\n }\n\n return chunks;\n}\n\nfunction buildPreWrapAtoms(items: readonly SourceItem[]): InlineAtom[][] {\n const chunks: InlineAtom[][] = [[]];\n let currentChunk = chunks[0]!;\n\n for (const item of items) {\n const atomicGroupId = item.breakMode === \"never\" ? item.itemIndex + 1 : null;\n const normalizedText = normalizePreWrapText(item.text);\n const graphemes = splitGraphemes(normalizedText);\n for (let index = 0; index < graphemes.length; index += 1) {\n const grapheme = graphemes[index] ?? \"\";\n if (grapheme === \"\\n\") {\n currentChunk = [];\n chunks.push(currentChunk);\n continue;\n }\n const isSpace = isPreservedWhitespaceGrapheme(grapheme);\n currentChunk.push({\n text: grapheme,\n font: item.font,\n itemIndex: item.itemIndex,\n width: measureTextWidth(item.font, grapheme),\n extraWidthAfter: index === graphemes.length - 1 ? item.extraWidth : 0,\n kind: isSpace ? \"space\" : \"text\",\n preservesLineEnd: isSpace,\n atomicGroupId,\n });\n }\n }\n\n return chunks;\n}\n\nfunction buildBaseCjkUnits(atoms: readonly InlineAtom[]): InlineAtom[][] {\n const units: InlineAtom[][] = [];\n let current: InlineAtom[] = [];\n let currentContainsCJK = false;\n let currentEndsWithClosingQuote = false;\n let currentIsSingleKinsokuEnd = false;\n\n const flushCurrent = () => {\n if (current.length === 0) {\n return;\n }\n units.push(current);\n current = [];\n currentContainsCJK = false;\n currentEndsWithClosingQuote = false;\n currentIsSingleKinsokuEnd = false;\n };\n\n for (const atom of atoms) {\n const atomContainsCJK = isCJK(atom.text);\n if (current.length === 0) {\n current = [atom];\n currentContainsCJK = atomContainsCJK;\n currentEndsWithClosingQuote = endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = kinsokuEnd.has(atom.text);\n continue;\n }\n\n if (\n currentIsSingleKinsokuEnd ||\n kinsokuStart.has(atom.text) ||\n leftStickyPunctuation.has(atom.text) ||\n (atomContainsCJK && currentEndsWithClosingQuote)\n ) {\n current.push(atom);\n currentContainsCJK = currentContainsCJK || atomContainsCJK;\n currentEndsWithClosingQuote = leftStickyPunctuation.has(atom.text)\n ? currentEndsWithClosingQuote || endsWithClosingQuote(atom.text)\n : endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = false;\n continue;\n }\n\n if (!currentContainsCJK && !atomContainsCJK) {\n current.push(atom);\n currentEndsWithClosingQuote = endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = false;\n continue;\n }\n\n flushCurrent();\n current = [atom];\n currentContainsCJK = atomContainsCJK;\n currentEndsWithClosingQuote = endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = kinsokuEnd.has(atom.text);\n }\n\n flushCurrent();\n return units;\n}\n\nfunction mergeKeepAllUnits(units: readonly InlineAtom[][]): InlineAtom[][] {\n if (units.length <= 1) {\n return units.slice();\n }\n\n const merged: InlineAtom[][] = [];\n let current = units[0]!.slice();\n let currentText = joinAtomText(current);\n let currentContainsCJK = isCJK(currentText);\n let currentCanContinue = canContinueKeepAllTextRun(currentText);\n\n const flush = () => {\n merged.push(current);\n };\n\n for (let index = 1; index < units.length; index += 1) {\n const next = units[index]!;\n const nextText = joinAtomText(next);\n const nextContainsCJK = isCJK(nextText);\n const nextCanContinue = canContinueKeepAllTextRun(nextText);\n\n if (currentContainsCJK && currentCanContinue) {\n current = [...current, ...next];\n currentText += nextText;\n currentContainsCJK = currentContainsCJK || nextContainsCJK;\n currentCanContinue = nextCanContinue;\n continue;\n }\n\n flush();\n current = next.slice();\n currentText = nextText;\n currentContainsCJK = nextContainsCJK;\n currentCanContinue = nextCanContinue;\n }\n\n flush();\n return merged;\n}\n\nfunction splitAtomsByWordSegments(atoms: readonly InlineAtom[]): InlineAtom[][] {\n if (atoms.length <= 1) {\n return atoms.length === 0 ? [] : [atoms.slice()];\n }\n const segmenter = getSharedWordSegmenter();\n if (segmenter == null) {\n return [atoms.slice()];\n }\n\n const text = joinAtomText(atoms);\n const offsets = [0];\n for (let index = 0; index < atoms.length; index += 1) {\n offsets.push((offsets[index] ?? 0) + (atoms[index]?.text.length ?? 0));\n }\n\n const units: InlineAtom[][] = [];\n let atomStart = 0;\n let atomEnd = 0;\n for (const segment of segmenter.segment(text)) {\n const start = segment.index;\n const end = start + segment.segment.length;\n while ((offsets[atomStart] ?? 0) < start) {\n atomStart += 1;\n }\n atomEnd = atomStart;\n while ((offsets[atomEnd] ?? 0) < end) {\n atomEnd += 1;\n }\n if (atomStart < atomEnd) {\n units.push(atoms.slice(atomStart, atomEnd));\n }\n atomStart = atomEnd;\n }\n\n return units.length > 0 ? units : [atoms.slice()];\n}\n\nfunction makeTextUnit(atoms: InlineAtom[], atomic = false): PreparedInlineUnit {\n const width = measureAtomSequenceWidth(atoms);\n return {\n kind: \"text\",\n atoms,\n width,\n fitEndWidth: width,\n paintEndWidth: width,\n breakAfter: true,\n breakable: !atomic && atoms.length > 1,\n atomic,\n };\n}\n\nfunction makeSpaceUnit(atoms: InlineAtom[]): PreparedInlineUnit {\n const width = measureAtomSequenceWidth(atoms);\n const preservesLineEnd = atoms.every((atom) => atom.preservesLineEnd);\n return {\n kind: \"space\",\n atoms,\n width,\n fitEndWidth: 0,\n paintEndWidth: preservesLineEnd ? width : 0,\n breakAfter: true,\n breakable: atoms.length > 1,\n atomic: false,\n };\n}\n\nfunction tokenizeChunkAtoms(\n chunkAtoms: readonly InlineAtom[],\n wordBreak: TextWordBreakMode,\n): PreparedInlineUnit[] {\n const units: PreparedInlineUnit[] = [];\n let index = 0;\n\n while (index < chunkAtoms.length) {\n const atom = chunkAtoms[index]!;\n if (atom.atomicGroupId != null) {\n const start = index;\n const atomicGroupId = atom.atomicGroupId;\n while (index < chunkAtoms.length && chunkAtoms[index]?.atomicGroupId === atomicGroupId) {\n index += 1;\n }\n units.push(makeTextUnit(chunkAtoms.slice(start, index), true));\n continue;\n }\n\n if (atom.kind === \"space\") {\n const start = index;\n while (index < chunkAtoms.length && chunkAtoms[index]?.kind === \"space\" && chunkAtoms[index]?.atomicGroupId == null) {\n index += 1;\n }\n units.push(makeSpaceUnit(chunkAtoms.slice(start, index)));\n continue;\n }\n\n const start = index;\n while (index < chunkAtoms.length && chunkAtoms[index]?.kind === \"text\" && chunkAtoms[index]?.atomicGroupId == null) {\n index += 1;\n }\n const textRunAtoms = chunkAtoms.slice(start, index);\n const runText = joinAtomText(textRunAtoms);\n const rawUnits = isCJK(runText)\n ? buildBaseCjkUnits(textRunAtoms)\n : splitAtomsByWordSegments(textRunAtoms);\n const normalizedUnits = wordBreak === \"keep-all\" && isCJK(runText)\n ? mergeKeepAllUnits(rawUnits)\n : rawUnits;\n for (const unitAtoms of normalizedUnits) {\n units.push(makeTextUnit(unitAtoms.slice(), false));\n }\n }\n\n return units;\n}\n\nfunction buildPreparedInlineLayout(\n items: readonly SourceItem[],\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedInlineLayout {\n const atomChunks = whiteSpace === \"pre-wrap\"\n ? buildPreWrapAtoms(items)\n : buildCollapsedWhitespaceAtoms(items);\n const chunks: PreparedInlineChunk[] = [];\n const units: PreparedInlineUnit[] = [];\n\n for (const atomChunk of atomChunks) {\n const startUnit = units.length;\n const chunkUnits = tokenizeChunkAtoms(atomChunk, wordBreak);\n units.push(...chunkUnits);\n chunks.push({\n startUnit,\n endUnit: units.length,\n });\n }\n\n return {\n units,\n chunks,\n whiteSpace,\n wordBreak,\n lineStatsCache: new Map<number, PreparedInlineStats>(),\n minContentWidthCache: new Map<TextOverflowWrapMode, number>(),\n };\n}\n\nfunction readNumberLruValue<T>(cache: Map<number, T>, key: number): T | undefined {\n const cached = cache.get(key);\n if (cached == null) {\n return undefined;\n }\n cache.delete(key);\n cache.set(key, cached);\n return cached;\n}\n\nfunction writeNumberLruValue<T>(cache: Map<number, T>, key: number, value: T, capacity: number): T {\n if (cache.has(key)) {\n cache.delete(key);\n } else if (cache.size >= capacity) {\n const firstKey = cache.keys().next().value;\n if (firstKey != null) {\n cache.delete(firstKey);\n }\n }\n cache.set(key, value);\n return value;\n}\n\nfunction cloneCursor(cursor: PreparedInlineCursor): PreparedInlineCursor {\n return {\n chunkIndex: cursor.chunkIndex,\n unitIndex: cursor.unitIndex,\n atomIndex: cursor.atomIndex,\n };\n}\n\nfunction cursorEquals(a: PreparedInlineCursor, b: PreparedInlineCursor): boolean {\n return a.chunkIndex === b.chunkIndex && a.unitIndex === b.unitIndex && a.atomIndex === b.atomIndex;\n}\n\nfunction fits(width: number, maxWidth: number): boolean {\n return width <= maxWidth + LINE_FIT_EPSILON;\n}\n\nfunction getVisibleEndAfterBreak(\n chunkIndex: number,\n unitIndex: number,\n unit: PreparedInlineUnit,\n): PreparedInlineCursor {\n if (unit.kind === \"space\" && unit.paintEndWidth === 0) {\n return { chunkIndex, unitIndex, atomIndex: 0 };\n }\n return { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n}\n\nfunction fitPartialUnit(\n unit: PreparedInlineUnit,\n startAtomIndex: number,\n lineWidth: number,\n maxWidth: number,\n): { count: number; width: number } {\n let width = 0;\n let count = 0;\n for (let index = startAtomIndex; index < unit.atoms.length; index += 1) {\n const atom = unit.atoms[index]!;\n const atomWidth = atom.width + atom.extraWidthAfter;\n if (count > 0 && !fits(lineWidth + width + atomWidth, maxWidth)) {\n break;\n }\n if (count === 0 || fits(lineWidth + width + atomWidth, maxWidth)) {\n width += atomWidth;\n count += 1;\n continue;\n }\n break;\n }\n return { count, width };\n}\n\nfunction stepChunkLine(\n prepared: PreparedInlineLayout,\n chunkIndex: number,\n startUnitIndex: number,\n startAtomIndex: number,\n maxWidth: number,\n): PreparedInlineLineRange | null {\n const chunk = prepared.chunks[chunkIndex];\n if (chunk == null || startUnitIndex >= chunk.endUnit) {\n return null;\n }\n\n const start: PreparedInlineCursor = {\n chunkIndex,\n unitIndex: startUnitIndex,\n atomIndex: startAtomIndex,\n };\n let unitIndex = startUnitIndex;\n let atomIndex = startAtomIndex;\n let lineWidth = 0;\n let hasContent = false;\n let pendingBreak:\n | {\n end: PreparedInlineCursor;\n next: PreparedInlineCursor;\n width: number;\n }\n | null = null;\n\n while (unitIndex < chunk.endUnit) {\n const unit = prepared.units[unitIndex]!;\n if (atomIndex > 0) {\n const fitted = fitPartialUnit(unit, atomIndex, lineWidth, maxWidth);\n if (fitted.count === 0) {\n if (hasContent) {\n return {\n width: lineWidth,\n start,\n end: { chunkIndex, unitIndex, atomIndex },\n next: { chunkIndex, unitIndex, atomIndex },\n };\n }\n const atom = unit.atoms[atomIndex]!;\n const width = atom.width + atom.extraWidthAfter;\n return {\n width,\n start,\n end: { chunkIndex, unitIndex, atomIndex: atomIndex + 1 },\n next: { chunkIndex, unitIndex, atomIndex: atomIndex + 1 },\n };\n }\n\n if (atomIndex + fitted.count >= unit.atoms.length) {\n lineWidth += fitted.width;\n hasContent = true;\n atomIndex = 0;\n unitIndex += 1;\n pendingBreak = {\n end: { chunkIndex, unitIndex, atomIndex: 0 },\n next: { chunkIndex, unitIndex, atomIndex: 0 },\n width: lineWidth,\n };\n continue;\n }\n\n return {\n width: lineWidth + fitted.width,\n start,\n end: { chunkIndex, unitIndex, atomIndex: atomIndex + fitted.count },\n next: { chunkIndex, unitIndex, atomIndex: atomIndex + fitted.count },\n };\n }\n\n if (!hasContent) {\n if (fits(unit.width, maxWidth) || unit.atomic || !unit.breakable) {\n lineWidth = unit.width;\n hasContent = true;\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n pendingBreak = {\n end: getVisibleEndAfterBreak(chunkIndex, unitIndex, unit),\n next,\n width: unit.paintEndWidth,\n };\n unitIndex += 1;\n continue;\n }\n\n const fitted = fitPartialUnit(unit, 0, 0, maxWidth);\n if (fitted.count >= unit.atoms.length) {\n lineWidth = fitted.width;\n hasContent = true;\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n pendingBreak = {\n end: next,\n next,\n width: lineWidth,\n };\n unitIndex += 1;\n continue;\n }\n return {\n width: fitted.width,\n start,\n end: { chunkIndex, unitIndex, atomIndex: fitted.count },\n next: { chunkIndex, unitIndex, atomIndex: fitted.count },\n };\n }\n\n if (fits(lineWidth + unit.width, maxWidth)) {\n const nextWidth = lineWidth + unit.width;\n lineWidth = nextWidth;\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n pendingBreak = {\n end: getVisibleEndAfterBreak(chunkIndex, unitIndex, unit),\n next,\n width: nextWidth - unit.width + unit.paintEndWidth,\n };\n unitIndex += 1;\n continue;\n }\n\n if (fits(lineWidth + unit.fitEndWidth, maxWidth)) {\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n return {\n width: lineWidth + unit.paintEndWidth,\n start,\n end: getVisibleEndAfterBreak(chunkIndex, unitIndex, unit),\n next,\n };\n }\n\n if (pendingBreak != null) {\n return {\n width: pendingBreak.width,\n start,\n end: pendingBreak.end,\n next: pendingBreak.next,\n };\n }\n\n return {\n width: lineWidth,\n start,\n end: { chunkIndex, unitIndex, atomIndex: 0 },\n next: { chunkIndex, unitIndex, atomIndex: 0 },\n };\n }\n\n if (!hasContent) {\n return null;\n }\n\n if (pendingBreak != null && pendingBreak.next.unitIndex === chunk.endUnit && pendingBreak.next.atomIndex === 0) {\n return {\n width: pendingBreak.width,\n start,\n end: pendingBreak.end,\n next: pendingBreak.next,\n };\n }\n\n return {\n width: lineWidth,\n start,\n end: { chunkIndex, unitIndex, atomIndex: 0 },\n next: { chunkIndex, unitIndex, atomIndex: 0 },\n };\n}\n\nexport function getPreparedLineStart(prepared: PreparedInlineLayout): PreparedInlineCursor | undefined {\n for (let chunkIndex = 0; chunkIndex < prepared.chunks.length; chunkIndex += 1) {\n const chunk = prepared.chunks[chunkIndex]!;\n if (chunk.startUnit === chunk.endUnit) {\n return { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n }\n return { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n }\n return undefined;\n}\n\nexport function getPreparedEndCursor(prepared: PreparedInlineLayout): PreparedInlineCursor {\n if (prepared.chunks.length === 0) {\n return { chunkIndex: 0, unitIndex: 0, atomIndex: 0 };\n }\n const lastChunkIndex = prepared.chunks.length - 1;\n const lastChunk = prepared.chunks[lastChunkIndex]!;\n return {\n chunkIndex: lastChunkIndex,\n unitIndex: lastChunk.endUnit,\n atomIndex: 0,\n };\n}\n\nexport function layoutNextPreparedLine(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n maxWidth: number,\n): PreparedInlineLineRange | null {\n const chunk = prepared.chunks[start.chunkIndex];\n if (chunk == null) {\n return null;\n }\n if (chunk.startUnit === chunk.endUnit) {\n return cursorEquals(start, { chunkIndex: start.chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 })\n ? null\n : {\n width: 0,\n start: cloneCursor(start),\n end: { chunkIndex: start.chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 },\n next: { chunkIndex: start.chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 },\n };\n }\n return stepChunkLine(\n prepared,\n start.chunkIndex,\n start.unitIndex,\n start.atomIndex,\n maxWidth,\n );\n}\n\nexport function walkPreparedLineRanges(\n prepared: PreparedInlineLayout,\n maxWidth: number,\n onLine: (line: PreparedInlineLineRange) => boolean | void,\n): number {\n let lineCount = 0;\n for (let chunkIndex = 0; chunkIndex < prepared.chunks.length; chunkIndex += 1) {\n const chunk = prepared.chunks[chunkIndex]!;\n if (chunk.startUnit === chunk.endUnit) {\n const cursor = { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n if (onLine({ width: 0, start: cursor, end: cursor, next: cursor }) === false) {\n lineCount += 1;\n return lineCount;\n }\n lineCount += 1;\n continue;\n }\n let cursor: PreparedInlineCursor = {\n chunkIndex,\n unitIndex: chunk.startUnit,\n atomIndex: 0,\n };\n while (true) {\n const line = layoutNextPreparedLine(prepared, cursor, maxWidth);\n if (line == null) {\n break;\n }\n if (onLine(line) === false) {\n lineCount += 1;\n return lineCount;\n }\n lineCount += 1;\n if (cursorEquals(line.next, cursor)) {\n break;\n }\n cursor = line.next;\n if (cursor.unitIndex >= chunk.endUnit && cursor.atomIndex === 0) {\n break;\n }\n }\n }\n return lineCount;\n}\n\nexport function forEachAtomFromCursorToEnd(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n cb: (atom: InlineAtom) => void,\n): void {\n for (let chunkIndex = start.chunkIndex; chunkIndex < prepared.chunks.length; chunkIndex += 1) {\n const chunk = prepared.chunks[chunkIndex];\n if (chunk == null) {\n continue;\n }\n const chunkStart = chunkIndex === start.chunkIndex\n ? start\n : { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n const chunkEnd = { chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 };\n forEachAtomInRange(prepared, chunkStart, chunkEnd, cb);\n }\n}\n\nexport function measurePreparedLineStats(prepared: PreparedInlineLayout, maxWidth: number): PreparedInlineStats {\n const cached = readNumberLruValue(prepared.lineStatsCache, maxWidth);\n if (cached != null) {\n return cached;\n }\n let lineCount = 0;\n let maxLineWidth = 0;\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n lineCount += 1;\n if (line.width > maxLineWidth) {\n maxLineWidth = line.width;\n }\n });\n return writeNumberLruValue(\n prepared.lineStatsCache,\n maxWidth,\n { lineCount, maxLineWidth },\n PREPARED_LINE_STATS_CACHE_CAPACITY,\n );\n}\n\nexport function measurePreparedNaturalWidth(prepared: PreparedInlineLayout): number {\n return measurePreparedLineStats(prepared, Number.POSITIVE_INFINITY).maxLineWidth;\n}\n\nexport function forEachAtomInRange(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n end: PreparedInlineCursor,\n cb: (atom: InlineAtom) => void,\n): void {\n if (start.chunkIndex !== end.chunkIndex) {\n throw new Error(\"Atom range iteration only supports a single chunk.\");\n }\n for (let unitIndex = start.unitIndex; unitIndex < end.unitIndex; unitIndex += 1) {\n const unit = prepared.units[unitIndex]!;\n const atomStart = unitIndex === start.unitIndex ? start.atomIndex : 0;\n const atomEnd = unitIndex === end.unitIndex ? end.atomIndex : unit.atoms.length;\n for (let atomIndex = atomStart; atomIndex < atomEnd; atomIndex += 1) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n cb(atom);\n }\n }\n }\n if (end.unitIndex < prepared.units.length) {\n const unit = prepared.units[end.unitIndex];\n if (unit != null && start.unitIndex === end.unitIndex) {\n for (let atomIndex = start.atomIndex; atomIndex < end.atomIndex; atomIndex += 1) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n cb(atom);\n }\n }\n }\n }\n}\n\nexport function collectAtomsInRange(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n end: PreparedInlineCursor,\n): InlineAtom[] {\n const atoms: InlineAtom[] = [];\n if (start.unitIndex === end.unitIndex) {\n const unit = prepared.units[start.unitIndex];\n if (unit == null) {\n return atoms;\n }\n for (let atomIndex = start.atomIndex; atomIndex < end.atomIndex; atomIndex += 1) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n atoms.push(atom);\n }\n }\n return atoms;\n }\n\n const startChunk = prepared.chunks[start.chunkIndex];\n if (startChunk == null) {\n return atoms;\n }\n for (let unitIndex = start.unitIndex; unitIndex < end.unitIndex; unitIndex += 1) {\n const unit = prepared.units[unitIndex]!;\n const atomStart = unitIndex === start.unitIndex ? start.atomIndex : 0;\n for (let atomIndex = atomStart; atomIndex < unit.atoms.length; atomIndex += 1) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n atoms.push(atom);\n }\n }\n }\n const endUnit = prepared.units[end.unitIndex];\n if (endUnit != null) {\n for (let atomIndex = 0; atomIndex < end.atomIndex; atomIndex += 1) {\n const atom = endUnit.atoms[atomIndex];\n if (atom != null) {\n atoms.push(atom);\n }\n }\n }\n return atoms;\n}\n\nexport function collectLineAtoms(prepared: PreparedInlineLayout, line: PreparedInlineLineRange): PreparedInlineAtomSlice {\n const atoms = collectAtomsInRange(prepared, line.start, line.end);\n return {\n atoms,\n width: line.width,\n };\n}\n\nexport function collectAtomsFromCursorToEnd(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n): InlineAtom[] {\n const atoms: InlineAtom[] = [];\n for (let chunkIndex = start.chunkIndex; chunkIndex < prepared.chunks.length; chunkIndex += 1) {\n const chunk = prepared.chunks[chunkIndex]!;\n const chunkStart = chunkIndex === start.chunkIndex\n ? start\n : { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n const chunkEnd = { chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 };\n atoms.push(...collectAtomsInRange(prepared, chunkStart, chunkEnd));\n }\n return atoms;\n}\n\nexport function materializePreparedLineText(prepared: PreparedInlineLayout, line: PreparedInlineLineRange): string {\n return joinAtomText(collectLineAtoms(prepared, line).atoms);\n}\n\nexport function flattenPreparedLineAtoms(prepared: PreparedInlineLayout, line: PreparedInlineLineRange): InlineAtom[] {\n return collectLineAtoms(prepared, line).atoms;\n}\n\nexport function measurePreparedMinContentWidth(\n prepared: PreparedInlineLayout,\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n): number {\n const cached = prepared.minContentWidthCache.get(overflowWrap);\n if (cached != null) {\n return cached;\n }\n let maxWidth = 0;\n let maxAnyWidth = 0;\n for (const unit of prepared.units) {\n if (unit.width > maxAnyWidth) {\n maxAnyWidth = unit.width;\n }\n if (unit.kind !== \"text\") {\n continue;\n }\n const candidateWidth = overflowWrap === \"anywhere\" && unit.breakable\n ? unit.atoms.reduce((widest, atom) => Math.max(widest, atom.width + atom.extraWidthAfter), 0)\n : unit.width;\n if (candidateWidth > maxWidth) {\n maxWidth = candidateWidth;\n }\n }\n const resolvedWidth = maxWidth > 0 ? maxWidth : maxAnyWidth;\n prepared.minContentWidthCache.set(overflowWrap, resolvedWidth);\n return resolvedWidth;\n}\n\nexport function getPreparedUnits(prepared: PreparedInlineLayout): Array<{ text: string; width: number }> {\n const resolvedUnits: Array<{ text: string; width: number }> = [];\n for (let unitIndex = 0; unitIndex < prepared.units.length; unitIndex += 1) {\n const unit = prepared.units[unitIndex]!;\n if (unit.kind === \"text\" && unit.breakable) {\n for (let atomIndex = 0; atomIndex < unit.atoms.length; atomIndex += 1) {\n const atom = unit.atoms[atomIndex]!;\n resolvedUnits.push({\n text: atom.text,\n width: atom.width + atom.extraWidthAfter,\n });\n }\n continue;\n }\n const text = joinAtomText(unit.atoms);\n if (text.length === 0 && unit.width === 0) {\n continue;\n }\n resolvedUnits.push({ text, width: unit.width });\n }\n return resolvedUnits;\n}\n\nexport function joinPreparedUnitText(\n units: ReadonlyArray<{ text: string; width: number }>,\n start: number,\n end: number,\n): string {\n if (start >= end) {\n return \"\";\n }\n let text = \"\";\n for (let index = start; index < end; index += 1) {\n text += units[index]?.text ?? \"\";\n }\n return text;\n}\n\nexport function measureAtomsWidth(atoms: readonly InlineAtom[]): number {\n let total = 0;\n for (let index = 0; index < atoms.length; index += 1) {\n const atom = atoms[index];\n if (atom != null) {\n total += atom.width + atom.extraWidthAfter;\n }\n }\n return total;\n}\n\nexport function readPreparedInlineLayout(\n key: string,\n items: readonly SourceItem[],\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedInlineLayout {\n const cached = readLruValue(preparedInlineCache, key);\n if (cached != null) {\n return cached;\n }\n return writeLruValue(\n preparedInlineCache,\n key,\n buildPreparedInlineLayout(items, whiteSpace, wordBreak),\n PREPARED_INLINE_CACHE_CAPACITY,\n );\n}\n\nexport function getPlainPreparedKey(\n text: string,\n font: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): string {\n return `plain\\u0000${font}\\u0000${whiteSpace}\\u0000${wordBreak}\\u0000${text}`;\n}\n\nexport function getRichPreparedKey<C extends CanvasRenderingContext2D>(\n spans: readonly InlineSpan<C>[],\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): string {\n let key = \"\";\n for (let index = 0; index < spans.length; index += 1) {\n const span = spans[index]!;\n if (index > 0) {\n key += \"\\u0001\";\n }\n key += span.font ?? defaultFont;\n key += \"\\u0000\";\n key += span.text;\n key += \"\\u0000\";\n key += span.break ?? \"\";\n key += \"\\u0000\";\n key += span.extraWidth ?? 0;\n }\n key += \"\\u0002\";\n key += whiteSpace;\n key += \"\\u0002\";\n key += wordBreak;\n return key;\n}\n\nexport function createPlainSourceItems(text: string, font: string): SourceItem[] {\n return [{\n text,\n font,\n itemIndex: 0,\n breakMode: \"normal\",\n extraWidth: 0,\n }];\n}\n\nexport function createRichSourceItems<C extends CanvasRenderingContext2D>(\n spans: readonly InlineSpan<C>[],\n defaultFont: string,\n): SourceItem[] {\n return spans.map((span, index) => ({\n text: span.text,\n font: span.font ?? defaultFont,\n itemIndex: index,\n breakMode: span.break ?? \"normal\",\n extraWidth: span.extraWidth ?? 0,\n }));\n}\n","import type { Context, TextOverflowWrapMode, TextWhiteSpaceMode, TextWordBreakMode } from \"../types\";\nimport {\n createPlainSourceItems,\n getPlainPreparedKey,\n getPreparedLineStart,\n getPreparedUnits as getInlinePreparedUnits,\n joinPreparedUnitText,\n layoutNextPreparedLine,\n materializePreparedLineText,\n measurePreparedMinContentWidth as measureInlinePreparedMinContentWidth,\n readPreparedInlineLayout,\n type PreparedInlineLayout,\n} from \"./inline-engine\";\n\nexport const PREPARED_TEXT_CACHE_CAPACITY = 512;\n\nexport type PreparedTextWithSegments = PreparedInlineLayout;\n\nexport type PreparedTextUnit = {\n text: string;\n width: number;\n};\n\nexport function readPreparedText(\n text: string,\n font: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedTextWithSegments {\n return readPreparedInlineLayout(\n getPlainPreparedKey(text, font, whiteSpace, wordBreak),\n createPlainSourceItems(text, font),\n whiteSpace,\n wordBreak,\n );\n}\n\nexport function readPreparedFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): { text: string; prepared: PreparedTextWithSegments } | undefined {\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return undefined;\n }\n const line = layoutNextPreparedLine(prepared, start, Number.POSITIVE_INFINITY);\n if (line == null) {\n return undefined;\n }\n return {\n text: materializePreparedLineText(prepared, line),\n prepared,\n };\n}\n\nexport function measurePreparedMinContentWidth(\n prepared: PreparedTextWithSegments,\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n): number {\n return measureInlinePreparedMinContentWidth(prepared, overflowWrap);\n}\n\nexport function getPreparedUnits(prepared: PreparedTextWithSegments): PreparedTextUnit[] {\n return getInlinePreparedUnits(prepared);\n}\n\nexport function joinUnitText(units: readonly PreparedTextUnit[], start: number, end: number): string {\n return joinPreparedUnitText(units, start, end);\n}\n","import type {\n Context,\n TextEllipsisPosition,\n TextOverflowMode,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n ELLIPSIS_GLYPH,\n MIN_CONTENT_WIDTH_EPSILON,\n measureEllipsisWidth,\n measureFontShift,\n normalizeMaxLines,\n resolveEllipsisSelection,\n selectEllipsisUnitCounts,\n} from \"./core\";\nimport {\n forEachAtomFromCursorToEnd,\n flattenPreparedLineAtoms,\n getPreparedLineStart,\n layoutNextPreparedLine,\n materializePreparedLineText,\n measurePreparedLineStats,\n measurePreparedNaturalWidth,\n walkPreparedLineRanges,\n type InlineAtom,\n type PreparedInlineLineRange,\n} from \"./inline-engine\";\nimport {\n measurePreparedMinContentWidth,\n readPreparedText,\n type PreparedTextWithSegments,\n} from \"./plain-core\";\n\nexport interface TextLayout {\n width: number;\n text: string;\n shift: number;\n}\n\nexport interface TextMeasurement {\n width: number;\n lineCount: number;\n}\n\nexport interface OverflowTextLayout extends TextLayout {\n overflowed: boolean;\n}\n\nexport interface OverflowTextBlockLayout {\n width: number;\n lines: OverflowTextLayout[];\n overflowed: boolean;\n}\n\ntype TextBlockLayout = {\n width: number;\n lines: TextLayout[];\n};\n\nfunction measureTextLayoutWidth(lines: ArrayLike<{ width: number }>): number {\n let width = 0;\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line != null && line.width > width) {\n width = line.width;\n }\n }\n return width;\n}\n\nfunction clampMaxWidth(maxWidth: number): number {\n return Math.max(0, maxWidth);\n}\n\nfunction createEllipsisOnlyLayout<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n maxWidth: number,\n shift: number,\n): OverflowTextLayout {\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n return { width: ellipsisWidth, text: ELLIPSIS_GLYPH, shift, overflowed: true };\n}\n\nfunction toTextBlockLayout(lines: PreparedInlineLineRange[], prepared: PreparedTextWithSegments, shift: number): TextBlockLayout {\n const mappedLines: TextLayout[] = [];\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index]!;\n mappedLines.push({\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift,\n });\n }\n const width = measureTextLayoutWidth(mappedLines);\n return { width, lines: mappedLines };\n}\n\nfunction collectEllipsisLayout<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n atoms: readonly InlineAtom[],\n maxWidth: number,\n shift: number,\n position: TextEllipsisPosition,\n forceEllipsis = false,\n): OverflowTextLayout {\n const widths: number[] = [];\n let intrinsicWidth = 0;\n for (let index = 0; index < atoms.length; index += 1) {\n const atom = atoms[index]!;\n const width = atom.width + atom.extraWidthAfter;\n widths.push(width);\n intrinsicWidth += width;\n }\n if (!forceEllipsis && intrinsicWidth <= maxWidth) {\n return {\n width: intrinsicWidth,\n text: atoms.map((atom) => atom.text).join(\"\"),\n shift,\n overflowed: false,\n };\n }\n\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n if (atoms.length === 0) {\n return createEllipsisOnlyLayout(ctx, maxWidth, shift);\n }\n\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position,\n });\n if (selection == null) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n const { prefixCount, suffixCount, width } = selection;\n\n const prefixText = atoms.slice(0, prefixCount).map((atom) => atom.text).join(\"\");\n const suffixText = atoms.slice(atoms.length - suffixCount).map((atom) => atom.text).join(\"\");\n\n return {\n width,\n text:\n position === \"start\"\n ? `${ELLIPSIS_GLYPH}${suffixText}`\n : position === \"middle\"\n ? `${prefixText}${ELLIPSIS_GLYPH}${suffixText}`\n : `${prefixText}${ELLIPSIS_GLYPH}`,\n shift,\n overflowed: true,\n };\n}\n\nfunction getFirstLineRange(prepared: PreparedTextWithSegments): PreparedInlineLineRange | undefined {\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return undefined;\n }\n return layoutNextPreparedLine(prepared, start, Number.POSITIVE_INFINITY) ?? undefined;\n}\n\nfunction walkLines(prepared: PreparedTextWithSegments, maxWidth: number): PreparedInlineLineRange[] {\n const lines: PreparedInlineLineRange[] = [];\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n lines.push(line);\n });\n return lines;\n}\n\nfunction collectVisibleLines(\n prepared: PreparedTextWithSegments,\n maxWidth: number,\n maxLines: number,\n): { lines: PreparedInlineLineRange[]; overflowed: boolean } {\n const lines: PreparedInlineLineRange[] = [];\n let overflowed = false;\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n if (lines.length < maxLines) {\n lines.push(line);\n return true;\n }\n overflowed = true;\n return false;\n });\n return { lines, overflowed };\n}\n\nfunction collectEndEllipsisLayoutFromCursor<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n prepared: PreparedTextWithSegments,\n start: PreparedInlineLineRange[\"start\"],\n maxWidth: number,\n shift: number,\n): OverflowTextLayout {\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n\n const widths: number[] = [];\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n widths.push(atom.width + atom.extraWidthAfter);\n });\n\n if (widths.length === 0) {\n return createEllipsisOnlyLayout(ctx, maxWidth, shift);\n }\n\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position: \"end\",\n });\n if (selection == null) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n const { prefixCount, width } = selection;\n\n let text = \"\";\n let atomIndex = 0;\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n if (atomIndex < prefixCount) {\n text += atom.text;\n }\n atomIndex += 1;\n });\n\n return {\n width,\n text: `${text}${ELLIPSIS_GLYPH}`,\n shift,\n overflowed: true,\n };\n}\n\nfunction layoutForcedEllipsizedLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n prepared: PreparedTextWithSegments,\n line: PreparedInlineLineRange,\n maxWidth: number,\n shift: number,\n): OverflowTextLayout {\n return collectEllipsisLayout(ctx, flattenPreparedLineAtoms(prepared, line), maxWidth, shift, \"end\", true);\n}\n\nexport function layoutFirstLineIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextLayout {\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const line = getFirstLineRange(prepared);\n if (line == null) {\n return { width: 0, text: \"\", shift: 0 };\n }\n return {\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift: measureFontShift(ctx),\n };\n}\n\nexport function measureTextIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextMeasurement {\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(prepared, Number.POSITIVE_INFINITY);\n return { width, lineCount };\n}\n\nexport function layoutTextIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextBlockLayout {\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const lines = walkLines(prepared, Number.POSITIVE_INFINITY);\n return toTextBlockLayout(lines, prepared, measureFontShift(ctx));\n}\n\nexport function layoutFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n const shift = measureFontShift(ctx);\n if (clampedMaxWidth === 0) {\n return { width: 0, text: \"\", shift };\n }\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return { width: 0, text: \"\", shift };\n }\n const line = layoutNextPreparedLine(prepared, start, clampedMaxWidth);\n if (line == null) {\n return { width: 0, text: \"\", shift };\n }\n return {\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift,\n };\n}\n\nexport function layoutEllipsizedFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n ellipsisPosition: TextEllipsisPosition = \"end\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): OverflowTextLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n const shift = measureFontShift(ctx);\n if (clampedMaxWidth === 0) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const intrinsicLine = getFirstLineRange(prepared);\n if (intrinsicLine == null) {\n return { width: 0, text: \"\", shift: 0, overflowed: false };\n }\n return collectEllipsisLayout(\n ctx,\n flattenPreparedLineAtoms(prepared, intrinsicLine),\n clampedMaxWidth,\n shift,\n ellipsisPosition,\n );\n}\n\nexport function measureText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextMeasurement {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n if (clampedMaxWidth === 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(prepared, clampedMaxWidth);\n return { width, lineCount };\n}\n\nexport function measureTextMinContent<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n): TextMeasurement {\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const width = measurePreparedMinContentWidth(prepared, overflowWrap);\n if (width === 0) {\n return { width: 0, lineCount: 0 };\n }\n const { lineCount } = measurePreparedLineStats(prepared, Math.max(width, MIN_CONTENT_WIDTH_EPSILON));\n return { width, lineCount };\n}\n\nexport function layoutText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextBlockLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n if (clampedMaxWidth === 0) {\n return { width: 0, lines: [] };\n }\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const lines = walkLines(prepared, clampedMaxWidth);\n return toTextBlockLayout(lines, prepared, measureFontShift(ctx));\n}\n\nexport function layoutTextWithOverflow<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n options: {\n whiteSpace?: TextWhiteSpaceMode;\n wordBreak?: TextWordBreakMode;\n overflow?: TextOverflowMode;\n maxLines?: number;\n } = {},\n): OverflowTextBlockLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n const whiteSpace = options.whiteSpace ?? \"normal\";\n const wordBreak = options.wordBreak ?? \"normal\";\n const overflow = options.overflow ?? \"clip\";\n const normalizedMaxLines = normalizeMaxLines(options.maxLines);\n\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n const shift = measureFontShift(ctx);\n if (normalizedMaxLines == null) {\n const lines = walkLines(prepared, clampedMaxWidth);\n const layout = toTextBlockLayout(lines, prepared, shift);\n return {\n width: layout.width,\n lines: layout.lines.map((line) => ({ ...line, overflowed: false })),\n overflowed: false,\n };\n }\n\n const { lines: visibleRanges, overflowed } = collectVisibleLines(prepared, clampedMaxWidth, normalizedMaxLines);\n if (!overflowed) {\n const layout = toTextBlockLayout(visibleRanges, prepared, shift);\n return {\n width: layout.width,\n lines: layout.lines.map((line) => ({ ...line, overflowed: false })),\n overflowed: false,\n };\n }\n const visibleLines = visibleRanges.map((line) => ({\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift,\n overflowed: false,\n }));\n\n if (overflow !== \"ellipsis\") {\n return {\n width: measureTextLayoutWidth(visibleLines),\n lines: visibleLines,\n overflowed: true,\n };\n }\n\n const lastVisibleRange = visibleRanges[visibleRanges.length - 1];\n const ellipsizedLastLine = lastVisibleRange == null\n ? createEllipsisOnlyLayout(ctx, clampedMaxWidth, shift)\n : collectEndEllipsisLayoutFromCursor(ctx, prepared, lastVisibleRange.start, clampedMaxWidth, shift);\n\n const mergedLines = [\n ...visibleLines.slice(0, -1),\n ellipsizedLastLine,\n ];\n return {\n width: measureTextLayoutWidth(mergedLines),\n lines: mergedLines,\n overflowed: true,\n };\n}\n\nexport function measureTextNaturalWidth<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): number {\n const prepared = readPreparedText(text, ctx.graphics.font, whiteSpace, wordBreak);\n return measurePreparedNaturalWidth(prepared);\n}\n","import type {\n Context,\n DynValue,\n InlineSpan,\n TextEllipsisPosition,\n TextOverflowMode,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n ELLIPSIS_GLYPH,\n MIN_CONTENT_WIDTH_EPSILON,\n measureEllipsisWidth,\n measureFontShift,\n normalizeMaxLines,\n resolveEllipsisSelection,\n selectEllipsisUnitCounts,\n} from \"./core\";\nimport {\n collectAtomsInRange,\n createRichSourceItems,\n forEachAtomFromCursorToEnd,\n forEachAtomInRange,\n getPreparedLineStart,\n getRichPreparedKey,\n layoutNextPreparedLine,\n materializePreparedLineText,\n measureAtomsWidth,\n measurePreparedLineStats,\n walkPreparedLineRanges,\n type InlineAtom,\n type PreparedInlineLayout,\n type PreparedInlineLineRange,\n} from \"./inline-engine\";\nimport { measurePreparedMinContentWidth, readPreparedInlineLayout } from \"./inline-engine\";\n\nexport interface RichFragmentLayout {\n itemIndex: number;\n text: string;\n font: string;\n color: DynValue<any, string> | undefined;\n gapBefore: number;\n gapAtomCount: number;\n gapSpaceCount: number;\n occupiedWidth: number;\n atomCount: number;\n spaceCount: number;\n shift: number;\n}\n\nexport interface RichLineLayout {\n width: number;\n fragments: RichFragmentLayout[];\n overflowed: boolean;\n}\n\nexport interface RichBlockLayout {\n width: number;\n lines: RichLineLayout[];\n overflowed: boolean;\n}\n\nexport interface RichMeasurement {\n width: number;\n lineCount: number;\n}\n\ntype PendingRichGap = {\n gapBefore: number;\n gapAtomCount: number;\n gapSpaceCount: number;\n};\n\nfunction measureRichBlockWidth(lines: ArrayLike<{ width: number }>): number {\n let width = 0;\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line != null && line.width > width) {\n width = line.width;\n }\n }\n return width;\n}\n\nfunction withFont<C extends CanvasRenderingContext2D, T>(ctx: Context<C>, font: string, cb: () => T): T {\n const previousFont = ctx.graphics.font;\n ctx.graphics.font = font;\n try {\n return cb();\n } finally {\n ctx.graphics.font = previousFont;\n }\n}\n\nfunction readRichPrepared<C extends CanvasRenderingContext2D>(\n spans: InlineSpan<C>[],\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedInlineLayout {\n return readPreparedInlineLayout(\n getRichPreparedKey(spans, defaultFont, whiteSpace, wordBreak),\n createRichSourceItems(spans, defaultFont),\n whiteSpace,\n wordBreak,\n );\n}\n\nfunction measureRichFragmentShift<C extends CanvasRenderingContext2D>(ctx: Context<C>, font: string): number {\n return withFont(ctx, font, () => measureFontShift(ctx));\n}\n\nfunction materializeRichFragments<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n atoms: readonly InlineAtom[],\n): RichFragmentLayout[] {\n const fragments: RichFragmentLayout[] = [];\n let pendingGap: PendingRichGap = { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n\n for (const atom of atoms) {\n pendingGap = appendRichFragment(ctx, spans, defaultColor, fragments, atom, pendingGap);\n }\n\n return fragments;\n}\n\nfunction appendRichFragment<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n fragments: RichFragmentLayout[],\n atom: InlineAtom,\n pendingGap: PendingRichGap,\n): PendingRichGap {\n const occupiedWidth = atom.width + atom.extraWidthAfter;\n if (atom.kind === \"space\" && !atom.preservesLineEnd && atom.atomicGroupId == null) {\n return {\n gapBefore: pendingGap.gapBefore + occupiedWidth,\n gapAtomCount: pendingGap.gapAtomCount + 1,\n gapSpaceCount: pendingGap.gapSpaceCount + 1,\n };\n }\n\n const span = spans[atom.itemIndex];\n const font = span?.font ?? atom.font;\n const color = span?.color ?? defaultColor;\n const previous = fragments[fragments.length - 1];\n const spaceCount = atom.kind === \"space\" ? 1 : 0;\n if (previous != null && previous.itemIndex === atom.itemIndex && previous.font === font && pendingGap.gapBefore === 0) {\n previous.text += atom.text;\n previous.occupiedWidth += occupiedWidth;\n previous.atomCount += 1;\n previous.spaceCount += spaceCount;\n return { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n }\n\n fragments.push({\n itemIndex: atom.itemIndex,\n text: atom.text,\n font,\n color: color as DynValue<any, string>,\n gapBefore: pendingGap.gapBefore,\n gapAtomCount: pendingGap.gapAtomCount,\n gapSpaceCount: pendingGap.gapSpaceCount,\n occupiedWidth,\n atomCount: 1,\n spaceCount,\n shift: measureRichFragmentShift(ctx, font),\n });\n return { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n}\n\nfunction materializeRichFragmentsInRange<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n prepared: PreparedInlineLayout,\n start: PreparedInlineLineRange[\"start\"],\n end: PreparedInlineLineRange[\"end\"],\n): RichFragmentLayout[] {\n const fragments: RichFragmentLayout[] = [];\n let pendingGap: PendingRichGap = { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n forEachAtomInRange(prepared, start, end, (atom) => {\n pendingGap = appendRichFragment(ctx, spans, defaultColor, fragments, atom, pendingGap);\n });\n return fragments;\n}\n\nfunction materializeRichLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n overflowed: boolean,\n): RichLineLayout {\n return {\n width: line.width,\n fragments: materializeRichFragmentsInRange(ctx, spans, defaultColor, prepared, line.start, line.end),\n overflowed,\n };\n}\n\nfunction getFirstLineRange(prepared: PreparedInlineLayout): PreparedInlineLineRange | undefined {\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return undefined;\n }\n return layoutNextPreparedLine(prepared, start, Number.POSITIVE_INFINITY) ?? undefined;\n}\n\nfunction walkLines(prepared: PreparedInlineLayout, maxWidth: number): PreparedInlineLineRange[] {\n const lines: PreparedInlineLineRange[] = [];\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n lines.push(line);\n });\n return lines;\n}\n\nfunction collectVisibleLines(\n prepared: PreparedInlineLayout,\n maxWidth: number,\n maxLines: number,\n): { lines: PreparedInlineLineRange[]; overflowed: boolean } {\n const lines: PreparedInlineLineRange[] = [];\n let overflowed = false;\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n if (lines.length < maxLines) {\n lines.push(line);\n return true;\n }\n overflowed = true;\n return false;\n });\n return { lines, overflowed };\n}\n\nfunction createRichEllipsisFragment<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n font: string,\n color: DynValue<C, string>,\n): RichFragmentLayout {\n return withFont(ctx, font, () => ({\n itemIndex: -1,\n text: ELLIPSIS_GLYPH,\n font,\n color,\n gapBefore: 0,\n gapAtomCount: 0,\n gapSpaceCount: 0,\n occupiedWidth: measureEllipsisWidth(ctx),\n atomCount: 1,\n spaceCount: 0,\n shift: measureFontShift(ctx),\n }));\n}\n\nfunction createRichEllipsisOnlyLayout<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n maxWidth: number,\n font: string,\n color: DynValue<C, string>,\n): RichLineLayout {\n const fragment = createRichEllipsisFragment(ctx, font, color);\n if (fragment.occupiedWidth > maxWidth) {\n return { width: 0, fragments: [], overflowed: true };\n }\n return { width: fragment.occupiedWidth, fragments: [fragment], overflowed: true };\n}\n\nfunction layoutRichEllipsisFromAtoms<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n atoms: readonly InlineAtom[],\n maxWidth: number,\n position: TextEllipsisPosition,\n forceEllipsis = false,\n): RichLineLayout {\n const intrinsicWidth = measureAtomsWidth(atoms);\n if (!forceEllipsis && intrinsicWidth <= maxWidth) {\n return {\n width: intrinsicWidth,\n fragments: materializeRichFragments(ctx, spans, defaultColor, atoms),\n overflowed: false,\n };\n }\n\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, fragments: [], overflowed: true };\n }\n if (atoms.length === 0) {\n return createRichEllipsisOnlyLayout(ctx, maxWidth, defaultFont, defaultColor);\n }\n\n const widths = atoms.map((atom) => atom.width + atom.extraWidthAfter);\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position,\n });\n if (selection == null) {\n return { width: 0, fragments: [], overflowed: true };\n }\n const { prefixCount, suffixCount, width } = selection;\n\n const prefixAtoms = atoms.slice(0, prefixCount);\n const suffixAtoms = atoms.slice(atoms.length - suffixCount);\n const ellipsisSource =\n position === \"start\"\n ? (suffixAtoms[0] ?? atoms[0])\n : position === \"middle\"\n ? (prefixAtoms[prefixAtoms.length - 1] ?? suffixAtoms[0] ?? atoms[atoms.length - 1])\n : (prefixAtoms[prefixAtoms.length - 1] ?? atoms[atoms.length - 1]);\n const ellipsisSpan = ellipsisSource == null ? undefined : spans[ellipsisSource.itemIndex];\n const ellipsisFragment = createRichEllipsisFragment(\n ctx,\n ellipsisSpan?.font ?? ellipsisSource?.font ?? defaultFont,\n (ellipsisSpan?.color ?? defaultColor) as DynValue<C, string>,\n );\n const prefixFragments = materializeRichFragments(ctx, spans, defaultColor, prefixAtoms);\n const suffixFragments = materializeRichFragments(ctx, spans, defaultColor, suffixAtoms);\n\n return {\n width,\n fragments:\n position === \"start\"\n ? [ellipsisFragment, ...suffixFragments]\n : position === \"middle\"\n ? [...prefixFragments, ellipsisFragment, ...suffixFragments]\n : [...prefixFragments, ellipsisFragment],\n overflowed: true,\n };\n}\n\nfunction layoutRichEndEllipsisFromCursor<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n prepared: PreparedInlineLayout,\n start: PreparedInlineLineRange[\"start\"],\n maxWidth: number,\n): RichLineLayout {\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, fragments: [], overflowed: true };\n }\n\n const widths: number[] = [];\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n widths.push(atom.width + atom.extraWidthAfter);\n });\n\n if (widths.length === 0) {\n return createRichEllipsisOnlyLayout(ctx, maxWidth, defaultFont, defaultColor);\n }\n\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position: \"end\",\n });\n if (selection == null) {\n return { width: 0, fragments: [], overflowed: true };\n }\n const { prefixCount, width } = selection;\n\n const fragments: RichFragmentLayout[] = [];\n let atomIndex = 0;\n let pendingGap: PendingRichGap = { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n let lastVisibleAtom: InlineAtom | undefined;\n let lastAtom: InlineAtom | undefined;\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n lastAtom = atom;\n if (atomIndex < prefixCount) {\n pendingGap = appendRichFragment(ctx, spans, defaultColor, fragments, atom, pendingGap);\n lastVisibleAtom = atom;\n }\n atomIndex += 1;\n });\n\n const ellipsisSource = lastVisibleAtom ?? lastAtom;\n const ellipsisSpan = ellipsisSource == null ? undefined : spans[ellipsisSource.itemIndex];\n fragments.push(createRichEllipsisFragment(\n ctx,\n ellipsisSpan?.font ?? ellipsisSource?.font ?? defaultFont,\n (ellipsisSpan?.color ?? defaultColor) as DynValue<C, string>,\n ));\n\n return {\n width,\n fragments,\n overflowed: true,\n };\n}\n\nexport function layoutRichFirstLineIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichLineLayout {\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const line = getFirstLineRange(prepared);\n if (line == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n return materializeRichLine(ctx, spans, defaultColor, prepared, line, false);\n}\n\nexport function layoutRichFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichLineLayout {\n const clampedMaxWidth = Math.max(0, maxWidth);\n if (clampedMaxWidth === 0 || spans.length === 0) {\n return { width: 0, fragments: [], overflowed: false };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n const line = layoutNextPreparedLine(prepared, start, clampedMaxWidth);\n if (line == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n return materializeRichLine(ctx, spans, defaultColor, prepared, line, false);\n}\n\nexport function layoutRichEllipsizedFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n ellipsisPosition: TextEllipsisPosition = \"end\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichLineLayout {\n const clampedMaxWidth = Math.max(0, maxWidth);\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const intrinsicLine = getFirstLineRange(prepared);\n if (intrinsicLine == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n if (clampedMaxWidth === 0) {\n return { width: 0, fragments: [], overflowed: true };\n }\n return layoutRichEllipsisFromAtoms(\n ctx,\n spans,\n defaultFont,\n defaultColor,\n collectAtomsInRange(prepared, intrinsicLine.start, intrinsicLine.end),\n clampedMaxWidth,\n ellipsisPosition,\n );\n}\n\nexport function measureRichText<C extends CanvasRenderingContext2D>(\n _ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichMeasurement {\n if (spans.length === 0 || maxWidth <= 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(prepared, maxWidth);\n return { width, lineCount };\n}\n\nexport function measureRichTextIntrinsic<C extends CanvasRenderingContext2D>(\n _ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichMeasurement {\n if (spans.length === 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(prepared, Number.POSITIVE_INFINITY);\n return { width, lineCount };\n}\n\nexport function measureRichTextMinContent<C extends CanvasRenderingContext2D>(\n _ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichMeasurement {\n if (spans.length === 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const width = measurePreparedMinContentWidth(prepared, overflowWrap);\n if (width === 0) {\n return { width: 0, lineCount: 0 };\n }\n const { lineCount } = measurePreparedLineStats(prepared, Math.max(width, MIN_CONTENT_WIDTH_EPSILON));\n return { width, lineCount };\n}\n\nexport function layoutRichText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichBlockLayout {\n if (spans.length === 0 || maxWidth <= 0) {\n return { width: 0, lines: [], overflowed: false };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const lines = walkLines(prepared, maxWidth).map((line) => materializeRichLine(ctx, spans, defaultColor, prepared, line, false));\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n}\n\nexport function layoutRichTextIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichBlockLayout {\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const lines = walkLines(prepared, Number.POSITIVE_INFINITY).map((line) =>\n materializeRichLine(ctx, spans, defaultColor, prepared, line, false)\n );\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n}\n\nexport function layoutRichTextWithOverflow<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n maxLines?: number,\n overflow: TextOverflowMode = \"clip\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichBlockLayout {\n if (spans.length === 0 || maxWidth <= 0) {\n return { width: 0, lines: [], overflowed: false };\n }\n const normalizedMaxLines = normalizeMaxLines(maxLines);\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n if (normalizedMaxLines == null) {\n const lineRanges = walkLines(prepared, maxWidth);\n const lines = lineRanges.map((line) => materializeRichLine(ctx, spans, defaultColor, prepared, line, false));\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n }\n const { lines: visibleRanges, overflowed } = collectVisibleLines(prepared, maxWidth, normalizedMaxLines);\n if (!overflowed) {\n const lines = visibleRanges.map((line) => materializeRichLine(ctx, spans, defaultColor, prepared, line, false));\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n }\n const visibleLines = visibleRanges.map((line) => materializeRichLine(ctx, spans, defaultColor, prepared, line, false));\n if (overflow !== \"ellipsis\") {\n return {\n width: measureRichBlockWidth(visibleLines),\n lines: visibleLines,\n overflowed: true,\n };\n }\n\n const lastVisibleRange = visibleRanges[visibleRanges.length - 1];\n const ellipsizedLastLine = lastVisibleRange == null\n ? { width: 0, fragments: [], overflowed: true }\n : layoutRichEndEllipsisFromCursor(ctx, spans, defaultFont, defaultColor, prepared, lastVisibleRange.start, maxWidth);\n const lines = [...visibleLines.slice(0, -1), ellipsizedLastLine];\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: true,\n };\n}\n\nexport function materializeRichLineText(line: RichLineLayout): string {\n return line.fragments.map((fragment) => fragment.text).join(\"\");\n}\n\nexport function materializePreparedRichLineText(prepared: PreparedInlineLayout, line: PreparedInlineLineRange): string {\n return materializePreparedLineText(prepared, line);\n}\n","import type { TextJustifyMode } from \"../types\";\nimport {\n forEachAtomInRange,\n isCJK,\n type PreparedInlineLayout,\n type PreparedInlineLineRange,\n} from \"./inline-engine\";\n\n// -------- Feature detection --------\n\nlet _justifySupported: boolean | undefined;\n\nexport function isJustifySupported(ctx: CanvasRenderingContext2D): boolean {\n if (_justifySupported !== undefined) return _justifySupported;\n _justifySupported =\n typeof (ctx as any).wordSpacing === \"string\" &&\n typeof (ctx as any).letterSpacing === \"string\";\n return _justifySupported;\n}\n\n/** Reset cached detection result (for testing). */\nexport function resetJustifySupportedCache(): void {\n _justifySupported = undefined;\n}\n\n// -------- Mode resolution --------\n\nexport type ResolvedJustifyMode = TextJustifyMode | null;\n\nexport function resolveJustifyMode(\n justify: boolean | TextJustifyMode | undefined,\n): ResolvedJustifyMode {\n if (justify === true) return \"inter-word\";\n if (justify === \"inter-word\" || justify === \"inter-character\") return justify;\n return null;\n}\n\n// -------- Line analysis --------\n\nconst HYBRID_WORD_SHARE_CANDIDATES = [\n 0.15,\n 0.20,\n 0.25,\n 0.30,\n 0.35,\n 0.40,\n 0.45,\n 0.50,\n 0.55,\n 0.60,\n 0.65,\n 0.70,\n 0.75,\n 0.80,\n 0.85,\n 1.0,\n 0.0,\n] as const;\n\nconst PUNCTUATION_OR_SYMBOL_PATTERN = /^[\\p{P}\\p{S}]$/u;\nconst JUSTIFY_SCORE_EPSILON = 1e-9;\n\nexport interface JustifyLineInfo {\n /** Number of word gaps (space units) in the line. */\n wordGapCount: number;\n /** Number of visible non-space runs in the line. */\n wordCount: number;\n /** Total number of visible atoms that receive letter spacing. */\n renderAtomCount: number;\n /** Total number of inter-atom gaps that receive letter spacing. */\n letterGapCount: number;\n /** Total number of visible space atoms. */\n spaceCount: number;\n /** Total number of visible non-space atoms. */\n nonSpaceCount: number;\n /** Number of visible CJK atoms. */\n cjkCount: number;\n /** Number of visible non-space Latin-like atoms. */\n latinLikeCount: number;\n /** Number of visible non-space punctuation/symbol atoms. */\n punctuationCount: number;\n /** Visible line width before justification. */\n lineWidth: number;\n /** Visible width excluding space atoms. */\n nonSpaceWidth: number;\n}\n\nexport function analyzeLineForJustify(\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n): JustifyLineInfo {\n let wordGapCount = 0;\n let wordCount = 0;\n let renderAtomCount = 0;\n let spaceCount = 0;\n let nonSpaceCount = 0;\n let cjkCount = 0;\n let latinLikeCount = 0;\n let punctuationCount = 0;\n let nonSpaceWidth = 0;\n let insideWord = false;\n\n forEachAtomInRange(prepared, line.start, line.end, (atom) => {\n if (atom.kind === \"space\" && !atom.preservesLineEnd && atom.atomicGroupId == null) {\n wordGapCount++;\n }\n renderAtomCount++;\n if (atom.kind === \"space\") {\n spaceCount++;\n insideWord = false;\n return;\n }\n\n nonSpaceCount++;\n nonSpaceWidth += atom.width + atom.extraWidthAfter;\n\n if (!insideWord) {\n wordCount++;\n insideWord = true;\n }\n\n if (isCJK(atom.text)) {\n cjkCount++;\n return;\n }\n if (PUNCTUATION_OR_SYMBOL_PATTERN.test(atom.text)) {\n punctuationCount++;\n return;\n }\n latinLikeCount++;\n });\n\n return {\n wordGapCount,\n wordCount,\n renderAtomCount,\n letterGapCount: Math.max(renderAtomCount - 1, 0),\n spaceCount,\n nonSpaceCount,\n cjkCount,\n latinLikeCount,\n punctuationCount,\n lineWidth: line.width,\n nonSpaceWidth,\n };\n}\n\nfunction getAverageWordWidth(info: JustifyLineInfo): number {\n return info.wordCount > 0 ? info.nonSpaceWidth / info.wordCount : info.lineWidth;\n}\n\nfunction getAverageCharWidth(info: JustifyLineInfo): number {\n return info.renderAtomCount > 0 ? info.lineWidth / info.renderAtomCount : info.lineWidth;\n}\n\nfunction resolvePerGapSpacing(totalSpace: number, gapCount: number): number | null {\n if (totalSpace === 0) {\n return 0;\n }\n if (gapCount <= 0) {\n return null;\n }\n return totalSpace / gapCount;\n}\n\nfunction exceedsThreshold(perGap: number, averageWidth: number, threshold: number): boolean {\n if (!Number.isFinite(threshold)) {\n return false;\n }\n return perGap > threshold * averageWidth;\n}\n\nfunction createJustifySpacing(wordSpacingPx: number, letterSpacingPx: number): JustifySpacing {\n return {\n wordSpacing: `${wordSpacingPx}px`,\n letterSpacing: `${letterSpacingPx}px`,\n wordSpacingPx,\n letterSpacingPx,\n };\n}\n\n// -------- Threshold check --------\n\nexport function shouldJustifyLine(\n lineWidth: number,\n maxWidth: number,\n info: JustifyLineInfo,\n mode: ResolvedJustifyMode,\n threshold: number,\n): boolean {\n return computeJustifySpacing(lineWidth, maxWidth, info, mode, threshold) != null;\n}\n\n// -------- Spacing computation --------\n\nexport interface JustifySpacing {\n wordSpacing: string;\n letterSpacing: string;\n wordSpacingPx: number;\n letterSpacingPx: number;\n}\n\nexport function computeJustifySpacing(\n lineWidth: number,\n maxWidth: number,\n info: JustifyLineInfo,\n mode: ResolvedJustifyMode,\n threshold = Number.POSITIVE_INFINITY,\n): JustifySpacing | null {\n const extraSpace = maxWidth - lineWidth;\n if (extraSpace <= 0 || mode == null) {\n return null;\n }\n\n if (mode === \"inter-word\" && info.wordGapCount > 0) {\n const perGap = extraSpace / info.wordGapCount;\n const avgWordWidth = Math.max(getAverageWordWidth(info), Number.EPSILON);\n if (exceedsThreshold(perGap, avgWordWidth, threshold)) {\n return null;\n }\n return createJustifySpacing(perGap, 0);\n }\n\n if (mode !== \"inter-character\" || info.renderAtomCount === 0) {\n return null;\n }\n\n const avgCharWidth = Math.max(getAverageCharWidth(info), Number.EPSILON);\n if (info.wordGapCount === 0) {\n const perGap = resolvePerGapSpacing(extraSpace, info.letterGapCount);\n if (perGap == null) {\n return null;\n }\n if (exceedsThreshold(perGap, avgCharWidth, threshold)) {\n return null;\n }\n return createJustifySpacing(0, perGap);\n }\n\n const avgWordWidth = Math.max(getAverageWordWidth(info), Number.EPSILON);\n const nonSpaceCount = Math.max(info.nonSpaceCount, 1);\n const cjkRatio = info.cjkCount / nonSpaceCount;\n const latinLikeRatio = info.latinLikeCount / nonSpaceCount;\n const punctuationRatio = info.punctuationCount / nonSpaceCount;\n const wordPenalty = 1 + cjkRatio;\n const letterPenalty = 1 + latinLikeRatio + 0.5 * punctuationRatio;\n\n let bestCandidate:\n | {\n spacing: JustifySpacing;\n score: number;\n wordShare: number;\n }\n | null = null;\n\n for (const wordShare of HYBRID_WORD_SHARE_CANDIDATES) {\n const wordExtraSpace = extraSpace * wordShare;\n const letterExtraSpace = extraSpace - wordExtraSpace;\n const wordSpacingPx = resolvePerGapSpacing(wordExtraSpace, info.wordGapCount);\n const letterSpacingPx = resolvePerGapSpacing(letterExtraSpace, info.letterGapCount);\n if (wordSpacingPx == null || letterSpacingPx == null) {\n continue;\n }\n if (\n exceedsThreshold(wordSpacingPx, avgWordWidth, threshold)\n || exceedsThreshold(letterSpacingPx, avgCharWidth, threshold)\n ) {\n continue;\n }\n\n const wordRatio = wordSpacingPx / avgWordWidth;\n const letterRatio = letterSpacingPx / avgCharWidth;\n const score = wordPenalty * (wordRatio ** 2) + letterPenalty * (letterRatio ** 2);\n if (\n bestCandidate == null\n || score < bestCandidate.score - JUSTIFY_SCORE_EPSILON\n || (\n Math.abs(score - bestCandidate.score) <= JUSTIFY_SCORE_EPSILON\n && wordShare > bestCandidate.wordShare\n )\n ) {\n bestCandidate = {\n spacing: createJustifySpacing(wordSpacingPx, letterSpacingPx),\n score,\n wordShare,\n };\n }\n }\n\n return bestCandidate?.spacing ?? null;\n}\n","import {\n layoutEllipsizedFirstLine,\n layoutFirstLine,\n layoutFirstLineIntrinsic,\n layoutRichEllipsizedFirstLine,\n layoutRichFirstLine,\n layoutRichFirstLineIntrinsic,\n layoutRichText,\n layoutRichTextIntrinsic,\n layoutRichTextWithOverflow,\n layoutText,\n layoutTextIntrinsic,\n layoutTextWithOverflow,\n measureRichText,\n measureRichTextIntrinsic,\n measureRichTextMinContent,\n measureText,\n measureTextMinContent,\n measureTextIntrinsic,\n type RichBlockLayout,\n type RichLineLayout,\n type RichMeasurement,\n type TextLayout,\n type TextMeasurement,\n analyzeLineForJustify,\n computeJustifySpacing,\n isJustifySupported,\n resolveJustifyMode,\n} from \"../text\";\nimport { readPreparedText } from \"../text/plain-core\";\nimport { readPreparedInlineLayout, createRichSourceItems, getRichPreparedKey, walkPreparedLineRanges } from \"../text/inline-engine\";\nimport type { Box, Context, InlineSpan, MultilineTextOptions, Node, PhysicalTextAlign, TextOptions } from \"../types\";\n\ntype SingleLineLayout = TextLayout;\ntype MultiLineDrawLayout = {\n width: number;\n lines: TextLayout[];\n};\ntype MultiLineMeasureLayout = TextMeasurement;\n\ntype TextLayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getTextLayout<T>(node: Node<C>, key: string): T | undefined;\n setTextLayout<T>(node: Node<C>, key: string, layout: T): void;\n};\n\nfunction resolvePhysicalTextAlign(\n options: Pick<MultilineTextOptions<any>, \"align\" | \"physicalAlign\">,\n): PhysicalTextAlign {\n if (options.physicalAlign != null) {\n return options.physicalAlign;\n }\n if (options.align != null) {\n switch (options.align) {\n case \"start\":\n return \"left\";\n case \"center\":\n return \"center\";\n case \"end\":\n return \"right\";\n }\n }\n return \"left\";\n}\n\nfunction normalizeTextMaxWidth(maxWidth: number | undefined): number | undefined {\n if (maxWidth == null) {\n return undefined;\n }\n return Math.max(0, maxWidth);\n}\n\nconst DEFAULT_TEXT_SPACING = {\n wordSpacing: \"0px\",\n letterSpacing: \"0px\",\n} as const;\n\nfunction supportsTextSpacing(g: CanvasRenderingContext2D): g is CanvasRenderingContext2D & {\n wordSpacing: string;\n letterSpacing: string;\n} {\n return typeof (g as any).wordSpacing === \"string\" && typeof (g as any).letterSpacing === \"string\";\n}\n\nfunction withTextSpacing<C extends CanvasRenderingContext2D, T>(\n g: C,\n spacing: { wordSpacing: string; letterSpacing: string },\n cb: () => T,\n): T {\n if (!supportsTextSpacing(g)) {\n return cb();\n }\n const savedWordSpacing = g.wordSpacing;\n const savedLetterSpacing = g.letterSpacing;\n try {\n g.wordSpacing = spacing.wordSpacing;\n g.letterSpacing = spacing.letterSpacing;\n return cb();\n } finally {\n g.wordSpacing = savedWordSpacing;\n g.letterSpacing = savedLetterSpacing;\n }\n}\n\nfunction getTextLayoutContext<C extends CanvasRenderingContext2D>(ctx: Context<C>): Context<C> & TextLayoutCacheAccess<C> {\n return ctx as Context<C> & TextLayoutCacheAccess<C>;\n}\n\nfunction readCachedTextLayout<C extends CanvasRenderingContext2D, T>(\n node: Node<C>,\n ctx: Context<C>,\n key: string,\n compute: () => T,\n): T {\n const textCtx = getTextLayoutContext(ctx);\n const cached = textCtx.getTextLayout<T>(node, key);\n if (cached != null) {\n return cached;\n }\n const layout = compute();\n textCtx.setTextLayout(node, key, layout);\n return layout;\n}\n\nfunction getSingleLineLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"single:intrinsic\" : `single:${maxWidth}`;\n}\n\nfunction getMultiLineMeasureLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"multi:measure:intrinsic\" : `multi:measure:${maxWidth}`;\n}\n\nfunction getRichMultiLineMeasureLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"rich:measure:intrinsic\" : `rich:measure:${maxWidth}`;\n}\n\nfunction getMultiLineDrawLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"multi:draw:intrinsic\" : `multi:draw:${maxWidth}`;\n}\n\nfunction getRichMultiLineDrawLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"rich:draw:intrinsic\" : `rich:draw:${maxWidth}`;\n}\n\nfunction getMultiLineOverflowLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"multi:overflow:intrinsic\" : `multi:overflow:${maxWidth}`;\n}\n\nfunction getRichMultiLineOverflowLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"rich:overflow:intrinsic\" : `rich:overflow:${maxWidth}`;\n}\n\nfunction shouldUseMultilineOverflowLayout(options: Pick<MultilineTextOptions<any>, \"maxLines\">): boolean {\n return options.maxLines != null;\n}\n\nfunction shouldReadConstrainedOverflowLayout(\n maxWidth: number | undefined,\n options: Pick<MultilineTextOptions<any>, \"maxLines\">,\n): maxWidth is number {\n return maxWidth != null && shouldUseMultilineOverflowLayout(options);\n}\n\nfunction measureBlockLayout<T extends { width: number; lines: ArrayLike<unknown> }>(layout: T): MultiLineMeasureLayout {\n return { width: layout.width, lineCount: layout.lines.length };\n}\n\nfunction getSingleLineMinContentLayoutKey(): string {\n return \"single:min-content\";\n}\n\nfunction getMultiLineMinContentLayoutKey(): string {\n return \"multi:min-content\";\n}\n\nfunction getRichMultiLineMinContentLayoutKey(): string {\n return \"rich:min-content\";\n}\n\nfunction getSingleLineLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: TextOptions<C>,\n): SingleLineLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(node, ctx, getSingleLineLayoutKey(maxWidth), () =>\n maxWidth == null\n ? layoutFirstLineIntrinsic(ctx, text, options.whiteSpace, options.wordBreak)\n : options.overflow === \"ellipsis\"\n ? layoutEllipsizedFirstLine(\n ctx,\n text,\n maxWidth,\n options.ellipsisPosition ?? \"end\",\n options.whiteSpace,\n options.wordBreak,\n )\n : layoutFirstLine(ctx, text, maxWidth, options.whiteSpace, options.wordBreak)\n );\n}\n\nfunction getRichSingleLineLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: TextOptions<C>,\n): RichLineLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(node, ctx, getSingleLineLayoutKey(maxWidth), () =>\n maxWidth == null\n ? layoutRichFirstLineIntrinsic(ctx, spans, options.font, options.color, options.whiteSpace, options.wordBreak)\n : options.overflow === \"ellipsis\"\n ? layoutRichEllipsizedFirstLine(\n ctx,\n spans,\n maxWidth,\n options.font,\n options.color,\n options.ellipsisPosition ?? \"end\",\n options.whiteSpace,\n options.wordBreak,\n )\n : layoutRichFirstLine(ctx, spans, maxWidth, options.font, options.color, options.whiteSpace, options.wordBreak)\n );\n}\n\nfunction getMultiLineOverflowLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: MultilineTextOptions<C>,\n): MultiLineDrawLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(node, ctx, getMultiLineOverflowLayoutKey(maxWidth), () =>\n layoutTextWithOverflow(ctx, text, maxWidth ?? 0, {\n whiteSpace: options.whiteSpace,\n wordBreak: options.wordBreak,\n overflow: options.overflow,\n maxLines: options.maxLines,\n })\n );\n}\n\nfunction getMultiLineMeasureLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: MultilineTextOptions<C>,\n): MultiLineMeasureLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return measureBlockLayout(getMultiLineOverflowLayout(node, ctx, text, options));\n }\n return readCachedTextLayout(node, ctx, getMultiLineMeasureLayoutKey(maxWidth), () =>\n maxWidth == null\n ? measureTextIntrinsic(ctx, text, options.whiteSpace, options.wordBreak)\n : measureText(ctx, text, maxWidth, options.whiteSpace, options.wordBreak)\n );\n}\n\nfunction getMultiLineDrawLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: MultilineTextOptions<C>,\n): MultiLineDrawLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return getMultiLineOverflowLayout(node, ctx, text, options);\n }\n return readCachedTextLayout(node, ctx, getMultiLineDrawLayoutKey(maxWidth), () =>\n maxWidth == null\n ? layoutTextIntrinsic(ctx, text, options.whiteSpace, options.wordBreak)\n : layoutText(ctx, text, maxWidth, options.whiteSpace, options.wordBreak)\n );\n}\n\nfunction getSingleLineMinContentLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: TextOptions<C>,\n): SingleLineLayout {\n return readCachedTextLayout(node, ctx, getSingleLineMinContentLayoutKey(), () => {\n const measurement = measureTextMinContent(ctx, text, options.whiteSpace, options.wordBreak, options.overflowWrap);\n const { shift } = layoutFirstLineIntrinsic(ctx, text, options.whiteSpace, options.wordBreak);\n return {\n width: measurement.width,\n text,\n shift,\n };\n });\n}\n\nfunction getRichSingleLineMinContentWidth<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: TextOptions<C>,\n): number {\n return readCachedTextLayout(node, ctx, getSingleLineMinContentLayoutKey(), () =>\n measureRichTextMinContent(ctx, spans, options.font, options.overflowWrap, options.whiteSpace, options.wordBreak).width\n );\n}\n\nfunction drawRichLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n line: RichLineLayout,\n fallbackColor: TextOptions<C>[\"color\"],\n x: number,\n y: number,\n lineHeight: number,\n): void {\n let cursorX = x;\n for (let fragmentIndex = 0; fragmentIndex < line.fragments.length; fragmentIndex += 1) {\n const fragment = line.fragments[fragmentIndex]!;\n cursorX += fragment.gapBefore;\n ctx.with((g) => {\n g.font = fragment.font;\n g.fillStyle = ctx.resolveDynValue((fragment.color ?? fallbackColor) as typeof fallbackColor);\n g.textAlign = \"left\";\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(fragment.text, cursorX, y + (lineHeight + fragment.shift) / 2);\n });\n });\n cursorX += fragment.occupiedWidth;\n }\n}\n\nfunction getMultiLineMinContentLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n whiteSpace: MultilineTextOptions<C>[\"whiteSpace\"],\n wordBreak: MultilineTextOptions<C>[\"wordBreak\"],\n overflowWrap: MultilineTextOptions<C>[\"overflowWrap\"],\n): MultiLineMeasureLayout {\n return readCachedTextLayout(node, ctx, getMultiLineMinContentLayoutKey(), () =>\n measureTextMinContent(ctx, text, whiteSpace, wordBreak, overflowWrap)\n );\n}\n\nfunction getRichMultiLineMeasureLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichMeasurement {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return measureBlockLayout(getRichMultiLineOverflowLayout(node, ctx, spans, options));\n }\n return readCachedTextLayout(node, ctx, getRichMultiLineMeasureLayoutKey(maxWidth), () =>\n maxWidth == null\n ? measureRichTextIntrinsic(ctx, spans, options.font, options.whiteSpace, options.wordBreak)\n : measureRichText(ctx, spans, maxWidth, options.font, options.whiteSpace, options.wordBreak)\n );\n}\n\nfunction getRichMultiLineOverflowLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichBlockLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(node, ctx, getRichMultiLineOverflowLayoutKey(maxWidth), () =>\n layoutRichTextWithOverflow(\n ctx,\n spans,\n maxWidth ?? 0,\n options.font,\n options.color,\n options.maxLines,\n options.overflow,\n options.whiteSpace,\n options.wordBreak,\n )\n );\n}\n\nfunction getRichMultiLineDrawLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichBlockLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return getRichMultiLineOverflowLayout(node, ctx, spans, options);\n }\n return readCachedTextLayout(node, ctx, getRichMultiLineDrawLayoutKey(maxWidth), () =>\n maxWidth == null\n ? layoutRichTextIntrinsic(ctx, spans, options.font, options.color, options.whiteSpace, options.wordBreak)\n : layoutRichText(ctx, spans, maxWidth, options.font, options.color, options.whiteSpace, options.wordBreak)\n );\n}\n\nfunction getRichMultiLineMinContentLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichMeasurement {\n return readCachedTextLayout(node, ctx, getRichMultiLineMinContentLayoutKey(), () =>\n measureRichTextMinContent(ctx, spans, options.font, options.overflowWrap, options.whiteSpace, options.wordBreak)\n );\n}\n\n/**\n * Draws wrapped text using the configured line height and alignment.\n * Accepts either a plain string or an array of `InlineSpan` items for mixed inline styles.\n */\nexport class MultilineText<C extends CanvasRenderingContext2D> implements Node<C> {\n /**\n * @param text Source text to measure and draw. Pass an `InlineSpan[]` for mixed inline styles.\n * @param options Text layout and drawing options.\n */\n constructor(\n readonly text: string | InlineSpan<C>[],\n readonly options: MultilineTextOptions<C>,\n ) {}\n\n measure(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const spans = this.text;\n const { width, lineCount } = getRichMultiLineMeasureLayout(this, ctx, spans, this.options);\n return { width, height: lineCount * this.options.lineHeight };\n }\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lineCount } = getMultiLineMeasureLayout(this, ctx, this.text as string, this.options);\n return { width, height: lineCount * this.options.lineHeight };\n });\n }\n\n measureMinContent(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const spans = this.text;\n const { width, lineCount } = getRichMultiLineMinContentLayout(this, ctx, spans, this.options);\n return { width, height: lineCount * this.options.lineHeight };\n }\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lineCount } = getMultiLineMinContentLayout(\n this,\n ctx,\n this.text as string,\n this.options.whiteSpace,\n this.options.wordBreak,\n this.options.overflowWrap,\n );\n return { width, height: lineCount * this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n if (typeof this.text !== \"string\") {\n const spans = this.text;\n const { width, lines } = getRichMultiLineDrawLayout(this, ctx, spans, this.options);\n const align = resolvePhysicalTextAlign(this.options);\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n const mode = resolveJustifyMode(this.options.justify);\n const canJustify = mode != null && maxWidth != null && maxWidth > 0 && isJustifySupported(ctx.graphics);\n const threshold = this.options.justifyGapThreshold ?? 2.0;\n\n if (canJustify) {\n const prepared = readPreparedInlineLayout(\n getRichPreparedKey(spans, this.options.font, this.options.whiteSpace ?? \"normal\", this.options.wordBreak ?? \"normal\"),\n createRichSourceItems(spans, this.options.font),\n this.options.whiteSpace ?? \"normal\",\n this.options.wordBreak ?? \"normal\",\n );\n let lineIndex = 0;\n const totalLines = lines.length;\n walkPreparedLineRanges(prepared, maxWidth, (lineRange) => {\n if (lineIndex >= totalLines) return false;\n const line = lines[lineIndex]!;\n const isLastLine = lineIndex === totalLines - 1;\n const isOverflowTruncated = isLastLine && shouldUseMultilineOverflowLayout(this.options)\n && this.options.overflow === \"ellipsis\";\n const wantJustify = !isOverflowTruncated\n && (!isLastLine || this.options.justifyLastLine === true);\n\n if (wantJustify) {\n const info = analyzeLineForJustify(prepared, lineRange);\n const spacing = computeJustifySpacing(lineRange.width, maxWidth, info, mode, threshold);\n if (spacing != null) {\n let cursorX = x;\n for (let fi = 0; fi < line.fragments.length; fi++) {\n const frag = line.fragments[fi]!;\n const leadingLetterGapCount = fi > 0 ? frag.gapAtomCount + 1 : 0;\n const internalLetterGapCount = Math.max(frag.atomCount - 1, 0);\n cursorX += frag.gapBefore\n + leadingLetterGapCount * spacing.letterSpacingPx\n + frag.gapSpaceCount * spacing.wordSpacingPx;\n ctx.with((g) => {\n g.font = frag.font;\n g.fillStyle = ctx.resolveDynValue((frag.color ?? this.options.color) as typeof this.options.color);\n g.textAlign = \"left\";\n withTextSpacing(g, spacing, () => {\n g.fillText(frag.text, cursorX, y + (this.options.lineHeight + frag.shift) / 2);\n });\n });\n cursorX += frag.occupiedWidth\n + internalLetterGapCount * spacing.letterSpacingPx\n + frag.spaceCount * spacing.wordSpacingPx;\n }\n y += this.options.lineHeight;\n lineIndex++;\n return;\n }\n }\n\n // Fallback: normal alignment\n const startX = align === \"right\" ? x + width : align === \"center\" ? x + width / 2 : x;\n let cursorX = startX;\n for (let fi = 0; fi < line.fragments.length; fi++) {\n const frag = line.fragments[fi]!;\n cursorX += frag.gapBefore;\n ctx.with((g) => {\n g.font = frag.font;\n g.fillStyle = ctx.resolveDynValue((frag.color ?? this.options.color) as typeof this.options.color);\n if (align === \"right\") {\n g.textAlign = \"right\";\n } else if (align === \"center\") {\n g.textAlign = \"center\";\n } else {\n g.textAlign = \"left\";\n }\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(frag.text, cursorX, y + (this.options.lineHeight + frag.shift) / 2);\n });\n });\n cursorX += frag.occupiedWidth;\n }\n y += this.options.lineHeight;\n lineIndex++;\n });\n } else {\n const startX = align === \"right\" ? x + width : align === \"center\" ? x + width / 2 : x;\n for (const line of lines) {\n let cursorX = startX;\n for (let fi = 0; fi < line.fragments.length; fi++) {\n const frag = line.fragments[fi]!;\n cursorX += frag.gapBefore;\n ctx.with((g) => {\n g.font = frag.font;\n g.fillStyle = ctx.resolveDynValue((frag.color ?? this.options.color) as typeof this.options.color);\n if (align === \"right\") {\n g.textAlign = \"right\";\n } else if (align === \"center\") {\n g.textAlign = \"center\";\n } else {\n g.textAlign = \"left\";\n }\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(frag.text, cursorX, y + (this.options.lineHeight + frag.shift) / 2);\n });\n });\n cursorX += frag.occupiedWidth;\n }\n y += this.options.lineHeight;\n }\n }\n return false;\n }\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.color);\n const { width, lines } = getMultiLineDrawLayout(this, ctx, this.text as string, this.options);\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n const mode = resolveJustifyMode(this.options.justify);\n const canJustify = mode != null && maxWidth != null && maxWidth > 0 && isJustifySupported(g);\n const threshold = this.options.justifyGapThreshold ?? 2.0;\n\n if (canJustify) {\n const prepared = readPreparedText(\n this.text as string,\n this.options.font,\n this.options.whiteSpace ?? \"normal\",\n this.options.wordBreak ?? \"normal\",\n );\n let lineIndex = 0;\n const totalLines = lines.length;\n walkPreparedLineRanges(prepared, maxWidth, (lineRange) => {\n if (lineIndex >= totalLines) return false;\n const layout = lines[lineIndex]!;\n const isLastLine = lineIndex === totalLines - 1;\n const isOverflowTruncated = isLastLine && shouldUseMultilineOverflowLayout(this.options)\n && this.options.overflow === \"ellipsis\";\n const wantJustify = !isOverflowTruncated\n && (!isLastLine || this.options.justifyLastLine === true);\n\n if (wantJustify) {\n const info = analyzeLineForJustify(prepared, lineRange);\n const spacing = computeJustifySpacing(lineRange.width, maxWidth, info, mode, threshold);\n if (spacing != null) {\n withTextSpacing(g, spacing, () => {\n g.textAlign = \"left\";\n g.fillText(layout.text, x, y + (this.options.lineHeight + layout.shift) / 2);\n });\n y += this.options.lineHeight;\n lineIndex++;\n return;\n }\n }\n\n // Fallback to normal alignment for this line\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n switch (resolvePhysicalTextAlign(this.options)) {\n case \"left\":\n g.textAlign = \"left\";\n g.fillText(layout.text, x, y + (this.options.lineHeight + layout.shift) / 2);\n break;\n case \"right\":\n g.textAlign = \"right\";\n g.fillText(layout.text, x + width, y + (this.options.lineHeight + layout.shift) / 2);\n break;\n case \"center\":\n g.textAlign = \"center\";\n g.fillText(layout.text, x + width / 2, y + (this.options.lineHeight + layout.shift) / 2);\n break;\n }\n });\n y += this.options.lineHeight;\n lineIndex++;\n });\n } else {\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n switch (resolvePhysicalTextAlign(this.options)) {\n case \"left\":\n for (const { text, shift } of lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"right\": {\n x += width;\n g.textAlign = \"right\";\n for (const { text, shift } of lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n case \"center\": {\n x += width / 2;\n g.textAlign = \"center\";\n for (const { text, shift } of lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n }\n });\n }\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: { x: number; y: number; type: \"click\" | \"auxclick\" | \"hover\" }): boolean {\n return false;\n }\n}\n\n/**\n * Draws a single line of text, clipped logically by measurement width.\n */\nexport class Text<C extends CanvasRenderingContext2D> implements Node<C> {\n /**\n * @param text Source text to measure and draw. Pass an `InlineSpan[]` for mixed inline styles.\n * @param options Text layout and drawing options.\n */\n constructor(\n readonly text: string | InlineSpan<C>[],\n readonly options: TextOptions<C>,\n ) {}\n\n measure(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const { width } = getRichSingleLineLayout(this, ctx, this.text, this.options);\n return { width, height: this.options.lineHeight };\n }\n const text = this.text;\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width } = getSingleLineLayout(this, ctx, text, this.options);\n return { width, height: this.options.lineHeight };\n });\n }\n\n measureMinContent(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const width = getRichSingleLineMinContentWidth(this, ctx, this.text, this.options);\n return { width, height: this.options.lineHeight };\n }\n const text = this.text;\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width } = getSingleLineMinContentLayout(this, ctx, text, this.options);\n return { width, height: this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n if (typeof this.text !== \"string\") {\n const line = getRichSingleLineLayout(this, ctx, this.text, this.options);\n drawRichLine(ctx, line, this.options.color, x, y, this.options.lineHeight);\n return false;\n }\n const text = this.text;\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.color);\n const layout = getSingleLineLayout(this, ctx, text, this.options);\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(layout.text, x, y + (this.options.lineHeight + layout.shift) / 2);\n });\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: { x: number; y: number; type: \"click\" | \"auxclick\" | \"hover\" }): boolean {\n return false;\n }\n}\n","import { forEachNodeAncestor, getNodeRevision } from \"../internal/node-registry\";\nimport type {\n Box,\n Context,\n DynValue,\n FlexLayoutResult,\n HitTest,\n LayoutConstraints,\n Node,\n RendererOptions,\n} from \"../types\";\nimport { shallow } from \"../utils\";\n\nconst MAX_CONSTRAINT_VARIANTS = 8;\n\ntype LayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getLayoutResult(node: Node<C>, constraints?: LayoutConstraints): FlexLayoutResult<C> | undefined;\n setLayoutResult(node: Node<C>, result: FlexLayoutResult<C>, constraints?: LayoutConstraints): void;\n};\n\ntype TextLayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getTextLayout<T>(node: Node<C>, key: string): T | undefined;\n setTextLayout<T>(node: Node<C>, key: string, layout: T): void;\n};\n\ntype BoxCacheEntry = {\n revision: number;\n box: Box;\n};\n\ntype LayoutCacheEntry<C extends CanvasRenderingContext2D> = {\n revision: number;\n layout: FlexLayoutResult<C>;\n};\n\ntype TextLayoutCacheEntry = {\n revision: number;\n layout: unknown;\n};\n\ntype RendererContext<C extends CanvasRenderingContext2D> = Context<C> & LayoutCacheAccess<C> & TextLayoutCacheAccess<C>;\n\nfunction constraintKey(constraints: LayoutConstraints | undefined): string {\n if (constraints == null) return \"\";\n return `${constraints.minWidth ?? \"\"},${constraints.maxWidth ?? \"\"},${constraints.minHeight ?? \"\"},${constraints.maxHeight ?? \"\"}`;\n}\n\n/**\n * Base renderer that provides measurement, layout caching, and drawing helpers.\n */\nexport class BaseRenderer<C extends CanvasRenderingContext2D, O extends {} = {}> {\n /** Canvas rendering context used by this renderer. */\n graphics: C;\n #ctx: RendererContext<C>;\n #lastWidth: number;\n #cache = new WeakMap<Node<C>, Map<string, BoxCacheEntry>>();\n #layoutCache = new WeakMap<Node<C>, Map<string, LayoutCacheEntry<C>>>();\n #textLayoutCache = new WeakMap<Node<C>, Map<string, TextLayoutCacheEntry>>();\n\n protected get context(): Context<C> {\n return shallow(this.#ctx);\n }\n\n /**\n * @param graphics Canvas rendering context used for all layout and drawing.\n * @param options Renderer-specific options.\n */\n constructor(\n graphics: C,\n readonly options: RendererOptions & O,\n ) {\n this.graphics = graphics;\n this.graphics.textRendering = \"optimizeLegibility\";\n const self = this;\n this.#ctx = {\n graphics: this.graphics,\n measureNode(node: Node<C>, constraints?: LayoutConstraints) {\n return self.measureNode(node, constraints);\n },\n getLayoutResult(node: Node<C>, constraints?: LayoutConstraints) {\n return self.getLayoutResult(node, constraints);\n },\n setLayoutResult(node: Node<C>, result: FlexLayoutResult<C>, constraints?: LayoutConstraints) {\n self.setLayoutResult(node, result, constraints);\n },\n getTextLayout<T>(node: Node<C>, key: string) {\n return self.getTextLayout<T>(node, key);\n },\n setTextLayout<T>(node: Node<C>, key: string, layout: T) {\n self.setTextLayout(node, key, layout);\n },\n invalidateNode: this.invalidateNode.bind(this),\n resolveDynValue<T>(value: DynValue<C, T>): T {\n if (typeof value === \"function\") {\n return value(this.graphics);\n }\n return value as T;\n },\n with<T>(cb: (g: C) => T): T {\n this.graphics.save();\n try {\n return cb(this.graphics);\n } finally {\n this.graphics.restore();\n }\n },\n };\n this.#lastWidth = this.graphics.canvas.clientWidth;\n }\n\n #clearAllCaches(): void {\n this.#cache = new WeakMap<Node<C>, Map<string, BoxCacheEntry>>();\n this.#layoutCache = new WeakMap<Node<C>, Map<string, LayoutCacheEntry<C>>>();\n this.#textLayoutCache = new WeakMap<Node<C>, Map<string, TextLayoutCacheEntry>>();\n }\n\n #syncCachesToViewportWidth(): void {\n const width = this.graphics.canvas.clientWidth;\n if (this.#lastWidth === width) {\n return;\n }\n this.#clearAllCaches();\n this.#lastWidth = width;\n }\n\n protected getRootConstraints(): LayoutConstraints {\n return {\n maxWidth: this.graphics.canvas.clientWidth,\n };\n }\n\n protected getRootContext(): Context<C> {\n const ctx = this.context;\n ctx.constraints = this.getRootConstraints();\n return ctx;\n }\n\n protected measureRootNode(node: Node<C>): Box {\n return this.measureNode(node, this.getRootConstraints());\n }\n\n protected drawRootNode(node: Node<C>, x = 0, y = 0): boolean {\n this.measureRootNode(node);\n return node.draw(this.getRootContext(), x, y);\n }\n\n protected hittestRootNode(node: Node<C>, test: HitTest): boolean {\n this.measureRootNode(node);\n return node.hittest(this.getRootContext(), test);\n }\n\n /**\n * Drops cached measurements for a node and every ancestor that depends on it.\n */\n invalidateNode(node: Node<C>): void {\n this.#syncCachesToViewportWidth();\n this.#cache.delete(node);\n this.#layoutCache.delete(node);\n this.#textLayoutCache.delete(node);\n forEachNodeAncestor(node, (ancestor) => {\n this.#cache.delete(ancestor);\n this.#layoutCache.delete(ancestor);\n this.#textLayoutCache.delete(ancestor);\n });\n }\n\n /**\n * Returns the cached layout result for a node under the given constraints, if available.\n */\n getLayoutResult(node: Node<C>, constraints?: LayoutConstraints): FlexLayoutResult<C> | undefined {\n this.#syncCachesToViewportWidth();\n const nodeCache = this.#layoutCache.get(node);\n if (nodeCache == null) {\n return undefined;\n }\n const key = constraintKey(constraints);\n const cached = nodeCache.get(key);\n if (cached == null) {\n return undefined;\n }\n if (cached.revision !== getNodeRevision(node)) {\n nodeCache.delete(key);\n return undefined;\n }\n return cached.layout;\n }\n\n /**\n * Stores a layout result for later draw and hit-test passes.\n */\n setLayoutResult(node: Node<C>, result: FlexLayoutResult<C>, constraints?: LayoutConstraints): void {\n this.#syncCachesToViewportWidth();\n let nodeCache = this.#layoutCache.get(node);\n if (nodeCache == null) {\n nodeCache = new Map();\n this.#layoutCache.set(node, nodeCache);\n } else if (nodeCache.size >= MAX_CONSTRAINT_VARIANTS) {\n const firstKey = nodeCache.keys().next().value!;\n nodeCache.delete(firstKey);\n }\n nodeCache.set(constraintKey(constraints), {\n revision: getNodeRevision(node),\n layout: result,\n });\n }\n\n protected getTextLayout<T>(node: Node<C>, key: string): T | undefined {\n this.#syncCachesToViewportWidth();\n const nodeCache = this.#textLayoutCache.get(node);\n if (nodeCache == null) {\n return undefined;\n }\n const cached = nodeCache.get(key);\n if (cached == null) {\n return undefined;\n }\n if (cached.revision !== getNodeRevision(node)) {\n nodeCache.delete(key);\n return undefined;\n }\n return cached.layout as T;\n }\n\n protected setTextLayout<T>(node: Node<C>, key: string, layout: T): void {\n this.#syncCachesToViewportWidth();\n let nodeCache = this.#textLayoutCache.get(node);\n if (nodeCache == null) {\n nodeCache = new Map();\n this.#textLayoutCache.set(node, nodeCache);\n } else if (nodeCache.size >= MAX_CONSTRAINT_VARIANTS) {\n const firstKey = nodeCache.keys().next().value!;\n nodeCache.delete(firstKey);\n }\n nodeCache.set(key, {\n revision: getNodeRevision(node),\n layout,\n });\n }\n\n /**\n * Measures a node under optional constraints, using cached results when possible.\n */\n measureNode(node: Node<C>, constraints?: LayoutConstraints): Box {\n this.#syncCachesToViewportWidth();\n {\n const nodeCache = this.#cache.get(node);\n if (nodeCache != null) {\n const key = constraintKey(constraints);\n const cached = nodeCache.get(key);\n if (cached != null) {\n if (cached.revision === getNodeRevision(node)) {\n return cached.box;\n }\n nodeCache.delete(key);\n }\n }\n }\n const ctx = this.context;\n if (constraints != null) {\n ctx.constraints = constraints;\n }\n const result = node.measure(ctx);\n const key = constraintKey(constraints);\n let nodeCache = this.#cache.get(node);\n if (nodeCache == null) {\n nodeCache = new Map();\n this.#cache.set(node, nodeCache);\n } else if (nodeCache.size >= MAX_CONSTRAINT_VARIANTS) {\n const firstKey = nodeCache.keys().next().value!;\n nodeCache.delete(firstKey);\n }\n nodeCache.set(key, {\n revision: getNodeRevision(node),\n box: result,\n });\n return result;\n }\n}\n\n/**\n * Immediate-mode renderer for a single root node.\n */\nexport class DebugRenderer<C extends CanvasRenderingContext2D> extends BaseRenderer<C> {\n /**\n * Clears the viewport and draws the provided root node.\n */\n draw(node: Node<C>): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n return this.drawRootNode(node);\n }\n\n /**\n * Hit-tests the provided root node using viewport-relative coordinates.\n */\n hittest(node: Node<C>, test: HitTest): boolean {\n return this.hittestRootNode(node, test);\n }\n}\n","export interface WeakRefLike<T extends object> {\n deref(): T | undefined;\n}\n\nexport interface WeakListenerRecord<Owner extends object, Event> {\n ownerRef: WeakRefLike<Owner>;\n notify: (owner: Owner, event: Event) => void;\n}\n\nexport function pruneWeakListenerMap<Owner extends object, Event>(\n listeners: Map<symbol, WeakListenerRecord<Owner, Event>>,\n): void {\n for (const [token, listener] of listeners) {\n if (listener.ownerRef.deref() == null) {\n listeners.delete(token);\n }\n }\n}\n\nexport function emitWeakListeners<Owner extends object, Event>(\n listeners: Map<symbol, WeakListenerRecord<Owner, Event>>,\n event: Event,\n): void {\n for (const [token, listener] of [...listeners]) {\n const owner = listener.ownerRef.deref();\n if (owner == null) {\n listeners.delete(token);\n continue;\n }\n listener.notify(owner, event);\n }\n}\n","import { emitWeakListeners, pruneWeakListenerMap, type WeakListenerRecord } from \"./weak-listeners\";\n\n/**\n * Mutable list state shared with virtualized renderers.\n */\nexport interface ReplaceListItemAnimationOptions {\n /** Animation duration in milliseconds. */\n duration?: number;\n}\n\ntype ListReplaceChange<T extends {}> = {\n type: \"replace\";\n index: number;\n prevItem: T;\n nextItem: T;\n animation: ReplaceListItemAnimationOptions | undefined;\n};\n\ntype ListUnshiftChange = {\n type: \"unshift\";\n count: number;\n};\n\ntype ListPushChange = {\n type: \"push\";\n count: number;\n};\n\ntype ListResetChange = {\n type: \"reset\";\n};\n\ntype ListSetChange = {\n type: \"set\";\n};\n\nexport type ListStateChange<T extends {}> =\n | ListReplaceChange<T>\n | ListUnshiftChange\n | ListPushChange\n | ListResetChange\n | ListSetChange;\n\nexport type ListStateChangeListener<T extends {}> = (change: ListStateChange<T>) => void;\n\ntype WeakListStateListenerRecord = WeakListenerRecord<object, ListStateChange<{}>>;\n\nconst listStateListeners = new WeakMap<ListState<{}>, Map<symbol, WeakListStateListenerRecord>>();\nconst listStateListenerRegistry =\n typeof FinalizationRegistry === \"function\"\n ? new FinalizationRegistry<{ listRef: WeakRef<ListState<{}>>; token: symbol }>(({ listRef, token }) => {\n const list = listRef.deref();\n if (list == null) {\n return;\n }\n deleteListStateListener(list, token);\n })\n : null;\n\nfunction deleteListStateListener(list: ListState<{}>, token: symbol): void {\n const listeners = listStateListeners.get(list);\n if (listeners == null) {\n return;\n }\n listeners.delete(token);\n if (listeners.size === 0) {\n listStateListeners.delete(list);\n }\n}\n\nfunction emitListStateChange<T extends {}>(list: ListState<T>, change: ListStateChange<T>): void {\n const listeners = listStateListeners.get(list as unknown as ListState<{}>);\n if (listeners == null) {\n return;\n }\n emitWeakListeners(listeners, change as ListStateChange<{}>);\n if (listeners.size === 0) {\n listStateListeners.delete(list as unknown as ListState<{}>);\n }\n}\n\nexport function subscribeListState<T extends {}, O extends object>(\n list: ListState<T>,\n owner: O,\n listener: (owner: O, change: ListStateChange<T>) => void,\n): void {\n const key = list as unknown as ListState<{}>;\n let listeners = listStateListeners.get(key);\n if (listeners == null) {\n listeners = new Map();\n listStateListeners.set(key, listeners);\n } else {\n pruneWeakListenerMap(listeners);\n }\n const token = Symbol();\n listeners.set(token, {\n ownerRef: new WeakRef(owner),\n notify: listener as (owner: object, change: ListStateChange<{}>) => void,\n });\n listStateListenerRegistry?.register(owner, {\n listRef: new WeakRef(key),\n token,\n });\n}\n\nexport class ListState<T extends {}> {\n #items: T[];\n\n /** Pixel offset from the anchored item edge. */\n offset = 0;\n /** Anchor item index, or `undefined` to use the renderer default. */\n position: number | undefined;\n\n /** Items currently managed by the renderer. */\n get items(): T[] {\n return this.#items;\n }\n\n /** Replaces the full item collection while preserving scroll state. */\n set items(value: T[]) {\n this.#items = [...value];\n emitListStateChange(this, { type: \"set\" });\n }\n\n /**\n * @param items Initial list items.\n */\n constructor(items: T[] = []) {\n this.#items = [...items];\n }\n\n /** Prepends one or more items. */\n unshift(...items: T[]): void {\n this.unshiftAll(items);\n }\n\n /** Prepends an array of items. */\n unshiftAll(items: T[]): void {\n if (items.length === 0) {\n return;\n }\n if (this.position != null) {\n this.position += items.length;\n }\n this.#items = items.concat(this.#items);\n emitListStateChange(this, {\n type: \"unshift\",\n count: items.length,\n });\n }\n\n /** Appends one or more items. */\n push(...items: T[]): void {\n this.pushAll(items);\n }\n\n /** Appends an array of items. */\n pushAll(items: T[]): void {\n if (items.length === 0) {\n return;\n }\n this.#items.push(...items);\n emitListStateChange(this, {\n type: \"push\",\n count: items.length,\n });\n }\n\n /**\n * Replaces an existing item by index.\n */\n replace(index: number, item: T, animation?: ReplaceListItemAnimationOptions): void {\n const normalizedIndex = Number.isFinite(index) ? Math.trunc(index) : Number.NaN;\n if (!Number.isInteger(normalizedIndex) || normalizedIndex < 0 || normalizedIndex >= this.#items.length) {\n throw new RangeError(`replace() index ${index} is out of range for list length ${this.#items.length}.`);\n }\n\n const prevItem = this.#items[normalizedIndex]!;\n this.#items[normalizedIndex] = item;\n emitListStateChange(this, {\n type: \"replace\",\n index: normalizedIndex,\n prevItem,\n nextItem: item,\n animation:\n animation != null && Number.isFinite(animation.duration)\n ? { duration: animation.duration }\n : animation == null\n ? undefined\n : {},\n });\n }\n\n /**\n * Sets the current anchor item and pixel offset.\n */\n setAnchor(position: number, offset = 0): void {\n this.position = Number.isFinite(position) ? Math.trunc(position) : undefined;\n this.offset = Number.isFinite(offset) ? offset : 0;\n }\n\n /**\n * Replaces all items and clears scroll state.\n */\n reset(items: T[] = []): void {\n this.#items = [...items];\n this.offset = 0;\n this.position = undefined;\n emitListStateChange(this, { type: \"reset\" });\n }\n\n /** Clears the current scroll anchor while keeping the items. */\n resetScroll(): void {\n this.offset = 0;\n this.position = undefined;\n }\n\n /** Applies a relative pixel scroll delta. */\n applyScroll(delta: number): void {\n this.offset += delta;\n }\n}\n","import type { Node } from \"../types\";\n\nconst DEFAULT_MEMO_RENDER_ITEM_BY_MAX_ENTRIES = 512;\n\nfunction isWeakMapKey(value: unknown): value is object {\n return (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n\nfunction normalizeMaxEntries(maxEntries: number | undefined): number {\n if (maxEntries === Number.POSITIVE_INFINITY) {\n return Number.POSITIVE_INFINITY;\n }\n if (maxEntries == null || !Number.isFinite(maxEntries)) {\n return DEFAULT_MEMO_RENDER_ITEM_BY_MAX_ENTRIES;\n }\n return Math.max(0, Math.trunc(maxEntries));\n}\n\nfunction readLruValue<K, V>(cache: Map<K, V>, key: K): V | undefined {\n const cached = cache.get(key);\n if (cached == null) {\n return undefined;\n }\n cache.delete(key);\n cache.set(key, cached);\n return cached;\n}\n\nfunction writeLruValue<K, V>(cache: Map<K, V>, key: K, value: V, maxEntries: number): V {\n if (cache.has(key)) {\n cache.delete(key);\n } else if (Number.isFinite(maxEntries) && cache.size >= maxEntries) {\n const oldestKey = cache.keys().next().value;\n if (oldestKey != null) {\n cache.delete(oldestKey);\n }\n }\n if (maxEntries > 0) {\n cache.set(key, value);\n }\n return value;\n}\n\n/**\n * Memoizes `renderItem` by object identity.\n */\nexport function memoRenderItem<C extends CanvasRenderingContext2D, T extends object>(\n renderItem: (item: T) => Node<C>,\n): ((item: T) => Node<C>) & { reset: (key: T) => boolean } {\n const cache = new WeakMap<object, Node<C>>();\n\n function fn(item: T): Node<C> {\n if (!isWeakMapKey(item)) {\n throw new TypeError(\"memoRenderItem() only supports object items. Use memoRenderItemBy() for primitive keys.\");\n }\n const key = item as unknown as object;\n const cached = cache.get(key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n cache.set(key, result);\n return result;\n }\n\n return Object.assign(fn, {\n reset: (key: T) => cache.delete(key as unknown as object),\n });\n}\n\n/**\n * Memoizes `renderItem` by a caller-provided cache key.\n */\nexport function memoRenderItemBy<C extends CanvasRenderingContext2D, T, K>(\n keyOf: (item: T) => K,\n renderItem: (item: T) => Node<C>,\n options: {\n maxEntries?: number;\n } = {},\n): ((item: T) => Node<C>) & { reset: (item: T) => boolean; resetKey: (key: K) => boolean } {\n const cache = new Map<K, Node<C>>();\n const maxEntries = normalizeMaxEntries(options.maxEntries);\n\n function fn(item: T): Node<C> {\n const key = keyOf(item);\n const cached = readLruValue(cache, key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n return writeLruValue(cache, key, result, maxEntries);\n }\n\n return Object.assign(fn, {\n reset: (item: T) => cache.delete(keyOf(item)),\n resetKey: (key: K) => cache.delete(key),\n });\n}\n","import type { HitTest, Node, RenderFeedback } from \"../../types\";\nimport { BaseRenderer } from \"../base\";\nimport {\n ListState,\n subscribeListState,\n type ListStateChange,\n} from \"../list-state\";\nimport type { NormalizedListState, VisibleListState, VisibleWindow } from \"./solver\";\n\n/**\n * Options for programmatic scrolling to a target item.\n */\nexport interface JumpToOptions {\n /** Whether to animate the jump. Defaults to `true`. */\n animated?: boolean;\n /** Which edge of the item should align with the viewport. */\n block?: \"start\" | \"center\" | \"end\";\n /** Animation duration in milliseconds. */\n duration?: number;\n /** Called after the jump completes or finishes animating. */\n onComplete?: () => void;\n}\n\ntype ControlledState = {\n position?: number;\n offset: number;\n};\n\ntype JumpAnimation = {\n startAnchor: number;\n targetAnchor: number;\n startTime: number;\n duration: number;\n needsMoreFrames: boolean;\n onComplete: (() => void) | undefined;\n};\n\ntype ReplacementLayer<C extends CanvasRenderingContext2D> = {\n key: number;\n node: Node<C>;\n fromAlpha: number;\n toAlpha: number;\n startTime: number;\n duration: number;\n};\n\ntype ReplacementAnimation<C extends CanvasRenderingContext2D> = {\n currentLayerKey: number;\n layers: ReplacementLayer<C>[];\n fromHeight: number;\n toHeight: number;\n startTime: number;\n duration: number;\n};\n\ntype VirtualizedResolvedItem<C extends CanvasRenderingContext2D> = {\n draw: (y: number) => boolean;\n hittest: (test: HitTest, y: number) => boolean;\n};\n\nconst ALPHA_EPSILON = 1e-3;\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction sameState(state: ControlledState, position: number | undefined, offset: number): boolean {\n return Object.is(state.position, position) && Object.is(state.offset, offset);\n}\n\nfunction smoothstep(value: number): number {\n return value * value * (3 - 2 * value);\n}\n\nfunction getProgress(startTime: number, duration: number, now: number): number {\n if (!(duration > 0)) {\n return 1;\n }\n return clamp((now - startTime) / duration, 0, 1);\n}\n\nfunction interpolate(from: number, to: number, startTime: number, duration: number, now: number): number {\n const progress = getProgress(startTime, duration, now);\n const eased = progress >= 1 ? 1 : smoothstep(progress);\n return from + (to - from) * eased;\n}\n\nfunction getNow(): number {\n return globalThis.performance?.now() ?? Date.now();\n}\n\n/**\n * Shared base class for virtualized list renderers.\n */\nexport abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<\n C,\n {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n }\n> {\n static readonly MIN_JUMP_DURATION = 160;\n static readonly MAX_JUMP_DURATION = 420;\n static readonly JUMP_DURATION_PER_ITEM = 28;\n\n #controlledState: ControlledState | undefined;\n #jumpAnimation: JumpAnimation | undefined;\n #replacementAnimations = new Map<number, ReplacementAnimation<C>>();\n #nextReplacementLayerKey = 0;\n\n constructor(\n graphics: C,\n options: {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n },\n ) {\n super(graphics, options);\n subscribeListState(options.list, this, (owner, change) => {\n owner.#handleListStateChange(change);\n });\n }\n\n /** Current anchor item index. */\n get position(): number | undefined {\n return this.options.list.position;\n }\n\n /** Updates the current anchor item index. */\n set position(value: number | undefined) {\n this.options.list.position = value;\n }\n\n /** Pixel offset from the anchored item edge. */\n get offset(): number {\n return this.options.list.offset;\n }\n\n /** Updates the pixel offset from the anchored item edge. */\n set offset(value: number) {\n this.options.list.offset = value;\n }\n\n /** Items currently available to the renderer. */\n get items(): T[] {\n return this.options.list.items;\n }\n\n /** Replaces the current item collection. */\n set items(value: T[]) {\n this.options.list.items = value;\n }\n\n /** Renders the current visible window. */\n abstract render(feedback?: RenderFeedback): boolean;\n /** Hit-tests the current visible window. */\n abstract hittest(test: { x: number; y: number; type: \"click\" | \"auxclick\" | \"hover\" }): boolean;\n\n protected _readListState(): VisibleListState {\n return {\n position: this.position,\n offset: this.offset,\n };\n }\n\n protected _commitListState(state: NormalizedListState): void {\n this.position = state.position;\n this.offset = state.offset;\n }\n\n /**\n * Scrolls the viewport to the requested item index.\n */\n jumpTo(index: number, options: JumpToOptions = {}): void {\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return;\n }\n\n const targetIndex = this._clampItemIndex(index);\n const currentState = this._normalizeListState(this._readListState());\n const targetBlock = options.block ?? this._getDefaultJumpBlock();\n const targetAnchor = this._getTargetAnchor(targetIndex, targetBlock);\n\n const animated = options.animated ?? true;\n if (!animated) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const startAnchor = this._readAnchor(currentState);\n if (!Number.isFinite(startAnchor)) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const duration = clamp(\n options.duration ??\n VirtualizedRenderer.MIN_JUMP_DURATION +\n Math.abs(targetAnchor - startAnchor) * VirtualizedRenderer.JUMP_DURATION_PER_ITEM,\n 0,\n VirtualizedRenderer.MAX_JUMP_DURATION,\n );\n\n if (duration <= 0 || Math.abs(targetAnchor - startAnchor) <= Number.EPSILON) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n this.#jumpAnimation = {\n startAnchor,\n targetAnchor,\n startTime: getNow(),\n duration,\n needsMoreFrames: true,\n onComplete: options.onComplete,\n };\n this.#controlledState = this._readListState();\n }\n\n protected _resetRenderFeedback(feedback?: RenderFeedback): void {\n if (feedback == null) {\n return;\n }\n feedback.minIdx = Number.NaN;\n feedback.maxIdx = Number.NaN;\n feedback.min = Number.NaN;\n feedback.max = Number.NaN;\n }\n\n protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void {\n if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) {\n return;\n }\n\n const viewportHeight = this.graphics.canvas.clientHeight;\n const visibleTop = clamp(-top, 0, height);\n const visibleBottom = clamp(viewportHeight - top, 0, height);\n if (visibleBottom <= visibleTop) {\n return;\n }\n\n const itemMin = idx + visibleTop / height;\n const itemMax = idx + visibleBottom / height;\n feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);\n feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);\n feedback.min = Number.isNaN(feedback.min) ? itemMin : Math.min(itemMin, feedback.min);\n feedback.max = Number.isNaN(feedback.max) ? itemMax : Math.max(itemMax, feedback.max);\n }\n\n protected _renderDrawList(\n list: VisibleWindow<VirtualizedResolvedItem<C>>[\"drawList\"],\n shift: number,\n feedback?: RenderFeedback,\n ): boolean {\n let result = false;\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n for (const { idx, value: item, offset, height } of list) {\n const y = offset + shift;\n if (feedback != null) {\n this._accumulateRenderFeedback(feedback, idx, y, height);\n }\n if (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (item.draw(y)) {\n result = true;\n }\n }\n\n return result;\n }\n\n protected _renderVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem<C>>, feedback?: RenderFeedback): boolean {\n this._resetRenderFeedback(feedback);\n return this._renderDrawList(window.drawList, window.shift, feedback);\n }\n\n protected _hittestVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem<C>>, test: HitTest): boolean {\n for (const { value: item, offset, height } of window.drawList) {\n const y = offset + window.shift;\n if (test.y < y || test.y >= y + height) {\n continue;\n }\n return item.hittest(test, y);\n }\n return false;\n }\n\n protected _prepareRender(): boolean {\n const now = getNow();\n const keepReplacing = this.#prepareReplacementAnimations(now);\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return keepReplacing;\n }\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return keepReplacing;\n }\n if (this.#controlledState != null && !sameState(this.#controlledState, this.position, this.offset)) {\n this.#cancelJumpAnimation();\n return keepReplacing;\n }\n\n const anchor = interpolate(animation.startAnchor, animation.targetAnchor, animation.startTime, animation.duration, now);\n const progress = getProgress(animation.startTime, animation.duration, now);\n this._applyAnchor(anchor);\n animation.needsMoreFrames = progress < 1;\n return keepReplacing || animation.needsMoreFrames;\n }\n\n protected _finishRender(requestRedraw: boolean): boolean {\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return requestRedraw;\n }\n\n if (animation.needsMoreFrames) {\n this.#controlledState = this._readListState();\n return true;\n }\n\n const onComplete = animation.onComplete;\n this.#cancelJumpAnimation();\n onComplete?.();\n return requestRedraw || this.#jumpAnimation != null;\n }\n\n protected _clampItemIndex(index: number): number {\n return clamp(Number.isFinite(index) ? Math.trunc(index) : 0, 0, this.items.length - 1);\n }\n\n protected _getItemHeight(index: number): number {\n const now = getNow();\n const replacement = this.#readReplacementAnimation(index, now);\n if (replacement != null) {\n return this.#sampleReplacementHeight(replacement, now);\n }\n const item = this.items[index];\n const node = this.options.renderItem(item);\n return this.measureRootNode(node).height;\n }\n\n protected _resolveItem(item: T, index: number, now: number): { value: VirtualizedResolvedItem<C>; height: number } {\n const replacement = this.#readReplacementAnimation(index, now);\n if (replacement == null) {\n const node = this.options.renderItem(item);\n return {\n value: {\n draw: (y) => this.drawRootNode(node, 0, y),\n hittest: (test, y) =>\n node.hittest(this.getRootContext(), {\n ...test,\n y: test.y - y,\n }),\n },\n height: this.measureRootNode(node).height,\n };\n }\n\n const slotHeight = this.#sampleReplacementHeight(replacement, now);\n const layers = replacement.layers\n .map((layer) => ({\n alpha: this.#sampleLayerAlpha(layer, now),\n node: layer.node,\n nodeHeight: this.measureRootNode(layer.node).height,\n }))\n .filter((layer) => layer.alpha > ALPHA_EPSILON);\n\n return {\n value: {\n draw: (y) => this.#drawReplacementLayers(layers, slotHeight, y),\n hittest: () => false,\n },\n height: slotHeight,\n };\n }\n\n protected _getAnchorAtOffset(index: number, offset: number): number {\n if (this.items.length === 0) {\n return 0;\n }\n\n let currentIndex = this._clampItemIndex(index);\n let remaining = Number.isFinite(offset) ? offset : 0;\n while (true) {\n if (remaining < 0) {\n if (currentIndex === 0) {\n return 0;\n }\n currentIndex -= 1;\n const height = this._getItemHeight(currentIndex);\n if (height > 0) {\n remaining += height;\n }\n continue;\n }\n\n const height = this._getItemHeight(currentIndex);\n if (height > 0) {\n if (remaining <= height) {\n return currentIndex + remaining / height;\n }\n remaining -= height;\n } else if (remaining === 0) {\n return currentIndex;\n }\n\n if (currentIndex === this.items.length - 1) {\n return this.items.length;\n }\n currentIndex += 1;\n }\n }\n\n protected abstract _normalizeListState(state: VisibleListState): NormalizedListState;\n protected abstract _readAnchor(state: NormalizedListState): number;\n protected abstract _applyAnchor(anchor: number): void;\n protected abstract _getDefaultJumpBlock(): NonNullable<JumpToOptions[\"block\"]>;\n protected abstract _getTargetAnchor(index: number, block: NonNullable<JumpToOptions[\"block\"]>): number;\n protected abstract _getAnimatedLayerOffset(slotHeight: number, nodeHeight: number): number;\n\n #cancelJumpAnimation(): void {\n this.#jumpAnimation = undefined;\n this.#controlledState = undefined;\n }\n\n #createReplacementLayer(node: Node<C>, fromAlpha: number, toAlpha: number, startTime: number, duration: number): ReplacementLayer<C> {\n return {\n key: ++this.#nextReplacementLayerKey,\n node,\n fromAlpha,\n toAlpha,\n startTime,\n duration,\n };\n }\n\n #sampleLayerAlpha(layer: ReplacementLayer<C>, now: number): number {\n return interpolate(layer.fromAlpha, layer.toAlpha, layer.startTime, layer.duration, now);\n }\n\n #sampleReplacementHeight(animation: ReplacementAnimation<C>, now: number): number {\n return interpolate(animation.fromHeight, animation.toHeight, animation.startTime, animation.duration, now);\n }\n\n #isLayerComplete(layer: ReplacementLayer<C>, now: number): boolean {\n return getProgress(layer.startTime, layer.duration, now) >= 1 && Math.abs(layer.toAlpha - this.#sampleLayerAlpha(layer, now)) <= ALPHA_EPSILON;\n }\n\n #readReplacementAnimation(index: number, now: number): ReplacementAnimation<C> | undefined {\n const animation = this.#replacementAnimations.get(index);\n if (animation == null) {\n return undefined;\n }\n\n const currentLayer = animation.layers.find((layer) => layer.key === animation.currentLayerKey);\n if (currentLayer == null) {\n this.#replacementAnimations.delete(index);\n return undefined;\n }\n\n animation.layers = animation.layers.filter((layer) => layer.key === animation.currentLayerKey || !this.#isLayerComplete(layer, now));\n if (\n getProgress(animation.startTime, animation.duration, now) >= 1 &&\n this.#isLayerComplete(currentLayer, now) &&\n animation.layers.length === 1\n ) {\n this.#replacementAnimations.delete(index);\n return undefined;\n }\n\n return animation;\n }\n\n #prepareReplacementAnimations(now: number): boolean {\n let keepAnimating = false;\n for (const index of [...this.#replacementAnimations.keys()]) {\n if (this.#readReplacementAnimation(index, now) != null) {\n keepAnimating = true;\n }\n }\n return keepAnimating;\n }\n\n #drawReplacementLayers(\n layers: { alpha: number; node: Node<C>; nodeHeight: number }[],\n slotHeight: number,\n y: number,\n ): boolean {\n if (slotHeight <= 0) {\n return false;\n }\n\n let result = false;\n const width = this.graphics.canvas.clientWidth;\n for (const layer of layers) {\n const alpha = clamp(layer.alpha, 0, 1);\n if (alpha <= ALPHA_EPSILON) {\n continue;\n }\n\n this.graphics.save();\n try {\n this.graphics.beginPath?.();\n this.graphics.rect?.(0, y, width, slotHeight);\n this.graphics.clip?.();\n if (typeof this.graphics.globalAlpha === \"number\") {\n this.graphics.globalAlpha *= alpha;\n }\n const layerY = y + this._getAnimatedLayerOffset(slotHeight, layer.nodeHeight);\n if (this.drawRootNode(layer.node, 0, layerY)) {\n result = true;\n }\n } finally {\n this.graphics.restore();\n }\n }\n return result;\n }\n\n #handleListStateChange(change: ListStateChange<T>): void {\n switch (change.type) {\n case \"replace\":\n this.#handleReplace(change.index, change.prevItem, change.nextItem, change.animation?.duration);\n break;\n case \"unshift\": {\n if (change.count <= 0 || this.#replacementAnimations.size === 0) {\n return;\n }\n const shifted = new Map<number, ReplacementAnimation<C>>();\n for (const [index, animation] of this.#replacementAnimations) {\n shifted.set(index + change.count, animation);\n }\n this.#replacementAnimations = shifted;\n break;\n }\n case \"push\":\n break;\n case \"reset\":\n case \"set\":\n this.#replacementAnimations.clear();\n break;\n }\n }\n\n #handleReplace(index: number, prevItem: T, nextItem: T, duration: number | undefined): void {\n const normalizedDuration = Number.isFinite(duration) ? Math.max(0, duration!) : 0;\n if (normalizedDuration <= 0) {\n this.#replacementAnimations.delete(index);\n return;\n }\n\n const now = getNow();\n const nextNode = this.options.renderItem(nextItem);\n const nextHeight = this.measureRootNode(nextNode).height;\n const animation = this.#readReplacementAnimation(index, now);\n if (animation == null) {\n const prevNode = this.options.renderItem(prevItem);\n const outgoing = this.#createReplacementLayer(prevNode, 1, 0, now, normalizedDuration);\n const incoming = this.#createReplacementLayer(nextNode, 0, 1, now, normalizedDuration);\n this.#replacementAnimations.set(index, {\n currentLayerKey: incoming.key,\n layers: [outgoing, incoming],\n fromHeight: this.measureRootNode(prevNode).height,\n toHeight: nextHeight,\n startTime: now,\n duration: normalizedDuration,\n });\n return;\n }\n\n const currentLayer = animation.layers.find((layer) => layer.key === animation.currentLayerKey);\n const currentNode = currentLayer?.node ?? this.options.renderItem(prevItem);\n const currentAlpha = currentLayer == null ? 1 : this.#sampleLayerAlpha(currentLayer, now);\n const layers = animation.layers.filter(\n (layer) => layer.key !== animation.currentLayerKey && !this.#isLayerComplete(layer, now),\n );\n if (currentAlpha > ALPHA_EPSILON) {\n layers.push(this.#createReplacementLayer(currentNode, currentAlpha, 0, now, normalizedDuration));\n }\n const incoming = this.#createReplacementLayer(nextNode, 0, 1, now, normalizedDuration);\n layers.push(incoming);\n this.#replacementAnimations.set(index, {\n currentLayerKey: incoming.key,\n layers,\n fromHeight: this.#sampleReplacementHeight(animation, now),\n toHeight: nextHeight,\n startTime: now,\n duration: normalizedDuration,\n });\n }\n}\n","export interface VisibleListState {\n position?: number;\n offset: number;\n}\n\nexport interface NormalizedListState {\n position: number;\n offset: number;\n}\n\nexport interface VisibleWindowEntry<T> {\n idx: number;\n value: T;\n offset: number;\n height: number;\n}\n\nexport interface VisibleWindow<T> {\n drawList: VisibleWindowEntry<T>[];\n shift: number;\n}\n\nexport interface VisibleWindowResult<T> {\n normalizedState: NormalizedListState;\n window: VisibleWindow<T>;\n}\n\ntype ResolvedItem<T> = {\n value: T;\n height: number;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction normalizeOffset(offset: number): number {\n return Number.isFinite(offset) ? offset : 0;\n}\n\nexport function normalizeTimelineState(itemCount: number, state: VisibleListState): NormalizedListState {\n if (itemCount <= 0) {\n return { position: 0, offset: 0 };\n }\n\n const position = state.position;\n if (typeof position !== \"number\" || !Number.isFinite(position)) {\n return {\n position: 0,\n offset: normalizeOffset(state.offset),\n };\n }\n\n return {\n position: clamp(Math.trunc(position), 0, itemCount - 1),\n offset: normalizeOffset(state.offset),\n };\n}\n\nexport function normalizeChatState(itemCount: number, state: VisibleListState): NormalizedListState {\n if (itemCount <= 0) {\n return { position: 0, offset: 0 };\n }\n\n const position = state.position;\n if (typeof position !== \"number\" || !Number.isFinite(position)) {\n return {\n position: itemCount - 1,\n offset: normalizeOffset(state.offset),\n };\n }\n\n return {\n position: clamp(Math.trunc(position), 0, itemCount - 1),\n offset: normalizeOffset(state.offset),\n };\n}\n\nexport function resolveTimelineVisibleWindow<T, V>(\n items: readonly T[],\n state: VisibleListState,\n viewportHeight: number,\n resolveItem: (item: T, idx: number) => ResolvedItem<V>,\n): VisibleWindowResult<V> {\n const normalizedState = normalizeTimelineState(items.length, state);\n if (items.length === 0) {\n return {\n normalizedState,\n window: { drawList: [], shift: 0 },\n };\n }\n\n let { position, offset } = normalizedState;\n let drawLength = 0;\n\n if (offset > 0) {\n if (position === 0) {\n offset = 0;\n } else {\n for (let i = position - 1; i >= 0; i -= 1) {\n const { height } = resolveItem(items[i]!, i);\n position = i;\n offset -= height;\n if (offset <= 0) {\n break;\n }\n }\n if (position === 0 && offset > 0) {\n offset = 0;\n }\n }\n }\n\n let y = offset;\n const drawList: VisibleWindowEntry<V>[] = [];\n for (let i = position; i < items.length; i += 1) {\n const { value, height } = resolveItem(items[i]!, i);\n if (y + height > 0) {\n drawList.push({ idx: i, value, offset: y, height });\n drawLength += height;\n } else {\n offset += height;\n position = i + 1;\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n\n let shift = 0;\n if (y < viewportHeight) {\n if (position === 0 && drawLength < viewportHeight) {\n shift = -offset;\n offset = 0;\n } else {\n shift = viewportHeight - y;\n y = (offset += shift);\n let lastIdx = -1;\n for (let i = position - 1; i >= 0; i -= 1) {\n const { value, height } = resolveItem(items[i]!, i);\n drawLength += height;\n y -= height;\n drawList.push({ idx: i, value, offset: y - shift, height });\n lastIdx = i;\n if (y < 0) {\n break;\n }\n }\n if (lastIdx === 0 && drawLength < viewportHeight) {\n shift = drawList.at(-1)?.offset == null ? 0 : -drawList.at(-1)!.offset;\n position = 0;\n offset = 0;\n }\n }\n }\n\n return {\n normalizedState: { position, offset },\n window: { drawList, shift },\n };\n}\n\nexport function resolveChatVisibleWindow<T, V>(\n items: readonly T[],\n state: VisibleListState,\n viewportHeight: number,\n resolveItem: (item: T, idx: number) => ResolvedItem<V>,\n): VisibleWindowResult<V> {\n const normalizedState = normalizeChatState(items.length, state);\n if (items.length === 0) {\n return {\n normalizedState,\n window: { drawList: [], shift: 0 },\n };\n }\n\n let { position, offset } = normalizedState;\n let drawLength = 0;\n\n if (offset < 0) {\n if (position === items.length - 1) {\n offset = 0;\n } else {\n for (let i = position + 1; i < items.length; i += 1) {\n const { height } = resolveItem(items[i]!, i);\n position = i;\n offset += height;\n if (offset > 0) {\n break;\n }\n }\n }\n }\n\n let y = viewportHeight + offset;\n const drawList: VisibleWindowEntry<V>[] = [];\n for (let i = position; i >= 0; i -= 1) {\n const { value, height } = resolveItem(items[i]!, i);\n y -= height;\n if (y <= viewportHeight) {\n drawList.push({ idx: i, value, offset: y, height });\n drawLength += height;\n } else {\n offset -= height;\n position = i - 1;\n }\n if (y < 0) {\n break;\n }\n }\n\n let shift = 0;\n if (y > 0) {\n shift = -y;\n if (drawLength < viewportHeight) {\n y = drawLength;\n for (let i = position + 1; i < items.length; i += 1) {\n const { value, height } = resolveItem(items[i]!, i);\n drawList.push({ idx: i, value, offset: y - shift, height });\n y = (drawLength += height);\n position = i;\n if (y >= viewportHeight) {\n break;\n }\n }\n offset = drawLength < viewportHeight ? 0 : drawLength - viewportHeight;\n } else {\n offset = drawLength - viewportHeight;\n }\n }\n\n return {\n normalizedState: { position, offset },\n window: { drawList, shift },\n };\n}\n","import type { HitTest, RenderFeedback } from \"../../types\";\nimport { VirtualizedRenderer } from \"./base\";\nimport type { JumpToOptions } from \"./base\";\nimport {\n normalizeChatState,\n resolveChatVisibleWindow,\n type NormalizedListState,\n type VisibleListState,\n} from \"./solver\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Virtualized renderer anchored to the bottom, suitable for chat-style UIs.\n */\nexport class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n #resolveVisibleWindow() {\n const now = globalThis.performance?.now() ?? Date.now();\n return resolveChatVisibleWindow(\n this.items,\n this._readListState(),\n this.graphics.canvas.clientHeight,\n (item, idx) => {\n return this._resolveItem(item, idx, now);\n },\n );\n }\n\n protected _getDefaultJumpBlock(): NonNullable<JumpToOptions[\"block\"]> {\n return \"end\";\n }\n\n protected _normalizeListState(state: VisibleListState): NormalizedListState {\n return normalizeChatState(this.items.length, state);\n }\n\n protected _readAnchor(state: NormalizedListState): number {\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(state.position);\n return height > 0 ? state.position + 1 - state.offset / height : state.position + 1;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.ceil(clampedAnchor) - 1, 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n const offset = height > 0 ? (position + 1 - clampedAnchor) * height : 0;\n this._commitListState({\n position,\n offset: Object.is(offset, -0) ? 0 : offset,\n });\n }\n\n protected _getTargetAnchor(index: number, block: NonNullable<JumpToOptions[\"block\"]>): number {\n const height = this._getItemHeight(index);\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n switch (block) {\n case \"start\":\n return this._getAnchorAtOffset(index, viewportHeight);\n case \"center\":\n return this._getAnchorAtOffset(index, height / 2 + viewportHeight / 2);\n case \"end\":\n return this._getAnchorAtOffset(index, height);\n }\n }\n\n protected _getAnimatedLayerOffset(slotHeight: number, nodeHeight: number): number {\n return slotHeight - nodeHeight;\n }\n\n render(feedback?: RenderFeedback): boolean {\n const keepAnimating = this._prepareRender();\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n const solution = this.#resolveVisibleWindow();\n const requestRedraw = this._renderVisibleWindow(solution.window, feedback);\n this._commitListState(solution.normalizedState);\n return this._finishRender(keepAnimating || requestRedraw);\n }\n\n hittest(test: HitTest): boolean {\n return this._hittestVisibleWindow(this.#resolveVisibleWindow().window, test);\n }\n}\n","import type { HitTest, RenderFeedback } from \"../../types\";\nimport { VirtualizedRenderer } from \"./base\";\nimport type { JumpToOptions } from \"./base\";\nimport {\n normalizeTimelineState,\n resolveTimelineVisibleWindow,\n type NormalizedListState,\n type VisibleListState,\n} from \"./solver\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Virtualized renderer anchored to the top, suitable for timeline-style UIs.\n */\nexport class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n #resolveVisibleWindow() {\n const now = globalThis.performance?.now() ?? Date.now();\n return resolveTimelineVisibleWindow(\n this.items,\n this._readListState(),\n this.graphics.canvas.clientHeight,\n (item, idx) => {\n return this._resolveItem(item, idx, now);\n },\n );\n }\n\n protected _getDefaultJumpBlock(): NonNullable<JumpToOptions[\"block\"]> {\n return \"start\";\n }\n\n protected _normalizeListState(state: VisibleListState): NormalizedListState {\n return normalizeTimelineState(this.items.length, state);\n }\n\n protected _readAnchor(state: NormalizedListState): number {\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(state.position);\n return height > 0 ? state.position - state.offset / height : state.position;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.floor(clampedAnchor), 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n const offset = height > 0 ? -(clampedAnchor - position) * height : 0;\n this._commitListState({\n position,\n offset: Object.is(offset, -0) ? 0 : offset,\n });\n }\n\n protected _getTargetAnchor(index: number, block: NonNullable<JumpToOptions[\"block\"]>): number {\n const height = this._getItemHeight(index);\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n switch (block) {\n case \"start\":\n return this._getAnchorAtOffset(index, 0);\n case \"center\":\n return this._getAnchorAtOffset(index, height / 2 - viewportHeight / 2);\n case \"end\":\n return this._getAnchorAtOffset(index, height - viewportHeight);\n }\n }\n\n protected _getAnimatedLayerOffset(_slotHeight: number, _nodeHeight: number): number {\n return 0;\n }\n\n render(feedback?: RenderFeedback): boolean {\n const keepAnimating = this._prepareRender();\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n const solution = this.#resolveVisibleWindow();\n const requestRedraw = this._renderVisibleWindow(solution.window, feedback);\n this._commitListState(solution.normalizedState);\n return this._finishRender(keepAnimating || requestRedraw);\n }\n\n hittest(test: HitTest): boolean {\n return this._hittestVisibleWindow(this.#resolveVisibleWindow().window, test);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["#children","#inner","clampToConstraints","#top","#bottom","#left","#right","#writeLayout","readLruValue","writeLruValue","measurePreparedMinContentWidth","readLruValue","writeLruValue","measureInlinePreparedMinContentWidth","getFirstLineRange","walkLines","collectVisibleLines","measurePreparedMinContentWidth","#ctx","#lastWidth","#cache","#layoutCache","#textLayoutCache","#clearAllCaches","#syncCachesToViewportWidth","#items","#pendingDeletes","clamp","#visibleItems","#hasVisibleItemSnapshot","#visibleSnapshotState","#activeReplacementItems","#replacementAnimations","#sampleReplacementHeight","#readReplacementLayers","#drawReplacementLayers","#canAnimateUpdate","#sampleLayerAlpha","#createLayer","clamp","#isIndexVisible","#handleListStateChange","#cancelJumpAnimation","clamp","#jumpAnimation","#controlledState","#replacementController","#handleDeleteComplete","#getReplacementRendererAdapter","#getReplacementUpdateContext","clamp","clamp"],"sources":["../src/internal/node-registry.ts","../src/utils.ts","../src/nodes/base.ts","../src/layout.ts","../src/nodes/shared.ts","../src/nodes/box.ts","../src/nodes/flex.ts","../src/nodes/place.ts","../src/nodes/shrinkwrap.ts","../src/text/core.ts","../src/text/inline-engine.ts","../src/text/plain-core.ts","../src/text/plain.ts","../src/text/rich.ts","../src/text/justify.ts","../src/nodes/text.ts","../src/renderer/base.ts","../src/renderer/weak-listeners.ts","../src/renderer/list-state.ts","../src/renderer/memo.ts","../src/renderer/virtualized/base-animation.ts","../src/renderer/virtualized/base-types.ts","../src/renderer/virtualized/base-replacement.ts","../src/renderer/virtualized/base.ts","../src/renderer/virtualized/solver.ts","../src/renderer/virtualized/chat.ts","../src/renderer/virtualized/timeline.ts"],"sourcesContent":["import type { Node } from \"../types\";\n\nconst registry = new WeakMap<Node<any>, Node<any>>();\nconst revisions = new WeakMap<Node<any>, number>();\n\nfunction getOwnershipError(): Error {\n return new Error(\n \"A node can only be attached to one parent. Shared nodes are not supported.\",\n );\n}\n\nfunction getDetachOwnershipError(): Error {\n return new Error(\n \"Cannot detach or replace a node from a parent that does not own it.\",\n );\n}\n\nfunction bumpRevision(node: Node<any>): void {\n revisions.set(node, (revisions.get(node) ?? 0) + 1);\n}\n\nexport function getNodeRevision<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n): number {\n return revisions.get(node) ?? 0;\n}\n\nexport function attachNodeToParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n if (registry.has(node)) {\n throw getOwnershipError();\n }\n registry.set(node, parent);\n bumpRevision(parent);\n}\n\nexport function attachNodesToParent<C extends CanvasRenderingContext2D>(\n nodes: Iterable<Node<C>>,\n parent: Node<C>,\n): void {\n for (const node of nodes) {\n attachNodeToParent(node, parent);\n }\n}\n\nexport function detachNodeFromParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent?: Node<C>,\n): void {\n const currentParent = registry.get(node);\n if (currentParent == null) {\n return;\n }\n if (parent != null && currentParent !== parent) {\n throw getDetachOwnershipError();\n }\n registry.delete(node);\n bumpRevision(currentParent);\n}\n\nexport function replaceNodeParent<C extends CanvasRenderingContext2D>(\n previousNode: Node<C>,\n nextNode: Node<C>,\n parent: Node<C>,\n): void {\n if (previousNode === nextNode) {\n return;\n }\n const currentParent = registry.get(previousNode);\n if (currentParent !== parent) {\n throw getDetachOwnershipError();\n }\n if (registry.has(nextNode)) {\n throw getOwnershipError();\n }\n registry.delete(previousNode);\n registry.set(nextNode, parent);\n bumpRevision(parent);\n}\n\nexport function replaceNodesParent<C extends CanvasRenderingContext2D>(\n previousNodes: Iterable<Node<C>>,\n nextNodes: Iterable<Node<C>>,\n parent: Node<C>,\n): void {\n const previousSnapshot = Array.from(previousNodes);\n const nextSnapshot = Array.from(nextNodes);\n if (\n previousSnapshot.length === nextSnapshot.length &&\n previousSnapshot.every((node, index) => node === nextSnapshot[index])\n ) {\n return;\n }\n\n const previousSet = new Set(previousSnapshot);\n const nextSet = new Set<Node<C>>();\n for (const node of nextSnapshot) {\n if (nextSet.has(node)) {\n throw getOwnershipError();\n }\n nextSet.add(node);\n const currentParent = registry.get(node);\n if (currentParent != null && currentParent !== parent) {\n throw getOwnershipError();\n }\n }\n\n for (const node of previousSnapshot) {\n if (!nextSet.has(node)) {\n const currentParent = registry.get(node);\n if (currentParent !== parent) {\n throw getDetachOwnershipError();\n }\n registry.delete(node);\n }\n }\n\n for (const node of nextSnapshot) {\n if (!previousSet.has(node)) {\n registry.set(node, parent);\n }\n }\n\n bumpRevision(parent);\n}\n\nexport function forEachNodeAncestor<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n visitor: (ancestor: Node<C>) => void,\n): void {\n let current: Node<C> | undefined = node;\n while ((current = registry.get(current))) {\n visitor(current);\n }\n}\n\nexport function registerNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n attachNodeToParent(node, parent);\n}\n\nexport function unregisterNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent?: Node<C>,\n): void {\n detachNodeFromParent(node, parent);\n}\n\nexport function getNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n): Node<C> | undefined {\n return registry.get(node);\n}\n","export function shallow<T extends object>(object: T): T {\n return Object.create(object) as T;\n}\n","import {\n attachNodeToParent,\n replaceNodeParent,\n replaceNodesParent,\n} from \"../internal/node-registry\";\nimport type { Box, Context, HitTest, LayoutConstraints, Node } from \"../types\";\nimport { shallow } from \"../utils\";\n\nexport function withNodeConstraints<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n constraints: LayoutConstraints | undefined,\n): Context<C> {\n if (constraints === ctx.constraints) {\n return ctx;\n }\n const next = shallow(ctx);\n next.constraints = constraints;\n return next;\n}\n\nexport function measureNodeMinContent<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n node: Node<C>,\n constraints: LayoutConstraints | undefined = ctx.constraints,\n): Box {\n const nextCtx = withNodeConstraints(ctx, constraints);\n if (node.measureMinContent != null) {\n return node.measureMinContent(nextCtx);\n }\n return node.measure(nextCtx);\n}\n\n/**\n * A node that owns an ordered list of child nodes.\n */\nexport abstract class Group<\n C extends CanvasRenderingContext2D,\n> implements Node<C> {\n #children: Node<C>[];\n\n /**\n * @param children Initial child nodes, in layout order.\n */\n constructor(children: Node<C>[]) {\n this.#children = [...children];\n replaceNodesParent([], this.#children, this);\n }\n\n /** Child nodes managed by this group. */\n get children(): readonly Node<C>[] {\n return this.#children;\n }\n\n /**\n * Replaces the full child list while updating parent links.\n */\n replaceChildren(nextChildren: Node<C>[]): void {\n const nextSnapshot = [...nextChildren];\n replaceNodesParent(this.#children, nextSnapshot, this);\n this.#children = nextSnapshot;\n }\n\n abstract measure(ctx: Context<C>): Box;\n abstract draw(ctx: Context<C>, x: number, y: number): boolean;\n abstract hittest(ctx: Context<C>, test: HitTest): boolean;\n}\n\n/**\n * A node that forwards layout and drawing to a single inner node.\n */\nexport class Wrapper<C extends CanvasRenderingContext2D> implements Node<C> {\n #inner: Node<C>;\n\n /**\n * @param inner Wrapped child node.\n */\n constructor(inner: Node<C>) {\n this.#inner = inner;\n attachNodeToParent(this.#inner, this);\n }\n\n /** The wrapped child node. */\n get inner(): Node<C> {\n return this.#inner;\n }\n\n /** Replaces the wrapped child node. */\n set inner(newNode: Node<C>) {\n if (newNode === this.#inner) {\n return;\n }\n replaceNodeParent(this.#inner, newNode, this);\n this.#inner = newNode;\n }\n\n measure(ctx: Context<C>): Box {\n return this.inner.measure(ctx);\n }\n\n measureMinContent(ctx: Context<C>): Box {\n return measureNodeMinContent(ctx, this.inner);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return this.inner.draw(ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return this.inner.hittest(ctx, test);\n }\n}\n","import type {\n Box,\n ChildLayoutResult,\n FlexLayoutResult,\n LayoutConstraints,\n LayoutRect,\n} from \"./types\";\n\n/**\n * 创建 LayoutRect 的辅助函数\n */\nexport function createRect(\n x: number,\n y: number,\n width: number,\n height: number,\n): LayoutRect {\n return { x, y, width, height };\n}\n\n/**\n * 合并多个 rect 得到包含所有 rect 的最小外接矩形\n */\nexport function mergeRects(rects: LayoutRect[]): LayoutRect {\n if (rects.length === 0) {\n return createRect(0, 0, 0, 0);\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const rect of rects) {\n minX = Math.min(minX, rect.x);\n minY = Math.min(minY, rect.y);\n maxX = Math.max(maxX, rect.x + rect.width);\n maxY = Math.max(maxY, rect.y + rect.height);\n }\n\n return createRect(minX, minY, maxX - minX, maxY - minY);\n}\n\n/**\n * 从子节点布局结果计算容器的 contentBox\n */\nexport function computeContentBox<C extends CanvasRenderingContext2D>(\n children: ChildLayoutResult<C>[],\n): LayoutRect {\n return mergeRects(children.map((child) => child.contentBox));\n}\n\n/**\n * 根据约束和实际内容计算最终的 containerBox\n */\nexport function computeContainerBox(\n contentBox: LayoutRect,\n constraints?: LayoutConstraints,\n): LayoutRect {\n let width = contentBox.width;\n let height = contentBox.height;\n\n if (constraints?.minWidth != null) {\n width = Math.max(width, constraints.minWidth);\n }\n if (constraints?.maxWidth != null) {\n width = Math.min(width, constraints.maxWidth);\n }\n if (constraints?.minHeight != null) {\n height = Math.max(height, constraints.minHeight);\n }\n if (constraints?.maxHeight != null) {\n height = Math.min(height, constraints.maxHeight);\n }\n\n return createRect(contentBox.x, contentBox.y, width, height);\n}\n\n/**\n * 将 Box 转换为 LayoutRect(位置为 0,0)\n */\nexport function boxToRect(box: Box): LayoutRect {\n return createRect(0, 0, box.width, box.height);\n}\n\n/**\n * 检查点是否在 rect 内\n */\nexport function pointInRect(x: number, y: number, rect: LayoutRect): boolean {\n return (\n x >= rect.x &&\n x < rect.x + rect.width &&\n y >= rect.y &&\n y < rect.y + rect.height\n );\n}\n\n/**\n * 平移 rect 的位置\n */\nexport function offsetRect(\n rect: LayoutRect,\n dx: number,\n dy: number,\n): LayoutRect {\n return createRect(rect.x + dx, rect.y + dy, rect.width, rect.height);\n}\n\n/**\n * 读取单子节点布局结果中的唯一 child。\n */\nexport function getSingleChildLayout<C extends CanvasRenderingContext2D>(\n layout: FlexLayoutResult<C>,\n): ChildLayoutResult<C> | undefined {\n return layout.children[0];\n}\n\n/**\n * 在布局结果中按指定盒模型查找命中的 child,并返回局部坐标。\n */\nexport function findChildAtPoint<C extends CanvasRenderingContext2D>(\n children: ChildLayoutResult<C>[],\n x: number,\n y: number,\n box: \"rect\" | \"contentBox\" = \"contentBox\",\n):\n | {\n child: ChildLayoutResult<C>;\n localX: number;\n localY: number;\n }\n | undefined {\n for (let i = children.length - 1; i >= 0; i -= 1) {\n const child = children[i]!;\n const target = box === \"rect\" ? child.rect : child.contentBox;\n if (!pointInRect(x, y, target)) {\n continue;\n }\n return {\n child,\n localX: x - target.x,\n localY: y - target.y,\n };\n }\n return undefined;\n}\n","import { findChildAtPoint } from \"../layout\";\nimport type {\n Context,\n FlexLayoutResult,\n HitTest,\n LayoutConstraints,\n Node,\n} from \"../types\";\nimport { shallow } from \"../utils\";\n\ntype LayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getLayoutResult(\n node: Node<C>,\n constraints?: LayoutConstraints,\n ): FlexLayoutResult<C> | undefined;\n setLayoutResult(\n node: Node<C>,\n result: FlexLayoutResult<C>,\n constraints?: LayoutConstraints,\n ): void;\n};\n\ntype LayoutContext<C extends CanvasRenderingContext2D> = Context<C> &\n LayoutCacheAccess<C>;\n\nexport function withConstraints<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n constraints: LayoutConstraints | undefined,\n): Context<C> {\n const next = shallow(ctx);\n next.constraints = constraints;\n return next;\n}\n\nfunction getLayoutContext<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n): LayoutContext<C> {\n return ctx as LayoutContext<C>;\n}\n\nexport function readLayoutResult<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n): FlexLayoutResult<C> | undefined {\n return getLayoutContext(ctx).getLayoutResult(node, ctx.constraints);\n}\n\nexport function writeLayoutResult<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n result: FlexLayoutResult<C>,\n): void {\n getLayoutContext(ctx).setLayoutResult(node, result, ctx.constraints);\n}\n\nfunction ensureLayoutResult<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n): FlexLayoutResult<C> | undefined {\n return readLayoutResult(node, ctx);\n}\n\nexport function drawLayoutChildren<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n x: number,\n y: number,\n): boolean {\n const layoutResult = ensureLayoutResult(node, ctx);\n if (!layoutResult) {\n return false;\n }\n\n let result = false;\n for (const childResult of layoutResult.children) {\n const childDrawn = childResult.node.draw(\n withConstraints(ctx, childResult.constraints),\n x + childResult.contentBox.x,\n y + childResult.contentBox.y,\n );\n result = childDrawn || result;\n }\n return result;\n}\n\nexport function hittestLayoutChildren<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n test: HitTest,\n box: \"rect\" | \"contentBox\" = \"contentBox\",\n): boolean {\n const layoutResult = ensureLayoutResult(node, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, box);\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(withConstraints(ctx, hit.child.constraints), {\n ...test,\n x: hit.localX,\n y: hit.localY,\n });\n}\n","import { createRect, findChildAtPoint, getSingleChildLayout } from \"../layout\";\nimport type { Box, Context, HitTest, Node } from \"../types\";\nimport { measureNodeMinContent } from \"./base\";\nimport { Wrapper } from \"./base\";\nimport { readLayoutResult, withConstraints, writeLayoutResult } from \"./shared\";\n\nfunction clampToConstraints(value: number, min?: number, max?: number): number {\n let result = value;\n if (min != null) {\n result = Math.max(result, min);\n }\n if (max != null) {\n result = Math.min(result, max);\n }\n return result;\n}\n\nfunction shrinkConstraint(\n value: number | undefined,\n padding: number,\n): number | undefined {\n if (value == null) {\n return undefined;\n }\n return Math.max(0, value - padding);\n}\n\n/**\n * Adds padding around a single child node.\n */\nexport class PaddingBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n /**\n * @param inner Wrapped child node.\n * @param padding Padding in CSS pixels on each side.\n */\n constructor(\n inner: Node<C>,\n readonly padding: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n } = {},\n ) {\n super(inner);\n }\n\n get #top(): number {\n return this.padding.top ?? 0;\n }\n\n get #bottom(): number {\n return this.padding.bottom ?? 0;\n }\n\n get #left(): number {\n return this.padding.left ?? 0;\n }\n\n get #right(): number {\n return this.padding.right ?? 0;\n }\n\n measure(ctx: Context<C>): Box {\n const paddingLeft = this.#left;\n const paddingRight = this.#right;\n const paddingTop = this.#top;\n const paddingBottom = this.#bottom;\n const horizontalPadding = paddingLeft + paddingRight;\n const verticalPadding = paddingTop + paddingBottom;\n const childConstraints = ctx.constraints\n ? {\n ...ctx.constraints,\n minWidth: shrinkConstraint(\n ctx.constraints.minWidth,\n horizontalPadding,\n ),\n maxWidth: shrinkConstraint(\n ctx.constraints.maxWidth,\n horizontalPadding,\n ),\n minHeight: shrinkConstraint(\n ctx.constraints.minHeight,\n verticalPadding,\n ),\n maxHeight: shrinkConstraint(\n ctx.constraints.maxHeight,\n verticalPadding,\n ),\n }\n : undefined;\n const { width, height } = ctx.measureNode(this.inner, childConstraints);\n const containerBox = createRect(\n 0,\n 0,\n clampToConstraints(\n width + horizontalPadding,\n ctx.constraints?.minWidth,\n ctx.constraints?.maxWidth,\n ),\n clampToConstraints(\n height + verticalPadding,\n ctx.constraints?.minHeight,\n ctx.constraints?.maxHeight,\n ),\n );\n const childRect = createRect(paddingLeft, paddingTop, width, height);\n writeLayoutResult(this, ctx, {\n containerBox,\n contentBox: childRect,\n children: [\n {\n node: this.inner,\n rect: childRect,\n contentBox: childRect,\n constraints: childConstraints,\n },\n ],\n constraints: ctx.constraints,\n });\n return {\n width: containerBox.width,\n height: containerBox.height,\n };\n }\n\n measureMinContent(ctx: Context<C>): Box {\n const paddingLeft = this.#left;\n const paddingRight = this.#right;\n const paddingTop = this.#top;\n const paddingBottom = this.#bottom;\n const horizontalPadding = paddingLeft + paddingRight;\n const verticalPadding = paddingTop + paddingBottom;\n const childConstraints = ctx.constraints\n ? {\n ...ctx.constraints,\n minWidth: shrinkConstraint(\n ctx.constraints.minWidth,\n horizontalPadding,\n ),\n maxWidth: shrinkConstraint(\n ctx.constraints.maxWidth,\n horizontalPadding,\n ),\n minHeight: shrinkConstraint(\n ctx.constraints.minHeight,\n verticalPadding,\n ),\n maxHeight: shrinkConstraint(\n ctx.constraints.maxHeight,\n verticalPadding,\n ),\n }\n : undefined;\n const { width, height } = measureNodeMinContent(\n ctx,\n this.inner,\n childConstraints,\n );\n return {\n width: width + horizontalPadding,\n height: height + verticalPadding,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return this.inner.draw(ctx, x + this.#left, y + this.#top);\n }\n\n const childResult = getSingleChildLayout(layoutResult);\n if (!childResult) {\n return false;\n }\n\n return childResult.node.draw(\n withConstraints(ctx, childResult.constraints),\n x + childResult.rect.x,\n y + childResult.rect.y,\n );\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, \"rect\");\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(withConstraints(ctx, hit.child.constraints), {\n ...test,\n x: hit.localX,\n y: hit.localY,\n });\n }\n}\n\n/**\n * A leaf node with a fixed size and no drawing behavior.\n */\nexport class Fixed<C extends CanvasRenderingContext2D> implements Node<C> {\n /**\n * @param width Fixed width in CSS pixels.\n * @param height Fixed height in CSS pixels.\n */\n constructor(\n readonly width: number,\n readonly height: number,\n ) {}\n\n measure(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n measureMinContent(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n draw(_ctx: Context<C>, _x: number, _y: number): boolean {\n return false;\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n","import { computeContentBox, createRect } from \"../layout\";\nimport type {\n Axis,\n Box,\n ChildLayoutResult,\n Context,\n CrossAxisAlignment,\n FlexContainerOptions,\n FlexItemOptions,\n HitTest,\n LayoutConstraints,\n Node,\n} from \"../types\";\nimport { Group, measureNodeMinContent, Wrapper } from \"./base\";\nimport {\n drawLayoutChildren,\n hittestLayoutChildren,\n writeLayoutResult,\n} from \"./shared\";\n\nfunction getMainSize(axis: Axis, box: Box): number {\n return axis === \"row\" ? box.width : box.height;\n}\n\nfunction getCrossSize(axis: Axis, box: Box): number {\n return axis === \"row\" ? box.height : box.width;\n}\n\nfunction getMinMain(\n axis: Axis,\n constraints?: LayoutConstraints,\n): number | undefined {\n return axis === \"row\" ? constraints?.minWidth : constraints?.minHeight;\n}\n\nfunction getMaxMain(\n axis: Axis,\n constraints?: LayoutConstraints,\n): number | undefined {\n return axis === \"row\" ? constraints?.maxWidth : constraints?.maxHeight;\n}\n\nfunction getMinCross(\n axis: Axis,\n constraints?: LayoutConstraints,\n): number | undefined {\n return axis === \"row\" ? constraints?.minHeight : constraints?.minWidth;\n}\n\nfunction getMaxCross(\n axis: Axis,\n constraints?: LayoutConstraints,\n): number | undefined {\n return axis === \"row\" ? constraints?.maxHeight : constraints?.maxWidth;\n}\n\nfunction createAxisConstraints(\n axis: Axis,\n constraints: LayoutConstraints | undefined,\n main: { min?: number; max?: number },\n cross: { min?: number; max?: number } = {},\n): LayoutConstraints | undefined {\n if (\n constraints == null &&\n main.min == null &&\n main.max == null &&\n cross.min == null &&\n cross.max == null\n ) {\n return undefined;\n }\n\n const next: LayoutConstraints = {\n ...constraints,\n };\n if (axis === \"row\") {\n next.minWidth = main.min;\n next.maxWidth = main.max;\n next.minHeight = cross.min;\n next.maxHeight = cross.max;\n } else {\n next.minHeight = main.min;\n next.maxHeight = main.max;\n next.minWidth = cross.min;\n next.maxWidth = cross.max;\n }\n return next;\n}\n\nfunction clampToConstraints(value: number, min?: number, max?: number): number {\n let result = value;\n if (min != null) {\n result = Math.max(result, min);\n }\n if (max != null) {\n result = Math.min(result, max);\n }\n return result;\n}\n\nfunction constraintsEqual(\n left: LayoutConstraints | undefined,\n right: LayoutConstraints | undefined,\n): boolean {\n if (left === right) {\n return true;\n }\n if (left == null || right == null) {\n return left == null && right == null;\n }\n return (\n left.minWidth === right.minWidth &&\n left.maxWidth === right.maxWidth &&\n left.minHeight === right.minHeight &&\n left.maxHeight === right.maxHeight\n );\n}\n\nfunction getCrossAlignment(\n alignSelf: CrossAxisAlignment | \"auto\" | undefined,\n alignItems: CrossAxisAlignment,\n): CrossAxisAlignment {\n if (alignSelf == null || alignSelf === \"auto\") {\n return alignItems;\n }\n return alignSelf;\n}\n\nfunction getJustifySpacing(\n justifyContent: NonNullable<FlexContainerOptions[\"justifyContent\"]>,\n freeSpace: number,\n itemCount: number,\n gap: number,\n): { leading: number; between: number } {\n switch (justifyContent) {\n case \"center\":\n return { leading: freeSpace / 2, between: gap };\n case \"end\":\n return { leading: freeSpace, between: gap };\n case \"space-between\":\n return {\n leading: 0,\n between: itemCount > 1 ? gap + freeSpace / (itemCount - 1) : gap,\n };\n case \"space-around\":\n return {\n leading: itemCount > 0 ? freeSpace / itemCount / 2 : 0,\n between: itemCount > 0 ? gap + freeSpace / itemCount : gap,\n };\n case \"space-evenly\":\n return {\n leading: itemCount > 0 ? freeSpace / (itemCount + 1) : 0,\n between: itemCount > 0 ? gap + freeSpace / (itemCount + 1) : gap,\n };\n case \"start\":\n default:\n return { leading: 0, between: gap };\n }\n}\n\nfunction getCrossOffset(\n align: CrossAxisAlignment,\n frameCross: number,\n contentCross: number,\n): number {\n switch (align) {\n case \"center\":\n return (frameCross - contentCross) / 2;\n case \"end\":\n return frameCross - contentCross;\n case \"stretch\":\n case \"start\":\n default:\n return 0;\n }\n}\n\nfunction createRectFromAxis(\n axis: Axis,\n main: number,\n cross: number,\n mainSize: number,\n crossSize: number,\n) {\n return axis === \"row\"\n ? createRect(main, cross, mainSize, crossSize)\n : createRect(cross, main, crossSize, mainSize);\n}\n\nconst SHRINK_EPSILON = 1e-6;\n\ntype FlexMeasurement<C extends CanvasRenderingContext2D> = {\n child: Node<C>;\n item: FlexItemOptions;\n basisMeasured: Box;\n measured: Box;\n basisConstraints?: LayoutConstraints;\n initialConstraints?: LayoutConstraints;\n finalConstraints?: LayoutConstraints;\n allocatedMain?: number;\n grow: number;\n shrink: number;\n effectiveAlign: CrossAxisAlignment;\n stretch: boolean;\n basis: number;\n minContentMain: number;\n finalMain: number;\n frozen: boolean;\n frameMain: number;\n frameCross: number;\n};\n\ntype MeasuredLayout<C extends CanvasRenderingContext2D> = {\n box: Box;\n layout: {\n containerBox: ChildLayoutResult<C>[\"rect\"];\n contentBox: ChildLayoutResult<C>[\"contentBox\"];\n children: ChildLayoutResult<C>[];\n constraints?: LayoutConstraints;\n };\n};\n\nfunction readFlexItemOptions<C extends CanvasRenderingContext2D>(\n child: Node<C>,\n): FlexItemOptions {\n if (child instanceof FlexItem) {\n return child.item;\n }\n return {};\n}\n\nexport function computeFlexLayout<C extends CanvasRenderingContext2D>(\n children: readonly Node<C>[],\n options: FlexContainerOptions,\n constraints: LayoutConstraints | undefined,\n measureChild: (node: Node<C>, constraints?: LayoutConstraints) => Box,\n measureChildMinContent: (\n node: Node<C>,\n constraints?: LayoutConstraints,\n ) => Box,\n): MeasuredLayout<C> {\n const axis = options.direction ?? \"row\";\n const gap = options.gap ?? 0;\n const justifyContent = options.justifyContent ?? \"start\";\n const alignItems = options.alignItems ?? \"start\";\n const reverse = options.reverse ?? false;\n const mainAxisSize = options.mainAxisSize ?? \"fill\";\n const orderedChildren = reverse ? [...children].reverse() : children;\n const maxMain = getMaxMain(axis, constraints);\n const minMain = getMinMain(axis, constraints);\n const maxCross = getMaxCross(axis, constraints);\n const minCross = getMinCross(axis, constraints);\n const gapTotal =\n orderedChildren.length > 1 ? gap * (orderedChildren.length - 1) : 0;\n const finiteMain = maxMain != null;\n const finiteCross = maxCross != null;\n const availableMain = finiteMain\n ? Math.max(0, maxMain - gapTotal)\n : undefined;\n let totalGrow = 0;\n let totalBasis = 0;\n let nonGrowBasis = 0;\n const measurements = new Map<Node<C>, FlexMeasurement<C>>();\n const basisConstraints = createAxisConstraints(\n axis,\n constraints,\n {\n min: undefined,\n max: undefined,\n },\n {\n min: undefined,\n max: maxCross,\n },\n );\n\n for (const child of orderedChildren) {\n const item = readFlexItemOptions(child);\n const grow = item.grow ?? 0;\n const shrink = item.shrink ?? 0;\n totalGrow += grow;\n const effectiveAlign = getCrossAlignment(item.alignSelf, alignItems);\n const stretch = effectiveAlign === \"stretch\";\n const basisMeasured = measureChild(child, basisConstraints);\n const basis = getMainSize(axis, basisMeasured);\n\n totalBasis += basis;\n if (grow <= 0) {\n nonGrowBasis += basis;\n }\n\n measurements.set(child, {\n child,\n item,\n basisMeasured,\n measured: basisMeasured,\n basisConstraints,\n initialConstraints: basisConstraints,\n finalConstraints: basisConstraints,\n allocatedMain: undefined,\n grow,\n shrink,\n effectiveAlign,\n stretch,\n basis,\n minContentMain: basis,\n finalMain: basis,\n frozen: false,\n frameMain: basis,\n frameCross: getCrossSize(axis, basisMeasured),\n });\n }\n\n const entersShrinkPath =\n finiteMain &&\n availableMain != null &&\n totalBasis - availableMain > SHRINK_EPSILON;\n\n if (entersShrinkPath) {\n const totalDeficit = totalBasis - availableMain!;\n let remainingDeficit = totalDeficit;\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n const minContentMeasured = measureChildMinContent(\n child,\n measurement.basisConstraints,\n );\n measurement.minContentMain = Math.min(\n measurement.basis,\n getMainSize(axis, minContentMeasured),\n );\n measurement.finalMain = measurement.basis;\n measurement.frozen =\n measurement.shrink <= 0 ||\n measurement.basis - measurement.minContentMain <= SHRINK_EPSILON;\n }\n\n while (remainingDeficit > SHRINK_EPSILON) {\n const active = orderedChildren\n .map((child) => measurements.get(child)!)\n .filter((measurement) => !measurement.frozen && measurement.shrink > 0);\n const totalScaled = active.reduce(\n (sum, measurement) => sum + measurement.shrink * measurement.basis,\n 0,\n );\n\n if (active.length === 0 || totalScaled <= SHRINK_EPSILON) {\n break;\n }\n\n let frozeAny = false;\n for (const measurement of active) {\n const tentative =\n measurement.basis -\n remainingDeficit *\n ((measurement.shrink * measurement.basis) / totalScaled);\n if (tentative <= measurement.minContentMain + SHRINK_EPSILON) {\n measurement.finalMain = measurement.minContentMain;\n measurement.frozen = true;\n frozeAny = true;\n } else {\n measurement.finalMain = tentative;\n }\n }\n\n if (!frozeAny) {\n remainingDeficit = 0;\n break;\n }\n\n let absorbedDeficit = 0;\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (measurement.frozen) {\n absorbedDeficit += Math.max(\n 0,\n measurement.basis - measurement.finalMain,\n );\n }\n }\n remainingDeficit = Math.max(0, totalDeficit - absorbedDeficit);\n }\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n measurement.measured = measurement.basisMeasured;\n measurement.initialConstraints = measurement.basisConstraints;\n measurement.finalConstraints = createAxisConstraints(\n axis,\n constraints,\n {\n min: undefined,\n max: measurement.finalMain,\n },\n {\n min: undefined,\n max: maxCross,\n },\n );\n measurement.allocatedMain = undefined;\n measurement.frameMain = measurement.finalMain;\n measurement.frameCross = getCrossSize(axis, measurement.measured);\n }\n } else {\n const remainingMain =\n finiteMain && availableMain != null\n ? Math.max(0, availableMain - nonGrowBasis)\n : undefined;\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (\n !(\n measurement.grow > 0 &&\n finiteMain &&\n remainingMain != null &&\n totalGrow > 0\n )\n ) {\n measurement.measured = measurement.basisMeasured;\n measurement.initialConstraints = measurement.basisConstraints;\n measurement.finalConstraints = finiteMain\n ? createAxisConstraints(\n axis,\n constraints,\n {\n min: undefined,\n max: measurement.finalMain,\n },\n {\n min: undefined,\n max: maxCross,\n },\n )\n : measurement.basisConstraints;\n measurement.allocatedMain = undefined;\n measurement.finalMain = measurement.basis;\n measurement.frameMain = measurement.basis;\n measurement.frameCross = getCrossSize(axis, measurement.measured);\n continue;\n }\n\n const allocatedMain = (remainingMain * measurement.grow) / totalGrow;\n const childConstraints = createAxisConstraints(\n axis,\n constraints,\n {\n max: allocatedMain,\n },\n {\n min: undefined,\n max: maxCross,\n },\n );\n const measured = measureChild(child, childConstraints);\n measurement.measured = measured;\n measurement.initialConstraints = childConstraints;\n measurement.finalConstraints = childConstraints;\n measurement.allocatedMain = allocatedMain;\n measurement.finalMain = allocatedMain;\n measurement.frameMain = allocatedMain;\n measurement.frameCross = getCrossSize(axis, measured);\n }\n }\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (\n !constraintsEqual(\n measurement.initialConstraints,\n measurement.finalConstraints,\n )\n ) {\n measurement.measured = measureChild(child, measurement.finalConstraints);\n }\n measurement.frameMain = measurement.finalMain;\n measurement.frameCross = getCrossSize(axis, measurement.measured);\n }\n\n let contentMain = gapTotal;\n let contentCross = 0;\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n contentMain += measurement.frameMain;\n contentCross = Math.max(contentCross, measurement.frameCross);\n }\n\n const containerMain =\n finiteMain && mainAxisSize === \"fill\"\n ? Math.max(maxMain!, contentMain)\n : clampToConstraints(contentMain, minMain, maxMain);\n const containerCross = clampToConstraints(contentCross, minCross, maxCross);\n if (finiteCross) {\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n if (!measurement.stretch) {\n continue;\n }\n\n const finalConstraints = createAxisConstraints(\n axis,\n measurement.finalConstraints,\n {\n min: getMinMain(axis, measurement.finalConstraints),\n max: getMaxMain(axis, measurement.finalConstraints),\n },\n {\n min: containerCross,\n max: containerCross,\n },\n );\n const remeasured = measureChild(child, finalConstraints);\n measurement.measured = remeasured;\n measurement.finalConstraints = finalConstraints;\n measurement.frameCross = containerCross;\n measurement.frameMain =\n measurement.allocatedMain ?? getMainSize(axis, remeasured);\n }\n\n contentMain = gapTotal;\n contentCross = 0;\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n contentMain += measurement.frameMain;\n contentCross = Math.max(\n contentCross,\n getCrossSize(axis, measurement.measured),\n );\n }\n }\n\n const finalContainerMain =\n finiteMain && mainAxisSize === \"fill\"\n ? Math.max(maxMain!, contentMain)\n : clampToConstraints(contentMain, minMain, maxMain);\n const freeSpace = Math.max(0, finalContainerMain - contentMain);\n const spacing = getJustifySpacing(\n justifyContent,\n freeSpace,\n orderedChildren.length,\n gap,\n );\n const childResults: ChildLayoutResult<C>[] = [];\n let cursor = spacing.leading;\n\n for (const child of orderedChildren) {\n const measurement = measurements.get(child)!;\n const frameCross =\n measurement.stretch && finiteCross\n ? containerCross\n : measurement.frameCross;\n const contentMainSize = getMainSize(axis, measurement.measured);\n const contentCrossSize = getCrossSize(axis, measurement.measured);\n const rectCross = measurement.stretch\n ? 0\n : getCrossOffset(measurement.effectiveAlign, containerCross, frameCross);\n const contentCrossOffset =\n rectCross +\n getCrossOffset(measurement.effectiveAlign, frameCross, contentCrossSize);\n const rect = createRectFromAxis(\n axis,\n cursor,\n rectCross,\n measurement.frameMain,\n frameCross,\n );\n const contentBox = createRectFromAxis(\n axis,\n cursor,\n contentCrossOffset,\n contentMainSize,\n contentCrossSize,\n );\n\n childResults.push({\n node: child,\n rect,\n contentBox,\n constraints: measurement.finalConstraints,\n });\n cursor += measurement.frameMain + spacing.between;\n }\n\n const containerBox =\n axis === \"row\"\n ? createRect(0, 0, finalContainerMain, containerCross)\n : createRect(0, 0, containerCross, finalContainerMain);\n const finalContentBox =\n childResults.length > 0\n ? computeContentBox(childResults)\n : createRect(0, 0, 0, 0);\n\n return {\n box: {\n width: containerBox.width,\n height: containerBox.height,\n },\n layout: {\n containerBox,\n contentBox: finalContentBox,\n children: childResults,\n constraints,\n },\n };\n}\n\n/**\n * Wraps a child node with per-item flex options.\n */\nexport class FlexItem<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n /**\n * @param inner Wrapped child node.\n * @param item Flex behavior overrides for the child.\n */\n constructor(\n inner: Node<C>,\n readonly item: FlexItemOptions = {},\n ) {\n super(inner);\n }\n}\n\n/**\n * Lays out children in a single flex row or column.\n */\nexport class Flex<C extends CanvasRenderingContext2D> extends Group<C> {\n /**\n * @param children Child nodes in visual order.\n * @param options Flex container configuration.\n */\n constructor(\n children: Node<C>[],\n readonly options: FlexContainerOptions = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n const result = computeFlexLayout(\n this.children,\n this.options,\n ctx.constraints,\n (node, constraints) => ctx.measureNode(node, constraints),\n (node, constraints) => measureNodeMinContent(ctx, node, constraints),\n );\n writeLayoutResult(this, ctx, result.layout);\n return result.box;\n }\n\n measureMinContent(ctx: Context<C>): Box {\n const axis = this.options.direction ?? \"row\";\n const gap = this.options.gap ?? 0;\n const orderedChildren = this.options.reverse\n ? [...this.children].reverse()\n : this.children;\n const gapTotal =\n orderedChildren.length > 1 ? gap * (orderedChildren.length - 1) : 0;\n const childConstraints = createAxisConstraints(\n axis,\n ctx.constraints,\n {\n min: undefined,\n max: undefined,\n },\n {\n min: undefined,\n max: getMaxCross(axis, ctx.constraints),\n },\n );\n\n let width = axis === \"row\" ? gapTotal : 0;\n let height = axis === \"column\" ? gapTotal : 0;\n\n for (const child of orderedChildren) {\n const measured = measureNodeMinContent(ctx, child, childConstraints);\n if (axis === \"row\") {\n width += measured.width;\n height = Math.max(height, measured.height);\n } else {\n width = Math.max(width, measured.width);\n height += measured.height;\n }\n }\n\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return drawLayoutChildren(this, ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return hittestLayoutChildren(this, ctx, test, \"contentBox\");\n }\n}\n","import { createRect, findChildAtPoint, getSingleChildLayout } from \"../layout\";\nimport type { Box, Context, HitTest, Node, TextAlign } from \"../types\";\nimport { measureNodeMinContent, Wrapper } from \"./base\";\nimport { readLayoutResult, withConstraints, writeLayoutResult } from \"./shared\";\n\nfunction resolveHorizontalOffset(\n align: TextAlign,\n availableWidth: number,\n childWidth: number,\n): number {\n switch (align) {\n case \"center\":\n return (availableWidth - childWidth) / 2;\n case \"end\":\n return availableWidth - childWidth;\n case \"start\":\n return 0;\n }\n}\n\n/**\n * Aligns a single child horizontally within the available width.\n */\nexport class Place<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n /**\n * @param inner Wrapped child node.\n * @param options Alignment behavior for the child.\n */\n constructor(\n inner: Node<C>,\n readonly options: {\n align?: TextAlign;\n expand?: boolean;\n } = {},\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n const availableWidth = ctx.constraints?.maxWidth;\n const expand = this.options.expand ?? true;\n const childConstraints = ctx.constraints\n ? {\n ...ctx.constraints,\n }\n : undefined;\n const childBox = ctx.measureNode(this.inner, childConstraints);\n let width =\n expand && availableWidth != null ? availableWidth : childBox.width;\n if (ctx.constraints?.minWidth != null) {\n width = Math.max(width, ctx.constraints.minWidth);\n }\n if (ctx.constraints?.maxWidth != null) {\n width = Math.min(width, ctx.constraints.maxWidth);\n }\n\n const align = this.options.align ?? \"start\";\n const childRect = createRect(\n resolveHorizontalOffset(align, width, childBox.width),\n 0,\n childBox.width,\n childBox.height,\n );\n\n writeLayoutResult(this, ctx, {\n containerBox: createRect(0, 0, width, childBox.height),\n contentBox: childRect,\n children: [\n {\n node: this.inner,\n rect: childRect,\n contentBox: createRect(0, 0, childBox.width, childBox.height),\n constraints: childConstraints,\n },\n ],\n constraints: ctx.constraints,\n });\n\n return {\n width,\n height: childBox.height,\n };\n }\n\n measureMinContent(ctx: Context<C>): Box {\n return measureNodeMinContent(ctx, this.inner);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return this.inner.draw(ctx, x, y);\n }\n\n const childResult = getSingleChildLayout(layoutResult);\n if (!childResult) {\n return false;\n }\n const childCtx = withConstraints(ctx, childResult.constraints);\n return childResult.node.draw(\n childCtx,\n x + childResult.rect.x,\n y + childResult.rect.y,\n );\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, \"rect\");\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(withConstraints(ctx, hit.child.constraints), {\n ...test,\n x: hit.localX,\n y: hit.localY,\n });\n }\n}\n","import { createRect, findChildAtPoint, getSingleChildLayout } from \"../layout\";\nimport type { Box, Context, HitTest, LayoutConstraints, Node } from \"../types\";\nimport { measureNodeMinContent, Wrapper } from \"./base\";\nimport { readLayoutResult, withConstraints, writeLayoutResult } from \"./shared\";\n\nexport interface ShrinkWrapOptions {\n tolerance?: number;\n preferredMinWidth?: number;\n}\n\nconst DEFAULT_TOLERANCE = 0.5;\nconst HEIGHT_EPSILON = 1e-6;\n\ntype ShrinkwrapProbeResult = {\n maxWidth: number;\n box: Box;\n};\n\nfunction withMaxWidth(\n constraints: LayoutConstraints | undefined,\n maxWidth: number,\n): LayoutConstraints {\n return {\n ...constraints,\n maxWidth,\n };\n}\n\nfunction computeShrinkwrapWidth(\n measure: (maxWidth: number) => Box,\n lowerBound: number,\n upperBound: number,\n referenceHeight: number,\n tolerance = DEFAULT_TOLERANCE,\n): ShrinkwrapProbeResult {\n const minWidth = Math.min(lowerBound, upperBound);\n const maxWidth = Math.max(lowerBound, upperBound);\n const effectiveTolerance = Math.max(tolerance, HEIGHT_EPSILON);\n const lowerBoundBox = measure(minWidth);\n if (lowerBoundBox.height <= referenceHeight + HEIGHT_EPSILON) {\n return {\n maxWidth: minWidth,\n box: lowerBoundBox,\n };\n }\n\n let lo = minWidth;\n let hi = maxWidth;\n let hiBox = measure(maxWidth);\n\n while (hi - lo > effectiveTolerance) {\n const probeWidth = (lo + hi) / 2;\n const probeBox = measure(probeWidth);\n if (probeBox.height <= referenceHeight + HEIGHT_EPSILON) {\n hi = probeWidth;\n hiBox = probeBox;\n continue;\n }\n lo = probeWidth;\n }\n\n return {\n maxWidth: hi,\n box: hiBox,\n };\n}\n\n/**\n * Shrinks a single child to the narrowest width that does not increase its reference height.\n */\nexport class ShrinkWrap<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n constructor(\n inner: Node<C>,\n readonly options: ShrinkWrapOptions = {},\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n const constraints = ctx.constraints;\n const availableWidth = constraints?.maxWidth;\n if (availableWidth == null) {\n const childConstraints =\n constraints == null ? undefined : { ...constraints };\n const childBox = ctx.measureNode(this.inner, childConstraints);\n this.#writeLayout(ctx, childBox, childConstraints);\n return childBox;\n }\n\n const boundedConstraints =\n constraints == null ? { maxWidth: availableWidth } : constraints;\n const referenceConstraints = { ...boundedConstraints };\n const referenceBox = ctx.measureNode(this.inner, referenceConstraints);\n let lowerBound = measureNodeMinContent(\n ctx,\n this.inner,\n boundedConstraints,\n ).width;\n const preferredMinWidth =\n this.options.preferredMinWidth == null\n ? undefined\n : Math.max(0, this.options.preferredMinWidth);\n if (preferredMinWidth != null && preferredMinWidth <= availableWidth) {\n lowerBound = Math.max(lowerBound, preferredMinWidth);\n }\n if (boundedConstraints.minWidth != null) {\n lowerBound = Math.max(lowerBound, boundedConstraints.minWidth);\n }\n if (lowerBound >= availableWidth) {\n this.#writeLayout(ctx, referenceBox, referenceConstraints);\n return referenceBox;\n }\n\n const finalProbe = computeShrinkwrapWidth(\n (maxWidth) =>\n ctx.measureNode(this.inner, withMaxWidth(boundedConstraints, maxWidth)),\n lowerBound,\n availableWidth,\n referenceBox.height,\n this.options.tolerance ?? DEFAULT_TOLERANCE,\n );\n const finalConstraints = withMaxWidth(\n boundedConstraints,\n finalProbe.maxWidth,\n );\n const finalBox = ctx.measureNode(this.inner, finalConstraints);\n this.#writeLayout(ctx, finalBox, finalConstraints);\n return finalBox;\n }\n\n measureMinContent(ctx: Context<C>): Box {\n return measureNodeMinContent(ctx, this.inner);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return this.inner.draw(ctx, x, y);\n }\n\n const childResult = getSingleChildLayout(layoutResult);\n if (!childResult) {\n return false;\n }\n\n return childResult.node.draw(\n withConstraints(ctx, childResult.constraints),\n x + childResult.rect.x,\n y + childResult.rect.y,\n );\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const layoutResult = readLayoutResult(this, ctx);\n if (!layoutResult) {\n return false;\n }\n\n const hit = findChildAtPoint(layoutResult.children, test.x, test.y, \"rect\");\n if (!hit) {\n return false;\n }\n\n return hit.child.node.hittest(withConstraints(ctx, hit.child.constraints), {\n ...test,\n x: hit.localX,\n y: hit.localY,\n });\n }\n\n #writeLayout(\n ctx: Context<C>,\n childBox: Box,\n childConstraints: LayoutConstraints | undefined,\n ): void {\n const childRect = createRect(0, 0, childBox.width, childBox.height);\n writeLayoutResult(this, ctx, {\n containerBox: childRect,\n contentBox: childRect,\n children: [\n {\n node: this.inner,\n rect: childRect,\n contentBox: childRect,\n constraints: childConstraints,\n },\n ],\n constraints: ctx.constraints,\n });\n }\n}\n","import type { Context, TextEllipsisPosition } from \"../types\";\n\nexport const FONT_SHIFT_PROBE = \"M\";\nexport const ELLIPSIS_GLYPH = \"…\";\nexport const INTRINSIC_MAX_WIDTH = Number.POSITIVE_INFINITY;\nexport const MIN_CONTENT_WIDTH_EPSILON = 0.001;\n\nlet sharedGraphemeSegmenter: Intl.Segmenter | null | undefined;\nconst fontShiftCache = new Map<string, number>();\nconst ellipsisWidthCache = new Map<string, number>();\n\nexport function readLruValue<T>(\n cache: Map<string, T>,\n key: string,\n): T | undefined {\n const cached = cache.get(key);\n if (cached == null) {\n return undefined;\n }\n cache.delete(key);\n cache.set(key, cached);\n return cached;\n}\n\nexport function writeLruValue<T>(\n cache: Map<string, T>,\n key: string,\n value: T,\n capacity: number,\n): T {\n if (cache.has(key)) {\n cache.delete(key);\n } else if (cache.size >= capacity) {\n const firstKey = cache.keys().next().value;\n if (firstKey != null) {\n cache.delete(firstKey);\n }\n }\n cache.set(key, value);\n return value;\n}\n\nexport function measureFontShift<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n): number {\n const font = ctx.graphics.font;\n const cached = fontShiftCache.get(font);\n if (cached != null) {\n return cached;\n }\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(FONT_SHIFT_PROBE);\n const shift = ascent - descent;\n fontShiftCache.set(font, shift);\n return shift;\n}\n\nexport function measureEllipsisWidth<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n): number {\n const font = ctx.graphics.font;\n const cached = ellipsisWidthCache.get(font);\n if (cached != null) {\n return cached;\n }\n const width = ctx.graphics.measureText(ELLIPSIS_GLYPH).width;\n ellipsisWidthCache.set(font, width);\n return width;\n}\n\nfunction getGraphemeSegmenter(): Intl.Segmenter | null {\n if (sharedGraphemeSegmenter !== undefined) {\n return sharedGraphemeSegmenter;\n }\n sharedGraphemeSegmenter =\n typeof Intl.Segmenter === \"function\"\n ? new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n : null;\n return sharedGraphemeSegmenter;\n}\n\nexport function splitGraphemes(text: string): string[] {\n const segmenter = getGraphemeSegmenter();\n if (segmenter == null) {\n return Array.from(text);\n }\n const graphemes: string[] = [];\n for (const part of segmenter.segment(text)) {\n graphemes.push(part.segment);\n }\n return graphemes;\n}\n\nexport function buildPrefixWidths(widths: readonly number[]): number[] {\n const cumulativeWidths = [0];\n let total = 0;\n for (const width of widths) {\n total += width;\n cumulativeWidths.push(total);\n }\n return cumulativeWidths;\n}\n\nexport function buildSuffixWidths(widths: readonly number[]): number[] {\n const cumulativeWidths = [0];\n let total = 0;\n for (let index = widths.length - 1; index >= 0; index -= 1) {\n total += widths[index] ?? 0;\n cumulativeWidths.push(total);\n }\n return cumulativeWidths;\n}\n\nexport function findMaxFittingCount(\n cumulativeWidths: readonly number[],\n maxWidth: number,\n): number {\n if (maxWidth <= 0) {\n return 0;\n }\n let low = 0;\n let high = cumulativeWidths.length - 1;\n while (low < high) {\n const mid = Math.floor((low + high + 1) / 2);\n if ((cumulativeWidths[mid] ?? 0) <= maxWidth) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return low;\n}\n\nexport function normalizeMaxLines(\n maxLines: number | undefined,\n): number | undefined {\n if (maxLines == null || !Number.isFinite(maxLines)) {\n return undefined;\n }\n return Math.max(1, Math.trunc(maxLines));\n}\n\nexport function selectEllipsisUnitCounts({\n position,\n prefixWidths,\n suffixWidths,\n unitCount,\n availableWidth,\n getMaxSuffixCount = (prefixCount) => unitCount - prefixCount,\n}: {\n position: TextEllipsisPosition;\n prefixWidths: readonly number[];\n suffixWidths: readonly number[];\n unitCount: number;\n availableWidth: number;\n getMaxSuffixCount?: (prefixCount: number) => number;\n}): { prefixCount: number; suffixCount: number } {\n let prefixCount = 0;\n let suffixCount = 0;\n\n switch (position) {\n case \"start\":\n suffixCount = Math.min(\n unitCount,\n findMaxFittingCount(suffixWidths, availableWidth),\n );\n break;\n case \"middle\": {\n let bestVisibleUnits = -1;\n let bestBalanceScore = Number.NEGATIVE_INFINITY;\n for (\n let nextPrefixCount = 0;\n nextPrefixCount <= unitCount;\n nextPrefixCount += 1\n ) {\n const prefixWidth = prefixWidths[nextPrefixCount] ?? 0;\n if (prefixWidth > availableWidth) {\n break;\n }\n const remainingWidth = availableWidth - prefixWidth;\n const maxSuffixCount = Math.max(0, getMaxSuffixCount(nextPrefixCount));\n const nextSuffixCount = Math.min(\n maxSuffixCount,\n findMaxFittingCount(suffixWidths, remainingWidth),\n );\n const visibleUnits = nextPrefixCount + nextSuffixCount;\n const balanceScore = -Math.abs(nextPrefixCount - nextSuffixCount);\n if (\n visibleUnits > bestVisibleUnits ||\n (visibleUnits === bestVisibleUnits &&\n balanceScore > bestBalanceScore) ||\n (visibleUnits === bestVisibleUnits &&\n balanceScore === bestBalanceScore &&\n nextPrefixCount > prefixCount)\n ) {\n prefixCount = nextPrefixCount;\n suffixCount = nextSuffixCount;\n bestVisibleUnits = visibleUnits;\n bestBalanceScore = balanceScore;\n }\n }\n break;\n }\n case \"end\":\n prefixCount = Math.min(\n unitCount,\n findMaxFittingCount(prefixWidths, availableWidth),\n );\n break;\n }\n\n return { prefixCount, suffixCount };\n}\n\nexport function resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position,\n}: {\n widths: readonly number[];\n ellipsisWidth: number;\n maxWidth: number;\n position: TextEllipsisPosition;\n}): { prefixCount: number; suffixCount: number; width: number } | undefined {\n if (ellipsisWidth > maxWidth) {\n return undefined;\n }\n\n const prefixWidths = buildPrefixWidths(widths);\n const suffixWidths = buildSuffixWidths(widths);\n const { prefixCount, suffixCount } = selectEllipsisUnitCounts({\n position,\n prefixWidths,\n suffixWidths,\n unitCount: widths.length,\n availableWidth: Math.max(0, maxWidth - ellipsisWidth),\n });\n\n const width =\n position === \"start\"\n ? ellipsisWidth + (suffixWidths[suffixCount] ?? 0)\n : position === \"middle\"\n ? (prefixWidths[prefixCount] ?? 0) +\n ellipsisWidth +\n (suffixWidths[suffixCount] ?? 0)\n : (prefixWidths[prefixCount] ?? 0) + ellipsisWidth;\n\n return { prefixCount, suffixCount, width };\n}\n","import type {\n Context,\n InlineSpan,\n TextEllipsisPosition,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n buildPrefixWidths,\n buildSuffixWidths,\n measureEllipsisWidth,\n readLruValue,\n selectEllipsisUnitCounts,\n splitGraphemes,\n writeLruValue,\n} from \"./core\";\n\nconst LINE_FIT_EPSILON = 0.005;\nconst PREPARED_INLINE_CACHE_CAPACITY = 512;\nconst PREPARED_LINE_STATS_CACHE_CAPACITY = 16;\n\ntype MeasureContext =\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D;\n\ntype SourceItem = {\n text: string;\n font: string;\n itemIndex: number;\n breakMode: \"normal\" | \"never\";\n extraWidth: number;\n};\n\nexport type InlineAtom = {\n text: string;\n font: string;\n itemIndex: number;\n width: number;\n extraWidthAfter: number;\n kind: \"text\" | \"space\";\n preservesLineEnd: boolean;\n atomicGroupId: number | null;\n};\n\nexport type PreparedInlineUnit = {\n kind: \"text\" | \"space\";\n atoms: InlineAtom[];\n width: number;\n fitEndWidth: number;\n paintEndWidth: number;\n breakAfter: boolean;\n breakable: boolean;\n atomic: boolean;\n};\n\nexport type PreparedInlineChunk = {\n startUnit: number;\n endUnit: number;\n};\n\nexport type PreparedInlineLayout = {\n units: PreparedInlineUnit[];\n chunks: PreparedInlineChunk[];\n whiteSpace: TextWhiteSpaceMode;\n wordBreak: TextWordBreakMode;\n lineStatsCache: Map<number, PreparedInlineStats>;\n minContentWidthCache: Map<TextOverflowWrapMode, number>;\n};\n\nexport type PreparedInlineCursor = {\n chunkIndex: number;\n unitIndex: number;\n atomIndex: number;\n};\n\nexport type PreparedInlineLineRange = {\n width: number;\n start: PreparedInlineCursor;\n end: PreparedInlineCursor;\n next: PreparedInlineCursor;\n};\n\nexport type PreparedInlineStats = {\n lineCount: number;\n maxLineWidth: number;\n};\n\nexport type PreparedInlineAtomSlice = {\n atoms: InlineAtom[];\n width: number;\n};\n\nconst kinsokuStart = new Set([\n \"\\uFF0C\",\n \"\\uFF0E\",\n \"\\uFF01\",\n \"\\uFF1A\",\n \"\\uFF1B\",\n \"\\uFF1F\",\n \"\\u3001\",\n \"\\u3002\",\n \"\\u30FB\",\n \"\\uFF09\",\n \"\\u3015\",\n \"\\u3009\",\n \"\\u300B\",\n \"\\u300D\",\n \"\\u300F\",\n \"\\u3011\",\n \"\\u3017\",\n \"\\u3019\",\n \"\\u301B\",\n \"\\u30FC\",\n \"\\u3005\",\n \"\\u303B\",\n \"\\u309D\",\n \"\\u309E\",\n \"\\u30FD\",\n \"\\u30FE\",\n]);\n\nconst kinsokuEnd = new Set([\n '\"',\n \"(\",\n \"[\",\n \"{\",\n \"“\",\n \"‘\",\n \"«\",\n \"‹\",\n \"\\uFF08\",\n \"\\u3014\",\n \"\\u3008\",\n \"\\u300A\",\n \"\\u300C\",\n \"\\u300E\",\n \"\\u3010\",\n \"\\u3016\",\n \"\\u3018\",\n \"\\u301A\",\n]);\n\nconst leftStickyPunctuation = new Set([\n \".\",\n \",\",\n \"!\",\n \"?\",\n \":\",\n \";\",\n \"\\u060C\",\n \"\\u061B\",\n \"\\u061F\",\n \"\\u0964\",\n \"\\u0965\",\n \"\\u104A\",\n \"\\u104B\",\n \"\\u104C\",\n \"\\u104D\",\n \"\\u104F\",\n \")\",\n \"]\",\n \"}\",\n \"%\",\n '\"',\n \"”\",\n \"’\",\n \"»\",\n \"›\",\n \"…\",\n]);\n\nconst keepAllGlueChars = new Set([\"\\u00A0\", \"\\u202F\", \"\\u2060\", \"\\uFEFF\"]);\n\nconst closingQuoteChars = new Set([\n \"”\",\n \"’\",\n \"»\",\n \"›\",\n \"\\u300D\",\n \"\\u300F\",\n \"\\u3011\",\n]);\n\nconst cjkCodePointRanges: Array<[number, number]> = [\n [0x4e00, 0x9fff],\n [0x3400, 0x4dbf],\n [0x20000, 0x2a6df],\n [0x2a700, 0x2b73f],\n [0x2b740, 0x2b81f],\n [0x2b820, 0x2ceaf],\n [0x2ceb0, 0x2ebef],\n [0x2ebf0, 0x2ee5d],\n [0x2f800, 0x2fa1f],\n [0x30000, 0x3134f],\n [0x31350, 0x323af],\n [0x323b0, 0x33479],\n [0xf900, 0xfaff],\n [0x3000, 0x303f],\n [0x3040, 0x309f],\n [0x30a0, 0x30ff],\n [0xac00, 0xd7af],\n [0xff00, 0xffef],\n];\n\nlet sharedMeasureContext: MeasureContext | null = null;\nlet sharedWordSegmenter: Intl.Segmenter | null | undefined;\nconst textWidthCache = new Map<string, Map<string, number>>();\nconst preparedInlineCache = new Map<string, PreparedInlineLayout>();\n\nfunction getMeasureContext(): MeasureContext {\n if (sharedMeasureContext != null) {\n return sharedMeasureContext;\n }\n if (typeof OffscreenCanvas !== \"undefined\") {\n const ctx = new OffscreenCanvas(1, 1).getContext(\"2d\");\n if (ctx != null) {\n sharedMeasureContext = ctx;\n return ctx;\n }\n }\n if (typeof document !== \"undefined\") {\n const ctx = document.createElement(\"canvas\").getContext(\"2d\");\n if (ctx != null) {\n sharedMeasureContext = ctx;\n return ctx;\n }\n }\n throw new Error(\n \"Text measurement requires OffscreenCanvas or a DOM canvas context.\",\n );\n}\n\nfunction getTextWidthCache(font: string): Map<string, number> {\n let cache = textWidthCache.get(font);\n if (cache == null) {\n cache = new Map<string, number>();\n textWidthCache.set(font, cache);\n }\n return cache;\n}\n\nfunction measureTextWidth(font: string, text: string): number {\n const cache = getTextWidthCache(font);\n const cached = cache.get(text);\n if (cached != null) {\n return cached;\n }\n const ctx = getMeasureContext();\n ctx.font = font;\n const width = ctx.measureText(text).width;\n cache.set(text, width);\n return width;\n}\n\nfunction isCollapsibleWhitespace(text: string): boolean {\n return /^[ \\t\\n\\f\\r]+$/u.test(text);\n}\n\nfunction isPreservedWhitespaceGrapheme(text: string): boolean {\n return text === \" \" || text === \"\\t\";\n}\n\nfunction normalizePreWrapText(text: string): string {\n if (!/[\\r\\f]/.test(text)) {\n return text.replace(/\\r\\n/g, \"\\n\");\n }\n return text.replace(/\\r\\n/g, \"\\n\").replace(/[\\r\\f]/g, \"\\n\");\n}\n\nfunction getLastCodePoint(text: string): string | null {\n if (text.length === 0) {\n return null;\n }\n const codePoints = Array.from(text);\n return codePoints[codePoints.length - 1] ?? null;\n}\n\nfunction isCJKCodePoint(codePoint: number): boolean {\n for (const [start, end] of cjkCodePointRanges) {\n if (codePoint >= start && codePoint <= end) {\n return true;\n }\n }\n return false;\n}\n\nexport function isCJK(text: string): boolean {\n for (const char of text) {\n const codePoint = char.codePointAt(0);\n if (codePoint != null && isCJKCodePoint(codePoint)) {\n return true;\n }\n }\n return false;\n}\n\nfunction endsWithClosingQuote(text: string): boolean {\n const last = getLastCodePoint(text);\n return last != null && closingQuoteChars.has(last);\n}\n\nfunction endsWithKeepAllGlueText(text: string): boolean {\n const last = getLastCodePoint(text);\n return last != null && keepAllGlueChars.has(last);\n}\n\nfunction endsWithLineStartProhibitedText(text: string): boolean {\n const last = getLastCodePoint(text);\n return (\n last != null && (kinsokuStart.has(last) || leftStickyPunctuation.has(last))\n );\n}\n\nfunction canContinueKeepAllTextRun(text: string): boolean {\n return (\n !endsWithLineStartProhibitedText(text) && !endsWithKeepAllGlueText(text)\n );\n}\n\nfunction getSharedWordSegmenter(): Intl.Segmenter | null {\n if (sharedWordSegmenter !== undefined) {\n return sharedWordSegmenter;\n }\n sharedWordSegmenter =\n typeof Intl.Segmenter === \"function\"\n ? new Intl.Segmenter(undefined, { granularity: \"word\" })\n : null;\n return sharedWordSegmenter;\n}\n\nfunction sumAtomWidths(\n atoms: readonly InlineAtom[],\n start = 0,\n end = atoms.length,\n): number {\n let width = 0;\n for (let index = start; index < end; index += 1) {\n const atom = atoms[index];\n if (atom != null) {\n width += atom.width + atom.extraWidthAfter;\n }\n }\n return width;\n}\n\nfunction joinAtomText(\n atoms: readonly InlineAtom[],\n start = 0,\n end = atoms.length,\n): string {\n let text = \"\";\n for (let index = start; index < end; index += 1) {\n const atom = atoms[index];\n if (atom != null) {\n text += atom.text;\n }\n }\n return text;\n}\n\nfunction measureAtomSequenceWidth(atoms: readonly InlineAtom[]): number {\n if (atoms.length === 0) {\n return 0;\n }\n let width = 0;\n let currentFont = atoms[0]!.font;\n let currentText = \"\";\n for (const atom of atoms) {\n if (atom.font !== currentFont && currentText.length > 0) {\n width += measureTextWidth(currentFont, currentText);\n currentFont = atom.font;\n currentText = \"\";\n }\n currentText += atom.text;\n width += atom.extraWidthAfter;\n }\n if (currentText.length > 0) {\n width += measureTextWidth(currentFont, currentText);\n }\n return width;\n}\n\nfunction pushTextPartAtoms(\n target: InlineAtom[],\n text: string,\n font: string,\n itemIndex: number,\n atomicGroupId: number | null,\n extraWidth: number,\n): void {\n const graphemes = splitGraphemes(text);\n for (let index = 0; index < graphemes.length; index += 1) {\n const grapheme = graphemes[index] ?? \"\";\n target.push({\n text: grapheme,\n font,\n itemIndex,\n width: measureTextWidth(font, grapheme),\n extraWidthAfter: index === graphemes.length - 1 ? extraWidth : 0,\n kind: \"text\",\n preservesLineEnd: false,\n atomicGroupId,\n });\n }\n}\n\nfunction buildCollapsedWhitespaceAtoms(\n items: readonly SourceItem[],\n): InlineAtom[][] {\n const chunks: InlineAtom[][] = [[]];\n const atoms = chunks[0]!;\n let pendingSpace: {\n font: string;\n itemIndex: number;\n atomicGroupId: number | null;\n } | null = null;\n let lastVisible: {\n font: string;\n itemIndex: number;\n atomicGroupId: number | null;\n } | null = null;\n\n for (const item of items) {\n const atomicGroupId =\n item.breakMode === \"never\" ? item.itemIndex + 1 : null;\n const parts = item.text.match(/[ \\t\\n\\f\\r]+|[^ \\t\\n\\f\\r]+/gu) ?? [];\n for (let partIndex = 0; partIndex < parts.length; partIndex += 1) {\n const part = parts[partIndex] ?? \"\";\n if (isCollapsibleWhitespace(part)) {\n if (lastVisible != null) {\n pendingSpace = {\n font: lastVisible.font,\n itemIndex: lastVisible.itemIndex,\n atomicGroupId,\n };\n }\n continue;\n }\n\n if (pendingSpace != null) {\n atoms.push({\n text: \" \",\n font: pendingSpace.font,\n itemIndex: pendingSpace.itemIndex,\n width: measureTextWidth(pendingSpace.font, \" \"),\n extraWidthAfter: 0,\n kind: \"space\",\n preservesLineEnd: false,\n atomicGroupId: pendingSpace.atomicGroupId,\n });\n pendingSpace = null;\n }\n\n pushTextPartAtoms(\n atoms,\n part,\n item.font,\n item.itemIndex,\n atomicGroupId,\n partIndex === parts.length - 1 ? item.extraWidth : 0,\n );\n lastVisible = {\n font: item.font,\n itemIndex: item.itemIndex,\n atomicGroupId,\n };\n }\n }\n\n return chunks;\n}\n\nfunction buildPreWrapAtoms(items: readonly SourceItem[]): InlineAtom[][] {\n const chunks: InlineAtom[][] = [[]];\n let currentChunk = chunks[0]!;\n\n for (const item of items) {\n const atomicGroupId =\n item.breakMode === \"never\" ? item.itemIndex + 1 : null;\n const normalizedText = normalizePreWrapText(item.text);\n const graphemes = splitGraphemes(normalizedText);\n for (let index = 0; index < graphemes.length; index += 1) {\n const grapheme = graphemes[index] ?? \"\";\n if (grapheme === \"\\n\") {\n currentChunk = [];\n chunks.push(currentChunk);\n continue;\n }\n const isSpace = isPreservedWhitespaceGrapheme(grapheme);\n currentChunk.push({\n text: grapheme,\n font: item.font,\n itemIndex: item.itemIndex,\n width: measureTextWidth(item.font, grapheme),\n extraWidthAfter: index === graphemes.length - 1 ? item.extraWidth : 0,\n kind: isSpace ? \"space\" : \"text\",\n preservesLineEnd: isSpace,\n atomicGroupId,\n });\n }\n }\n\n return chunks;\n}\n\nfunction buildBaseCjkUnits(atoms: readonly InlineAtom[]): InlineAtom[][] {\n const units: InlineAtom[][] = [];\n let current: InlineAtom[] = [];\n let currentContainsCJK = false;\n let currentEndsWithClosingQuote = false;\n let currentIsSingleKinsokuEnd = false;\n\n const flushCurrent = () => {\n if (current.length === 0) {\n return;\n }\n units.push(current);\n current = [];\n currentContainsCJK = false;\n currentEndsWithClosingQuote = false;\n currentIsSingleKinsokuEnd = false;\n };\n\n for (const atom of atoms) {\n const atomContainsCJK = isCJK(atom.text);\n if (current.length === 0) {\n current = [atom];\n currentContainsCJK = atomContainsCJK;\n currentEndsWithClosingQuote = endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = kinsokuEnd.has(atom.text);\n continue;\n }\n\n if (\n currentIsSingleKinsokuEnd ||\n kinsokuStart.has(atom.text) ||\n leftStickyPunctuation.has(atom.text) ||\n (atomContainsCJK && currentEndsWithClosingQuote)\n ) {\n current.push(atom);\n currentContainsCJK = currentContainsCJK || atomContainsCJK;\n currentEndsWithClosingQuote = leftStickyPunctuation.has(atom.text)\n ? currentEndsWithClosingQuote || endsWithClosingQuote(atom.text)\n : endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = false;\n continue;\n }\n\n if (!currentContainsCJK && !atomContainsCJK) {\n current.push(atom);\n currentEndsWithClosingQuote = endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = false;\n continue;\n }\n\n flushCurrent();\n current = [atom];\n currentContainsCJK = atomContainsCJK;\n currentEndsWithClosingQuote = endsWithClosingQuote(atom.text);\n currentIsSingleKinsokuEnd = kinsokuEnd.has(atom.text);\n }\n\n flushCurrent();\n return units;\n}\n\nfunction mergeKeepAllUnits(units: readonly InlineAtom[][]): InlineAtom[][] {\n if (units.length <= 1) {\n return units.slice();\n }\n\n const merged: InlineAtom[][] = [];\n let current = units[0]!.slice();\n let currentText = joinAtomText(current);\n let currentContainsCJK = isCJK(currentText);\n let currentCanContinue = canContinueKeepAllTextRun(currentText);\n\n const flush = () => {\n merged.push(current);\n };\n\n for (let index = 1; index < units.length; index += 1) {\n const next = units[index]!;\n const nextText = joinAtomText(next);\n const nextContainsCJK = isCJK(nextText);\n const nextCanContinue = canContinueKeepAllTextRun(nextText);\n\n if (currentContainsCJK && currentCanContinue) {\n current = [...current, ...next];\n currentText += nextText;\n currentContainsCJK = currentContainsCJK || nextContainsCJK;\n currentCanContinue = nextCanContinue;\n continue;\n }\n\n flush();\n current = next.slice();\n currentText = nextText;\n currentContainsCJK = nextContainsCJK;\n currentCanContinue = nextCanContinue;\n }\n\n flush();\n return merged;\n}\n\nfunction splitAtomsByWordSegments(\n atoms: readonly InlineAtom[],\n): InlineAtom[][] {\n if (atoms.length <= 1) {\n return atoms.length === 0 ? [] : [atoms.slice()];\n }\n const segmenter = getSharedWordSegmenter();\n if (segmenter == null) {\n return [atoms.slice()];\n }\n\n const text = joinAtomText(atoms);\n const offsets = [0];\n for (let index = 0; index < atoms.length; index += 1) {\n offsets.push((offsets[index] ?? 0) + (atoms[index]?.text.length ?? 0));\n }\n\n const units: InlineAtom[][] = [];\n let atomStart = 0;\n let atomEnd = 0;\n for (const segment of segmenter.segment(text)) {\n const start = segment.index;\n const end = start + segment.segment.length;\n while ((offsets[atomStart] ?? 0) < start) {\n atomStart += 1;\n }\n atomEnd = atomStart;\n while ((offsets[atomEnd] ?? 0) < end) {\n atomEnd += 1;\n }\n if (atomStart < atomEnd) {\n units.push(atoms.slice(atomStart, atomEnd));\n }\n atomStart = atomEnd;\n }\n\n return units.length > 0 ? units : [atoms.slice()];\n}\n\nfunction makeTextUnit(atoms: InlineAtom[], atomic = false): PreparedInlineUnit {\n const width = measureAtomSequenceWidth(atoms);\n return {\n kind: \"text\",\n atoms,\n width,\n fitEndWidth: width,\n paintEndWidth: width,\n breakAfter: true,\n breakable: !atomic && atoms.length > 1,\n atomic,\n };\n}\n\nfunction makeSpaceUnit(atoms: InlineAtom[]): PreparedInlineUnit {\n const width = measureAtomSequenceWidth(atoms);\n const preservesLineEnd = atoms.every((atom) => atom.preservesLineEnd);\n return {\n kind: \"space\",\n atoms,\n width,\n fitEndWidth: 0,\n paintEndWidth: preservesLineEnd ? width : 0,\n breakAfter: true,\n breakable: atoms.length > 1,\n atomic: false,\n };\n}\n\nfunction tokenizeChunkAtoms(\n chunkAtoms: readonly InlineAtom[],\n wordBreak: TextWordBreakMode,\n): PreparedInlineUnit[] {\n const units: PreparedInlineUnit[] = [];\n let index = 0;\n\n while (index < chunkAtoms.length) {\n const atom = chunkAtoms[index]!;\n if (atom.atomicGroupId != null) {\n const start = index;\n const atomicGroupId = atom.atomicGroupId;\n while (\n index < chunkAtoms.length &&\n chunkAtoms[index]?.atomicGroupId === atomicGroupId\n ) {\n index += 1;\n }\n units.push(makeTextUnit(chunkAtoms.slice(start, index), true));\n continue;\n }\n\n if (atom.kind === \"space\") {\n const start = index;\n while (\n index < chunkAtoms.length &&\n chunkAtoms[index]?.kind === \"space\" &&\n chunkAtoms[index]?.atomicGroupId == null\n ) {\n index += 1;\n }\n units.push(makeSpaceUnit(chunkAtoms.slice(start, index)));\n continue;\n }\n\n const start = index;\n while (\n index < chunkAtoms.length &&\n chunkAtoms[index]?.kind === \"text\" &&\n chunkAtoms[index]?.atomicGroupId == null\n ) {\n index += 1;\n }\n const textRunAtoms = chunkAtoms.slice(start, index);\n const runText = joinAtomText(textRunAtoms);\n const rawUnits = isCJK(runText)\n ? buildBaseCjkUnits(textRunAtoms)\n : splitAtomsByWordSegments(textRunAtoms);\n const normalizedUnits =\n wordBreak === \"keep-all\" && isCJK(runText)\n ? mergeKeepAllUnits(rawUnits)\n : rawUnits;\n for (const unitAtoms of normalizedUnits) {\n units.push(makeTextUnit(unitAtoms.slice(), false));\n }\n }\n\n return units;\n}\n\nfunction buildPreparedInlineLayout(\n items: readonly SourceItem[],\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedInlineLayout {\n const atomChunks =\n whiteSpace === \"pre-wrap\"\n ? buildPreWrapAtoms(items)\n : buildCollapsedWhitespaceAtoms(items);\n const chunks: PreparedInlineChunk[] = [];\n const units: PreparedInlineUnit[] = [];\n\n for (const atomChunk of atomChunks) {\n const startUnit = units.length;\n const chunkUnits = tokenizeChunkAtoms(atomChunk, wordBreak);\n units.push(...chunkUnits);\n chunks.push({\n startUnit,\n endUnit: units.length,\n });\n }\n\n return {\n units,\n chunks,\n whiteSpace,\n wordBreak,\n lineStatsCache: new Map<number, PreparedInlineStats>(),\n minContentWidthCache: new Map<TextOverflowWrapMode, number>(),\n };\n}\n\nfunction readNumberLruValue<T>(\n cache: Map<number, T>,\n key: number,\n): T | undefined {\n const cached = cache.get(key);\n if (cached == null) {\n return undefined;\n }\n cache.delete(key);\n cache.set(key, cached);\n return cached;\n}\n\nfunction writeNumberLruValue<T>(\n cache: Map<number, T>,\n key: number,\n value: T,\n capacity: number,\n): T {\n if (cache.has(key)) {\n cache.delete(key);\n } else if (cache.size >= capacity) {\n const firstKey = cache.keys().next().value;\n if (firstKey != null) {\n cache.delete(firstKey);\n }\n }\n cache.set(key, value);\n return value;\n}\n\nfunction cloneCursor(cursor: PreparedInlineCursor): PreparedInlineCursor {\n return {\n chunkIndex: cursor.chunkIndex,\n unitIndex: cursor.unitIndex,\n atomIndex: cursor.atomIndex,\n };\n}\n\nfunction cursorEquals(\n a: PreparedInlineCursor,\n b: PreparedInlineCursor,\n): boolean {\n return (\n a.chunkIndex === b.chunkIndex &&\n a.unitIndex === b.unitIndex &&\n a.atomIndex === b.atomIndex\n );\n}\n\nfunction fits(width: number, maxWidth: number): boolean {\n return width <= maxWidth + LINE_FIT_EPSILON;\n}\n\nfunction getVisibleEndAfterBreak(\n chunkIndex: number,\n unitIndex: number,\n unit: PreparedInlineUnit,\n): PreparedInlineCursor {\n if (unit.kind === \"space\" && unit.paintEndWidth === 0) {\n return { chunkIndex, unitIndex, atomIndex: 0 };\n }\n return { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n}\n\nfunction fitPartialUnit(\n unit: PreparedInlineUnit,\n startAtomIndex: number,\n lineWidth: number,\n maxWidth: number,\n): { count: number; width: number } {\n let width = 0;\n let count = 0;\n for (let index = startAtomIndex; index < unit.atoms.length; index += 1) {\n const atom = unit.atoms[index]!;\n const atomWidth = atom.width + atom.extraWidthAfter;\n if (count > 0 && !fits(lineWidth + width + atomWidth, maxWidth)) {\n break;\n }\n if (count === 0 || fits(lineWidth + width + atomWidth, maxWidth)) {\n width += atomWidth;\n count += 1;\n continue;\n }\n break;\n }\n return { count, width };\n}\n\nfunction stepChunkLine(\n prepared: PreparedInlineLayout,\n chunkIndex: number,\n startUnitIndex: number,\n startAtomIndex: number,\n maxWidth: number,\n): PreparedInlineLineRange | null {\n const chunk = prepared.chunks[chunkIndex];\n if (chunk == null || startUnitIndex >= chunk.endUnit) {\n return null;\n }\n\n const start: PreparedInlineCursor = {\n chunkIndex,\n unitIndex: startUnitIndex,\n atomIndex: startAtomIndex,\n };\n let unitIndex = startUnitIndex;\n let atomIndex = startAtomIndex;\n let lineWidth = 0;\n let hasContent = false;\n let pendingBreak: {\n end: PreparedInlineCursor;\n next: PreparedInlineCursor;\n width: number;\n } | null = null;\n\n while (unitIndex < chunk.endUnit) {\n const unit = prepared.units[unitIndex]!;\n if (atomIndex > 0) {\n const fitted = fitPartialUnit(unit, atomIndex, lineWidth, maxWidth);\n if (fitted.count === 0) {\n if (hasContent) {\n return {\n width: lineWidth,\n start,\n end: { chunkIndex, unitIndex, atomIndex },\n next: { chunkIndex, unitIndex, atomIndex },\n };\n }\n const atom = unit.atoms[atomIndex]!;\n const width = atom.width + atom.extraWidthAfter;\n return {\n width,\n start,\n end: { chunkIndex, unitIndex, atomIndex: atomIndex + 1 },\n next: { chunkIndex, unitIndex, atomIndex: atomIndex + 1 },\n };\n }\n\n if (atomIndex + fitted.count >= unit.atoms.length) {\n lineWidth += fitted.width;\n hasContent = true;\n atomIndex = 0;\n unitIndex += 1;\n pendingBreak = {\n end: { chunkIndex, unitIndex, atomIndex: 0 },\n next: { chunkIndex, unitIndex, atomIndex: 0 },\n width: lineWidth,\n };\n continue;\n }\n\n return {\n width: lineWidth + fitted.width,\n start,\n end: { chunkIndex, unitIndex, atomIndex: atomIndex + fitted.count },\n next: { chunkIndex, unitIndex, atomIndex: atomIndex + fitted.count },\n };\n }\n\n if (!hasContent) {\n if (fits(unit.width, maxWidth) || unit.atomic || !unit.breakable) {\n lineWidth = unit.width;\n hasContent = true;\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n pendingBreak = {\n end: getVisibleEndAfterBreak(chunkIndex, unitIndex, unit),\n next,\n width: unit.paintEndWidth,\n };\n unitIndex += 1;\n continue;\n }\n\n const fitted = fitPartialUnit(unit, 0, 0, maxWidth);\n if (fitted.count >= unit.atoms.length) {\n lineWidth = fitted.width;\n hasContent = true;\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n pendingBreak = {\n end: next,\n next,\n width: lineWidth,\n };\n unitIndex += 1;\n continue;\n }\n return {\n width: fitted.width,\n start,\n end: { chunkIndex, unitIndex, atomIndex: fitted.count },\n next: { chunkIndex, unitIndex, atomIndex: fitted.count },\n };\n }\n\n if (fits(lineWidth + unit.width, maxWidth)) {\n const nextWidth = lineWidth + unit.width;\n lineWidth = nextWidth;\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n pendingBreak = {\n end: getVisibleEndAfterBreak(chunkIndex, unitIndex, unit),\n next,\n width: nextWidth - unit.width + unit.paintEndWidth,\n };\n unitIndex += 1;\n continue;\n }\n\n if (fits(lineWidth + unit.fitEndWidth, maxWidth)) {\n const next = { chunkIndex, unitIndex: unitIndex + 1, atomIndex: 0 };\n return {\n width: lineWidth + unit.paintEndWidth,\n start,\n end: getVisibleEndAfterBreak(chunkIndex, unitIndex, unit),\n next,\n };\n }\n\n if (pendingBreak != null) {\n return {\n width: pendingBreak.width,\n start,\n end: pendingBreak.end,\n next: pendingBreak.next,\n };\n }\n\n return {\n width: lineWidth,\n start,\n end: { chunkIndex, unitIndex, atomIndex: 0 },\n next: { chunkIndex, unitIndex, atomIndex: 0 },\n };\n }\n\n if (!hasContent) {\n return null;\n }\n\n if (\n pendingBreak != null &&\n pendingBreak.next.unitIndex === chunk.endUnit &&\n pendingBreak.next.atomIndex === 0\n ) {\n return {\n width: pendingBreak.width,\n start,\n end: pendingBreak.end,\n next: pendingBreak.next,\n };\n }\n\n return {\n width: lineWidth,\n start,\n end: { chunkIndex, unitIndex, atomIndex: 0 },\n next: { chunkIndex, unitIndex, atomIndex: 0 },\n };\n}\n\nexport function getPreparedLineStart(\n prepared: PreparedInlineLayout,\n): PreparedInlineCursor | undefined {\n for (\n let chunkIndex = 0;\n chunkIndex < prepared.chunks.length;\n chunkIndex += 1\n ) {\n const chunk = prepared.chunks[chunkIndex]!;\n if (chunk.startUnit === chunk.endUnit) {\n return { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n }\n return { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n }\n return undefined;\n}\n\nexport function getPreparedEndCursor(\n prepared: PreparedInlineLayout,\n): PreparedInlineCursor {\n if (prepared.chunks.length === 0) {\n return { chunkIndex: 0, unitIndex: 0, atomIndex: 0 };\n }\n const lastChunkIndex = prepared.chunks.length - 1;\n const lastChunk = prepared.chunks[lastChunkIndex]!;\n return {\n chunkIndex: lastChunkIndex,\n unitIndex: lastChunk.endUnit,\n atomIndex: 0,\n };\n}\n\nexport function layoutNextPreparedLine(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n maxWidth: number,\n): PreparedInlineLineRange | null {\n const chunk = prepared.chunks[start.chunkIndex];\n if (chunk == null) {\n return null;\n }\n if (chunk.startUnit === chunk.endUnit) {\n return cursorEquals(start, {\n chunkIndex: start.chunkIndex,\n unitIndex: chunk.endUnit,\n atomIndex: 0,\n })\n ? null\n : {\n width: 0,\n start: cloneCursor(start),\n end: {\n chunkIndex: start.chunkIndex,\n unitIndex: chunk.endUnit,\n atomIndex: 0,\n },\n next: {\n chunkIndex: start.chunkIndex,\n unitIndex: chunk.endUnit,\n atomIndex: 0,\n },\n };\n }\n return stepChunkLine(\n prepared,\n start.chunkIndex,\n start.unitIndex,\n start.atomIndex,\n maxWidth,\n );\n}\n\nexport function walkPreparedLineRanges(\n prepared: PreparedInlineLayout,\n maxWidth: number,\n onLine: (line: PreparedInlineLineRange) => boolean | void,\n): number {\n let lineCount = 0;\n for (\n let chunkIndex = 0;\n chunkIndex < prepared.chunks.length;\n chunkIndex += 1\n ) {\n const chunk = prepared.chunks[chunkIndex]!;\n if (chunk.startUnit === chunk.endUnit) {\n const cursor = { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n if (\n onLine({ width: 0, start: cursor, end: cursor, next: cursor }) === false\n ) {\n lineCount += 1;\n return lineCount;\n }\n lineCount += 1;\n continue;\n }\n let cursor: PreparedInlineCursor = {\n chunkIndex,\n unitIndex: chunk.startUnit,\n atomIndex: 0,\n };\n while (true) {\n const line = layoutNextPreparedLine(prepared, cursor, maxWidth);\n if (line == null) {\n break;\n }\n if (onLine(line) === false) {\n lineCount += 1;\n return lineCount;\n }\n lineCount += 1;\n if (cursorEquals(line.next, cursor)) {\n break;\n }\n cursor = line.next;\n if (cursor.unitIndex >= chunk.endUnit && cursor.atomIndex === 0) {\n break;\n }\n }\n }\n return lineCount;\n}\n\nexport function forEachAtomFromCursorToEnd(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n cb: (atom: InlineAtom) => void,\n): void {\n for (\n let chunkIndex = start.chunkIndex;\n chunkIndex < prepared.chunks.length;\n chunkIndex += 1\n ) {\n const chunk = prepared.chunks[chunkIndex];\n if (chunk == null) {\n continue;\n }\n const chunkStart =\n chunkIndex === start.chunkIndex\n ? start\n : { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n const chunkEnd = { chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 };\n forEachAtomInRange(prepared, chunkStart, chunkEnd, cb);\n }\n}\n\nexport function measurePreparedLineStats(\n prepared: PreparedInlineLayout,\n maxWidth: number,\n): PreparedInlineStats {\n const cached = readNumberLruValue(prepared.lineStatsCache, maxWidth);\n if (cached != null) {\n return cached;\n }\n let lineCount = 0;\n let maxLineWidth = 0;\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n lineCount += 1;\n if (line.width > maxLineWidth) {\n maxLineWidth = line.width;\n }\n });\n return writeNumberLruValue(\n prepared.lineStatsCache,\n maxWidth,\n { lineCount, maxLineWidth },\n PREPARED_LINE_STATS_CACHE_CAPACITY,\n );\n}\n\nexport function measurePreparedNaturalWidth(\n prepared: PreparedInlineLayout,\n): number {\n return measurePreparedLineStats(prepared, Number.POSITIVE_INFINITY)\n .maxLineWidth;\n}\n\nexport function forEachAtomInRange(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n end: PreparedInlineCursor,\n cb: (atom: InlineAtom) => void,\n): void {\n if (start.chunkIndex !== end.chunkIndex) {\n throw new Error(\"Atom range iteration only supports a single chunk.\");\n }\n for (\n let unitIndex = start.unitIndex;\n unitIndex < end.unitIndex;\n unitIndex += 1\n ) {\n const unit = prepared.units[unitIndex]!;\n const atomStart = unitIndex === start.unitIndex ? start.atomIndex : 0;\n const atomEnd =\n unitIndex === end.unitIndex ? end.atomIndex : unit.atoms.length;\n for (let atomIndex = atomStart; atomIndex < atomEnd; atomIndex += 1) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n cb(atom);\n }\n }\n }\n if (end.unitIndex < prepared.units.length) {\n const unit = prepared.units[end.unitIndex];\n if (unit != null && start.unitIndex === end.unitIndex) {\n for (\n let atomIndex = start.atomIndex;\n atomIndex < end.atomIndex;\n atomIndex += 1\n ) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n cb(atom);\n }\n }\n }\n }\n}\n\nexport function collectAtomsInRange(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n end: PreparedInlineCursor,\n): InlineAtom[] {\n const atoms: InlineAtom[] = [];\n if (start.unitIndex === end.unitIndex) {\n const unit = prepared.units[start.unitIndex];\n if (unit == null) {\n return atoms;\n }\n for (\n let atomIndex = start.atomIndex;\n atomIndex < end.atomIndex;\n atomIndex += 1\n ) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n atoms.push(atom);\n }\n }\n return atoms;\n }\n\n const startChunk = prepared.chunks[start.chunkIndex];\n if (startChunk == null) {\n return atoms;\n }\n for (\n let unitIndex = start.unitIndex;\n unitIndex < end.unitIndex;\n unitIndex += 1\n ) {\n const unit = prepared.units[unitIndex]!;\n const atomStart = unitIndex === start.unitIndex ? start.atomIndex : 0;\n for (\n let atomIndex = atomStart;\n atomIndex < unit.atoms.length;\n atomIndex += 1\n ) {\n const atom = unit.atoms[atomIndex];\n if (atom != null) {\n atoms.push(atom);\n }\n }\n }\n const endUnit = prepared.units[end.unitIndex];\n if (endUnit != null) {\n for (let atomIndex = 0; atomIndex < end.atomIndex; atomIndex += 1) {\n const atom = endUnit.atoms[atomIndex];\n if (atom != null) {\n atoms.push(atom);\n }\n }\n }\n return atoms;\n}\n\nexport function collectLineAtoms(\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n): PreparedInlineAtomSlice {\n const atoms = collectAtomsInRange(prepared, line.start, line.end);\n return {\n atoms,\n width: line.width,\n };\n}\n\nexport function collectAtomsFromCursorToEnd(\n prepared: PreparedInlineLayout,\n start: PreparedInlineCursor,\n): InlineAtom[] {\n const atoms: InlineAtom[] = [];\n for (\n let chunkIndex = start.chunkIndex;\n chunkIndex < prepared.chunks.length;\n chunkIndex += 1\n ) {\n const chunk = prepared.chunks[chunkIndex]!;\n const chunkStart =\n chunkIndex === start.chunkIndex\n ? start\n : { chunkIndex, unitIndex: chunk.startUnit, atomIndex: 0 };\n const chunkEnd = { chunkIndex, unitIndex: chunk.endUnit, atomIndex: 0 };\n atoms.push(...collectAtomsInRange(prepared, chunkStart, chunkEnd));\n }\n return atoms;\n}\n\nexport function materializePreparedLineText(\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n): string {\n return joinAtomText(collectLineAtoms(prepared, line).atoms);\n}\n\nexport function flattenPreparedLineAtoms(\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n): InlineAtom[] {\n return collectLineAtoms(prepared, line).atoms;\n}\n\nexport function measurePreparedMinContentWidth(\n prepared: PreparedInlineLayout,\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n): number {\n const cached = prepared.minContentWidthCache.get(overflowWrap);\n if (cached != null) {\n return cached;\n }\n let maxWidth = 0;\n let maxAnyWidth = 0;\n for (const unit of prepared.units) {\n if (unit.width > maxAnyWidth) {\n maxAnyWidth = unit.width;\n }\n if (unit.kind !== \"text\") {\n continue;\n }\n const candidateWidth =\n overflowWrap === \"anywhere\" && unit.breakable\n ? unit.atoms.reduce(\n (widest, atom) =>\n Math.max(widest, atom.width + atom.extraWidthAfter),\n 0,\n )\n : unit.width;\n if (candidateWidth > maxWidth) {\n maxWidth = candidateWidth;\n }\n }\n const resolvedWidth = maxWidth > 0 ? maxWidth : maxAnyWidth;\n prepared.minContentWidthCache.set(overflowWrap, resolvedWidth);\n return resolvedWidth;\n}\n\nexport function getPreparedUnits(\n prepared: PreparedInlineLayout,\n): Array<{ text: string; width: number }> {\n const resolvedUnits: Array<{ text: string; width: number }> = [];\n for (let unitIndex = 0; unitIndex < prepared.units.length; unitIndex += 1) {\n const unit = prepared.units[unitIndex]!;\n if (unit.kind === \"text\" && unit.breakable) {\n for (let atomIndex = 0; atomIndex < unit.atoms.length; atomIndex += 1) {\n const atom = unit.atoms[atomIndex]!;\n resolvedUnits.push({\n text: atom.text,\n width: atom.width + atom.extraWidthAfter,\n });\n }\n continue;\n }\n const text = joinAtomText(unit.atoms);\n if (text.length === 0 && unit.width === 0) {\n continue;\n }\n resolvedUnits.push({ text, width: unit.width });\n }\n return resolvedUnits;\n}\n\nexport function joinPreparedUnitText(\n units: ReadonlyArray<{ text: string; width: number }>,\n start: number,\n end: number,\n): string {\n if (start >= end) {\n return \"\";\n }\n let text = \"\";\n for (let index = start; index < end; index += 1) {\n text += units[index]?.text ?? \"\";\n }\n return text;\n}\n\nexport function measureAtomsWidth(atoms: readonly InlineAtom[]): number {\n let total = 0;\n for (let index = 0; index < atoms.length; index += 1) {\n const atom = atoms[index];\n if (atom != null) {\n total += atom.width + atom.extraWidthAfter;\n }\n }\n return total;\n}\n\nexport function readPreparedInlineLayout(\n key: string,\n items: readonly SourceItem[],\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedInlineLayout {\n const cached = readLruValue(preparedInlineCache, key);\n if (cached != null) {\n return cached;\n }\n return writeLruValue(\n preparedInlineCache,\n key,\n buildPreparedInlineLayout(items, whiteSpace, wordBreak),\n PREPARED_INLINE_CACHE_CAPACITY,\n );\n}\n\nexport function getPlainPreparedKey(\n text: string,\n font: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): string {\n return `plain\\u0000${font}\\u0000${whiteSpace}\\u0000${wordBreak}\\u0000${text}`;\n}\n\nexport function getRichPreparedKey<C extends CanvasRenderingContext2D>(\n spans: readonly InlineSpan<C>[],\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): string {\n let key = \"\";\n for (let index = 0; index < spans.length; index += 1) {\n const span = spans[index]!;\n if (index > 0) {\n key += \"\\u0001\";\n }\n key += span.font ?? defaultFont;\n key += \"\\u0000\";\n key += span.text;\n key += \"\\u0000\";\n key += span.break ?? \"\";\n key += \"\\u0000\";\n key += span.extraWidth ?? 0;\n }\n key += \"\\u0002\";\n key += whiteSpace;\n key += \"\\u0002\";\n key += wordBreak;\n return key;\n}\n\nexport function createPlainSourceItems(\n text: string,\n font: string,\n): SourceItem[] {\n return [\n {\n text,\n font,\n itemIndex: 0,\n breakMode: \"normal\",\n extraWidth: 0,\n },\n ];\n}\n\nexport function createRichSourceItems<C extends CanvasRenderingContext2D>(\n spans: readonly InlineSpan<C>[],\n defaultFont: string,\n): SourceItem[] {\n return spans.map((span, index) => ({\n text: span.text,\n font: span.font ?? defaultFont,\n itemIndex: index,\n breakMode: span.break ?? \"normal\",\n extraWidth: span.extraWidth ?? 0,\n }));\n}\n","import type {\n Context,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n createPlainSourceItems,\n getPlainPreparedKey,\n getPreparedLineStart,\n getPreparedUnits as getInlinePreparedUnits,\n joinPreparedUnitText,\n layoutNextPreparedLine,\n materializePreparedLineText,\n measurePreparedMinContentWidth as measureInlinePreparedMinContentWidth,\n readPreparedInlineLayout,\n type PreparedInlineLayout,\n} from \"./inline-engine\";\n\nexport const PREPARED_TEXT_CACHE_CAPACITY = 512;\n\nexport type PreparedTextWithSegments = PreparedInlineLayout;\n\nexport type PreparedTextUnit = {\n text: string;\n width: number;\n};\n\nexport function readPreparedText(\n text: string,\n font: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedTextWithSegments {\n return readPreparedInlineLayout(\n getPlainPreparedKey(text, font, whiteSpace, wordBreak),\n createPlainSourceItems(text, font),\n whiteSpace,\n wordBreak,\n );\n}\n\nexport function readPreparedFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): { text: string; prepared: PreparedTextWithSegments } | undefined {\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return undefined;\n }\n const line = layoutNextPreparedLine(\n prepared,\n start,\n Number.POSITIVE_INFINITY,\n );\n if (line == null) {\n return undefined;\n }\n return {\n text: materializePreparedLineText(prepared, line),\n prepared,\n };\n}\n\nexport function measurePreparedMinContentWidth(\n prepared: PreparedTextWithSegments,\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n): number {\n return measureInlinePreparedMinContentWidth(prepared, overflowWrap);\n}\n\nexport function getPreparedUnits(\n prepared: PreparedTextWithSegments,\n): PreparedTextUnit[] {\n return getInlinePreparedUnits(prepared);\n}\n\nexport function joinUnitText(\n units: readonly PreparedTextUnit[],\n start: number,\n end: number,\n): string {\n return joinPreparedUnitText(units, start, end);\n}\n","import type {\n Context,\n TextEllipsisPosition,\n TextOverflowMode,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n ELLIPSIS_GLYPH,\n MIN_CONTENT_WIDTH_EPSILON,\n measureEllipsisWidth,\n measureFontShift,\n normalizeMaxLines,\n resolveEllipsisSelection,\n selectEllipsisUnitCounts,\n} from \"./core\";\nimport {\n forEachAtomFromCursorToEnd,\n flattenPreparedLineAtoms,\n getPreparedLineStart,\n layoutNextPreparedLine,\n materializePreparedLineText,\n measurePreparedLineStats,\n measurePreparedNaturalWidth,\n walkPreparedLineRanges,\n type InlineAtom,\n type PreparedInlineLineRange,\n} from \"./inline-engine\";\nimport {\n measurePreparedMinContentWidth,\n readPreparedText,\n type PreparedTextWithSegments,\n} from \"./plain-core\";\n\nexport interface TextLayout {\n width: number;\n text: string;\n shift: number;\n}\n\nexport interface TextMeasurement {\n width: number;\n lineCount: number;\n}\n\nexport interface OverflowTextLayout extends TextLayout {\n overflowed: boolean;\n}\n\nexport interface OverflowTextBlockLayout {\n width: number;\n lines: OverflowTextLayout[];\n overflowed: boolean;\n}\n\ntype TextBlockLayout = {\n width: number;\n lines: TextLayout[];\n};\n\nfunction measureTextLayoutWidth(lines: ArrayLike<{ width: number }>): number {\n let width = 0;\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line != null && line.width > width) {\n width = line.width;\n }\n }\n return width;\n}\n\nfunction clampMaxWidth(maxWidth: number): number {\n return Math.max(0, maxWidth);\n}\n\nfunction createEllipsisOnlyLayout<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n maxWidth: number,\n shift: number,\n): OverflowTextLayout {\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n return {\n width: ellipsisWidth,\n text: ELLIPSIS_GLYPH,\n shift,\n overflowed: true,\n };\n}\n\nfunction toTextBlockLayout(\n lines: PreparedInlineLineRange[],\n prepared: PreparedTextWithSegments,\n shift: number,\n): TextBlockLayout {\n const mappedLines: TextLayout[] = [];\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index]!;\n mappedLines.push({\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift,\n });\n }\n const width = measureTextLayoutWidth(mappedLines);\n return { width, lines: mappedLines };\n}\n\nfunction collectEllipsisLayout<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n atoms: readonly InlineAtom[],\n maxWidth: number,\n shift: number,\n position: TextEllipsisPosition,\n forceEllipsis = false,\n): OverflowTextLayout {\n const widths: number[] = [];\n let intrinsicWidth = 0;\n for (let index = 0; index < atoms.length; index += 1) {\n const atom = atoms[index]!;\n const width = atom.width + atom.extraWidthAfter;\n widths.push(width);\n intrinsicWidth += width;\n }\n if (!forceEllipsis && intrinsicWidth <= maxWidth) {\n return {\n width: intrinsicWidth,\n text: atoms.map((atom) => atom.text).join(\"\"),\n shift,\n overflowed: false,\n };\n }\n\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n if (atoms.length === 0) {\n return createEllipsisOnlyLayout(ctx, maxWidth, shift);\n }\n\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position,\n });\n if (selection == null) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n const { prefixCount, suffixCount, width } = selection;\n\n const prefixText = atoms\n .slice(0, prefixCount)\n .map((atom) => atom.text)\n .join(\"\");\n const suffixText = atoms\n .slice(atoms.length - suffixCount)\n .map((atom) => atom.text)\n .join(\"\");\n\n return {\n width,\n text:\n position === \"start\"\n ? `${ELLIPSIS_GLYPH}${suffixText}`\n : position === \"middle\"\n ? `${prefixText}${ELLIPSIS_GLYPH}${suffixText}`\n : `${prefixText}${ELLIPSIS_GLYPH}`,\n shift,\n overflowed: true,\n };\n}\n\nfunction getFirstLineRange(\n prepared: PreparedTextWithSegments,\n): PreparedInlineLineRange | undefined {\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return undefined;\n }\n return (\n layoutNextPreparedLine(prepared, start, Number.POSITIVE_INFINITY) ??\n undefined\n );\n}\n\nfunction walkLines(\n prepared: PreparedTextWithSegments,\n maxWidth: number,\n): PreparedInlineLineRange[] {\n const lines: PreparedInlineLineRange[] = [];\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n lines.push(line);\n });\n return lines;\n}\n\nfunction collectVisibleLines(\n prepared: PreparedTextWithSegments,\n maxWidth: number,\n maxLines: number,\n): { lines: PreparedInlineLineRange[]; overflowed: boolean } {\n const lines: PreparedInlineLineRange[] = [];\n let overflowed = false;\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n if (lines.length < maxLines) {\n lines.push(line);\n return true;\n }\n overflowed = true;\n return false;\n });\n return { lines, overflowed };\n}\n\nfunction collectEndEllipsisLayoutFromCursor<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n prepared: PreparedTextWithSegments,\n start: PreparedInlineLineRange[\"start\"],\n maxWidth: number,\n shift: number,\n): OverflowTextLayout {\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n\n const widths: number[] = [];\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n widths.push(atom.width + atom.extraWidthAfter);\n });\n\n if (widths.length === 0) {\n return createEllipsisOnlyLayout(ctx, maxWidth, shift);\n }\n\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position: \"end\",\n });\n if (selection == null) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n const { prefixCount, width } = selection;\n\n let text = \"\";\n let atomIndex = 0;\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n if (atomIndex < prefixCount) {\n text += atom.text;\n }\n atomIndex += 1;\n });\n\n return {\n width,\n text: `${text}${ELLIPSIS_GLYPH}`,\n shift,\n overflowed: true,\n };\n}\n\nfunction layoutForcedEllipsizedLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n prepared: PreparedTextWithSegments,\n line: PreparedInlineLineRange,\n maxWidth: number,\n shift: number,\n): OverflowTextLayout {\n return collectEllipsisLayout(\n ctx,\n flattenPreparedLineAtoms(prepared, line),\n maxWidth,\n shift,\n \"end\",\n true,\n );\n}\n\nexport function layoutFirstLineIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextLayout {\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const line = getFirstLineRange(prepared);\n if (line == null) {\n return { width: 0, text: \"\", shift: 0 };\n }\n return {\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift: measureFontShift(ctx),\n };\n}\n\nexport function measureTextIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextMeasurement {\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(\n prepared,\n Number.POSITIVE_INFINITY,\n );\n return { width, lineCount };\n}\n\nexport function layoutTextIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextBlockLayout {\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const lines = walkLines(prepared, Number.POSITIVE_INFINITY);\n return toTextBlockLayout(lines, prepared, measureFontShift(ctx));\n}\n\nexport function layoutFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n const shift = measureFontShift(ctx);\n if (clampedMaxWidth === 0) {\n return { width: 0, text: \"\", shift };\n }\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return { width: 0, text: \"\", shift };\n }\n const line = layoutNextPreparedLine(prepared, start, clampedMaxWidth);\n if (line == null) {\n return { width: 0, text: \"\", shift };\n }\n return {\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift,\n };\n}\n\nexport function layoutEllipsizedFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n ellipsisPosition: TextEllipsisPosition = \"end\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): OverflowTextLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n const shift = measureFontShift(ctx);\n if (clampedMaxWidth === 0) {\n return { width: 0, text: \"\", shift, overflowed: true };\n }\n\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const intrinsicLine = getFirstLineRange(prepared);\n if (intrinsicLine == null) {\n return { width: 0, text: \"\", shift: 0, overflowed: false };\n }\n return collectEllipsisLayout(\n ctx,\n flattenPreparedLineAtoms(prepared, intrinsicLine),\n clampedMaxWidth,\n shift,\n ellipsisPosition,\n );\n}\n\nexport function measureText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextMeasurement {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n if (clampedMaxWidth === 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(\n prepared,\n clampedMaxWidth,\n );\n return { width, lineCount };\n}\n\nexport function measureTextMinContent<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n): TextMeasurement {\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const width = measurePreparedMinContentWidth(prepared, overflowWrap);\n if (width === 0) {\n return { width: 0, lineCount: 0 };\n }\n const { lineCount } = measurePreparedLineStats(\n prepared,\n Math.max(width, MIN_CONTENT_WIDTH_EPSILON),\n );\n return { width, lineCount };\n}\n\nexport function layoutText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): TextBlockLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n if (clampedMaxWidth === 0) {\n return { width: 0, lines: [] };\n }\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const lines = walkLines(prepared, clampedMaxWidth);\n return toTextBlockLayout(lines, prepared, measureFontShift(ctx));\n}\n\nexport function layoutTextWithOverflow<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n options: {\n whiteSpace?: TextWhiteSpaceMode;\n wordBreak?: TextWordBreakMode;\n overflow?: TextOverflowMode;\n maxLines?: number;\n } = {},\n): OverflowTextBlockLayout {\n const clampedMaxWidth = clampMaxWidth(maxWidth);\n const whiteSpace = options.whiteSpace ?? \"normal\";\n const wordBreak = options.wordBreak ?? \"normal\";\n const overflow = options.overflow ?? \"clip\";\n const normalizedMaxLines = normalizeMaxLines(options.maxLines);\n\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n const shift = measureFontShift(ctx);\n if (normalizedMaxLines == null) {\n const lines = walkLines(prepared, clampedMaxWidth);\n const layout = toTextBlockLayout(lines, prepared, shift);\n return {\n width: layout.width,\n lines: layout.lines.map((line) => ({ ...line, overflowed: false })),\n overflowed: false,\n };\n }\n\n const { lines: visibleRanges, overflowed } = collectVisibleLines(\n prepared,\n clampedMaxWidth,\n normalizedMaxLines,\n );\n if (!overflowed) {\n const layout = toTextBlockLayout(visibleRanges, prepared, shift);\n return {\n width: layout.width,\n lines: layout.lines.map((line) => ({ ...line, overflowed: false })),\n overflowed: false,\n };\n }\n const visibleLines = visibleRanges.map((line) => ({\n width: line.width,\n text: materializePreparedLineText(prepared, line),\n shift,\n overflowed: false,\n }));\n\n if (overflow !== \"ellipsis\") {\n return {\n width: measureTextLayoutWidth(visibleLines),\n lines: visibleLines,\n overflowed: true,\n };\n }\n\n const lastVisibleRange = visibleRanges[visibleRanges.length - 1];\n const ellipsizedLastLine =\n lastVisibleRange == null\n ? createEllipsisOnlyLayout(ctx, clampedMaxWidth, shift)\n : collectEndEllipsisLayoutFromCursor(\n ctx,\n prepared,\n lastVisibleRange.start,\n clampedMaxWidth,\n shift,\n );\n\n const mergedLines = [...visibleLines.slice(0, -1), ellipsizedLastLine];\n return {\n width: measureTextLayoutWidth(mergedLines),\n lines: mergedLines,\n overflowed: true,\n };\n}\n\nexport function measureTextNaturalWidth<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): number {\n const prepared = readPreparedText(\n text,\n ctx.graphics.font,\n whiteSpace,\n wordBreak,\n );\n return measurePreparedNaturalWidth(prepared);\n}\n","import type {\n Context,\n DynValue,\n InlineSpan,\n TextEllipsisPosition,\n TextOverflowMode,\n TextOverflowWrapMode,\n TextWhiteSpaceMode,\n TextWordBreakMode,\n} from \"../types\";\nimport {\n ELLIPSIS_GLYPH,\n MIN_CONTENT_WIDTH_EPSILON,\n measureEllipsisWidth,\n measureFontShift,\n normalizeMaxLines,\n resolveEllipsisSelection,\n selectEllipsisUnitCounts,\n} from \"./core\";\nimport {\n collectAtomsInRange,\n createRichSourceItems,\n forEachAtomFromCursorToEnd,\n forEachAtomInRange,\n getPreparedLineStart,\n getRichPreparedKey,\n layoutNextPreparedLine,\n materializePreparedLineText,\n measureAtomsWidth,\n measurePreparedLineStats,\n walkPreparedLineRanges,\n type InlineAtom,\n type PreparedInlineLayout,\n type PreparedInlineLineRange,\n} from \"./inline-engine\";\nimport {\n measurePreparedMinContentWidth,\n readPreparedInlineLayout,\n} from \"./inline-engine\";\n\nexport interface RichFragmentLayout {\n itemIndex: number;\n text: string;\n font: string;\n color: DynValue<any, string> | undefined;\n gapBefore: number;\n gapAtomCount: number;\n gapSpaceCount: number;\n occupiedWidth: number;\n atomCount: number;\n spaceCount: number;\n shift: number;\n}\n\nexport interface RichLineLayout {\n width: number;\n fragments: RichFragmentLayout[];\n overflowed: boolean;\n}\n\nexport interface RichBlockLayout {\n width: number;\n lines: RichLineLayout[];\n overflowed: boolean;\n}\n\nexport interface RichMeasurement {\n width: number;\n lineCount: number;\n}\n\ntype PendingRichGap = {\n gapBefore: number;\n gapAtomCount: number;\n gapSpaceCount: number;\n};\n\nfunction measureRichBlockWidth(lines: ArrayLike<{ width: number }>): number {\n let width = 0;\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line != null && line.width > width) {\n width = line.width;\n }\n }\n return width;\n}\n\nfunction withFont<C extends CanvasRenderingContext2D, T>(\n ctx: Context<C>,\n font: string,\n cb: () => T,\n): T {\n const previousFont = ctx.graphics.font;\n ctx.graphics.font = font;\n try {\n return cb();\n } finally {\n ctx.graphics.font = previousFont;\n }\n}\n\nfunction readRichPrepared<C extends CanvasRenderingContext2D>(\n spans: InlineSpan<C>[],\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode,\n wordBreak: TextWordBreakMode,\n): PreparedInlineLayout {\n return readPreparedInlineLayout(\n getRichPreparedKey(spans, defaultFont, whiteSpace, wordBreak),\n createRichSourceItems(spans, defaultFont),\n whiteSpace,\n wordBreak,\n );\n}\n\nfunction measureRichFragmentShift<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n font: string,\n): number {\n return withFont(ctx, font, () => measureFontShift(ctx));\n}\n\nfunction materializeRichFragments<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n atoms: readonly InlineAtom[],\n): RichFragmentLayout[] {\n const fragments: RichFragmentLayout[] = [];\n let pendingGap: PendingRichGap = {\n gapBefore: 0,\n gapAtomCount: 0,\n gapSpaceCount: 0,\n };\n\n for (const atom of atoms) {\n pendingGap = appendRichFragment(\n ctx,\n spans,\n defaultColor,\n fragments,\n atom,\n pendingGap,\n );\n }\n\n return fragments;\n}\n\nfunction appendRichFragment<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n fragments: RichFragmentLayout[],\n atom: InlineAtom,\n pendingGap: PendingRichGap,\n): PendingRichGap {\n const occupiedWidth = atom.width + atom.extraWidthAfter;\n if (\n atom.kind === \"space\" &&\n !atom.preservesLineEnd &&\n atom.atomicGroupId == null\n ) {\n return {\n gapBefore: pendingGap.gapBefore + occupiedWidth,\n gapAtomCount: pendingGap.gapAtomCount + 1,\n gapSpaceCount: pendingGap.gapSpaceCount + 1,\n };\n }\n\n const span = spans[atom.itemIndex];\n const font = span?.font ?? atom.font;\n const color = span?.color ?? defaultColor;\n const previous = fragments[fragments.length - 1];\n const spaceCount = atom.kind === \"space\" ? 1 : 0;\n if (\n previous != null &&\n previous.itemIndex === atom.itemIndex &&\n previous.font === font &&\n pendingGap.gapBefore === 0\n ) {\n previous.text += atom.text;\n previous.occupiedWidth += occupiedWidth;\n previous.atomCount += 1;\n previous.spaceCount += spaceCount;\n return { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n }\n\n fragments.push({\n itemIndex: atom.itemIndex,\n text: atom.text,\n font,\n color: color as DynValue<any, string>,\n gapBefore: pendingGap.gapBefore,\n gapAtomCount: pendingGap.gapAtomCount,\n gapSpaceCount: pendingGap.gapSpaceCount,\n occupiedWidth,\n atomCount: 1,\n spaceCount,\n shift: measureRichFragmentShift(ctx, font),\n });\n return { gapBefore: 0, gapAtomCount: 0, gapSpaceCount: 0 };\n}\n\nfunction materializeRichFragmentsInRange<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n prepared: PreparedInlineLayout,\n start: PreparedInlineLineRange[\"start\"],\n end: PreparedInlineLineRange[\"end\"],\n): RichFragmentLayout[] {\n const fragments: RichFragmentLayout[] = [];\n let pendingGap: PendingRichGap = {\n gapBefore: 0,\n gapAtomCount: 0,\n gapSpaceCount: 0,\n };\n forEachAtomInRange(prepared, start, end, (atom) => {\n pendingGap = appendRichFragment(\n ctx,\n spans,\n defaultColor,\n fragments,\n atom,\n pendingGap,\n );\n });\n return fragments;\n}\n\nfunction materializeRichLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultColor: DynValue<C, string>,\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n overflowed: boolean,\n): RichLineLayout {\n return {\n width: line.width,\n fragments: materializeRichFragmentsInRange(\n ctx,\n spans,\n defaultColor,\n prepared,\n line.start,\n line.end,\n ),\n overflowed,\n };\n}\n\nfunction getFirstLineRange(\n prepared: PreparedInlineLayout,\n): PreparedInlineLineRange | undefined {\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return undefined;\n }\n return (\n layoutNextPreparedLine(prepared, start, Number.POSITIVE_INFINITY) ??\n undefined\n );\n}\n\nfunction walkLines(\n prepared: PreparedInlineLayout,\n maxWidth: number,\n): PreparedInlineLineRange[] {\n const lines: PreparedInlineLineRange[] = [];\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n lines.push(line);\n });\n return lines;\n}\n\nfunction collectVisibleLines(\n prepared: PreparedInlineLayout,\n maxWidth: number,\n maxLines: number,\n): { lines: PreparedInlineLineRange[]; overflowed: boolean } {\n const lines: PreparedInlineLineRange[] = [];\n let overflowed = false;\n walkPreparedLineRanges(prepared, maxWidth, (line) => {\n if (lines.length < maxLines) {\n lines.push(line);\n return true;\n }\n overflowed = true;\n return false;\n });\n return { lines, overflowed };\n}\n\nfunction createRichEllipsisFragment<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n font: string,\n color: DynValue<C, string>,\n): RichFragmentLayout {\n return withFont(ctx, font, () => ({\n itemIndex: -1,\n text: ELLIPSIS_GLYPH,\n font,\n color,\n gapBefore: 0,\n gapAtomCount: 0,\n gapSpaceCount: 0,\n occupiedWidth: measureEllipsisWidth(ctx),\n atomCount: 1,\n spaceCount: 0,\n shift: measureFontShift(ctx),\n }));\n}\n\nfunction createRichEllipsisOnlyLayout<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n maxWidth: number,\n font: string,\n color: DynValue<C, string>,\n): RichLineLayout {\n const fragment = createRichEllipsisFragment(ctx, font, color);\n if (fragment.occupiedWidth > maxWidth) {\n return { width: 0, fragments: [], overflowed: true };\n }\n return {\n width: fragment.occupiedWidth,\n fragments: [fragment],\n overflowed: true,\n };\n}\n\nfunction layoutRichEllipsisFromAtoms<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n atoms: readonly InlineAtom[],\n maxWidth: number,\n position: TextEllipsisPosition,\n forceEllipsis = false,\n): RichLineLayout {\n const intrinsicWidth = measureAtomsWidth(atoms);\n if (!forceEllipsis && intrinsicWidth <= maxWidth) {\n return {\n width: intrinsicWidth,\n fragments: materializeRichFragments(ctx, spans, defaultColor, atoms),\n overflowed: false,\n };\n }\n\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, fragments: [], overflowed: true };\n }\n if (atoms.length === 0) {\n return createRichEllipsisOnlyLayout(\n ctx,\n maxWidth,\n defaultFont,\n defaultColor,\n );\n }\n\n const widths = atoms.map((atom) => atom.width + atom.extraWidthAfter);\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position,\n });\n if (selection == null) {\n return { width: 0, fragments: [], overflowed: true };\n }\n const { prefixCount, suffixCount, width } = selection;\n\n const prefixAtoms = atoms.slice(0, prefixCount);\n const suffixAtoms = atoms.slice(atoms.length - suffixCount);\n const ellipsisSource =\n position === \"start\"\n ? (suffixAtoms[0] ?? atoms[0])\n : position === \"middle\"\n ? (prefixAtoms[prefixAtoms.length - 1] ??\n suffixAtoms[0] ??\n atoms[atoms.length - 1])\n : (prefixAtoms[prefixAtoms.length - 1] ?? atoms[atoms.length - 1]);\n const ellipsisSpan =\n ellipsisSource == null ? undefined : spans[ellipsisSource.itemIndex];\n const ellipsisFragment = createRichEllipsisFragment(\n ctx,\n ellipsisSpan?.font ?? ellipsisSource?.font ?? defaultFont,\n (ellipsisSpan?.color ?? defaultColor) as DynValue<C, string>,\n );\n const prefixFragments = materializeRichFragments(\n ctx,\n spans,\n defaultColor,\n prefixAtoms,\n );\n const suffixFragments = materializeRichFragments(\n ctx,\n spans,\n defaultColor,\n suffixAtoms,\n );\n\n return {\n width,\n fragments:\n position === \"start\"\n ? [ellipsisFragment, ...suffixFragments]\n : position === \"middle\"\n ? [...prefixFragments, ellipsisFragment, ...suffixFragments]\n : [...prefixFragments, ellipsisFragment],\n overflowed: true,\n };\n}\n\nfunction layoutRichEndEllipsisFromCursor<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n prepared: PreparedInlineLayout,\n start: PreparedInlineLineRange[\"start\"],\n maxWidth: number,\n): RichLineLayout {\n const ellipsisWidth = measureEllipsisWidth(ctx);\n if (ellipsisWidth > maxWidth) {\n return { width: 0, fragments: [], overflowed: true };\n }\n\n const widths: number[] = [];\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n widths.push(atom.width + atom.extraWidthAfter);\n });\n\n if (widths.length === 0) {\n return createRichEllipsisOnlyLayout(\n ctx,\n maxWidth,\n defaultFont,\n defaultColor,\n );\n }\n\n const selection = resolveEllipsisSelection({\n widths,\n ellipsisWidth,\n maxWidth,\n position: \"end\",\n });\n if (selection == null) {\n return { width: 0, fragments: [], overflowed: true };\n }\n const { prefixCount, width } = selection;\n\n const fragments: RichFragmentLayout[] = [];\n let atomIndex = 0;\n let pendingGap: PendingRichGap = {\n gapBefore: 0,\n gapAtomCount: 0,\n gapSpaceCount: 0,\n };\n let lastVisibleAtom: InlineAtom | undefined;\n let lastAtom: InlineAtom | undefined;\n forEachAtomFromCursorToEnd(prepared, start, (atom) => {\n lastAtom = atom;\n if (atomIndex < prefixCount) {\n pendingGap = appendRichFragment(\n ctx,\n spans,\n defaultColor,\n fragments,\n atom,\n pendingGap,\n );\n lastVisibleAtom = atom;\n }\n atomIndex += 1;\n });\n\n const ellipsisSource = lastVisibleAtom ?? lastAtom;\n const ellipsisSpan =\n ellipsisSource == null ? undefined : spans[ellipsisSource.itemIndex];\n fragments.push(\n createRichEllipsisFragment(\n ctx,\n ellipsisSpan?.font ?? ellipsisSource?.font ?? defaultFont,\n (ellipsisSpan?.color ?? defaultColor) as DynValue<C, string>,\n ),\n );\n\n return {\n width,\n fragments,\n overflowed: true,\n };\n}\n\nexport function layoutRichFirstLineIntrinsic<\n C extends CanvasRenderingContext2D,\n>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichLineLayout {\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const line = getFirstLineRange(prepared);\n if (line == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n return materializeRichLine(ctx, spans, defaultColor, prepared, line, false);\n}\n\nexport function layoutRichFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichLineLayout {\n const clampedMaxWidth = Math.max(0, maxWidth);\n if (clampedMaxWidth === 0 || spans.length === 0) {\n return { width: 0, fragments: [], overflowed: false };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const start = getPreparedLineStart(prepared);\n if (start == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n const line = layoutNextPreparedLine(prepared, start, clampedMaxWidth);\n if (line == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n return materializeRichLine(ctx, spans, defaultColor, prepared, line, false);\n}\n\nexport function layoutRichEllipsizedFirstLine<\n C extends CanvasRenderingContext2D,\n>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n ellipsisPosition: TextEllipsisPosition = \"end\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichLineLayout {\n const clampedMaxWidth = Math.max(0, maxWidth);\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const intrinsicLine = getFirstLineRange(prepared);\n if (intrinsicLine == null) {\n return { width: 0, fragments: [], overflowed: false };\n }\n if (clampedMaxWidth === 0) {\n return { width: 0, fragments: [], overflowed: true };\n }\n return layoutRichEllipsisFromAtoms(\n ctx,\n spans,\n defaultFont,\n defaultColor,\n collectAtomsInRange(prepared, intrinsicLine.start, intrinsicLine.end),\n clampedMaxWidth,\n ellipsisPosition,\n );\n}\n\nexport function measureRichText<C extends CanvasRenderingContext2D>(\n _ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichMeasurement {\n if (spans.length === 0 || maxWidth <= 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(\n prepared,\n maxWidth,\n );\n return { width, lineCount };\n}\n\nexport function measureRichTextIntrinsic<C extends CanvasRenderingContext2D>(\n _ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichMeasurement {\n if (spans.length === 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const { maxLineWidth: width, lineCount } = measurePreparedLineStats(\n prepared,\n Number.POSITIVE_INFINITY,\n );\n return { width, lineCount };\n}\n\nexport function measureRichTextMinContent<C extends CanvasRenderingContext2D>(\n _ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n overflowWrap: TextOverflowWrapMode = \"break-word\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichMeasurement {\n if (spans.length === 0) {\n return { width: 0, lineCount: 0 };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const width = measurePreparedMinContentWidth(prepared, overflowWrap);\n if (width === 0) {\n return { width: 0, lineCount: 0 };\n }\n const { lineCount } = measurePreparedLineStats(\n prepared,\n Math.max(width, MIN_CONTENT_WIDTH_EPSILON),\n );\n return { width, lineCount };\n}\n\nexport function layoutRichText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichBlockLayout {\n if (spans.length === 0 || maxWidth <= 0) {\n return { width: 0, lines: [], overflowed: false };\n }\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const lines = walkLines(prepared, maxWidth).map((line) =>\n materializeRichLine(ctx, spans, defaultColor, prepared, line, false),\n );\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n}\n\nexport function layoutRichTextIntrinsic<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichBlockLayout {\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n const lines = walkLines(prepared, Number.POSITIVE_INFINITY).map((line) =>\n materializeRichLine(ctx, spans, defaultColor, prepared, line, false),\n );\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n}\n\nexport function layoutRichTextWithOverflow<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n maxWidth: number,\n defaultFont: string,\n defaultColor: DynValue<C, string>,\n maxLines?: number,\n overflow: TextOverflowMode = \"clip\",\n whiteSpace: TextWhiteSpaceMode = \"normal\",\n wordBreak: TextWordBreakMode = \"normal\",\n): RichBlockLayout {\n if (spans.length === 0 || maxWidth <= 0) {\n return { width: 0, lines: [], overflowed: false };\n }\n const normalizedMaxLines = normalizeMaxLines(maxLines);\n const prepared = readRichPrepared(spans, defaultFont, whiteSpace, wordBreak);\n if (normalizedMaxLines == null) {\n const lineRanges = walkLines(prepared, maxWidth);\n const lines = lineRanges.map((line) =>\n materializeRichLine(ctx, spans, defaultColor, prepared, line, false),\n );\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n }\n const { lines: visibleRanges, overflowed } = collectVisibleLines(\n prepared,\n maxWidth,\n normalizedMaxLines,\n );\n if (!overflowed) {\n const lines = visibleRanges.map((line) =>\n materializeRichLine(ctx, spans, defaultColor, prepared, line, false),\n );\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: false,\n };\n }\n const visibleLines = visibleRanges.map((line) =>\n materializeRichLine(ctx, spans, defaultColor, prepared, line, false),\n );\n if (overflow !== \"ellipsis\") {\n return {\n width: measureRichBlockWidth(visibleLines),\n lines: visibleLines,\n overflowed: true,\n };\n }\n\n const lastVisibleRange = visibleRanges[visibleRanges.length - 1];\n const ellipsizedLastLine =\n lastVisibleRange == null\n ? { width: 0, fragments: [], overflowed: true }\n : layoutRichEndEllipsisFromCursor(\n ctx,\n spans,\n defaultFont,\n defaultColor,\n prepared,\n lastVisibleRange.start,\n maxWidth,\n );\n const lines = [...visibleLines.slice(0, -1), ellipsizedLastLine];\n return {\n width: measureRichBlockWidth(lines),\n lines,\n overflowed: true,\n };\n}\n\nexport function materializeRichLineText(line: RichLineLayout): string {\n return line.fragments.map((fragment) => fragment.text).join(\"\");\n}\n\nexport function materializePreparedRichLineText(\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n): string {\n return materializePreparedLineText(prepared, line);\n}\n","import type { TextJustifyMode } from \"../types\";\nimport {\n forEachAtomInRange,\n isCJK,\n type PreparedInlineLayout,\n type PreparedInlineLineRange,\n} from \"./inline-engine\";\n\n// -------- Feature detection --------\n\nlet _justifySupported: boolean | undefined;\n\nexport function isJustifySupported(ctx: CanvasRenderingContext2D): boolean {\n if (_justifySupported !== undefined) return _justifySupported;\n _justifySupported =\n typeof (ctx as any).wordSpacing === \"string\" &&\n typeof (ctx as any).letterSpacing === \"string\";\n return _justifySupported;\n}\n\n/** Reset cached detection result (for testing). */\nexport function resetJustifySupportedCache(): void {\n _justifySupported = undefined;\n}\n\n// -------- Mode resolution --------\n\nexport type ResolvedJustifyMode = TextJustifyMode | null;\n\nexport function resolveJustifyMode(\n justify: boolean | TextJustifyMode | undefined,\n): ResolvedJustifyMode {\n if (justify === true) return \"inter-word\";\n if (justify === \"inter-word\" || justify === \"inter-character\") return justify;\n return null;\n}\n\n// -------- Line analysis --------\n\nconst HYBRID_WORD_SHARE_CANDIDATES = [\n 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8,\n 0.85, 1.0, 0.0,\n] as const;\n\nconst PUNCTUATION_OR_SYMBOL_PATTERN = /^[\\p{P}\\p{S}]$/u;\nconst JUSTIFY_SCORE_EPSILON = 1e-9;\n\nexport interface JustifyLineInfo {\n /** Number of word gaps (space units) in the line. */\n wordGapCount: number;\n /** Number of visible non-space runs in the line. */\n wordCount: number;\n /** Total number of visible atoms that receive letter spacing. */\n renderAtomCount: number;\n /** Total number of inter-atom gaps that receive letter spacing. */\n letterGapCount: number;\n /** Total number of visible space atoms. */\n spaceCount: number;\n /** Total number of visible non-space atoms. */\n nonSpaceCount: number;\n /** Number of visible CJK atoms. */\n cjkCount: number;\n /** Number of visible non-space Latin-like atoms. */\n latinLikeCount: number;\n /** Number of visible non-space punctuation/symbol atoms. */\n punctuationCount: number;\n /** Visible line width before justification. */\n lineWidth: number;\n /** Visible width excluding space atoms. */\n nonSpaceWidth: number;\n}\n\nexport function analyzeLineForJustify(\n prepared: PreparedInlineLayout,\n line: PreparedInlineLineRange,\n): JustifyLineInfo {\n let wordGapCount = 0;\n let wordCount = 0;\n let renderAtomCount = 0;\n let spaceCount = 0;\n let nonSpaceCount = 0;\n let cjkCount = 0;\n let latinLikeCount = 0;\n let punctuationCount = 0;\n let nonSpaceWidth = 0;\n let insideWord = false;\n\n forEachAtomInRange(prepared, line.start, line.end, (atom) => {\n if (\n atom.kind === \"space\" &&\n !atom.preservesLineEnd &&\n atom.atomicGroupId == null\n ) {\n wordGapCount++;\n }\n renderAtomCount++;\n if (atom.kind === \"space\") {\n spaceCount++;\n insideWord = false;\n return;\n }\n\n nonSpaceCount++;\n nonSpaceWidth += atom.width + atom.extraWidthAfter;\n\n if (!insideWord) {\n wordCount++;\n insideWord = true;\n }\n\n if (isCJK(atom.text)) {\n cjkCount++;\n return;\n }\n if (PUNCTUATION_OR_SYMBOL_PATTERN.test(atom.text)) {\n punctuationCount++;\n return;\n }\n latinLikeCount++;\n });\n\n return {\n wordGapCount,\n wordCount,\n renderAtomCount,\n letterGapCount: Math.max(renderAtomCount - 1, 0),\n spaceCount,\n nonSpaceCount,\n cjkCount,\n latinLikeCount,\n punctuationCount,\n lineWidth: line.width,\n nonSpaceWidth,\n };\n}\n\nfunction getAverageWordWidth(info: JustifyLineInfo): number {\n return info.wordCount > 0\n ? info.nonSpaceWidth / info.wordCount\n : info.lineWidth;\n}\n\nfunction getAverageCharWidth(info: JustifyLineInfo): number {\n return info.renderAtomCount > 0\n ? info.lineWidth / info.renderAtomCount\n : info.lineWidth;\n}\n\nfunction resolvePerGapSpacing(\n totalSpace: number,\n gapCount: number,\n): number | null {\n if (totalSpace === 0) {\n return 0;\n }\n if (gapCount <= 0) {\n return null;\n }\n return totalSpace / gapCount;\n}\n\nfunction exceedsThreshold(\n perGap: number,\n averageWidth: number,\n threshold: number,\n): boolean {\n if (!Number.isFinite(threshold)) {\n return false;\n }\n return perGap > threshold * averageWidth;\n}\n\nfunction createJustifySpacing(\n wordSpacingPx: number,\n letterSpacingPx: number,\n): JustifySpacing {\n return {\n wordSpacing: `${wordSpacingPx}px`,\n letterSpacing: `${letterSpacingPx}px`,\n wordSpacingPx,\n letterSpacingPx,\n };\n}\n\n// -------- Threshold check --------\n\nexport function shouldJustifyLine(\n lineWidth: number,\n maxWidth: number,\n info: JustifyLineInfo,\n mode: ResolvedJustifyMode,\n threshold: number,\n): boolean {\n return (\n computeJustifySpacing(lineWidth, maxWidth, info, mode, threshold) != null\n );\n}\n\n// -------- Spacing computation --------\n\nexport interface JustifySpacing {\n wordSpacing: string;\n letterSpacing: string;\n wordSpacingPx: number;\n letterSpacingPx: number;\n}\n\nexport function computeJustifySpacing(\n lineWidth: number,\n maxWidth: number,\n info: JustifyLineInfo,\n mode: ResolvedJustifyMode,\n threshold = Number.POSITIVE_INFINITY,\n): JustifySpacing | null {\n const extraSpace = maxWidth - lineWidth;\n if (extraSpace <= 0 || mode == null) {\n return null;\n }\n\n if (mode === \"inter-word\" && info.wordGapCount > 0) {\n const perGap = extraSpace / info.wordGapCount;\n const avgWordWidth = Math.max(getAverageWordWidth(info), Number.EPSILON);\n if (exceedsThreshold(perGap, avgWordWidth, threshold)) {\n return null;\n }\n return createJustifySpacing(perGap, 0);\n }\n\n if (mode !== \"inter-character\" || info.renderAtomCount === 0) {\n return null;\n }\n\n const avgCharWidth = Math.max(getAverageCharWidth(info), Number.EPSILON);\n if (info.wordGapCount === 0) {\n const perGap = resolvePerGapSpacing(extraSpace, info.letterGapCount);\n if (perGap == null) {\n return null;\n }\n if (exceedsThreshold(perGap, avgCharWidth, threshold)) {\n return null;\n }\n return createJustifySpacing(0, perGap);\n }\n\n const avgWordWidth = Math.max(getAverageWordWidth(info), Number.EPSILON);\n const nonSpaceCount = Math.max(info.nonSpaceCount, 1);\n const cjkRatio = info.cjkCount / nonSpaceCount;\n const latinLikeRatio = info.latinLikeCount / nonSpaceCount;\n const punctuationRatio = info.punctuationCount / nonSpaceCount;\n const wordPenalty = 1 + cjkRatio;\n const letterPenalty = 1 + latinLikeRatio + 0.5 * punctuationRatio;\n\n let bestCandidate: {\n spacing: JustifySpacing;\n score: number;\n wordShare: number;\n } | null = null;\n\n for (const wordShare of HYBRID_WORD_SHARE_CANDIDATES) {\n const wordExtraSpace = extraSpace * wordShare;\n const letterExtraSpace = extraSpace - wordExtraSpace;\n const wordSpacingPx = resolvePerGapSpacing(\n wordExtraSpace,\n info.wordGapCount,\n );\n const letterSpacingPx = resolvePerGapSpacing(\n letterExtraSpace,\n info.letterGapCount,\n );\n if (wordSpacingPx == null || letterSpacingPx == null) {\n continue;\n }\n if (\n exceedsThreshold(wordSpacingPx, avgWordWidth, threshold) ||\n exceedsThreshold(letterSpacingPx, avgCharWidth, threshold)\n ) {\n continue;\n }\n\n const wordRatio = wordSpacingPx / avgWordWidth;\n const letterRatio = letterSpacingPx / avgCharWidth;\n const score =\n wordPenalty * wordRatio ** 2 + letterPenalty * letterRatio ** 2;\n if (\n bestCandidate == null ||\n score < bestCandidate.score - JUSTIFY_SCORE_EPSILON ||\n (Math.abs(score - bestCandidate.score) <= JUSTIFY_SCORE_EPSILON &&\n wordShare > bestCandidate.wordShare)\n ) {\n bestCandidate = {\n spacing: createJustifySpacing(wordSpacingPx, letterSpacingPx),\n score,\n wordShare,\n };\n }\n }\n\n return bestCandidate?.spacing ?? null;\n}\n","import {\n layoutEllipsizedFirstLine,\n layoutFirstLine,\n layoutFirstLineIntrinsic,\n layoutRichEllipsizedFirstLine,\n layoutRichFirstLine,\n layoutRichFirstLineIntrinsic,\n layoutRichText,\n layoutRichTextIntrinsic,\n layoutRichTextWithOverflow,\n layoutText,\n layoutTextIntrinsic,\n layoutTextWithOverflow,\n measureRichText,\n measureRichTextIntrinsic,\n measureRichTextMinContent,\n measureText,\n measureTextMinContent,\n measureTextIntrinsic,\n type RichBlockLayout,\n type RichLineLayout,\n type RichMeasurement,\n type TextLayout,\n type TextMeasurement,\n analyzeLineForJustify,\n computeJustifySpacing,\n isJustifySupported,\n resolveJustifyMode,\n} from \"../text\";\nimport { readPreparedText } from \"../text/plain-core\";\nimport {\n readPreparedInlineLayout,\n createRichSourceItems,\n getRichPreparedKey,\n walkPreparedLineRanges,\n} from \"../text/inline-engine\";\nimport type {\n Box,\n Context,\n InlineSpan,\n MultilineTextOptions,\n Node,\n PhysicalTextAlign,\n TextOptions,\n} from \"../types\";\n\ntype SingleLineLayout = TextLayout;\ntype MultiLineDrawLayout = {\n width: number;\n lines: TextLayout[];\n};\ntype MultiLineMeasureLayout = TextMeasurement;\n\ntype TextLayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getTextLayout<T>(node: Node<C>, key: string): T | undefined;\n setTextLayout<T>(node: Node<C>, key: string, layout: T): void;\n};\n\nfunction resolvePhysicalTextAlign(\n options: Pick<MultilineTextOptions<any>, \"align\" | \"physicalAlign\">,\n): PhysicalTextAlign {\n if (options.physicalAlign != null) {\n return options.physicalAlign;\n }\n if (options.align != null) {\n switch (options.align) {\n case \"start\":\n return \"left\";\n case \"center\":\n return \"center\";\n case \"end\":\n return \"right\";\n }\n }\n return \"left\";\n}\n\nfunction normalizeTextMaxWidth(\n maxWidth: number | undefined,\n): number | undefined {\n if (maxWidth == null) {\n return undefined;\n }\n return Math.max(0, maxWidth);\n}\n\nconst DEFAULT_TEXT_SPACING = {\n wordSpacing: \"0px\",\n letterSpacing: \"0px\",\n} as const;\n\nfunction supportsTextSpacing(\n g: CanvasRenderingContext2D,\n): g is CanvasRenderingContext2D & {\n wordSpacing: string;\n letterSpacing: string;\n} {\n return (\n typeof (g as any).wordSpacing === \"string\" &&\n typeof (g as any).letterSpacing === \"string\"\n );\n}\n\nfunction withTextSpacing<C extends CanvasRenderingContext2D, T>(\n g: C,\n spacing: { wordSpacing: string; letterSpacing: string },\n cb: () => T,\n): T {\n if (!supportsTextSpacing(g)) {\n return cb();\n }\n const savedWordSpacing = g.wordSpacing;\n const savedLetterSpacing = g.letterSpacing;\n try {\n g.wordSpacing = spacing.wordSpacing;\n g.letterSpacing = spacing.letterSpacing;\n return cb();\n } finally {\n g.wordSpacing = savedWordSpacing;\n g.letterSpacing = savedLetterSpacing;\n }\n}\n\nfunction getTextLayoutContext<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n): Context<C> & TextLayoutCacheAccess<C> {\n return ctx as Context<C> & TextLayoutCacheAccess<C>;\n}\n\nfunction readCachedTextLayout<C extends CanvasRenderingContext2D, T>(\n node: Node<C>,\n ctx: Context<C>,\n key: string,\n compute: () => T,\n): T {\n const textCtx = getTextLayoutContext(ctx);\n const cached = textCtx.getTextLayout<T>(node, key);\n if (cached != null) {\n return cached;\n }\n const layout = compute();\n textCtx.setTextLayout(node, key, layout);\n return layout;\n}\n\nfunction getSingleLineLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"single:intrinsic\" : `single:${maxWidth}`;\n}\n\nfunction getMultiLineMeasureLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null\n ? \"multi:measure:intrinsic\"\n : `multi:measure:${maxWidth}`;\n}\n\nfunction getRichMultiLineMeasureLayoutKey(\n maxWidth: number | undefined,\n): string {\n return maxWidth == null\n ? \"rich:measure:intrinsic\"\n : `rich:measure:${maxWidth}`;\n}\n\nfunction getMultiLineDrawLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"multi:draw:intrinsic\" : `multi:draw:${maxWidth}`;\n}\n\nfunction getRichMultiLineDrawLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null ? \"rich:draw:intrinsic\" : `rich:draw:${maxWidth}`;\n}\n\nfunction getMultiLineOverflowLayoutKey(maxWidth: number | undefined): string {\n return maxWidth == null\n ? \"multi:overflow:intrinsic\"\n : `multi:overflow:${maxWidth}`;\n}\n\nfunction getRichMultiLineOverflowLayoutKey(\n maxWidth: number | undefined,\n): string {\n return maxWidth == null\n ? \"rich:overflow:intrinsic\"\n : `rich:overflow:${maxWidth}`;\n}\n\nfunction shouldUseMultilineOverflowLayout(\n options: Pick<MultilineTextOptions<any>, \"maxLines\">,\n): boolean {\n return options.maxLines != null;\n}\n\nfunction shouldReadConstrainedOverflowLayout(\n maxWidth: number | undefined,\n options: Pick<MultilineTextOptions<any>, \"maxLines\">,\n): maxWidth is number {\n return maxWidth != null && shouldUseMultilineOverflowLayout(options);\n}\n\nfunction measureBlockLayout<\n T extends { width: number; lines: ArrayLike<unknown> },\n>(layout: T): MultiLineMeasureLayout {\n return { width: layout.width, lineCount: layout.lines.length };\n}\n\nfunction getSingleLineMinContentLayoutKey(): string {\n return \"single:min-content\";\n}\n\nfunction getMultiLineMinContentLayoutKey(): string {\n return \"multi:min-content\";\n}\n\nfunction getRichMultiLineMinContentLayoutKey(): string {\n return \"rich:min-content\";\n}\n\nfunction getSingleLineLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: TextOptions<C>,\n): SingleLineLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(\n node,\n ctx,\n getSingleLineLayoutKey(maxWidth),\n () =>\n maxWidth == null\n ? layoutFirstLineIntrinsic(\n ctx,\n text,\n options.whiteSpace,\n options.wordBreak,\n )\n : options.overflow === \"ellipsis\"\n ? layoutEllipsizedFirstLine(\n ctx,\n text,\n maxWidth,\n options.ellipsisPosition ?? \"end\",\n options.whiteSpace,\n options.wordBreak,\n )\n : layoutFirstLine(\n ctx,\n text,\n maxWidth,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getRichSingleLineLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: TextOptions<C>,\n): RichLineLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(\n node,\n ctx,\n getSingleLineLayoutKey(maxWidth),\n () =>\n maxWidth == null\n ? layoutRichFirstLineIntrinsic(\n ctx,\n spans,\n options.font,\n options.color,\n options.whiteSpace,\n options.wordBreak,\n )\n : options.overflow === \"ellipsis\"\n ? layoutRichEllipsizedFirstLine(\n ctx,\n spans,\n maxWidth,\n options.font,\n options.color,\n options.ellipsisPosition ?? \"end\",\n options.whiteSpace,\n options.wordBreak,\n )\n : layoutRichFirstLine(\n ctx,\n spans,\n maxWidth,\n options.font,\n options.color,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getMultiLineOverflowLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: MultilineTextOptions<C>,\n): MultiLineDrawLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(\n node,\n ctx,\n getMultiLineOverflowLayoutKey(maxWidth),\n () =>\n layoutTextWithOverflow(ctx, text, maxWidth ?? 0, {\n whiteSpace: options.whiteSpace,\n wordBreak: options.wordBreak,\n overflow: options.overflow,\n maxLines: options.maxLines,\n }),\n );\n}\n\nfunction getMultiLineMeasureLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: MultilineTextOptions<C>,\n): MultiLineMeasureLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return measureBlockLayout(\n getMultiLineOverflowLayout(node, ctx, text, options),\n );\n }\n return readCachedTextLayout(\n node,\n ctx,\n getMultiLineMeasureLayoutKey(maxWidth),\n () =>\n maxWidth == null\n ? measureTextIntrinsic(ctx, text, options.whiteSpace, options.wordBreak)\n : measureText(\n ctx,\n text,\n maxWidth,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getMultiLineDrawLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: MultilineTextOptions<C>,\n): MultiLineDrawLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return getMultiLineOverflowLayout(node, ctx, text, options);\n }\n return readCachedTextLayout(\n node,\n ctx,\n getMultiLineDrawLayoutKey(maxWidth),\n () =>\n maxWidth == null\n ? layoutTextIntrinsic(ctx, text, options.whiteSpace, options.wordBreak)\n : layoutText(\n ctx,\n text,\n maxWidth,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getSingleLineMinContentLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n options: TextOptions<C>,\n): SingleLineLayout {\n return readCachedTextLayout(\n node,\n ctx,\n getSingleLineMinContentLayoutKey(),\n () => {\n const measurement = measureTextMinContent(\n ctx,\n text,\n options.whiteSpace,\n options.wordBreak,\n options.overflowWrap,\n );\n const { shift } = layoutFirstLineIntrinsic(\n ctx,\n text,\n options.whiteSpace,\n options.wordBreak,\n );\n return {\n width: measurement.width,\n text,\n shift,\n };\n },\n );\n}\n\nfunction getRichSingleLineMinContentWidth<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: TextOptions<C>,\n): number {\n return readCachedTextLayout(\n node,\n ctx,\n getSingleLineMinContentLayoutKey(),\n () =>\n measureRichTextMinContent(\n ctx,\n spans,\n options.font,\n options.overflowWrap,\n options.whiteSpace,\n options.wordBreak,\n ).width,\n );\n}\n\nfunction drawRichLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n line: RichLineLayout,\n fallbackColor: TextOptions<C>[\"color\"],\n x: number,\n y: number,\n lineHeight: number,\n): void {\n let cursorX = x;\n for (\n let fragmentIndex = 0;\n fragmentIndex < line.fragments.length;\n fragmentIndex += 1\n ) {\n const fragment = line.fragments[fragmentIndex]!;\n cursorX += fragment.gapBefore;\n ctx.with((g) => {\n g.font = fragment.font;\n g.fillStyle = ctx.resolveDynValue(\n (fragment.color ?? fallbackColor) as typeof fallbackColor,\n );\n g.textAlign = \"left\";\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(\n fragment.text,\n cursorX,\n y + (lineHeight + fragment.shift) / 2,\n );\n });\n });\n cursorX += fragment.occupiedWidth;\n }\n}\n\nfunction getMultiLineMinContentLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n text: string,\n whiteSpace: MultilineTextOptions<C>[\"whiteSpace\"],\n wordBreak: MultilineTextOptions<C>[\"wordBreak\"],\n overflowWrap: MultilineTextOptions<C>[\"overflowWrap\"],\n): MultiLineMeasureLayout {\n return readCachedTextLayout(\n node,\n ctx,\n getMultiLineMinContentLayoutKey(),\n () => measureTextMinContent(ctx, text, whiteSpace, wordBreak, overflowWrap),\n );\n}\n\nfunction getRichMultiLineMeasureLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichMeasurement {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return measureBlockLayout(\n getRichMultiLineOverflowLayout(node, ctx, spans, options),\n );\n }\n return readCachedTextLayout(\n node,\n ctx,\n getRichMultiLineMeasureLayoutKey(maxWidth),\n () =>\n maxWidth == null\n ? measureRichTextIntrinsic(\n ctx,\n spans,\n options.font,\n options.whiteSpace,\n options.wordBreak,\n )\n : measureRichText(\n ctx,\n spans,\n maxWidth,\n options.font,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getRichMultiLineOverflowLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichBlockLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n return readCachedTextLayout(\n node,\n ctx,\n getRichMultiLineOverflowLayoutKey(maxWidth),\n () =>\n layoutRichTextWithOverflow(\n ctx,\n spans,\n maxWidth ?? 0,\n options.font,\n options.color,\n options.maxLines,\n options.overflow,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getRichMultiLineDrawLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichBlockLayout {\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n if (shouldReadConstrainedOverflowLayout(maxWidth, options)) {\n return getRichMultiLineOverflowLayout(node, ctx, spans, options);\n }\n return readCachedTextLayout(\n node,\n ctx,\n getRichMultiLineDrawLayoutKey(maxWidth),\n () =>\n maxWidth == null\n ? layoutRichTextIntrinsic(\n ctx,\n spans,\n options.font,\n options.color,\n options.whiteSpace,\n options.wordBreak,\n )\n : layoutRichText(\n ctx,\n spans,\n maxWidth,\n options.font,\n options.color,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\nfunction getRichMultiLineMinContentLayout<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n ctx: Context<C>,\n spans: InlineSpan<C>[],\n options: MultilineTextOptions<C>,\n): RichMeasurement {\n return readCachedTextLayout(\n node,\n ctx,\n getRichMultiLineMinContentLayoutKey(),\n () =>\n measureRichTextMinContent(\n ctx,\n spans,\n options.font,\n options.overflowWrap,\n options.whiteSpace,\n options.wordBreak,\n ),\n );\n}\n\n/**\n * Draws wrapped text using the configured line height and alignment.\n * Accepts either a plain string or an array of `InlineSpan` items for mixed inline styles.\n */\nexport class MultilineText<\n C extends CanvasRenderingContext2D,\n> implements Node<C> {\n /**\n * @param text Source text to measure and draw. Pass an `InlineSpan[]` for mixed inline styles.\n * @param options Text layout and drawing options.\n */\n constructor(\n readonly text: string | InlineSpan<C>[],\n readonly options: MultilineTextOptions<C>,\n ) {}\n\n measure(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const spans = this.text;\n const { width, lineCount } = getRichMultiLineMeasureLayout(\n this,\n ctx,\n spans,\n this.options,\n );\n return { width, height: lineCount * this.options.lineHeight };\n }\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lineCount } = getMultiLineMeasureLayout(\n this,\n ctx,\n this.text as string,\n this.options,\n );\n return { width, height: lineCount * this.options.lineHeight };\n });\n }\n\n measureMinContent(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const spans = this.text;\n const { width, lineCount } = getRichMultiLineMinContentLayout(\n this,\n ctx,\n spans,\n this.options,\n );\n return { width, height: lineCount * this.options.lineHeight };\n }\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lineCount } = getMultiLineMinContentLayout(\n this,\n ctx,\n this.text as string,\n this.options.whiteSpace,\n this.options.wordBreak,\n this.options.overflowWrap,\n );\n return { width, height: lineCount * this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n if (typeof this.text !== \"string\") {\n const spans = this.text;\n const { width, lines } = getRichMultiLineDrawLayout(\n this,\n ctx,\n spans,\n this.options,\n );\n const align = resolvePhysicalTextAlign(this.options);\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n const mode = resolveJustifyMode(this.options.justify);\n const canJustify =\n mode != null &&\n maxWidth != null &&\n maxWidth > 0 &&\n isJustifySupported(ctx.graphics);\n const threshold = this.options.justifyGapThreshold ?? 2.0;\n\n if (canJustify) {\n const prepared = readPreparedInlineLayout(\n getRichPreparedKey(\n spans,\n this.options.font,\n this.options.whiteSpace ?? \"normal\",\n this.options.wordBreak ?? \"normal\",\n ),\n createRichSourceItems(spans, this.options.font),\n this.options.whiteSpace ?? \"normal\",\n this.options.wordBreak ?? \"normal\",\n );\n let lineIndex = 0;\n const totalLines = lines.length;\n walkPreparedLineRanges(prepared, maxWidth, (lineRange) => {\n if (lineIndex >= totalLines) return false;\n const line = lines[lineIndex]!;\n const isLastLine = lineIndex === totalLines - 1;\n const isOverflowTruncated =\n isLastLine &&\n shouldUseMultilineOverflowLayout(this.options) &&\n this.options.overflow === \"ellipsis\";\n const wantJustify =\n !isOverflowTruncated &&\n (!isLastLine || this.options.justifyLastLine === true);\n\n if (wantJustify) {\n const info = analyzeLineForJustify(prepared, lineRange);\n const spacing = computeJustifySpacing(\n lineRange.width,\n maxWidth,\n info,\n mode,\n threshold,\n );\n if (spacing != null) {\n let cursorX = x;\n for (let fi = 0; fi < line.fragments.length; fi++) {\n const frag = line.fragments[fi]!;\n const leadingLetterGapCount =\n fi > 0 ? frag.gapAtomCount + 1 : 0;\n const internalLetterGapCount = Math.max(frag.atomCount - 1, 0);\n cursorX +=\n frag.gapBefore +\n leadingLetterGapCount * spacing.letterSpacingPx +\n frag.gapSpaceCount * spacing.wordSpacingPx;\n ctx.with((g) => {\n g.font = frag.font;\n g.fillStyle = ctx.resolveDynValue(\n (frag.color ??\n this.options.color) as typeof this.options.color,\n );\n g.textAlign = \"left\";\n withTextSpacing(g, spacing, () => {\n g.fillText(\n frag.text,\n cursorX,\n y + (this.options.lineHeight + frag.shift) / 2,\n );\n });\n });\n cursorX +=\n frag.occupiedWidth +\n internalLetterGapCount * spacing.letterSpacingPx +\n frag.spaceCount * spacing.wordSpacingPx;\n }\n y += this.options.lineHeight;\n lineIndex++;\n return;\n }\n }\n\n // Fallback: normal alignment\n const startX =\n align === \"right\"\n ? x + width\n : align === \"center\"\n ? x + width / 2\n : x;\n let cursorX = startX;\n for (let fi = 0; fi < line.fragments.length; fi++) {\n const frag = line.fragments[fi]!;\n cursorX += frag.gapBefore;\n ctx.with((g) => {\n g.font = frag.font;\n g.fillStyle = ctx.resolveDynValue(\n (frag.color ?? this.options.color) as typeof this.options.color,\n );\n if (align === \"right\") {\n g.textAlign = \"right\";\n } else if (align === \"center\") {\n g.textAlign = \"center\";\n } else {\n g.textAlign = \"left\";\n }\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(\n frag.text,\n cursorX,\n y + (this.options.lineHeight + frag.shift) / 2,\n );\n });\n });\n cursorX += frag.occupiedWidth;\n }\n y += this.options.lineHeight;\n lineIndex++;\n });\n } else {\n const startX =\n align === \"right\"\n ? x + width\n : align === \"center\"\n ? x + width / 2\n : x;\n for (const line of lines) {\n let cursorX = startX;\n for (let fi = 0; fi < line.fragments.length; fi++) {\n const frag = line.fragments[fi]!;\n cursorX += frag.gapBefore;\n ctx.with((g) => {\n g.font = frag.font;\n g.fillStyle = ctx.resolveDynValue(\n (frag.color ?? this.options.color) as typeof this.options.color,\n );\n if (align === \"right\") {\n g.textAlign = \"right\";\n } else if (align === \"center\") {\n g.textAlign = \"center\";\n } else {\n g.textAlign = \"left\";\n }\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(\n frag.text,\n cursorX,\n y + (this.options.lineHeight + frag.shift) / 2,\n );\n });\n });\n cursorX += frag.occupiedWidth;\n }\n y += this.options.lineHeight;\n }\n }\n return false;\n }\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.color);\n const { width, lines } = getMultiLineDrawLayout(\n this,\n ctx,\n this.text as string,\n this.options,\n );\n const maxWidth = normalizeTextMaxWidth(ctx.constraints?.maxWidth);\n const mode = resolveJustifyMode(this.options.justify);\n const canJustify =\n mode != null &&\n maxWidth != null &&\n maxWidth > 0 &&\n isJustifySupported(g);\n const threshold = this.options.justifyGapThreshold ?? 2.0;\n\n if (canJustify) {\n const prepared = readPreparedText(\n this.text as string,\n this.options.font,\n this.options.whiteSpace ?? \"normal\",\n this.options.wordBreak ?? \"normal\",\n );\n let lineIndex = 0;\n const totalLines = lines.length;\n walkPreparedLineRanges(prepared, maxWidth, (lineRange) => {\n if (lineIndex >= totalLines) return false;\n const layout = lines[lineIndex]!;\n const isLastLine = lineIndex === totalLines - 1;\n const isOverflowTruncated =\n isLastLine &&\n shouldUseMultilineOverflowLayout(this.options) &&\n this.options.overflow === \"ellipsis\";\n const wantJustify =\n !isOverflowTruncated &&\n (!isLastLine || this.options.justifyLastLine === true);\n\n if (wantJustify) {\n const info = analyzeLineForJustify(prepared, lineRange);\n const spacing = computeJustifySpacing(\n lineRange.width,\n maxWidth,\n info,\n mode,\n threshold,\n );\n if (spacing != null) {\n withTextSpacing(g, spacing, () => {\n g.textAlign = \"left\";\n g.fillText(\n layout.text,\n x,\n y + (this.options.lineHeight + layout.shift) / 2,\n );\n });\n y += this.options.lineHeight;\n lineIndex++;\n return;\n }\n }\n\n // Fallback to normal alignment for this line\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n switch (resolvePhysicalTextAlign(this.options)) {\n case \"left\":\n g.textAlign = \"left\";\n g.fillText(\n layout.text,\n x,\n y + (this.options.lineHeight + layout.shift) / 2,\n );\n break;\n case \"right\":\n g.textAlign = \"right\";\n g.fillText(\n layout.text,\n x + width,\n y + (this.options.lineHeight + layout.shift) / 2,\n );\n break;\n case \"center\":\n g.textAlign = \"center\";\n g.fillText(\n layout.text,\n x + width / 2,\n y + (this.options.lineHeight + layout.shift) / 2,\n );\n break;\n }\n });\n y += this.options.lineHeight;\n lineIndex++;\n });\n } else {\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n switch (resolvePhysicalTextAlign(this.options)) {\n case \"left\":\n for (const { text, shift } of lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"right\": {\n x += width;\n g.textAlign = \"right\";\n for (const { text, shift } of lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n case \"center\": {\n x += width / 2;\n g.textAlign = \"center\";\n for (const { text, shift } of lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n }\n });\n }\n return false;\n });\n }\n\n hittest(\n _ctx: Context<C>,\n _test: { x: number; y: number; type: \"click\" | \"auxclick\" | \"hover\" },\n ): boolean {\n return false;\n }\n}\n\n/**\n * Draws a single line of text, clipped logically by measurement width.\n */\nexport class Text<C extends CanvasRenderingContext2D> implements Node<C> {\n /**\n * @param text Source text to measure and draw. Pass an `InlineSpan[]` for mixed inline styles.\n * @param options Text layout and drawing options.\n */\n constructor(\n readonly text: string | InlineSpan<C>[],\n readonly options: TextOptions<C>,\n ) {}\n\n measure(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const { width } = getRichSingleLineLayout(\n this,\n ctx,\n this.text,\n this.options,\n );\n return { width, height: this.options.lineHeight };\n }\n const text = this.text;\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width } = getSingleLineLayout(this, ctx, text, this.options);\n return { width, height: this.options.lineHeight };\n });\n }\n\n measureMinContent(ctx: Context<C>): Box {\n if (typeof this.text !== \"string\") {\n const width = getRichSingleLineMinContentWidth(\n this,\n ctx,\n this.text,\n this.options,\n );\n return { width, height: this.options.lineHeight };\n }\n const text = this.text;\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width } = getSingleLineMinContentLayout(\n this,\n ctx,\n text,\n this.options,\n );\n return { width, height: this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n if (typeof this.text !== \"string\") {\n const line = getRichSingleLineLayout(this, ctx, this.text, this.options);\n drawRichLine(\n ctx,\n line,\n this.options.color,\n x,\n y,\n this.options.lineHeight,\n );\n return false;\n }\n const text = this.text;\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.color);\n const layout = getSingleLineLayout(this, ctx, text, this.options);\n withTextSpacing(g, DEFAULT_TEXT_SPACING, () => {\n g.fillText(\n layout.text,\n x,\n y + (this.options.lineHeight + layout.shift) / 2,\n );\n });\n return false;\n });\n }\n\n hittest(\n _ctx: Context<C>,\n _test: { x: number; y: number; type: \"click\" | \"auxclick\" | \"hover\" },\n ): boolean {\n return false;\n }\n}\n","import {\n forEachNodeAncestor,\n getNodeRevision,\n} from \"../internal/node-registry\";\nimport type {\n Box,\n Context,\n DynValue,\n FlexLayoutResult,\n HitTest,\n LayoutConstraints,\n Node,\n RendererOptions,\n} from \"../types\";\nimport { shallow } from \"../utils\";\n\nconst MAX_CONSTRAINT_VARIANTS = 8;\n\ntype LayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getLayoutResult(\n node: Node<C>,\n constraints?: LayoutConstraints,\n ): FlexLayoutResult<C> | undefined;\n setLayoutResult(\n node: Node<C>,\n result: FlexLayoutResult<C>,\n constraints?: LayoutConstraints,\n ): void;\n};\n\ntype TextLayoutCacheAccess<C extends CanvasRenderingContext2D> = {\n getTextLayout<T>(node: Node<C>, key: string): T | undefined;\n setTextLayout<T>(node: Node<C>, key: string, layout: T): void;\n};\n\ntype BoxCacheEntry = {\n revision: number;\n box: Box;\n};\n\ntype LayoutCacheEntry<C extends CanvasRenderingContext2D> = {\n revision: number;\n layout: FlexLayoutResult<C>;\n};\n\ntype TextLayoutCacheEntry = {\n revision: number;\n layout: unknown;\n};\n\ntype RendererContext<C extends CanvasRenderingContext2D> = Context<C> &\n LayoutCacheAccess<C> &\n TextLayoutCacheAccess<C>;\n\nfunction constraintKey(constraints: LayoutConstraints | undefined): string {\n if (constraints == null) return \"\";\n return `${constraints.minWidth ?? \"\"},${constraints.maxWidth ?? \"\"},${constraints.minHeight ?? \"\"},${constraints.maxHeight ?? \"\"}`;\n}\n\n/**\n * Base renderer that provides measurement, layout caching, and drawing helpers.\n */\nexport class BaseRenderer<\n C extends CanvasRenderingContext2D,\n O extends {} = {},\n> {\n /** Canvas rendering context used by this renderer. */\n graphics: C;\n #ctx: RendererContext<C>;\n #lastWidth: number;\n #cache = new WeakMap<Node<C>, Map<string, BoxCacheEntry>>();\n #layoutCache = new WeakMap<Node<C>, Map<string, LayoutCacheEntry<C>>>();\n #textLayoutCache = new WeakMap<Node<C>, Map<string, TextLayoutCacheEntry>>();\n\n protected get context(): Context<C> {\n return shallow(this.#ctx);\n }\n\n /**\n * @param graphics Canvas rendering context used for all layout and drawing.\n * @param options Renderer-specific options.\n */\n constructor(\n graphics: C,\n readonly options: RendererOptions & O,\n ) {\n this.graphics = graphics;\n this.graphics.textRendering = \"optimizeLegibility\";\n const self = this;\n this.#ctx = {\n graphics: this.graphics,\n measureNode(node: Node<C>, constraints?: LayoutConstraints) {\n return self.measureNode(node, constraints);\n },\n getLayoutResult(node: Node<C>, constraints?: LayoutConstraints) {\n return self.getLayoutResult(node, constraints);\n },\n setLayoutResult(\n node: Node<C>,\n result: FlexLayoutResult<C>,\n constraints?: LayoutConstraints,\n ) {\n self.setLayoutResult(node, result, constraints);\n },\n getTextLayout<T>(node: Node<C>, key: string) {\n return self.getTextLayout<T>(node, key);\n },\n setTextLayout<T>(node: Node<C>, key: string, layout: T) {\n self.setTextLayout(node, key, layout);\n },\n invalidateNode: this.invalidateNode.bind(this),\n resolveDynValue<T>(value: DynValue<C, T>): T {\n if (typeof value === \"function\") {\n return value(this.graphics);\n }\n return value as T;\n },\n with<T>(cb: (g: C) => T): T {\n this.graphics.save();\n try {\n return cb(this.graphics);\n } finally {\n this.graphics.restore();\n }\n },\n };\n this.#lastWidth = this.graphics.canvas.clientWidth;\n }\n\n #clearAllCaches(): void {\n this.#cache = new WeakMap<Node<C>, Map<string, BoxCacheEntry>>();\n this.#layoutCache = new WeakMap<\n Node<C>,\n Map<string, LayoutCacheEntry<C>>\n >();\n this.#textLayoutCache = new WeakMap<\n Node<C>,\n Map<string, TextLayoutCacheEntry>\n >();\n }\n\n #syncCachesToViewportWidth(): void {\n const width = this.graphics.canvas.clientWidth;\n if (this.#lastWidth === width) {\n return;\n }\n this.#clearAllCaches();\n this.#lastWidth = width;\n }\n\n protected getRootConstraints(): LayoutConstraints {\n return {\n maxWidth: this.graphics.canvas.clientWidth,\n };\n }\n\n protected getRootContext(): Context<C> {\n const ctx = this.context;\n ctx.constraints = this.getRootConstraints();\n return ctx;\n }\n\n protected measureRootNode(node: Node<C>): Box {\n return this.measureNode(node, this.getRootConstraints());\n }\n\n protected drawRootNode(node: Node<C>, x = 0, y = 0): boolean {\n this.measureRootNode(node);\n return node.draw(this.getRootContext(), x, y);\n }\n\n protected hittestRootNode(node: Node<C>, test: HitTest): boolean {\n this.measureRootNode(node);\n return node.hittest(this.getRootContext(), test);\n }\n\n /**\n * Drops cached measurements for a node and every ancestor that depends on it.\n */\n invalidateNode(node: Node<C>): void {\n this.#syncCachesToViewportWidth();\n this.#cache.delete(node);\n this.#layoutCache.delete(node);\n this.#textLayoutCache.delete(node);\n forEachNodeAncestor(node, (ancestor) => {\n this.#cache.delete(ancestor);\n this.#layoutCache.delete(ancestor);\n this.#textLayoutCache.delete(ancestor);\n });\n }\n\n /**\n * Returns the cached layout result for a node under the given constraints, if available.\n */\n getLayoutResult(\n node: Node<C>,\n constraints?: LayoutConstraints,\n ): FlexLayoutResult<C> | undefined {\n this.#syncCachesToViewportWidth();\n const nodeCache = this.#layoutCache.get(node);\n if (nodeCache == null) {\n return undefined;\n }\n const key = constraintKey(constraints);\n const cached = nodeCache.get(key);\n if (cached == null) {\n return undefined;\n }\n if (cached.revision !== getNodeRevision(node)) {\n nodeCache.delete(key);\n return undefined;\n }\n return cached.layout;\n }\n\n /**\n * Stores a layout result for later draw and hit-test passes.\n */\n setLayoutResult(\n node: Node<C>,\n result: FlexLayoutResult<C>,\n constraints?: LayoutConstraints,\n ): void {\n this.#syncCachesToViewportWidth();\n let nodeCache = this.#layoutCache.get(node);\n if (nodeCache == null) {\n nodeCache = new Map();\n this.#layoutCache.set(node, nodeCache);\n } else if (nodeCache.size >= MAX_CONSTRAINT_VARIANTS) {\n const firstKey = nodeCache.keys().next().value!;\n nodeCache.delete(firstKey);\n }\n nodeCache.set(constraintKey(constraints), {\n revision: getNodeRevision(node),\n layout: result,\n });\n }\n\n protected getTextLayout<T>(node: Node<C>, key: string): T | undefined {\n this.#syncCachesToViewportWidth();\n const nodeCache = this.#textLayoutCache.get(node);\n if (nodeCache == null) {\n return undefined;\n }\n const cached = nodeCache.get(key);\n if (cached == null) {\n return undefined;\n }\n if (cached.revision !== getNodeRevision(node)) {\n nodeCache.delete(key);\n return undefined;\n }\n return cached.layout as T;\n }\n\n protected setTextLayout<T>(node: Node<C>, key: string, layout: T): void {\n this.#syncCachesToViewportWidth();\n let nodeCache = this.#textLayoutCache.get(node);\n if (nodeCache == null) {\n nodeCache = new Map();\n this.#textLayoutCache.set(node, nodeCache);\n } else if (nodeCache.size >= MAX_CONSTRAINT_VARIANTS) {\n const firstKey = nodeCache.keys().next().value!;\n nodeCache.delete(firstKey);\n }\n nodeCache.set(key, {\n revision: getNodeRevision(node),\n layout,\n });\n }\n\n /**\n * Measures a node under optional constraints, using cached results when possible.\n */\n measureNode(node: Node<C>, constraints?: LayoutConstraints): Box {\n this.#syncCachesToViewportWidth();\n {\n const nodeCache = this.#cache.get(node);\n if (nodeCache != null) {\n const key = constraintKey(constraints);\n const cached = nodeCache.get(key);\n if (cached != null) {\n if (cached.revision === getNodeRevision(node)) {\n return cached.box;\n }\n nodeCache.delete(key);\n }\n }\n }\n const ctx = this.context;\n if (constraints != null) {\n ctx.constraints = constraints;\n }\n const result = node.measure(ctx);\n const key = constraintKey(constraints);\n let nodeCache = this.#cache.get(node);\n if (nodeCache == null) {\n nodeCache = new Map();\n this.#cache.set(node, nodeCache);\n } else if (nodeCache.size >= MAX_CONSTRAINT_VARIANTS) {\n const firstKey = nodeCache.keys().next().value!;\n nodeCache.delete(firstKey);\n }\n nodeCache.set(key, {\n revision: getNodeRevision(node),\n box: result,\n });\n return result;\n }\n}\n\n/**\n * Immediate-mode renderer for a single root node.\n */\nexport class DebugRenderer<\n C extends CanvasRenderingContext2D,\n> extends BaseRenderer<C> {\n /**\n * Clears the viewport and draws the provided root node.\n */\n draw(node: Node<C>): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } =\n this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n return this.drawRootNode(node);\n }\n\n /**\n * Hit-tests the provided root node using viewport-relative coordinates.\n */\n hittest(node: Node<C>, test: HitTest): boolean {\n return this.hittestRootNode(node, test);\n }\n}\n","export interface WeakRefLike<T extends object> {\n deref(): T | undefined;\n}\n\nexport interface WeakListenerRecord<Owner extends object, Event> {\n ownerRef: WeakRefLike<Owner>;\n notify: (owner: Owner, event: Event) => void;\n}\n\nexport function pruneWeakListenerMap<Owner extends object, Event>(\n listeners: Map<symbol, WeakListenerRecord<Owner, Event>>,\n): void {\n for (const [token, listener] of listeners) {\n if (listener.ownerRef.deref() == null) {\n listeners.delete(token);\n }\n }\n}\n\nexport function emitWeakListeners<Owner extends object, Event>(\n listeners: Map<symbol, WeakListenerRecord<Owner, Event>>,\n event: Event,\n): void {\n for (const [token, listener] of [...listeners]) {\n const owner = listener.ownerRef.deref();\n if (owner == null) {\n listeners.delete(token);\n continue;\n }\n listener.notify(owner, event);\n }\n}\n","import {\n emitWeakListeners,\n pruneWeakListenerMap,\n type WeakListenerRecord,\n} from \"./weak-listeners\";\n\n/**\n * Mutable list state shared with virtualized renderers.\n */\nexport interface UpdateListItemAnimationOptions {\n /** Animation duration in milliseconds. */\n duration?: number;\n}\n\nexport interface DeleteListItemAnimationOptions {\n /** Animation duration in milliseconds. */\n duration?: number;\n}\n\ntype ListUpdateChange<T extends {}> = {\n type: \"update\";\n prevItem: T;\n nextItem: T;\n animation: UpdateListItemAnimationOptions | undefined;\n};\n\ntype ListDeleteChange<T extends {}> = {\n type: \"delete\";\n item: T;\n animation: DeleteListItemAnimationOptions | undefined;\n};\n\ntype ListDeleteFinalizeChange<T extends {}> = {\n type: \"delete-finalize\";\n item: T;\n};\n\ntype ListUnshiftChange = {\n type: \"unshift\";\n count: number;\n};\n\ntype ListPushChange = {\n type: \"push\";\n count: number;\n};\n\ntype ListResetChange = {\n type: \"reset\";\n};\n\ntype ListSetChange = {\n type: \"set\";\n};\n\nexport type ListStateChange<T extends {}> =\n | ListUpdateChange<T>\n | ListDeleteChange<T>\n | ListDeleteFinalizeChange<T>\n | ListUnshiftChange\n | ListPushChange\n | ListResetChange\n | ListSetChange;\n\nexport type ListStateChangeListener<T extends {}> = (\n change: ListStateChange<T>,\n) => void;\n\ntype WeakListStateListenerRecord = WeakListenerRecord<\n object,\n ListStateChange<{}>\n>;\n\nconst listStateListeners = new WeakMap<\n ListState<{}>,\n Map<symbol, WeakListStateListenerRecord>\n>();\nconst listStateListenerRegistry =\n typeof FinalizationRegistry === \"function\"\n ? new FinalizationRegistry<{\n listRef: WeakRef<ListState<{}>>;\n token: symbol;\n }>(({ listRef, token }) => {\n const list = listRef.deref();\n if (list == null) {\n return;\n }\n deleteListStateListener(list, token);\n })\n : null;\n\nfunction deleteListStateListener(list: ListState<{}>, token: symbol): void {\n const listeners = listStateListeners.get(list);\n if (listeners == null) {\n return;\n }\n listeners.delete(token);\n if (listeners.size === 0) {\n listStateListeners.delete(list);\n }\n}\n\nfunction emitListStateChange<T extends {}>(\n list: ListState<T>,\n change: ListStateChange<T>,\n): void {\n const listeners = listStateListeners.get(list as unknown as ListState<{}>);\n if (listeners == null) {\n return;\n }\n emitWeakListeners(listeners, change as ListStateChange<{}>);\n if (listeners.size === 0) {\n listStateListeners.delete(list as unknown as ListState<{}>);\n }\n}\n\nexport function subscribeListState<T extends {}, O extends object>(\n list: ListState<T>,\n owner: O,\n listener: (owner: O, change: ListStateChange<T>) => void,\n): void {\n const key = list as unknown as ListState<{}>;\n let listeners = listStateListeners.get(key);\n if (listeners == null) {\n listeners = new Map();\n listStateListeners.set(key, listeners);\n } else {\n pruneWeakListenerMap(listeners);\n }\n const token = Symbol();\n listeners.set(token, {\n ownerRef: new WeakRef(owner),\n notify: listener as (owner: object, change: ListStateChange<{}>) => void,\n });\n listStateListenerRegistry?.register(owner, {\n listRef: new WeakRef(key),\n token,\n });\n}\n\nfunction isObjectIdentityCandidate(value: unknown): value is object {\n return (\n (typeof value === \"object\" && value !== null) || typeof value === \"function\"\n );\n}\n\nfunction assertUniqueItemReferences<T extends {}>(\n items: readonly T[],\n existingItems?: readonly T[],\n): void {\n const seen = new Set<T>();\n if (existingItems != null) {\n for (const item of existingItems) {\n if (isObjectIdentityCandidate(item)) {\n seen.add(item);\n }\n }\n }\n for (const item of items) {\n if (!isObjectIdentityCandidate(item)) {\n continue;\n }\n if (seen.has(item)) {\n throw new Error(\"ListState items must use unique object references.\");\n }\n seen.add(item);\n }\n}\n\nfunction normalizeAnimationDuration(\n duration: number | undefined,\n): { duration?: number } | undefined {\n if (duration == null) {\n return undefined;\n }\n return Number.isFinite(duration) ? { duration } : {};\n}\n\nfunction normalizeUpdateAnimation(\n animation: UpdateListItemAnimationOptions | undefined,\n): UpdateListItemAnimationOptions | undefined {\n return normalizeAnimationDuration(animation?.duration);\n}\n\nfunction normalizeDeleteAnimation(\n animation: DeleteListItemAnimationOptions | undefined,\n): DeleteListItemAnimationOptions | undefined {\n return normalizeAnimationDuration(animation?.duration);\n}\n\nexport class ListState<T extends {}> {\n #items: T[];\n #pendingDeletes = new Set<T>();\n\n /** Pixel offset from the anchored item edge. */\n offset = 0;\n /** Anchor item index, or `undefined` to use the renderer default. */\n position: number | undefined;\n\n /** Items currently managed by the renderer. */\n get items(): T[] {\n return this.#items;\n }\n\n /** Replaces the full item collection while preserving scroll state. */\n set items(value: T[]) {\n const nextItems = [...value];\n assertUniqueItemReferences(nextItems);\n this.#items = nextItems;\n this.#pendingDeletes.clear();\n emitListStateChange(this, { type: \"set\" });\n }\n\n /**\n * @param items Initial list items.\n */\n constructor(items: T[] = []) {\n const nextItems = [...items];\n assertUniqueItemReferences(nextItems);\n this.#items = nextItems;\n }\n\n /** Prepends one or more items. */\n unshift(...items: T[]): void {\n this.unshiftAll(items);\n }\n\n /** Prepends an array of items. */\n unshiftAll(items: T[]): void {\n if (items.length === 0) {\n return;\n }\n assertUniqueItemReferences(items, this.#items);\n if (this.position != null) {\n this.position += items.length;\n }\n this.#items = items.concat(this.#items);\n emitListStateChange(this, {\n type: \"unshift\",\n count: items.length,\n });\n }\n\n /** Appends one or more items. */\n push(...items: T[]): void {\n this.pushAll(items);\n }\n\n /** Appends an array of items. */\n pushAll(items: T[]): void {\n if (items.length === 0) {\n return;\n }\n assertUniqueItemReferences(items, this.#items);\n this.#items.push(...items);\n emitListStateChange(this, {\n type: \"push\",\n count: items.length,\n });\n }\n\n /**\n * Updates an existing item by object identity.\n */\n update(\n targetItem: T,\n nextItem: T,\n animation?: UpdateListItemAnimationOptions,\n ): void {\n if (\n !isObjectIdentityCandidate(targetItem) ||\n !isObjectIdentityCandidate(nextItem)\n ) {\n throw new TypeError(\"update() only supports object items.\");\n }\n if (targetItem === nextItem) {\n throw new Error(\n \"update() requires nextItem to be a new object reference.\",\n );\n }\n const index = this.#items.indexOf(targetItem);\n if (index < 0) {\n throw new Error(\"update() targetItem is not present in the list.\");\n }\n if (this.#pendingDeletes.has(targetItem)) {\n throw new Error(\"update() targetItem is pending deletion.\");\n }\n if (this.#items.includes(nextItem)) {\n throw new Error(\"update() nextItem is already present in the list.\");\n }\n const prevItem = this.#items[index]!;\n this.#items[index] = nextItem;\n emitListStateChange(this, {\n type: \"update\",\n prevItem,\n nextItem,\n animation: normalizeUpdateAnimation(animation),\n });\n }\n\n /**\n * Starts deleting an existing item by object identity.\n */\n delete(item: T, animation?: DeleteListItemAnimationOptions): void {\n if (!isObjectIdentityCandidate(item)) {\n throw new TypeError(\"delete() only supports object items.\");\n }\n const index = this.#items.indexOf(item);\n if (index < 0) {\n throw new Error(\"delete() item is not present in the list.\");\n }\n if (this.#pendingDeletes.has(item)) {\n return;\n }\n const normalizedAnimation = normalizeDeleteAnimation(animation);\n const duration = normalizedAnimation?.duration ?? 0;\n if (!(duration > 0)) {\n this.#pendingDeletes.add(item);\n this.finalizeDelete(item);\n return;\n }\n this.#pendingDeletes.add(item);\n emitListStateChange(this, {\n type: \"delete\",\n item,\n animation: normalizedAnimation,\n });\n }\n\n /**\n * Finalizes a pending delete by removing the item from the list.\n */\n finalizeDelete(item: T): void {\n if (!this.#pendingDeletes.has(item)) {\n return;\n }\n const index = this.#items.indexOf(item);\n this.#pendingDeletes.delete(item);\n if (index < 0) {\n return;\n }\n this.#items.splice(index, 1);\n if (this.#items.length === 0) {\n this.position = undefined;\n this.offset = 0;\n } else if (this.position != null) {\n if (this.position > index) {\n this.position -= 1;\n } else if (this.position === index) {\n this.position = Math.min(index, this.#items.length - 1);\n }\n }\n emitListStateChange(this, {\n type: \"delete-finalize\",\n item,\n });\n }\n\n /**\n * Sets the current anchor item and pixel offset.\n */\n setAnchor(position: number, offset = 0): void {\n this.position = Number.isFinite(position)\n ? Math.trunc(position)\n : undefined;\n this.offset = Number.isFinite(offset) ? offset : 0;\n }\n\n /**\n * Replaces all items and clears scroll state.\n */\n reset(items: T[] = []): void {\n const nextItems = [...items];\n assertUniqueItemReferences(nextItems);\n this.#items = nextItems;\n this.#pendingDeletes.clear();\n this.offset = 0;\n this.position = undefined;\n emitListStateChange(this, { type: \"reset\" });\n }\n\n /** Clears the current scroll anchor while keeping the items. */\n resetScroll(): void {\n this.offset = 0;\n this.position = undefined;\n }\n\n /** Applies a relative pixel scroll delta. */\n applyScroll(delta: number): void {\n this.offset += delta;\n }\n}\n","import type { Node } from \"../types\";\n\nconst DEFAULT_MEMO_RENDER_ITEM_BY_MAX_ENTRIES = 512;\n\nfunction isWeakMapKey(value: unknown): value is object {\n return (\n (typeof value === \"object\" && value !== null) || typeof value === \"function\"\n );\n}\n\nfunction normalizeMaxEntries(maxEntries: number | undefined): number {\n if (maxEntries === Number.POSITIVE_INFINITY) {\n return Number.POSITIVE_INFINITY;\n }\n if (maxEntries == null || !Number.isFinite(maxEntries)) {\n return DEFAULT_MEMO_RENDER_ITEM_BY_MAX_ENTRIES;\n }\n return Math.max(0, Math.trunc(maxEntries));\n}\n\nfunction readLruValue<K, V>(cache: Map<K, V>, key: K): V | undefined {\n const cached = cache.get(key);\n if (cached == null) {\n return undefined;\n }\n cache.delete(key);\n cache.set(key, cached);\n return cached;\n}\n\nfunction writeLruValue<K, V>(\n cache: Map<K, V>,\n key: K,\n value: V,\n maxEntries: number,\n): V {\n if (cache.has(key)) {\n cache.delete(key);\n } else if (Number.isFinite(maxEntries) && cache.size >= maxEntries) {\n const oldestKey = cache.keys().next().value;\n if (oldestKey != null) {\n cache.delete(oldestKey);\n }\n }\n if (maxEntries > 0) {\n cache.set(key, value);\n }\n return value;\n}\n\n/**\n * Memoizes `renderItem` by object identity.\n */\nexport function memoRenderItem<\n C extends CanvasRenderingContext2D,\n T extends object,\n>(\n renderItem: (item: T) => Node<C>,\n): ((item: T) => Node<C>) & { reset: (key: T) => boolean } {\n const cache = new WeakMap<object, Node<C>>();\n\n function fn(item: T): Node<C> {\n if (!isWeakMapKey(item)) {\n throw new TypeError(\n \"memoRenderItem() only supports object items. Use memoRenderItemBy() for primitive keys.\",\n );\n }\n const key = item as unknown as object;\n const cached = cache.get(key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n cache.set(key, result);\n return result;\n }\n\n return Object.assign(fn, {\n reset: (key: T) => cache.delete(key as unknown as object),\n });\n}\n\n/**\n * Memoizes `renderItem` by a caller-provided cache key.\n */\nexport function memoRenderItemBy<C extends CanvasRenderingContext2D, T, K>(\n keyOf: (item: T) => K,\n renderItem: (item: T) => Node<C>,\n options: {\n maxEntries?: number;\n } = {},\n): ((item: T) => Node<C>) & {\n reset: (item: T) => boolean;\n resetKey: (key: K) => boolean;\n} {\n const cache = new Map<K, Node<C>>();\n const maxEntries = normalizeMaxEntries(options.maxEntries);\n\n function fn(item: T): Node<C> {\n const key = keyOf(item);\n const cached = readLruValue(cache, key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n return writeLruValue(cache, key, result, maxEntries);\n }\n\n return Object.assign(fn, {\n reset: (item: T) => cache.delete(keyOf(item)),\n resetKey: (key: K) => cache.delete(key),\n });\n}\n","import type { ControlledState } from \"./base-types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nexport function sameState(\n state: ControlledState,\n position: number | undefined,\n offset: number,\n): boolean {\n return Object.is(state.position, position) && Object.is(state.offset, offset);\n}\n\nexport function smoothstep(value: number): number {\n return value * value * (3 - 2 * value);\n}\n\nexport function getProgress(\n startTime: number,\n duration: number,\n now: number,\n): number {\n if (!(duration > 0)) {\n return 1;\n }\n return clamp((now - startTime) / duration, 0, 1);\n}\n\nexport function interpolate(\n from: number,\n to: number,\n startTime: number,\n duration: number,\n now: number,\n): number {\n const progress = getProgress(startTime, duration, now);\n const eased = progress >= 1 ? 1 : smoothstep(progress);\n return from + (to - from) * eased;\n}\n\nexport function getNow(): number {\n return globalThis.performance?.now() ?? Date.now();\n}\n","import type { HitTest, Node } from \"../../types\";\n\n/** Scroll position snapshot used to detect external state changes. */\nexport type ControlledState = {\n position?: number;\n offset: number;\n};\n\n/** Tracks an in-progress programmatic jump animation. */\nexport type JumpAnimation = {\n startAnchor: number;\n targetAnchor: number;\n startTime: number;\n duration: number;\n needsMoreFrames: boolean;\n onComplete: (() => void) | undefined;\n};\n\n/** A single cross-fade layer within a replacement animation. */\nexport type ReplacementLayer<C extends CanvasRenderingContext2D> = {\n node: Node<C>;\n fromAlpha: number;\n toAlpha: number;\n startTime: number;\n duration: number;\n};\n\n/** Full state for an item replacement (cross-fade + height) animation. */\nexport type ReplacementAnimation<C extends CanvasRenderingContext2D> = {\n kind: \"update\" | \"delete\";\n outgoing: ReplacementLayer<C> | undefined;\n /** undefined for delete animations where the slot shrinks to nothing. */\n incoming: ReplacementLayer<C> | undefined;\n fromHeight: number;\n toHeight: number;\n startTime: number;\n duration: number;\n};\n\n/** Per-item draw/hittest callbacks produced by the resolver. */\nexport type VirtualizedResolvedItem = {\n draw: (y: number) => boolean;\n hittest: (test: HitTest, y: number) => boolean;\n};\n\n/** Alpha values below this threshold are treated as fully transparent. */\nexport const ALPHA_EPSILON = 1e-3;\n","import type { Box, Context, Node } from \"../../types\";\nimport type { ListStateChange } from \"../list-state\";\nimport type { VisibleWindow, VisibleWindowResult } from \"./solver\";\nimport {\n clamp,\n getNow,\n getProgress,\n interpolate,\n sameState,\n} from \"./base-animation\";\nimport {\n ALPHA_EPSILON,\n type ControlledState,\n type ReplacementAnimation,\n type ReplacementLayer,\n type VirtualizedResolvedItem,\n} from \"./base-types\";\n\n/** Rendering services delegated to the host VirtualizedRenderer. */\nexport type ReplacementRendererAdapter<\n C extends CanvasRenderingContext2D,\n T extends {},\n> = {\n renderItem: (item: T) => Node<C>;\n measureNode: (node: Node<C>) => Box;\n drawNode: (node: Node<C>, x: number, y: number) => boolean;\n getRootContext: () => Context<C>;\n graphics: C;\n getAnimatedLayerOffset: (slotHeight: number, nodeHeight: number) => number;\n onDeleteComplete: (item: T) => void;\n};\n\n/** State context needed to check whether an update can be animated. */\nexport type ReplacementUpdateContext<\n C extends CanvasRenderingContext2D,\n T extends {},\n> = {\n items: readonly T[];\n position: number | undefined;\n offset: number;\n readListState: () => ControlledState;\n readVisibleRange: (\n top: number,\n height: number,\n ) => { top: number; bottom: number } | undefined;\n resolveVisibleWindow: () => VisibleWindowResult<unknown>;\n} & ReplacementRendererAdapter<C, T>;\n\n/**\n * Self-contained subsystem that manages item replacement (cross-fade + height)\n * animations for a VirtualizedRenderer.\n */\nexport class ReplacementController<\n C extends CanvasRenderingContext2D,\n T extends {},\n> {\n #replacementAnimations = new WeakMap<T, ReplacementAnimation<C>>();\n #activeReplacementItems = new Set<T>();\n\n // Visible-item snapshot used to decide whether an update can be animated.\n #visibleItems = new Set<T>();\n #hasVisibleItemSnapshot = false;\n #visibleSnapshotState: ControlledState | undefined;\n\n captureVisibleItemSnapshot(\n window: VisibleWindow<unknown>,\n items: readonly T[],\n readVisibleRange: (\n top: number,\n height: number,\n ) => { top: number; bottom: number } | undefined,\n readListState: () => ControlledState,\n ): void {\n const nextVisibleItems = new Set<T>();\n for (const { idx, offset, height } of window.drawList) {\n if (readVisibleRange(offset + window.shift, height) == null) {\n continue;\n }\n const item = items[idx];\n if (item != null) {\n nextVisibleItems.add(item);\n }\n }\n this.#visibleItems = nextVisibleItems;\n this.#hasVisibleItemSnapshot = true;\n this.#visibleSnapshotState = readListState();\n }\n\n /**\n * Removes animations for items that are no longer visible.\n * Returns true if any animation was canceled or finalized.\n */\n pruneInvisible(\n adapter: Pick<ReplacementRendererAdapter<C, T>, \"onDeleteComplete\">,\n ): boolean {\n let changed = false;\n for (const item of [...this.#activeReplacementItems]) {\n if (this.#visibleItems.has(item)) {\n continue;\n }\n const animation = this.#replacementAnimations.get(item);\n this.#replacementAnimations.delete(item);\n this.#activeReplacementItems.delete(item);\n if (animation?.kind === \"delete\") {\n adapter.onDeleteComplete(item);\n }\n changed = true;\n }\n return changed;\n }\n\n /** Advance all active animations and return true if any are still running. */\n prepare(\n now: number,\n adapter: Pick<ReplacementRendererAdapter<C, T>, \"onDeleteComplete\">,\n ): boolean {\n let keepAnimating = false;\n for (const item of [...this.#activeReplacementItems]) {\n if (this.readAnimation(item, now, adapter) != null) {\n keepAnimating = true;\n }\n }\n return keepAnimating;\n }\n\n /**\n * Returns the active animation for an item, or undefined if none / already\n * completed (and cleans up completed animations as a side effect).\n */\n readAnimation(\n item: T,\n now: number,\n adapter?: Pick<ReplacementRendererAdapter<C, T>, \"onDeleteComplete\">,\n ): ReplacementAnimation<C> | undefined {\n const animation = this.#replacementAnimations.get(item);\n if (animation == null) {\n return undefined;\n }\n if (getProgress(animation.startTime, animation.duration, now) >= 1) {\n this.#replacementAnimations.delete(item);\n this.#activeReplacementItems.delete(item);\n if (animation.kind === \"delete\") {\n adapter?.onDeleteComplete(item);\n }\n return undefined;\n }\n return animation;\n }\n\n /** Returns the effective rendered height for an item, accounting for animations. */\n getItemHeight(\n item: T,\n now: number,\n adapter: Pick<\n ReplacementRendererAdapter<C, T>,\n \"renderItem\" | \"measureNode\"\n >,\n ): number {\n const replacement = this.readAnimation(item, now);\n if (replacement != null) {\n return this.#sampleReplacementHeight(replacement, now);\n }\n const node = adapter.renderItem(item);\n return adapter.measureNode(node).height;\n }\n\n /** Resolves an item to its draw/hittest callbacks for the current frame. */\n resolveItem(\n item: T,\n now: number,\n adapter: ReplacementRendererAdapter<C, T>,\n ): { value: VirtualizedResolvedItem; height: number } {\n const replacement = this.readAnimation(item, now, adapter);\n if (replacement == null) {\n const node = adapter.renderItem(item);\n return {\n value: {\n draw: (y) => adapter.drawNode(node, 0, y),\n hittest: (test, y) =>\n node.hittest(adapter.getRootContext(), { ...test, y: test.y - y }),\n },\n height: adapter.measureNode(node).height,\n };\n }\n\n const slotHeight = this.#sampleReplacementHeight(replacement, now);\n const layers = this.#readReplacementLayers(\n replacement,\n now,\n adapter.measureNode,\n );\n\n return {\n value: {\n draw: (y) =>\n this.#drawReplacementLayers(layers, slotHeight, y, adapter),\n hittest: () => false,\n },\n height: slotHeight,\n };\n }\n\n handleListStateChange(\n change: ListStateChange<T>,\n ctx: ReplacementUpdateContext<C, T>,\n ): void {\n switch (change.type) {\n case \"update\":\n this.handleUpdate(\n change.prevItem,\n change.nextItem,\n change.animation?.duration,\n ctx,\n );\n break;\n case \"delete\":\n this.handleDelete(change.item, change.animation?.duration, ctx);\n break;\n case \"delete-finalize\":\n this.#replacementAnimations.delete(change.item);\n this.#activeReplacementItems.delete(change.item);\n break;\n case \"unshift\":\n case \"push\":\n break;\n case \"reset\":\n case \"set\":\n this.reset();\n break;\n }\n }\n\n handleUpdate(\n prevItem: T,\n nextItem: T,\n duration: number | undefined,\n ctx: ReplacementUpdateContext<C, T>,\n ): void {\n const normalizedDuration = Math.max(\n 0,\n typeof duration === \"number\" && Number.isFinite(duration) ? duration : 0,\n );\n const nextIndex = ctx.items.indexOf(nextItem);\n if (\n normalizedDuration <= 0 ||\n nextIndex < 0 ||\n !this.#canAnimateUpdate(nextIndex, prevItem, ctx)\n ) {\n this.#replacementAnimations.delete(prevItem);\n this.#activeReplacementItems.delete(prevItem);\n return;\n }\n\n const now = getNow();\n const nextNode = ctx.renderItem(nextItem);\n const nextHeight = ctx.measureNode(nextNode).height;\n const animation = this.readAnimation(prevItem, now, ctx);\n\n let currentNode: Node<C>;\n let currentAlpha = 1;\n let fromHeight: number;\n if (animation == null || animation.incoming == null) {\n currentNode = ctx.renderItem(prevItem);\n fromHeight = ctx.measureNode(currentNode).height;\n } else {\n currentNode = animation.incoming.node;\n currentAlpha = this.#sampleLayerAlpha(animation.incoming, now);\n fromHeight = this.#sampleReplacementHeight(animation, now);\n }\n\n const outgoing =\n currentAlpha > ALPHA_EPSILON\n ? this.#createLayer(\n currentNode,\n currentAlpha,\n 0,\n now,\n normalizedDuration,\n )\n : undefined;\n const incoming = this.#createLayer(nextNode, 0, 1, now, normalizedDuration);\n\n this.#replacementAnimations.delete(prevItem);\n this.#replacementAnimations.set(nextItem, {\n kind: \"update\",\n outgoing,\n incoming,\n fromHeight,\n toHeight: nextHeight,\n startTime: now,\n duration: normalizedDuration,\n });\n this.#activeReplacementItems.delete(prevItem);\n this.#activeReplacementItems.add(nextItem);\n }\n\n handleDelete(\n item: T,\n duration: number | undefined,\n ctx: ReplacementUpdateContext<C, T>,\n ): void {\n const normalizedDuration = Math.max(\n 0,\n typeof duration === \"number\" && Number.isFinite(duration) ? duration : 0,\n );\n const index = ctx.items.indexOf(item);\n if (\n normalizedDuration <= 0 ||\n index < 0 ||\n !this.#canAnimateUpdate(index, item, ctx)\n ) {\n this.#replacementAnimations.delete(item);\n this.#activeReplacementItems.delete(item);\n ctx.onDeleteComplete(item);\n return;\n }\n\n const now = getNow();\n const animation = this.readAnimation(item, now, ctx);\n\n let currentNode: Node<C>;\n let currentAlpha = 1;\n let fromHeight: number;\n if (animation == null) {\n currentNode = ctx.renderItem(item);\n fromHeight = ctx.measureNode(currentNode).height;\n } else if (animation.incoming != null) {\n currentNode = animation.incoming.node;\n currentAlpha = this.#sampleLayerAlpha(animation.incoming, now);\n fromHeight = this.#sampleReplacementHeight(animation, now);\n } else if (animation.outgoing != null) {\n currentNode = animation.outgoing.node;\n currentAlpha = this.#sampleLayerAlpha(animation.outgoing, now);\n fromHeight = this.#sampleReplacementHeight(animation, now);\n } else {\n currentNode = ctx.renderItem(item);\n fromHeight = ctx.measureNode(currentNode).height;\n }\n\n const outgoing =\n currentAlpha > ALPHA_EPSILON\n ? this.#createLayer(\n currentNode,\n currentAlpha,\n 0,\n now,\n normalizedDuration,\n )\n : undefined;\n\n this.#replacementAnimations.set(item, {\n kind: \"delete\",\n outgoing,\n incoming: undefined,\n fromHeight,\n toHeight: 0,\n startTime: now,\n duration: normalizedDuration,\n });\n this.#activeReplacementItems.add(item);\n }\n\n /** Clears all animation state (e.g., on list reset). */\n reset(): void {\n this.#replacementAnimations = new WeakMap<T, ReplacementAnimation<C>>();\n this.#activeReplacementItems.clear();\n this.#visibleItems.clear();\n this.#hasVisibleItemSnapshot = false;\n this.#visibleSnapshotState = undefined;\n }\n\n #createLayer(\n node: Node<C>,\n fromAlpha: number,\n toAlpha: number,\n startTime: number,\n duration: number,\n ): ReplacementLayer<C> {\n return { node, fromAlpha, toAlpha, startTime, duration };\n }\n\n #sampleLayerAlpha(layer: ReplacementLayer<C>, now: number): number {\n return interpolate(\n layer.fromAlpha,\n layer.toAlpha,\n layer.startTime,\n layer.duration,\n now,\n );\n }\n\n #sampleReplacementHeight(\n animation: ReplacementAnimation<C>,\n now: number,\n ): number {\n return interpolate(\n animation.fromHeight,\n animation.toHeight,\n animation.startTime,\n animation.duration,\n now,\n );\n }\n\n #readReplacementLayers(\n animation: ReplacementAnimation<C>,\n now: number,\n measureNode: (node: Node<C>) => Box,\n ): { alpha: number; node: Node<C>; nodeHeight: number }[] {\n return [animation.outgoing, animation.incoming]\n .filter((layer): layer is ReplacementLayer<C> => layer != null)\n .map((layer) => ({\n alpha: this.#sampleLayerAlpha(layer, now),\n node: layer.node,\n nodeHeight: measureNode(layer.node).height,\n }))\n .filter((layer) => layer.alpha > ALPHA_EPSILON);\n }\n\n #drawReplacementLayers(\n layers: { alpha: number; node: Node<C>; nodeHeight: number }[],\n slotHeight: number,\n y: number,\n adapter: ReplacementRendererAdapter<C, T>,\n ): boolean {\n if (slotHeight <= 0) {\n return false;\n }\n\n let result = false;\n const width = adapter.graphics.canvas.clientWidth;\n for (const layer of layers) {\n const alpha = clamp(layer.alpha, 0, 1);\n if (alpha <= ALPHA_EPSILON) {\n continue;\n }\n\n adapter.graphics.save();\n try {\n adapter.graphics.beginPath?.();\n adapter.graphics.rect?.(0, y, width, slotHeight);\n adapter.graphics.clip?.();\n if (typeof adapter.graphics.globalAlpha === \"number\") {\n adapter.graphics.globalAlpha *= alpha;\n }\n const layerY =\n y + adapter.getAnimatedLayerOffset(slotHeight, layer.nodeHeight);\n if (adapter.drawNode(layer.node, 0, layerY)) {\n result = true;\n }\n } finally {\n adapter.graphics.restore();\n }\n }\n return result;\n }\n\n #isIndexVisible(\n index: number,\n resolveVisibleWindow: () => VisibleWindowResult<unknown>,\n readVisibleRange: (\n top: number,\n height: number,\n ) => { top: number; bottom: number } | undefined,\n ): boolean {\n if (index < 0) {\n return false;\n }\n const solution = resolveVisibleWindow();\n for (const entry of solution.window.drawList) {\n if (entry.idx !== index) {\n continue;\n }\n if (\n readVisibleRange(entry.offset + solution.window.shift, entry.height) !=\n null\n ) {\n return true;\n }\n }\n return false;\n }\n\n #canAnimateUpdate(\n nextIndex: number,\n prevItem: T,\n ctx: ReplacementUpdateContext<C, T>,\n ): boolean {\n if (nextIndex < 0) {\n return false;\n }\n if (\n this.#hasVisibleItemSnapshot &&\n this.#visibleSnapshotState != null &&\n sameState(this.#visibleSnapshotState, ctx.position, ctx.offset)\n ) {\n return (\n this.#visibleItems.has(prevItem) ||\n this.#activeReplacementItems.has(prevItem)\n );\n }\n return this.#isIndexVisible(\n nextIndex,\n ctx.resolveVisibleWindow,\n ctx.readVisibleRange,\n );\n }\n}\n","import type { HitTest, Node, RenderFeedback } from \"../../types\";\nimport { BaseRenderer } from \"../base\";\nimport {\n ListState,\n subscribeListState,\n type ListStateChange,\n} from \"../list-state\";\nimport {\n clamp,\n getNow,\n getProgress,\n interpolate,\n sameState,\n} from \"./base-animation\";\nimport {\n type ControlledState,\n type JumpAnimation,\n type VirtualizedResolvedItem,\n} from \"./base-types\";\nimport {\n ReplacementController,\n type ReplacementRendererAdapter,\n type ReplacementUpdateContext,\n} from \"./base-replacement\";\nimport type {\n NormalizedListState,\n VisibleListState,\n VisibleWindow,\n VisibleWindowResult,\n} from \"./solver\";\n\n/**\n * Options for programmatic scrolling to a target item.\n */\nexport interface JumpToOptions {\n /** Whether to animate the jump. Defaults to `true`. */\n animated?: boolean;\n /** Which edge of the item should align with the viewport. */\n block?: \"start\" | \"center\" | \"end\";\n /** Animation duration in milliseconds. */\n duration?: number;\n /** Called after the jump completes or finishes animating. */\n onComplete?: () => void;\n}\n\n/**\n * Shared base class for virtualized list renderers.\n */\nexport abstract class VirtualizedRenderer<\n C extends CanvasRenderingContext2D,\n T extends {},\n> extends BaseRenderer<\n C,\n {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n }\n> {\n static readonly MIN_JUMP_DURATION = 160;\n static readonly MAX_JUMP_DURATION = 420;\n static readonly JUMP_DURATION_PER_ITEM = 28;\n\n #controlledState: ControlledState | undefined;\n #jumpAnimation: JumpAnimation | undefined;\n #replacementController = new ReplacementController<C, T>();\n\n constructor(\n graphics: C,\n options: {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n },\n ) {\n super(graphics, options);\n subscribeListState(options.list, this, (owner, change) => {\n owner.#handleListStateChange(change);\n });\n }\n\n /** Current anchor item index. */\n get position(): number | undefined {\n return this.options.list.position;\n }\n\n /** Updates the current anchor item index. */\n set position(value: number | undefined) {\n this.options.list.position = value;\n }\n\n /** Pixel offset from the anchored item edge. */\n get offset(): number {\n return this.options.list.offset;\n }\n\n /** Updates the pixel offset from the anchored item edge. */\n set offset(value: number) {\n this.options.list.offset = value;\n }\n\n /** Items currently available to the renderer. */\n get items(): T[] {\n return this.options.list.items;\n }\n\n /** Replaces the current item collection. */\n set items(value: T[]) {\n this.options.list.items = value;\n }\n\n /** Renders the current visible window. */\n render(feedback?: RenderFeedback): boolean {\n const now = getNow();\n const keepAnimating = this._prepareRender(now);\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } =\n this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n\n let solution = this._resolveVisibleWindow(now);\n this._captureVisibleItemSnapshot(solution.window);\n const requestSettleRedraw = this._pruneReplacementAnimations(\n solution.window,\n );\n if (requestSettleRedraw) {\n solution = this._resolveVisibleWindow(now);\n this._captureVisibleItemSnapshot(solution.window);\n }\n const requestRedraw = this._renderVisibleWindow(solution.window, feedback);\n this._commitListState(solution.normalizedState);\n\n return this._finishRender(\n keepAnimating || requestRedraw || requestSettleRedraw,\n );\n }\n\n /** Hit-tests the current visible window. */\n hittest(test: {\n x: number;\n y: number;\n type: \"click\" | \"auxclick\" | \"hover\";\n }): boolean {\n let solution = this._resolveVisibleWindow(getNow());\n this._captureVisibleItemSnapshot(solution.window);\n if (this._pruneReplacementAnimations(solution.window)) {\n solution = this._resolveVisibleWindow(getNow());\n this._captureVisibleItemSnapshot(solution.window);\n }\n return this._hittestVisibleWindow(solution.window, test);\n }\n\n protected _readListState(): VisibleListState {\n return {\n position: this.position,\n offset: this.offset,\n };\n }\n\n protected _commitListState(state: NormalizedListState): void {\n this.position = state.position;\n this.offset = state.offset;\n }\n\n /**\n * Scrolls the viewport to the requested item index.\n */\n jumpTo(index: number, options: JumpToOptions = {}): void {\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return;\n }\n\n const targetIndex = this._clampItemIndex(index);\n const currentState = this._normalizeListState(this._readListState());\n const targetBlock = options.block ?? this._getDefaultJumpBlock();\n const targetAnchor = this._getTargetAnchor(targetIndex, targetBlock);\n\n const animated = options.animated ?? true;\n if (!animated) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const startAnchor = this._readAnchor(currentState);\n if (!Number.isFinite(startAnchor)) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const duration = clamp(\n options.duration ??\n VirtualizedRenderer.MIN_JUMP_DURATION +\n Math.abs(targetAnchor - startAnchor) *\n VirtualizedRenderer.JUMP_DURATION_PER_ITEM,\n 0,\n VirtualizedRenderer.MAX_JUMP_DURATION,\n );\n\n if (\n duration <= 0 ||\n Math.abs(targetAnchor - startAnchor) <= Number.EPSILON\n ) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n this.#jumpAnimation = {\n startAnchor,\n targetAnchor,\n startTime: getNow(),\n duration,\n needsMoreFrames: true,\n onComplete: options.onComplete,\n };\n this.#controlledState = this._readListState();\n }\n\n protected _resetRenderFeedback(feedback?: RenderFeedback): void {\n if (feedback == null) {\n return;\n }\n feedback.minIdx = Number.NaN;\n feedback.maxIdx = Number.NaN;\n feedback.min = Number.NaN;\n feedback.max = Number.NaN;\n }\n\n protected _accumulateRenderFeedback(\n feedback: RenderFeedback,\n idx: number,\n top: number,\n height: number,\n ): void {\n const visibleRange = this._readVisibleRange(top, height);\n if (visibleRange == null) {\n return;\n }\n\n const itemMin = idx + visibleRange.top / height;\n const itemMax = idx + visibleRange.bottom / height;\n feedback.minIdx = Number.isNaN(feedback.minIdx)\n ? idx\n : Math.min(idx, feedback.minIdx);\n feedback.maxIdx = Number.isNaN(feedback.maxIdx)\n ? idx\n : Math.max(idx, feedback.maxIdx);\n feedback.min = Number.isNaN(feedback.min)\n ? itemMin\n : Math.min(itemMin, feedback.min);\n feedback.max = Number.isNaN(feedback.max)\n ? itemMax\n : Math.max(itemMax, feedback.max);\n }\n\n protected _renderDrawList(\n list: VisibleWindow<VirtualizedResolvedItem>[\"drawList\"],\n shift: number,\n feedback?: RenderFeedback,\n ): boolean {\n let result = false;\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n for (const { idx, value: item, offset, height } of list) {\n const y = offset + shift;\n if (feedback != null) {\n this._accumulateRenderFeedback(feedback, idx, y, height);\n }\n if (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (item.draw(y)) {\n result = true;\n }\n }\n\n return result;\n }\n\n protected _renderVisibleWindow(\n window: VisibleWindow<VirtualizedResolvedItem>,\n feedback?: RenderFeedback,\n ): boolean {\n this._resetRenderFeedback(feedback);\n return this._renderDrawList(window.drawList, window.shift, feedback);\n }\n\n protected _readVisibleRange(\n top: number,\n height: number,\n ): { top: number; bottom: number } | undefined {\n if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) {\n return undefined;\n }\n\n const viewportHeight = this.graphics.canvas.clientHeight;\n const visibleTop = clamp(-top, 0, height);\n const visibleBottom = clamp(viewportHeight - top, 0, height);\n if (visibleBottom <= visibleTop) {\n return undefined;\n }\n\n return {\n top: visibleTop,\n bottom: visibleBottom,\n };\n }\n\n protected _pruneReplacementAnimations(\n _window: VisibleWindow<unknown>,\n ): boolean {\n return this.#replacementController.pruneInvisible({\n onDeleteComplete: this.#handleDeleteComplete.bind(this),\n });\n }\n\n protected _hittestVisibleWindow(\n window: VisibleWindow<VirtualizedResolvedItem>,\n test: HitTest,\n ): boolean {\n for (const { value: item, offset, height } of window.drawList) {\n const y = offset + window.shift;\n if (test.y < y || test.y >= y + height) {\n continue;\n }\n return item.hittest(test, y);\n }\n return false;\n }\n\n protected _captureVisibleItemSnapshot(window: VisibleWindow<unknown>): void {\n this.#replacementController.captureVisibleItemSnapshot(\n window,\n this.items,\n this._readVisibleRange.bind(this),\n this._readListState.bind(this),\n );\n }\n\n protected _prepareRender(now: number): boolean {\n const keepReplacing = this.#replacementController.prepare(now, {\n onDeleteComplete: this.#handleDeleteComplete.bind(this),\n });\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return keepReplacing;\n }\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return keepReplacing;\n }\n if (\n this.#controlledState != null &&\n !sameState(this.#controlledState, this.position, this.offset)\n ) {\n this.#cancelJumpAnimation();\n return keepReplacing;\n }\n\n const anchor = interpolate(\n animation.startAnchor,\n animation.targetAnchor,\n animation.startTime,\n animation.duration,\n now,\n );\n const progress = getProgress(animation.startTime, animation.duration, now);\n this._applyAnchor(anchor);\n animation.needsMoreFrames = progress < 1;\n return keepReplacing || animation.needsMoreFrames;\n }\n\n protected _finishRender(requestRedraw: boolean): boolean {\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return requestRedraw;\n }\n\n if (animation.needsMoreFrames) {\n this.#controlledState = this._readListState();\n return true;\n }\n\n const onComplete = animation.onComplete;\n this.#cancelJumpAnimation();\n onComplete?.();\n return requestRedraw || this.#jumpAnimation != null;\n }\n\n protected _clampItemIndex(index: number): number {\n return clamp(\n Number.isFinite(index) ? Math.trunc(index) : 0,\n 0,\n this.items.length - 1,\n );\n }\n\n protected _getItemHeight(index: number): number {\n const item = this.items[index]!;\n return this.#replacementController.getItemHeight(item, getNow(), {\n renderItem: this.options.renderItem,\n measureNode: this.measureRootNode.bind(this),\n });\n }\n\n protected _resolveItem(\n item: T,\n _index: number,\n now: number,\n ): { value: VirtualizedResolvedItem; height: number } {\n return this.#replacementController.resolveItem(\n item,\n now,\n this.#getReplacementRendererAdapter(),\n );\n }\n\n protected _getAnchorAtOffset(index: number, offset: number): number {\n if (this.items.length === 0) {\n return 0;\n }\n\n let currentIndex = this._clampItemIndex(index);\n let remaining = Number.isFinite(offset) ? offset : 0;\n while (true) {\n if (remaining < 0) {\n if (currentIndex === 0) {\n return 0;\n }\n currentIndex -= 1;\n const height = this._getItemHeight(currentIndex);\n if (height > 0) {\n remaining += height;\n }\n continue;\n }\n\n const height = this._getItemHeight(currentIndex);\n if (height > 0) {\n if (remaining <= height) {\n return currentIndex + remaining / height;\n }\n remaining -= height;\n } else if (remaining === 0) {\n return currentIndex;\n }\n\n if (currentIndex === this.items.length - 1) {\n return this.items.length;\n }\n currentIndex += 1;\n }\n }\n\n protected abstract _normalizeListState(\n state: VisibleListState,\n ): NormalizedListState;\n protected abstract _resolveVisibleWindow(\n now: number,\n ): VisibleWindowResult<VirtualizedResolvedItem>;\n protected abstract _readAnchor(state: NormalizedListState): number;\n protected abstract _applyAnchor(anchor: number): void;\n protected abstract _getDefaultJumpBlock(): NonNullable<\n JumpToOptions[\"block\"]\n >;\n protected abstract _getTargetAnchor(\n index: number,\n block: NonNullable<JumpToOptions[\"block\"]>,\n ): number;\n protected abstract _getAnimatedLayerOffset(\n slotHeight: number,\n nodeHeight: number,\n ): number;\n\n // ── Jump animation ─────────────────────────────────────────────────────────\n\n #cancelJumpAnimation(): void {\n this.#jumpAnimation = undefined;\n this.#controlledState = undefined;\n }\n\n // ── Replacement animation delegation ───────────────────────────────────────\n\n #handleDeleteComplete(item: T): void {\n this.options.list.finalizeDelete(item);\n }\n\n #getReplacementRendererAdapter(): ReplacementRendererAdapter<C, T> {\n return {\n renderItem: this.options.renderItem,\n measureNode: this.measureRootNode.bind(this),\n drawNode: this.drawRootNode.bind(this),\n getRootContext: this.getRootContext.bind(this),\n graphics: this.graphics,\n getAnimatedLayerOffset: this._getAnimatedLayerOffset.bind(this),\n onDeleteComplete: this.#handleDeleteComplete.bind(this),\n };\n }\n\n #getReplacementUpdateContext(): ReplacementUpdateContext<C, T> {\n return {\n ...this.#getReplacementRendererAdapter(),\n items: this.items,\n position: this.position,\n offset: this.offset,\n readListState: this._readListState.bind(this),\n readVisibleRange: this._readVisibleRange.bind(this),\n resolveVisibleWindow: () => this._resolveVisibleWindow(getNow()),\n };\n }\n\n #handleListStateChange(change: ListStateChange<T>): void {\n this.#replacementController.handleListStateChange(\n change,\n this.#getReplacementUpdateContext(),\n );\n }\n}\n","export interface VisibleListState {\n position?: number;\n offset: number;\n}\n\nexport interface NormalizedListState {\n position: number;\n offset: number;\n}\n\nexport interface VisibleWindowEntry<T> {\n idx: number;\n value: T;\n offset: number;\n height: number;\n}\n\nexport interface VisibleWindow<T> {\n drawList: VisibleWindowEntry<T>[];\n shift: number;\n}\n\nexport interface VisibleWindowResult<T> {\n normalizedState: NormalizedListState;\n window: VisibleWindow<T>;\n}\n\ntype ResolvedItem<T> = {\n value: T;\n height: number;\n};\n\nexport type VisibleDirection = \"forward\" | \"backward\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction normalizeOffset(offset: number): number {\n return Number.isFinite(offset) ? offset : 0;\n}\n\nexport function normalizeVisibleState(\n itemCount: number,\n state: VisibleListState,\n direction: VisibleDirection,\n): NormalizedListState {\n if (itemCount <= 0) {\n return { position: 0, offset: 0 };\n }\n\n const position = state.position;\n const fallbackPosition = direction === \"forward\" ? 0 : itemCount - 1;\n if (typeof position !== \"number\" || !Number.isFinite(position)) {\n return {\n position: fallbackPosition,\n offset: normalizeOffset(state.offset),\n };\n }\n\n return {\n position: clamp(Math.trunc(position), 0, itemCount - 1),\n offset: normalizeOffset(state.offset),\n };\n}\n\nexport function normalizeTimelineState(\n itemCount: number,\n state: VisibleListState,\n): NormalizedListState {\n return normalizeVisibleState(itemCount, state, \"forward\");\n}\n\nexport function normalizeChatState(\n itemCount: number,\n state: VisibleListState,\n): NormalizedListState {\n return normalizeVisibleState(itemCount, state, \"backward\");\n}\n\nexport function resolveVisibleWindow<T, V>(\n items: readonly T[],\n state: VisibleListState,\n viewportHeight: number,\n resolveItem: (item: T, idx: number) => ResolvedItem<V>,\n direction: VisibleDirection,\n): VisibleWindowResult<V> {\n const normalizedState = normalizeVisibleState(items.length, state, direction);\n if (items.length === 0) {\n return {\n normalizedState,\n window: { drawList: [], shift: 0 },\n };\n }\n\n if (direction === \"forward\") {\n let { position, offset } = normalizedState;\n let drawLength = 0;\n\n if (offset > 0) {\n if (position === 0) {\n offset = 0;\n } else {\n for (let i = position - 1; i >= 0; i -= 1) {\n const { height } = resolveItem(items[i]!, i);\n position = i;\n offset -= height;\n if (offset <= 0) {\n break;\n }\n }\n if (position === 0 && offset > 0) {\n offset = 0;\n }\n }\n }\n\n let y = offset;\n const drawList: VisibleWindowEntry<V>[] = [];\n for (let i = position; i < items.length; i += 1) {\n const { value, height } = resolveItem(items[i]!, i);\n if (y + height > 0) {\n drawList.push({ idx: i, value, offset: y, height });\n drawLength += height;\n } else {\n offset += height;\n position = i + 1;\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n\n let shift = 0;\n if (y < viewportHeight) {\n if (position === 0 && drawLength < viewportHeight) {\n shift = -offset;\n offset = 0;\n } else {\n shift = viewportHeight - y;\n y = offset += shift;\n let lastIdx = -1;\n for (let i = position - 1; i >= 0; i -= 1) {\n const { value, height } = resolveItem(items[i]!, i);\n drawLength += height;\n y -= height;\n drawList.push({ idx: i, value, offset: y - shift, height });\n lastIdx = i;\n if (y < 0) {\n break;\n }\n }\n if (lastIdx === 0 && drawLength < viewportHeight) {\n shift =\n drawList.at(-1)?.offset == null ? 0 : -drawList.at(-1)!.offset;\n position = 0;\n offset = 0;\n }\n }\n }\n\n return {\n normalizedState: { position, offset },\n window: { drawList, shift },\n };\n }\n\n let { position, offset } = normalizedState;\n let drawLength = 0;\n\n if (offset < 0) {\n if (position === items.length - 1) {\n offset = 0;\n } else {\n for (let i = position + 1; i < items.length; i += 1) {\n const { height } = resolveItem(items[i]!, i);\n position = i;\n offset += height;\n if (offset > 0) {\n break;\n }\n }\n }\n }\n\n let y = viewportHeight + offset;\n const drawList: VisibleWindowEntry<V>[] = [];\n for (let i = position; i >= 0; i -= 1) {\n const { value, height } = resolveItem(items[i]!, i);\n y -= height;\n if (y <= viewportHeight) {\n drawList.push({ idx: i, value, offset: y, height });\n drawLength += height;\n } else {\n offset -= height;\n position = i - 1;\n }\n if (y < 0) {\n break;\n }\n }\n\n let shift = 0;\n if (y > 0) {\n shift = -y;\n if (drawLength < viewportHeight) {\n y = drawLength;\n for (let i = position + 1; i < items.length; i += 1) {\n const { value, height } = resolveItem(items[i]!, i);\n drawList.push({ idx: i, value, offset: y - shift, height });\n y = drawLength += height;\n position = i;\n if (y >= viewportHeight) {\n break;\n }\n }\n offset = drawLength < viewportHeight ? 0 : drawLength - viewportHeight;\n } else {\n offset = drawLength - viewportHeight;\n }\n }\n\n return {\n normalizedState: { position, offset },\n window: { drawList, shift },\n };\n}\n\nexport function resolveTimelineVisibleWindow<T, V>(\n items: readonly T[],\n state: VisibleListState,\n viewportHeight: number,\n resolveItem: (item: T, idx: number) => ResolvedItem<V>,\n): VisibleWindowResult<V> {\n return resolveVisibleWindow(\n items,\n state,\n viewportHeight,\n resolveItem,\n \"forward\",\n );\n}\n\nexport function resolveChatVisibleWindow<T, V>(\n items: readonly T[],\n state: VisibleListState,\n viewportHeight: number,\n resolveItem: (item: T, idx: number) => ResolvedItem<V>,\n): VisibleWindowResult<V> {\n return resolveVisibleWindow(\n items,\n state,\n viewportHeight,\n resolveItem,\n \"backward\",\n );\n}\n","import { VirtualizedRenderer } from \"./base\";\nimport type { JumpToOptions } from \"./base\";\nimport {\n normalizeChatState,\n resolveChatVisibleWindow,\n type NormalizedListState,\n type VisibleListState,\n} from \"./solver\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Virtualized renderer anchored to the bottom, suitable for chat-style UIs.\n */\nexport class ChatRenderer<\n C extends CanvasRenderingContext2D,\n T extends {},\n> extends VirtualizedRenderer<C, T> {\n protected _resolveVisibleWindow(now: number) {\n return resolveChatVisibleWindow(\n this.items,\n this._readListState(),\n this.graphics.canvas.clientHeight,\n (item, idx) => {\n return this._resolveItem(item, idx, now);\n },\n );\n }\n\n protected _getDefaultJumpBlock(): NonNullable<JumpToOptions[\"block\"]> {\n return \"end\";\n }\n\n protected _normalizeListState(state: VisibleListState): NormalizedListState {\n return normalizeChatState(this.items.length, state);\n }\n\n protected _readAnchor(state: NormalizedListState): number {\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(state.position);\n return height > 0\n ? state.position + 1 - state.offset / height\n : state.position + 1;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(\n Math.ceil(clampedAnchor) - 1,\n 0,\n this.items.length - 1,\n );\n const height = this._getItemHeight(position);\n const offset = height > 0 ? (position + 1 - clampedAnchor) * height : 0;\n this._commitListState({\n position,\n offset: Object.is(offset, -0) ? 0 : offset,\n });\n }\n\n protected _getTargetAnchor(\n index: number,\n block: NonNullable<JumpToOptions[\"block\"]>,\n ): number {\n const height = this._getItemHeight(index);\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n switch (block) {\n case \"start\":\n return this._getAnchorAtOffset(index, viewportHeight);\n case \"center\":\n return this._getAnchorAtOffset(index, height / 2 + viewportHeight / 2);\n case \"end\":\n return this._getAnchorAtOffset(index, height);\n }\n }\n\n protected _getAnimatedLayerOffset(\n slotHeight: number,\n nodeHeight: number,\n ): number {\n return slotHeight - nodeHeight;\n }\n}\n","import { VirtualizedRenderer } from \"./base\";\nimport type { JumpToOptions } from \"./base\";\nimport {\n normalizeTimelineState,\n resolveTimelineVisibleWindow,\n type NormalizedListState,\n type VisibleListState,\n} from \"./solver\";\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Virtualized renderer anchored to the top, suitable for timeline-style UIs.\n */\nexport class TimelineRenderer<\n C extends CanvasRenderingContext2D,\n T extends {},\n> extends VirtualizedRenderer<C, T> {\n protected _resolveVisibleWindow(now: number) {\n return resolveTimelineVisibleWindow(\n this.items,\n this._readListState(),\n this.graphics.canvas.clientHeight,\n (item, idx) => {\n return this._resolveItem(item, idx, now);\n },\n );\n }\n\n protected _getDefaultJumpBlock(): NonNullable<JumpToOptions[\"block\"]> {\n return \"start\";\n }\n\n protected _normalizeListState(state: VisibleListState): NormalizedListState {\n return normalizeTimelineState(this.items.length, state);\n }\n\n protected _readAnchor(state: NormalizedListState): number {\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(state.position);\n return height > 0 ? state.position - state.offset / height : state.position;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.floor(clampedAnchor), 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n const offset = height > 0 ? -(clampedAnchor - position) * height : 0;\n this._commitListState({\n position,\n offset: Object.is(offset, -0) ? 0 : offset,\n });\n }\n\n protected _getTargetAnchor(\n index: number,\n block: NonNullable<JumpToOptions[\"block\"]>,\n ): number {\n const height = this._getItemHeight(index);\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n switch (block) {\n case \"start\":\n return this._getAnchorAtOffset(index, 0);\n case \"center\":\n return this._getAnchorAtOffset(index, height / 2 - viewportHeight / 2);\n case \"end\":\n return this._getAnchorAtOffset(index, height - viewportHeight);\n }\n }\n\n protected _getAnimatedLayerOffset(\n _slotHeight: number,\n _nodeHeight: number,\n ): number {\n return 0;\n }\n}\n"],"mappings":"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"}