open-plant 1.4.20 → 1.4.21
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/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/core/gl-utils.ts","../src/core/ortho-camera.ts","../src/core/m1-tile-renderer.ts","../node_modules/splaytree/dist/splaytree.js","../node_modules/robust-predicates/esm/util.js","../node_modules/robust-predicates/esm/orient2d.js","../node_modules/polygon-clipping/dist/polygon-clipping.esm.js","../src/wsi/roi-geometry.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/wsi/brush-stroke.ts","../src/wsi/device-pixel-ratio.ts","../src/react/draw-layer-types.ts","../src/react/draw-layer-utils.ts","../src/react/draw-layer-brush.ts","../src/react/draw-layer-label.ts","../src/react/draw-layer-overlay.ts","../src/react/draw-layer-stamp.ts","../src/react/draw-layer.tsx","../src/react/viewer-context.ts","../src/react/drawing-layer.tsx","../src/wsi/spatial-index.ts","../src/react/heatmap-webgl.ts","../src/react/heatmap-layer.tsx","../src/react/overlay-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/patch-layer.tsx","../src/wsi/point-clip.ts","../src/wsi/webgpu.ts","../src/wsi/point-clip-hybrid.ts","../src/wsi/worker-client.ts","../src/wsi/point-clip-worker-client.ts","../src/react/use-point-clipping.ts","../src/wsi/point-hit-index-shared.ts","../src/wsi/point-hit-index-worker-client.ts","../src/react/use-point-hit-test.ts","../src/react/point-layer.tsx","../src/react/use-region-label-auto-lift.ts","../src/react/wsi-region-hit-utils.ts","../src/react/region-layer.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/tile-scheduler.ts","../src/wsi/wsi-canvas-lifecycle.ts","../src/wsi/wsi-normalize.ts","../src/wsi/wsi-interaction.ts","../src/wsi/wsi-tile-visibility.ts","../src/wsi/wsi-input-handlers.ts","../src/wsi/wsi-tile-cache.ts","../src/wsi/wsi-lifecycle-ops.ts","../src/wsi/wsi-point-data.ts","../src/wsi/wsi-render-pass.ts","../src/wsi/wsi-shaders.ts","../src/wsi/wsi-view-animation.ts","../src/wsi/wsi-view-ops.ts","../src/wsi/wsi-zoom-snap.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer.tsx","../src/wsi/roi-class-stats.ts","../src/wsi/wkt.ts"],"sourcesContent":["function compileShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new Error(\"Failed to create shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);\n if (!ok) {\n const log = gl.getShaderInfoLog(shader) ?? \"unknown shader error\";\n gl.deleteShader(shader);\n throw new Error(log);\n }\n\n return shader;\n}\n\nexport function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\n const program = gl.createProgram();\n if (!program) {\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n throw new Error(\"Failed to create program.\");\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const ok = gl.getProgramParameter(program, gl.LINK_STATUS);\n if (!ok) {\n const log = gl.getProgramInfoLog(program) ?? \"unknown link error\";\n gl.deleteProgram(program);\n throw new Error(log);\n }\n\n return program;\n}\n\nexport function requireUniformLocation(gl: WebGL2RenderingContext, program: WebGLProgram, uniformName: string): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, uniformName);\n if (!location) {\n throw new Error(`Failed to get uniform location: ${uniformName}`);\n }\n return location;\n}\n\nexport function requireWebGL2(canvas: HTMLCanvasElement, options?: { preserveDrawingBuffer?: boolean }): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: options?.preserveDrawingBuffer ?? false,\n powerPreference: \"high-performance\",\n });\n\n if (!context) {\n throw new Error(\"WebGL2 is not available.\");\n }\n\n return context;\n}\n","export interface ViewState {\n offsetX: number;\n offsetY: number;\n zoom: number;\n rotationDeg: number;\n}\n\nexport type WorldPoint = [number, number];\n\nfunction toRadians(deg: number): number {\n return (deg * Math.PI) / 180;\n}\n\nexport class OrthoCamera {\n private viewportWidth = 1;\n private viewportHeight = 1;\n\n private viewState: ViewState = {\n offsetX: 0,\n offsetY: 0,\n zoom: 1,\n rotationDeg: 0,\n };\n\n setViewport(width: number, height: number): void {\n this.viewportWidth = Math.max(1, width);\n this.viewportHeight = Math.max(1, height);\n }\n\n getViewportSize(): { width: number; height: number } {\n return {\n width: this.viewportWidth,\n height: this.viewportHeight,\n };\n }\n\n setViewState(next: Partial<ViewState>): void {\n if (next.offsetX !== undefined) {\n this.viewState.offsetX = next.offsetX;\n }\n\n if (next.offsetY !== undefined) {\n this.viewState.offsetY = next.offsetY;\n }\n\n if (next.zoom !== undefined) {\n this.viewState.zoom = Math.max(0.0001, next.zoom);\n }\n\n if (typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg)) {\n this.viewState.rotationDeg = next.rotationDeg;\n }\n }\n\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getCenter(): WorldPoint {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n return [\n this.viewState.offsetX + this.viewportWidth / (2 * zoom),\n this.viewState.offsetY + this.viewportHeight / (2 * zoom),\n ];\n }\n\n setCenter(centerX: number, centerY: number): void {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n this.viewState.offsetX = centerX - this.viewportWidth / (2 * zoom);\n this.viewState.offsetY = centerY - this.viewportHeight / (2 * zoom);\n }\n\n screenToWorld(screenX: number, screenY: number): WorldPoint {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n const [centerX, centerY] = this.getCenter();\n const rotationDeg = this.viewState.rotationDeg ?? 0;\n const dx = (screenX - this.viewportWidth * 0.5) / zoom;\n const dy = (screenY - this.viewportHeight * 0.5) / zoom;\n const rad = toRadians(rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n return [centerX + dx * cos - dy * sin, centerY + dx * sin + dy * cos];\n }\n\n worldToScreen(worldX: number, worldY: number): WorldPoint {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n const [centerX, centerY] = this.getCenter();\n const rotationDeg = this.viewState.rotationDeg ?? 0;\n const dx = worldX - centerX;\n const dy = worldY - centerY;\n const rad = toRadians(rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const rx = dx * cos + dy * sin;\n const ry = -dx * sin + dy * cos;\n return [\n this.viewportWidth * 0.5 + rx * zoom,\n this.viewportHeight * 0.5 + ry * zoom,\n ];\n }\n\n getViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n const w = this.viewportWidth;\n const h = this.viewportHeight;\n return [\n this.screenToWorld(0, 0),\n this.screenToWorld(w, 0),\n this.screenToWorld(w, h),\n this.screenToWorld(0, h),\n ];\n }\n\n getMatrix(): Float32Array {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n const rotationDeg = this.viewState.rotationDeg ?? 0;\n\n if (rotationDeg === 0) {\n const viewWidth = this.viewportWidth / zoom;\n const viewHeight = this.viewportHeight / zoom;\n const sx = 2 / viewWidth;\n const sy = -2 / viewHeight;\n const tx = -1 - this.viewState.offsetX * sx;\n const ty = 1 - this.viewState.offsetY * sy;\n return new Float32Array([sx, 0, 0, 0, sy, 0, tx, ty, 1]);\n }\n\n const [centerX, centerY] = this.getCenter();\n const rad = toRadians(rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const ax = (2 * zoom * cos) / this.viewportWidth;\n const bx = (2 * zoom * sin) / this.viewportWidth;\n const ay = (2 * zoom * sin) / this.viewportHeight;\n const by = (-2 * zoom * cos) / this.viewportHeight;\n const tx = -(ax * centerX + bx * centerY);\n const ty = -(ay * centerX + by * centerY);\n return new Float32Array([ax, ay, 0, bx, by, 0, tx, ty, 1]);\n }\n}\n","import { createProgram, requireUniformLocation, requireWebGL2 } from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n id: string;\n bounds: Bounds;\n texture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n canvas: HTMLCanvasElement;\n imageWidth: number;\n imageHeight: number;\n clearColor?: [number, number, number, number];\n initialViewState?: Partial<ViewState>;\n preserveDrawingBuffer?: boolean;\n}\n\nconst VERTEX_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 aUnit;\nin vec2 aUv;\n\nuniform mat3 uCamera;\nuniform vec4 uBounds;\n\nout vec2 vUv;\n\nvoid main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n}\n`;\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nuniform sampler2D uTexture;\n\nout vec4 outColor;\n\nvoid main() {\n outColor = texture(uTexture, vUv);\n}\n`;\n\nexport class M1TileRenderer {\n private readonly canvas: HTMLCanvasElement;\n private readonly gl: WebGL2RenderingContext;\n private readonly camera = new OrthoCamera();\n private readonly imageWidth: number;\n private readonly imageHeight: number;\n private readonly clearColor: [number, number, number, number];\n private readonly program: WebGLProgram;\n private readonly vao: WebGLVertexArrayObject;\n private readonly quadBuffer: WebGLBuffer;\n private readonly uCameraLocation: WebGLUniformLocation;\n private readonly uBoundsLocation: WebGLUniformLocation;\n private readonly uTextureLocation: WebGLUniformLocation;\n private readonly resizeObserver: ResizeObserver;\n\n private tiles: LoadedTile[] = [];\n private frameId: number | null = null;\n private loadVersion = 0;\n private destroyed = false;\n private fitted = false;\n private controlledViewState = false;\n\n constructor(options: M1TileRendererOptions) {\n this.canvas = options.canvas;\n this.imageWidth = Math.max(1, options.imageWidth);\n this.imageHeight = Math.max(1, options.imageHeight);\n this.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n this.gl = requireWebGL2(this.canvas, { preserveDrawingBuffer: options.preserveDrawingBuffer });\n this.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n const vao = this.gl.createVertexArray();\n const quadBuffer = this.gl.createBuffer();\n if (!vao || !quadBuffer) {\n throw new Error(\"Failed to create WebGL buffers.\");\n }\n\n this.vao = vao;\n this.quadBuffer = quadBuffer;\n\n this.gl.bindVertexArray(this.vao);\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n const quadVertices = new Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]);\n\n this.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n const unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n const uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n if (unitLocation < 0 || uvLocation < 0) {\n throw new Error(\"Failed to get attribute locations.\");\n }\n\n const stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n this.gl.enableVertexAttribArray(unitLocation);\n this.gl.vertexAttribPointer(unitLocation, 2, this.gl.FLOAT, false, stride, 0);\n this.gl.enableVertexAttribArray(uvLocation);\n this.gl.vertexAttribPointer(uvLocation, 2, this.gl.FLOAT, false, stride, 2 * Float32Array.BYTES_PER_ELEMENT);\n\n this.gl.bindVertexArray(null);\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n this.uCameraLocation = requireUniformLocation(this.gl, this.program, \"uCamera\");\n this.uBoundsLocation = requireUniformLocation(this.gl, this.program, \"uBounds\");\n this.uTextureLocation = requireUniformLocation(this.gl, this.program, \"uTexture\");\n\n if (options.initialViewState) {\n this.controlledViewState = true;\n this.camera.setViewState(options.initialViewState);\n }\n\n this.resizeObserver = new ResizeObserver(() => {\n this.resize();\n });\n\n this.resizeObserver.observe(this.canvas);\n this.resize();\n }\n\n async setTiles(tiles: TileDefinition[]): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n const version = ++this.loadVersion;\n\n const loaded = await Promise.all(\n tiles.map(async tile => {\n const loadedTile = await this.loadTile(tile, version);\n return loadedTile;\n })\n );\n\n if (this.destroyed || version !== this.loadVersion) {\n for (const tile of loaded) {\n if (tile) {\n this.gl.deleteTexture(tile.texture);\n }\n }\n return;\n }\n\n this.disposeTiles(this.tiles);\n this.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n this.requestRender();\n }\n\n setViewState(viewState: Partial<ViewState>): void {\n this.controlledViewState = true;\n this.camera.setViewState(viewState);\n this.requestRender();\n }\n\n getViewState(): ViewState {\n return this.camera.getViewState();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n this.loadVersion += 1;\n\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n\n this.resizeObserver.disconnect();\n this.disposeTiles(this.tiles);\n this.tiles = [];\n\n this.gl.deleteBuffer(this.quadBuffer);\n this.gl.deleteVertexArray(this.vao);\n this.gl.deleteProgram(this.program);\n }\n\n private async loadTile(tile: TileDefinition, version: number): Promise<LoadedTile | null> {\n try {\n const response = await fetch(tile.url);\n if (!response.ok) {\n throw new Error(`Tile fetch failed: ${response.status} ${response.statusText}`);\n }\n\n const blob = await response.blob();\n const bitmap = await createImageBitmap(blob);\n\n if (this.destroyed || version !== this.loadVersion) {\n bitmap.close();\n return null;\n }\n\n const texture = this.gl.createTexture();\n if (!texture) {\n bitmap.close();\n throw new Error(\"Failed to create tile texture.\");\n }\n\n this.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, bitmap);\n this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n bitmap.close();\n\n return {\n id: tile.id,\n bounds: tile.bounds,\n texture,\n };\n } catch (error) {\n console.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n return null;\n }\n }\n\n private resize(): void {\n if (this.destroyed) {\n return;\n }\n\n const rect = this.canvas.getBoundingClientRect();\n const cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n const cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n const targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n if (this.canvas.width !== targetWidth || this.canvas.height !== targetHeight) {\n this.canvas.width = targetWidth;\n this.canvas.height = targetHeight;\n }\n\n this.camera.setViewport(cssWidth, cssHeight);\n this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n if (!this.fitted && !this.controlledViewState) {\n this.fitToImage();\n this.fitted = true;\n }\n\n this.requestRender();\n }\n\n private fitToImage(): void {\n const viewport = this.camera.getViewportSize();\n\n const zoom = Math.min(viewport.width / this.imageWidth, viewport.height / this.imageHeight);\n const safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n const visibleWorldWidth = viewport.width / safeZoom;\n const visibleWorldHeight = viewport.height / safeZoom;\n\n const offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n const offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n this.camera.setViewState({\n zoom: safeZoom,\n offsetX,\n offsetY,\n });\n }\n\n private requestRender(): void {\n if (this.frameId !== null || this.destroyed) {\n return;\n }\n\n this.frameId = requestAnimationFrame(() => {\n this.frameId = null;\n this.render();\n });\n }\n\n private render(): void {\n if (this.destroyed) {\n return;\n }\n\n this.gl.clearColor(this.clearColor[0], this.clearColor[1], this.clearColor[2], this.clearColor[3]);\n this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n this.gl.useProgram(this.program);\n this.gl.bindVertexArray(this.vao);\n this.gl.uniformMatrix3fv(this.uCameraLocation, false, this.camera.getMatrix());\n this.gl.uniform1i(this.uTextureLocation, 0);\n\n for (const tile of this.tiles) {\n this.gl.activeTexture(this.gl.TEXTURE0);\n this.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n this.gl.uniform4f(this.uBoundsLocation, tile.bounds[0], tile.bounds[1], tile.bounds[2], tile.bounds[3]);\n this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n }\n\n this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n this.gl.bindVertexArray(null);\n }\n\n private disposeTiles(tiles: LoadedTile[]): void {\n for (const tile of tiles) {\n this.gl.deleteTexture(tile.texture);\n }\n }\n}\n","class f {\n constructor(t, e) {\n this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;\n }\n}\nfunction d(n, t) {\n return n > t ? 1 : n < t ? -1 : 0;\n}\nfunction u(n, t, e) {\n const r = new f(null, null);\n let l = r, i = r;\n for (; ; ) {\n const o = e(n, t.key);\n if (o < 0) {\n if (t.left === null) break;\n if (e(n, t.left.key) < 0) {\n const s = t.left;\n if (t.left = s.right, s.right = t, t = s, t.left === null) break;\n }\n i.left = t, i = t, t = t.left;\n } else if (o > 0) {\n if (t.right === null) break;\n if (e(n, t.right.key) > 0) {\n const s = t.right;\n if (t.right = s.left, s.left = t, t = s, t.right === null) break;\n }\n l.right = t, l = t, t = t.right;\n } else break;\n }\n return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;\n}\nfunction c(n, t, e, r) {\n const l = new f(n, t);\n if (e === null)\n return l.left = l.right = null, l;\n e = u(n, e, r);\n const i = r(n, e.key);\n return i < 0 ? (l.left = e.left, l.right = e, e.left = null) : i >= 0 && (l.right = e.right, l.left = e, e.right = null), l;\n}\nfunction m(n, t, e) {\n let r = null, l = null;\n if (t) {\n t = u(n, t, e);\n const i = e(t.key, n);\n i === 0 ? (r = t.left, l = t.right) : i < 0 ? (l = t.right, t.right = null, r = t) : (r = t.left, t.left = null, l = t);\n }\n return { left: r, right: l };\n}\nfunction w(n, t, e) {\n return t === null ? n : (n === null || (t = u(n.key, t, e), t.left = n), t);\n}\nfunction _(n, t, e, r, l) {\n if (n) {\n r(`${t}${e ? \"└── \" : \"├── \"}${l(n)}\n`);\n const i = t + (e ? \" \" : \"│ \");\n n.left && _(n.left, i, !1, r, l), n.right && _(n.right, i, !0, r, l);\n }\n}\nclass z {\n constructor(t = d) {\n this._root = null, this._size = 0, this._comparator = t;\n }\n /**\n * Inserts a key, allows duplicates\n */\n insert(t, e) {\n return this._size++, this._root = c(t, e, this._root, this._comparator);\n }\n /**\n * Adds a key, if it is not present in the tree\n */\n add(t, e) {\n const r = new f(t, e);\n this._root === null && (r.left = r.right = null, this._size++, this._root = r);\n const l = this._comparator, i = u(t, this._root, l), o = l(t, i.key);\n return o === 0 ? this._root = i : (o < 0 ? (r.left = i.left, r.right = i, i.left = null) : o > 0 && (r.right = i.right, r.left = i, i.right = null), this._size++, this._root = r), this._root;\n }\n /**\n * @param {Key} key\n * @return {Node|null}\n */\n remove(t) {\n this._root = this._remove(t, this._root, this._comparator);\n }\n /**\n * Deletes i from the tree if it's there\n */\n _remove(t, e, r) {\n let l;\n return e === null ? null : (e = u(t, e, r), r(t, e.key) === 0 ? (e.left === null ? l = e.right : (l = u(t, e.left, r), l.right = e.right), this._size--, l) : e);\n }\n /**\n * Removes and returns the node with smallest key\n */\n pop() {\n let t = this._root;\n if (t) {\n for (; t.left; ) t = t.left;\n return this._root = u(t.key, this._root, this._comparator), this._root = this._remove(t.key, this._root, this._comparator), { key: t.key, data: t.data };\n }\n return null;\n }\n /**\n * Find without splaying\n */\n findStatic(t) {\n let e = this._root;\n const r = this._comparator;\n for (; e; ) {\n const l = r(t, e.key);\n if (l === 0) return e;\n l < 0 ? e = e.left : e = e.right;\n }\n return null;\n }\n find(t) {\n return this._root && (this._root = u(t, this._root, this._comparator), this._comparator(t, this._root.key) !== 0) ? null : this._root;\n }\n contains(t) {\n let e = this._root;\n const r = this._comparator;\n for (; e; ) {\n const l = r(t, e.key);\n if (l === 0) return !0;\n l < 0 ? e = e.left : e = e.right;\n }\n return !1;\n }\n forEach(t, e) {\n let r = this._root;\n const l = [];\n let i = !1;\n for (; !i; )\n r !== null ? (l.push(r), r = r.left) : l.length !== 0 ? (r = l.pop(), t.call(e, r), r = r.right) : i = !0;\n return this;\n }\n /**\n * Walk key range from `low` to `high`. Stops if `fn` returns a value.\n */\n range(t, e, r, l) {\n const i = [], o = this._comparator;\n let s = this._root, h;\n for (; i.length !== 0 || s; )\n if (s)\n i.push(s), s = s.left;\n else {\n if (s = i.pop(), h = o(s.key, e), h > 0)\n break;\n if (o(s.key, t) >= 0 && r.call(l, s))\n return this;\n s = s.right;\n }\n return this;\n }\n /**\n * Returns array of keys\n */\n keys() {\n const t = [];\n return this.forEach(({ key: e }) => {\n t.push(e);\n }), t;\n }\n /**\n * Returns array of all the data in the nodes\n */\n values() {\n const t = [];\n return this.forEach(({ data: e }) => {\n t.push(e);\n }), t;\n }\n min() {\n return this._root ? this.minNode(this._root).key : null;\n }\n max() {\n return this._root ? this.maxNode(this._root).key : null;\n }\n minNode(t = this._root) {\n if (t) for (; t.left; ) t = t.left;\n return t;\n }\n maxNode(t = this._root) {\n if (t) for (; t.right; ) t = t.right;\n return t;\n }\n /**\n * Returns node at given index\n */\n at(t) {\n let e = this._root, r = !1, l = 0;\n const i = [];\n for (; !r; )\n if (e)\n i.push(e), e = e.left;\n else if (i.length > 0) {\n if (e = i.pop(), l === t) return e;\n l++, e = e.right;\n } else r = !0;\n return null;\n }\n next(t) {\n let e = this._root, r = null;\n if (t.right) {\n for (r = t.right; r.left; ) r = r.left;\n return r;\n }\n const l = this._comparator;\n for (; e; ) {\n const i = l(t.key, e.key);\n if (i === 0) break;\n i < 0 ? (r = e, e = e.left) : e = e.right;\n }\n return r;\n }\n prev(t) {\n let e = this._root, r = null;\n if (t.left !== null) {\n for (r = t.left; r.right; ) r = r.right;\n return r;\n }\n const l = this._comparator;\n for (; e; ) {\n const i = l(t.key, e.key);\n if (i === 0) break;\n i < 0 ? e = e.left : (r = e, e = e.right);\n }\n return r;\n }\n clear() {\n return this._root = null, this._size = 0, this;\n }\n toList() {\n return k(this._root);\n }\n /**\n * Bulk-load items. Both array have to be same size\n */\n load(t, e = [], r = !1) {\n let l = t.length;\n const i = this._comparator;\n if (r && g(t, e, 0, l - 1, i), this._root === null)\n this._root = a(t, e, 0, l), this._size = l;\n else {\n const o = y(\n this.toList(),\n x(t, e),\n i\n );\n l = this._size + l, this._root = p({ head: o }, 0, l);\n }\n return this;\n }\n isEmpty() {\n return this._root === null;\n }\n get size() {\n return this._size;\n }\n get root() {\n return this._root;\n }\n toString(t = (e) => String(e.key)) {\n const e = [];\n return _(this._root, \"\", !0, (r) => e.push(r), t), e.join(\"\");\n }\n update(t, e, r) {\n const l = this._comparator;\n let { left: i, right: o } = m(t, this._root, l);\n l(t, e) < 0 ? o = c(e, r, o, l) : i = c(e, r, i, l), this._root = w(i, o, l);\n }\n split(t) {\n return m(t, this._root, this._comparator);\n }\n *[Symbol.iterator]() {\n let t = this._root;\n const e = [];\n let r = !1;\n for (; !r; )\n t !== null ? (e.push(t), t = t.left) : e.length !== 0 ? (t = e.pop(), yield t, t = t.right) : r = !0;\n }\n}\nfunction a(n, t, e, r) {\n const l = r - e;\n if (l > 0) {\n const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f(o, s);\n return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;\n }\n return null;\n}\nfunction x(n, t) {\n const e = new f(null, null);\n let r = e;\n for (let l = 0; l < n.length; l++)\n r = r.next = new f(n[l], t[l]);\n return r.next = null, e.next;\n}\nfunction k(n) {\n let t = n;\n const e = [];\n let r = !1;\n const l = new f(null, null);\n let i = l;\n for (; !r; )\n t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = !0;\n return i.next = null, l.next;\n}\nfunction p(n, t, e) {\n const r = e - t;\n if (r > 0) {\n const l = t + Math.floor(r / 2), i = p(n, t, l), o = n.head;\n return o.left = i, n.head = n.head.next, o.right = p(n, l + 1, e), o;\n }\n return null;\n}\nfunction y(n, t, e) {\n const r = new f(null, null);\n let l = r, i = n, o = t;\n for (; i !== null && o !== null; )\n e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;\n return i !== null ? l.next = i : o !== null && (l.next = o), r.next;\n}\nfunction g(n, t, e, r, l) {\n if (e >= r) return;\n const i = n[e + r >> 1];\n let o = e - 1, s = r + 1;\n for (; ; ) {\n do\n o++;\n while (l(n[o], i) < 0);\n do\n s--;\n while (l(n[s], i) > 0);\n if (o >= s) break;\n let h = n[o];\n n[o] = n[s], n[s] = h, h = t[o], t[o] = t[s], t[s] = h;\n }\n g(n, t, e, s, l), g(n, t, s + 1, r, l);\n}\nexport {\n z as default\n};\n//# sourceMappingURL=splaytree.js.map\n","export const epsilon = 1.1102230246251565e-16;\nexport const splitter = 134217729;\nexport const resulterrbound = (3 + 8 * epsilon) * epsilon;\n\n// fast_expansion_sum_zeroelim routine from oritinal code\nexport function sum(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if ((fnow > enow) === (fnow > -enow)) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function sum_three(alen, a, blen, b, clen, c, tmp, out) {\n return sum(sum(alen, a, blen, b, tmp), tmp, clen, c, out);\n}\n\n// scale_expansion_zeroelim routine from oritinal code\nexport function scale(elen, e, b, h) {\n let Q, sum, hh, product1, product0;\n let bvirt, c, ahi, alo, bhi, blo;\n\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n let enow = e[0];\n Q = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);\n let hindex = 0;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n for (let i = 1; i < elen; i++) {\n enow = e[i];\n product1 = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);\n sum = Q + product0;\n bvirt = sum - Q;\n hh = Q - (sum - bvirt) + (product0 - bvirt);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n Q = product1 + sum;\n hh = sum - (Q - product1);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function negate(elen, e) {\n for (let i = 0; i < elen; i++) e[i] = -e[i];\n return elen;\n}\n\nexport function estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\n\nexport function vec(n) {\n return new Float64Array(n);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum} from './util.js';\n\nconst ccwerrboundA = (3 + 16 * epsilon) * epsilon;\nconst ccwerrboundB = (2 + 12 * epsilon) * epsilon;\nconst ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;\n\nconst B = vec(4);\nconst C1 = vec(8);\nconst C2 = vec(12);\nconst D = vec(16);\nconst u = vec(4);\n\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n\n s1 = acx * bcy;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcx;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n B[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n B[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n B[2] = _j - (u3 - bvirt) + (_i - bvirt);\n B[3] = u3;\n\n let det = estimate(4, B);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n\n s1 = acxtail * bcy;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcx;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C1len = sum(4, B, 4, u, C1);\n\n s1 = acx * bcytail;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcxtail;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C2len = sum(C1len, C1, 4, u, C2);\n\n s1 = acxtail * bcytail;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcxtail;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const Dlen = sum(C2len, C2, 4, u, D);\n\n return D[Dlen - 1];\n}\n\nexport function orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\nexport function orient2dfast(ax, ay, bx, by, cx, cy) {\n return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);\n}\n","import SplayTree from 'splaytree';\nimport { orient2d } from 'robust-predicates';\n\n/**\n * A bounding box has the format:\n *\n * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }\n *\n */\n\nconst isInBbox = (bbox, point) => {\n return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;\n};\n\n/* Returns either null, or a bbox (aka an ordered pair of points)\n * If there is only one point of overlap, a bbox with identical points\n * will be returned */\nconst getBboxOverlap = (b1, b2) => {\n // check if the bboxes overlap at all\n if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null;\n\n // find the middle two X values\n const lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;\n const upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x;\n\n // find the middle two Y values\n const lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;\n const upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y;\n\n // put those middle values together to get the overlap\n return {\n ll: {\n x: lowerX,\n y: lowerY\n },\n ur: {\n x: upperX,\n y: upperY\n }\n };\n};\n\n/* Javascript doesn't do integer math. Everything is\n * floating point with percision Number.EPSILON.\n *\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON\n */\n\nlet epsilon = Number.EPSILON;\n\n// IE Polyfill\nif (epsilon === undefined) epsilon = Math.pow(2, -52);\nconst EPSILON_SQ = epsilon * epsilon;\n\n/* FLP comparator */\nconst cmp = (a, b) => {\n // check if they're both 0\n if (-epsilon < a && a < epsilon) {\n if (-epsilon < b && b < epsilon) {\n return 0;\n }\n }\n\n // check if they're flp equal\n const ab = a - b;\n if (ab * ab < EPSILON_SQ * a * b) {\n return 0;\n }\n\n // normal comparison\n return a < b ? -1 : 1;\n};\n\n/**\n * This class rounds incoming values sufficiently so that\n * floating points problems are, for the most part, avoided.\n *\n * Incoming points are have their x & y values tested against\n * all previously seen x & y values. If either is 'too close'\n * to a previously seen value, it's value is 'snapped' to the\n * previously seen value.\n *\n * All points should be rounded by this class before being\n * stored in any data structures in the rest of this algorithm.\n */\n\nclass PtRounder {\n constructor() {\n this.reset();\n }\n reset() {\n this.xRounder = new CoordRounder();\n this.yRounder = new CoordRounder();\n }\n round(x, y) {\n return {\n x: this.xRounder.round(x),\n y: this.yRounder.round(y)\n };\n }\n}\nclass CoordRounder {\n constructor() {\n this.tree = new SplayTree();\n // preseed with 0 so we don't end up with values < Number.EPSILON\n this.round(0);\n }\n\n // Note: this can rounds input values backwards or forwards.\n // You might ask, why not restrict this to just rounding\n // forwards? Wouldn't that allow left endpoints to always\n // remain left endpoints during splitting (never change to\n // right). No - it wouldn't, because we snap intersections\n // to endpoints (to establish independence from the segment\n // angle for t-intersections).\n round(coord) {\n const node = this.tree.add(coord);\n const prevNode = this.tree.prev(node);\n if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {\n this.tree.remove(coord);\n return prevNode.key;\n }\n const nextNode = this.tree.next(node);\n if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {\n this.tree.remove(coord);\n return nextNode.key;\n }\n return coord;\n }\n}\n\n// singleton available by import\nconst rounder = new PtRounder();\n\n/* Cross Product of two vectors with first point at origin */\nconst crossProduct = (a, b) => a.x * b.y - a.y * b.x;\n\n/* Dot Product of two vectors with first point at origin */\nconst dotProduct = (a, b) => a.x * b.x + a.y * b.y;\n\n/* Comparator for two vectors with same starting point */\nconst compareVectorAngles = (basePt, endPt1, endPt2) => {\n const res = orient2d(basePt.x, basePt.y, endPt1.x, endPt1.y, endPt2.x, endPt2.y);\n if (res > 0) return -1;\n if (res < 0) return 1;\n return 0;\n};\nconst length = v => Math.sqrt(dotProduct(v, v));\n\n/* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */\nconst sineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = {\n x: pBase.x - pShared.x,\n y: pBase.y - pShared.y\n };\n const vAngle = {\n x: pAngle.x - pShared.x,\n y: pAngle.y - pShared.y\n };\n return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);\n};\n\n/* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */\nconst cosineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = {\n x: pBase.x - pShared.x,\n y: pBase.y - pShared.y\n };\n const vAngle = {\n x: pAngle.x - pShared.x,\n y: pAngle.y - pShared.y\n };\n return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);\n};\n\n/* Get the x coordinate where the given line (defined by a point and vector)\n * crosses the horizontal line with the given y coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst horizontalIntersection = (pt, v, y) => {\n if (v.y === 0) return null;\n return {\n x: pt.x + v.x / v.y * (y - pt.y),\n y: y\n };\n};\n\n/* Get the y coordinate where the given line (defined by a point and vector)\n * crosses the vertical line with the given x coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst verticalIntersection = (pt, v, x) => {\n if (v.x === 0) return null;\n return {\n x: x,\n y: pt.y + v.y / v.x * (x - pt.x)\n };\n};\n\n/* Get the intersection of two lines, each defined by a base point and a vector.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst intersection$1 = (pt1, v1, pt2, v2) => {\n // take some shortcuts for vertical and horizontal lines\n // this also ensures we don't calculate an intersection and then discover\n // it's actually outside the bounding box of the line\n if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);\n if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);\n if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);\n if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y);\n\n // General case for non-overlapping segments.\n // This algorithm is based on Schneider and Eberly.\n // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244\n\n const kross = crossProduct(v1, v2);\n if (kross == 0) return null;\n const ve = {\n x: pt2.x - pt1.x,\n y: pt2.y - pt1.y\n };\n const d1 = crossProduct(ve, v1) / kross;\n const d2 = crossProduct(ve, v2) / kross;\n\n // take the average of the two calculations to minimize rounding error\n const x1 = pt1.x + d2 * v1.x,\n x2 = pt2.x + d1 * v2.x;\n const y1 = pt1.y + d2 * v1.y,\n y2 = pt2.y + d1 * v2.y;\n const x = (x1 + x2) / 2;\n const y = (y1 + y2) / 2;\n return {\n x: x,\n y: y\n };\n};\n\nclass SweepEvent {\n // for ordering sweep events in the sweep event queue\n static compare(a, b) {\n // favor event with a point that the sweep line hits first\n const ptCmp = SweepEvent.comparePoints(a.point, b.point);\n if (ptCmp !== 0) return ptCmp;\n\n // the points are the same, so link them if needed\n if (a.point !== b.point) a.link(b);\n\n // favor right events over left\n if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1;\n\n // we have two matching left or right endpoints\n // ordering of this case is the same as for their segments\n return Segment.compare(a.segment, b.segment);\n }\n\n // for ordering points in sweep line order\n static comparePoints(aPt, bPt) {\n if (aPt.x < bPt.x) return -1;\n if (aPt.x > bPt.x) return 1;\n if (aPt.y < bPt.y) return -1;\n if (aPt.y > bPt.y) return 1;\n return 0;\n }\n\n // Warning: 'point' input will be modified and re-used (for performance)\n constructor(point, isLeft) {\n if (point.events === undefined) point.events = [this];else point.events.push(this);\n this.point = point;\n this.isLeft = isLeft;\n // this.segment, this.otherSE set by factory\n }\n link(other) {\n if (other.point === this.point) {\n throw new Error(\"Tried to link already linked events\");\n }\n const otherEvents = other.point.events;\n for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {\n const evt = otherEvents[i];\n this.point.events.push(evt);\n evt.point = this.point;\n }\n this.checkForConsuming();\n }\n\n /* Do a pass over our linked events and check to see if any pair\n * of segments match, and should be consumed. */\n checkForConsuming() {\n // FIXME: The loops in this method run O(n^2) => no good.\n // Maintain little ordered sweep event trees?\n // Can we maintaining an ordering that avoids the need\n // for the re-sorting with getLeftmostComparator in geom-out?\n\n // Compare each pair of events to see if other events also match\n const numEvents = this.point.events.length;\n for (let i = 0; i < numEvents; i++) {\n const evt1 = this.point.events[i];\n if (evt1.segment.consumedBy !== undefined) continue;\n for (let j = i + 1; j < numEvents; j++) {\n const evt2 = this.point.events[j];\n if (evt2.consumedBy !== undefined) continue;\n if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;\n evt1.segment.consume(evt2.segment);\n }\n }\n }\n getAvailableLinkedEvents() {\n // point.events is always of length 2 or greater\n const events = [];\n for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {\n const evt = this.point.events[i];\n if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {\n events.push(evt);\n }\n }\n return events;\n }\n\n /**\n * Returns a comparator function for sorting linked events that will\n * favor the event that will give us the smallest left-side angle.\n * All ring construction starts as low as possible heading to the right,\n * so by always turning left as sharp as possible we'll get polygons\n * without uncessary loops & holes.\n *\n * The comparator function has a compute cache such that it avoids\n * re-computing already-computed values.\n */\n getLeftmostComparator(baseEvent) {\n const cache = new Map();\n const fillCache = linkedEvent => {\n const nextEvent = linkedEvent.otherSE;\n cache.set(linkedEvent, {\n sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),\n cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point)\n });\n };\n return (a, b) => {\n if (!cache.has(a)) fillCache(a);\n if (!cache.has(b)) fillCache(b);\n const {\n sine: asine,\n cosine: acosine\n } = cache.get(a);\n const {\n sine: bsine,\n cosine: bcosine\n } = cache.get(b);\n\n // both on or above x-axis\n if (asine >= 0 && bsine >= 0) {\n if (acosine < bcosine) return 1;\n if (acosine > bcosine) return -1;\n return 0;\n }\n\n // both below x-axis\n if (asine < 0 && bsine < 0) {\n if (acosine < bcosine) return -1;\n if (acosine > bcosine) return 1;\n return 0;\n }\n\n // one above x-axis, one below\n if (bsine < asine) return -1;\n if (bsine > asine) return 1;\n return 0;\n };\n }\n}\n\n// Give segments unique ID's to get consistent sorting of\n// segments and sweep events when all else is identical\nlet segmentId = 0;\nclass Segment {\n /* This compare() function is for ordering segments in the sweep\n * line tree, and does so according to the following criteria:\n *\n * Consider the vertical line that lies an infinestimal step to the\n * right of the right-more of the two left endpoints of the input\n * segments. Imagine slowly moving a point up from negative infinity\n * in the increasing y direction. Which of the two segments will that\n * point intersect first? That segment comes 'before' the other one.\n *\n * If neither segment would be intersected by such a line, (if one\n * or more of the segments are vertical) then the line to be considered\n * is directly on the right-more of the two left inputs.\n */\n static compare(a, b) {\n const alx = a.leftSE.point.x;\n const blx = b.leftSE.point.x;\n const arx = a.rightSE.point.x;\n const brx = b.rightSE.point.x;\n\n // check if they're even in the same vertical plane\n if (brx < alx) return 1;\n if (arx < blx) return -1;\n const aly = a.leftSE.point.y;\n const bly = b.leftSE.point.y;\n const ary = a.rightSE.point.y;\n const bry = b.rightSE.point.y;\n\n // is left endpoint of segment B the right-more?\n if (alx < blx) {\n // are the two segments in the same horizontal plane?\n if (bly < aly && bly < ary) return 1;\n if (bly > aly && bly > ary) return -1;\n\n // is the B left endpoint colinear to segment A?\n const aCmpBLeft = a.comparePoint(b.leftSE.point);\n if (aCmpBLeft < 0) return 1;\n if (aCmpBLeft > 0) return -1;\n\n // is the A right endpoint colinear to segment B ?\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0) return bCmpARight;\n\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return -1;\n }\n\n // is left endpoint of segment A the right-more?\n if (alx > blx) {\n if (aly < bly && aly < bry) return -1;\n if (aly > bly && aly > bry) return 1;\n\n // is the A left endpoint colinear to segment B?\n const bCmpALeft = b.comparePoint(a.leftSE.point);\n if (bCmpALeft !== 0) return bCmpALeft;\n\n // is the B right endpoint colinear to segment A?\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0) return 1;\n if (aCmpBRight > 0) return -1;\n\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return 1;\n }\n\n // if we get here, the two left endpoints are in the same\n // vertical plane, ie alx === blx\n\n // consider the lower left-endpoint to come first\n if (aly < bly) return -1;\n if (aly > bly) return 1;\n\n // left endpoints are identical\n // check for colinearity by using the left-more right endpoint\n\n // is the A right endpoint more left-more?\n if (arx < brx) {\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0) return bCmpARight;\n }\n\n // is the B right endpoint more left-more?\n if (arx > brx) {\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0) return 1;\n if (aCmpBRight > 0) return -1;\n }\n if (arx !== brx) {\n // are these two [almost] vertical segments with opposite orientation?\n // if so, the one with the lower right endpoint comes first\n const ay = ary - aly;\n const ax = arx - alx;\n const by = bry - bly;\n const bx = brx - blx;\n if (ay > ax && by < bx) return 1;\n if (ay < ax && by > bx) return -1;\n }\n\n // we have colinear segments with matching orientation\n // consider the one with more left-more right endpoint to be first\n if (arx > brx) return 1;\n if (arx < brx) return -1;\n\n // if we get here, two two right endpoints are in the same\n // vertical plane, ie arx === brx\n\n // consider the lower right-endpoint to come first\n if (ary < bry) return -1;\n if (ary > bry) return 1;\n\n // right endpoints identical as well, so the segments are idential\n // fall back on creation order as consistent tie-breaker\n if (a.id < b.id) return -1;\n if (a.id > b.id) return 1;\n\n // identical segment, ie a === b\n return 0;\n }\n\n /* Warning: a reference to ringWindings input will be stored,\n * and possibly will be later modified */\n constructor(leftSE, rightSE, rings, windings) {\n this.id = ++segmentId;\n this.leftSE = leftSE;\n leftSE.segment = this;\n leftSE.otherSE = rightSE;\n this.rightSE = rightSE;\n rightSE.segment = this;\n rightSE.otherSE = leftSE;\n this.rings = rings;\n this.windings = windings;\n // left unset for performance, set later in algorithm\n // this.ringOut, this.consumedBy, this.prev\n }\n static fromRing(pt1, pt2, ring) {\n let leftPt, rightPt, winding;\n\n // ordering the two points according to sweep line ordering\n const cmpPts = SweepEvent.comparePoints(pt1, pt2);\n if (cmpPts < 0) {\n leftPt = pt1;\n rightPt = pt2;\n winding = 1;\n } else if (cmpPts > 0) {\n leftPt = pt2;\n rightPt = pt1;\n winding = -1;\n } else throw new Error(`Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`);\n const leftSE = new SweepEvent(leftPt, true);\n const rightSE = new SweepEvent(rightPt, false);\n return new Segment(leftSE, rightSE, [ring], [winding]);\n }\n\n /* When a segment is split, the rightSE is replaced with a new sweep event */\n replaceRightSE(newRightSE) {\n this.rightSE = newRightSE;\n this.rightSE.segment = this;\n this.rightSE.otherSE = this.leftSE;\n this.leftSE.otherSE = this.rightSE;\n }\n bbox() {\n const y1 = this.leftSE.point.y;\n const y2 = this.rightSE.point.y;\n return {\n ll: {\n x: this.leftSE.point.x,\n y: y1 < y2 ? y1 : y2\n },\n ur: {\n x: this.rightSE.point.x,\n y: y1 > y2 ? y1 : y2\n }\n };\n }\n\n /* A vector from the left point to the right */\n vector() {\n return {\n x: this.rightSE.point.x - this.leftSE.point.x,\n y: this.rightSE.point.y - this.leftSE.point.y\n };\n }\n isAnEndpoint(pt) {\n return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;\n }\n\n /* Compare this segment with a point.\n *\n * A point P is considered to be colinear to a segment if there\n * exists a distance D such that if we travel along the segment\n * from one * endpoint towards the other a distance D, we find\n * ourselves at point P.\n *\n * Return value indicates:\n *\n * 1: point lies above the segment (to the left of vertical)\n * 0: point is colinear to segment\n * -1: point lies below the segment (to the right of vertical)\n */\n comparePoint(point) {\n if (this.isAnEndpoint(point)) return 0;\n const lPt = this.leftSE.point;\n const rPt = this.rightSE.point;\n const v = this.vector();\n\n // Exactly vertical segments.\n if (lPt.x === rPt.x) {\n if (point.x === lPt.x) return 0;\n return point.x < lPt.x ? 1 : -1;\n }\n\n // Nearly vertical segments with an intersection.\n // Check to see where a point on the line with matching Y coordinate is.\n const yDist = (point.y - lPt.y) / v.y;\n const xFromYDist = lPt.x + yDist * v.x;\n if (point.x === xFromYDist) return 0;\n\n // General case.\n // Check to see where a point on the line with matching X coordinate is.\n const xDist = (point.x - lPt.x) / v.x;\n const yFromXDist = lPt.y + xDist * v.y;\n if (point.y === yFromXDist) return 0;\n return point.y < yFromXDist ? -1 : 1;\n }\n\n /**\n * Given another segment, returns the first non-trivial intersection\n * between the two segments (in terms of sweep line ordering), if it exists.\n *\n * A 'non-trivial' intersection is one that will cause one or both of the\n * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:\n *\n * * endpoint of segA with endpoint of segB --> trivial\n * * endpoint of segA with point along segB --> non-trivial\n * * endpoint of segB with point along segA --> non-trivial\n * * point along segA with point along segB --> non-trivial\n *\n * If no non-trivial intersection exists, return null\n * Else, return null.\n */\n getIntersection(other) {\n // If bboxes don't overlap, there can't be any intersections\n const tBbox = this.bbox();\n const oBbox = other.bbox();\n const bboxOverlap = getBboxOverlap(tBbox, oBbox);\n if (bboxOverlap === null) return null;\n\n // We first check to see if the endpoints can be considered intersections.\n // This will 'snap' intersections to endpoints if possible, and will\n // handle cases of colinearity.\n\n const tlp = this.leftSE.point;\n const trp = this.rightSE.point;\n const olp = other.leftSE.point;\n const orp = other.rightSE.point;\n\n // does each endpoint touch the other segment?\n // note that we restrict the 'touching' definition to only allow segments\n // to touch endpoints that lie forward from where we are in the sweep line pass\n const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;\n const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;\n const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;\n const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;\n\n // do left endpoints match?\n if (touchesThisLSE && touchesOtherLSE) {\n // these two cases are for colinear segments with matching left\n // endpoints, and one segment being longer than the other\n if (touchesThisRSE && !touchesOtherRSE) return trp;\n if (!touchesThisRSE && touchesOtherRSE) return orp;\n // either the two segments match exactly (two trival intersections)\n // or just on their left endpoint (one trivial intersection\n return null;\n }\n\n // does this left endpoint matches (other doesn't)\n if (touchesThisLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesOtherRSE) {\n if (tlp.x === orp.x && tlp.y === orp.y) return null;\n }\n // t-intersection on left endpoint\n return tlp;\n }\n\n // does other left endpoint matches (this doesn't)\n if (touchesOtherLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesThisRSE) {\n if (trp.x === olp.x && trp.y === olp.y) return null;\n }\n // t-intersection on left endpoint\n return olp;\n }\n\n // trivial intersection on right endpoints\n if (touchesThisRSE && touchesOtherRSE) return null;\n\n // t-intersections on just one right endpoint\n if (touchesThisRSE) return trp;\n if (touchesOtherRSE) return orp;\n\n // None of our endpoints intersect. Look for a general intersection between\n // infinite lines laid over the segments\n const pt = intersection$1(tlp, this.vector(), olp, other.vector());\n\n // are the segments parrallel? Note that if they were colinear with overlap,\n // they would have an endpoint intersection and that case was already handled above\n if (pt === null) return null;\n\n // is the intersection found between the lines not on the segments?\n if (!isInBbox(bboxOverlap, pt)) return null;\n\n // round the the computed point if needed\n return rounder.round(pt.x, pt.y);\n }\n\n /**\n * Split the given segment into multiple segments on the given points.\n * * Each existing segment will retain its leftSE and a new rightSE will be\n * generated for it.\n * * A new segment will be generated which will adopt the original segment's\n * rightSE, and a new leftSE will be generated for it.\n * * If there are more than two points given to split on, new segments\n * in the middle will be generated with new leftSE and rightSE's.\n * * An array of the newly generated SweepEvents will be returned.\n *\n * Warning: input array of points is modified\n */\n split(point) {\n const newEvents = [];\n const alreadyLinked = point.events !== undefined;\n const newLeftSE = new SweepEvent(point, true);\n const newRightSE = new SweepEvent(point, false);\n const oldRightSE = this.rightSE;\n this.replaceRightSE(newRightSE);\n newEvents.push(newRightSE);\n newEvents.push(newLeftSE);\n const newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice());\n\n // when splitting a nearly vertical downward-facing segment,\n // sometimes one of the resulting new segments is vertical, in which\n // case its left and right events may need to be swapped\n if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {\n newSeg.swapEvents();\n }\n if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {\n this.swapEvents();\n }\n\n // in the point we just used to create new sweep events with was already\n // linked to other events, we need to check if either of the affected\n // segments should be consumed\n if (alreadyLinked) {\n newLeftSE.checkForConsuming();\n newRightSE.checkForConsuming();\n }\n return newEvents;\n }\n\n /* Swap which event is left and right */\n swapEvents() {\n const tmpEvt = this.rightSE;\n this.rightSE = this.leftSE;\n this.leftSE = tmpEvt;\n this.leftSE.isLeft = true;\n this.rightSE.isLeft = false;\n for (let i = 0, iMax = this.windings.length; i < iMax; i++) {\n this.windings[i] *= -1;\n }\n }\n\n /* Consume another segment. We take their rings under our wing\n * and mark them as consumed. Use for perfectly overlapping segments */\n consume(other) {\n let consumer = this;\n let consumee = other;\n while (consumer.consumedBy) consumer = consumer.consumedBy;\n while (consumee.consumedBy) consumee = consumee.consumedBy;\n const cmp = Segment.compare(consumer, consumee);\n if (cmp === 0) return; // already consumed\n // the winner of the consumption is the earlier segment\n // according to sweep line ordering\n if (cmp > 0) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n\n // make sure a segment doesn't consume it's prev\n if (consumer.prev === consumee) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {\n const ring = consumee.rings[i];\n const winding = consumee.windings[i];\n const index = consumer.rings.indexOf(ring);\n if (index === -1) {\n consumer.rings.push(ring);\n consumer.windings.push(winding);\n } else consumer.windings[index] += winding;\n }\n consumee.rings = null;\n consumee.windings = null;\n consumee.consumedBy = consumer;\n\n // mark sweep events consumed as to maintain ordering in sweep event queue\n consumee.leftSE.consumedBy = consumer.leftSE;\n consumee.rightSE.consumedBy = consumer.rightSE;\n }\n\n /* The first segment previous segment chain that is in the result */\n prevInResult() {\n if (this._prevInResult !== undefined) return this._prevInResult;\n if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();\n return this._prevInResult;\n }\n beforeState() {\n if (this._beforeState !== undefined) return this._beforeState;\n if (!this.prev) this._beforeState = {\n rings: [],\n windings: [],\n multiPolys: []\n };else {\n const seg = this.prev.consumedBy || this.prev;\n this._beforeState = seg.afterState();\n }\n return this._beforeState;\n }\n afterState() {\n if (this._afterState !== undefined) return this._afterState;\n const beforeState = this.beforeState();\n this._afterState = {\n rings: beforeState.rings.slice(0),\n windings: beforeState.windings.slice(0),\n multiPolys: []\n };\n const ringsAfter = this._afterState.rings;\n const windingsAfter = this._afterState.windings;\n const mpsAfter = this._afterState.multiPolys;\n\n // calculate ringsAfter, windingsAfter\n for (let i = 0, iMax = this.rings.length; i < iMax; i++) {\n const ring = this.rings[i];\n const winding = this.windings[i];\n const index = ringsAfter.indexOf(ring);\n if (index === -1) {\n ringsAfter.push(ring);\n windingsAfter.push(winding);\n } else windingsAfter[index] += winding;\n }\n\n // calcualte polysAfter\n const polysAfter = [];\n const polysExclude = [];\n for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {\n if (windingsAfter[i] === 0) continue; // non-zero rule\n const ring = ringsAfter[i];\n const poly = ring.poly;\n if (polysExclude.indexOf(poly) !== -1) continue;\n if (ring.isExterior) polysAfter.push(poly);else {\n if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);\n const index = polysAfter.indexOf(ring.poly);\n if (index !== -1) polysAfter.splice(index, 1);\n }\n }\n\n // calculate multiPolysAfter\n for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {\n const mp = polysAfter[i].multiPoly;\n if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);\n }\n return this._afterState;\n }\n\n /* Is this segment part of the final result? */\n isInResult() {\n // if we've been consumed, we're not in the result\n if (this.consumedBy) return false;\n if (this._isInResult !== undefined) return this._isInResult;\n const mpsBefore = this.beforeState().multiPolys;\n const mpsAfter = this.afterState().multiPolys;\n switch (operation.type) {\n case \"union\":\n {\n // UNION - included iff:\n // * On one side of us there is 0 poly interiors AND\n // * On the other side there is 1 or more.\n const noBefores = mpsBefore.length === 0;\n const noAfters = mpsAfter.length === 0;\n this._isInResult = noBefores !== noAfters;\n break;\n }\n case \"intersection\":\n {\n // INTERSECTION - included iff:\n // * on one side of us all multipolys are rep. with poly interiors AND\n // * on the other side of us, not all multipolys are repsented\n // with poly interiors\n let least;\n let most;\n if (mpsBefore.length < mpsAfter.length) {\n least = mpsBefore.length;\n most = mpsAfter.length;\n } else {\n least = mpsAfter.length;\n most = mpsBefore.length;\n }\n this._isInResult = most === operation.numMultiPolys && least < most;\n break;\n }\n case \"xor\":\n {\n // XOR - included iff:\n // * the difference between the number of multipolys represented\n // with poly interiors on our two sides is an odd number\n const diff = Math.abs(mpsBefore.length - mpsAfter.length);\n this._isInResult = diff % 2 === 1;\n break;\n }\n case \"difference\":\n {\n // DIFFERENCE included iff:\n // * on exactly one side, we have just the subject\n const isJustSubject = mps => mps.length === 1 && mps[0].isSubject;\n this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);\n break;\n }\n default:\n throw new Error(`Unrecognized operation type found ${operation.type}`);\n }\n return this._isInResult;\n }\n}\n\nclass RingIn {\n constructor(geomRing, poly, isExterior) {\n if (!Array.isArray(geomRing) || geomRing.length === 0) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.poly = poly;\n this.isExterior = isExterior;\n this.segments = [];\n if (typeof geomRing[0][0] !== \"number\" || typeof geomRing[0][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n const firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);\n this.bbox = {\n ll: {\n x: firstPoint.x,\n y: firstPoint.y\n },\n ur: {\n x: firstPoint.x,\n y: firstPoint.y\n }\n };\n let prevPoint = firstPoint;\n for (let i = 1, iMax = geomRing.length; i < iMax; i++) {\n if (typeof geomRing[i][0] !== \"number\" || typeof geomRing[i][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n let point = rounder.round(geomRing[i][0], geomRing[i][1]);\n // skip repeated points\n if (point.x === prevPoint.x && point.y === prevPoint.y) continue;\n this.segments.push(Segment.fromRing(prevPoint, point, this));\n if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;\n if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y;\n if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;\n if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;\n prevPoint = point;\n }\n // add segment from last to first if last is not the same as first\n if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {\n this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));\n }\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.segments.length; i < iMax; i++) {\n const segment = this.segments[i];\n sweepEvents.push(segment.leftSE);\n sweepEvents.push(segment.rightSE);\n }\n return sweepEvents;\n }\n}\nclass PolyIn {\n constructor(geomPoly, multiPoly) {\n if (!Array.isArray(geomPoly)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.exteriorRing = new RingIn(geomPoly[0], this, true);\n // copy by value\n this.bbox = {\n ll: {\n x: this.exteriorRing.bbox.ll.x,\n y: this.exteriorRing.bbox.ll.y\n },\n ur: {\n x: this.exteriorRing.bbox.ur.x,\n y: this.exteriorRing.bbox.ur.y\n }\n };\n this.interiorRings = [];\n for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {\n const ring = new RingIn(geomPoly[i], this, false);\n if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;\n if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;\n if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;\n if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;\n this.interiorRings.push(ring);\n }\n this.multiPoly = multiPoly;\n }\n getSweepEvents() {\n const sweepEvents = this.exteriorRing.getSweepEvents();\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringSweepEvents = this.interiorRings[i].getSweepEvents();\n for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {\n sweepEvents.push(ringSweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\nclass MultiPolyIn {\n constructor(geom, isSubject) {\n if (!Array.isArray(geom)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n try {\n // if the input looks like a polygon, convert it to a multipolygon\n if (typeof geom[0][0][0] === \"number\") geom = [geom];\n } catch (ex) {\n // The input is either malformed or has empty arrays.\n // In either case, it will be handled later on.\n }\n this.polys = [];\n this.bbox = {\n ll: {\n x: Number.POSITIVE_INFINITY,\n y: Number.POSITIVE_INFINITY\n },\n ur: {\n x: Number.NEGATIVE_INFINITY,\n y: Number.NEGATIVE_INFINITY\n }\n };\n for (let i = 0, iMax = geom.length; i < iMax; i++) {\n const poly = new PolyIn(geom[i], this);\n if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;\n if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;\n if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;\n if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;\n this.polys.push(poly);\n }\n this.isSubject = isSubject;\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polySweepEvents = this.polys[i].getSweepEvents();\n for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {\n sweepEvents.push(polySweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\n\nclass RingOut {\n /* Given the segments from the sweep line pass, compute & return a series\n * of closed rings from all the segments marked to be part of the result */\n static factory(allSegments) {\n const ringsOut = [];\n for (let i = 0, iMax = allSegments.length; i < iMax; i++) {\n const segment = allSegments[i];\n if (!segment.isInResult() || segment.ringOut) continue;\n let prevEvent = null;\n let event = segment.leftSE;\n let nextEvent = segment.rightSE;\n const events = [event];\n const startingPoint = event.point;\n const intersectionLEs = [];\n\n /* Walk the chain of linked events to form a closed ring */\n while (true) {\n prevEvent = event;\n event = nextEvent;\n events.push(event);\n\n /* Is the ring complete? */\n if (event.point === startingPoint) break;\n while (true) {\n const availableLEs = event.getAvailableLinkedEvents();\n\n /* Did we hit a dead end? This shouldn't happen.\n * Indicates some earlier part of the algorithm malfunctioned. */\n if (availableLEs.length === 0) {\n const firstPt = events[0].point;\n const lastPt = events[events.length - 1].point;\n throw new Error(`Unable to complete output ring starting at [${firstPt.x},` + ` ${firstPt.y}]. Last matching segment found ends at` + ` [${lastPt.x}, ${lastPt.y}].`);\n }\n\n /* Only one way to go, so cotinue on the path */\n if (availableLEs.length === 1) {\n nextEvent = availableLEs[0].otherSE;\n break;\n }\n\n /* We must have an intersection. Check for a completed loop */\n let indexLE = null;\n for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {\n if (intersectionLEs[j].point === event.point) {\n indexLE = j;\n break;\n }\n }\n /* Found a completed loop. Cut that off and make a ring */\n if (indexLE !== null) {\n const intersectionLE = intersectionLEs.splice(indexLE)[0];\n const ringEvents = events.splice(intersectionLE.index);\n ringEvents.unshift(ringEvents[0].otherSE);\n ringsOut.push(new RingOut(ringEvents.reverse()));\n continue;\n }\n /* register the intersection */\n intersectionLEs.push({\n index: events.length,\n point: event.point\n });\n /* Choose the left-most option to continue the walk */\n const comparator = event.getLeftmostComparator(prevEvent);\n nextEvent = availableLEs.sort(comparator)[0].otherSE;\n break;\n }\n }\n ringsOut.push(new RingOut(events));\n }\n return ringsOut;\n }\n constructor(events) {\n this.events = events;\n for (let i = 0, iMax = events.length; i < iMax; i++) {\n events[i].segment.ringOut = this;\n }\n this.poly = null;\n }\n getGeom() {\n // Remove superfluous points (ie extra points along a straight line),\n let prevPt = this.events[0].point;\n const points = [prevPt];\n for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {\n const pt = this.events[i].point;\n const nextPt = this.events[i + 1].point;\n if (compareVectorAngles(pt, prevPt, nextPt) === 0) continue;\n points.push(pt);\n prevPt = pt;\n }\n\n // ring was all (within rounding error of angle calc) colinear points\n if (points.length === 1) return null;\n\n // check if the starting point is necessary\n const pt = points[0];\n const nextPt = points[1];\n if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();\n points.push(points[0]);\n const step = this.isExteriorRing() ? 1 : -1;\n const iStart = this.isExteriorRing() ? 0 : points.length - 1;\n const iEnd = this.isExteriorRing() ? points.length : -1;\n const orderedPoints = [];\n for (let i = iStart; i != iEnd; i += step) orderedPoints.push([points[i].x, points[i].y]);\n return orderedPoints;\n }\n isExteriorRing() {\n if (this._isExteriorRing === undefined) {\n const enclosing = this.enclosingRing();\n this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;\n }\n return this._isExteriorRing;\n }\n enclosingRing() {\n if (this._enclosingRing === undefined) {\n this._enclosingRing = this._calcEnclosingRing();\n }\n return this._enclosingRing;\n }\n\n /* Returns the ring that encloses this one, if any */\n _calcEnclosingRing() {\n // start with the ealier sweep line event so that the prevSeg\n // chain doesn't lead us inside of a loop of ours\n let leftMostEvt = this.events[0];\n for (let i = 1, iMax = this.events.length; i < iMax; i++) {\n const evt = this.events[i];\n if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;\n }\n let prevSeg = leftMostEvt.segment.prevInResult();\n let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n while (true) {\n // no segment found, thus no ring can enclose us\n if (!prevSeg) return null;\n\n // no segments below prev segment found, thus the ring of the prev\n // segment must loop back around and enclose us\n if (!prevPrevSeg) return prevSeg.ringOut;\n\n // if the two segments are of different rings, the ring of the prev\n // segment must either loop around us or the ring of the prev prev\n // seg, which would make us and the ring of the prev peers\n if (prevPrevSeg.ringOut !== prevSeg.ringOut) {\n if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {\n return prevSeg.ringOut;\n } else return prevSeg.ringOut.enclosingRing();\n }\n\n // two segments are from the same ring, so this was a penisula\n // of that ring. iterate downward, keep searching\n prevSeg = prevPrevSeg.prevInResult();\n prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n }\n }\n}\nclass PolyOut {\n constructor(exteriorRing) {\n this.exteriorRing = exteriorRing;\n exteriorRing.poly = this;\n this.interiorRings = [];\n }\n addInterior(ring) {\n this.interiorRings.push(ring);\n ring.poly = this;\n }\n getGeom() {\n const geom = [this.exteriorRing.getGeom()];\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (geom[0] === null) return null;\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringGeom = this.interiorRings[i].getGeom();\n // interior ring was all (within rounding error of angle calc) colinear points\n if (ringGeom === null) continue;\n geom.push(ringGeom);\n }\n return geom;\n }\n}\nclass MultiPolyOut {\n constructor(rings) {\n this.rings = rings;\n this.polys = this._composePolys(rings);\n }\n getGeom() {\n const geom = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polyGeom = this.polys[i].getGeom();\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (polyGeom === null) continue;\n geom.push(polyGeom);\n }\n return geom;\n }\n _composePolys(rings) {\n const polys = [];\n for (let i = 0, iMax = rings.length; i < iMax; i++) {\n const ring = rings[i];\n if (ring.poly) continue;\n if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {\n const enclosingRing = ring.enclosingRing();\n if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));\n enclosingRing.poly.addInterior(ring);\n }\n }\n return polys;\n }\n}\n\n/**\n * NOTE: We must be careful not to change any segments while\n * they are in the SplayTree. AFAIK, there's no way to tell\n * the tree to rebalance itself - thus before splitting\n * a segment that's in the tree, we remove it from the tree,\n * do the split, then re-insert it. (Even though splitting a\n * segment *shouldn't* change its correct position in the\n * sweep line tree, the reality is because of rounding errors,\n * it sometimes does.)\n */\n\nclass SweepLine {\n constructor(queue) {\n let comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;\n this.queue = queue;\n this.tree = new SplayTree(comparator);\n this.segments = [];\n }\n process(event) {\n const segment = event.segment;\n const newEvents = [];\n\n // if we've already been consumed by another segment,\n // clean up our body parts and get out\n if (event.consumedBy) {\n if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);\n return newEvents;\n }\n const node = event.isLeft ? this.tree.add(segment) : this.tree.find(segment);\n if (!node) throw new Error(`Unable to find segment #${segment.id} ` + `[${segment.leftSE.point.x}, ${segment.leftSE.point.y}] -> ` + `[${segment.rightSE.point.x}, ${segment.rightSE.point.y}] ` + \"in SweepLine tree.\");\n let prevNode = node;\n let nextNode = node;\n let prevSeg = undefined;\n let nextSeg = undefined;\n\n // skip consumed segments still in tree\n while (prevSeg === undefined) {\n prevNode = this.tree.prev(prevNode);\n if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;\n }\n\n // skip consumed segments still in tree\n while (nextSeg === undefined) {\n nextNode = this.tree.next(nextNode);\n if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;\n }\n if (event.isLeft) {\n // Check for intersections against the previous segment in the sweep line\n let prevMySplitter = null;\n if (prevSeg) {\n const prevInter = prevSeg.getIntersection(segment);\n if (prevInter !== null) {\n if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;\n if (!prevSeg.isAnEndpoint(prevInter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n\n // Check for intersections against the next segment in the sweep line\n let nextMySplitter = null;\n if (nextSeg) {\n const nextInter = nextSeg.getIntersection(segment);\n if (nextInter !== null) {\n if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;\n if (!nextSeg.isAnEndpoint(nextInter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n\n // For simplicity, even if we find more than one intersection we only\n // spilt on the 'earliest' (sweep-line style) of the intersections.\n // The other intersection will be handled in a future process().\n if (prevMySplitter !== null || nextMySplitter !== null) {\n let mySplitter = null;\n if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {\n const cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);\n mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;\n }\n\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n this.queue.remove(segment.rightSE);\n newEvents.push(segment.rightSE);\n const newEventsFromSplit = segment.split(mySplitter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (newEvents.length > 0) {\n // We found some intersections, so re-do the current event to\n // make sure sweep line ordering is totally consistent for later\n // use with the segment 'prev' pointers\n this.tree.remove(segment);\n newEvents.push(event);\n } else {\n // done with left event\n this.segments.push(segment);\n segment.prev = prevSeg;\n }\n } else {\n // event.isRight\n\n // since we're about to be removed from the sweep line, check for\n // intersections between our previous and next segments\n if (prevSeg && nextSeg) {\n const inter = prevSeg.getIntersection(nextSeg);\n if (inter !== null) {\n if (!prevSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (!nextSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n this.tree.remove(segment);\n }\n return newEvents;\n }\n\n /* Safely split a segment that is currently in the datastructures\n * IE - a segment other than the one that is currently being processed. */\n _splitSafely(seg, pt) {\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n // removeNode() doesn't work, so have re-find the seg\n // https://github.com/w8r/splay-tree/pull/5\n this.tree.remove(seg);\n const rightSE = seg.rightSE;\n this.queue.remove(rightSE);\n const newEvents = seg.split(pt);\n newEvents.push(rightSE);\n // splitting can trigger consumption\n if (seg.consumedBy === undefined) this.tree.add(seg);\n return newEvents;\n }\n}\n\n// Limits on iterative processes to prevent infinite loops - usually caused by floating-point math round-off errors.\nconst POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== \"undefined\" && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;\nconst POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== \"undefined\" && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;\nclass Operation {\n run(type, geom, moreGeoms) {\n operation.type = type;\n rounder.reset();\n\n /* Convert inputs to MultiPoly objects */\n const multipolys = [new MultiPolyIn(geom, true)];\n for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {\n multipolys.push(new MultiPolyIn(moreGeoms[i], false));\n }\n operation.numMultiPolys = multipolys.length;\n\n /* BBox optimization for difference operation\n * If the bbox of a multipolygon that's part of the clipping doesn't\n * intersect the bbox of the subject at all, we can just drop that\n * multiploygon. */\n if (operation.type === \"difference\") {\n // in place removal\n const subject = multipolys[0];\n let i = 1;\n while (i < multipolys.length) {\n if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null) i++;else multipolys.splice(i, 1);\n }\n }\n\n /* BBox optimization for intersection operation\n * If we can find any pair of multipolygons whose bbox does not overlap,\n * then the result will be empty. */\n if (operation.type === \"intersection\") {\n // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,\n // it could be optimized to O(n * ln(n))\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const mpA = multipolys[i];\n for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {\n if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];\n }\n }\n }\n\n /* Put segment endpoints in a priority queue */\n const queue = new SplayTree(SweepEvent.compare);\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const sweepEvents = multipolys[i].getSweepEvents();\n for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {\n queue.insert(sweepEvents[j]);\n if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when putting segment endpoints in a priority queue \" + \"(queue size too big).\");\n }\n }\n }\n\n /* Pass the sweep line over those endpoints */\n const sweepLine = new SweepLine(queue);\n let prevQueueSize = queue.size;\n let node = queue.pop();\n while (node) {\n const evt = node.key;\n if (queue.size === prevQueueSize) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n const seg = evt.segment;\n throw new Error(`Unable to pop() ${evt.isLeft ? \"left\" : \"right\"} SweepEvent ` + `[${evt.point.x}, ${evt.point.y}] from segment #${seg.id} ` + `[${seg.leftSE.point.x}, ${seg.leftSE.point.y}] -> ` + `[${seg.rightSE.point.x}, ${seg.rightSE.point.y}] from queue.`);\n }\n if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when passing sweep line over endpoints \" + \"(queue size too big).\");\n }\n if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when passing sweep line over endpoints \" + \"(too many sweep line segments).\");\n }\n const newEvents = sweepLine.process(evt);\n for (let i = 0, iMax = newEvents.length; i < iMax; i++) {\n const evt = newEvents[i];\n if (evt.consumedBy === undefined) queue.insert(evt);\n }\n prevQueueSize = queue.size;\n node = queue.pop();\n }\n\n // free some memory we don't need anymore\n rounder.reset();\n\n /* Collect and compile segments we're keeping into a multipolygon */\n const ringsOut = RingOut.factory(sweepLine.segments);\n const result = new MultiPolyOut(ringsOut);\n return result.getGeom();\n }\n}\n\n// singleton available by import\nconst operation = new Operation();\n\nconst union = function (geom) {\n for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n moreGeoms[_key - 1] = arguments[_key];\n }\n return operation.run(\"union\", geom, moreGeoms);\n};\nconst intersection = function (geom) {\n for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n moreGeoms[_key2 - 1] = arguments[_key2];\n }\n return operation.run(\"intersection\", geom, moreGeoms);\n};\nconst xor = function (geom) {\n for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n moreGeoms[_key3 - 1] = arguments[_key3];\n }\n return operation.run(\"xor\", geom, moreGeoms);\n};\nconst difference = function (subjectGeom) {\n for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n clippingGeoms[_key4 - 1] = arguments[_key4];\n }\n return operation.run(\"difference\", subjectGeom, clippingGeoms);\n};\nvar index = {\n union: union,\n intersection: intersection,\n xor: xor,\n difference: difference\n};\n\nexport { index as default };\n","import type { WsiRegionCoordinates } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiLinearRing = RoiCoordinate[];\nexport type RoiPolygonRings = RoiLinearRing[];\nexport type RoiMultiPolygon = RoiPolygonRings[];\nexport type RoiGeometry = RoiLinearRing | RoiPolygonRings | RoiMultiPolygon;\n\nexport function toRoiGeometry(coords: WsiRegionCoordinates | null | undefined): RoiGeometry | null | undefined;\nexport function toRoiGeometry(coords: unknown): RoiGeometry | null | undefined;\nexport function toRoiGeometry(coords: unknown): RoiGeometry | null | undefined {\n\tif (coords == null) return null;\n\tif (isLinearRing(coords) || isPolygonRings(coords) || isMultiPolygon(coords)) {\n\t\treturn coords;\n\t}\n\treturn null;\n}\n\nexport interface PreparedRoiPolygon {\n\touter: RoiLinearRing;\n\tholes: RoiLinearRing[];\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n\tarea: number;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is RoiCoordinate {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length >= 2 &&\n\t\tisFiniteNumber(value[0]) &&\n\t\tisFiniteNumber(value[1])\n\t);\n}\n\nfunction isLinearRing(value: unknown): value is RoiLinearRing {\n\treturn Array.isArray(value) && value.length > 0 && value.every(point => isCoordinatePair(point));\n}\n\nfunction isPolygonRings(value: unknown): value is RoiPolygonRings {\n\treturn Array.isArray(value) && value.length > 0 && value.every(ring => isLinearRing(ring));\n}\n\nfunction isMultiPolygon(value: unknown): value is RoiMultiPolygon {\n\treturn Array.isArray(value) && value.length > 0 && value.every(polygon => isPolygonRings(polygon));\n}\n\nexport function closeRoiRing(coordinates: readonly RoiCoordinate[]): RoiLinearRing {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out: RoiLinearRing = [];\n\tfor (const point of coordinates) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue;\n\t\tconst x = Number(point[0]);\n\t\tconst y = Number(point[1]);\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n\t\tconst prev = out[out.length - 1];\n\t\tif (prev && prev[0] === x && prev[1] === y) continue;\n\t\tout.push([x, y]);\n\t}\n\tif (out.length < 3) return [];\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out.length >= 4 ? out : [];\n}\n\nexport function polygonSignedArea(ring: RoiLinearRing): number {\n\tif (!Array.isArray(ring) || ring.length < 4) return 0;\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst a = ring[i];\n\t\tconst b = ring[i + 1];\n\t\tsum += a[0] * b[1] - b[0] * a[1];\n\t}\n\treturn sum * 0.5;\n}\n\nfunction normalizePolygonRings(rings: RoiPolygonRings): RoiPolygonRings {\n\tif (!Array.isArray(rings) || rings.length === 0) return [];\n\tconst normalized: RoiLinearRing[] = [];\n\tfor (const ring of rings) {\n\t\tconst closed = closeRoiRing(ring);\n\t\tif (closed.length >= 4) normalized.push(closed);\n\t}\n\tif (normalized.length === 0) return [];\n\tif (normalized.length === 1) return [normalized[0]];\n\n\tlet outerIndex = 0;\n\tlet outerArea = 0;\n\tfor (let i = 0; i < normalized.length; i += 1) {\n\t\tconst area = Math.abs(polygonSignedArea(normalized[i]));\n\t\tif (area <= outerArea) continue;\n\t\touterArea = area;\n\t\touterIndex = i;\n\t}\n\n\tconst out: RoiPolygonRings = [normalized[outerIndex]];\n\tfor (let i = 0; i < normalized.length; i += 1) {\n\t\tif (i === outerIndex) continue;\n\t\tout.push(normalized[i]);\n\t}\n\treturn out;\n}\n\nexport function normalizeRoiGeometry(geometry: RoiGeometry | null | undefined): RoiMultiPolygon {\n\tif (!Array.isArray(geometry) || geometry.length === 0) return [];\n\n\tconst first = geometry[0];\n\tif (isCoordinatePair(first)) {\n\t\tconst polygon = normalizePolygonRings([geometry as RoiLinearRing]);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (!Array.isArray(first) || first.length === 0) return [];\n\tconst second = first[0];\n\tif (isCoordinatePair(second)) {\n\t\tconst polygon = normalizePolygonRings(geometry as RoiPolygonRings);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (!Array.isArray(second) || second.length === 0 || !isCoordinatePair(second[0])) {\n\t\treturn [];\n\t}\n\n\tconst out: RoiMultiPolygon = [];\n\tfor (const polygon of geometry as RoiMultiPolygon) {\n\t\tconst normalized = normalizePolygonRings(polygon);\n\t\tif (normalized.length > 0) out.push(normalized);\n\t}\n\treturn out;\n}\n\nexport function pointInRing(x: number, y: number, ring: RoiLinearRing): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tif (yi === yj) continue;\n\t\tif ((yi > y) === (yj > y)) continue;\n\t\tconst intersect = x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nexport function pointInPolygonWithHoles(\n\tx: number,\n\ty: number,\n\tpolygon: RoiPolygonRings,\n): boolean {\n\tif (!Array.isArray(polygon) || polygon.length === 0) return false;\n\tconst outer = polygon[0];\n\tif (!outer || outer.length < 4) return false;\n\tif (!pointInRing(x, y, outer)) return false;\n\tfor (let i = 1; i < polygon.length; i += 1) {\n\t\tconst hole = polygon[i];\n\t\tif (!hole || hole.length < 4) continue;\n\t\tif (pointInRing(x, y, hole)) return false;\n\t}\n\treturn true;\n}\n\nexport function prepareRoiPolygons(\n\tgeometries: readonly (RoiGeometry | null | undefined)[] | null | undefined,\n): PreparedRoiPolygon[] {\n\tconst prepared: PreparedRoiPolygon[] = [];\n\tfor (const geometry of geometries ?? []) {\n\t\tconst multipolygon = normalizeRoiGeometry(geometry);\n\t\tfor (const polygon of multipolygon) {\n\t\t\tconst outer = polygon[0];\n\t\t\tif (!outer || outer.length < 4) continue;\n\t\t\tlet minX = Infinity;\n\t\t\tlet minY = Infinity;\n\t\t\tlet maxX = -Infinity;\n\t\t\tlet maxY = -Infinity;\n\t\t\tfor (const [x, y] of outer) {\n\t\t\t\tif (x < minX) minX = x;\n\t\t\t\tif (x > maxX) maxX = x;\n\t\t\t\tif (y < minY) minY = y;\n\t\t\t\tif (y > maxY) maxY = y;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!Number.isFinite(minX) ||\n\t\t\t\t!Number.isFinite(minY) ||\n\t\t\t\t!Number.isFinite(maxX) ||\n\t\t\t\t!Number.isFinite(maxY)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet area = Math.abs(polygonSignedArea(outer));\n\t\t\tfor (let i = 1; i < polygon.length; i += 1) {\n\t\t\t\tarea -= Math.abs(polygonSignedArea(polygon[i]));\n\t\t\t}\n\t\t\tprepared.push({\n\t\t\t\touter,\n\t\t\t\tholes: polygon.slice(1),\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\tarea: Math.max(1e-6, area),\n\t\t\t});\n\t\t}\n\t}\n\treturn prepared;\n}\n\nexport function pointInPreparedPolygon(\n\tx: number,\n\ty: number,\n\tpolygon: PreparedRoiPolygon,\n): boolean {\n\tif (x < polygon.minX || x > polygon.maxX || y < polygon.minY || y > polygon.maxY) {\n\t\treturn false;\n\t}\n\tif (!pointInRing(x, y, polygon.outer)) return false;\n\tfor (const hole of polygon.holes) {\n\t\tif (pointInRing(x, y, hole)) return false;\n\t}\n\treturn true;\n}\n\nexport function pointInAnyPreparedPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: readonly PreparedRoiPolygon[],\n): boolean {\n\tfor (const polygon of polygons) {\n\t\tif (!pointInPreparedPolygon(x, y, polygon)) continue;\n\t\treturn true;\n\t}\n\treturn false;\n}\n","export const DEFAULT_POINT_COLOR: [number, number, number, number] = [\n\t160, 160, 160, 255,\n];\n","import { DEFAULT_POINT_COLOR } from \"./constants\";\nimport type { ClassPalette, WsiPointData, WsiViewState } from \"./types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nexport function calcScaleResolution(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst z0 = Number(imageZoom);\n\tconst z1 = Number(currentZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 1;\n\tif (!Number.isFinite(z0) || !Number.isFinite(z1)) return mpp;\n\treturn Math.pow(2, z0 - z1) * mpp;\n}\n\nexport function calcViewingMagnification(\n\timageMpp: number,\n\tviewZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst zoom = Number(viewZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 0;\n\tif (!Number.isFinite(zoom) || zoom <= 0) return 0;\n\treturn zoom * (10 / mpp);\n}\n\nexport function calcScaleLength(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): string {\n\tconst resolution = calcScaleResolution(imageMpp, imageZoom, currentZoom);\n\tlet length = 100 * resolution;\n\tif (Number(imageMpp)) {\n\t\tlet unit = \"μm\";\n\t\tif (length > 1000) {\n\t\t\tlength /= 1000;\n\t\t\tunit = \"mm\";\n\t\t}\n\t\treturn `${length.toPrecision(3)} ${unit}`;\n\t}\n\treturn `${Math.round(length * 1000) / 1000} pixels`;\n}\n\nexport function nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nexport function sanitizePointCount(pointData: WsiPointData): number {\n\tconst fillModesLength =\n\t\tpointData.fillModes instanceof Uint8Array\n\t\t\t? pointData.fillModes.length\n\t\t\t: Number.MAX_SAFE_INTEGER;\n\treturn Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData.count ?? 0),\n\t\t\tMath.floor((pointData.positions?.length ?? 0) / 2),\n\t\t\tpointData.paletteIndices?.length ?? 0,\n\t\t\tfillModesLength,\n\t\t),\n\t);\n}\n\nexport function isSameViewState(\n\ta: Partial<WsiViewState> | null | undefined,\n\tb: Partial<WsiViewState> | null | undefined,\n): boolean {\n\tif (!a && !b) return true;\n\tif (!a || !b) return false;\n\treturn (\n\t\tMath.abs((a.zoom ?? 0) - (b.zoom ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetX ?? 0) - (b.offsetX ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetY ?? 0) - (b.offsetY ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.rotationDeg ?? 0) - (b.rotationDeg ?? 0)) < 1e-6\n\t);\n}\n\nexport function toBearerToken(value: string | null | undefined): string {\n\tconst trimmed = String(value ?? \"\").trim();\n\tif (!trimmed) return \"\";\n\tif (/^bearer\\s+/i.test(trimmed)) {\n\t\tconst token = trimmed.replace(/^bearer\\s+/i, \"\").trim();\n\t\treturn token ? `Bearer ${token}` : \"\";\n\t}\n\treturn `Bearer ${trimmed}`;\n}\n\nexport function hexToRgba(\n\thex: string | null | undefined,\n): [number, number, number, number] {\n\tconst value = String(hex ?? \"\").trim();\n\tconst match = value.match(/^#?([0-9a-fA-F]{6})$/);\n\tif (!match) return [...DEFAULT_POINT_COLOR];\n\n\tconst n = Number.parseInt(match[1], 16);\n\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n}\n\nexport function parseHexColorToRgba(\n\tvalue: string | null | undefined,\n\tfallback: [number, number, number, number],\n): [number, number, number, number] {\n\tconst input = String(value ?? \"\").trim();\n\tif (!input) return [...fallback];\n\n\tconst hexMatch = input.match(/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);\n\tif (hexMatch) {\n\t\tconst hex = hexMatch[1].length === 3 ? hexMatch[1].split(\"\").map(ch => ch + ch).join(\"\") : hexMatch[1];\n\t\tconst n = Number.parseInt(hex, 16);\n\t\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n\t}\n\n\treturn [...fallback];\n}\n\nfunction resolvePaletteClassKey(\n\titem:\n\t\t| { classId?: string | null; className?: string | null }\n\t\t| null\n\t\t| undefined,\n): string {\n\tconst classId = String(item?.classId ?? \"\").trim();\n\tif (classId) return classId;\n\treturn String(item?.className ?? \"\").trim();\n}\n\nexport function buildClassPalette(\n\tclasses:\n\t\t| Array<{ classId?: string | null; className?: string | null; classColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): ClassPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst classToPaletteIndex = new Map<string, number>();\n\n\tfor (const item of classes ?? []) {\n\t\tconst classKey = resolvePaletteClassKey(item);\n\t\tif (!classKey || classToPaletteIndex.has(classKey)) continue;\n\n\t\tclassToPaletteIndex.set(classKey, palette.length);\n\t\tpalette.push(hexToRgba(item?.classColor));\n\t}\n\n\tconst colors = new Uint8Array(palette.length * 4);\n\tfor (let i = 0; i < palette.length; i += 1) {\n\t\tcolors[i * 4] = palette[i][0];\n\t\tcolors[i * 4 + 1] = palette[i][1];\n\t\tcolors[i * 4 + 2] = palette[i][2];\n\t\tcolors[i * 4 + 3] = palette[i][3];\n\t}\n\n\treturn { colors, classToPaletteIndex };\n}\n","import polygonClipping from \"polygon-clipping\"\nimport { closeRoiRing as closeRing, polygonSignedArea } from \"./roi-geometry\"\nimport { clamp } from \"./utils\"\n\nexport type BrushStrokeCoordinate = [number, number]\nexport type BrushStrokeBounds = [number, number, number, number]\n\nexport interface BrushStrokePolygonOptions {\n\tradius: number\n\tclipBounds?: BrushStrokeBounds\n\tminRasterStep?: number\n\tmaxRasterPixels?: number\n\tmaxRasterSize?: number\n\tsimplifyTolerance?: number\n\tcircleSides?: number\n\tsmoothingPasses?: number\n}\n\nconst ROUND_PRECISIONS = [6, 4, 2] as const\nconst DEFAULT_CIRCLE_SIDES = 64\nconst DEFAULT_SIMPLIFY_FACTOR = 0.04\nconst DEFAULT_SMOOTHING_PASSES = 1\nconst MAX_SMOOTHING_PASSES = 4\nconst MIN_RADIUS = 1e-6\nconst MIN_TUNNEL_LENGTH_FACTOR = 0.1\n\nfunction sanitizePath(points: BrushStrokeCoordinate[]): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(points) || points.length === 0) return []\n\tconst out: BrushStrokeCoordinate[] = []\n\tfor (const point of points) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue\n\t\tconst x = Number(point[0])\n\t\tconst y = Number(point[1])\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue\n\t\tconst prev = out[out.length - 1]\n\t\tif (prev && Math.abs(prev[0] - x) < 1e-9 && Math.abs(prev[1] - y) < 1e-9) {\n\t\t\tcontinue\n\t\t}\n\t\tout.push([x, y])\n\t}\n\treturn out\n}\n\nfunction createCircleRing(center: BrushStrokeCoordinate, radius: number, sides: number): BrushStrokeCoordinate[] {\n\tif (radius <= MIN_RADIUS || sides < 8) return []\n\tconst ring: BrushStrokeCoordinate[] = []\n\tfor (let i = 0; i <= sides; i += 1) {\n\t\tconst t = (i / sides) * Math.PI * 2\n\t\tring.push([center[0] + Math.cos(t) * radius, center[1] + Math.sin(t) * radius])\n\t}\n\treturn closeRing(ring)\n}\n\nfunction createTunnelRing(\n\tstart: BrushStrokeCoordinate,\n\tend: BrushStrokeCoordinate,\n\tradius: number,\n\tminLength: number,\n): BrushStrokeCoordinate[] {\n\tconst dx = end[0] - start[0]\n\tconst dy = end[1] - start[1]\n\tconst length = Math.sqrt(dx * dx + dy * dy)\n\tif (!Number.isFinite(length) || length <= minLength) return []\n\n\tconst ux = dx / length\n\tconst uy = dy / length\n\tconst perpX = -uy\n\tconst perpY = ux\n\tconst r = Math.max(MIN_RADIUS, radius)\n\treturn closeRing([\n\t\t[start[0] + perpX * r, start[1] + perpY * r],\n\t\t[end[0] + perpX * r, end[1] + perpY * r],\n\t\t[end[0] - perpX * r, end[1] - perpY * r],\n\t\t[start[0] - perpX * r, start[1] - perpY * r],\n\t])\n}\n\nfunction createBoundsFallback(points: BrushStrokeCoordinate[], radius: number): BrushStrokeCoordinate[] {\n\tif (!points.length) return []\n\tlet minX = Infinity\n\tlet minY = Infinity\n\tlet maxX = -Infinity\n\tlet maxY = -Infinity\n\tfor (const [x, y] of points) {\n\t\tif (x < minX) minX = x\n\t\tif (x > maxX) maxX = x\n\t\tif (y < minY) minY = y\n\t\tif (y > maxY) maxY = y\n\t}\n\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) return []\n\tconst pad = Math.max(radius, 1)\n\treturn closeRing([\n\t\t[minX - pad, minY - pad],\n\t\t[maxX + pad, minY - pad],\n\t\t[maxX + pad, maxY + pad],\n\t\t[minX - pad, maxY + pad],\n\t])\n}\n\nfunction clampRingToBounds(\n\tring: BrushStrokeCoordinate[],\n\tbounds: BrushStrokeBounds | undefined,\n): BrushStrokeCoordinate[] {\n\tif (!bounds) return closeRing(ring)\n\treturn closeRing(\n\t\tring.map(([x, y]) => [\n\t\t\tclamp(x, bounds[0], bounds[2]),\n\t\t\tclamp(y, bounds[1], bounds[3]),\n\t\t] as BrushStrokeCoordinate),\n\t)\n}\n\nfunction round(value: number, precision: number): number {\n\tif (!Number.isFinite(value)) return value\n\treturn Number(value.toFixed(precision))\n}\n\nfunction sanitizeRing(ring: polygonClipping.Ring, precision: number): polygonClipping.Ring {\n\tif (!Array.isArray(ring) || ring.length === 0) return []\n\tconst sanitized: polygonClipping.Ring = []\n\tfor (const point of ring) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue\n\t\tconst x = round(Number(point[0]), precision)\n\t\tconst y = round(Number(point[1]), precision)\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue\n\t\tconst prev = sanitized[sanitized.length - 1]\n\t\tif (!prev || prev[0] !== x || prev[1] !== y) {\n\t\t\tsanitized.push([x, y])\n\t\t}\n\t}\n\n\tif (sanitized.length >= 2) {\n\t\tconst first = sanitized[0]\n\t\tconst last = sanitized[sanitized.length - 1]\n\t\tif (!first || !last) return []\n\t\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\t\tsanitized.push([first[0], first[1]])\n\t\t}\n\t}\n\n\treturn sanitized.length >= 4 ? sanitized : []\n}\n\nfunction sanitizePolygon(polygon: polygonClipping.Polygon, precision: number): polygonClipping.Polygon {\n\tif (!Array.isArray(polygon) || polygon.length === 0) return []\n\tconst rings = polygon\n\t\t.map(ring => sanitizeRing(ring, precision))\n\t\t.filter(ring => ring.length >= 4)\n\treturn rings.length > 0 ? rings : []\n}\n\nfunction tryUnionWithPrecision(\n\tpolygons: polygonClipping.Polygon[],\n\tprecision: number,\n): polygonClipping.MultiPolygon | null {\n\tconst sanitized = polygons\n\t\t.map(polygon => sanitizePolygon(polygon, precision))\n\t\t.filter(polygon => polygon.length > 0)\n\tif (sanitized.length === 0) return null\n\n\tlet current: polygonClipping.MultiPolygon = [sanitized[0]]\n\ttry {\n\t\tfor (let i = 1; i < sanitized.length; i += 1) {\n\t\t\tcurrent = polygonClipping.union(current, [sanitized[i]])\n\t\t\tif (!Array.isArray(current) || current.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\t/* biome-ignore lint/suspicious/noConsole: fallback logging for polygon union */\n\t\tconsole.error(\"buildBrushStrokePolygon union failed\", precision, error)\n\t\treturn null\n\t}\n\n\treturn current.length > 0 ? current : null\n}\n\nfunction unionPolygons(polygons: polygonClipping.Polygon[]): polygonClipping.MultiPolygon | null {\n\tif (polygons.length === 0) return null\n\tfor (const precision of ROUND_PRECISIONS) {\n\t\tconst result = tryUnionWithPrecision(polygons, precision)\n\t\tif (result) return result\n\t}\n\treturn null\n}\n\nfunction toBrushRing(ring: polygonClipping.Ring): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(ring) || ring.length === 0) return []\n\tconst out: BrushStrokeCoordinate[] = []\n\tfor (const point of ring) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue\n\t\tconst x = Number(point[0])\n\t\tconst y = Number(point[1])\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue\n\t\tout.push([x, y])\n\t}\n\treturn closeRing(out)\n}\n\nfunction selectLargestOuterRing(multiPolygon: polygonClipping.MultiPolygon): BrushStrokeCoordinate[] {\n\tlet best: BrushStrokeCoordinate[] = []\n\tlet bestArea = 0\n\tfor (const polygon of multiPolygon) {\n\t\tif (!Array.isArray(polygon) || polygon.length === 0) continue\n\t\tconst outer = toBrushRing(polygon[0] ?? [])\n\t\tif (outer.length < 4) continue\n\t\tconst area = Math.abs(polygonSignedArea(outer))\n\t\tif (area <= bestArea) continue\n\t\tbestArea = area\n\t\tbest = outer\n\t}\n\treturn best\n}\n\nfunction removeCollinearVertices(\n\tring: BrushStrokeCoordinate[],\n\tepsilon = 1e-9,\n): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring)\n\tif (closed.length < 5) return closed\n\tconst out: BrushStrokeCoordinate[] = [closed[0]]\n\tfor (let i = 1; i < closed.length - 1; i += 1) {\n\t\tconst prev = out[out.length - 1]\n\t\tconst curr = closed[i]\n\t\tconst next = closed[i + 1]\n\t\tconst cross =\n\t\t\t(curr[0] - prev[0]) * (next[1] - curr[1]) -\n\t\t\t(curr[1] - prev[1]) * (next[0] - curr[0])\n\t\tif (Math.abs(cross) <= epsilon) continue\n\t\tout.push(curr)\n\t}\n\tout.push(out[0])\n\treturn closeRing(out)\n}\n\nfunction pointLineDistanceSquared(\n\tp: BrushStrokeCoordinate,\n\ta: BrushStrokeCoordinate,\n\tb: BrushStrokeCoordinate,\n): number {\n\tconst abx = b[0] - a[0]\n\tconst aby = b[1] - a[1]\n\tconst len2 = abx * abx + aby * aby\n\tif (len2 <= 1e-12) {\n\t\tconst dx = p[0] - a[0]\n\t\tconst dy = p[1] - a[1]\n\t\treturn dx * dx + dy * dy\n\t}\n\tconst t = clamp(\n\t\t((p[0] - a[0]) * abx + (p[1] - a[1]) * aby) / len2,\n\t\t0,\n\t\t1,\n\t)\n\tconst x = a[0] + abx * t\n\tconst y = a[1] + aby * t\n\tconst dx = p[0] - x\n\tconst dy = p[1] - y\n\treturn dx * dx + dy * dy\n}\n\nfunction simplifyRdp(points: BrushStrokeCoordinate[], tolerance: number): BrushStrokeCoordinate[] {\n\tif (points.length <= 2 || tolerance <= 0) return points.slice()\n\n\tconst keep = new Uint8Array(points.length)\n\tkeep[0] = 1\n\tkeep[points.length - 1] = 1\n\tconst tolerance2 = tolerance * tolerance\n\tconst stack: Array<[number, number]> = [[0, points.length - 1]]\n\n\twhile (stack.length > 0) {\n\t\tconst next = stack.pop()\n\t\tif (!next) break\n\t\tconst [start, end] = next\n\t\tif (end - start <= 1) continue\n\n\t\tlet maxDist2 = 0\n\t\tlet split = -1\n\t\tfor (let i = start + 1; i < end; i += 1) {\n\t\t\tconst dist2 = pointLineDistanceSquared(points[i], points[start], points[end])\n\t\t\tif (dist2 > maxDist2) {\n\t\t\t\tmaxDist2 = dist2\n\t\t\t\tsplit = i\n\t\t\t}\n\t\t}\n\n\t\tif (split >= 0 && maxDist2 > tolerance2) {\n\t\t\tkeep[split] = 1\n\t\t\tstack.push([start, split], [split, end])\n\t\t}\n\t}\n\n\tconst out: BrushStrokeCoordinate[] = []\n\tfor (let i = 0; i < points.length; i += 1) {\n\t\tif (keep[i]) out.push(points[i])\n\t}\n\treturn out\n}\n\nfunction simplifyClosedRing(ring: BrushStrokeCoordinate[], tolerance: number): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring)\n\tif (closed.length < 5 || tolerance <= 0) return closed\n\tconst open = closed.slice(0, -1)\n\tconst simplified = simplifyRdp(open, tolerance)\n\tif (simplified.length < 3) return closed\n\treturn closeRing(simplified)\n}\n\nfunction smoothClosedRingChaikin(\n\tring: BrushStrokeCoordinate[],\n\titerations: number,\n): BrushStrokeCoordinate[] {\n\tlet out = closeRing(ring)\n\tif (iterations <= 0 || out.length < 5) return out\n\n\tfor (let pass = 0; pass < iterations; pass += 1) {\n\t\tconst open = out.slice(0, -1)\n\t\tif (open.length < 3) break\n\t\tconst next: BrushStrokeCoordinate[] = []\n\t\tfor (let i = 0; i < open.length; i += 1) {\n\t\t\tconst a = open[i]\n\t\t\tconst b = open[(i + 1) % open.length]\n\t\t\tnext.push(\n\t\t\t\t[a[0] * 0.75 + b[0] * 0.25, a[1] * 0.75 + b[1] * 0.25],\n\t\t\t\t[a[0] * 0.25 + b[0] * 0.75, a[1] * 0.25 + b[1] * 0.75],\n\t\t\t)\n\t\t}\n\t\tout = closeRing(next)\n\t}\n\treturn out\n}\n\nexport function buildBrushStrokePolygon(\n\tpath: BrushStrokeCoordinate[],\n\toptions: BrushStrokePolygonOptions,\n): BrushStrokeCoordinate[] {\n\tconst points = sanitizePath(path)\n\tconst radius = Math.max(MIN_RADIUS, Number(options.radius) || 0)\n\tif (points.length === 0 || !Number.isFinite(radius)) return []\n\n\tconst circleSides = Math.max(12, Math.floor(options.circleSides || DEFAULT_CIRCLE_SIDES))\n\tif (points.length === 1) {\n\t\treturn clampRingToBounds(createCircleRing(points[0], radius, circleSides), options.clipBounds)\n\t}\n\n\tconst polygons: polygonClipping.Polygon[] = []\n\tconst minTunnelLength = Math.max(MIN_RADIUS, radius * MIN_TUNNEL_LENGTH_FACTOR)\n\tfor (let i = 0; i < points.length; i += 1) {\n\t\tconst center = points[i]\n\t\tconst circle = createCircleRing(center, radius, circleSides)\n\t\tif (circle.length >= 4) {\n\t\t\tpolygons.push([circle])\n\t\t}\n\t\tif (i === 0) continue\n\t\tconst tunnel = createTunnelRing(points[i - 1], center, radius, minTunnelLength)\n\t\tif (tunnel.length >= 4) {\n\t\t\tpolygons.push([tunnel])\n\t\t}\n\t}\n\n\tconst unioned = unionPolygons(polygons)\n\tconst unionRing = unioned ? selectLargestOuterRing(unioned) : []\n\tif (!unionRing.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds)\n\t}\n\n\tconst tolerance =\n\t\ttypeof options.simplifyTolerance === \"number\" && Number.isFinite(options.simplifyTolerance)\n\t\t\t? Math.max(0, options.simplifyTolerance)\n\t\t\t: Math.max(0.25, radius * DEFAULT_SIMPLIFY_FACTOR)\n\tconst smoothingPasses =\n\t\ttypeof options.smoothingPasses === \"number\" && Number.isFinite(options.smoothingPasses)\n\t\t\t? Math.round(clamp(options.smoothingPasses, 0, MAX_SMOOTHING_PASSES))\n\t\t\t: DEFAULT_SMOOTHING_PASSES\n\n\tconst optimized = simplifyClosedRing(\n\t\tsmoothClosedRingChaikin(\n\t\t\tremoveCollinearVertices(unionRing, 1e-9),\n\t\t\tsmoothingPasses,\n\t\t),\n\t\ttolerance,\n\t)\n\n\tif (optimized.length < 4) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds)\n\t}\n\treturn clampRingToBounds(optimized, options.clipBounds)\n}\n","function readDevicePixelRatio(): number {\n if (typeof window === \"undefined\") return 1;\n const raw = window.devicePixelRatio || 1;\n return Number.isFinite(raw) && raw > 0 ? raw : 1;\n}\n\nexport interface DevicePixelRatioChangeEvent {\n previousDpr: number;\n nextDpr: number;\n trigger: \"match-media\" | \"window-resize\" | \"visual-viewport-resize\";\n}\n\nexport function observeDevicePixelRatioChanges(onChange: (event: DevicePixelRatioChangeEvent) => void): () => void {\n if (typeof window === \"undefined\") {\n return () => {\n // noop\n };\n }\n\n let active = true;\n let lastDpr = readDevicePixelRatio();\n let mediaQuery: MediaQueryList | null = null;\n let removeMediaQueryListener: (() => void) | null = null;\n\n const unbindMediaQuery = () => {\n removeMediaQueryListener?.();\n removeMediaQueryListener = null;\n mediaQuery = null;\n };\n\n const bindMediaQuery = () => {\n unbindMediaQuery();\n mediaQuery = window.matchMedia(`(resolution: ${lastDpr}dppx)`);\n const handleMediaQueryChange = () => {\n emitIfChanged(\"match-media\");\n };\n if (typeof mediaQuery.addEventListener === \"function\") {\n mediaQuery.addEventListener(\"change\", handleMediaQueryChange);\n removeMediaQueryListener = () => mediaQuery?.removeEventListener(\"change\", handleMediaQueryChange);\n return;\n }\n mediaQuery.addListener(handleMediaQueryChange);\n removeMediaQueryListener = () => mediaQuery?.removeListener(handleMediaQueryChange);\n };\n\n const emitIfChanged = (trigger: DevicePixelRatioChangeEvent[\"trigger\"]) => {\n if (!active) return;\n const nextDpr = readDevicePixelRatio();\n if (Math.abs(nextDpr - lastDpr) <= 1e-4) return;\n const previousDpr = lastDpr;\n lastDpr = nextDpr;\n bindMediaQuery();\n onChange({ previousDpr, nextDpr, trigger });\n };\n\n const handleWindowResize = () => emitIfChanged(\"window-resize\");\n const handleVisualViewportResize = () => emitIfChanged(\"visual-viewport-resize\");\n\n bindMediaQuery();\n window.addEventListener(\"resize\", handleWindowResize);\n window.visualViewport?.addEventListener(\"resize\", handleVisualViewportResize);\n\n return () => {\n active = false;\n unbindMediaQuery();\n window.removeEventListener(\"resize\", handleWindowResize);\n window.visualViewport?.removeEventListener(\"resize\", handleVisualViewportResize);\n };\n}\n","import type { CSSProperties, MutableRefObject, RefObject } from \"react\";\n\nexport type StampDrawTool =\n | \"stamp-rectangle\"\n | \"stamp-circle\"\n | \"stamp-rectangle-4096px\"\n | \"stamp-rectangle-2mm2\"\n | \"stamp-circle-2mm2\"\n | \"stamp-circle-hpf-0.2mm2\";\n\nexport type StampShape = \"rectangle\" | \"circle\";\n\nexport interface StampToolConfig {\n shape: StampShape;\n areaMm2?: number;\n pixelSize?: number;\n}\n\nexport type DrawTool =\n | \"cursor\"\n | \"freehand\"\n | \"rectangle\"\n | \"circular\"\n | \"brush\"\n | \"eraser\"\n | \"region-brush\"\n | \"region-eraser\"\n | StampDrawTool\n | { stamp: StampToolConfig };\n\nexport type DrawCoordinate = [number, number];\n\nexport type DrawBounds = [number, number, number, number];\nexport type DrawRegionCoordinates = DrawCoordinate[] | DrawCoordinate[][] | DrawCoordinate[][][];\n\nexport type DrawIntent = \"roi\" | \"patch\" | \"brush\";\n\nexport interface DrawResult {\n tool: Exclude<DrawTool, \"cursor\">;\n intent: DrawIntent;\n coordinates: DrawCoordinate[];\n bbox: DrawBounds;\n areaPx: number;\n}\n\nexport type PatchDrawResult = DrawResult & {\n tool: \"stamp-rectangle-4096px\";\n intent: \"patch\";\n};\n\nexport interface DrawRegion {\n id?: string | number;\n coordinates: DrawRegionCoordinates;\n label?: string;\n}\n\nexport interface RegionStyleContext {\n region: DrawRegion;\n regionId: string | number;\n regionIndex: number;\n state: \"default\" | \"hover\" | \"active\";\n}\n\nexport type RegionStrokeStyleResolver = (context: RegionStyleContext) => Partial<RegionStrokeStyle> | null | undefined;\n\nexport interface RegionLabelStyleContext {\n region: DrawRegion;\n regionId: string | number;\n regionIndex: number;\n zoom: number;\n}\n\nexport type RegionLabelStyleResolver = (context: RegionLabelStyleContext) => Partial<RegionLabelStyle> | null | undefined;\n\nexport type DrawOverlayCoordinates = DrawCoordinate[] | DrawCoordinate[][] | DrawCoordinate[][][];\n\nexport interface DrawOverlayShape {\n id?: string | number;\n coordinates: DrawOverlayCoordinates;\n closed?: boolean;\n fill?: boolean;\n stroke?: Partial<RegionStrokeStyle>;\n strokeStyle?: Partial<RegionStrokeStyle>;\n invertedFill?: DrawOverlayInvertedFillStyle;\n visible?: boolean;\n}\n\nexport interface DrawOverlayInvertedFillStyle {\n fillColor: string;\n}\n\nexport interface RegionStrokeStyle {\n color: string;\n width: number;\n lineDash: number[];\n lineJoin: CanvasLineJoin;\n lineCap: CanvasLineCap;\n shadowColor: string;\n shadowBlur: number;\n shadowOffsetX: number;\n shadowOffsetY: number;\n}\n\nexport interface RegionLabelStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: string | number;\n textColor: string;\n backgroundColor: string;\n borderColor: string;\n borderWidth: number;\n paddingX: number;\n paddingY: number;\n offsetY: number;\n borderRadius: number;\n}\n\nexport type RegionLabelAnchorMode = \"top-center\" | \"top-left\";\n\nexport interface DrawAreaTooltipStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: string | number;\n textColor: string;\n backgroundColor: string;\n borderRadius: number;\n paddingX: number;\n paddingY: number;\n}\n\nexport interface DrawAreaTooltipOptions {\n enabled?: boolean;\n format?: (areaMm2: number) => string;\n style?: Partial<DrawAreaTooltipStyle>;\n cursorOffset?: {\n x: number;\n y: number;\n };\n}\n\nexport interface DrawProjector {\n screenToWorld(clientX: number, clientY: number): DrawCoordinate | number[];\n worldToScreen(worldX: number, worldY: number): DrawCoordinate | number[];\n getViewState?: () => { zoom: number; rotationDeg?: number };\n getZoomRange?: () => { minZoom: number; maxZoom: number };\n getRegionLabelAutoLiftCapZoom?: () => number;\n handleWheelZoom?: (deltaY: number, screenX: number, screenY: number) => void;\n zoomBy?: (factor: number, screenX: number, screenY: number) => void;\n}\n\nexport interface StampOptions {\n rectangleAreaMm2?: number;\n circleAreaMm2?: number;\n rectanglePixelSize?: number;\n}\n\nexport interface BrushOptions {\n radius: number;\n edgeDetail?: number;\n edgeSmoothing?: number;\n clickSelectRoi?: boolean;\n fillColor?: string;\n fillOpacity?: number;\n cursorColor?: string;\n cursorActiveColor?: string;\n cursorLineWidth?: number;\n cursorLineDash?: number[];\n}\n\nexport interface DrawLayerProps {\n tool: DrawTool;\n imageWidth: number;\n imageHeight: number;\n imageMpp?: number;\n imageZoom?: number;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n projectorRef: RefObject<DrawProjector | null>;\n onBrushTap?: (coordinate: DrawCoordinate) => boolean;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n enabled?: boolean;\n viewStateSignal?: unknown;\n persistedRegions?: DrawRegion[];\n patchRegions?: DrawRegion[];\n persistedPolygons?: DrawRegionCoordinates[];\n drawFillColor?: string;\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n resolveRegionLabelStyle?: RegionLabelStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n regionLabelStyle?: Partial<RegionLabelStyle>;\n drawAreaTooltip?: DrawAreaTooltipOptions;\n autoLiftRegionLabelAtMaxZoom?: boolean;\n regionLabelAnchor?: RegionLabelAnchorMode;\n clampRegionLabelToViewport?: boolean;\n regionLabelAutoLiftOffsetPx?: number;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\nexport interface DrawSession {\n isDrawing: boolean;\n pointerId: number | null;\n start: DrawCoordinate | null;\n current: DrawCoordinate | null;\n cursor: DrawCoordinate | null;\n cursorScreen: DrawCoordinate | null;\n points: DrawCoordinate[];\n screenPoints: DrawCoordinate[];\n stampCenter: DrawCoordinate | null;\n}\n\nexport interface NormalizedDrawRegionPolygon {\n outer: DrawCoordinate[];\n holes: DrawCoordinate[][];\n}\n\nexport interface PreparedRenderedRegion {\n region: DrawRegion;\n regionIndex: number;\n regionKey: string | number;\n polygons: NormalizedDrawRegionPolygon[];\n}\n\nexport interface ResolvedBrushOptions {\n radius: number;\n edgeDetail: number;\n edgeSmoothing: number;\n clickSelectRoi: boolean;\n fillColor: string;\n fillOpacity: number;\n cursorColor: string;\n cursorActiveColor: string;\n cursorLineWidth: number;\n cursorLineDash: number[];\n}\n\nexport interface ResolvedDrawAreaTooltipOptions {\n enabled: boolean;\n format: (areaMm2: number) => string;\n style: DrawAreaTooltipStyle;\n cursorOffsetX: number;\n cursorOffsetY: number;\n}\n\nexport const EMPTY_DASH: number[] = [];\nexport const EMPTY_REGIONS: DrawRegion[] = [];\n\nexport const DEFAULT_REGION_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#ff4d4f\",\n width: 2,\n lineDash: EMPTY_DASH,\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nexport const DEFAULT_PATCH_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#4cc9f0\",\n width: 2,\n lineDash: [10, 8],\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nexport const REGION_INTERACTION_SHADOW_COLOR = \"rgba(23, 23, 25, 0.1)\";\nexport const REGION_INTERACTION_SHADOW_WIDTH = 6;\n\nexport const DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n fontFamily: \"Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: 11,\n fontWeight: 600,\n textColor: \"#171719\",\n backgroundColor: \"#FFCC00\",\n borderColor: \"rgba(0, 0, 0, 0)\",\n borderWidth: 0,\n paddingX: 8,\n paddingY: 4,\n offsetY: 10,\n borderRadius: 4,\n};\n\nexport const DEFAULT_DRAW_AREA_TOOLTIP_STYLE: DrawAreaTooltipStyle = {\n fontFamily: \"Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: 13,\n fontWeight: 500,\n textColor: \"#FFFFFF\",\n backgroundColor: \"rgba(23, 23, 25, 0.5)\",\n borderRadius: 4,\n paddingX: 6,\n paddingY: 3,\n};\n\nexport const DEFAULT_DRAW_AREA_TOOLTIP_OFFSET = {\n x: 16,\n y: -24,\n} as const;\n\nexport const REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX = 20;\nexport const REGION_LABEL_AUTO_LIFT_MAX_EPSILON = 1e-6;\n\nexport const DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nexport const DEFAULT_DRAW_PREVIEW_FILL = \"transparent\";\nexport const FREEHAND_MIN_POINTS = 3;\nexport const FREEHAND_SCREEN_STEP = 2;\nexport const CIRCLE_SIDES = 96;\nexport const MIN_AREA_PX = 1;\nexport const MICRONS_PER_MM = 1000;\nexport const DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nexport const DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nexport const DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE = 4096;\nexport const LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\nexport const WHEEL_ZOOM_IN_FACTOR = 1.12;\nexport const WHEEL_ZOOM_OUT_FACTOR = 0.89;\nexport const DEFAULT_BRUSH_RADIUS = 32;\nexport const DEFAULT_BRUSH_FILL_COLOR = \"#000000\";\nexport const DEFAULT_BRUSH_FILL_OPACITY = 0.1;\nexport const DEFAULT_BRUSH_CURSOR_COLOR = \"#FFCF00\";\nexport const DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR = \"#FF0000\";\nexport const DEFAULT_BRUSH_CURSOR_LINE_WIDTH = 1.5;\nexport const DEFAULT_BRUSH_CURSOR_DASH = [2, 2];\nexport const DEFAULT_BRUSH_EDGE_DETAIL = 1;\nexport const MIN_BRUSH_EDGE_DETAIL = 0.25;\nexport const MAX_BRUSH_EDGE_DETAIL = 4;\nexport const DEFAULT_BRUSH_EDGE_SMOOTHING = 1;\nexport const MIN_BRUSH_EDGE_SMOOTHING = 0;\nexport const MAX_BRUSH_EDGE_SMOOTHING = 4;\nexport const MIN_BRUSH_RASTER_STEP = 0.05;\nexport const BRUSH_RASTER_DIAMETER_SAMPLES = 256;\nexport const BRUSH_SCREEN_STEP = 1.5;\n","import { closeRoiRing, normalizeRoiGeometry, polygonSignedArea, toRoiGeometry } from \"../wsi/roi-geometry\";\nimport { clamp } from \"../wsi/utils\";\nimport type { DrawCoordinate, DrawOverlayCoordinates, DrawRegionCoordinates, NormalizedDrawRegionPolygon, RegionStrokeStyle } from \"./draw-layer-types\";\nimport { CIRCLE_SIDES, DEFAULT_REGION_STROKE_STYLE, type DrawBounds, EMPTY_DASH } from \"./draw-layer-types\";\n\nexport { clamp };\n\nexport function clampWorld(coord: DrawCoordinate, imageWidth: number, imageHeight: number): DrawCoordinate {\n return [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nexport function toDrawCoordinate(value: unknown): DrawCoordinate | null {\n if (!Array.isArray(value) || value.length < 2) return null;\n const x = Number(value[0]);\n const y = Number(value[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n}\n\nexport const toCoord = toDrawCoordinate;\n\nexport function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n return closeRoiRing(coords) as DrawCoordinate[];\n}\n\nexport function polygonArea(coords: DrawCoordinate[]): number {\n return Math.abs(polygonSignedArea(closeRing(coords)));\n}\n\nexport function computeBounds(coords: DrawCoordinate[]): DrawBounds {\n if (!Array.isArray(coords) || coords.length === 0) return [0, 0, 0, 0];\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of coords) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n return [minX, minY, maxX, maxY];\n}\n\nexport function tracePath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], close = false): void {\n if (points.length === 0) return;\n\n ctx.moveTo(points[0][0], points[0][1]);\n for (let i = 1; i < points.length; i += 1) {\n ctx.lineTo(points[i][0], points[i][1]);\n }\n\n if (close) {\n ctx.closePath();\n }\n}\n\nexport function drawPath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], strokeStyle: RegionStrokeStyle, close = false, fill = false, fillColor = \"rgba(255, 77, 79, 0.16)\"): void {\n if (points.length === 0) return;\n\n ctx.beginPath();\n tracePath(ctx, points, close);\n if (fill && close) {\n ctx.fillStyle = fillColor;\n ctx.fill();\n }\n\n ctx.strokeStyle = strokeStyle.color;\n ctx.lineWidth = strokeStyle.width;\n ctx.lineJoin = strokeStyle.lineJoin;\n ctx.lineCap = strokeStyle.lineCap;\n ctx.shadowColor = strokeStyle.shadowColor;\n ctx.shadowBlur = strokeStyle.shadowBlur;\n ctx.shadowOffsetX = strokeStyle.shadowOffsetX;\n ctx.shadowOffsetY = strokeStyle.shadowOffsetY;\n ctx.setLineDash(strokeStyle.lineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.shadowColor = \"rgba(0, 0, 0, 0)\";\n ctx.shadowBlur = 0;\n ctx.shadowOffsetX = 0;\n ctx.shadowOffsetY = 0;\n}\n\nexport function resolveStrokeStyle(style: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n const dash = Array.isArray(style?.lineDash) ? style.lineDash.filter(value => Number.isFinite(value) && value >= 0) : EMPTY_DASH;\n const width = typeof style?.width === \"number\" && Number.isFinite(style.width) ? Math.max(0, style.width) : DEFAULT_REGION_STROKE_STYLE.width;\n const shadowBlur = typeof style?.shadowBlur === \"number\" && Number.isFinite(style.shadowBlur) ? Math.max(0, style.shadowBlur) : DEFAULT_REGION_STROKE_STYLE.shadowBlur;\n const shadowOffsetX = typeof style?.shadowOffsetX === \"number\" && Number.isFinite(style.shadowOffsetX) ? style.shadowOffsetX : DEFAULT_REGION_STROKE_STYLE.shadowOffsetX;\n const shadowOffsetY = typeof style?.shadowOffsetY === \"number\" && Number.isFinite(style.shadowOffsetY) ? style.shadowOffsetY : DEFAULT_REGION_STROKE_STYLE.shadowOffsetY;\n return {\n color: style?.color || DEFAULT_REGION_STROKE_STYLE.color,\n width,\n lineDash: dash.length ? dash : EMPTY_DASH,\n lineJoin: style?.lineJoin || DEFAULT_REGION_STROKE_STYLE.lineJoin,\n lineCap: style?.lineCap || DEFAULT_REGION_STROKE_STYLE.lineCap,\n shadowColor: style?.shadowColor || DEFAULT_REGION_STROKE_STYLE.shadowColor,\n shadowBlur,\n shadowOffsetX,\n shadowOffsetY,\n };\n}\n\nexport function mergeStrokeStyle(base: RegionStrokeStyle, override: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n if (!override) return base;\n return resolveStrokeStyle({\n color: override.color ?? base.color,\n width: override.width ?? base.width,\n lineDash: override.lineDash ?? base.lineDash,\n lineJoin: override.lineJoin ?? base.lineJoin,\n lineCap: override.lineCap ?? base.lineCap,\n shadowColor: override.shadowColor ?? base.shadowColor,\n shadowBlur: override.shadowBlur ?? base.shadowBlur,\n shadowOffsetX: override.shadowOffsetX ?? base.shadowOffsetX,\n shadowOffsetY: override.shadowOffsetY ?? base.shadowOffsetY,\n });\n}\n\nexport function isSameRegionId(a: string | number | null | undefined, b: string | number | null | undefined): boolean {\n if (a === null || a === undefined || b === null || b === undefined) {\n return false;\n }\n return String(a) === String(b);\n}\n\nexport function isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nexport function isCoordinatePair(value: unknown): value is [number, number] {\n return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);\n}\n\nexport function isCoordinateRing(value: unknown): value is DrawCoordinate[] {\n return Array.isArray(value) && value.length >= 2 && value.every(point => isCoordinatePair(point));\n}\n\nfunction collectOverlayRings(value: unknown, out: DrawCoordinate[][]): void {\n if (!Array.isArray(value) || value.length === 0) return;\n if (isCoordinateRing(value)) {\n out.push(value.map(([x, y]) => [x, y] as DrawCoordinate));\n return;\n }\n for (const item of value) {\n collectOverlayRings(item, out);\n }\n}\n\nexport function normalizeOverlayRings(coordinates: DrawOverlayCoordinates, close: boolean): DrawCoordinate[][] {\n const sourceRings: DrawCoordinate[][] = [];\n collectOverlayRings(coordinates, sourceRings);\n const out: DrawCoordinate[][] = [];\n for (const ring of sourceRings) {\n if (ring.length < 2) continue;\n const normalized = close ? closeRing(ring) : ring;\n if (normalized.length >= (close ? 4 : 2)) {\n out.push(normalized);\n }\n }\n return out;\n}\n\nexport function clampPositiveOrFallback(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n return fallback;\n }\n return value;\n}\n\nexport function clampUnitOpacity(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n return clamp(value, 0, 1);\n}\n\nexport function drawRoundedRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number): void {\n const r = Math.max(0, Math.min(radius, width * 0.5, height * 0.5));\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + r);\n ctx.lineTo(x + width, y + height - r);\n ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n ctx.lineTo(x + r, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n}\n\nexport function isNestedRingCoordinates(coordinates: DrawOverlayCoordinates): boolean {\n const first = coordinates[0];\n return Array.isArray(first) && Array.isArray(first[0]);\n}\n\nexport function createRectangle(\n start: DrawCoordinate | null,\n end: DrawCoordinate | null,\n projection?: {\n worldToScreen: (x: number, y: number) => DrawCoordinate | null;\n screenToWorld: (screen: DrawCoordinate) => DrawCoordinate | null;\n }\n): DrawCoordinate[] {\n if (!start || !end) return [];\n\n if (projection) {\n const startScreen = projection.worldToScreen(start[0], start[1]);\n const endScreen = projection.worldToScreen(end[0], end[1]);\n\n if (startScreen && endScreen) {\n const screenCorners: DrawCoordinate[] = [\n [startScreen[0], startScreen[1]],\n [endScreen[0], startScreen[1]],\n [endScreen[0], endScreen[1]],\n [startScreen[0], endScreen[1]],\n ];\n const worldCorners: DrawCoordinate[] = [];\n for (const corner of screenCorners) {\n const world = projection.screenToWorld(corner);\n if (!world) return createRectangle(start, end);\n worldCorners.push(world);\n }\n return closeRing(worldCorners);\n }\n }\n\n return closeRing([\n [start[0], start[1]],\n [end[0], start[1]],\n [end[0], end[1]],\n [start[0], end[1]],\n ]);\n}\n\nexport function createCircle(start: DrawCoordinate | null, end: DrawCoordinate | null, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!start || !end) return [];\n\n const centerX = (start[0] + end[0]) * 0.5;\n const centerY = (start[1] + end[1]) * 0.5;\n const radius = Math.hypot(end[0] - start[0], end[1] - start[1]) * 0.5;\n if (radius < 1) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([centerX + Math.cos(t) * radius, centerY + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nexport function normalizeDrawRegionPolygons(coordinates: DrawRegionCoordinates): NormalizedDrawRegionPolygon[] {\n const multipolygon = normalizeRoiGeometry(toRoiGeometry(coordinates));\n if (multipolygon.length === 0) return [];\n\n const out: NormalizedDrawRegionPolygon[] = [];\n for (const polygon of multipolygon) {\n const outer = polygon[0];\n if (!outer || outer.length < 4) continue;\n const normalizedOuter = outer.map(([x, y]) => [x, y] as DrawCoordinate);\n const holes: DrawCoordinate[][] = [];\n for (let i = 1; i < polygon.length; i += 1) {\n const hole = polygon[i];\n if (!hole || hole.length < 4) continue;\n holes.push(hole.map(([x, y]) => [x, y] as DrawCoordinate));\n }\n out.push({\n outer: normalizedOuter,\n holes,\n });\n }\n return out;\n}\n","import type { BrushOptions, DrawCoordinate, DrawProjector, DrawSession, ResolvedBrushOptions } from \"./draw-layer-types\";\nimport {\n DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR,\n DEFAULT_BRUSH_CURSOR_COLOR,\n DEFAULT_BRUSH_CURSOR_DASH,\n DEFAULT_BRUSH_CURSOR_LINE_WIDTH,\n DEFAULT_BRUSH_EDGE_DETAIL,\n DEFAULT_BRUSH_EDGE_SMOOTHING,\n DEFAULT_BRUSH_FILL_COLOR,\n DEFAULT_BRUSH_FILL_OPACITY,\n DEFAULT_BRUSH_RADIUS,\n EMPTY_DASH,\n MAX_BRUSH_EDGE_DETAIL,\n MAX_BRUSH_EDGE_SMOOTHING,\n MIN_BRUSH_EDGE_DETAIL,\n MIN_BRUSH_EDGE_SMOOTHING,\n} from \"./draw-layer-types\";\nimport { clamp, clampPositiveOrFallback, clampUnitOpacity, toCoord } from \"./draw-layer-utils\";\n\nexport type { BrushOptions, ResolvedBrushOptions };\n\nexport function sanitizeBrushLineDash(value: number[] | undefined): number[] {\n if (!Array.isArray(value)) return DEFAULT_BRUSH_CURSOR_DASH;\n const out = value.filter(item => Number.isFinite(item) && item >= 0);\n return out.length > 0 ? out : DEFAULT_BRUSH_CURSOR_DASH;\n}\n\nexport function resolveBrushEdgeDetail(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_BRUSH_EDGE_DETAIL;\n return clamp(value, MIN_BRUSH_EDGE_DETAIL, MAX_BRUSH_EDGE_DETAIL);\n}\n\nexport function resolveBrushEdgeSmoothing(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_BRUSH_EDGE_SMOOTHING;\n return Math.round(clamp(value, MIN_BRUSH_EDGE_SMOOTHING, MAX_BRUSH_EDGE_SMOOTHING));\n}\n\nexport function resolveBrushOptions(options: BrushOptions | undefined): ResolvedBrushOptions {\n const radius = clampPositiveOrFallback(options?.radius, DEFAULT_BRUSH_RADIUS);\n const cursorLineWidth = clampPositiveOrFallback(options?.cursorLineWidth, DEFAULT_BRUSH_CURSOR_LINE_WIDTH);\n const edgeDetail = resolveBrushEdgeDetail(options?.edgeDetail);\n const edgeSmoothing = resolveBrushEdgeSmoothing(options?.edgeSmoothing);\n return {\n radius,\n edgeDetail,\n edgeSmoothing,\n clickSelectRoi: options?.clickSelectRoi === true,\n fillColor: options?.fillColor || DEFAULT_BRUSH_FILL_COLOR,\n fillOpacity: clampUnitOpacity(options?.fillOpacity, DEFAULT_BRUSH_FILL_OPACITY),\n cursorColor: options?.cursorColor || DEFAULT_BRUSH_CURSOR_COLOR,\n cursorActiveColor: options?.cursorActiveColor || DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR,\n cursorLineWidth,\n cursorLineDash: sanitizeBrushLineDash(options?.cursorLineDash),\n };\n}\n\nexport function drawBrushStrokePreview(ctx: CanvasRenderingContext2D, session: DrawSession, resolvedBrushOptions: ResolvedBrushOptions): void {\n if (!session.isDrawing || session.screenPoints.length === 0) return;\n const screenPoints = session.screenPoints;\n if (screenPoints.length === 0) return;\n const radiusPx = resolvedBrushOptions.radius;\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.globalAlpha = resolvedBrushOptions.fillOpacity;\n ctx.fillStyle = resolvedBrushOptions.fillColor;\n ctx.strokeStyle = resolvedBrushOptions.fillColor;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.lineWidth = radiusPx * 2;\n if (screenPoints.length === 1) {\n ctx.beginPath();\n ctx.arc(screenPoints[0][0], screenPoints[0][1], radiusPx, 0, Math.PI * 2);\n ctx.fill();\n } else {\n ctx.beginPath();\n ctx.moveTo(screenPoints[0][0], screenPoints[0][1]);\n for (let i = 1; i < screenPoints.length; i += 1) {\n ctx.lineTo(screenPoints[i][0], screenPoints[i][1]);\n }\n ctx.stroke();\n }\n ctx.restore();\n}\n\nexport function drawBrushCursor(ctx: CanvasRenderingContext2D, session: DrawSession, projector: DrawProjector | null, resolvedBrushOptions: ResolvedBrushOptions): void {\n const cursor = session.cursor;\n if (!cursor) return;\n const screen = session.cursorScreen ?? toCoord(projector?.worldToScreen(cursor[0], cursor[1]) ?? []);\n if (!screen) return;\n const radiusPx = resolvedBrushOptions.radius;\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.beginPath();\n ctx.arc(screen[0], screen[1], radiusPx, 0, Math.PI * 2);\n ctx.strokeStyle = session.isDrawing ? resolvedBrushOptions.cursorActiveColor : resolvedBrushOptions.cursorColor;\n ctx.lineWidth = resolvedBrushOptions.cursorLineWidth;\n ctx.setLineDash(resolvedBrushOptions.cursorLineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.restore();\n}\n","import type { DrawAreaTooltipOptions, DrawAreaTooltipStyle, DrawCoordinate, RegionLabelAnchorMode, RegionLabelStyle, ResolvedDrawAreaTooltipOptions } from \"./draw-layer-types\";\nimport {\n DEFAULT_DRAW_AREA_TOOLTIP_OFFSET,\n DEFAULT_DRAW_AREA_TOOLTIP_STYLE,\n DEFAULT_REGION_LABEL_STYLE,\n REGION_LABEL_AUTO_LIFT_MAX_EPSILON,\n REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX,\n} from \"./draw-layer-types\";\nimport { clamp, drawRoundedRect } from \"./draw-layer-utils\";\n\nconst LABEL_MEASURE_FALLBACK_EM = 0.58;\nconst LABEL_MEASURE_CACHE_LIMIT = 4096;\nconst TOP_ANCHOR_Y_TOLERANCE = 0.5;\n\nlet sharedLabelMeasureContext: CanvasRenderingContext2D | null = null;\nconst labelTextWidthCache = new Map<string, number>();\n\nfunction getLabelMeasureContext(): CanvasRenderingContext2D | null {\n if (sharedLabelMeasureContext) return sharedLabelMeasureContext;\n if (typeof document === \"undefined\") return null;\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return null;\n sharedLabelMeasureContext = ctx;\n return sharedLabelMeasureContext;\n}\n\nexport function measureLabelTextWidth(label: string, labelStyle: { fontFamily: string; fontSize: number; fontWeight: string | number }): number {\n const key = `${labelStyle.fontWeight}|${labelStyle.fontSize}|${labelStyle.fontFamily}|${label}`;\n const cached = labelTextWidthCache.get(key);\n if (cached !== undefined) return cached;\n\n const fallback = label.length * labelStyle.fontSize * LABEL_MEASURE_FALLBACK_EM;\n const ctx = getLabelMeasureContext();\n let width = fallback;\n if (ctx) {\n ctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n const measured = ctx.measureText(label).width;\n if (Number.isFinite(measured) && measured >= 0) {\n width = measured;\n }\n }\n\n if (labelTextWidthCache.size > LABEL_MEASURE_CACHE_LIMIT) {\n labelTextWidthCache.clear();\n }\n labelTextWidthCache.set(key, width);\n return width;\n}\n\nexport function getTopAnchor(coords: DrawCoordinate[], anchorMode: RegionLabelAnchorMode = \"top-center\"): DrawCoordinate | null {\n if (!coords.length) return null;\n\n let minY = Infinity;\n for (const point of coords) {\n if (point[1] < minY) minY = point[1];\n }\n if (!Number.isFinite(minY)) return null;\n\n let minX = Infinity;\n let maxX = -Infinity;\n for (const point of coords) {\n if (Math.abs(point[1] - minY) > TOP_ANCHOR_Y_TOLERANCE) continue;\n if (point[0] < minX) minX = point[0];\n if (point[0] > maxX) maxX = point[0];\n }\n\n if (!Number.isFinite(minX) || !Number.isFinite(maxX)) return null;\n if (anchorMode === \"top-center\") {\n return [(minX + maxX) * 0.5, minY];\n }\n return [minX, minY];\n}\n\nexport function getTopAnchorFromPolygons<T extends { outer: DrawCoordinate[] }>(polygons: T[], anchorMode: RegionLabelAnchorMode = \"top-center\"): DrawCoordinate | null {\n let best: DrawCoordinate | null = null;\n for (const polygon of polygons) {\n const anchor = getTopAnchor(polygon.outer, anchorMode);\n if (!anchor) continue;\n if (!best || anchor[1] < best[1] || (anchor[1] === best[1] && anchor[0] < best[0])) {\n best = anchor;\n }\n }\n return best;\n}\n\nexport function getTopAnchorFromProjectedPolygons<T extends { outer: DrawCoordinate[] }>(\n polygons: T[],\n project: (points: DrawCoordinate[]) => DrawCoordinate[],\n anchorMode: RegionLabelAnchorMode = \"top-center\"\n): DrawCoordinate | null {\n let best: DrawCoordinate | null = null;\n for (const polygon of polygons) {\n const projectedOuter = project(polygon.outer);\n if (projectedOuter.length === 0) continue;\n const anchor = getTopAnchor(projectedOuter, anchorMode);\n if (!anchor) continue;\n if (!best || anchor[1] < best[1] || (anchor[1] === best[1] && anchor[0] < best[0])) {\n best = anchor;\n }\n }\n return best;\n}\n\nexport function resolveRegionLabelStyle(style: Partial<RegionLabelStyle> | undefined): RegionLabelStyle {\n const px = typeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX) ? Math.max(0, style.paddingX) : DEFAULT_REGION_LABEL_STYLE.paddingX;\n const py = typeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY) ? Math.max(0, style.paddingY) : DEFAULT_REGION_LABEL_STYLE.paddingY;\n const fs = typeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize) ? Math.max(8, style.fontSize) : DEFAULT_REGION_LABEL_STYLE.fontSize;\n const bw = typeof style?.borderWidth === \"number\" && Number.isFinite(style.borderWidth) ? Math.max(0, style.borderWidth) : DEFAULT_REGION_LABEL_STYLE.borderWidth;\n const oy = typeof style?.offsetY === \"number\" && Number.isFinite(style.offsetY) ? style.offsetY : DEFAULT_REGION_LABEL_STYLE.offsetY;\n const br = typeof style?.borderRadius === \"number\" && Number.isFinite(style.borderRadius) ? Math.max(0, style.borderRadius) : DEFAULT_REGION_LABEL_STYLE.borderRadius;\n return {\n fontFamily: style?.fontFamily || DEFAULT_REGION_LABEL_STYLE.fontFamily,\n fontSize: fs,\n fontWeight: style?.fontWeight || DEFAULT_REGION_LABEL_STYLE.fontWeight,\n textColor: style?.textColor || DEFAULT_REGION_LABEL_STYLE.textColor,\n backgroundColor: style?.backgroundColor || DEFAULT_REGION_LABEL_STYLE.backgroundColor,\n borderColor: style?.borderColor || DEFAULT_REGION_LABEL_STYLE.borderColor,\n borderWidth: bw,\n paddingX: px,\n paddingY: py,\n offsetY: oy,\n borderRadius: br,\n };\n}\n\nexport function mergeRegionLabelStyle(base: RegionLabelStyle, override: Partial<RegionLabelStyle> | null | undefined): RegionLabelStyle {\n if (!override) return base;\n return resolveRegionLabelStyle({\n fontFamily: override.fontFamily ?? base.fontFamily,\n fontSize: override.fontSize ?? base.fontSize,\n fontWeight: override.fontWeight ?? base.fontWeight,\n textColor: override.textColor ?? base.textColor,\n backgroundColor: override.backgroundColor ?? base.backgroundColor,\n borderColor: override.borderColor ?? base.borderColor,\n borderWidth: override.borderWidth ?? base.borderWidth,\n paddingX: override.paddingX ?? base.paddingX,\n paddingY: override.paddingY ?? base.paddingY,\n offsetY: override.offsetY ?? base.offsetY,\n borderRadius: override.borderRadius ?? base.borderRadius,\n });\n}\n\nexport function resolveRegionLabelAutoLiftOffsetPx(\n enabled: boolean | undefined,\n zoom: number,\n zoomRange: { minZoom: number; maxZoom: number } | null | undefined,\n liftCapZoom?: number | null | undefined,\n): number {\n if (!enabled) return 0;\n if (!zoomRange) return 0;\n\n const minZoom = Number(zoomRange.minZoom);\n const maxZoom = Number(zoomRange.maxZoom);\n if (!Number.isFinite(minZoom) || !Number.isFinite(maxZoom)) return 0;\n\n if (maxZoom - minZoom <= REGION_LABEL_AUTO_LIFT_MAX_EPSILON) return 0;\n if (!Number.isFinite(zoom)) return 0;\n\n let cap = maxZoom;\n if (liftCapZoom != null && Number.isFinite(liftCapZoom)) {\n cap = clamp(liftCapZoom, minZoom, maxZoom);\n }\n const tol = Math.max(REGION_LABEL_AUTO_LIFT_MAX_EPSILON, Math.abs(cap) * 1e-9);\n return zoom >= cap - tol ? REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX : 0;\n}\n\nfunction resolveDrawAreaTooltipStyle(style: Partial<DrawAreaTooltipStyle> | undefined): DrawAreaTooltipStyle {\n const fontSize = typeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize) ? Math.max(8, style.fontSize) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.fontSize;\n const borderRadius = typeof style?.borderRadius === \"number\" && Number.isFinite(style.borderRadius) ? Math.max(0, style.borderRadius) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.borderRadius;\n const paddingX = typeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX) ? Math.max(0, style.paddingX) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.paddingX;\n const paddingY = typeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY) ? Math.max(0, style.paddingY) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.paddingY;\n return {\n fontFamily: style?.fontFamily || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.fontFamily,\n fontSize,\n fontWeight: style?.fontWeight || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.fontWeight,\n textColor: style?.textColor || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.textColor,\n backgroundColor: style?.backgroundColor || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.backgroundColor,\n borderRadius,\n paddingX,\n paddingY,\n };\n}\n\nfunction resolveTooltipCursorOffset(value: DrawAreaTooltipOptions[\"cursorOffset\"]): { x: number; y: number } {\n const x = typeof value?.x === \"number\" && Number.isFinite(value.x) ? value.x : DEFAULT_DRAW_AREA_TOOLTIP_OFFSET.x;\n const y = typeof value?.y === \"number\" && Number.isFinite(value.y) ? value.y : DEFAULT_DRAW_AREA_TOOLTIP_OFFSET.y;\n return { x, y };\n}\n\nexport function defaultDrawAreaTooltipFormatter(areaMm2: number): string {\n if (!Number.isFinite(areaMm2)) return \"0.000 mm²\";\n return `${Math.max(0, areaMm2).toFixed(3)} mm²`;\n}\n\nexport function resolveDrawAreaTooltipOptions(options: DrawAreaTooltipOptions | undefined): ResolvedDrawAreaTooltipOptions {\n const format = typeof options?.format === \"function\" ? options.format : defaultDrawAreaTooltipFormatter;\n const cursorOffset = resolveTooltipCursorOffset(options?.cursorOffset);\n return {\n enabled: options?.enabled === true,\n format,\n style: resolveDrawAreaTooltipStyle(options?.style),\n cursorOffsetX: cursorOffset.x,\n cursorOffsetY: cursorOffset.y,\n };\n}\n\nexport function drawRegionLabel(\n ctx: CanvasRenderingContext2D,\n text: string,\n anchor: DrawCoordinate,\n canvasWidth: number,\n canvasHeight: number,\n labelStyle: RegionLabelStyle,\n clampToViewport = true\n): void {\n const label = text.trim();\n if (!label) return;\n\n ctx.save();\n ctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n\n const textWidth = measureLabelTextWidth(label, labelStyle);\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const rawX = anchor[0];\n const rawY = anchor[1] - labelStyle.offsetY;\n const x = clampToViewport ? clamp(rawX, boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1) : rawX;\n const y = clampToViewport ? clamp(rawY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1) : rawY;\n const left = x - boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n\n ctx.fillStyle = labelStyle.backgroundColor;\n ctx.strokeStyle = labelStyle.borderColor;\n ctx.lineWidth = labelStyle.borderWidth;\n drawRoundedRect(ctx, left, top, boxWidth, boxHeight, labelStyle.borderRadius);\n ctx.fill();\n if (labelStyle.borderWidth > 0) {\n ctx.stroke();\n }\n\n ctx.fillStyle = labelStyle.textColor;\n ctx.fillText(label, x, y + 0.5);\n ctx.restore();\n}\n\nexport function drawAreaTooltipBox(\n ctx: CanvasRenderingContext2D,\n text: string,\n cursorScreen: DrawCoordinate,\n canvasWidth: number,\n canvasHeight: number,\n style: DrawAreaTooltipStyle,\n offsetX: number,\n offsetY: number\n): void {\n const label = text.trim();\n if (!label) return;\n\n ctx.save();\n ctx.font = `${style.fontWeight} ${style.fontSize}px ${style.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n\n const textWidth = measureLabelTextWidth(label, style);\n const boxWidth = textWidth + style.paddingX * 2;\n const boxHeight = style.fontSize + style.paddingY * 2;\n\n const x = clamp(cursorScreen[0] + offsetX, boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1);\n const y = clamp(cursorScreen[1] + offsetY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1);\n const left = x - boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n\n ctx.fillStyle = style.backgroundColor;\n drawRoundedRect(ctx, left, top, boxWidth, boxHeight, style.borderRadius);\n ctx.fill();\n\n ctx.fillStyle = style.textColor;\n ctx.fillText(label, x, y + 0.5);\n ctx.restore();\n}\n","import type { DrawCoordinate, DrawOverlayShape, RegionStrokeStyle } from \"./draw-layer-types\";\nimport { drawPath, isNestedRingCoordinates, mergeStrokeStyle, normalizeOverlayRings, tracePath } from \"./draw-layer-utils\";\n\nexport function drawInvertedFillMask(ctx: CanvasRenderingContext2D, outerRing: DrawCoordinate[], holeRings: DrawCoordinate[][], fillColor: string): void {\n if (outerRing.length < 4 || holeRings.length === 0) return;\n ctx.save();\n ctx.beginPath();\n tracePath(ctx, outerRing, true);\n for (const ring of holeRings) {\n if (ring.length < 4) continue;\n tracePath(ctx, ring, true);\n }\n ctx.fillStyle = fillColor;\n ctx.fill(\"evenodd\");\n ctx.restore();\n}\n\nexport interface DrawOverlayShapesParams {\n ctx: CanvasRenderingContext2D;\n overlayShapes: DrawOverlayShape[];\n imageOuterRing: DrawCoordinate[];\n worldToScreenPoints: (points: DrawCoordinate[]) => DrawCoordinate[];\n baseStrokeStyle: RegionStrokeStyle;\n onInvertedFillDebug?: (info: { id: string | number; outerRingPoints: number; sourceRingCount: number; holeRingCount: number; fillColor: string }) => void;\n}\n\nexport function drawOverlayShapes(params: DrawOverlayShapesParams): void {\n const { ctx, overlayShapes, imageOuterRing, worldToScreenPoints, baseStrokeStyle, onInvertedFillDebug } = params;\n\n const debugOverlay = Boolean((globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__);\n\n for (let i = 0; i < overlayShapes.length; i += 1) {\n const shape = overlayShapes[i];\n if (!shape?.coordinates?.length || shape.visible === false) continue;\n\n const closed = shape.closed ?? isNestedRingCoordinates(shape.coordinates);\n const renderRings = normalizeOverlayRings(shape.coordinates, closed);\n\n if (shape.invertedFill?.fillColor) {\n const holeRings: DrawCoordinate[][] = [];\n const closedRings = normalizeOverlayRings(shape.coordinates, true);\n for (const ring of closedRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length >= 4) {\n holeRings.push(screen);\n }\n }\n if (debugOverlay && onInvertedFillDebug) {\n onInvertedFillDebug({\n id: shape.id ?? i,\n outerRingPoints: imageOuterRing.length,\n sourceRingCount: closedRings.length,\n holeRingCount: holeRings.length,\n fillColor: shape.invertedFill.fillColor,\n });\n }\n drawInvertedFillMask(ctx, imageOuterRing, holeRings, shape.invertedFill.fillColor);\n }\n\n if (renderRings.length === 0) continue;\n const strokeStyle = mergeStrokeStyle(baseStrokeStyle, shape.stroke ?? shape.strokeStyle);\n for (const ring of renderRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length < 2) continue;\n drawPath(ctx, screen, strokeStyle, closed, shape.fill ?? false);\n }\n }\n}\n","import type { DrawCoordinate, DrawTool, StampDrawTool, StampOptions, StampToolConfig } from \"./draw-layer-types\";\nimport { CIRCLE_SIDES, DEFAULT_STAMP_CIRCLE_AREA_MM2, DEFAULT_STAMP_RECTANGLE_AREA_MM2, DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE, LEGACY_HPF_CIRCLE_AREA_MM2 } from \"./draw-layer-types\";\nimport { clampPositiveOrFallback, clampWorld, closeRing } from \"./draw-layer-utils\";\n\nexport type { StampDrawTool, StampOptions, StampToolConfig };\n\nexport function isStampTool(tool: DrawTool): tool is StampDrawTool {\n return (\n typeof tool === \"string\" && (\n tool === \"stamp-rectangle\" || tool === \"stamp-circle\" || tool === \"stamp-rectangle-4096px\" || tool === \"stamp-rectangle-2mm2\" || tool === \"stamp-circle-2mm2\" || tool === \"stamp-circle-hpf-0.2mm2\"\n )\n );\n}\n\nexport function isStampConfig(tool: DrawTool): tool is { stamp: StampToolConfig } {\n return typeof tool === \"object\" && tool !== null && \"stamp\" in tool;\n}\n\nexport function isDrawToolString(tool: DrawTool): tool is Exclude<DrawTool, { stamp: StampToolConfig }> {\n return typeof tool === \"string\";\n}\n\nexport function isBrushVariant(tool: DrawTool): boolean {\n return tool === \"brush\" || tool === \"eraser\" || tool === \"region-brush\" || tool === \"region-eraser\";\n}\n\nexport function resolveStampOptions(options: StampOptions | undefined): Required<StampOptions> {\n return {\n rectangleAreaMm2: clampPositiveOrFallback(options?.rectangleAreaMm2, DEFAULT_STAMP_RECTANGLE_AREA_MM2),\n circleAreaMm2: clampPositiveOrFallback(options?.circleAreaMm2, DEFAULT_STAMP_CIRCLE_AREA_MM2),\n rectanglePixelSize: clampPositiveOrFallback(options?.rectanglePixelSize, DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE),\n };\n}\n\nconst MICRONS_PER_MM = 1000;\n\nexport function mm2ToUm2(areaMm2: number): number {\n return areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nexport function createSquareFromCenter(\n center: DrawCoordinate | null,\n halfLength: number,\n projection?: {\n worldToScreen: (x: number, y: number) => DrawCoordinate | null;\n screenToWorld: (screen: DrawCoordinate) => DrawCoordinate | null;\n }\n): DrawCoordinate[] {\n if (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\n\n if (projection) {\n const screenCenter = projection.worldToScreen(center[0], center[1]);\n const screenEdge = projection.worldToScreen(center[0] + halfLength, center[1]);\n if (screenCenter && screenEdge) {\n const screenHL = Math.hypot(screenEdge[0] - screenCenter[0], screenEdge[1] - screenCenter[1]);\n const screenCorners: DrawCoordinate[] = [\n [screenCenter[0] - screenHL, screenCenter[1] - screenHL],\n [screenCenter[0] + screenHL, screenCenter[1] - screenHL],\n [screenCenter[0] + screenHL, screenCenter[1] + screenHL],\n [screenCenter[0] - screenHL, screenCenter[1] + screenHL],\n ];\n const worldCorners: DrawCoordinate[] = [];\n for (const corner of screenCorners) {\n const world = projection.screenToWorld(corner);\n if (!world) throw new Error(\"Failed to create rectangle\");\n worldCorners.push(world);\n }\n return closeRing(worldCorners);\n }\n }\n\n return closeRing([\n [center[0] - halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] + halfLength],\n [center[0] - halfLength, center[1] + halfLength],\n ]);\n}\n\nexport function createCircleFromCenter(center: DrawCoordinate | null, radius: number, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!center || !Number.isFinite(radius) || radius <= 0) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([center[0] + Math.cos(t) * radius, center[1] + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nexport interface BuildStampCoordsParams {\n stampTool: StampDrawTool;\n center: DrawCoordinate | null;\n resolvedStampOptions: Required<StampOptions>;\n imageWidth: number;\n imageHeight: number;\n micronsToWorldPixels: (lengthUm: number) => number;\n getRectangleProjection: () =>\n | {\n worldToScreen: (x: number, y: number) => DrawCoordinate | null;\n screenToWorld: (screen: DrawCoordinate) => DrawCoordinate | null;\n }\n | undefined;\n}\n\nexport function buildStampCoords(params: BuildStampCoordsParams): DrawCoordinate[] {\n const { stampTool, center, resolvedStampOptions, imageWidth, imageHeight, micronsToWorldPixels, getRectangleProjection } = params;\n\n if (!center) return [];\n\n if (stampTool === \"stamp-rectangle-4096px\") {\n const halfLength = resolvedStampOptions.rectanglePixelSize * 0.5;\n return createSquareFromCenter(center, halfLength, getRectangleProjection()).map(point => clampWorld(point, imageWidth, imageHeight));\n }\n\n let areaMm2 = 0;\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n areaMm2 = stampTool === \"stamp-rectangle-2mm2\" ? DEFAULT_STAMP_RECTANGLE_AREA_MM2 : resolvedStampOptions.rectangleAreaMm2;\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n areaMm2 = stampTool === \"stamp-circle-hpf-0.2mm2\" ? LEGACY_HPF_CIRCLE_AREA_MM2 : stampTool === \"stamp-circle-2mm2\" ? DEFAULT_STAMP_CIRCLE_AREA_MM2 : resolvedStampOptions.circleAreaMm2;\n }\n if (!Number.isFinite(areaMm2) || areaMm2 <= 0) return [];\n\n const areaUm2 = mm2ToUm2(areaMm2);\n let coords: DrawCoordinate[] = [];\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n const halfLength = micronsToWorldPixels(Math.sqrt(areaUm2) * 0.5);\n coords = createSquareFromCenter(center, halfLength, getRectangleProjection());\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n const radius = micronsToWorldPixels(Math.sqrt(areaUm2 / Math.PI));\n coords = createCircleFromCenter(center, radius);\n }\n\n if (!coords.length) return [];\n return coords.map(point => clampWorld(point, imageWidth, imageHeight));\n}\n","import { type CSSProperties, type PointerEvent as ReactPointerEvent, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { buildBrushStrokePolygon } from \"../wsi/brush-stroke\";\nimport { observeDevicePixelRatioChanges } from \"../wsi/device-pixel-ratio\";\nimport { calcScaleResolution } from \"../wsi/utils\";\nimport { drawBrushCursor, drawBrushStrokePreview, resolveBrushOptions } from \"./draw-layer-brush\";\nimport {\n drawAreaTooltipBox,\n drawRegionLabel,\n getTopAnchorFromProjectedPolygons,\n mergeRegionLabelStyle,\n resolveDrawAreaTooltipOptions,\n resolveRegionLabelAutoLiftOffsetPx,\n resolveRegionLabelStyle,\n} from \"./draw-layer-label\";\nimport { drawOverlayShapes } from \"./draw-layer-overlay\";\nimport { buildStampCoords, isStampTool, resolveStampOptions } from \"./draw-layer-stamp\";\nimport {\n BRUSH_SCREEN_STEP,\n DEFAULT_DRAW_PREVIEW_FILL,\n DEFAULT_PATCH_STROKE_STYLE,\n type DrawLayerProps,\n type DrawRegion,\n type DrawSession,\n type DrawTool,\n EMPTY_DASH,\n EMPTY_REGIONS,\n FREEHAND_MIN_POINTS,\n FREEHAND_SCREEN_STEP,\n MICRONS_PER_MM,\n MIN_AREA_PX,\n type PreparedRenderedRegion,\n REGION_INTERACTION_SHADOW_COLOR,\n REGION_INTERACTION_SHADOW_WIDTH,\n type StampDrawTool,\n WHEEL_ZOOM_IN_FACTOR,\n WHEEL_ZOOM_OUT_FACTOR,\n} from \"./draw-layer-types\";\nimport {\n clamp,\n clampWorld,\n closeRing,\n computeBounds,\n createCircle,\n createRectangle,\n drawPath,\n isSameRegionId,\n mergeStrokeStyle,\n normalizeDrawRegionPolygons,\n polygonArea,\n resolveStrokeStyle,\n toCoord,\n} from \"./draw-layer-utils\";\n\nexport { mergeRegionLabelStyle, resolveRegionLabelAutoLiftOffsetPx, resolveRegionLabelStyle } from \"./draw-layer-label\";\nexport type {\n BrushOptions,\n DrawAreaTooltipOptions,\n DrawAreaTooltipStyle,\n DrawBounds,\n DrawCoordinate,\n DrawIntent,\n DrawOverlayCoordinates,\n DrawOverlayInvertedFillStyle,\n DrawOverlayShape,\n DrawProjector,\n DrawRegion,\n DrawRegionCoordinates,\n DrawResult,\n DrawTool,\n PatchDrawResult,\n RegionLabelAnchorMode,\n RegionLabelStyle,\n RegionLabelStyleContext,\n RegionLabelStyleResolver,\n RegionStrokeStyle,\n RegionStrokeStyleResolver,\n RegionStyleContext,\n StampDrawTool,\n StampOptions,\n StampShape,\n StampToolConfig,\n} from \"./draw-layer-types\";\nexport { closeRing, createCircle, createRectangle } from \"./draw-layer-utils\";\n\nfunction resolveRegionInteractionShadowStyle(strokeStyle: import(\"./draw-layer-types\").RegionStrokeStyle): import(\"./draw-layer-types\").RegionStrokeStyle {\n return {\n color: REGION_INTERACTION_SHADOW_COLOR,\n width: REGION_INTERACTION_SHADOW_WIDTH,\n lineDash: EMPTY_DASH,\n lineJoin: strokeStyle.lineJoin,\n lineCap: strokeStyle.lineCap,\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n };\n}\n\nfunction resolveDrawPreviewFillColor(value: string | undefined): string {\n if (typeof value !== \"string\") return DEFAULT_DRAW_PREVIEW_FILL;\n const next = value.trim();\n return next.length > 0 ? next : DEFAULT_DRAW_PREVIEW_FILL;\n}\n\nfunction isValidPolygon(coords: import(\"./draw-layer-types\").DrawCoordinate[]): boolean {\n return Array.isArray(coords) && coords.length >= 4 && polygonArea(coords) > MIN_AREA_PX;\n}\n\nexport function DrawLayer({\n tool,\n imageWidth,\n imageHeight,\n imageMpp,\n imageZoom,\n stampOptions,\n brushOptions,\n projectorRef,\n onBrushTap,\n onDrawComplete,\n onPatchComplete,\n enabled,\n viewStateSignal,\n persistedRegions,\n patchRegions,\n persistedPolygons,\n drawFillColor,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n resolveRegionLabelStyle: resolveRegionLabelStyleProp,\n overlayShapes,\n hoveredRegionId = null,\n activeRegionId = null,\n regionLabelStyle,\n drawAreaTooltip,\n autoLiftRegionLabelAtMaxZoom = false,\n regionLabelAnchor = \"top-center\",\n clampRegionLabelToViewport = true,\n regionLabelAutoLiftOffsetPx,\n invalidateRef,\n className,\n style,\n}: DrawLayerProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const drawPendingRef = useRef(false);\n const overlayDebugSnapshotRef = useRef<Map<string, string>>(new Map());\n const lastToolRef = useRef<DrawTool>(tool);\n const sessionRef = useRef<DrawSession>({\n isDrawing: false,\n pointerId: null,\n start: null,\n current: null,\n cursor: null,\n cursorScreen: null,\n points: [],\n screenPoints: [],\n stampCenter: null,\n });\n\n const active = enabled ?? tool !== \"cursor\";\n const mergedPersistedRegions = useMemo<DrawRegion[]>(() => {\n if (persistedRegions && persistedRegions.length > 0) {\n return persistedRegions;\n }\n if (!persistedPolygons || persistedPolygons.length === 0) {\n return EMPTY_REGIONS;\n }\n return persistedPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [persistedRegions, persistedPolygons]);\n const mergedPatchRegions = useMemo<DrawRegion[]>(() => patchRegions ?? EMPTY_REGIONS, [patchRegions]);\n const preparedPersistedRegions = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < mergedPersistedRegions.length; i += 1) {\n const region = mergedPersistedRegions[i];\n const polygons = normalizeDrawRegionPolygons(region.coordinates);\n if (polygons.length === 0) continue;\n out.push({\n region,\n regionIndex: i,\n regionKey: region.id ?? i,\n polygons,\n });\n }\n return out;\n }, [mergedPersistedRegions]);\n const preparedPatchRegions = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < mergedPatchRegions.length; i += 1) {\n const region = mergedPatchRegions[i];\n const polygons = normalizeDrawRegionPolygons(region.coordinates);\n if (polygons.length === 0) continue;\n out.push({\n region,\n regionIndex: i,\n regionKey: region.id ?? i,\n polygons,\n });\n }\n return out;\n }, [mergedPatchRegions]);\n\n const resolvedStrokeStyle = useMemo(() => resolveStrokeStyle(regionStrokeStyle), [regionStrokeStyle]);\n const resolvedHoverStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeHoverStyle), [resolvedStrokeStyle, regionStrokeHoverStyle]);\n const resolvedActiveStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeActiveStyle), [resolvedStrokeStyle, regionStrokeActiveStyle]);\n const resolvedPatchStrokeStyle = useMemo(() => mergeStrokeStyle(DEFAULT_PATCH_STROKE_STYLE, patchStrokeStyle), [patchStrokeStyle]);\n const resolvedDrawPreviewFillColor = useMemo(() => resolveDrawPreviewFillColor(drawFillColor), [drawFillColor]);\n\n const resolvedLabelStyle = useMemo(() => resolveRegionLabelStyle(regionLabelStyle), [regionLabelStyle]);\n const resolvedDrawAreaTooltipOptions = useMemo(() => resolveDrawAreaTooltipOptions(drawAreaTooltip), [drawAreaTooltip]);\n const resolvedStampOptions = useMemo(() => resolveStampOptions(stampOptions), [stampOptions]);\n const resolvedBrushOptions = useMemo(() => resolveBrushOptions(brushOptions), [brushOptions]);\n\n const mergedStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n inset: 0,\n zIndex: 2,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n pointerEvents: active ? \"auto\" : \"none\",\n cursor: active ? (tool === \"brush\" ? \"none\" : \"crosshair\") : \"default\",\n ...style,\n }),\n [active, tool, style]\n );\n\n const resizeCanvas = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const rect = canvas.getBoundingClientRect();\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const w = Math.max(1, Math.round(rect.width * dpr));\n const h = Math.max(1, Math.round(rect.height * dpr));\n\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n }, [active, tool]);\n\n const worldToScreenPoints = useCallback(\n (points: import(\"./draw-layer-types\").DrawCoordinate[]): import(\"./draw-layer-types\").DrawCoordinate[] => {\n const projector = projectorRef.current;\n if (!projector || points.length === 0) return [];\n\n const out = new Array<import(\"./draw-layer-types\").DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [projectorRef]\n );\n\n const localScreenToWorld = useCallback(\n (screen: import(\"./draw-layer-types\").DrawCoordinate): import(\"./draw-layer-types\").DrawCoordinate | null => {\n const projector = projectorRef.current;\n const canvas = canvasRef.current;\n if (!projector || !canvas) return null;\n const rect = canvas.getBoundingClientRect();\n const raw = toCoord(projector.screenToWorld(rect.left + screen[0], rect.top + screen[1]));\n if (!raw) return null;\n return clampWorld(raw, imageWidth, imageHeight);\n },\n [projectorRef, imageWidth, imageHeight]\n );\n\n const getRectangleProjection = useCallback(() => {\n const projector = projectorRef.current;\n const rotationDeg = projector?.getViewState?.().rotationDeg ?? 0;\n if (Math.abs(rotationDeg % 360) < 0.01 || !projector) return undefined;\n\n return {\n worldToScreen: (x: number, y: number): import(\"./draw-layer-types\").DrawCoordinate | null => toCoord(projector.worldToScreen(x, y)),\n screenToWorld: localScreenToWorld,\n };\n }, [projectorRef, localScreenToWorld]);\n\n const micronsToWorldPixels = useCallback(\n (lengthUm: number): number => {\n if (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n const mppValue = typeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0 ? imageMpp : 1;\n const imageZoomValue = typeof imageZoom === \"number\" && Number.isFinite(imageZoom) ? imageZoom : 0;\n const viewZoomRaw = projectorRef.current?.getViewState?.().zoom;\n const viewZoom = typeof viewZoomRaw === \"number\" && Number.isFinite(viewZoomRaw) && viewZoomRaw > 0 ? viewZoomRaw : 1;\n const continuousZoom = imageZoomValue + Math.log2(viewZoom);\n const umPerScreenPixel = Math.max(1e-9, calcScaleResolution(mppValue, imageZoomValue, continuousZoom));\n const screenPixels = lengthUm / umPerScreenPixel;\n return screenPixels / viewZoom;\n },\n [imageMpp, imageZoom, projectorRef]\n );\n\n const buildStampCoordsCallback = useCallback(\n (stampTool: StampDrawTool, center: import(\"./draw-layer-types\").DrawCoordinate | null): import(\"./draw-layer-types\").DrawCoordinate[] => {\n return buildStampCoords({\n stampTool,\n center,\n resolvedStampOptions,\n imageWidth,\n imageHeight,\n micronsToWorldPixels,\n getRectangleProjection,\n });\n },\n [micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions, getRectangleProjection]\n );\n\n const buildPreviewCoords = useCallback((): import(\"./draw-layer-types\").DrawCoordinate[] => {\n const session = sessionRef.current;\n if (isStampTool(tool)) {\n return buildStampCoordsCallback(tool, session.stampCenter);\n }\n if (tool === \"brush\") {\n return [];\n }\n if (!session.isDrawing) return [];\n\n if (tool === \"freehand\") {\n return session.points;\n }\n if (tool === \"rectangle\") {\n return createRectangle(session.start, session.current, getRectangleProjection());\n }\n if (tool === \"circular\") {\n return createCircle(session.start, session.current);\n }\n\n return [];\n }, [tool, buildStampCoordsCallback, getRectangleProjection]);\n\n const drawOverlay = useCallback(() => {\n resizeCanvas();\n\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const canvasWidth = canvas.width / dpr;\n const canvasHeight = canvas.height / dpr;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n if (preparedPersistedRegions.length > 0) {\n for (const entry of preparedPersistedRegions) {\n const { region, polygons, regionIndex, regionKey } = entry;\n const state: \"default\" | \"hover\" | \"active\" = isSameRegionId(activeRegionId, regionKey) ? \"active\" : isSameRegionId(hoveredRegionId, regionKey) ? \"hover\" : \"default\";\n let strokeStyle = state === \"active\" ? resolvedActiveStrokeStyle : state === \"hover\" ? resolvedHoverStrokeStyle : resolvedStrokeStyle;\n\n if (resolveRegionStrokeStyle) {\n const resolved = resolveRegionStrokeStyle({\n region,\n regionId: regionKey,\n regionIndex,\n state,\n });\n strokeStyle = mergeStrokeStyle(strokeStyle, resolved || undefined);\n }\n const interactionShadowStyle = state === \"default\" ? null : resolveRegionInteractionShadowStyle(strokeStyle);\n\n for (const polygon of polygons) {\n const screenOuter = worldToScreenPoints(polygon.outer);\n if (screenOuter.length >= 4) {\n if (interactionShadowStyle) {\n drawPath(ctx, screenOuter, interactionShadowStyle, true, false);\n }\n drawPath(ctx, screenOuter, strokeStyle, true, false);\n }\n for (const hole of polygon.holes) {\n const screenHole = worldToScreenPoints(hole);\n if (screenHole.length >= 4) {\n if (interactionShadowStyle) {\n drawPath(ctx, screenHole, interactionShadowStyle, true, false);\n }\n drawPath(ctx, screenHole, strokeStyle, true, false);\n }\n }\n }\n }\n }\n\n if (preparedPatchRegions.length > 0) {\n for (const entry of preparedPatchRegions) {\n for (const polygon of entry.polygons) {\n const screenOuter = worldToScreenPoints(polygon.outer);\n if (screenOuter.length >= 4) {\n drawPath(ctx, screenOuter, resolvedPatchStrokeStyle, true, false);\n }\n for (const hole of polygon.holes) {\n const screenHole = worldToScreenPoints(hole);\n if (screenHole.length >= 4) {\n drawPath(ctx, screenHole, resolvedPatchStrokeStyle, true, false);\n }\n }\n }\n }\n }\n\n if (Array.isArray(overlayShapes) && overlayShapes.length > 0) {\n const imageOuterRing = worldToScreenPoints(\n closeRing([\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ])\n );\n drawOverlayShapes({\n ctx,\n overlayShapes,\n imageOuterRing,\n worldToScreenPoints,\n baseStrokeStyle: resolvedStrokeStyle,\n onInvertedFillDebug: (globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__\n ? info => {\n const debugKey = String(info.id);\n const debugSignature = `${info.outerRingPoints}|${info.sourceRingCount}|${info.holeRingCount}|${info.fillColor}`;\n if (overlayDebugSnapshotRef.current.get(debugKey) !== debugSignature) {\n overlayDebugSnapshotRef.current.set(debugKey, debugSignature);\n console.debug(\"[open-plant] invertedFill\", info);\n }\n }\n : undefined,\n });\n }\n\n const preview = buildPreviewCoords();\n\n if (active) {\n if (tool === \"brush\") {\n drawBrushStrokePreview(ctx, sessionRef.current, resolvedBrushOptions);\n drawBrushCursor(ctx, sessionRef.current, projectorRef.current, resolvedBrushOptions);\n } else if (preview.length > 0) {\n if (tool === \"freehand\") {\n const line = worldToScreenPoints(preview);\n if (line.length >= 2) {\n drawPath(ctx, line, resolvedStrokeStyle, false, false);\n }\n if (line.length >= 3) {\n drawPath(ctx, worldToScreenPoints(closeRing(preview)), resolvedStrokeStyle, true, true, resolvedDrawPreviewFillColor);\n }\n } else {\n const polygon = worldToScreenPoints(preview);\n if (polygon.length >= 4) {\n drawPath(ctx, polygon, resolvedStrokeStyle, true, true, resolvedDrawPreviewFillColor);\n }\n }\n }\n }\n\n if (preparedPersistedRegions.length > 0) {\n const zoom = Math.max(1e-6, projectorRef.current?.getViewState?.().zoom ?? 1);\n const labelAutoLiftOffset =\n typeof regionLabelAutoLiftOffsetPx === \"number\" && Number.isFinite(regionLabelAutoLiftOffsetPx)\n ? Math.max(0, regionLabelAutoLiftOffsetPx)\n : resolveRegionLabelAutoLiftOffsetPx(\n autoLiftRegionLabelAtMaxZoom,\n zoom,\n projectorRef.current?.getZoomRange?.(),\n projectorRef.current?.getRegionLabelAutoLiftCapZoom?.(),\n );\n for (const entry of preparedPersistedRegions) {\n if (!entry.region.label) continue;\n const anchorScreen = getTopAnchorFromProjectedPolygons(entry.polygons, worldToScreenPoints, regionLabelAnchor);\n if (!anchorScreen) continue;\n let dynamicLabelStyle = mergeRegionLabelStyle(\n resolvedLabelStyle,\n resolveRegionLabelStyleProp?.({\n region: entry.region,\n regionId: entry.regionKey,\n regionIndex: entry.regionIndex,\n zoom,\n })\n );\n if (labelAutoLiftOffset > 0) {\n dynamicLabelStyle = {\n ...dynamicLabelStyle,\n offsetY: dynamicLabelStyle.offsetY + labelAutoLiftOffset,\n };\n }\n drawRegionLabel(ctx, entry.region.label, anchorScreen, canvasWidth, canvasHeight, dynamicLabelStyle, clampRegionLabelToViewport);\n }\n }\n\n if (resolvedDrawAreaTooltipOptions.enabled && active && (tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\")) {\n const session = sessionRef.current;\n if (session.isDrawing) {\n const areaCoords = tool === \"freehand\" ? closeRing(preview) : preview;\n if (areaCoords.length >= 4) {\n const areaPx = polygonArea(areaCoords);\n const mpp = typeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0 ? imageMpp : 0;\n const areaMm2 = mpp > 0 ? (areaPx * mpp * mpp) / (MICRONS_PER_MM * MICRONS_PER_MM) : 0;\n const text = resolvedDrawAreaTooltipOptions.format(areaMm2);\n\n const cursor = session.cursorScreen ?? (session.current ? toCoord(projectorRef.current?.worldToScreen(session.current[0], session.current[1]) ?? []) : null);\n if (cursor) {\n drawAreaTooltipBox(\n ctx,\n text,\n cursor,\n canvasWidth,\n canvasHeight,\n resolvedDrawAreaTooltipOptions.style,\n resolvedDrawAreaTooltipOptions.cursorOffsetX,\n resolvedDrawAreaTooltipOptions.cursorOffsetY\n );\n }\n }\n }\n }\n }, [\n active,\n tool,\n buildPreviewCoords,\n resizeCanvas,\n worldToScreenPoints,\n imageWidth,\n imageHeight,\n projectorRef,\n preparedPersistedRegions,\n overlayShapes,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n resolvedDrawPreviewFillColor,\n preparedPatchRegions,\n resolvedPatchStrokeStyle,\n resolveRegionStrokeStyle,\n resolveRegionLabelStyleProp,\n resolvedLabelStyle,\n resolvedDrawAreaTooltipOptions,\n autoLiftRegionLabelAtMaxZoom,\n regionLabelAnchor,\n clampRegionLabelToViewport,\n regionLabelAutoLiftOffsetPx,\n imageMpp,\n resolvedBrushOptions,\n ]);\n\n const requestDraw = useCallback(() => {\n if (drawPendingRef.current) return;\n drawPendingRef.current = true;\n requestAnimationFrame(() => {\n drawPendingRef.current = false;\n drawOverlay();\n });\n }, [drawOverlay]);\n\n const resetSession = useCallback((preserveCursor = false) => {\n const session = sessionRef.current;\n const canvas = canvasRef.current;\n\n if (canvas && session.pointerId !== null && canvas.hasPointerCapture(session.pointerId)) {\n canvas.releasePointerCapture(session.pointerId);\n }\n\n session.isDrawing = false;\n session.pointerId = null;\n session.start = null;\n session.current = null;\n session.points = [];\n session.screenPoints = [];\n session.stampCenter = null;\n if (!preserveCursor) {\n session.cursor = null;\n session.cursorScreen = null;\n }\n }, []);\n\n const toWorld = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): import(\"./draw-layer-types\").DrawCoordinate | null => {\n const projector = projectorRef.current;\n if (!projector || imageWidth <= 0 || imageHeight <= 0) return null;\n\n const raw = toCoord(projector.screenToWorld(event.clientX, event.clientY));\n if (!raw) return null;\n return clampWorld(raw, imageWidth, imageHeight);\n },\n [projectorRef, imageWidth, imageHeight]\n );\n\n const toLocalScreen = useCallback((event: ReactPointerEvent<HTMLCanvasElement>): import(\"./draw-layer-types\").DrawCoordinate | null => {\n const canvas = canvasRef.current;\n if (!canvas) return null;\n const rect = canvas.getBoundingClientRect();\n const x = clamp(event.clientX - rect.left, 0, rect.width);\n const y = clamp(event.clientY - rect.top, 0, rect.height);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const finishSession = useCallback(() => {\n const session = sessionRef.current;\n if (!session.isDrawing) {\n resetSession(true);\n requestDraw();\n return;\n }\n\n let coordinates: import(\"./draw-layer-types\").DrawCoordinate[] = [];\n if (tool === \"freehand\") {\n if (session.points.length >= FREEHAND_MIN_POINTS) {\n coordinates = closeRing(session.points);\n }\n } else if (tool === \"rectangle\") {\n coordinates = createRectangle(session.start, session.current, getRectangleProjection());\n } else if (tool === \"circular\") {\n coordinates = createCircle(session.start, session.current);\n } else if (tool === \"brush\") {\n const tapPoint = session.points[session.points.length - 1] ?? session.current ?? session.start;\n if (resolvedBrushOptions.clickSelectRoi && tapPoint && session.points.length <= 1 && onBrushTap?.(tapPoint)) {\n resetSession(true);\n requestDraw();\n return;\n }\n const edgeDetail = Math.max(0.25, resolvedBrushOptions.edgeDetail);\n const screenPath = session.screenPoints.length > 0 ? session.screenPoints : worldToScreenPoints(session.points);\n const simplifyTolerance = Math.max(0.5, (resolvedBrushOptions.radius * 0.04) / edgeDetail);\n const screenPolygon = buildBrushStrokePolygon(screenPath, {\n radius: resolvedBrushOptions.radius,\n circleSides: Math.max(16, Math.round(32 * edgeDetail)),\n simplifyTolerance,\n smoothingPasses: resolvedBrushOptions.edgeSmoothing,\n }) as import(\"./draw-layer-types\").DrawCoordinate[];\n const worldPolygon: import(\"./draw-layer-types\").DrawCoordinate[] = [];\n for (const point of screenPolygon) {\n const world = localScreenToWorld(point);\n if (!world) continue;\n worldPolygon.push(world);\n }\n coordinates = closeRing(worldPolygon);\n }\n\n if ((tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\" || tool === \"brush\") && isValidPolygon(coordinates) && onDrawComplete) {\n const intent: import(\"./draw-layer-types\").DrawIntent = tool === \"brush\" ? \"brush\" : \"roi\";\n onDrawComplete({\n tool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n });\n }\n\n resetSession(true);\n requestDraw();\n }, [\n tool,\n onDrawComplete,\n resetSession,\n requestDraw,\n worldToScreenPoints,\n localScreenToWorld,\n getRectangleProjection,\n resolvedBrushOptions.radius,\n resolvedBrushOptions.edgeDetail,\n resolvedBrushOptions.edgeSmoothing,\n resolvedBrushOptions.clickSelectRoi,\n onBrushTap,\n ]);\n\n const handleStampAt = useCallback(\n (stampTool: StampDrawTool, center: import(\"./draw-layer-types\").DrawCoordinate): void => {\n const coordinates = buildStampCoordsCallback(stampTool, center);\n if (!isValidPolygon(coordinates)) return;\n const intent: import(\"./draw-layer-types\").DrawIntent = stampTool === \"stamp-rectangle-4096px\" ? \"patch\" : \"roi\";\n const result: import(\"./draw-layer-types\").DrawResult = {\n tool: stampTool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n };\n onDrawComplete?.(result);\n if (intent === \"patch\" && onPatchComplete) {\n onPatchComplete(result as import(\"./draw-layer-types\").PatchDrawResult);\n }\n },\n [buildStampCoordsCallback, onDrawComplete, onPatchComplete]\n );\n\n const appendBrushPoint = useCallback(\n (session: DrawSession, world: import(\"./draw-layer-types\").DrawCoordinate, screen: import(\"./draw-layer-types\").DrawCoordinate): void => {\n const minScreenStep = Math.max(BRUSH_SCREEN_STEP, resolvedBrushOptions.radius * 0.1);\n const minScreenStep2 = minScreenStep * minScreenStep;\n const prevScreen = session.screenPoints[session.screenPoints.length - 1];\n if (!prevScreen) {\n session.points.push(world);\n session.screenPoints.push(screen);\n session.current = world;\n return;\n }\n const dx = screen[0] - prevScreen[0];\n const dy = screen[1] - prevScreen[1];\n if (dx * dx + dy * dy >= minScreenStep2) {\n session.points.push(world);\n session.screenPoints.push(screen);\n } else {\n session.points[session.points.length - 1] = world;\n session.screenPoints[session.screenPoints.length - 1] = screen;\n }\n session.current = world;\n },\n [resolvedBrushOptions.radius]\n );\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n if (event.button !== 0) return;\n\n const world = toWorld(event);\n if (!world) return;\n const screen = toLocalScreen(event);\n if (!screen) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n handleStampAt(tool, world);\n requestDraw();\n return;\n }\n\n const canvas = canvasRef.current;\n if (canvas) {\n canvas.setPointerCapture(event.pointerId);\n }\n\n const session = sessionRef.current;\n session.isDrawing = true;\n session.pointerId = event.pointerId;\n session.start = world;\n session.current = world;\n session.cursor = world;\n session.cursorScreen = screen;\n session.points = tool === \"freehand\" || tool === \"brush\" ? [world] : [];\n session.screenPoints = tool === \"brush\" ? [screen] : [];\n requestDraw();\n },\n [active, tool, toWorld, toLocalScreen, handleStampAt, requestDraw]\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n\n const world = toWorld(event);\n if (!world) return;\n const screen = toLocalScreen(event);\n if (!screen) return;\n\n const session = sessionRef.current;\n session.cursor = world;\n session.cursorScreen = screen;\n\n if (isStampTool(tool)) {\n session.stampCenter = world;\n event.preventDefault();\n event.stopPropagation();\n requestDraw();\n return;\n }\n\n if (tool === \"brush\") {\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n requestDraw();\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n appendBrushPoint(session, world, screen);\n requestDraw();\n return;\n }\n\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n if (tool === \"freehand\") {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = FREEHAND_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n\n if (!prev) {\n session.points.push(world);\n } else {\n const dx = world[0] - prev[0];\n const dy = world[1] - prev[1];\n if (dx * dx + dy * dy >= minWorldStep2) {\n session.points.push(world);\n }\n }\n } else {\n session.current = world;\n }\n\n requestDraw();\n },\n [active, tool, toWorld, toLocalScreen, requestDraw, projectorRef, appendBrushPoint]\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.pointerId !== event.pointerId) return;\n\n event.preventDefault();\n event.stopPropagation();\n const world = toWorld(event);\n const screen = toLocalScreen(event);\n if (world) {\n session.cursor = world;\n if (screen) {\n session.cursorScreen = screen;\n }\n if (tool === \"brush\") {\n if (screen) {\n appendBrushPoint(session, world, screen);\n }\n } else {\n session.current = world;\n }\n }\n const canvas = canvasRef.current;\n if (canvas && canvas.hasPointerCapture(event.pointerId)) {\n canvas.releasePointerCapture(event.pointerId);\n }\n\n finishSession();\n },\n [finishSession, toWorld, toLocalScreen, tool, appendBrushPoint]\n );\n\n const handlePointerLeave = useCallback(() => {\n const session = sessionRef.current;\n let changed = false;\n if (tool === \"brush\" && !session.isDrawing && session.cursor) {\n session.cursor = null;\n session.cursorScreen = null;\n changed = true;\n }\n if (isStampTool(tool) && session.stampCenter) {\n session.stampCenter = null;\n changed = true;\n }\n if (changed) {\n requestDraw();\n }\n }, [tool, requestDraw]);\n\n useEffect(() => {\n resizeCanvas();\n requestDraw();\n\n const canvas = canvasRef.current;\n if (!canvas) return undefined;\n\n const observer = new ResizeObserver(() => {\n resizeCanvas();\n requestDraw();\n });\n observer.observe(canvas);\n\n return () => {\n observer.disconnect();\n };\n }, [resizeCanvas, requestDraw]);\n\n useEffect(() => observeDevicePixelRatioChanges(() => {\n resizeCanvas();\n requestDraw();\n }), [resizeCanvas, requestDraw]);\n\n useEffect(() => {\n if (!active) {\n resetSession();\n }\n requestDraw();\n }, [active, requestDraw, resetSession]);\n\n useEffect(() => {\n if (lastToolRef.current === tool) {\n return;\n }\n lastToolRef.current = tool;\n resetSession();\n requestDraw();\n }, [tool, resetSession, requestDraw]);\n\n useEffect(() => {\n requestDraw();\n }, [viewStateSignal, mergedPersistedRegions, overlayShapes, requestDraw]);\n\n useEffect(() => {\n if (!invalidateRef) return undefined;\n invalidateRef.current = requestDraw;\n return () => {\n if (invalidateRef.current === requestDraw) {\n invalidateRef.current = null;\n }\n };\n }, [invalidateRef, requestDraw]);\n\n useEffect(() => {\n if (!active) return undefined;\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n resetSession();\n requestDraw();\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [active, resetSession, requestDraw]);\n\n return (\n <canvas\n ref={canvasRef}\n className={className}\n style={mergedStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onPointerLeave={handlePointerLeave}\n onContextMenu={event => {\n if (active) event.preventDefault();\n }}\n onWheel={event => {\n if (!active) return;\n const canvas = canvasRef.current;\n const projector = projectorRef.current;\n const hasWheelZoom = typeof projector?.handleWheelZoom === \"function\";\n const hasLegacyZoom = typeof projector?.zoomBy === \"function\";\n if (!canvas || (!hasWheelZoom && !hasLegacyZoom)) return;\n event.preventDefault();\n event.stopPropagation();\n const rect = canvas.getBoundingClientRect();\n const screenX = event.clientX - rect.left;\n const screenY = event.clientY - rect.top;\n if (hasWheelZoom) {\n projector.handleWheelZoom?.(event.deltaY, screenX, screenY);\n } else {\n projector.zoomBy?.(event.deltaY < 0 ? WHEEL_ZOOM_IN_FACTOR : WHEEL_ZOOM_OUT_FACTOR, screenX, screenY);\n }\n requestDraw();\n }}\n />\n );\n}\n","import { createContext, type MutableRefObject, type RefObject, useContext } from \"react\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate } from \"./draw-layer-types\";\n\nexport type OverlayDrawFn = (ctx: CanvasRenderingContext2D, width: number, height: number) => void;\n\nexport interface ViewerContextValue {\n source: WsiImageSource | null;\n rendererRef: RefObject<WsiTileRenderer | null>;\n rendererSerial: number;\n canvasRef: RefObject<HTMLCanvasElement | null>;\n containerRef: RefObject<HTMLDivElement | null>;\n drawInvalidateRef: MutableRefObject<(() => void) | null>;\n overviewInvalidateRef: MutableRefObject<(() => void) | null>;\n\n worldToScreen: (worldX: number, worldY: number) => DrawCoordinate | null;\n screenToWorld: (clientX: number, clientY: number) => DrawCoordinate | null;\n\n registerDrawCallback: (id: string, priority: number, draw: OverlayDrawFn) => void;\n unregisterDrawCallback: (id: string) => void;\n requestOverlayRedraw: () => void;\n\n registerViewStateListener: (listener: (state: WsiViewState) => void) => () => void;\n\n setInteractionLock: (id: string, locked: boolean) => void;\n isInteractionLocked: () => boolean;\n}\n\nconst ViewerContext = createContext<ViewerContextValue | null>(null);\n\nexport const ViewerContextProvider = ViewerContext.Provider;\n\nexport function useViewerContext(): ViewerContextValue {\n const ctx = useContext(ViewerContext);\n if (!ctx) {\n throw new Error(\"useViewerContext must be used within a <WsiViewer>\");\n }\n return ctx;\n}\n\nexport function useOptionalViewerContext(): ViewerContextValue | null {\n return useContext(ViewerContext);\n}\n","import { useEffect, useMemo } from \"react\";\nimport { DrawLayer } from \"./draw-layer\";\nimport type { BrushOptions, DrawAreaTooltipOptions, DrawCoordinate, DrawResult, DrawTool, PatchDrawResult, StampOptions } from \"./draw-layer-types\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport interface DrawingLayerProps {\n tool?: DrawTool;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n fillColor?: string;\n areaTooltip?: DrawAreaTooltipOptions;\n onComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n onBrushTap?: (coordinate: DrawCoordinate) => boolean;\n}\n\nexport function DrawingLayer({ tool = \"cursor\", stampOptions, brushOptions, fillColor, areaTooltip, onComplete, onPatchComplete, onBrushTap }: DrawingLayerProps): React.ReactElement | null {\n const { source, rendererRef, rendererSerial, setInteractionLock } = useViewerContext();\n\n const active = tool !== \"cursor\";\n\n useEffect(() => {\n setInteractionLock(\"drawing-layer\", active);\n return () => setInteractionLock(\"drawing-layer\", false);\n }, [active, setInteractionLock]);\n\n const viewStateSignal = useMemo(() => rendererRef.current?.getViewState(), [rendererSerial]);\n\n if (!source) return null;\n\n return (\n <DrawLayer\n tool={tool}\n enabled={active}\n imageWidth={source.width}\n imageHeight={source.height}\n imageMpp={source.mpp}\n imageZoom={source.maxTierZoom}\n stampOptions={stampOptions}\n brushOptions={brushOptions}\n drawFillColor={fillColor}\n projectorRef={rendererRef}\n onBrushTap={onBrushTap}\n viewStateSignal={viewStateSignal}\n drawAreaTooltip={areaTooltip}\n onDrawComplete={onComplete}\n onPatchComplete={onPatchComplete}\n />\n );\n}\n","export type SpatialExtent = [number, number, number, number];\n\nexport interface SpatialIndexItem<T> {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n value: T;\n}\n\nexport interface SpatialIndex<T> {\n load(items: SpatialIndexItem<T>[]): void;\n search(extent: SpatialExtent): SpatialIndexItem<T>[];\n}\n\nfunction normalizeExtent(minX: number, minY: number, maxX: number, maxY: number): SpatialExtent {\n return [Math.min(minX, maxX), Math.min(minY, maxY), Math.max(minX, maxX), Math.max(minY, maxY)];\n}\n\nfunction intersects(a: SpatialExtent, b: SpatialExtent): boolean {\n return !(a[2] < b[0] || a[0] > b[2] || a[3] < b[1] || a[1] > b[3]);\n}\n\nclass GridSpatialIndex<T> implements SpatialIndex<T> {\n private readonly targetNodeSize: number;\n\n private items: SpatialIndexItem<T>[] = [];\n\n private globalBounds: SpatialExtent = [0, 0, 0, 0];\n\n private gridSize = 1;\n\n private cellWidth = 1;\n\n private cellHeight = 1;\n\n private buckets: number[][] = [];\n\n private visited = new Uint32Array(0);\n\n private querySerial = 1;\n\n constructor(nodeSize = 16) {\n const finite = Number.isFinite(nodeSize) ? Math.floor(nodeSize) : 16;\n this.targetNodeSize = Math.max(1, finite);\n }\n\n load(items: SpatialIndexItem<T>[]): void {\n if (!Array.isArray(items) || items.length === 0) {\n this.items = [];\n this.globalBounds = [0, 0, 0, 0];\n this.gridSize = 1;\n this.cellWidth = 1;\n this.cellHeight = 1;\n this.buckets = [];\n this.visited = new Uint32Array(0);\n this.querySerial = 1;\n return;\n }\n\n const normalized: SpatialIndexItem<T>[] = [];\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const item of items) {\n if (!item) continue;\n if (!Number.isFinite(item.minX) || !Number.isFinite(item.minY) || !Number.isFinite(item.maxX) || !Number.isFinite(item.maxY)) {\n continue;\n }\n const bounds = normalizeExtent(item.minX, item.minY, item.maxX, item.maxY);\n minX = Math.min(minX, bounds[0]);\n minY = Math.min(minY, bounds[1]);\n maxX = Math.max(maxX, bounds[2]);\n maxY = Math.max(maxY, bounds[3]);\n normalized.push({\n minX: bounds[0],\n minY: bounds[1],\n maxX: bounds[2],\n maxY: bounds[3],\n value: item.value,\n });\n }\n\n this.items = normalized;\n this.visited = new Uint32Array(normalized.length);\n this.querySerial = 1;\n\n if (normalized.length === 0 || !Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {\n this.globalBounds = [0, 0, 0, 0];\n this.gridSize = 1;\n this.cellWidth = 1;\n this.cellHeight = 1;\n this.buckets = [];\n return;\n }\n\n this.globalBounds = [minX, minY, maxX, maxY];\n this.gridSize = Math.max(1, Math.ceil(Math.sqrt(normalized.length / this.targetNodeSize)));\n\n const spanX = Math.max(0, maxX - minX);\n const spanY = Math.max(0, maxY - minY);\n this.cellWidth = spanX > 0 ? spanX / this.gridSize : 1;\n this.cellHeight = spanY > 0 ? spanY / this.gridSize : 1;\n\n const bucketCount = this.gridSize * this.gridSize;\n this.buckets = Array.from({ length: bucketCount }, () => []);\n\n for (let index = 0; index < normalized.length; index += 1) {\n const item = normalized[index];\n const minCellX = this.toCellX(item.minX);\n const maxCellX = this.toCellX(item.maxX);\n const minCellY = this.toCellY(item.minY);\n const maxCellY = this.toCellY(item.maxY);\n for (let y = minCellY; y <= maxCellY; y += 1) {\n for (let x = minCellX; x <= maxCellX; x += 1) {\n this.buckets[y * this.gridSize + x].push(index);\n }\n }\n }\n }\n\n search(extent: SpatialExtent): SpatialIndexItem<T>[] {\n if (this.items.length === 0) return [];\n if (!Array.isArray(extent) || extent.length < 4) return [];\n\n const query = normalizeExtent(extent[0], extent[1], extent[2], extent[3]);\n if (!intersects(query, this.globalBounds)) return [];\n\n const minCellX = this.toCellX(query[0]);\n const maxCellX = this.toCellX(query[2]);\n const minCellY = this.toCellY(query[1]);\n const maxCellY = this.toCellY(query[3]);\n\n const serial = this.nextSerial();\n const out: SpatialIndexItem<T>[] = [];\n\n for (let y = minCellY; y <= maxCellY; y += 1) {\n for (let x = minCellX; x <= maxCellX; x += 1) {\n const bucket = this.buckets[y * this.gridSize + x];\n if (!bucket || bucket.length === 0) continue;\n for (const itemIndex of bucket) {\n if (this.visited[itemIndex] === serial) continue;\n this.visited[itemIndex] = serial;\n const item = this.items[itemIndex];\n if (!intersects(query, [item.minX, item.minY, item.maxX, item.maxY])) continue;\n out.push(item);\n }\n }\n }\n\n return out;\n }\n\n private nextSerial(): number {\n this.querySerial += 1;\n if (this.querySerial === 0xffffffff) {\n this.visited.fill(0);\n this.querySerial = 1;\n }\n return this.querySerial;\n }\n\n private toCellX(x: number): number {\n const minX = this.globalBounds[0];\n const maxX = this.globalBounds[2];\n if (this.gridSize <= 1 || maxX <= minX) return 0;\n const ratio = (x - minX) / this.cellWidth;\n if (!Number.isFinite(ratio)) return 0;\n if (ratio <= 0) return 0;\n if (ratio >= this.gridSize - 1) return this.gridSize - 1;\n return Math.max(0, Math.min(this.gridSize - 1, Math.floor(ratio)));\n }\n\n private toCellY(y: number): number {\n const minY = this.globalBounds[1];\n const maxY = this.globalBounds[3];\n if (this.gridSize <= 1 || maxY <= minY) return 0;\n const ratio = (y - minY) / this.cellHeight;\n if (!Number.isFinite(ratio)) return 0;\n if (ratio <= 0) return 0;\n if (ratio >= this.gridSize - 1) return this.gridSize - 1;\n return Math.max(0, Math.min(this.gridSize - 1, Math.floor(ratio)));\n }\n}\n\nexport function createSpatialIndex<T>(nodeSize?: number): SpatialIndex<T> {\n return new GridSpatialIndex<T>(nodeSize);\n}\n\n","import { createProgram } from \"../core/gl-utils\";\n\nconst ACCUM_VERTEX_SHADER = `#version 300 es\nprecision highp float;\nin vec2 aCenter;\nin float aWeight;\nuniform vec2 uResolution;\nuniform float uPointSize;\nout float vWeight;\nvoid main() {\n vec2 zeroToOne = aCenter / uResolution;\n vec2 clip = vec2(zeroToOne.x * 2.0 - 1.0, 1.0 - zeroToOne.y * 2.0);\n gl_Position = vec4(clip, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vWeight = aWeight;\n}`;\n\nconst ACCUM_FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\nin float vWeight;\nuniform float uCoreRatio;\nuniform float uPointAlpha;\nout vec4 outColor;\nvoid main() {\n vec2 pointCoord = gl_PointCoord * 2.0 - 1.0;\n float radius = length(pointCoord);\n if (radius > 1.0) discard;\n\n float coreRatio = clamp(uCoreRatio, 0.02, 0.98);\n float intensity = 1.0 - smoothstep(coreRatio, 1.0, radius);\n float alpha = intensity * max(0.0, vWeight) * max(0.0, uPointAlpha);\n if (alpha <= 0.0001) discard;\n outColor = vec4(0.0, 0.0, 0.0, alpha);\n}`;\n\nconst COLOR_VERTEX_SHADER = `#version 300 es\nprecision highp float;\nin vec2 aPosition;\nvoid main() {\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}`;\n\nconst COLOR_FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\nuniform sampler2D uAccumTexture;\nuniform sampler2D uGradientTexture;\nuniform float uOpacity;\nuniform float uCutoff;\nuniform float uGain;\nuniform float uGamma;\nuniform float uBias;\nuniform float uStretch;\nuniform vec2 uResolution;\nout vec4 outColor;\nvoid main() {\n vec2 accumUv = vec2(\n (gl_FragCoord.x - 0.5) / max(1.0, uResolution.x),\n (gl_FragCoord.y - 0.5) / max(1.0, uResolution.y)\n );\n float density = texture(uAccumTexture, accumUv).a;\n if (density <= uCutoff) discard;\n\n float boosted = 1.0 - exp(-max(0.0, density - uCutoff) * uGain);\n float contrast = clamp(uGamma, 0.35, 6.0);\n float bias = clamp(uBias, 0.0, 0.92);\n float biased = max(0.0, boosted - bias);\n float stretched = pow(\n biased / max(1e-5, 1.0 - bias),\n 1.0 / clamp(uStretch, 1.0, 4.0)\n );\n float normalized = pow(stretched, 1.0 / contrast);\n float shoulder = 1.0 - pow(max(0.0, 1.0 - normalized), 1.0 + max(0.0, contrast - 1.0));\n float shoulderBlend = clamp((contrast - 1.0) * 0.32, 0.0, 0.78);\n float gradientT = mix(normalized, shoulder, shoulderBlend);\n vec4 gradientColor = texture(uGradientTexture, vec2(gradientT, 0.5));\n float alpha = gradientColor.a * clamp(uOpacity, 0.0, 1.0);\n if (alpha <= 0.0001) discard;\n outColor = vec4(gradientColor.rgb * alpha, alpha);\n}`;\n\nexport interface HeatmapWebGLRenderParams {\n width: number;\n height: number;\n positions: Float32Array;\n weights: Float32Array;\n count: number;\n kernelRadiusPx: number;\n blurRadiusPx: number;\n pointAlpha: number;\n gradient: readonly string[];\n opacity: number;\n cutoff?: number;\n gain?: number;\n gamma?: number;\n bias?: number;\n stretch?: number;\n}\n\nexport class HeatmapWebGLRenderer {\n readonly canvas: HTMLCanvasElement;\n\n private readonly gl: WebGL2RenderingContext;\n\n private readonly accumProgram: WebGLProgram;\n\n private readonly colorProgram: WebGLProgram;\n\n private readonly accumVao: WebGLVertexArrayObject;\n\n private readonly colorVao: WebGLVertexArrayObject;\n\n private readonly pointBuffer: WebGLBuffer;\n\n private readonly quadBuffer: WebGLBuffer;\n\n private readonly accumTexture: WebGLTexture;\n\n private readonly gradientTexture: WebGLTexture;\n\n private readonly framebuffer: WebGLFramebuffer;\n\n private readonly accumInternalFormat: number;\n\n private readonly accumTextureFormat: number;\n\n private readonly accumTextureType: number;\n\n private readonly uAccumResolution: WebGLUniformLocation;\n\n private readonly uAccumPointSize: WebGLUniformLocation;\n\n private readonly uAccumCoreRatio: WebGLUniformLocation;\n\n private readonly uAccumPointAlpha: WebGLUniformLocation;\n\n private readonly uColorAccumTexture: WebGLUniformLocation;\n\n private readonly uColorGradientTexture: WebGLUniformLocation;\n\n private readonly uColorOpacity: WebGLUniformLocation;\n\n private readonly uColorCutoff: WebGLUniformLocation;\n\n private readonly uColorGain: WebGLUniformLocation;\n\n private readonly uColorResolution: WebGLUniformLocation;\n\n private readonly uColorGamma: WebGLUniformLocation;\n\n private readonly uColorBias: WebGLUniformLocation;\n\n private readonly uColorStretch: WebGLUniformLocation;\n\n private pointCapacity = 0;\n\n private interleavedCapacity = 0;\n\n private interleavedBuffer: Float32Array | null = null;\n\n private gradientKey = \"\";\n\n constructor() {\n this.canvas = document.createElement(\"canvas\");\n const gl = this.canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: true,\n premultipliedAlpha: true,\n powerPreference: \"high-performance\",\n });\n if (!gl) {\n throw new Error(\"WebGL2 is not available for heatmap rendering.\");\n }\n this.gl = gl;\n\n const colorBufferFloat = gl.getExtension(\"EXT_color_buffer_float\");\n const supportsFloatAccum = Boolean(colorBufferFloat);\n this.accumInternalFormat = supportsFloatAccum ? gl.RGBA16F : gl.RGBA8;\n this.accumTextureFormat = gl.RGBA;\n this.accumTextureType = supportsFloatAccum ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;\n\n this.accumProgram = createProgram(gl, ACCUM_VERTEX_SHADER, ACCUM_FRAGMENT_SHADER);\n this.colorProgram = createProgram(gl, COLOR_VERTEX_SHADER, COLOR_FRAGMENT_SHADER);\n\n const accumVao = gl.createVertexArray();\n const colorVao = gl.createVertexArray();\n const pointBuffer = gl.createBuffer();\n const quadBuffer = gl.createBuffer();\n const accumTexture = gl.createTexture();\n const gradientTexture = gl.createTexture();\n const framebuffer = gl.createFramebuffer();\n if (!accumVao || !colorVao || !pointBuffer || !quadBuffer || !accumTexture || !gradientTexture || !framebuffer) {\n throw new Error(\"Failed to allocate heatmap WebGL resources.\");\n }\n this.accumVao = accumVao;\n this.colorVao = colorVao;\n this.pointBuffer = pointBuffer;\n this.quadBuffer = quadBuffer;\n this.accumTexture = accumTexture;\n this.gradientTexture = gradientTexture;\n this.framebuffer = framebuffer;\n\n const accumResolution = gl.getUniformLocation(this.accumProgram, \"uResolution\");\n const accumPointSize = gl.getUniformLocation(this.accumProgram, \"uPointSize\");\n const accumCoreRatio = gl.getUniformLocation(this.accumProgram, \"uCoreRatio\");\n const accumPointAlpha = gl.getUniformLocation(this.accumProgram, \"uPointAlpha\");\n const colorAccumTexture = gl.getUniformLocation(this.colorProgram, \"uAccumTexture\");\n const colorGradientTexture = gl.getUniformLocation(this.colorProgram, \"uGradientTexture\");\n const colorOpacity = gl.getUniformLocation(this.colorProgram, \"uOpacity\");\n const colorCutoff = gl.getUniformLocation(this.colorProgram, \"uCutoff\");\n const colorGain = gl.getUniformLocation(this.colorProgram, \"uGain\");\n const colorGamma = gl.getUniformLocation(this.colorProgram, \"uGamma\");\n const colorBias = gl.getUniformLocation(this.colorProgram, \"uBias\");\n const colorStretch = gl.getUniformLocation(this.colorProgram, \"uStretch\");\n const colorResolution = gl.getUniformLocation(this.colorProgram, \"uResolution\");\n if (!accumResolution || !accumPointSize || !accumCoreRatio || !accumPointAlpha || !colorAccumTexture || !colorGradientTexture || !colorOpacity || !colorCutoff || !colorGain || !colorGamma || !colorBias || !colorStretch || !colorResolution) {\n throw new Error(\"Failed to resolve heatmap WebGL uniforms.\");\n }\n this.uAccumResolution = accumResolution;\n this.uAccumPointSize = accumPointSize;\n this.uAccumCoreRatio = accumCoreRatio;\n this.uAccumPointAlpha = accumPointAlpha;\n this.uColorAccumTexture = colorAccumTexture;\n this.uColorGradientTexture = colorGradientTexture;\n this.uColorOpacity = colorOpacity;\n this.uColorCutoff = colorCutoff;\n this.uColorGain = colorGain;\n this.uColorGamma = colorGamma;\n this.uColorBias = colorBias;\n this.uColorStretch = colorStretch;\n this.uColorResolution = colorResolution;\n\n gl.bindVertexArray(this.accumVao);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n const centerLocation = gl.getAttribLocation(this.accumProgram, \"aCenter\");\n const weightLocation = gl.getAttribLocation(this.accumProgram, \"aWeight\");\n if (centerLocation < 0 || weightLocation < 0) {\n throw new Error(\"Failed to resolve heatmap WebGL attributes.\");\n }\n gl.enableVertexAttribArray(centerLocation);\n gl.vertexAttribPointer(centerLocation, 2, gl.FLOAT, false, 12, 0);\n gl.enableVertexAttribArray(weightLocation);\n gl.vertexAttribPointer(weightLocation, 1, gl.FLOAT, false, 12, 8);\n gl.bindVertexArray(null);\n\n gl.bindVertexArray(this.colorVao);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n -1, -1,\n 1, -1,\n -1, 1,\n 1, 1,\n ]), gl.STATIC_DRAW);\n const positionLocation = gl.getAttribLocation(this.colorProgram, \"aPosition\");\n if (positionLocation < 0) {\n throw new Error(\"Failed to resolve heatmap color position attribute.\");\n }\n gl.enableVertexAttribArray(positionLocation);\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 8, 0);\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n gl.bindTexture(gl.TEXTURE_2D, this.accumTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.ensureCanvasSize(1, 1);\n }\n\n render(params: HeatmapWebGLRenderParams): boolean {\n if (params.count <= 0 || params.width <= 0 || params.height <= 0) {\n return false;\n }\n\n this.ensureCanvasSize(params.width, params.height);\n this.ensureGradientTexture(params.gradient);\n this.uploadPointData(params.positions, params.weights, params.count);\n\n const gl = this.gl;\n gl.disable(gl.SCISSOR_TEST);\n gl.disable(gl.DEPTH_TEST);\n gl.disable(gl.CULL_FACE);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.viewport(0, 0, params.width, params.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(this.accumProgram);\n gl.bindVertexArray(this.accumVao);\n gl.uniform2f(this.uAccumResolution, params.width, params.height);\n gl.uniform1f(this.uAccumPointSize, Math.max(1, (params.kernelRadiusPx + params.blurRadiusPx) * 2));\n gl.uniform1f(this.uAccumCoreRatio, params.kernelRadiusPx / Math.max(1e-6, params.kernelRadiusPx + params.blurRadiusPx));\n gl.uniform1f(this.uAccumPointAlpha, Math.max(0, params.pointAlpha));\n gl.enable(gl.BLEND);\n gl.blendEquation(gl.FUNC_ADD);\n gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);\n gl.drawArrays(gl.POINTS, 0, params.count);\n gl.disable(gl.BLEND);\n gl.bindVertexArray(null);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, params.width, params.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(this.colorProgram);\n gl.bindVertexArray(this.colorVao);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.accumTexture);\n gl.uniform1i(this.uColorAccumTexture, 0);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture);\n gl.uniform1i(this.uColorGradientTexture, 1);\n gl.uniform1f(this.uColorOpacity, params.opacity);\n gl.uniform1f(this.uColorCutoff, params.cutoff ?? 0.008);\n gl.uniform1f(this.uColorGain, params.gain ?? 2.6);\n gl.uniform1f(this.uColorGamma, params.gamma ?? 1.0);\n gl.uniform1f(this.uColorBias, params.bias ?? 0);\n gl.uniform1f(this.uColorStretch, params.stretch ?? 1);\n gl.uniform2f(this.uColorResolution, params.width, params.height);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n gl.bindVertexArray(null);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.flush();\n\n return true;\n }\n\n destroy(): void {\n const gl = this.gl;\n gl.deleteTexture(this.accumTexture);\n gl.deleteTexture(this.gradientTexture);\n gl.deleteFramebuffer(this.framebuffer);\n gl.deleteBuffer(this.pointBuffer);\n gl.deleteBuffer(this.quadBuffer);\n gl.deleteVertexArray(this.accumVao);\n gl.deleteVertexArray(this.colorVao);\n gl.deleteProgram(this.accumProgram);\n gl.deleteProgram(this.colorProgram);\n this.canvas.width = 0;\n this.canvas.height = 0;\n }\n\n private ensureCanvasSize(width: number, height: number): void {\n const safeWidth = Math.max(1, Math.round(width));\n const safeHeight = Math.max(1, Math.round(height));\n if (this.canvas.width !== safeWidth) {\n this.canvas.width = safeWidth;\n }\n if (this.canvas.height !== safeHeight) {\n this.canvas.height = safeHeight;\n }\n\n const gl = this.gl;\n gl.bindTexture(gl.TEXTURE_2D, this.accumTexture);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n this.accumInternalFormat,\n safeWidth,\n safeHeight,\n 0,\n this.accumTextureFormat,\n this.accumTextureType,\n null,\n );\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.accumTexture, 0);\n const framebufferStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n if (framebufferStatus !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(`Heatmap framebuffer incomplete: ${framebufferStatus}`);\n }\n }\n\n private ensureGradientTexture(colors: readonly string[]): void {\n const nextKey = colors.join(\"|\");\n if (this.gradientKey === nextKey) return;\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = 256;\n canvas.height = 1;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n throw new Error(\"Failed to create heatmap gradient canvas.\");\n }\n\n const gradient = ctx.createLinearGradient(0, 0, 256, 0);\n const stops = colors.length > 1 ? colors : [\"#00000000\", \"#3876FF\", \"#4CDDDD\", \"#FFE75C\", \"#FF8434\", \"#FF3434\"];\n const step = 1 / Math.max(1, stops.length - 1);\n for (let index = 0; index < stops.length; index += 1) {\n gradient.addColorStop(index * step, stops[index]);\n }\n ctx.clearRect(0, 0, 256, 1);\n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, 256, 1);\n\n const pixels = ctx.getImageData(0, 0, 256, 1).data;\n const gl = this.gl;\n gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.gradientKey = nextKey;\n }\n\n private uploadPointData(positions: Float32Array, weights: Float32Array, count: number): void {\n const gl = this.gl;\n const requiredFloats = count * 3;\n const bytes = requiredFloats * 4;\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);\n if (count > this.pointCapacity) {\n gl.bufferData(gl.ARRAY_BUFFER, bytes, gl.DYNAMIC_DRAW);\n this.pointCapacity = count;\n }\n\n if (requiredFloats > this.interleavedCapacity) {\n this.interleavedCapacity = requiredFloats;\n this.interleavedBuffer = new Float32Array(requiredFloats);\n }\n const interleaved = this.interleavedBuffer;\n if (!interleaved) {\n throw new Error(\"Failed to allocate heatmap upload buffer.\");\n }\n for (let index = 0; index < count; index += 1) {\n const sourceOffset = index * 2;\n const targetOffset = index * 3;\n interleaved[targetOffset] = positions[sourceOffset] ?? 0;\n interleaved[targetOffset + 1] = positions[sourceOffset + 1] ?? 0;\n interleaved[targetOffset + 2] = weights[index] ?? 0;\n }\n gl.bufferSubData(gl.ARRAY_BUFFER, 0, interleaved.subarray(0, requiredFloats));\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n }\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport type { PreparedRoiPolygon } from \"../wsi/roi-geometry\";\nimport { pointInAnyPreparedPolygon, prepareRoiPolygons, toRoiGeometry } from \"../wsi/roi-geometry\";\nimport { createSpatialIndex, type SpatialIndex } from \"../wsi/spatial-index\";\nimport type { WsiImageSource, WsiRegion } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\nimport { tracePath } from \"./draw-layer-utils\";\nimport { HeatmapWebGLRenderer } from \"./heatmap-webgl\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport type HeatmapKernelScaleMode = \"screen\" | \"fixed-zoom\";\n\nexport interface HeatmapPointData {\n count: number;\n positions: Float32Array;\n weights?: Float32Array;\n}\n\nexport interface HeatmapLayerStats {\n pointCount: number;\n renderTimeMs: number;\n visiblePointCount: number;\n renderedBinCount: number;\n sampleStride: number;\n maxDensity: number;\n}\n\nexport interface HeatmapLayerProps {\n data: HeatmapPointData | null;\n visible?: boolean;\n opacity?: number;\n radius?: number;\n blur?: number;\n gradient?: readonly string[];\n backgroundColor?: string | null;\n scaleMode?: HeatmapKernelScaleMode;\n fixedZoom?: number;\n zoomThreshold?: number;\n densityContrast?: number;\n clipToRegions?: readonly WsiRegion[];\n zIndex?: number;\n maxRenderedPoints?: number;\n onStats?: (stats: HeatmapLayerStats) => void;\n}\n\ninterface HeatmapCell {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n worldX: number;\n worldY: number;\n renderWorldX: number;\n renderWorldY: number;\n weight: number;\n count: number;\n}\n\ninterface HeatmapLevel {\n cellWorldSize: number;\n bins: HeatmapCell[];\n index: SpatialIndex<number>;\n normalizationUpperWeight: number;\n}\n\ninterface HeatmapSourceData {\n dataRef: HeatmapPointData | null;\n sourceRef: WsiImageSource | null;\n positionsRef: Float32Array;\n weightsRef?: Float32Array;\n inputCount: number;\n clipRef: readonly PreparedRoiPolygon[] | null;\n clipKey: string;\n pointCount: number;\n xs: Float32Array;\n ys: Float32Array;\n ws: Float32Array;\n pointIndex: SpatialIndex<number>;\n cellSizes: number[];\n levels: Array<HeatmapLevel | null>;\n}\n\ninterface HeatmapFixedState {\n dataRef: HeatmapPointData | null;\n positionsRef: Float32Array;\n weightsRef?: Float32Array;\n inputCount: number;\n clipRef: readonly PreparedRoiPolygon[] | null;\n clipKey: string;\n referenceZoom: number;\n referenceRawZoom: number;\n heatmapScale: number;\n kernelWorldRadius: number;\n blurWorldRadius: number;\n sampleProbability: number;\n sampleStride: number;\n pointAlpha: number;\n}\n\ninterface HeatmapRuntime {\n sourceData: HeatmapSourceData | null;\n fixedState: HeatmapFixedState | null;\n screenLevelIndex: number;\n screenSecondaryLevelIndex: number;\n screenSecondaryLevelWeight: number;\n screenPointAlpha: number;\n screenNormalizationMaxWeight: number;\n screenVisibilityStrength: number;\n webgl: HeatmapWebGLRenderer | null | undefined;\n webglWarningIssued: boolean;\n webglPositions: Float32Array | null;\n webglWeights: Float32Array | null;\n webglCapacity: number;\n}\n\ninterface DrawState {\n data: HeatmapPointData | null;\n visible: boolean;\n opacity: number;\n radius: number;\n blur: number;\n gradient: readonly string[];\n backgroundColor: string | null;\n scaleMode: HeatmapKernelScaleMode;\n fixedZoom?: number;\n zoomThreshold: number;\n densityContrast: number;\n clipPolygons: readonly PreparedRoiPolygon[];\n clipKey: string;\n maxRenderedPoints: number;\n onStats?: (stats: HeatmapLayerStats) => void;\n}\n\ninterface ViewportFrame {\n heatmapScale: number;\n rasterWidth: number;\n rasterHeight: number;\n rasterScaleX: number;\n rasterScaleY: number;\n rawZoom: number;\n kernelRadiusPx: number;\n blurRadiusPx: number;\n outerWorldRadius: number;\n desiredCellWorldSize: number;\n}\n\nconst HEATMAP_DRAW_ID = \"__open_plant_heatmap_layer__\";\nconst DEFAULT_GRADIENT = [\"#00000000\", \"#3876FF\", \"#4CDDDD\", \"#FFE75C\", \"#FF8434\", \"#FF3434\"] as const;\nconst DEFAULT_RADIUS = 3;\nconst DEFAULT_BLUR = 2;\nconst DEFAULT_OPACITY = 0.9;\nconst DEFAULT_MAX_RENDERED_POINTS = 52000;\nconst DEFAULT_SCALE_MODE: HeatmapKernelScaleMode = \"screen\";\nconst DEFAULT_DENSITY_CONTRAST = 2.2;\nconst MIN_RASTER_SIZE = 128;\nconst MAX_RASTER_SIZE = 1600;\nconst BASE_RADIUS_UNIT_PX = 1.9;\nconst BASE_BLUR_UNIT_PX = 4.2;\nconst MIN_VISIBLE_BUDGET = 3000;\nconst PYRAMID_SCALE_STEP = Math.SQRT2;\nconst NORMALIZATION_SAMPLE_SIZE = 2048;\nconst NORMALIZATION_PERCENTILE = 0.9;\nconst MAX_DENSITY_CONTRAST = 16;\nconst MAX_ZOOM_THRESHOLD = 8;\n\nfunction resolveContinuousZoom(rawZoom: number, source: WsiImageSource): number {\n return source.maxTierZoom + Math.log2(Math.max(1e-6, rawZoom));\n}\n\nfunction resolveRawZoomFromContinuousZoom(continuousZoom: number, source: WsiImageSource): number {\n return Math.max(1e-6, 2 ** (continuousZoom - source.maxTierZoom));\n}\n\nfunction applyZoomThreshold(rawZoom: number, source: WsiImageSource, zoomThreshold: number): number {\n if (!Number.isFinite(zoomThreshold) || Math.abs(zoomThreshold) < 1e-6) {\n return Math.max(1e-6, rawZoom);\n }\n const shiftedZoom = resolveContinuousZoom(rawZoom, source) - zoomThreshold;\n return resolveRawZoomFromContinuousZoom(shiftedZoom, source);\n}\n\nfunction resolveThresholdLevelBias(zoomThreshold: number): number {\n if (!Number.isFinite(zoomThreshold) || Math.abs(zoomThreshold) < 1e-6) {\n return 0;\n }\n return Math.round((zoomThreshold * 1.5) / Math.max(1e-6, Math.log2(PYRAMID_SCALE_STEP)));\n}\n\nfunction resolveDensityWeightExponent(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n return clamp(0.55 + Math.sqrt(Math.max(0, contrast)) * 0.48, 0.55, 6);\n}\n\nfunction resolveCellSupportFactor(cellCount: number): number {\n const count = Math.max(0, cellCount);\n if (count <= 1) return 0.18;\n if (count <= 2) return 0.3;\n if (count <= 4) return 0.48;\n if (count <= 8) return 0.7;\n if (count <= 16) return 0.86;\n return 1;\n}\n\nfunction resolveDensityCutoff(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n const t = contrast / MAX_DENSITY_CONTRAST;\n return 0.022 - t * 0.015;\n}\n\nfunction resolveDensityGain(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n return 0.18 + Math.pow(Math.max(0, contrast), 0.72) * 0.42 + Math.log2(contrast + 1) * 0.24;\n}\n\nfunction resolveDensityGamma(densityContrast: number): number {\n return resolveDensityWeightExponent(densityContrast);\n}\n\nfunction resolveDensityBias(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n const t = contrast / MAX_DENSITY_CONTRAST;\n return clamp(0.46 - t * 0.34, 0.12, 0.46);\n}\n\nfunction resolveDensityStretch(densityContrast: number, rawZoom: number, source: WsiImageSource): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n const contrastT = contrast / MAX_DENSITY_CONTRAST;\n const continuousZoom = resolveContinuousZoom(rawZoom, source);\n const zoomStart = source.maxTierZoom - 3.2;\n const zoomEnd = source.maxTierZoom - 1.15;\n const zoomT = clamp((continuousZoom - zoomStart) / Math.max(1e-6, zoomEnd - zoomStart), 0, 1);\n const baseStretch = 1.12 + Math.pow(contrastT, 0.82) * 1.18;\n const zoomStretch = 1 + zoomT * (0.48 + contrastT * 0.92);\n return baseStretch * zoomStretch;\n}\n\nfunction resolveNormalizedDensityWeight(weight: number, normalizationMaxWeight: number, densityContrast: number): number {\n void densityContrast;\n const safeWeight = Math.max(0, weight);\n const safeMaxWeight = Math.max(1e-6, normalizationMaxWeight);\n const normalized = Math.log1p(safeWeight) / Math.log1p(safeMaxWeight);\n return clamp(normalized, 0, 1);\n}\n\nfunction resolveNormalizationPercentile(densityContrast: number): number {\n void densityContrast;\n return NORMALIZATION_PERCENTILE;\n}\n\nfunction resolveNormalizationUpperWeight(cells: readonly HeatmapCell[], densityContrast: number): number {\n if (cells.length === 0) return 1;\n\n const sampleCount = Math.min(cells.length, NORMALIZATION_SAMPLE_SIZE);\n const sampledWeights = new Array<number>(sampleCount);\n let maxWeight = 1;\n\n for (let sampleIndex = 0; sampleIndex < sampleCount; sampleIndex += 1) {\n const cellIndex = Math.min(\n cells.length - 1,\n Math.floor(((sampleIndex + 0.5) * cells.length) / sampleCount),\n );\n const weight = Math.max(0, cells[cellIndex]?.weight ?? 0);\n sampledWeights[sampleIndex] = weight;\n if (weight > maxWeight) maxWeight = weight;\n }\n\n for (let cellIndex = 0; cellIndex < cells.length; cellIndex += 1) {\n const weight = Math.max(0, cells[cellIndex]?.weight ?? 0);\n if (weight > maxWeight) maxWeight = weight;\n }\n\n sampledWeights.sort((left, right) => left - right);\n const percentile = resolveNormalizationPercentile(densityContrast);\n const percentileIndex = Math.max(0, Math.min(\n sampledWeights.length - 1,\n Math.floor((sampledWeights.length - 1) * percentile),\n ));\n const percentileWeight = sampledWeights[percentileIndex] ?? maxWeight;\n const floorRatio = 0.14;\n const uplift = 1.08;\n return Math.max(1, Math.min(maxWeight, Math.max(percentileWeight * uplift, maxWeight * floorRatio)));\n}\n\nfunction resolveZoomVisibilityStrength(rawZoom: number, source: WsiImageSource, zoomThreshold: number): number {\n void zoomThreshold;\n const continuousZoom = resolveContinuousZoom(rawZoom, source);\n const fadeStart = source.maxTierZoom - 2.45;\n const fadeEnd = source.maxTierZoom - 1.2;\n const baseStrength =\n continuousZoom <= fadeStart ? 1 :\n continuousZoom >= fadeEnd ? 0 :\n (() => {\n const t = clamp((continuousZoom - fadeStart) / Math.max(1e-6, fadeEnd - fadeStart), 0, 1);\n const smooth = t * t * (3 - 2 * t);\n return 1 - smooth;\n })();\n return clamp(baseStrength, 0, 1);\n}\n\nfunction resolveSampleWeightBoost(sampleProbability: number): number {\n if (sampleProbability >= 1) return 1;\n const effectiveStride = 1 / Math.max(sampleProbability, 1e-6);\n return 1 + Math.log2(effectiveStride) * 0.28;\n}\n\nfunction resolveLowResScale(width: number, height: number, totalPointCount: number, rawZoom: number): number {\n const longestSide = Math.max(1, width, height);\n const deviceScale = typeof window === \"undefined\" ? 1 : clamp(window.devicePixelRatio || 1, 1, 2.4);\n const lowZoomBoost =\n rawZoom <= 0.35 ? 1.42 :\n rawZoom <= 0.55 ? 1.26 :\n rawZoom <= 0.8 ? 1.14 :\n 1;\n const targetMaxSize =\n totalPointCount > 160000 ? 896 :\n totalPointCount > 80000 ? 1152 :\n totalPointCount > 30000 ? 1408 :\n MAX_RASTER_SIZE;\n const minScale = MIN_RASTER_SIZE / longestSide;\n const maxScale = MAX_RASTER_SIZE / longestSide;\n return clamp((targetMaxSize * deviceScale * lowZoomBoost) / longestSide, minScale, maxScale);\n}\n\nfunction buildViewportFrame(params: {\n logicalWidth: number;\n logicalHeight: number;\n totalPointCount: number;\n rawZoom: number;\n radius: number;\n blur: number;\n heatmapScale?: number;\n}): ViewportFrame {\n const heatmapScale = params.heatmapScale ?? resolveLowResScale(params.logicalWidth, params.logicalHeight, params.totalPointCount, params.rawZoom);\n const rasterWidth = Math.max(MIN_RASTER_SIZE, Math.min(MAX_RASTER_SIZE, Math.round(params.logicalWidth * heatmapScale)));\n const rasterHeight = Math.max(MIN_RASTER_SIZE, Math.min(MAX_RASTER_SIZE, Math.round(params.logicalHeight * heatmapScale)));\n const rasterScaleX = rasterWidth / Math.max(1, params.logicalWidth);\n const rasterScaleY = rasterHeight / Math.max(1, params.logicalHeight);\n const effectiveScale = Math.min(rasterScaleX, rasterScaleY);\n const rawZoom = Math.max(1e-6, params.rawZoom);\n const kernelRadiusPx = Math.max(0.75, params.radius * BASE_RADIUS_UNIT_PX * effectiveScale);\n const blurRadiusPx = Math.max(0.6, params.blur * BASE_BLUR_UNIT_PX * effectiveScale);\n const outerWorldRadius = (kernelRadiusPx + blurRadiusPx) / Math.max(1e-6, rawZoom * effectiveScale);\n const desiredCellWorldSize = Math.max(\n outerWorldRadius * 0.4,\n 0.62 / Math.max(1e-6, rawZoom * effectiveScale),\n );\n\n return {\n heatmapScale,\n rasterWidth,\n rasterHeight,\n rasterScaleX,\n rasterScaleY,\n rawZoom,\n kernelRadiusPx,\n blurRadiusPx,\n outerWorldRadius,\n desiredCellWorldSize,\n };\n}\n\nfunction resolvePointCount(data: HeatmapPointData | null): number {\n if (!data) return 0;\n const maxByPosition = Math.floor(data.positions.length / 2);\n const maxByWeight = data.weights ? data.weights.length : Number.MAX_SAFE_INTEGER;\n return Math.max(0, Math.min(Math.floor(data.count), maxByPosition, maxByWeight));\n}\n\nfunction hashCoordinate(value: number, seed: number): number {\n const normalized = Number.isFinite(value) ? Math.round(value * 1024) : 0;\n return Math.imul(seed ^ normalized, 0x45d9f3b) >>> 0;\n}\n\nfunction hashIntPair(x: number, y: number, seed = 0x9e3779b9): number {\n let hash = Math.imul(seed ^ (x | 0), 0x85ebca6b) >>> 0;\n hash = Math.imul(hash ^ (y | 0), 0xc2b2ae35) >>> 0;\n hash ^= hash >>> 16;\n return hash >>> 0;\n}\n\nfunction hashToUnitFloat(hash: number): number {\n return (hash >>> 0) / 0xffffffff;\n}\n\nfunction resolveJitteredCoordinate(\n center: number,\n min: number,\n max: number,\n jitterUnit: number,\n paddingFraction: number,\n jitterFraction: number,\n): number {\n const span = Math.max(1e-6, max - min);\n const padding = Math.min(span * clamp(paddingFraction, 0.12, 0.32), span * 0.5 - 1e-6);\n const jitterRange = Math.max(0, span * clamp(jitterFraction, 0.01, 0.22) - padding * 0.15);\n const jitter = (jitterUnit * 2 - 1) * jitterRange;\n return clamp(center + jitter, min + padding, max - padding);\n}\n\nfunction buildClipKey(polygons: readonly PreparedRoiPolygon[]): string {\n let hash = 0x811c9dc5;\n for (let polygonIndex = 0; polygonIndex < polygons.length; polygonIndex += 1) {\n const polygon = polygons[polygonIndex]!;\n hash = Math.imul(hash ^ polygon.outer.length, 0x01000193) >>> 0;\n for (let pointIndex = 0; pointIndex < polygon.outer.length; pointIndex += 1) {\n const point = polygon.outer[pointIndex]!;\n hash = hashCoordinate(point[0], hash);\n hash = hashCoordinate(point[1], hash);\n }\n hash = Math.imul(hash ^ polygon.holes.length, 0x01000193) >>> 0;\n for (let holeIndex = 0; holeIndex < polygon.holes.length; holeIndex += 1) {\n const hole = polygon.holes[holeIndex]!;\n hash = Math.imul(hash ^ hole.length, 0x01000193) >>> 0;\n for (let pointIndex = 0; pointIndex < hole.length; pointIndex += 1) {\n const point = hole[pointIndex]!;\n hash = hashCoordinate(point[0], hash);\n hash = hashCoordinate(point[1], hash);\n }\n }\n }\n return `${polygons.length}:${hash >>> 0}`;\n}\n\nfunction isSameHeatmapInput(\n input: Pick<HeatmapSourceData, \"dataRef\" | \"positionsRef\" | \"weightsRef\" | \"inputCount\" | \"clipKey\"> | Pick<HeatmapFixedState, \"dataRef\" | \"positionsRef\" | \"weightsRef\" | \"inputCount\" | \"clipKey\">,\n data: HeatmapPointData | null,\n clipKey: string,\n): boolean {\n if (input.dataRef === data && input.clipKey === clipKey) {\n return true;\n }\n if (!data) return false;\n return input.clipKey === clipKey &&\n input.inputCount === resolvePointCount(data) &&\n input.positionsRef === data.positions &&\n input.weightsRef === data.weights;\n}\n\nfunction buildSourceData(data: HeatmapPointData | null, clipPolygons: readonly PreparedRoiPolygon[], clipKey: string, source: WsiImageSource | null): HeatmapSourceData | null {\n const pointCount = resolvePointCount(data);\n if (!data || pointCount <= 0) {\n return null;\n }\n\n let xs = new Float32Array(pointCount);\n let ys = new Float32Array(pointCount);\n let ws = new Float32Array(pointCount);\n let acceptedCount = 0;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (let index = 0; index < pointCount; index += 1) {\n const worldX = data.positions[index * 2];\n const worldY = data.positions[index * 2 + 1];\n if (!Number.isFinite(worldX) || !Number.isFinite(worldY)) continue;\n if (clipPolygons.length > 0 && !pointInAnyPreparedPolygon(worldX, worldY, clipPolygons)) continue;\n\n const rawWeight = data.weights?.[index];\n const weight = typeof rawWeight === \"number\" && Number.isFinite(rawWeight) ? Math.max(0, rawWeight) : 1;\n if (weight <= 0) continue;\n\n xs[acceptedCount] = worldX;\n ys[acceptedCount] = worldY;\n ws[acceptedCount] = weight;\n acceptedCount += 1;\n if (worldX < minX) minX = worldX;\n if (worldX > maxX) maxX = worldX;\n if (worldY < minY) minY = worldY;\n if (worldY > maxY) maxY = worldY;\n }\n\n if (acceptedCount === 0 || !Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {\n return null;\n }\n\n if (acceptedCount < pointCount) {\n xs = xs.slice(0, acceptedCount);\n ys = ys.slice(0, acceptedCount);\n ws = ws.slice(0, acceptedCount);\n }\n\n const pointIndexItems: Array<{ minX: number; minY: number; maxX: number; maxY: number; value: number }> = [];\n for (let index = 0; index < acceptedCount; index += 1) {\n const x = xs[index]!;\n const y = ys[index]!;\n pointIndexItems.push({\n minX: x,\n minY: y,\n maxX: x,\n maxY: y,\n value: index,\n });\n }\n const pointIndex = createSpatialIndex<number>(64);\n pointIndex.load(pointIndexItems);\n\n const maxDimension = Math.max(\n source?.width ?? 0,\n source?.height ?? 0,\n maxX - minX,\n maxY - minY,\n 1,\n );\n\n const cellSizes: number[] = [];\n let cellSize = 0.5;\n let guard = 0;\n while (cellSize <= maxDimension && guard < 32) {\n cellSizes.push(cellSize);\n cellSize *= PYRAMID_SCALE_STEP;\n guard += 1;\n }\n if (cellSizes.length === 0) {\n cellSizes.push(1);\n }\n\n return {\n dataRef: data,\n sourceRef: source,\n positionsRef: data.positions,\n weightsRef: data.weights,\n inputCount: pointCount,\n clipRef: clipPolygons,\n clipKey,\n pointCount: acceptedCount,\n xs,\n ys,\n ws,\n pointIndex,\n cellSizes,\n levels: Array.from({ length: cellSizes.length }, () => null),\n };\n}\n\nfunction estimateVisibleBinCount(viewBounds: [number, number, number, number], cellWorldSize: number): number {\n const width = Math.max(1, viewBounds[2] - viewBounds[0]);\n const height = Math.max(1, viewBounds[3] - viewBounds[1]);\n return Math.max(1, Math.round((width * height) / Math.max(1e-6, cellWorldSize * cellWorldSize)));\n}\n\nfunction buildLevel(sourceData: HeatmapSourceData, levelIndex: number): HeatmapLevel | null {\n if (levelIndex < 0 || levelIndex >= sourceData.cellSizes.length) return null;\n const cachedLevel = sourceData.levels[levelIndex];\n if (cachedLevel) return cachedLevel;\n\n const currentCellSize = sourceData.cellSizes[levelIndex];\n const levelT = sourceData.cellSizes.length <= 1 ? 0 : levelIndex / (sourceData.cellSizes.length - 1);\n const adaptivePaddingFraction = 0.24 - levelT * 0.08;\n const adaptiveJitterFraction = 0.035 + levelT * 0.11;\n const cells = new Map<string, {\n cellX: number;\n cellY: number;\n sumX: number;\n sumY: number;\n weight: number;\n count: number;\n }>();\n\n for (let pointIndex = 0; pointIndex < sourceData.pointCount; pointIndex += 1) {\n const worldX = sourceData.xs[pointIndex]!;\n const worldY = sourceData.ys[pointIndex]!;\n const weight = sourceData.ws[pointIndex]!;\n const cellX = Math.floor(worldX / currentCellSize);\n const cellY = Math.floor(worldY / currentCellSize);\n const key = `${cellX}:${cellY}`;\n const existing = cells.get(key);\n if (existing) {\n existing.sumX += worldX * weight;\n existing.sumY += worldY * weight;\n existing.weight += weight;\n existing.count += 1;\n } else {\n cells.set(key, {\n cellX,\n cellY,\n sumX: worldX * weight,\n sumY: worldY * weight,\n weight,\n count: 1,\n });\n }\n }\n\n const bins: HeatmapCell[] = [];\n const items: Array<{ minX: number; minY: number; maxX: number; maxY: number; value: number }> = [];\n cells.forEach(cell => {\n if (cell.weight <= 0) return;\n const cellMinX = cell.cellX * currentCellSize;\n const cellMinY = cell.cellY * currentCellSize;\n const centerX = cell.sumX / cell.weight;\n const centerY = cell.sumY / cell.weight;\n const jitterSeed = hashIntPair(cell.cellX, cell.cellY, Math.round(currentCellSize * 1024));\n const bin: HeatmapCell = {\n minX: cellMinX,\n minY: cellMinY,\n maxX: cellMinX + currentCellSize,\n maxY: cellMinY + currentCellSize,\n worldX: centerX,\n worldY: centerY,\n renderWorldX: resolveJitteredCoordinate(\n centerX,\n cellMinX,\n cellMinX + currentCellSize,\n hashToUnitFloat(jitterSeed),\n adaptivePaddingFraction,\n adaptiveJitterFraction,\n ),\n renderWorldY: resolveJitteredCoordinate(\n centerY,\n cellMinY,\n cellMinY + currentCellSize,\n hashToUnitFloat(hashIntPair(cell.cellY, cell.cellX, jitterSeed ^ 0x68bc21eb)),\n adaptivePaddingFraction,\n adaptiveJitterFraction,\n ),\n weight: cell.weight,\n count: cell.count,\n };\n const value = bins.length;\n bins.push(bin);\n items.push({\n minX: bin.minX,\n minY: bin.minY,\n maxX: bin.maxX,\n maxY: bin.maxY,\n value,\n });\n });\n\n const index = createSpatialIndex<number>(32);\n index.load(items);\n const level = {\n cellWorldSize: currentCellSize,\n bins,\n index,\n normalizationUpperWeight: resolveNormalizationUpperWeight(bins, 1),\n };\n sourceData.levels[levelIndex] = level;\n return level;\n}\n\nfunction findLevelIndex(cellSizes: readonly number[], desiredCellWorldSize: number, previousIndex: number): number {\n if (cellSizes.length === 0) return 0;\n\n if (previousIndex >= 0 && previousIndex < cellSizes.length) {\n const previousCellSize = cellSizes[previousIndex]!;\n if (desiredCellWorldSize >= previousCellSize * 0.52 && desiredCellWorldSize <= previousCellSize * 2.1) {\n return previousIndex;\n }\n }\n\n let bestIndex = 0;\n let bestDistance = Infinity;\n const desiredLog = Math.log2(Math.max(1e-6, desiredCellWorldSize));\n\n for (let index = 0; index < cellSizes.length; index += 1) {\n const distance = Math.abs(Math.log2(cellSizes[index]!) - desiredLog);\n if (distance >= bestDistance) continue;\n bestDistance = distance;\n bestIndex = index;\n }\n return bestIndex;\n}\n\nfunction resolveLevelIndex(params: {\n cellSizes: readonly number[];\n desiredCellWorldSize: number;\n zoomThreshold: number;\n maxRenderedPoints: number;\n viewBounds: [number, number, number, number];\n previousIndex: number;\n}): number {\n const { cellSizes, desiredCellWorldSize, zoomThreshold, maxRenderedPoints, viewBounds, previousIndex } = params;\n let index = findLevelIndex(cellSizes, desiredCellWorldSize, previousIndex);\n const budget = Math.max(MIN_VISIBLE_BUDGET, maxRenderedPoints);\n while (index < cellSizes.length - 1 && estimateVisibleBinCount(viewBounds, cellSizes[index]!) > budget * 1.28) {\n index += 1;\n }\n while (index > 0 && estimateVisibleBinCount(viewBounds, cellSizes[index - 1]!) <= budget * 0.76) {\n index -= 1;\n }\n return Math.max(0, Math.min(cellSizes.length - 1, index + resolveThresholdLevelBias(zoomThreshold)));\n}\n\nfunction resolveScreenLevelBlend(params: {\n cellSizes: readonly number[];\n desiredCellWorldSize: number;\n zoomThreshold: number;\n maxRenderedPoints: number;\n viewBounds: [number, number, number, number];\n}): { lowerIndex: number; upperIndex: number; upperWeight: number } {\n const { cellSizes, desiredCellWorldSize, zoomThreshold, maxRenderedPoints, viewBounds } = params;\n if (cellSizes.length === 0) {\n return { lowerIndex: 0, upperIndex: 0, upperWeight: 0 };\n }\n\n const stepLog = Math.log2(PYRAMID_SCALE_STEP);\n const firstCellLog = Math.log2(Math.max(1e-6, cellSizes[0]!));\n let desiredPosition =\n (Math.log2(Math.max(1e-6, desiredCellWorldSize)) - firstCellLog) / Math.max(1e-6, stepLog) +\n resolveThresholdLevelBias(zoomThreshold);\n\n const budget = Math.max(MIN_VISIBLE_BUDGET, maxRenderedPoints);\n let minimumBudgetIndex = 0;\n while (\n minimumBudgetIndex < cellSizes.length - 1 &&\n estimateVisibleBinCount(viewBounds, cellSizes[minimumBudgetIndex]!) > budget * 1.12\n ) {\n minimumBudgetIndex += 1;\n }\n\n desiredPosition = clamp(desiredPosition, minimumBudgetIndex, cellSizes.length - 1);\n const lowerIndex = Math.floor(desiredPosition);\n const upperIndex = Math.min(cellSizes.length - 1, Math.ceil(desiredPosition));\n const upperWeight = upperIndex === lowerIndex ? 0 : desiredPosition - lowerIndex;\n return { lowerIndex, upperIndex, upperWeight };\n}\n\nfunction collectVisibleCells(level: HeatmapLevel, viewBounds: [number, number, number, number], outerWorldRadius: number): HeatmapCell[] {\n const hits = level.index.search([\n viewBounds[0] - outerWorldRadius,\n viewBounds[1] - outerWorldRadius,\n viewBounds[2] + outerWorldRadius,\n viewBounds[3] + outerWorldRadius,\n ]);\n const visible: HeatmapCell[] = [];\n for (let index = 0; index < hits.length; index += 1) {\n const hit = hits[index];\n if (!hit) continue;\n const cell = level.bins[hit.value];\n if (!cell) continue;\n visible.push(cell);\n }\n return visible;\n}\n\nfunction collectVisiblePointIndices(sourceData: HeatmapSourceData, viewBounds: [number, number, number, number], outerWorldRadius: number): number[] {\n const hits = sourceData.pointIndex.search([\n viewBounds[0] - outerWorldRadius,\n viewBounds[1] - outerWorldRadius,\n viewBounds[2] + outerWorldRadius,\n viewBounds[3] + outerWorldRadius,\n ]);\n const visible = new Array<number>(hits.length);\n let count = 0;\n for (let index = 0; index < hits.length; index += 1) {\n const hit = hits[index];\n if (!hit) continue;\n visible[count] = hit.value;\n count += 1;\n }\n visible.length = count;\n return visible;\n}\n\nfunction resolveSampleProbability(visiblePointCount: number, maxRenderedPoints: number): number {\n const budget = Math.max(MIN_VISIBLE_BUDGET, maxRenderedPoints);\n if (visiblePointCount <= budget) return 1;\n return clamp(budget / Math.max(1, visiblePointCount), 1 / 65536, 1);\n}\n\nfunction resolveSampleStride(sampleProbability: number): number {\n if (sampleProbability >= 1) return 1;\n return Math.max(1, Math.round(1 / Math.max(1e-6, sampleProbability)));\n}\n\nfunction shouldKeepSample(pointIndex: number, sampleProbability: number): boolean {\n if (sampleProbability >= 1) return true;\n const sampleHash = hashIntPair(pointIndex, 0x51ed270b, 0x68bc21eb);\n return hashToUnitFloat(sampleHash) <= clamp(sampleProbability, 0, 1);\n}\n\nfunction resolvePointAlpha(binCount: number, kernelOuterRadiusPx: number, rasterWidth: number, rasterHeight: number): number {\n const rasterArea = Math.max(1, rasterWidth * rasterHeight);\n const kernelArea = Math.PI * kernelOuterRadiusPx * kernelOuterRadiusPx;\n const coverage = (Math.max(1, binCount) * kernelArea) / rasterArea;\n return clamp(0.085 / Math.sqrt(Math.max(1, coverage)), 0.012, 0.075);\n}\n\nfunction smoothHeatmapValue(previousValue: number, nextValue: number, riseFactor: number, fallFactor: number): number {\n if (!Number.isFinite(previousValue) || previousValue <= 0) {\n return nextValue;\n }\n const factor = nextValue >= previousValue ? riseFactor : fallFactor;\n return previousValue + (nextValue - previousValue) * clamp(factor, 0, 1);\n}\n\nfunction shouldFreezeScreenHeatmapAtMinZoom(\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>,\n rawZoom: number,\n): boolean {\n if (!renderer.isViewAnimating()) return false;\n const zoomRange = renderer.getZoomRange();\n const minZoom = Math.max(1e-6, zoomRange.minZoom);\n return rawZoom <= minZoom * 1.075;\n}\n\nfunction getWebglRenderer(runtime: HeatmapRuntime): HeatmapWebGLRenderer | null {\n if (runtime.webgl !== undefined) {\n return runtime.webgl;\n }\n if (typeof document === \"undefined\") {\n runtime.webgl = null;\n return null;\n }\n try {\n runtime.webgl = new HeatmapWebGLRenderer();\n } catch (error) {\n if (!runtime.webglWarningIssued && typeof console !== \"undefined\" && typeof console.warn === \"function\") {\n const reason = error instanceof Error ? error.message : String(error);\n console.warn(`[open-plant] HeatmapLayer disabled because WebGL2 heatmap initialization failed: ${reason}`);\n runtime.webglWarningIssued = true;\n }\n runtime.webgl = null;\n }\n return runtime.webgl;\n}\n\nfunction projectClipRing(renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>, ring: readonly [number, number][]): [number, number][] {\n const out: [number, number][] = [];\n for (let index = 0; index < ring.length; index += 1) {\n const point = ring[index];\n if (!point) continue;\n const projected = renderer.worldToScreen(point[0], point[1]);\n if (!Array.isArray(projected) || projected.length < 2) continue;\n const x = Number(projected[0]);\n const y = Number(projected[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n out.push([x, y]);\n }\n return out;\n}\n\nfunction applyClipPath(ctx: CanvasRenderingContext2D, renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>, polygons: readonly PreparedRoiPolygon[]): void {\n if (polygons.length === 0) return;\n ctx.beginPath();\n for (let index = 0; index < polygons.length; index += 1) {\n const polygon = polygons[index]!;\n const outer = projectClipRing(renderer, polygon.outer);\n if (outer.length >= 3) {\n tracePath(ctx, outer, true);\n }\n for (let holeIndex = 0; holeIndex < polygon.holes.length; holeIndex += 1) {\n const hole = projectClipRing(renderer, polygon.holes[holeIndex]!);\n if (hole.length >= 3) {\n tracePath(ctx, hole, true);\n }\n }\n }\n ctx.clip(\"evenodd\");\n}\n\nfunction ensureSourceData(runtime: HeatmapRuntime, data: HeatmapPointData | null, clipPolygons: readonly PreparedRoiPolygon[], clipKey: string, source: WsiImageSource | null): HeatmapSourceData | null {\n const current = runtime.sourceData;\n if (current && current.sourceRef === source && isSameHeatmapInput(current, data, clipKey)) {\n return current;\n }\n runtime.sourceData = buildSourceData(data, clipPolygons, clipKey, source);\n runtime.fixedState = null;\n runtime.screenLevelIndex = -1;\n return runtime.sourceData;\n}\n\nfunction buildFixedState(params: {\n runtime: HeatmapRuntime;\n sourceData: HeatmapSourceData;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n radius: number;\n blur: number;\n fixedZoom?: number;\n zoomThreshold: number;\n densityContrast: number;\n maxRenderedPoints: number;\n}): HeatmapFixedState | null {\n const { sourceData, renderer, source, logicalWidth, logicalHeight, radius, blur, fixedZoom, maxRenderedPoints } = params;\n\n const currentRawZoom = Math.max(1e-6, renderer.getViewState().zoom);\n const referenceZoom = fixedZoom ?? resolveContinuousZoom(currentRawZoom, source);\n const referenceRawZoom = resolveRawZoomFromContinuousZoom(referenceZoom, source);\n const frame = buildViewportFrame({\n logicalWidth,\n logicalHeight,\n totalPointCount: sourceData.pointCount,\n rawZoom: referenceRawZoom,\n radius,\n blur,\n });\n const viewBounds = renderer.getViewBounds();\n const visiblePointIndices = collectVisiblePointIndices(sourceData, viewBounds, frame.outerWorldRadius);\n const sampleProbability = resolveSampleProbability(visiblePointIndices.length, maxRenderedPoints);\n const sampleStride = resolveSampleStride(sampleProbability);\n const effectiveScale = Math.min(frame.rasterScaleX, frame.rasterScaleY);\n\n return {\n dataRef: sourceData.dataRef,\n positionsRef: sourceData.positionsRef,\n weightsRef: sourceData.weightsRef,\n inputCount: sourceData.inputCount,\n clipRef: sourceData.clipRef,\n clipKey: sourceData.clipKey,\n referenceZoom,\n referenceRawZoom,\n heatmapScale: frame.heatmapScale,\n kernelWorldRadius: frame.kernelRadiusPx / Math.max(1e-6, referenceRawZoom * effectiveScale),\n blurWorldRadius: frame.blurRadiusPx / Math.max(1e-6, referenceRawZoom * effectiveScale),\n sampleProbability,\n sampleStride,\n pointAlpha: resolvePointAlpha(visiblePointIndices.length, frame.kernelRadiusPx + frame.blurRadiusPx, frame.rasterWidth, frame.rasterHeight),\n };\n}\n\nfunction drawHeatmapWebgl(params: {\n ctx: CanvasRenderingContext2D;\n runtime: HeatmapRuntime;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n frame: ViewportFrame;\n cells: readonly HeatmapCell[];\n normalizationMaxWeight: number;\n pointAlpha: number;\n gradient: readonly string[];\n opacity: number;\n densityContrast: number;\n backgroundColor: string | null;\n clipPolygons: readonly PreparedRoiPolygon[];\n}): number {\n const { ctx, runtime, renderer, logicalWidth, logicalHeight, frame, cells, normalizationMaxWeight, pointAlpha, gradient, opacity, densityContrast, backgroundColor, clipPolygons } = params;\n const { source } = params;\n const webgl = getWebglRenderer(runtime);\n if (!webgl || cells.length === 0) {\n return 0;\n }\n\n if (cells.length > runtime.webglCapacity) {\n runtime.webglCapacity = cells.length;\n runtime.webglPositions = new Float32Array(cells.length * 2);\n runtime.webglWeights = new Float32Array(cells.length);\n }\n const positions = runtime.webglPositions;\n const weights = runtime.webglWeights;\n if (!positions || !weights) {\n return 0;\n }\n\n const outerRadiusPx = frame.kernelRadiusPx + frame.blurRadiusPx;\n let drawCount = 0;\n\n for (let index = 0; index < cells.length; index += 1) {\n const cell = cells[index]!;\n const projected = renderer.worldToScreen(cell.renderWorldX, cell.renderWorldY);\n if (!Array.isArray(projected) || projected.length < 2) continue;\n\n const screenX = Number(projected[0]);\n const screenY = Number(projected[1]);\n if (!Number.isFinite(screenX) || !Number.isFinite(screenY)) continue;\n\n const rasterX = screenX * frame.rasterScaleX;\n const rasterY = screenY * frame.rasterScaleY;\n if (\n rasterX < -outerRadiusPx ||\n rasterY < -outerRadiusPx ||\n rasterX > frame.rasterWidth + outerRadiusPx ||\n rasterY > frame.rasterHeight + outerRadiusPx\n ) {\n continue;\n }\n\n const offset = drawCount * 2;\n const supportFactor = resolveCellSupportFactor(cell.count);\n const normalizedWeight = resolveNormalizedDensityWeight(cell.weight, normalizationMaxWeight, densityContrast);\n const effectiveWeight = normalizedWeight * supportFactor;\n if (effectiveWeight <= 0.025) continue;\n\n positions[offset] = rasterX;\n positions[offset + 1] = rasterY;\n weights[drawCount] = effectiveWeight;\n drawCount += 1;\n }\n\n if (drawCount <= 0) {\n return 0;\n }\n\n const rendered = webgl.render({\n width: frame.rasterWidth,\n height: frame.rasterHeight,\n positions,\n weights,\n count: drawCount,\n kernelRadiusPx: frame.kernelRadiusPx,\n blurRadiusPx: frame.blurRadiusPx,\n pointAlpha,\n gradient,\n opacity,\n cutoff: resolveDensityCutoff(densityContrast),\n gain: resolveDensityGain(densityContrast),\n gamma: resolveDensityGamma(densityContrast),\n bias: resolveDensityBias(densityContrast),\n stretch: resolveDensityStretch(densityContrast, frame.rawZoom, source),\n });\n if (!rendered) {\n return 0;\n }\n\n ctx.save();\n if (clipPolygons.length > 0) {\n applyClipPath(ctx, renderer, clipPolygons);\n }\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, logicalWidth, logicalHeight);\n }\n ctx.globalAlpha = 1;\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(webgl.canvas, 0, 0, frame.rasterWidth, frame.rasterHeight, 0, 0, logicalWidth, logicalHeight);\n ctx.restore();\n\n return drawCount;\n}\n\nfunction drawHeatmapWebglPoints(params: {\n ctx: CanvasRenderingContext2D;\n runtime: HeatmapRuntime;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n frame: ViewportFrame;\n sourceData: HeatmapSourceData;\n visiblePointIndices: readonly number[];\n sampleProbability: number;\n sampleStride: number;\n pointAlpha: number;\n gradient: readonly string[];\n opacity: number;\n densityContrast: number;\n backgroundColor: string | null;\n clipPolygons: readonly PreparedRoiPolygon[];\n}): number {\n const {\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n frame,\n sourceData,\n visiblePointIndices,\n sampleProbability,\n sampleStride,\n pointAlpha,\n gradient,\n opacity,\n densityContrast,\n backgroundColor,\n clipPolygons,\n } = params;\n const webgl = getWebglRenderer(runtime);\n if (!webgl || visiblePointIndices.length === 0) {\n return 0;\n }\n\n const targetCapacity = Math.min(\n visiblePointIndices.length,\n Math.max(64, Math.ceil(visiblePointIndices.length * Math.min(1, sampleProbability * 1.15))),\n );\n if (targetCapacity > runtime.webglCapacity) {\n runtime.webglCapacity = targetCapacity;\n runtime.webglPositions = new Float32Array(targetCapacity * 2);\n runtime.webglWeights = new Float32Array(targetCapacity);\n }\n const positions = runtime.webglPositions;\n const weights = runtime.webglWeights;\n if (!positions || !weights) {\n return 0;\n }\n\n const outerRadiusPx = frame.kernelRadiusPx + frame.blurRadiusPx;\n const sampleWeightBoost = resolveSampleWeightBoost(sampleProbability);\n let drawCount = 0;\n\n for (let visibleIndex = 0; visibleIndex < visiblePointIndices.length; visibleIndex += 1) {\n const pointIndex = visiblePointIndices[visibleIndex]!;\n if (!shouldKeepSample(pointIndex, sampleProbability)) continue;\n\n const worldX = sourceData.xs[pointIndex];\n const worldY = sourceData.ys[pointIndex];\n if (!Number.isFinite(worldX) || !Number.isFinite(worldY)) continue;\n\n const projected = renderer.worldToScreen(worldX, worldY);\n if (!Array.isArray(projected) || projected.length < 2) continue;\n\n const screenX = Number(projected[0]);\n const screenY = Number(projected[1]);\n if (!Number.isFinite(screenX) || !Number.isFinite(screenY)) continue;\n\n const rasterX = screenX * frame.rasterScaleX;\n const rasterY = screenY * frame.rasterScaleY;\n if (\n rasterX < -outerRadiusPx ||\n rasterY < -outerRadiusPx ||\n rasterX > frame.rasterWidth + outerRadiusPx ||\n rasterY > frame.rasterHeight + outerRadiusPx\n ) {\n continue;\n }\n\n const offset = drawCount * 2;\n positions[offset] = rasterX;\n positions[offset + 1] = rasterY;\n weights[drawCount] = Math.max(0, (sourceData.ws[pointIndex] ?? 0) * sampleWeightBoost);\n drawCount += 1;\n }\n\n if (drawCount <= 0) {\n return 0;\n }\n\n const rendered = webgl.render({\n width: frame.rasterWidth,\n height: frame.rasterHeight,\n positions,\n weights,\n count: drawCount,\n kernelRadiusPx: frame.kernelRadiusPx,\n blurRadiusPx: frame.blurRadiusPx,\n pointAlpha,\n gradient,\n opacity,\n cutoff: resolveDensityCutoff(densityContrast),\n gain: resolveDensityGain(densityContrast),\n gamma: resolveDensityGamma(densityContrast),\n bias: resolveDensityBias(densityContrast),\n stretch: resolveDensityStretch(densityContrast, frame.rawZoom, source),\n });\n if (!rendered) {\n return 0;\n }\n\n ctx.save();\n if (clipPolygons.length > 0) {\n applyClipPath(ctx, renderer, clipPolygons);\n }\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, logicalWidth, logicalHeight);\n }\n ctx.globalAlpha = 1;\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(webgl.canvas, 0, 0, frame.rasterWidth, frame.rasterHeight, 0, 0, logicalWidth, logicalHeight);\n ctx.restore();\n\n return drawCount;\n}\n\nfunction drawHeatmap(params: {\n ctx: CanvasRenderingContext2D;\n runtime: HeatmapRuntime;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n state: DrawState;\n}): HeatmapLayerStats | null {\n const { ctx, runtime, renderer, source, logicalWidth, logicalHeight, state } = params;\n const sourceData = ensureSourceData(runtime, state.data, state.clipPolygons, state.clipKey, source);\n if (!sourceData || sourceData.cellSizes.length === 0 || sourceData.pointCount <= 0) {\n return null;\n }\n\n const rawZoom = Math.max(1e-6, renderer.getViewState().zoom);\n const zoomVisibilityStrength = resolveZoomVisibilityStrength(rawZoom, source, state.zoomThreshold);\n const viewBounds = renderer.getViewBounds();\n if (zoomVisibilityStrength <= 0.001) {\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: 0,\n renderedBinCount: 0,\n sampleStride: 1,\n maxDensity: 0,\n };\n }\n\n if (state.scaleMode !== \"fixed-zoom\") {\n const frame = buildViewportFrame({\n logicalWidth,\n logicalHeight,\n totalPointCount: sourceData.pointCount,\n rawZoom,\n radius: state.radius,\n blur: state.blur,\n });\n const visiblePointIndices = collectVisiblePointIndices(sourceData, viewBounds, frame.outerWorldRadius);\n if (visiblePointIndices.length === 0) {\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: 0,\n renderedBinCount: 0,\n sampleStride: 1,\n maxDensity: 0,\n };\n }\n\n const sampleProbability = resolveSampleProbability(visiblePointIndices.length, state.maxRenderedPoints);\n const sampleStride = resolveSampleStride(sampleProbability);\n const targetPointAlpha = resolvePointAlpha(\n visiblePointIndices.length,\n frame.kernelRadiusPx + frame.blurRadiusPx,\n frame.rasterWidth,\n frame.rasterHeight,\n );\n runtime.screenLevelIndex = -1;\n runtime.screenSecondaryLevelIndex = -1;\n runtime.screenSecondaryLevelWeight = 0;\n runtime.screenNormalizationMaxWeight = 1;\n runtime.screenPointAlpha = smoothHeatmapValue(runtime.screenPointAlpha, targetPointAlpha, 0.12, 0.08);\n runtime.screenVisibilityStrength = renderer.isViewAnimating()\n ? smoothHeatmapValue(runtime.screenVisibilityStrength, zoomVisibilityStrength, 0.16, 0.12)\n : zoomVisibilityStrength;\n\n const renderedPointCount = drawHeatmapWebglPoints({\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n frame,\n sourceData,\n visiblePointIndices,\n sampleProbability,\n sampleStride,\n pointAlpha: runtime.screenPointAlpha * Math.max(0.08, runtime.screenVisibilityStrength),\n gradient: state.gradient,\n opacity: state.opacity * runtime.screenVisibilityStrength,\n densityContrast: state.densityContrast,\n backgroundColor: state.backgroundColor,\n clipPolygons: state.clipPolygons,\n });\n\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: visiblePointIndices.length,\n renderedBinCount: renderedPointCount,\n sampleStride,\n maxDensity: Math.round(runtime.screenPointAlpha * 255),\n };\n }\n\n const fixedState = runtime.fixedState;\n if (!fixedState) return null;\n\n const frame = buildViewportFrame({\n logicalWidth,\n logicalHeight,\n totalPointCount: sourceData.pointCount,\n rawZoom,\n radius: state.radius,\n blur: state.blur,\n heatmapScale: fixedState.heatmapScale,\n });\n const effectiveScale = Math.min(frame.rasterScaleX, frame.rasterScaleY);\n frame.kernelRadiusPx = Math.max(0.75, fixedState.kernelWorldRadius * rawZoom * effectiveScale);\n frame.blurRadiusPx = Math.max(0.6, fixedState.blurWorldRadius * rawZoom * effectiveScale);\n frame.outerWorldRadius = fixedState.kernelWorldRadius + fixedState.blurWorldRadius;\n\n const visiblePointIndices = collectVisiblePointIndices(sourceData, viewBounds, frame.outerWorldRadius);\n if (visiblePointIndices.length === 0) {\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: 0,\n renderedBinCount: 0,\n sampleStride: 1,\n maxDensity: 0,\n };\n }\n\n runtime.screenPointAlpha = fixedState.pointAlpha;\n runtime.screenVisibilityStrength = zoomVisibilityStrength;\n\n const renderedPointCount = drawHeatmapWebglPoints({\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n frame,\n sourceData,\n visiblePointIndices,\n sampleProbability: fixedState.sampleProbability,\n sampleStride: fixedState.sampleStride,\n pointAlpha: fixedState.pointAlpha * Math.max(0.08, zoomVisibilityStrength),\n gradient: state.gradient,\n opacity: state.opacity * zoomVisibilityStrength,\n densityContrast: state.densityContrast,\n backgroundColor: state.backgroundColor,\n clipPolygons: state.clipPolygons,\n });\n\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: visiblePointIndices.length,\n renderedBinCount: renderedPointCount,\n sampleStride: fixedState.sampleStride,\n maxDensity: Math.round(fixedState.pointAlpha * 255),\n };\n}\n\nexport function HeatmapLayer({\n data,\n visible = true,\n opacity = DEFAULT_OPACITY,\n radius = DEFAULT_RADIUS,\n blur = DEFAULT_BLUR,\n gradient = DEFAULT_GRADIENT,\n backgroundColor = null,\n scaleMode = DEFAULT_SCALE_MODE,\n fixedZoom,\n zoomThreshold = 0,\n densityContrast = DEFAULT_DENSITY_CONTRAST,\n clipToRegions,\n zIndex = 5,\n maxRenderedPoints = DEFAULT_MAX_RENDERED_POINTS,\n onStats,\n}: HeatmapLayerProps): null {\n const { rendererRef, source, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw } = useViewerContext();\n\n const clipPolygons = useMemo(() => {\n const geometries = (clipToRegions ?? [])\n .map(region => toRoiGeometry(region?.coordinates))\n .filter((geometry): geometry is NonNullable<typeof geometry> => geometry != null);\n return prepareRoiPolygons(geometries);\n }, [clipToRegions]);\n const clipKey = useMemo(() => buildClipKey(clipPolygons), [clipPolygons]);\n\n const runtimeRef = useRef<HeatmapRuntime>({\n sourceData: null,\n fixedState: null,\n screenLevelIndex: -1,\n screenSecondaryLevelIndex: -1,\n screenSecondaryLevelWeight: 0,\n screenPointAlpha: 0,\n screenNormalizationMaxWeight: 1,\n screenVisibilityStrength: 1,\n webgl: undefined,\n webglWarningIssued: false,\n webglPositions: null,\n webglWeights: null,\n webglCapacity: 0,\n });\n\n const stateRef = useRef<DrawState>({\n data,\n visible,\n opacity,\n radius: clamp(radius, 0.05, 128),\n blur: clamp(blur, 0.05, 128),\n gradient,\n backgroundColor,\n scaleMode,\n fixedZoom,\n zoomThreshold,\n densityContrast: clamp(densityContrast, 0, MAX_DENSITY_CONTRAST),\n clipPolygons,\n clipKey,\n maxRenderedPoints: Math.max(MIN_VISIBLE_BUDGET, Math.floor(maxRenderedPoints)),\n onStats,\n });\n\n stateRef.current = {\n data,\n visible,\n opacity,\n radius: clamp(radius, 0.05, 128),\n blur: clamp(blur, 0.05, 128),\n gradient,\n backgroundColor,\n scaleMode,\n fixedZoom,\n zoomThreshold,\n densityContrast: clamp(densityContrast, 0, MAX_DENSITY_CONTRAST),\n clipPolygons,\n clipKey,\n maxRenderedPoints: Math.max(MIN_VISIBLE_BUDGET, Math.floor(maxRenderedPoints)),\n onStats,\n };\n\n useEffect(() => {\n const draw = (ctx: CanvasRenderingContext2D, logicalWidth: number, logicalHeight: number): void => {\n const state = stateRef.current;\n const runtime = runtimeRef.current;\n const renderer = rendererRef.current;\n if (!state.visible || !state.data || !renderer || !source) return;\n\n const sourceData = ensureSourceData(runtime, state.data, state.clipPolygons, state.clipKey, source);\n if (!sourceData) return;\n\n const needsFixedState =\n state.scaleMode === \"fixed-zoom\" &&\n (!runtime.fixedState ||\n !isSameHeatmapInput(runtime.fixedState, state.data, state.clipKey) ||\n (state.fixedZoom !== undefined && Math.abs(runtime.fixedState.referenceZoom - state.fixedZoom) > 1e-6));\n\n if (needsFixedState) {\n runtime.fixedState = buildFixedState({\n runtime,\n sourceData,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n radius: state.radius,\n blur: state.blur,\n fixedZoom: state.fixedZoom,\n zoomThreshold: state.zoomThreshold,\n densityContrast: state.densityContrast,\n maxRenderedPoints: state.maxRenderedPoints,\n });\n } else if (state.scaleMode !== \"fixed-zoom\") {\n runtime.fixedState = null;\n }\n\n const startedAt = performance.now();\n const stats = drawHeatmap({\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n state,\n });\n if (!stats || !state.onStats) return;\n state.onStats({\n ...stats,\n renderTimeMs: performance.now() - startedAt,\n });\n };\n\n registerDrawCallback(HEATMAP_DRAW_ID, zIndex, draw);\n return () => {\n unregisterDrawCallback(HEATMAP_DRAW_ID);\n runtimeRef.current.sourceData = null;\n runtimeRef.current.fixedState = null;\n runtimeRef.current.screenLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelWeight = 0;\n runtimeRef.current.screenPointAlpha = 0;\n runtimeRef.current.screenNormalizationMaxWeight = 1;\n runtimeRef.current.screenVisibilityStrength = 1;\n runtimeRef.current.webgl?.destroy();\n runtimeRef.current.webgl = undefined;\n runtimeRef.current.webglPositions = null;\n runtimeRef.current.webglWeights = null;\n runtimeRef.current.webglCapacity = 0;\n };\n }, [registerDrawCallback, unregisterDrawCallback, rendererRef, source, zIndex]);\n\n useEffect(() => {\n runtimeRef.current.sourceData = null;\n runtimeRef.current.fixedState = null;\n runtimeRef.current.screenLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelWeight = 0;\n runtimeRef.current.screenPointAlpha = 0;\n runtimeRef.current.screenNormalizationMaxWeight = 1;\n runtimeRef.current.screenVisibilityStrength = 1;\n requestOverlayRedraw();\n }, [data?.positions, data?.weights, data?.count, clipKey, requestOverlayRedraw]);\n\n useEffect(() => {\n runtimeRef.current.fixedState = null;\n runtimeRef.current.screenSecondaryLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelWeight = 0;\n runtimeRef.current.screenPointAlpha = 0;\n runtimeRef.current.screenNormalizationMaxWeight = 1;\n runtimeRef.current.screenVisibilityStrength = 1;\n requestOverlayRedraw();\n }, [radius, blur, scaleMode, fixedZoom, zoomThreshold, densityContrast, maxRenderedPoints, requestOverlayRedraw]);\n\n useEffect(() => {\n requestOverlayRedraw();\n }, [visible, opacity, gradient, backgroundColor, requestOverlayRedraw]);\n\n return null;\n}\n\nexport const __heatmapLayerInternals = {\n applyZoomThreshold,\n buildClipKey,\n resolveCellSupportFactor,\n resolveContinuousZoom,\n resolveDensityCutoff,\n resolveDensityBias,\n resolveDensityGain,\n resolveDensityGamma,\n resolveDensityStretch,\n resolveNormalizedDensityWeight,\n resolveNormalizationUpperWeight,\n resolveDensityWeightExponent,\n resolveRawZoomFromContinuousZoom,\n resolvePointCount,\n resolveThresholdLevelBias,\n resolveZoomVisibilityStrength,\n isSameHeatmapInput,\n};\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { drawOverlayShapes } from \"./draw-layer-overlay\";\nimport type { DrawCoordinate, DrawOverlayShape } from \"./draw-layer-types\";\nimport { DEFAULT_REGION_STROKE_STYLE } from \"./draw-layer-types\";\nimport { closeRing, toCoord } from \"./draw-layer-utils\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport interface OverlayLayerProps {\n shapes?: DrawOverlayShape[];\n}\n\nconst OVERLAY_DRAW_ID = \"__overlay_layer__\";\n\nexport function OverlayLayer({ shapes }: OverlayLayerProps): React.ReactElement | null {\n const { rendererRef, rendererSerial, source, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw } = useViewerContext();\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = rendererRef.current;\n if (!projector || points.length === 0) return [];\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [],\n );\n\n const drawRef = useRef({ shapes, worldToScreenPoints, source });\n drawRef.current = { shapes, worldToScreenPoints, source };\n\n useEffect(() => {\n const draw = (ctx: CanvasRenderingContext2D) => {\n const { shapes: s, worldToScreenPoints: w2s, source: src } = drawRef.current;\n if (!Array.isArray(s) || s.length === 0 || !src) return;\n\n const imageOuterRing = w2s(\n closeRing([\n [0, 0],\n [src.width, 0],\n [src.width, src.height],\n [0, src.height],\n ]),\n );\n drawOverlayShapes({\n ctx,\n overlayShapes: s,\n imageOuterRing,\n worldToScreenPoints: w2s,\n baseStrokeStyle: DEFAULT_REGION_STROKE_STYLE,\n });\n };\n registerDrawCallback(OVERLAY_DRAW_ID, 30, draw);\n return () => unregisterDrawCallback(OVERLAY_DRAW_ID);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n useEffect(() => { requestOverlayRedraw(); }, [rendererSerial, shapes, source, requestOverlayRedraw]);\n\n return null;\n}\n","import type { WsiClass, WsiImageSource } from \"./types\";\n\nexport interface RawImsInfo {\n width?: number | null;\n height?: number | null;\n tileSize?: number | null;\n zoom?: number | null;\n path?: string | null;\n mpp?: number | null;\n}\n\nexport interface RawWsiClass {\n classId?: string | null;\n className?: string | null;\n classColor?: string | null;\n}\n\nexport interface RawImagePayload {\n _id?: string | null;\n id?: string | null;\n name?: string | null;\n width?: number | null;\n height?: number | null;\n tileSize?: number | null;\n zoom?: number | null;\n path?: string | null;\n mpp?: number | null;\n imsInfo?: RawImsInfo | null;\n classes?: RawWsiClass[] | null;\n tileUrlBuilder?: (tier: number, x: number, y: number, tilePath: string, tileBaseUrl: string) => string;\n}\n\nexport function normalizeImageClasses(raw: Pick<RawImagePayload, \"classes\"> | null | undefined): WsiClass[] {\n return Array.isArray(raw?.classes)\n ? raw.classes.map((item: RawWsiClass) => ({\n classId: String(item?.classId ?? \"\"),\n className: String(item?.className ?? \"\"),\n classColor: String(item?.classColor ?? \"\"),\n }))\n : [];\n}\n\nfunction trimTrailingSlash(value: string): string {\n return String(value ?? \"\").replace(/\\/+$/, \"\");\n}\n\nfunction ensureLeadingSlash(value: string): string {\n const raw = String(value ?? \"\");\n return raw.startsWith(\"/\") ? raw : `/${raw}`;\n}\n\nfunction joinImsTileRoot(tileBaseUrl: string): string {\n const base = trimTrailingSlash(tileBaseUrl);\n if (!base) return \"\";\n\n // Explicit TileGroup path already provided.\n if (/\\/TileGroup\\d+$/i.test(base)) return base;\n\n let parsed: URL | null = null;\n try {\n parsed = new URL(base);\n } catch {\n parsed = null;\n }\n\n if (parsed) {\n const origin = `${parsed.protocol}//${parsed.host}`;\n const path = trimTrailingSlash(parsed.pathname || \"\");\n\n // If caller passes /ims, keep /ims and append image path directly:\n // /ims + /tiles/<hash> + /tier/y_x.webp\n if (/\\/ims$/i.test(path)) return `${origin}${path}`;\n if (/\\/tiles$/i.test(path)) return `${origin}${path}`;\n return `${origin}${path}/tiles`;\n }\n\n // Relative path mode\n if (/\\/ims$/i.test(base)) return `/ims`;\n if (/\\/tiles$/i.test(base)) return `${base}`;\n return `${base}/tiles`;\n}\n\nexport function normalizeImageInfo(raw: RawImagePayload, tileBaseUrl: string): WsiImageSource {\n const ims = raw?.imsInfo ?? {};\n const isIms = !!raw?.imsInfo;\n\n const width = Number(ims.width ?? raw?.width ?? 0);\n const height = Number(ims.height ?? raw?.height ?? 0);\n const tileSize = Number(ims.tileSize ?? raw?.tileSize ?? 0);\n const maxTierZoom = Number(ims.zoom ?? raw?.zoom ?? 0);\n const tilePath = String(ims.path ?? raw?.path ?? \"\");\n const mpp = Number(ims.mpp ?? raw?.mpp ?? 0);\n\n if (!width || !height || !tileSize || !tilePath) {\n throw new Error(\"Incomplete image metadata: width/height/tileSize/path required\");\n }\n\n const normalizedPath = ensureLeadingSlash(tilePath);\n const imsTileRoot = joinImsTileRoot(tileBaseUrl);\n const tileUrlBuilder = raw?.tileUrlBuilder\n ?? (isIms ? (tier: number, x: number, y: number): string => `${imsTileRoot}${normalizedPath}/${tier}/${y}_${x}.webp` : undefined);\n\n return {\n id: raw?._id || raw?.id || \"unknown\",\n name: raw?.name || \"unknown\",\n width,\n height,\n mpp: Number.isFinite(mpp) && mpp > 0 ? mpp : undefined,\n tileSize,\n maxTierZoom: Number.isFinite(maxTierZoom) ? Math.max(0, Math.floor(maxTierZoom)) : 0,\n tilePath,\n tileBaseUrl,\n tileUrlBuilder,\n };\n}\n\nexport function toTileUrl(source: Pick<WsiImageSource, \"tilePath\" | \"tileBaseUrl\" | \"tileUrlBuilder\">, tier: number, x: number, y: number): string {\n if (source.tileUrlBuilder) {\n return source.tileUrlBuilder(tier, x, y, source.tilePath, source.tileBaseUrl);\n }\n const normalizedPath = ensureLeadingSlash(source.tilePath);\n return `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import { type CSSProperties, type MutableRefObject, type ReactNode, type PointerEvent as ReactPointerEvent, type RefObject, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { observeDevicePixelRatioChanges } from \"../wsi/device-pixel-ratio\";\nimport { toTileUrl } from \"../wsi/image-info\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\n\ntype Bounds = [number, number, number, number];\n\ninterface RotatedImageMetrics {\n cos: number;\n sin: number;\n minX: number;\n minY: number;\n width: number;\n height: number;\n translateX: number;\n translateY: number;\n}\n\ninterface OverviewImageLayout {\n contentX: number;\n contentY: number;\n contentWidth: number;\n contentHeight: number;\n metrics: RotatedImageMetrics;\n}\n\nfunction shouldAttachAuthHeaderToOverviewTile(url: string, authToken: string): boolean {\n if (!authToken) return false;\n const host = new URL(url, typeof window !== \"undefined\" ? window.location.href : undefined).hostname.toLowerCase();\n if (host.includes(\"amazonaws.com\") || host.startsWith(\"s3.\") || host.includes(\".s3.\")) return false;\n return true;\n}\n\nexport interface OverviewMapProjector {\n getViewState: () => WsiViewState;\n setViewState: (next: Partial<WsiViewState>) => void;\n setViewCenter?: (worldX: number, worldY: number) => void;\n getViewBounds?: () => number[];\n getViewCorners?: () => Array<[number, number]>;\n getInitialRotationDeg?: () => number;\n}\n\nexport type OverviewMapPosition = \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\n\nexport type ViewportBorderStyle = \"stroke\" | \"dash\";\n\nexport interface OverviewMapOptions {\n width: number;\n height: number;\n margin: number;\n position: OverviewMapPosition;\n borderRadius: number;\n borderWidth: number;\n backgroundColor: string;\n borderColor: string;\n viewportBorderColor: string;\n viewportBorderStyle: ViewportBorderStyle;\n viewportFillColor: string;\n interactive: boolean;\n showThumbnail: boolean;\n maxThumbnailTiles: number;\n onClose?: () => void;\n closeIcon?: ReactNode;\n closeButtonStyle?: CSSProperties;\n}\n\nexport interface OverviewMapProps {\n source: WsiImageSource;\n projectorRef: RefObject<OverviewMapProjector | null>;\n authToken?: string;\n options?: Partial<OverviewMapOptions>;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n width: 200,\n height: 125,\n margin: 16,\n position: \"bottom-right\",\n borderRadius: 6,\n borderWidth: 0,\n backgroundColor: \"rgba(4, 10, 18, 0.88)\",\n borderColor: \"rgba(230, 244, 255, 0.35)\",\n viewportBorderColor: \"rgba(255, 106, 61, 0.95)\",\n viewportBorderStyle: \"dash\",\n viewportFillColor: \"transparent\",\n interactive: true,\n showThumbnail: true,\n maxThumbnailTiles: 16,\n};\n\nfunction strokeSymmetricDashedPolygon(ctx: CanvasRenderingContext2D, points: Array<[number, number]>, dashLen: number, gapLen: number): void {\n const len = points.length;\n if (len < 3) return;\n if (dashLen <= 0 || gapLen <= 0) return;\n\n for (let i = 0; i < len; i += 1) {\n const from = points[i];\n const to = points[(i + 1) % len];\n const sideLen = Math.hypot(to[0] - from[0], to[1] - from[1]);\n if (sideLen < 1e-6) continue;\n\n const n = Math.max(1, Math.round((sideLen + gapLen) / (dashLen + gapLen)));\n const fittedLen = n * dashLen + (n - 1) * gapLen;\n const scale = sideLen / Math.max(1e-6, fittedLen);\n const adjDash = dashLen * scale;\n const adjGap = gapLen * scale;\n\n ctx.beginPath();\n ctx.moveTo(from[0], from[1]);\n ctx.lineTo(to[0], to[1]);\n ctx.setLineDash([adjDash, adjGap]);\n ctx.lineDashOffset = 0;\n ctx.stroke();\n }\n\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n}\n\nfunction isSamePoint(a: readonly [number, number], b: readonly [number, number], epsilon = 1e-4): boolean {\n return Math.abs(a[0] - b[0]) <= epsilon && Math.abs(a[1] - b[1]) <= epsilon;\n}\n\nfunction compactPolygonPoints(points: Array<[number, number]>): Array<[number, number]> {\n const compact: Array<[number, number]> = [];\n for (const point of points) {\n const prev = compact[compact.length - 1];\n if (!prev || !isSamePoint(prev, point)) {\n compact.push(point);\n }\n }\n if (compact.length > 1 && isSamePoint(compact[0], compact[compact.length - 1])) {\n compact.pop();\n }\n return compact;\n}\n\nfunction intersectAtX(from: readonly [number, number], to: readonly [number, number], x: number): [number, number] {\n const dx = to[0] - from[0];\n if (Math.abs(dx) < 1e-6) return [x, from[1]];\n const t = (x - from[0]) / dx;\n return [x, from[1] + (to[1] - from[1]) * t];\n}\n\nfunction intersectAtY(from: readonly [number, number], to: readonly [number, number], y: number): [number, number] {\n const dy = to[1] - from[1];\n if (Math.abs(dy) < 1e-6) return [from[0], y];\n const t = (y - from[1]) / dy;\n return [from[0] + (to[0] - from[0]) * t, y];\n}\n\nfunction clipPolygonToRect(points: Array<[number, number]>, minX: number, minY: number, maxX: number, maxY: number): Array<[number, number]> {\n let output = compactPolygonPoints(points);\n if (output.length < 3) return [];\n\n const edges: Array<{\n inside: (point: readonly [number, number]) => boolean;\n intersect: (from: readonly [number, number], to: readonly [number, number]) => [number, number];\n }> = [\n {\n inside: point => point[0] >= minX,\n intersect: (from, to) => intersectAtX(from, to, minX),\n },\n {\n inside: point => point[0] <= maxX,\n intersect: (from, to) => intersectAtX(from, to, maxX),\n },\n {\n inside: point => point[1] >= minY,\n intersect: (from, to) => intersectAtY(from, to, minY),\n },\n {\n inside: point => point[1] <= maxY,\n intersect: (from, to) => intersectAtY(from, to, maxY),\n },\n ];\n\n for (const edge of edges) {\n if (output.length === 0) return [];\n const input = output;\n output = [];\n let prev = input[input.length - 1];\n let prevInside = edge.inside(prev);\n for (const curr of input) {\n const currInside = edge.inside(curr);\n if (currInside) {\n if (!prevInside) {\n output.push(edge.intersect(prev, curr));\n }\n output.push(curr);\n } else if (prevInside) {\n output.push(edge.intersect(prev, curr));\n }\n prev = curr;\n prevInside = currInside;\n }\n output = compactPolygonPoints(output);\n }\n\n return output.length >= 3 ? output : [];\n}\n\nfunction toPositiveNumber(value: number | undefined, fallback: number, min = 1): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n return Math.max(min, value);\n}\n\nfunction toFiniteRotation(value: number | undefined): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction toRadians(deg: number): number {\n return (deg * Math.PI) / 180;\n}\n\nfunction getRotatedImageMetrics(imageWidth: number, imageHeight: number, rotationDeg: number): RotatedImageMetrics {\n const safeRotation = toFiniteRotation(rotationDeg);\n const rad = toRadians(safeRotation);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const centerX = imageWidth * 0.5;\n const centerY = imageHeight * 0.5;\n const translateX = -cos * centerX - sin * centerY;\n const translateY = sin * centerX - cos * centerY;\n\n const corners: Array<[number, number]> = [\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ].map(([x, y]) => [cos * x + sin * y + translateX, -sin * x + cos * y + translateY]);\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of corners) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n return {\n cos,\n sin,\n minX,\n minY,\n width: Math.max(1e-6, maxX - minX),\n height: Math.max(1e-6, maxY - minY),\n translateX,\n translateY,\n };\n}\n\nfunction getOverviewImageLayout(imageWidth: number, imageHeight: number, boxWidth: number, boxHeight: number, rotationDeg: number): OverviewImageLayout {\n const metrics = getRotatedImageMetrics(imageWidth, imageHeight, rotationDeg);\n const imageAspect = metrics.width / metrics.height;\n const boxAspect = boxWidth / boxHeight;\n\n let contentWidth: number;\n let contentHeight: number;\n if (imageAspect > boxAspect) {\n contentWidth = boxWidth;\n contentHeight = boxWidth / imageAspect;\n } else {\n contentHeight = boxHeight;\n contentWidth = boxHeight * imageAspect;\n }\n\n return {\n contentX: (boxWidth - contentWidth) / 2,\n contentY: (boxHeight - contentHeight) / 2,\n contentWidth,\n contentHeight,\n metrics,\n };\n}\n\nfunction worldToOverviewPoint(worldX: number, worldY: number, layout: OverviewImageLayout): [number, number] {\n const { contentX, contentY, contentWidth, contentHeight, metrics } = layout;\n const rotatedX = metrics.cos * worldX + metrics.sin * worldY + metrics.translateX - metrics.minX;\n const rotatedY = -metrics.sin * worldX + metrics.cos * worldY + metrics.translateY - metrics.minY;\n return [contentX + (rotatedX / metrics.width) * contentWidth, contentY + (rotatedY / metrics.height) * contentHeight];\n}\n\nfunction overviewPointToWorld(pointX: number, pointY: number, layout: OverviewImageLayout, imageWidth: number, imageHeight: number): [number, number] {\n const { metrics } = layout;\n const rotatedX = pointX + metrics.minX - metrics.translateX;\n const rotatedY = pointY + metrics.minY - metrics.translateY;\n const worldX = rotatedX * metrics.cos - rotatedY * metrics.sin;\n const worldY = rotatedX * metrics.sin + rotatedY * metrics.cos;\n return [clamp(worldX, 0, imageWidth), clamp(worldY, 0, imageHeight)];\n}\n\nfunction boundsToCorners(bounds: Bounds): Array<[number, number]> {\n return [\n [bounds[0], bounds[1]],\n [bounds[2], bounds[1]],\n [bounds[2], bounds[3]],\n [bounds[0], bounds[3]],\n ];\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n return Array.isArray(bounds) && bounds.length === 4 && Number.isFinite(bounds[0]) && Number.isFinite(bounds[1]) && Number.isFinite(bounds[2]) && Number.isFinite(bounds[3]);\n}\n\nconst DEFAULT_CLOSE_BUTTON_STYLE: CSSProperties = {\n position: \"absolute\",\n top: 4,\n right: 4,\n zIndex: 1,\n width: 18,\n height: 18,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.4)\",\n background: \"rgba(16, 17, 19, 0.85)\",\n color: \"#fff\",\n fontSize: 12,\n lineHeight: 1,\n cursor: \"pointer\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n};\n\nexport function OverviewMap({ source, projectorRef, authToken = \"\", options, invalidateRef, className, style }: OverviewMapProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n const lastBoundsRef = useRef<Bounds | null>(null);\n const draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n active: false,\n pointerId: null,\n });\n const rafRef = useRef<number | null>(null);\n const drawPendingRef = useRef(false);\n\n const width = toPositiveNumber(options?.width, DEFAULT_OVERVIEW_MAP_OPTIONS.width, 64);\n const height = toPositiveNumber(options?.height, DEFAULT_OVERVIEW_MAP_OPTIONS.height, 48);\n\n const margin = toPositiveNumber(options?.margin, DEFAULT_OVERVIEW_MAP_OPTIONS.margin, 0);\n const borderRadius = toPositiveNumber(options?.borderRadius, DEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius, 0);\n const borderWidth = toPositiveNumber(options?.borderWidth, DEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth, 0);\n const maxThumbnailTiles = Math.max(1, Math.round(toPositiveNumber(options?.maxThumbnailTiles, DEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles, 1)));\n\n const backgroundColor = options?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n const borderColor = options?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n const viewportBorderColor = options?.viewportBorderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.viewportBorderColor;\n const viewportBorderStyle = options?.viewportBorderStyle === \"stroke\" || options?.viewportBorderStyle === \"dash\" ? options.viewportBorderStyle : DEFAULT_OVERVIEW_MAP_OPTIONS.viewportBorderStyle;\n const viewportFillColor = options?.viewportFillColor ?? DEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n const interactive = options?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n const showThumbnail = options?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n const position = options?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n const onClose = options?.onClose;\n const closeIcon = options?.closeIcon;\n const closeButtonStyle = options?.closeButtonStyle;\n\n const mergedStyle = useMemo<CSSProperties>(() => {\n const pos: CSSProperties = {};\n if (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n else pos.right = margin;\n if (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n else pos.bottom = margin;\n\n return {\n position: \"absolute\",\n ...pos,\n width,\n height,\n borderRadius,\n overflow: \"hidden\",\n zIndex: 4,\n pointerEvents: interactive ? \"auto\" : \"none\",\n touchAction: \"none\",\n boxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n ...style,\n };\n }, [margin, position, width, height, borderRadius, interactive, style]);\n\n const draw = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const cssW = width;\n const cssH = height;\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const pixelW = Math.max(1, Math.round(cssW * dpr));\n const pixelH = Math.max(1, Math.round(cssH * dpr));\n if (canvas.width !== pixelW || canvas.height !== pixelH) {\n canvas.width = pixelW;\n canvas.height = pixelH;\n }\n\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, cssW, cssH);\n\n const projector = projectorRef.current;\n const initialRotationDeg = toFiniteRotation(projector?.getInitialRotationDeg?.());\n const layout = getOverviewImageLayout(source.width, source.height, cssW, cssH, initialRotationDeg);\n const { contentX: cx, contentY: cy, contentWidth: cw, contentHeight: ch, metrics } = layout;\n\n const preview = thumbnailRef.current;\n if (preview) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(cx, cy, cw, ch);\n ctx.clip();\n ctx.translate(cx, cy);\n ctx.scale(cw / metrics.width, ch / metrics.height);\n ctx.transform(metrics.cos, -metrics.sin, metrics.sin, metrics.cos, metrics.translateX - metrics.minX, metrics.translateY - metrics.minY);\n ctx.drawImage(preview, 0, 0, source.width, source.height);\n ctx.restore();\n }\n\n ctx.strokeStyle = borderColor;\n ctx.lineWidth = borderWidth;\n ctx.strokeRect(borderWidth * 0.5, borderWidth * 0.5, cssW - borderWidth, cssH - borderWidth);\n\n const bounds = projector?.getViewBounds?.();\n const corners = projector?.getViewCorners?.();\n const safeCorners =\n Array.isArray(corners) && corners.length >= 4 && corners.every(point => Array.isArray(point) && point.length >= 2 && Number.isFinite(point[0]) && Number.isFinite(point[1]))\n ? (corners as Array<[number, number]>)\n : null;\n const safeBounds = isFiniteBounds(bounds) ? bounds : isFiniteBounds(lastBoundsRef.current) ? lastBoundsRef.current : null;\n if (isFiniteBounds(bounds)) {\n lastBoundsRef.current = bounds;\n }\n\n const isDash = viewportBorderStyle === \"dash\";\n\n if (safeCorners) {\n const screenCorners: Array<[number, number]> = safeCorners.map(point => worldToOverviewPoint(point[0], point[1], layout));\n const clippedCorners = clipPolygonToRect(screenCorners, cx, cy, cx + cw, cy + ch);\n\n if (clippedCorners.length >= 3) {\n ctx.beginPath();\n for (let i = 0; i < clippedCorners.length; i += 1) {\n if (i === 0) ctx.moveTo(clippedCorners[i][0], clippedCorners[i][1]);\n else ctx.lineTo(clippedCorners[i][0], clippedCorners[i][1]);\n }\n ctx.closePath();\n ctx.fillStyle = viewportFillColor;\n ctx.fill();\n ctx.strokeStyle = viewportBorderColor;\n ctx.lineWidth = 2.25;\n if (isDash) {\n strokeSymmetricDashedPolygon(ctx, clippedCorners, 4, 3);\n } else {\n ctx.stroke();\n }\n return;\n }\n }\n\n if (!safeBounds) {\n return;\n }\n\n const fallbackCorners = boundsToCorners(safeBounds).map(point => worldToOverviewPoint(point[0], point[1], layout));\n const clippedCorners = clipPolygonToRect(fallbackCorners, cx, cy, cx + cw, cy + ch);\n if (clippedCorners.length < 3) {\n return;\n }\n\n ctx.beginPath();\n for (let i = 0; i < clippedCorners.length; i += 1) {\n if (i === 0) ctx.moveTo(clippedCorners[i][0], clippedCorners[i][1]);\n else ctx.lineTo(clippedCorners[i][0], clippedCorners[i][1]);\n }\n ctx.closePath();\n ctx.fillStyle = viewportFillColor;\n ctx.fill();\n ctx.strokeStyle = viewportBorderColor;\n ctx.lineWidth = 2.25;\n if (isDash) {\n strokeSymmetricDashedPolygon(ctx, clippedCorners, 4, 3);\n } else {\n ctx.stroke();\n }\n }, [width, height, backgroundColor, borderColor, borderWidth, projectorRef, source.width, source.height, viewportFillColor, viewportBorderColor, viewportBorderStyle]);\n\n const requestDraw = useCallback(() => {\n if (drawPendingRef.current) return;\n drawPendingRef.current = true;\n rafRef.current = requestAnimationFrame(() => {\n drawPendingRef.current = false;\n rafRef.current = null;\n draw();\n });\n }, [draw]);\n\n const toWorldFromClient = useCallback(\n (clientX: number, clientY: number): [number, number] | null => {\n const canvas = canvasRef.current;\n if (!canvas) return null;\n\n const rect = canvas.getBoundingClientRect();\n if (!rect.width || !rect.height) return null;\n\n const projector = projectorRef.current;\n const initialRotationDeg = toFiniteRotation(projector?.getInitialRotationDeg?.());\n const layout = getOverviewImageLayout(source.width, source.height, width, height, initialRotationDeg);\n const scaleX = rect.width / width;\n const scaleY = rect.height / height;\n const cxPx = layout.contentX * scaleX;\n const cyPx = layout.contentY * scaleY;\n const cwPx = layout.contentWidth * scaleX;\n const chPx = layout.contentHeight * scaleY;\n\n const nx = clamp((clientX - rect.left - cxPx) / cwPx, 0, 1);\n const ny = clamp((clientY - rect.top - cyPx) / chPx, 0, 1);\n return overviewPointToWorld(nx * layout.metrics.width, ny * layout.metrics.height, layout, source.width, source.height);\n },\n [projectorRef, source.width, source.height, width, height]\n );\n\n const recenterTo = useCallback(\n (worldX: number, worldY: number) => {\n const projector = projectorRef.current;\n if (!projector) return;\n\n if (projector.setViewCenter) {\n projector.setViewCenter(worldX, worldY);\n requestDraw();\n return;\n }\n\n const bounds = projector.getViewBounds?.();\n const safeBounds = isFiniteBounds(bounds) ? bounds : isFiniteBounds(lastBoundsRef.current) ? lastBoundsRef.current : null;\n if (!safeBounds) return;\n\n const visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n const visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n projector.setViewState({\n offsetX: worldX - visibleW * 0.5,\n offsetY: worldY - visibleH * 0.5,\n });\n requestDraw();\n },\n [projectorRef, requestDraw]\n );\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!interactive) return;\n if (event.button !== 0) return;\n\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const world = toWorldFromClient(event.clientX, event.clientY);\n if (!world) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n canvas.setPointerCapture(event.pointerId);\n draggingRef.current = { active: true, pointerId: event.pointerId };\n recenterTo(world[0], world[1]);\n },\n [interactive, toWorldFromClient, recenterTo]\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const drag = draggingRef.current;\n if (!drag.active || drag.pointerId !== event.pointerId) return;\n\n const world = toWorldFromClient(event.clientX, event.clientY);\n if (!world) return;\n\n event.preventDefault();\n event.stopPropagation();\n recenterTo(world[0], world[1]);\n },\n [toWorldFromClient, recenterTo]\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const drag = draggingRef.current;\n if (!drag.active || drag.pointerId !== event.pointerId) return;\n\n const canvas = canvasRef.current;\n if (canvas && canvas.hasPointerCapture(event.pointerId)) {\n try {\n canvas.releasePointerCapture(event.pointerId);\n } catch {\n // noop\n }\n }\n\n draggingRef.current = { active: false, pointerId: null };\n requestDraw();\n },\n [requestDraw]\n );\n\n useEffect(() => {\n let cancelled = false;\n thumbnailRef.current = null;\n requestDraw();\n\n const tier = 0;\n const levelScale = 2 ** (source.maxTierZoom - tier);\n const levelWidth = Math.ceil(source.width / levelScale);\n const levelHeight = Math.ceil(source.height / levelScale);\n const tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n const tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n const tileCount = tilesX * tilesY;\n\n if (!showThumbnail || tileCount > maxThumbnailTiles) {\n return undefined;\n }\n\n const previewScale = Math.min(width / Math.max(1, source.width), height / Math.max(1, source.height));\n const preview = document.createElement(\"canvas\");\n preview.width = Math.max(1, Math.round(source.width * previewScale));\n preview.height = Math.max(1, Math.round(source.height * previewScale));\n const ctx = preview.getContext(\"2d\");\n if (!ctx) {\n return undefined;\n }\n\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, preview.width, preview.height);\n\n const requests: Array<{\n url: string;\n bounds: Bounds;\n }> = [];\n\n for (let y = 0; y < tilesY; y += 1) {\n for (let x = 0; x < tilesX; x += 1) {\n const left = x * source.tileSize * levelScale;\n const top = y * source.tileSize * levelScale;\n const right = Math.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n const bottom = Math.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n requests.push({\n url: toTileUrl(source, tier, x, y),\n bounds: [left, top, right, bottom],\n });\n }\n }\n\n void Promise.allSettled(\n requests.map(async tile => {\n const useAuthHeader = shouldAttachAuthHeaderToOverviewTile(tile.url, authToken);\n const response = await fetch(tile.url, {\n headers: useAuthHeader ? { Authorization: authToken } : undefined,\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const bitmap = await createImageBitmap(await response.blob());\n return { tile, bitmap };\n })\n ).then(results => {\n if (cancelled) {\n for (const result of results) {\n if (result.status === \"fulfilled\") {\n result.value.bitmap.close();\n }\n }\n return;\n }\n\n const sx = preview.width / Math.max(1, source.width);\n const sy = preview.height / Math.max(1, source.height);\n for (const result of results) {\n if (result.status !== \"fulfilled\") continue;\n const {\n tile: { bounds },\n bitmap,\n } = result.value;\n const dx = bounds[0] * sx;\n const dy = bounds[1] * sy;\n const dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n const dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n ctx.drawImage(bitmap, dx, dy, dw, dh);\n bitmap.close();\n }\n\n thumbnailRef.current = preview;\n requestDraw();\n });\n\n return () => {\n cancelled = true;\n };\n }, [source, authToken, backgroundColor, width, height, showThumbnail, maxThumbnailTiles, requestDraw]);\n\n useEffect(() => {\n requestDraw();\n }, [requestDraw]);\n\n useEffect(() => {\n if (projectorRef.current) return undefined;\n let rafId = 0;\n const tick = () => {\n if (projectorRef.current) {\n requestDraw();\n return;\n }\n rafId = requestAnimationFrame(tick);\n };\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [projectorRef, requestDraw]);\n\n useEffect(() => observeDevicePixelRatioChanges(() => requestDraw()), [requestDraw]);\n\n useEffect(() => {\n if (!invalidateRef) return undefined;\n invalidateRef.current = requestDraw;\n return () => {\n if (invalidateRef.current === requestDraw) {\n invalidateRef.current = null;\n }\n };\n }, [invalidateRef, requestDraw]);\n\n useEffect(\n () => () => {\n draggingRef.current = { active: false, pointerId: null };\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n drawPendingRef.current = false;\n },\n []\n );\n\n return (\n <div className={className} style={mergedStyle}>\n <canvas\n ref={canvasRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n borderRadius: \"inherit\",\n }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onContextMenu={event => {\n event.preventDefault();\n }}\n onWheel={event => {\n event.preventDefault();\n event.stopPropagation();\n }}\n />\n {onClose && (\n <button\n type=\"button\"\n aria-label=\"Hide overview map\"\n onClick={event => {\n event.stopPropagation();\n onClose();\n }}\n style={closeButtonStyle ? { ...(closeButtonStyle as CSSProperties) } : { ...(DEFAULT_CLOSE_BUTTON_STYLE as CSSProperties) }}\n >\n {closeIcon ?? \"×\"}\n </button>\n )}\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { WsiRegion } from \"../wsi/types\";\nimport type {\n DrawCoordinate,\n PreparedRenderedRegion,\n RegionStrokeStyle,\n} from \"./draw-layer-types\";\nimport { DEFAULT_PATCH_STROKE_STYLE } from \"./draw-layer-types\";\nimport { drawPath, mergeStrokeStyle, normalizeDrawRegionPolygons, toCoord } from \"./draw-layer-utils\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport interface PatchLayerProps {\n regions?: WsiRegion[];\n strokeStyle?: Partial<RegionStrokeStyle>;\n}\n\nconst PATCH_DRAW_ID = \"__patch_layer__\";\nconst EMPTY_REGIONS: WsiRegion[] = [];\n\nexport function PatchLayer({ regions, strokeStyle }: PatchLayerProps): React.ReactElement | null {\n const { rendererRef, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw } = useViewerContext();\n\n const safeRegions = regions ?? EMPTY_REGIONS;\n\n const resolvedStrokeStyle = useMemo(() => mergeStrokeStyle(DEFAULT_PATCH_STROKE_STYLE, strokeStyle), [strokeStyle]);\n\n const prepared = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < safeRegions.length; i += 1) {\n const region = safeRegions[i];\n const polys = normalizeDrawRegionPolygons(region.coordinates);\n if (polys.length === 0) continue;\n out.push({ region, regionIndex: i, regionKey: region.id ?? i, polygons: polys });\n }\n return out;\n }, [safeRegions]);\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = rendererRef.current;\n if (!projector || points.length === 0) return [];\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [],\n );\n\n const drawRef = useRef({ prepared, resolvedStrokeStyle, worldToScreenPoints });\n drawRef.current = { prepared, resolvedStrokeStyle, worldToScreenPoints };\n\n useEffect(() => {\n const draw = (ctx: CanvasRenderingContext2D) => {\n const { prepared: prep, resolvedStrokeStyle: style, worldToScreenPoints: w2s } = drawRef.current;\n for (const entry of prep) {\n for (const polygon of entry.polygons) {\n const screenOuter = w2s(polygon.outer);\n if (screenOuter.length >= 4) drawPath(ctx, screenOuter, style, true, false);\n for (const hole of polygon.holes) {\n const screenHole = w2s(hole);\n if (screenHole.length >= 4) drawPath(ctx, screenHole, style, true, false);\n }\n }\n }\n };\n registerDrawCallback(PATCH_DRAW_ID, 20, draw);\n return () => unregisterDrawCallback(PATCH_DRAW_ID);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n useEffect(() => { requestOverlayRedraw(); }, [prepared, resolvedStrokeStyle, requestOverlayRedraw]);\n\n return null;\n}\n","import { pointInAnyPreparedPolygon, prepareRoiPolygons, type RoiCoordinate, type RoiGeometry } from \"./roi-geometry\";\nimport type { WsiPointData } from \"./types\";\nimport { sanitizePointCount } from \"./utils\";\n\nexport type { RoiCoordinate };\nexport type RoiPolygon = RoiGeometry;\n\nexport function filterPointDataByPolygons(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): WsiPointData | null {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const prepared = prepareRoiPolygons(polygons ?? []);\n if (prepared.length === 0) {\n const empty: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointData.fillModes instanceof Uint8Array) {\n empty.fillModes = new Uint8Array(0);\n }\n if (pointData.ids instanceof Uint32Array) {\n empty.ids = new Uint32Array(0);\n }\n return empty;\n }\n\n const count = sanitizePointCount(pointData);\n const positions = pointData.positions;\n const classes = pointData.paletteIndices;\n const fillModes = pointData.fillModes instanceof Uint8Array && pointData.fillModes.length >= count ? pointData.fillModes : null;\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= count ? pointData.ids : null;\n\n const nextPositions = new Float32Array(count * 2);\n const nextClasses = new Uint16Array(count);\n const nextFillModes = fillModes ? new Uint8Array(count) : null;\n const nextIds = pointIds ? new Uint32Array(count) : null;\n let cursor = 0;\n\n for (let i = 0; i < count; i += 1) {\n const x = positions[i * 2];\n const y = positions[i * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextClasses[cursor] = classes[i];\n if (nextFillModes) {\n nextFillModes[cursor] = fillModes![i];\n }\n if (nextIds) {\n nextIds[cursor] = pointIds![i];\n }\n cursor += 1;\n }\n\n const output: WsiPointData = {\n count: cursor,\n positions: nextPositions.subarray(0, cursor * 2),\n paletteIndices: nextClasses.subarray(0, cursor),\n };\n if (nextFillModes) {\n output.fillModes = nextFillModes.subarray(0, cursor);\n }\n if (nextIds) {\n output.ids = nextIds.subarray(0, cursor);\n }\n return output;\n}\n\nexport function filterPointIndicesByPolygons(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Uint32Array {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return new Uint32Array(0);\n }\n\n const prepared = prepareRoiPolygons(polygons ?? []);\n if (prepared.length === 0) {\n return new Uint32Array(0);\n }\n\n const count = sanitizePointCount(pointData);\n if (count === 0) {\n return new Uint32Array(0);\n }\n\n const positions = pointData.positions;\n const out = new Uint32Array(count);\n let cursor = 0;\n\n for (let i = 0; i < count; i += 1) {\n const x = positions[i * 2];\n const y = positions[i * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n out[cursor] = i;\n cursor += 1;\n }\n\n return out.subarray(0, cursor);\n}\n","export interface WebGpuCapabilities {\n\tsupported: boolean;\n\tadapterName?: string;\n\tfeatures: string[];\n\tlimits?: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n}\n\ninterface NavigatorGpuLike {\n\trequestAdapter: () => Promise<GpuAdapterLike | null>;\n}\n\ninterface GpuAdapterLike {\n\tinfo?: {\n\t\tdescription?: string;\n\t\tvendor?: string;\n\t};\n\tfeatures: Iterable<string>;\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n\trequestDevice: () => Promise<GpuDeviceLike>;\n}\n\ninterface GpuBufferLike {\n\tdestroy: () => void;\n\tmapAsync: (mode: number) => Promise<void>;\n\tgetMappedRange: () => ArrayBuffer;\n\tunmap: () => void;\n}\n\ninterface GpuComputePassLike {\n\tsetPipeline: (pipeline: GpuComputePipelineLike) => void;\n\tsetBindGroup: (index: number, bindGroup: unknown) => void;\n\tdispatchWorkgroups: (x: number, y?: number, z?: number) => void;\n\tend: () => void;\n}\n\ninterface GpuCommandEncoderLike {\n\tbeginComputePass: () => GpuComputePassLike;\n\tcopyBufferToBuffer: (\n\t\tsource: GpuBufferLike,\n\t\tsourceOffset: number,\n\t\tdestination: GpuBufferLike,\n\t\tdestinationOffset: number,\n\t\tsize: number,\n\t) => void;\n\tfinish: () => unknown;\n}\n\ninterface GpuQueueLike {\n\twriteBuffer: (\n\t\tbuffer: GpuBufferLike,\n\t\tbufferOffset: number,\n\t\tdata: ArrayBufferView | ArrayBufferLike,\n\t\tdataOffset?: number,\n\t\tsize?: number,\n\t) => void;\n\tsubmit: (commands: unknown[]) => void;\n}\n\ninterface GpuComputePipelineLike {\n\treadonly _brand?: \"GpuComputePipelineLike\";\n}\n\ninterface GpuBindGroupLayoutLike {\n\treadonly _brand?: \"GpuBindGroupLayoutLike\";\n}\n\ninterface GpuDeviceLike {\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t};\n\tqueue: GpuQueueLike;\n\tcreateBindGroupLayout: (descriptor: unknown) => GpuBindGroupLayoutLike;\n\tcreatePipelineLayout: (descriptor: unknown) => unknown;\n\tcreateShaderModule: (descriptor: { code: string }) => unknown;\n\tcreateComputePipeline: (descriptor: unknown) => GpuComputePipelineLike;\n\tcreateBuffer: (descriptor: { size: number; usage: number }) => GpuBufferLike;\n\tcreateBindGroup: (descriptor: unknown) => unknown;\n\tcreateCommandEncoder: () => GpuCommandEncoderLike;\n}\n\ninterface WebGpuContext {\n\tdevice: GpuDeviceLike;\n\tpipeline: GpuComputePipelineLike;\n\tbindGroupLayout: GpuBindGroupLayoutLike;\n}\n\nlet contextPromise: Promise<WebGpuContext | null> | null = null;\n\nconst BBOX_PREFILTER_SHADER = `\nstruct Params {\n pointCount: u32,\n boundsCount: u32,\n _pad0: u32,\n _pad1: u32,\n};\n\n@group(0) @binding(0) var<storage, read> positions: array<vec2<f32>>;\n@group(0) @binding(1) var<storage, read> bounds: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read_write> outputMask: array<u32>;\n@group(0) @binding(3) var<uniform> params: Params;\n\n@compute @workgroup_size(256)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let i = gid.x;\n if (i >= params.pointCount) {\n return;\n }\n\n let p = positions[i];\n var inside: u32 = 0u;\n for (var bi: u32 = 0u; bi < params.boundsCount; bi = bi + 1u) {\n let b = bounds[bi];\n if (p.x >= b.x && p.x <= b.z && p.y >= b.y && p.y <= b.w) {\n inside = 1u;\n break;\n }\n }\n outputMask[i] = inside;\n}\n`;\n\nfunction hasWebGpu(): boolean {\n\tif (typeof navigator === \"undefined\") return false;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\treturn typeof nav.gpu === \"object\" && nav.gpu !== null;\n}\n\nfunction getNavigatorGpu(): NavigatorGpuLike | null {\n\tif (!hasWebGpu()) return null;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\tconst gpu = nav.gpu;\n\tif (!gpu || typeof gpu !== \"object\") return null;\n\tconst candidate = gpu as Partial<NavigatorGpuLike>;\n\tif (typeof candidate.requestAdapter !== \"function\") return null;\n\treturn candidate as NavigatorGpuLike;\n}\n\nconst GPU_SHADER_STAGE_COMPUTE =\n\t(globalThis as { GPUShaderStage?: { COMPUTE?: number } }).GPUShaderStage\n\t\t?.COMPUTE ?? 0x4;\nconst GPU_BUFFER_USAGE_STORAGE =\n\t(globalThis as { GPUBufferUsage?: { STORAGE?: number } }).GPUBufferUsage\n\t\t?.STORAGE ?? 0x80;\nconst GPU_BUFFER_USAGE_COPY_DST =\n\t(globalThis as { GPUBufferUsage?: { COPY_DST?: number } }).GPUBufferUsage\n\t\t?.COPY_DST ?? 0x08;\nconst GPU_BUFFER_USAGE_COPY_SRC =\n\t(globalThis as { GPUBufferUsage?: { COPY_SRC?: number } }).GPUBufferUsage\n\t\t?.COPY_SRC ?? 0x04;\nconst GPU_BUFFER_USAGE_UNIFORM =\n\t(globalThis as { GPUBufferUsage?: { UNIFORM?: number } }).GPUBufferUsage\n\t\t?.UNIFORM ?? 0x40;\nconst GPU_BUFFER_USAGE_MAP_READ =\n\t(globalThis as { GPUBufferUsage?: { MAP_READ?: number } }).GPUBufferUsage\n\t\t?.MAP_READ ?? 0x01;\nconst GPU_MAP_MODE_READ =\n\t(globalThis as { GPUMapMode?: { READ?: number } }).GPUMapMode?.READ ?? 0x01;\n\nexport async function getWebGpuCapabilities(): Promise<WebGpuCapabilities> {\n\tconst navGpu = getNavigatorGpu();\n\tif (!navGpu) {\n\t\treturn { supported: false, features: [] };\n\t}\n\tconst adapter = await navGpu.requestAdapter();\n\tif (!adapter) {\n\t\treturn { supported: false, features: [] };\n\t}\n\n\treturn {\n\t\tsupported: true,\n\t\tadapterName: adapter.info?.description ?? adapter.info?.vendor ?? \"unknown\",\n\t\tfeatures: Array.from(adapter.features),\n\t\tlimits: {\n\t\t\tmaxStorageBufferBindingSize: Number(\n\t\t\t\tadapter.limits.maxStorageBufferBindingSize,\n\t\t\t),\n\t\t\tmaxComputeInvocationsPerWorkgroup: Number(\n\t\t\t\tadapter.limits.maxComputeInvocationsPerWorkgroup,\n\t\t\t),\n\t\t\tmaxComputeWorkgroupSizeX: Number(adapter.limits.maxComputeWorkgroupSizeX),\n\t\t},\n\t};\n}\n\nasync function getContext(): Promise<WebGpuContext | null> {\n\tif (contextPromise) return contextPromise;\n\tcontextPromise = (async () => {\n\t\tconst navGpu = getNavigatorGpu();\n\t\tif (!navGpu) return null;\n\t\tconst adapter = await navGpu.requestAdapter();\n\t\tif (!adapter) return null;\n\t\tconst device = await adapter.requestDevice();\n\n\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: [\n\t\t\t\t{\n\t\t\t\t\tbinding: 0,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 1,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 2,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 3,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"uniform\" },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\n\t\tconst pipeline = device.createComputePipeline({\n\t\t\tlayout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),\n\t\t\tcompute: {\n\t\t\t\tmodule: device.createShaderModule({ code: BBOX_PREFILTER_SHADER }),\n\t\t\t\tentryPoint: \"main\",\n\t\t\t},\n\t\t});\n\n\t\treturn { device, pipeline, bindGroupLayout };\n\t})();\n\n\treturn contextPromise;\n}\n\nfunction align(value: number, step: number): number {\n\treturn Math.ceil(value / step) * step;\n}\n\nexport async function prefilterPointsByBoundsWebGpu(\n\tpositions: Float32Array,\n\tpointCount: number,\n\tbounds: Float32Array,\n): Promise<Uint32Array | null> {\n\tconst ctx = await getContext();\n\tif (!ctx) return null;\n\n\tconst count = Math.max(0, Math.floor(pointCount));\n\tconst boundsCount = Math.max(0, Math.floor(bounds.length / 4));\n\tif (count === 0 || boundsCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst safePointCount = Math.min(count, Math.floor(positions.length / 2));\n\tif (safePointCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positionBytes = safePointCount * 2 * Float32Array.BYTES_PER_ELEMENT;\n\tconst boundsBytes = boundsCount * 4 * Float32Array.BYTES_PER_ELEMENT;\n\tconst outputBytes = safePointCount * Uint32Array.BYTES_PER_ELEMENT;\n\n\tconst limit = Number(ctx.device.limits.maxStorageBufferBindingSize);\n\tif (positionBytes > limit || boundsBytes > limit || outputBytes > limit) {\n\t\treturn null;\n\t}\n\n\tconst positionsBuffer = ctx.device.createBuffer({\n\t\tsize: align(positionBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst boundsBuffer = ctx.device.createBuffer({\n\t\tsize: align(boundsBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst outputBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC,\n\t});\n\tconst uniformBuffer = ctx.device.createBuffer({\n\t\tsize: 16,\n\t\tusage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst readBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_MAP_READ,\n\t});\n\n\tlet readBufferMapped = false;\n\ttry {\n\t\tctx.device.queue.writeBuffer(\n\t\t\tpositionsBuffer,\n\t\t\t0,\n\t\t\tpositions.buffer,\n\t\t\tpositions.byteOffset,\n\t\t\tpositionBytes,\n\t\t);\n\t\tctx.device.queue.writeBuffer(\n\t\t\tboundsBuffer,\n\t\t\t0,\n\t\t\tbounds.buffer,\n\t\t\tbounds.byteOffset,\n\t\t\tboundsBytes,\n\t\t);\n\t\tctx.device.queue.writeBuffer(\n\t\t\tuniformBuffer,\n\t\t\t0,\n\t\t\tnew Uint32Array([safePointCount, boundsCount, 0, 0]),\n\t\t);\n\n\t\tconst bindGroup = ctx.device.createBindGroup({\n\t\t\tlayout: ctx.bindGroupLayout,\n\t\t\tentries: [\n\t\t\t\t{ binding: 0, resource: { buffer: positionsBuffer } },\n\t\t\t\t{ binding: 1, resource: { buffer: boundsBuffer } },\n\t\t\t\t{ binding: 2, resource: { buffer: outputBuffer } },\n\t\t\t\t{ binding: 3, resource: { buffer: uniformBuffer } },\n\t\t\t],\n\t\t});\n\n\t\tconst commandEncoder = ctx.device.createCommandEncoder();\n\t\tconst pass = commandEncoder.beginComputePass();\n\t\tpass.setPipeline(ctx.pipeline);\n\t\tpass.setBindGroup(0, bindGroup);\n\t\tpass.dispatchWorkgroups(Math.ceil(safePointCount / 256));\n\t\tpass.end();\n\n\t\tcommandEncoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, outputBytes);\n\t\tctx.device.queue.submit([commandEncoder.finish()]);\n\n\t\tawait readBuffer.mapAsync(GPU_MAP_MODE_READ);\n\t\treadBufferMapped = true;\n\t\tconst mapped = readBuffer.getMappedRange();\n\t\treturn new Uint32Array(mapped.slice(0));\n\t} finally {\n\t\tif (readBufferMapped) {\n\t\t\ttry {\n\t\t\t\treadBuffer.unmap();\n\t\t\t} catch {\n\t\t\t\t// Already unmapped or map failed after resolving.\n\t\t\t}\n\t\t}\n\t\tpositionsBuffer.destroy();\n\t\tboundsBuffer.destroy();\n\t\toutputBuffer.destroy();\n\t\tuniformBuffer.destroy();\n\t\treadBuffer.destroy();\n\t}\n}\n","import { filterPointDataByPolygons, type RoiPolygon } from \"./point-clip\";\nimport {\n pointInAnyPreparedPolygon,\n prepareRoiPolygons,\n} from \"./roi-geometry\";\nimport type { WsiPointData } from \"./types\";\nimport { nowMs, sanitizePointCount } from \"./utils\";\nimport { prefilterPointsByBoundsWebGpu } from \"./webgpu\";\n\nexport interface HybridPointClipOptions {\n bridgeToDraw?: boolean;\n}\n\nexport interface HybridPointClipResult {\n data: WsiPointData | null;\n meta: {\n mode: \"hybrid-webgpu\";\n durationMs: number;\n usedWebGpu: boolean;\n candidateCount: number;\n bridgedToDraw?: boolean;\n };\n}\n\nexport async function filterPointDataByPolygonsHybrid(\n pointData: WsiPointData | null | undefined,\n polygons: RoiPolygon[] | null | undefined,\n options: HybridPointClipOptions = {}\n): Promise<HybridPointClipResult> {\n const start = nowMs();\n const bridgeToDraw = options.bridgeToDraw === true;\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const prepared = prepareRoiPolygons(polygons ?? []);\n if (prepared.length === 0) {\n const data: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointData.fillModes instanceof Uint8Array) {\n data.fillModes = new Uint8Array(0);\n }\n if (pointData.ids instanceof Uint32Array) {\n data.ids = new Uint32Array(0);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const safeCount = sanitizePointCount(pointData);\n const pointFillModes = pointData.fillModes instanceof Uint8Array && pointData.fillModes.length >= safeCount ? pointData.fillModes : null;\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids : null;\n if (safeCount === 0) {\n const data: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointFillModes) {\n data.fillModes = new Uint8Array(0);\n }\n if (pointIds) {\n data.ids = new Uint32Array(0);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const bboxFlat = new Float32Array(prepared.length * 4);\n for (let i = 0; i < prepared.length; i += 1) {\n const base = i * 4;\n const polygon = prepared[i];\n bboxFlat[base] = polygon.minX;\n bboxFlat[base + 1] = polygon.minY;\n bboxFlat[base + 2] = polygon.maxX;\n bboxFlat[base + 3] = polygon.maxY;\n }\n\n let candidateMask: Uint32Array | null = null;\n let usedWebGpu = false;\n try {\n candidateMask = await prefilterPointsByBoundsWebGpu(pointData.positions, safeCount, bboxFlat);\n usedWebGpu = !!candidateMask;\n } catch {\n candidateMask = null;\n usedWebGpu = false;\n }\n\n if (!candidateMask) {\n const fallback = filterPointDataByPolygons(pointData, polygons);\n return {\n data: fallback,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: safeCount,\n bridgedToDraw: false,\n },\n };\n }\n\n let candidateCount = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] === 1) candidateCount += 1;\n }\n\n const candidateIndices = new Uint32Array(candidateCount);\n if (candidateCount > 0) {\n let candidateCursor = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] !== 1) continue;\n candidateIndices[candidateCursor] = i;\n candidateCursor += 1;\n }\n }\n\n if (candidateCount === 0) {\n if (bridgeToDraw) {\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: new Uint32Array(0),\n };\n if (pointFillModes) {\n data.fillModes = pointFillModes.subarray(0, safeCount);\n }\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: true,\n },\n };\n }\n\n const data: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointFillModes) {\n data.fillModes = new Uint8Array(0);\n }\n if (pointIds) {\n data.ids = new Uint32Array(0);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n if (bridgeToDraw) {\n const drawIndices = new Uint32Array(candidateCount);\n let visibleCount = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n drawIndices[visibleCount] = pointIndex;\n visibleCount += 1;\n }\n\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: drawIndices.subarray(0, visibleCount),\n };\n if (pointFillModes) {\n data.fillModes = pointFillModes.subarray(0, safeCount);\n }\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: true,\n },\n };\n }\n\n const nextPositions = new Float32Array(candidateCount * 2);\n const nextClasses = new Uint16Array(candidateCount);\n const nextFillModes = pointFillModes ? new Uint8Array(candidateCount) : null;\n const nextIds = pointIds ? new Uint32Array(candidateCount) : null;\n let cursor = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextClasses[cursor] = pointData.paletteIndices[pointIndex];\n if (nextFillModes) {\n nextFillModes[cursor] = pointFillModes![pointIndex];\n }\n if (nextIds) {\n nextIds[cursor] = pointIds![pointIndex];\n }\n cursor += 1;\n }\n\n const compactData: WsiPointData = {\n count: cursor,\n positions: nextPositions.subarray(0, cursor * 2),\n paletteIndices: nextClasses.subarray(0, cursor),\n };\n if (nextFillModes) {\n compactData.fillModes = nextFillModes.subarray(0, cursor);\n }\n if (nextIds) {\n compactData.ids = nextIds.subarray(0, cursor);\n }\n\n return {\n data: compactData,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: false,\n },\n };\n}\n","export interface WorkerClientHandlers<Res extends { id: number }, Pending> {\n onResponse: (message: Res, pending: Pending) => void;\n rejectPending: (pending: Pending, error: Error) => void;\n}\n\nexport class WorkerClient<Res extends { id: number }, Pending> {\n private worker: Worker | null = null;\n private supported = true;\n private requestId = 1;\n private readonly pendingById = new Map<number, Pending>();\n\n private readonly handleMessage = (event: MessageEvent<Res>): void => {\n const message = event.data;\n if (!message) return;\n const pending = this.pendingById.get(message.id);\n if (!pending) return;\n this.pendingById.delete(message.id);\n this.handlers.onResponse(message, pending);\n };\n\n private readonly handleError = (): void => {\n this.supported = false;\n this.teardownWorker(\"worker crashed\");\n };\n\n constructor(\n private readonly createWorker: () => Worker,\n private readonly handlers: WorkerClientHandlers<Res, Pending>,\n ) {}\n\n beginRequest(pending: Pending): { id: number; worker: Worker } | null {\n const worker = this.getOrCreateWorker();\n if (!worker) return null;\n const id = this.requestId++;\n this.pendingById.set(id, pending);\n return { id, worker };\n }\n\n cancelRequest(id: number): Pending | undefined {\n const pending = this.pendingById.get(id);\n if (!pending) return undefined;\n this.pendingById.delete(id);\n return pending;\n }\n\n terminate(reason = \"worker terminated\"): void {\n this.teardownWorker(reason);\n }\n\n private getOrCreateWorker(): Worker | null {\n if (!this.supported) return null;\n if (this.worker) return this.worker;\n\n try {\n const worker = this.createWorker();\n worker.addEventListener(\"message\", this.handleMessage);\n worker.addEventListener(\"error\", this.handleError);\n this.worker = worker;\n return worker;\n } catch {\n this.supported = false;\n return null;\n }\n }\n\n private teardownWorker(reason: string): void {\n if (this.worker) {\n this.worker.removeEventListener(\"message\", this.handleMessage);\n this.worker.removeEventListener(\"error\", this.handleError);\n this.worker.terminate();\n this.worker = null;\n }\n\n const error = new Error(reason);\n for (const [, pending] of this.pendingById) {\n this.handlers.rejectPending(pending, error);\n }\n this.pendingById.clear();\n }\n}\n","import { filterPointDataByPolygons, filterPointIndicesByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { RoiClipWorkerRequest, RoiClipWorkerResponse } from \"./point-clip-worker-protocol\";\nimport type { WsiPointData } from \"./types\";\nimport { nowMs, sanitizePointCount } from \"./utils\";\nimport { WorkerClient } from \"./worker-client\";\n\nexport type PointClipMode = \"sync\" | \"worker\" | \"hybrid-webgpu\";\n\nexport interface PointClipResultMeta {\n mode: PointClipMode;\n durationMs: number;\n}\n\nexport interface PointClipResult {\n data: WsiPointData | null;\n meta: PointClipResultMeta;\n}\n\nexport interface PointClipIndexResult {\n indices: Uint32Array;\n meta: PointClipResultMeta;\n}\n\ninterface PendingDataWorkerRequest {\n kind: \"data\";\n resolve: (result: PointClipResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ninterface PendingIndexWorkerRequest {\n kind: \"index\";\n resolve: (result: PointClipIndexResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ntype PendingWorkerRequest = PendingDataWorkerRequest | PendingIndexWorkerRequest;\n\nconst workerClient = new WorkerClient<RoiClipWorkerResponse, PendingWorkerRequest>(\n () => new Worker(new URL(\"../workers/roi-clip-worker.ts\", import.meta.url), { type: \"module\" }),\n {\n onResponse: (msg, pending) => {\n if (msg.type === \"roi-clip-failure\") {\n pending.reject(new Error(msg.error || \"worker clip failed\"));\n return;\n }\n\n if (msg.type === \"roi-clip-index-success\") {\n if (pending.kind !== \"index\") {\n pending.reject(new Error(\"worker response mismatch: expected point data result\"));\n return;\n }\n const count = Math.max(0, Math.floor(msg.count));\n const indices = new Uint32Array(msg.indices).subarray(0, count);\n pending.resolve({\n indices,\n meta: {\n mode: \"worker\",\n durationMs:\n Number.isFinite(msg.durationMs)\n ? msg.durationMs\n : nowMs() - pending.startMs,\n },\n });\n return;\n }\n\n if (pending.kind !== \"data\") {\n pending.reject(new Error(\"worker response mismatch: expected index result\"));\n return;\n }\n\n const count = Math.max(0, Math.floor(msg.count));\n const positions = new Float32Array(msg.positions);\n const paletteIndices = new Uint16Array(msg.paletteIndices);\n const fillModes = msg.fillModes ? new Uint8Array(msg.fillModes) : null;\n const ids = msg.ids ? new Uint32Array(msg.ids) : null;\n const output: WsiPointData = {\n count,\n positions: positions.subarray(0, count * 2),\n paletteIndices: paletteIndices.subarray(0, count),\n };\n if (fillModes) {\n output.fillModes = fillModes.subarray(0, count);\n }\n if (ids) {\n output.ids = ids.subarray(0, count);\n }\n\n pending.resolve({\n data: output,\n meta: {\n mode: \"worker\",\n durationMs:\n Number.isFinite(msg.durationMs)\n ? msg.durationMs\n : nowMs() - pending.startMs,\n },\n });\n },\n rejectPending: (pending, error) => {\n pending.reject(error);\n },\n },\n);\n\nexport function terminateRoiClipWorker(): void {\n workerClient.terminate(\"worker terminated\");\n}\n\nexport async function filterPointDataByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const safeCount = sanitizePointCount(pointData);\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const classesCopy = pointData.paletteIndices.slice(0, safeCount);\n const fillModesCopy = pointData.fillModes instanceof Uint8Array && pointData.fillModes.length >= safeCount ? pointData.fillModes.slice(0, safeCount) : null;\n const idsCopy = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.slice(0, safeCount) : null;\n\n return new Promise<PointClipResult>((resolve, reject) => {\n const startMs = nowMs();\n const requestTicket = workerClient.beginRequest({\n kind: \"data\",\n resolve,\n reject,\n startMs,\n });\n\n if (!requestTicket) {\n resolve({\n data: filterPointDataByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - startMs },\n });\n return;\n }\n\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-request\",\n id: requestTicket.id,\n count: safeCount,\n positions: positionsCopy.buffer,\n paletteIndices: classesCopy.buffer,\n fillModes: fillModesCopy?.buffer,\n ids: idsCopy?.buffer,\n polygons: polygons ?? [],\n };\n\n const transfer: Transferable[] = [positionsCopy.buffer, classesCopy.buffer];\n if (fillModesCopy) transfer.push(fillModesCopy.buffer);\n if (idsCopy) transfer.push(idsCopy.buffer);\n\n try {\n requestTicket.worker.postMessage(msg, transfer);\n } catch (error) {\n const canceled = workerClient.cancelRequest(requestTicket.id);\n if (canceled) {\n canceled.reject(error);\n } else {\n reject(error);\n }\n }\n });\n}\n\nexport async function filterPointIndicesByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipIndexResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n indices: new Uint32Array(0),\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const safeCount = sanitizePointCount(pointData);\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n\n return new Promise<PointClipIndexResult>((resolve, reject) => {\n const startMs = nowMs();\n const requestTicket = workerClient.beginRequest({\n kind: \"index\",\n resolve,\n reject,\n startMs,\n });\n\n if (!requestTicket) {\n resolve({\n indices: filterPointIndicesByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - startMs },\n });\n return;\n }\n\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-index-request\",\n id: requestTicket.id,\n count: safeCount,\n positions: positionsCopy.buffer,\n polygons: polygons ?? [],\n };\n\n try {\n requestTicket.worker.postMessage(msg, [positionsCopy.buffer]);\n } catch (error) {\n const canceled = workerClient.cancelRequest(requestTicket.id);\n if (canceled) {\n canceled.reject(error);\n } else {\n reject(error);\n }\n }\n });\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { filterPointDataByPolygons, type RoiPolygon } from \"../wsi/point-clip\";\nimport { filterPointDataByPolygonsHybrid } from \"../wsi/point-clip-hybrid\";\nimport { filterPointDataByPolygonsInWorker, type PointClipMode } from \"../wsi/point-clip-worker-client\";\nimport { toRoiGeometry } from \"../wsi/roi-geometry\";\nimport type { WsiPointData, WsiRegion } from \"../wsi/types\";\nimport type { PointClipStatsEvent } from \"./wsi-viewer-canvas-types\";\n\nconst EMPTY_CLIPPED_POINTS: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n};\n\nexport function usePointClipping(\n clipPointsToRois: boolean,\n clipMode: PointClipMode,\n pointData: WsiPointData | null,\n effectiveRoiRegions: WsiRegion[],\n onClipStats?: (event: PointClipStatsEvent) => void,\n): WsiPointData | null {\n const clipRunIdRef = useRef(0);\n const [renderPointData, setRenderPointData] = useState<WsiPointData | null>(pointData);\n\n const clipPolygons = useMemo<RoiPolygon[]>(\n () => effectiveRoiRegions.map(region => toRoiGeometry(region.coordinates)).filter((p): p is RoiPolygon => p != null),\n [effectiveRoiRegions],\n );\n\n useEffect(() => {\n const runId = ++clipRunIdRef.current;\n let cancelled = false;\n\n if (!clipPointsToRois) {\n setRenderPointData(pointData);\n return () => {\n cancelled = true;\n };\n }\n\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n setRenderPointData(null);\n return () => {\n cancelled = true;\n };\n }\n\n if (clipPolygons.length === 0) {\n setRenderPointData(EMPTY_CLIPPED_POINTS);\n onClipStats?.({\n mode: clipMode,\n durationMs: 0,\n inputCount: pointData.count,\n outputCount: 0,\n polygonCount: 0,\n });\n return () => {\n cancelled = true;\n };\n }\n\n const applyResult = (data: WsiPointData | null, stats: Omit<PointClipStatsEvent, \"inputCount\" | \"outputCount\" | \"polygonCount\">) => {\n if (cancelled || runId !== clipRunIdRef.current) return;\n const inputCount = pointData.count;\n const outputCount = data?.drawIndices ? data.drawIndices.length : (data?.count ?? 0);\n setRenderPointData(data);\n onClipStats?.({\n mode: stats.mode,\n durationMs: stats.durationMs,\n inputCount,\n outputCount,\n polygonCount: clipPolygons.length,\n usedWebGpu: stats.usedWebGpu,\n candidateCount: stats.candidateCount,\n bridgedToDraw: stats.bridgedToDraw,\n });\n };\n\n const run = async (): Promise<void> => {\n if (clipMode === \"sync\") {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n return;\n }\n\n if (clipMode === \"hybrid-webgpu\") {\n const result = await filterPointDataByPolygonsHybrid(pointData, clipPolygons, { bridgeToDraw: true });\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n usedWebGpu: result.meta.usedWebGpu,\n candidateCount: result.meta.candidateCount,\n bridgedToDraw: result.meta.bridgedToDraw,\n });\n return;\n }\n\n try {\n const result = await filterPointDataByPolygonsInWorker(pointData, clipPolygons);\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n });\n } catch {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n }\n };\n\n void run();\n return () => {\n cancelled = true;\n };\n }, [clipPointsToRois, clipMode, pointData, clipPolygons, onClipStats]);\n\n return renderPointData;\n}\n","export const MIN_POINT_HIT_GRID_SIZE = 24;\nexport const MAX_POINT_HIT_GRID_SIZE = 1024;\nexport const POINT_HIT_GRID_DENSITY_SCALE = 4;\nexport const HASH_EMPTY = -1;\n\nexport interface PointHitIndexBuildInput {\n count: number;\n positions: Float32Array;\n drawIndices?: Uint32Array | null;\n sourceWidth: number;\n sourceHeight: number;\n}\n\nexport interface PointHitIndexBuildResult {\n cellSize: number;\n safeCount: number;\n cellCount: number;\n hashCapacity: number;\n hashTable: Int32Array;\n cellKeys: Int32Array;\n cellOffsets: Uint32Array;\n cellLengths: Uint32Array;\n pointIndices: Uint32Array;\n}\n\nexport function cellHash(cellX: number, cellY: number, mask: number): number {\n return (((cellX * 73856093) ^ (cellY * 19349663)) >>> 0) & mask;\n}\n\nfunction resolveGridSize(sourceWidth: number, sourceHeight: number, visibleCount: number): number {\n if (sourceWidth <= 0 || sourceHeight <= 0 || visibleCount <= 0) return 256;\n const area = Math.max(1, sourceWidth * sourceHeight);\n const avgSpacing = Math.sqrt(area / Math.max(1, visibleCount));\n const raw = avgSpacing * POINT_HIT_GRID_DENSITY_SCALE;\n return Math.max(MIN_POINT_HIT_GRID_SIZE, Math.min(MAX_POINT_HIT_GRID_SIZE, raw));\n}\n\nfunction sanitizeDrawIndices(raw: Uint32Array | null | undefined, safeCount: number): Uint32Array | null {\n if (!(raw instanceof Uint32Array) || raw.length === 0) {\n return null;\n }\n\n let allValid = true;\n for (let i = 0; i < raw.length; i += 1) {\n if (raw[i] < safeCount) continue;\n allValid = false;\n break;\n }\n if (allValid) {\n return raw;\n }\n\n const filtered = new Uint32Array(raw.length);\n let cursor = 0;\n for (let i = 0; i < raw.length; i += 1) {\n if (raw[i] >= safeCount) continue;\n filtered[cursor] = raw[i];\n cursor += 1;\n }\n return cursor > 0 ? filtered.subarray(0, cursor) : null;\n}\n\nexport function buildPointHitIndex(input: PointHitIndexBuildInput): PointHitIndexBuildResult | null {\n const count = Math.max(0, Math.floor(input.count));\n const maxCountByPositions = Math.floor(input.positions.length / 2);\n const safeCount = Math.max(0, Math.min(count, maxCountByPositions));\n if (safeCount <= 0) {\n return null;\n }\n\n const drawIndices = sanitizeDrawIndices(input.drawIndices ?? null, safeCount);\n const visibleCount = drawIndices ? drawIndices.length : safeCount;\n if (visibleCount === 0) {\n return null;\n }\n\n const cellSize = resolveGridSize(input.sourceWidth, input.sourceHeight, visibleCount);\n const invCellSize = 1.0 / cellSize;\n\n const pointCellX = new Int32Array(visibleCount);\n const pointCellY = new Int32Array(visibleCount);\n let validCount = 0;\n\n if (drawIndices) {\n for (let i = 0; i < visibleCount; i += 1) {\n const pi = drawIndices[i];\n const px = input.positions[pi * 2];\n const py = input.positions[pi * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) continue;\n pointCellX[validCount] = Math.floor(px * invCellSize);\n pointCellY[validCount] = Math.floor(py * invCellSize);\n validCount += 1;\n }\n } else {\n for (let i = 0; i < safeCount; i += 1) {\n const px = input.positions[i * 2];\n const py = input.positions[i * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) continue;\n pointCellX[validCount] = Math.floor(px * invCellSize);\n pointCellY[validCount] = Math.floor(py * invCellSize);\n validCount += 1;\n }\n }\n\n if (validCount === 0) {\n return null;\n }\n\n let estimatedCells = Math.min(validCount, Math.max(64, validCount >>> 3));\n if (!Number.isFinite(estimatedCells) || estimatedCells <= 0) {\n estimatedCells = validCount;\n }\n\n let hashCapacity = 1;\n while (hashCapacity < estimatedCells * 2) hashCapacity <<= 1;\n let hashMask = hashCapacity - 1;\n\n let tempHashKeys = new Int32Array(hashCapacity * 2);\n let tempHashCounts = new Int32Array(hashCapacity);\n tempHashKeys.fill(0x7fffffff);\n let cellCount = 0;\n\n const pointCellSlot = new Int32Array(validCount);\n\n for (let i = 0; i < validCount; i += 1) {\n const cx = pointCellX[i];\n const cy = pointCellY[i];\n let slot = cellHash(cx, cy, hashMask);\n\n while (true) {\n const kx = tempHashKeys[slot * 2];\n if (kx === 0x7fffffff) {\n tempHashKeys[slot * 2] = cx;\n tempHashKeys[slot * 2 + 1] = cy;\n tempHashCounts[slot] = 1;\n pointCellSlot[i] = slot;\n cellCount += 1;\n\n if (cellCount * 4 > hashCapacity * 3) {\n const oldCap = hashCapacity;\n hashCapacity <<= 1;\n hashMask = hashCapacity - 1;\n\n const newKeys = new Int32Array(hashCapacity * 2);\n const newCounts = new Int32Array(hashCapacity);\n newKeys.fill(0x7fffffff);\n\n for (let s = 0; s < oldCap; s += 1) {\n if (tempHashKeys[s * 2] === 0x7fffffff) continue;\n const ocx = tempHashKeys[s * 2];\n const ocy = tempHashKeys[s * 2 + 1];\n let ns = cellHash(ocx, ocy, hashMask);\n while (newKeys[ns * 2] !== 0x7fffffff) ns = (ns + 1) & hashMask;\n newKeys[ns * 2] = ocx;\n newKeys[ns * 2 + 1] = ocy;\n newCounts[ns] = tempHashCounts[s];\n }\n\n tempHashKeys = newKeys;\n tempHashCounts = newCounts;\n\n slot = cellHash(cx, cy, hashMask);\n while (\n tempHashKeys[slot * 2] !== cx ||\n tempHashKeys[slot * 2 + 1] !== cy\n ) {\n slot = (slot + 1) & hashMask;\n }\n pointCellSlot[i] = slot;\n }\n break;\n }\n\n if (kx === cx && tempHashKeys[slot * 2 + 1] === cy) {\n tempHashCounts[slot] += 1;\n pointCellSlot[i] = slot;\n break;\n }\n\n slot = (slot + 1) & hashMask;\n }\n }\n\n const cellKeys = new Int32Array(cellCount * 2);\n const cellOffsets = new Uint32Array(cellCount);\n const cellLengths = new Uint32Array(cellCount);\n const slotToCellIndex = new Int32Array(hashCapacity);\n slotToCellIndex.fill(HASH_EMPTY);\n\n let cellIdx = 0;\n let offset = 0;\n for (let s = 0; s < hashCapacity; s += 1) {\n if (tempHashKeys[s * 2] === 0x7fffffff) continue;\n cellKeys[cellIdx * 2] = tempHashKeys[s * 2];\n cellKeys[cellIdx * 2 + 1] = tempHashKeys[s * 2 + 1];\n cellOffsets[cellIdx] = offset;\n cellLengths[cellIdx] = tempHashCounts[s];\n slotToCellIndex[s] = cellIdx;\n offset += tempHashCounts[s];\n cellIdx += 1;\n }\n\n const pointIndices = new Uint32Array(validCount);\n const fillCursor = new Uint32Array(cellCount);\n fillCursor.set(cellOffsets);\n\n if (drawIndices) {\n for (let i = 0; i < validCount; i += 1) {\n const ci = slotToCellIndex[pointCellSlot[i]];\n pointIndices[fillCursor[ci]] = drawIndices[i];\n fillCursor[ci] += 1;\n }\n } else {\n let srcIdx = 0;\n for (let i = 0; i < safeCount; i += 1) {\n const px = input.positions[i * 2];\n const py = input.positions[i * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) continue;\n const ci = slotToCellIndex[pointCellSlot[srcIdx]];\n pointIndices[fillCursor[ci]] = i;\n fillCursor[ci] += 1;\n srcIdx += 1;\n }\n }\n\n let finalCap = 1;\n while (finalCap < cellCount * 2) finalCap <<= 1;\n const finalMask = finalCap - 1;\n const hashTable = new Int32Array(finalCap);\n hashTable.fill(HASH_EMPTY);\n\n for (let i = 0; i < cellCount; i += 1) {\n const cx = cellKeys[i * 2];\n const cy = cellKeys[i * 2 + 1];\n let slot = cellHash(cx, cy, finalMask);\n while (hashTable[slot] !== HASH_EMPTY) slot = (slot + 1) & finalMask;\n hashTable[slot] = i;\n }\n\n return {\n cellSize,\n safeCount,\n cellCount,\n hashCapacity: finalCap,\n hashTable,\n cellKeys,\n cellOffsets,\n cellLengths,\n pointIndices,\n };\n}\n","import { HASH_EMPTY, buildPointHitIndex, cellHash } from \"./point-hit-index-shared\";\nimport type {\n PointHitIndexWorkerRequest,\n PointHitIndexWorkerResponse,\n PointHitIndexWorkerSuccess,\n} from \"./point-hit-index-worker-protocol\";\nimport type { WsiImageSource, WsiPointData } from \"./types\";\nimport { sanitizePointCount } from \"./utils\";\nimport { WorkerClient } from \"./worker-client\";\n\nexport interface FlatPointSpatialIndex {\n cellSize: number;\n safeCount: number;\n positions: Float32Array;\n ids: Uint32Array | null;\n hashCapacity: number;\n hashMask: number;\n hashTable: Int32Array;\n cellKeys: Int32Array;\n cellOffsets: Uint32Array;\n cellLengths: Uint32Array;\n pointIndices: Uint32Array;\n}\n\nexport function lookupCellIndex(\n index: FlatPointSpatialIndex,\n cellX: number,\n cellY: number,\n): number {\n const { hashTable, cellKeys, hashMask } = index;\n let slot = cellHash(cellX, cellY, hashMask);\n while (true) {\n const ci = hashTable[slot];\n if (ci === HASH_EMPTY) return -1;\n if (cellKeys[ci * 2] === cellX && cellKeys[ci * 2 + 1] === cellY) return ci;\n slot = (slot + 1) & hashMask;\n }\n}\n\ninterface PendingRequest {\n resolve: (result: FlatPointSpatialIndex | null) => void;\n reject: (reason?: unknown) => void;\n pointData: WsiPointData;\n}\n\nfunction buildFromResponse(msg: PointHitIndexWorkerSuccess, pointData: WsiPointData): FlatPointSpatialIndex | null {\n if (msg.safeCount <= 0 || msg.cellCount <= 0) return null;\n\n const safeCount = msg.safeCount;\n return {\n cellSize: msg.cellSize,\n safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n ids:\n pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount\n ? pointData.ids.subarray(0, safeCount)\n : null,\n hashCapacity: msg.hashCapacity,\n hashMask: msg.hashCapacity - 1,\n hashTable: new Int32Array(msg.hashTable),\n cellKeys: new Int32Array(msg.cellKeys),\n cellOffsets: new Uint32Array(msg.cellOffsets),\n cellLengths: new Uint32Array(msg.cellLengths),\n pointIndices: new Uint32Array(msg.pointIndices),\n };\n}\n\nconst workerClient = new WorkerClient<PointHitIndexWorkerResponse, PendingRequest>(\n () =>\n new Worker(new URL(\"../workers/point-hit-index-worker.ts\", import.meta.url), {\n type: \"module\",\n }),\n {\n onResponse: (message, pending) => {\n if (message.type === \"point-hit-index-failure\") {\n pending.reject(new Error(message.error || \"worker index build failed\"));\n return;\n }\n pending.resolve(buildFromResponse(message, pending.pointData));\n },\n rejectPending: (pending, error) => {\n pending.reject(error);\n },\n },\n);\n\nexport function terminatePointHitIndexWorker(): void {\n workerClient.terminate(\"worker terminated\");\n}\n\nfunction buildSyncFallback(\n pointData: WsiPointData,\n source: WsiImageSource | null,\n): FlatPointSpatialIndex | null {\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) return null;\n\n const positions = pointData.positions.subarray(0, safeCount * 2);\n const result = buildPointHitIndex({\n count: safeCount,\n positions,\n drawIndices:\n pointData.drawIndices instanceof Uint32Array ? pointData.drawIndices : null,\n sourceWidth: source?.width ?? 0,\n sourceHeight: source?.height ?? 0,\n });\n if (!result) return null;\n\n return {\n cellSize: result.cellSize,\n safeCount,\n positions,\n ids:\n pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount\n ? pointData.ids.subarray(0, safeCount)\n : null,\n hashCapacity: result.hashCapacity,\n hashMask: result.hashCapacity - 1,\n hashTable: result.hashTable,\n cellKeys: result.cellKeys,\n cellOffsets: result.cellOffsets,\n cellLengths: result.cellLengths,\n pointIndices: result.pointIndices,\n };\n}\n\nexport async function buildPointSpatialIndexAsync(\n pointData: WsiPointData | null | undefined,\n source: WsiImageSource | null,\n): Promise<FlatPointSpatialIndex | null> {\n if (!pointData || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) return null;\n\n return new Promise<FlatPointSpatialIndex | null>((resolve, reject) => {\n const pending: PendingRequest = {\n resolve,\n reject,\n pointData,\n };\n const requestTicket = workerClient.beginRequest(pending);\n if (!requestTicket || !requestTicket.worker) {\n resolve(buildSyncFallback(pointData, source));\n return;\n }\n\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const drawIndicesCopy =\n pointData.drawIndices instanceof Uint32Array &&\n pointData.drawIndices.length > 0\n ? pointData.drawIndices.slice()\n : undefined;\n\n const msg: PointHitIndexWorkerRequest = {\n type: \"point-hit-index-request\",\n id: requestTicket.id,\n count: safeCount,\n positions: positionsCopy.buffer,\n drawIndices: drawIndicesCopy?.buffer,\n sourceWidth: source?.width ?? 0,\n sourceHeight: source?.height ?? 0,\n };\n const transfer: Transferable[] = [positionsCopy.buffer];\n if (drawIndicesCopy) transfer.push(drawIndicesCopy.buffer);\n\n try {\n requestTicket.worker.postMessage(msg, transfer);\n } catch (error) {\n const canceled = workerClient.cancelRequest(requestTicket.id);\n if (canceled) {\n canceled.reject(error);\n } else {\n reject(error);\n }\n }\n });\n}\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport { buildPointSpatialIndexAsync, type FlatPointSpatialIndex, lookupCellIndex } from \"../wsi/point-hit-index-worker-client\";\nimport type { WsiImageSource, WsiPointData } from \"../wsi/types\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate, DrawTool } from \"./draw-layer\";\nimport type { PointClickEvent, PointHitEvent, PointHoverEvent } from \"./wsi-viewer-canvas-types\";\n\nconst POINT_HIT_RADIUS_SCALE = 0.65;\nconst MIN_POINT_HIT_RADIUS_PX = 4;\n\nexport interface UsePointHitTestResult {\n getCellByCoordinates: (coordinate: DrawCoordinate) => PointHitEvent | null;\n emitPointHover: (hit: PointHitEvent | null, coordinate: DrawCoordinate | null) => void;\n emitPointClick: (coordinate: DrawCoordinate, button: number) => void;\n}\n\nexport function usePointHitTest(\n renderPointData: WsiPointData | null,\n source: WsiImageSource | null,\n onPointHover: ((event: PointHoverEvent) => void) | undefined,\n onPointClick: ((event: PointClickEvent) => void) | undefined,\n getCellByCoordinatesRef: MutableRefObject<((coordinate: DrawCoordinate) => PointHitEvent | null) | null> | undefined,\n drawTool: DrawTool,\n rendererRef: MutableRefObject<WsiTileRenderer | null>,\n pointLayerId?: string,\n): UsePointHitTestResult {\n const shouldEnablePointHitTest = Boolean(onPointHover || onPointClick || getCellByCoordinatesRef);\n const [pointSpatialIndex, setPointSpatialIndex] = useState<FlatPointSpatialIndex | null>(null);\n const hoveredPointIndexRef = useRef<number | null>(null);\n const hoveredPointIdRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (!shouldEnablePointHitTest || !renderPointData) {\n setPointSpatialIndex(null);\n return;\n }\n let cancelled = false;\n\n buildPointSpatialIndexAsync(renderPointData, source).then(nextIndex => {\n if (!cancelled) setPointSpatialIndex(nextIndex);\n });\n\n return () => {\n cancelled = true;\n };\n }, [shouldEnablePointHitTest, renderPointData, source]);\n\n const getCellByCoordinates = useCallback(\n (coordinate: DrawCoordinate): PointHitEvent | null => {\n const renderer = rendererRef.current;\n if (!renderer || !pointSpatialIndex) return null;\n\n const x = Number(coordinate[0]);\n const y = Number(coordinate[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\n const zoom = Math.max(1e-6, renderer.getViewState().zoom);\n const pointSizePx = renderer.getPointSize(pointLayerId);\n const hitRadiusPx = Math.max(MIN_POINT_HIT_RADIUS_PX, pointSizePx * POINT_HIT_RADIUS_SCALE);\n const hitRadiusWorld = hitRadiusPx / zoom;\n if (!Number.isFinite(hitRadiusWorld) || hitRadiusWorld <= 0) return null;\n\n const { cellSize, cellOffsets, cellLengths, pointIndices: idxBuf, positions: posBuf, safeCount } = pointSpatialIndex;\n const baseCellX = Math.floor(x / cellSize);\n const baseCellY = Math.floor(y / cellSize);\n const cellRadius = Math.max(1, Math.ceil(hitRadiusWorld / cellSize));\n const maxDist2 = hitRadiusWorld * hitRadiusWorld;\n\n let nearestIndex = -1;\n let nearestDist2 = maxDist2;\n let nearestX = 0;\n let nearestY = 0;\n\n for (let cx = baseCellX - cellRadius; cx <= baseCellX + cellRadius; cx += 1) {\n for (let cy = baseCellY - cellRadius; cy <= baseCellY + cellRadius; cy += 1) {\n const ci = lookupCellIndex(pointSpatialIndex, cx, cy);\n if (ci < 0) continue;\n\n const off = cellOffsets[ci];\n const end = off + cellLengths[ci];\n for (let i = off; i < end; i += 1) {\n const pointIndex = idxBuf[i];\n if (pointIndex >= safeCount) continue;\n\n const px = posBuf[pointIndex * 2];\n const py = posBuf[pointIndex * 2 + 1];\n const dx = px - x;\n const dy = py - y;\n const dist2 = dx * dx + dy * dy;\n if (dist2 > nearestDist2) continue;\n\n nearestDist2 = dist2;\n nearestIndex = pointIndex;\n nearestX = px;\n nearestY = py;\n }\n }\n }\n\n if (nearestIndex < 0) return null;\n const pointId = pointSpatialIndex.ids ? Number(pointSpatialIndex.ids[nearestIndex]) : null;\n return {\n index: nearestIndex,\n id: pointId,\n coordinate: [x, y],\n pointCoordinate: [nearestX, nearestY],\n };\n },\n [pointLayerId, pointSpatialIndex],\n );\n\n const emitPointHover = useCallback(\n (hit: PointHitEvent | null, coordinate: DrawCoordinate | null) => {\n if (!onPointHover) return;\n const nextIndex = hit?.index ?? null;\n const nextId = hit?.id ?? null;\n if (hoveredPointIndexRef.current === nextIndex && hoveredPointIdRef.current === nextId) return;\n hoveredPointIndexRef.current = nextIndex;\n hoveredPointIdRef.current = nextId;\n onPointHover({\n index: nextIndex,\n id: nextId,\n coordinate,\n pointCoordinate: hit?.pointCoordinate ?? null,\n });\n },\n [onPointHover],\n );\n\n const emitPointClick = useCallback(\n (coordinate: DrawCoordinate, button: number) => {\n if (!onPointClick) return;\n const hit = getCellByCoordinates(coordinate);\n if (!hit) return;\n onPointClick({\n ...hit,\n button,\n });\n },\n [onPointClick, getCellByCoordinates],\n );\n\n useEffect(() => {\n if (!getCellByCoordinatesRef) return;\n getCellByCoordinatesRef.current = getCellByCoordinates;\n return () => {\n if (getCellByCoordinatesRef.current === getCellByCoordinates) {\n getCellByCoordinatesRef.current = null;\n }\n };\n }, [getCellByCoordinatesRef, getCellByCoordinates]);\n\n useEffect(() => {\n const hoveredPointIndex = hoveredPointIndexRef.current;\n if (hoveredPointIndex === null) return;\n if (pointSpatialIndex && hoveredPointIndex < pointSpatialIndex.safeCount) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [pointSpatialIndex, onPointHover]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredPointIndexRef.current === null) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [drawTool, onPointHover]);\n\n return { getCellByCoordinates, emitPointHover, emitPointClick };\n}\n","import { forwardRef, useEffect, useImperativeHandle, useRef } from \"react\";\nimport type { PointClipMode } from \"../wsi/point-clip-worker-client\";\nimport type { WsiPointData, WsiRegion } from \"../wsi/types\";\nimport type { PointSizeByMagnification, PointSizeByZoom, PointWeightByMagnification } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate } from \"./draw-layer-types\";\nimport { usePointClipping } from \"./use-point-clipping\";\nimport { usePointHitTest } from \"./use-point-hit-test\";\nimport { useViewerContext } from \"./viewer-context\";\nimport type { PointClickEvent, PointClipStatsEvent, PointHitEvent, PointHoverEvent } from \"./wsi-viewer-canvas-types\";\n\nexport interface PointLayerProps {\n data?: WsiPointData | null;\n palette?: Uint8Array | null;\n sizeByZoom?: PointSizeByZoom;\n sizeByMagnification?: PointSizeByMagnification;\n weightByMagnification?: PointWeightByMagnification;\n opacity?: number;\n strokeScale?: number;\n innerFillOpacity?: number;\n innerFillColor?: string;\n clipEnabled?: boolean;\n clipToRegions?: WsiRegion[];\n clipMode?: PointClipMode;\n onClipStats?: (event: PointClipStatsEvent) => void;\n onHover?: (event: PointHoverEvent) => void;\n onClick?: (event: PointClickEvent) => void;\n dashed?: [number, number];\n}\n\nexport interface PointQueryHandle {\n queryAt: (coordinate: DrawCoordinate) => PointHitEvent | null;\n}\n\nlet nextPointLayerId = 0;\n\nexport const PointLayer = forwardRef<PointQueryHandle, PointLayerProps>(function PointLayer(\n {\n data = null,\n palette = null,\n sizeByZoom,\n sizeByMagnification,\n weightByMagnification,\n opacity,\n strokeScale,\n innerFillOpacity,\n innerFillColor,\n clipEnabled = false,\n clipToRegions,\n clipMode = \"worker\",\n onClipStats,\n onHover,\n onClick,\n dashed,\n },\n ref\n) {\n const { rendererRef, rendererSerial, source } = useViewerContext();\n const getCellByCoordinatesRef = useRef<((coordinate: DrawCoordinate) => PointHitEvent | null) | null>(null);\n const layerIdRef = useRef(`__point_layer__${nextPointLayerId++}`);\n\n const effectiveClipRegions = clipToRegions ?? EMPTY_REGIONS;\n\n const renderPointData = usePointClipping(clipEnabled, clipMode, data, effectiveClipRegions, onClipStats);\n\n const { getCellByCoordinates } = usePointHitTest(renderPointData, source, onHover, onClick, getCellByCoordinatesRef, \"cursor\", rendererRef, layerIdRef.current);\n\n useImperativeHandle(ref, () => ({ queryAt: getCellByCoordinates }), [getCellByCoordinates]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n const layerId = layerIdRef.current;\n renderer.registerPointLayer(layerId);\n return () => {\n renderer.unregisterPointLayer(layerId);\n };\n }, [rendererRef, rendererSerial]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointPalette(palette, layerIdRef.current);\n }, [rendererSerial, palette, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointLineDash(dashed, layerIdRef.current);\n }, [rendererSerial, dashed, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointSizeByZoom(sizeByZoom, layerIdRef.current);\n }, [rendererSerial, sizeByZoom, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointSizeByMagnification(sizeByMagnification, layerIdRef.current);\n }, [rendererSerial, sizeByMagnification, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointWeightByMagnification(weightByMagnification, layerIdRef.current);\n }, [rendererSerial, weightByMagnification, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || opacity === undefined) return;\n renderer.setPointOpacity(opacity, layerIdRef.current);\n }, [rendererSerial, opacity, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || strokeScale === undefined) return;\n renderer.setPointStrokeScale(strokeScale, layerIdRef.current);\n }, [rendererSerial, strokeScale, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || innerFillOpacity === undefined) return;\n renderer.setPointInnerFillOpacity(innerFillOpacity, layerIdRef.current);\n }, [rendererSerial, innerFillOpacity, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointInnerFillColor(innerFillColor, layerIdRef.current);\n }, [rendererSerial, innerFillColor, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointData(renderPointData, layerIdRef.current);\n }, [rendererSerial, renderPointData, rendererRef]);\n\n return null;\n});\n\nconst EMPTY_REGIONS: WsiRegion[] = [];\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport { clamp } from \"../wsi/utils\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport { resolveRegionLabelAutoLiftOffsetPx } from \"./draw-layer\";\n\nconst REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS = 180;\nconst REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX = 20;\n\nfunction smoothstep01(t: number): number {\n const x = clamp(t, 0, 1);\n return x * x * (3 - 2 * x);\n}\n\nexport interface UseRegionLabelAutoLiftResult {\n regionLabelAutoLiftOffsetPx: number;\n syncRegionLabelAutoLiftTarget: (zoom: number | null | undefined) => void;\n cancelRegionLabelAutoLiftAnimation: () => void;\n applyRegionLabelAutoLiftOffset: (next: number) => void;\n}\n\nexport function useRegionLabelAutoLift(\n autoLiftRegionLabelAtMaxZoom: boolean,\n rendererRef: MutableRefObject<WsiTileRenderer | null>,\n drawInvalidateRef: MutableRefObject<(() => void) | null>,\n): UseRegionLabelAutoLiftResult {\n const [regionLabelAutoLiftOffsetPx, setRegionLabelAutoLiftOffsetPx] = useState(0);\n const regionLabelAutoLiftOffsetRef = useRef(0);\n const regionLabelAutoLiftAnimationRef = useRef<{ rafId: number | null; startMs: number; from: number; to: number }>({\n rafId: null,\n startMs: 0,\n from: 0,\n to: 0,\n });\n\n const applyRegionLabelAutoLiftOffset = useCallback((next: number) => {\n const clamped = clamp(next, 0, REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX);\n if (Math.abs(regionLabelAutoLiftOffsetRef.current - clamped) < 1e-4) return;\n regionLabelAutoLiftOffsetRef.current = clamped;\n setRegionLabelAutoLiftOffsetPx(clamped);\n }, []);\n\n const cancelRegionLabelAutoLiftAnimation = useCallback(() => {\n const animation = regionLabelAutoLiftAnimationRef.current;\n if (animation.rafId !== null) {\n cancelAnimationFrame(animation.rafId);\n animation.rafId = null;\n }\n }, []);\n\n const animateRegionLabelAutoLiftTo = useCallback(\n (target: number) => {\n const clampedTarget = clamp(target, 0, REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX);\n const animation = regionLabelAutoLiftAnimationRef.current;\n const from = regionLabelAutoLiftOffsetRef.current;\n if (Math.abs(from - clampedTarget) < 1e-4) {\n cancelRegionLabelAutoLiftAnimation();\n animation.to = clampedTarget;\n applyRegionLabelAutoLiftOffset(clampedTarget);\n return;\n }\n\n cancelRegionLabelAutoLiftAnimation();\n animation.startMs = performance.now();\n animation.from = from;\n animation.to = clampedTarget;\n\n const step = (timestamp: number) => {\n const current = regionLabelAutoLiftAnimationRef.current;\n const elapsed = Math.max(0, timestamp - current.startMs);\n const rawT = REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS <= 0 ? 1 : clamp(elapsed / REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS, 0, 1);\n const eased = smoothstep01(rawT);\n const nextValue = current.from + (current.to - current.from) * eased;\n applyRegionLabelAutoLiftOffset(nextValue);\n drawInvalidateRef.current?.();\n\n if (rawT >= 1) {\n current.rafId = null;\n applyRegionLabelAutoLiftOffset(current.to);\n return;\n }\n current.rafId = requestAnimationFrame(step);\n };\n\n animation.rafId = requestAnimationFrame(step);\n },\n [applyRegionLabelAutoLiftOffset, cancelRegionLabelAutoLiftAnimation],\n );\n\n const syncRegionLabelAutoLiftTarget = useCallback(\n (zoom: number | null | undefined) => {\n const renderer = rendererRef.current;\n if (!renderer || typeof zoom !== \"number\" || !Number.isFinite(zoom)) {\n animateRegionLabelAutoLiftTo(0);\n return;\n }\n const target = resolveRegionLabelAutoLiftOffsetPx(autoLiftRegionLabelAtMaxZoom, zoom, renderer.getZoomRange(), renderer.getRegionLabelAutoLiftCapZoom());\n animateRegionLabelAutoLiftTo(target);\n },\n [autoLiftRegionLabelAtMaxZoom, animateRegionLabelAutoLiftTo],\n );\n\n useEffect(() => {\n return () => {\n cancelRegionLabelAutoLiftAnimation();\n };\n }, [cancelRegionLabelAutoLiftAnimation]);\n\n return {\n regionLabelAutoLiftOffsetPx,\n syncRegionLabelAutoLiftTarget,\n cancelRegionLabelAutoLiftAnimation,\n applyRegionLabelAutoLiftOffset,\n };\n}\n","import { type PreparedRoiPolygon, prepareRoiPolygons, toRoiGeometry } from \"../wsi/roi-geometry\";\nimport type { WsiRegion } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport { getTopAnchorFromProjectedPolygons, measureLabelTextWidth, mergeRegionLabelStyle } from \"./draw-layer-label\";\nimport type { DrawCoordinate, RegionLabelAnchorMode, RegionLabelStyle, RegionLabelStyleResolver } from \"./draw-layer-types\";\nimport { toDrawCoordinate } from \"./draw-layer-utils\";\n\nconst REGION_CONTOUR_HIT_DISTANCE_PX = 6;\n\nexport interface PreparedRegionHit {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n polygons: PreparedRoiPolygon[];\n label: string;\n}\n\nexport function resolveRegionId(region: WsiRegion, index: number): string | number {\n return region.id ?? index;\n}\n\nfunction pointSegmentDistanceSq(px: number, py: number, ax: number, ay: number, bx: number, by: number): number {\n const abx = bx - ax;\n const aby = by - ay;\n const lengthSq = abx * abx + aby * aby;\n if (lengthSq <= 1e-12) {\n const dx = px - ax;\n const dy = py - ay;\n return dx * dx + dy * dy;\n }\n const t = clamp(((px - ax) * abx + (py - ay) * aby) / lengthSq, 0, 1);\n const nx = ax + abx * t;\n const ny = ay + aby * t;\n const dx = px - nx;\n const dy = py - ny;\n return dx * dx + dy * dy;\n}\n\nfunction isPointNearRing(x: number, y: number, ring: DrawCoordinate[], maxDistanceSq: number): boolean {\n for (let i = 1; i < ring.length; i += 1) {\n const prev = ring[i - 1];\n const next = ring[i];\n if (pointSegmentDistanceSq(x, y, prev[0], prev[1], next[0], next[1]) <= maxDistanceSq) {\n return true;\n }\n }\n return false;\n}\n\nfunction isPointNearPolygonContour(x: number, y: number, polygon: PreparedRoiPolygon, maxDistance: number): boolean {\n if (x < polygon.minX - maxDistance || x > polygon.maxX + maxDistance || y < polygon.minY - maxDistance || y > polygon.maxY + maxDistance) {\n return false;\n }\n const maxDistanceSq = maxDistance * maxDistance;\n if (isPointNearRing(x, y, polygon.outer, maxDistanceSq)) return true;\n for (const hole of polygon.holes) {\n if (isPointNearRing(x, y, hole, maxDistanceSq)) return true;\n }\n return false;\n}\n\nexport function isScreenPointInsideLabel(\n region: PreparedRegionHit,\n screenCoord: DrawCoordinate,\n renderer: WsiTileRenderer,\n regionLabelAnchor: RegionLabelAnchorMode,\n labelStyle: RegionLabelStyle,\n canvasWidth: number,\n canvasHeight: number,\n clampToViewport: boolean\n): boolean {\n if (!region.label) return false;\n\n const anchorScreen = getTopAnchorFromProjectedPolygons(\n region.polygons,\n points => {\n const projected: DrawCoordinate[] = [];\n for (let i = 0; i < points.length; i += 1) {\n const coord = toDrawCoordinate(renderer.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n projected.push(coord);\n }\n return projected;\n },\n regionLabelAnchor\n );\n if (!anchorScreen) return false;\n\n const textWidth = measureLabelTextWidth(region.label, labelStyle);\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const rawX = anchorScreen[0];\n const rawY = anchorScreen[1] - labelStyle.offsetY;\n const x = clampToViewport ? clamp(rawX, boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1) : rawX;\n const y = clampToViewport ? clamp(rawY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1) : rawY;\n const left = x - boxWidth * 0.5;\n const right = x + boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n const bottom = y + boxHeight * 0.5;\n\n return screenCoord[0] >= left && screenCoord[0] <= right && screenCoord[1] >= top && screenCoord[1] <= bottom;\n}\n\nexport function prepareRegionHits(regions: WsiRegion[]): PreparedRegionHit[] {\n const out: PreparedRegionHit[] = [];\n for (let i = 0; i < regions.length; i += 1) {\n const region = regions[i];\n const polygons = prepareRoiPolygons([toRoiGeometry(region?.coordinates)]);\n if (polygons.length === 0) continue;\n const label = typeof region?.label === \"string\" ? region.label.trim() : \"\";\n out.push({\n region,\n regionIndex: i,\n regionId: resolveRegionId(region, i),\n polygons,\n label,\n });\n }\n return out;\n}\n\nexport function pickPreparedRegionAt(\n coord: DrawCoordinate,\n screenCoord: DrawCoordinate,\n regions: PreparedRegionHit[],\n renderer: WsiTileRenderer,\n regionLabelAnchor: RegionLabelAnchorMode,\n labelStyle: RegionLabelStyle,\n labelStyleResolver: RegionLabelStyleResolver | undefined,\n labelAutoLiftOffsetPx: number,\n canvasWidth: number,\n canvasHeight: number,\n clampRegionLabelToViewport = true\n): {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n} | null {\n const x = coord[0];\n const y = coord[1];\n const zoom = Math.max(1e-6, renderer.getViewState().zoom);\n const labelAutoLiftOffset = Math.max(0, labelAutoLiftOffsetPx);\n const contourHitDistance = REGION_CONTOUR_HIT_DISTANCE_PX / zoom;\n for (let i = regions.length - 1; i >= 0; i -= 1) {\n const region = regions[i];\n for (const polygon of region.polygons) {\n if (!isPointNearPolygonContour(x, y, polygon, contourHitDistance)) continue;\n return {\n region: region.region,\n regionIndex: region.regionIndex,\n regionId: region.regionId,\n };\n }\n let dynamicLabelStyle = mergeRegionLabelStyle(\n labelStyle,\n labelStyleResolver?.({\n region: region.region,\n regionId: region.regionId,\n regionIndex: region.regionIndex,\n zoom,\n })\n );\n if (labelAutoLiftOffset > 0) {\n dynamicLabelStyle = {\n ...dynamicLabelStyle,\n offsetY: dynamicLabelStyle.offsetY + labelAutoLiftOffset,\n };\n }\n if (!isScreenPointInsideLabel(region, screenCoord, renderer, regionLabelAnchor, dynamicLabelStyle, canvasWidth, canvasHeight, clampRegionLabelToViewport)) continue;\n return {\n region: region.region,\n regionIndex: region.regionIndex,\n regionId: region.regionId,\n };\n }\n return null;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { WsiRegion } from \"../wsi/types\";\nimport { drawRegionLabel, getTopAnchorFromProjectedPolygons, mergeRegionLabelStyle, resolveRegionLabelAutoLiftOffsetPx, resolveRegionLabelStyle } from \"./draw-layer-label\";\nimport type {\n DrawCoordinate,\n DrawRegionCoordinates,\n PreparedRenderedRegion,\n RegionLabelAnchorMode,\n RegionLabelStyle,\n RegionLabelStyleResolver,\n RegionStrokeStyle,\n RegionStrokeStyleResolver,\n} from \"./draw-layer-types\";\nimport { EMPTY_DASH, REGION_INTERACTION_SHADOW_COLOR, REGION_INTERACTION_SHADOW_WIDTH } from \"./draw-layer-types\";\nimport { drawPath, isSameRegionId, mergeStrokeStyle, normalizeDrawRegionPolygons, resolveStrokeStyle, toCoord } from \"./draw-layer-utils\";\nimport { useRegionLabelAutoLift } from \"./use-region-label-auto-lift\";\nimport { useViewerContext } from \"./viewer-context\";\nimport { pickPreparedRegionAt, prepareRegionHits, resolveRegionId } from \"./wsi-region-hit-utils\";\nimport type { RegionClickEvent, RegionHoverEvent } from \"./wsi-viewer-canvas-types\";\n\nexport interface RegionLayerProps {\n regions?: WsiRegion[];\n polygons?: DrawRegionCoordinates[];\n strokeStyle?: Partial<RegionStrokeStyle>;\n hoverStrokeStyle?: Partial<RegionStrokeStyle>;\n activeStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveStrokeStyle?: RegionStrokeStyleResolver;\n labelStyle?: Partial<RegionLabelStyle> | RegionLabelStyleResolver;\n labelAnchor?: RegionLabelAnchorMode;\n autoLiftLabelAtMaxZoom?: boolean;\n clampLabelToViewport?: boolean;\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n interactive?: boolean;\n onActiveChange?: (regionId: string | number | null) => void;\n onHover?: (event: RegionHoverEvent) => void;\n onClick?: (event: RegionClickEvent) => void;\n}\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawRegionCoordinates[] = [];\nlet nextRegionLayerInstanceId = 0;\n\nfunction resolveRegionInteractionShadow(strokeStyle: RegionStrokeStyle): RegionStrokeStyle {\n return {\n color: REGION_INTERACTION_SHADOW_COLOR,\n width: REGION_INTERACTION_SHADOW_WIDTH,\n lineDash: EMPTY_DASH,\n lineJoin: strokeStyle.lineJoin,\n lineCap: strokeStyle.lineCap,\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n };\n}\n\nexport function RegionLayer({\n regions,\n polygons,\n strokeStyle: strokeStyleProp,\n hoverStrokeStyle: hoverStrokeStyleProp,\n activeStrokeStyle: activeStrokeStyleProp,\n resolveStrokeStyle: resolveStrokeStyleProp,\n labelStyle: labelStyleProp,\n labelAnchor = \"top-center\",\n autoLiftLabelAtMaxZoom = false,\n clampLabelToViewport = true,\n hoveredRegionId: controlledHoveredRegionId,\n activeRegionId: controlledActiveRegionId,\n interactive = true,\n onActiveChange,\n onHover,\n onClick,\n}: RegionLayerProps): React.ReactElement | null {\n const { rendererRef, rendererSerial, canvasRef, containerRef, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw, drawInvalidateRef, registerViewStateListener, screenToWorld, worldToScreen, isInteractionLocked } = useViewerContext();\n\n const safeRegions = regions ?? EMPTY_ROI_REGIONS;\n const safePolygons = polygons ?? EMPTY_ROI_POLYGONS;\n\n const effectiveRegions = useMemo<WsiRegion[]>(() => {\n if (safeRegions.length > 0) return safeRegions;\n if (safePolygons.length === 0) return EMPTY_ROI_REGIONS;\n return safePolygons.map((coordinates, index) => ({ id: index, coordinates }));\n }, [safeRegions, safePolygons]);\n\n const [uncontrolledHoveredRegionId, setUncontrolledHoveredRegionId] = useState<string | number | null>(() => controlledHoveredRegionId ?? null);\n const [uncontrolledActiveRegionId, setUncontrolledActiveRegionId] = useState<string | number | null>(() => controlledActiveRegionId ?? null);\n const isHoverControlled = controlledHoveredRegionId !== undefined;\n const isControlled = controlledActiveRegionId !== undefined;\n const hoveredRegionId = isHoverControlled ? (controlledHoveredRegionId ?? null) : uncontrolledHoveredRegionId;\n const activeRegionId = isControlled ? (controlledActiveRegionId ?? null) : uncontrolledActiveRegionId;\n const hoveredRegionIdRef = useRef<string | number | null>(controlledHoveredRegionId ?? null);\n const drawCallbackIdRef = useRef<string | null>(null);\n const labelDrawCallbackIdRef = useRef<string | null>(null);\n\n if (drawCallbackIdRef.current === null || labelDrawCallbackIdRef.current === null) {\n const instanceId = nextRegionLayerInstanceId++;\n drawCallbackIdRef.current = `__region_layer__${instanceId}`;\n labelDrawCallbackIdRef.current = `__region_label__${instanceId}`;\n }\n\n useEffect(() => {\n if (!isControlled) return;\n setUncontrolledActiveRegionId(controlledActiveRegionId ?? null);\n }, [isControlled, controlledActiveRegionId]);\n\n useEffect(() => {\n if (!isHoverControlled) return;\n const next = controlledHoveredRegionId ?? null;\n hoveredRegionIdRef.current = next;\n setUncontrolledHoveredRegionId(next);\n }, [isHoverControlled, controlledHoveredRegionId]);\n\n const commitActive = useCallback(\n (next: string | number | null) => {\n if (String(activeRegionId) === String(next)) return;\n if (!isControlled) setUncontrolledActiveRegionId(next);\n onActiveChange?.(next);\n },\n [activeRegionId, isControlled, onActiveChange]\n );\n\n const { regionLabelAutoLiftOffsetPx, syncRegionLabelAutoLiftTarget } = useRegionLabelAutoLift(autoLiftLabelAtMaxZoom, rendererRef, drawInvalidateRef);\n\n const resolvedStrokeStyle = useMemo(() => resolveStrokeStyle(strokeStyleProp), [strokeStyleProp]);\n const resolvedHoverStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, hoverStrokeStyleProp), [resolvedStrokeStyle, hoverStrokeStyleProp]);\n const resolvedActiveStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, activeStrokeStyleProp), [resolvedStrokeStyle, activeStrokeStyleProp]);\n\n const { staticLabelStyle, labelStyleResolver } = useMemo(() => {\n if (typeof labelStyleProp === \"function\") {\n return { staticLabelStyle: undefined, labelStyleResolver: labelStyleProp };\n }\n return { staticLabelStyle: labelStyleProp, labelStyleResolver: undefined };\n }, [labelStyleProp]);\n\n const resolvedLabelStyle = useMemo(() => resolveRegionLabelStyle(staticLabelStyle), [staticLabelStyle]);\n\n const preparedRegions = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < effectiveRegions.length; i += 1) {\n const region = effectiveRegions[i];\n const polys = normalizeDrawRegionPolygons(region.coordinates);\n if (polys.length === 0) continue;\n out.push({ region, regionIndex: i, regionKey: region.id ?? i, polygons: polys });\n }\n return out;\n }, [effectiveRegions]);\n\n const preparedRegionHits = useMemo(() => prepareRegionHits(effectiveRegions), [effectiveRegions]);\n\n // sync label auto-lift target when zoom changes (rendererSerial: new renderer instance)\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n syncRegionLabelAutoLiftTarget(renderer.getViewState().zoom);\n return registerViewStateListener(next => {\n syncRegionLabelAutoLiftTarget(next.zoom);\n });\n }, [rendererSerial, registerViewStateListener, syncRegionLabelAutoLiftTarget]);\n\n // clean up stale hover/active on regions change\n useEffect(() => {\n const hasActive = activeRegionId === null ? true : effectiveRegions.some((r, i) => String(resolveRegionId(r, i)) === String(activeRegionId));\n if (!hasActive && activeRegionId !== null) commitActive(null);\n\n const currentHover = hoveredRegionIdRef.current;\n const hasHover = currentHover === null ? true : effectiveRegions.some((r, i) => String(resolveRegionId(r, i)) === String(currentHover));\n if (!hasHover && currentHover !== null) {\n hoveredRegionIdRef.current = null;\n if (!isHoverControlled) setUncontrolledHoveredRegionId(null);\n onHover?.({ region: null, regionId: null, regionIndex: -1, coordinate: null });\n }\n }, [effectiveRegions, activeRegionId, isHoverControlled, onHover, commitActive]);\n\n // worldToScreenPoints helper\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = rendererRef.current;\n if (!projector || points.length === 0) return [];\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n []\n );\n\n // --- register region polygon draw callback ---\n\n const regionDrawRef = useRef({\n preparedRegions,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n resolveStrokeStyleProp,\n worldToScreenPoints,\n });\n regionDrawRef.current = {\n preparedRegions,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n resolveStrokeStyleProp,\n worldToScreenPoints,\n };\n\n useEffect(() => {\n const drawRegions = (_ctx: CanvasRenderingContext2D) => {\n const {\n preparedRegions: prep,\n hoveredRegionId: hovered,\n activeRegionId: active,\n resolvedStrokeStyle: base,\n resolvedHoverStrokeStyle: hover,\n resolvedActiveStrokeStyle: activeS,\n resolveStrokeStyleProp: resolver,\n worldToScreenPoints: w2s,\n } = regionDrawRef.current;\n\n for (const entry of prep) {\n const { region, polygons: polys, regionIndex, regionKey } = entry;\n const state: \"default\" | \"hover\" | \"active\" = isSameRegionId(active, regionKey) ? \"active\" : isSameRegionId(hovered, regionKey) ? \"hover\" : \"default\";\n let style = state === \"active\" ? activeS : state === \"hover\" ? hover : base;\n\n if (resolver) {\n const resolved = resolver({ region, regionId: regionKey, regionIndex, state });\n style = mergeStrokeStyle(style, resolved || undefined);\n }\n const shadow = state === \"default\" ? null : resolveRegionInteractionShadow(style);\n\n for (const polygon of polys) {\n const screenOuter = w2s(polygon.outer);\n if (screenOuter.length >= 4) {\n if (shadow) drawPath(_ctx, screenOuter, shadow, true, false);\n drawPath(_ctx, screenOuter, style, true, false);\n }\n for (const hole of polygon.holes) {\n const screenHole = w2s(hole);\n if (screenHole.length >= 4) {\n if (shadow) drawPath(_ctx, screenHole, shadow, true, false);\n drawPath(_ctx, screenHole, style, true, false);\n }\n }\n }\n }\n };\n\n const drawId = drawCallbackIdRef.current;\n if (!drawId) return;\n registerDrawCallback(drawId, 10, drawRegions);\n return () => unregisterDrawCallback(drawId);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n // --- register region label draw callback ---\n\n const labelDrawRef = useRef({\n preparedRegions,\n resolvedLabelStyle,\n labelStyleResolver,\n labelAnchor,\n autoLiftLabelAtMaxZoom,\n clampLabelToViewport,\n regionLabelAutoLiftOffsetPx,\n rendererRef,\n });\n labelDrawRef.current = {\n preparedRegions,\n resolvedLabelStyle,\n labelStyleResolver,\n labelAnchor,\n autoLiftLabelAtMaxZoom,\n clampLabelToViewport,\n regionLabelAutoLiftOffsetPx,\n rendererRef,\n };\n\n useEffect(() => {\n const drawLabels = (ctx: CanvasRenderingContext2D, canvasWidth: number, canvasHeight: number) => {\n const {\n preparedRegions: prep,\n resolvedLabelStyle: labelS,\n labelStyleResolver: resolver,\n labelAnchor: anchor,\n autoLiftLabelAtMaxZoom: autoLift,\n clampLabelToViewport: clampVp,\n regionLabelAutoLiftOffsetPx: autoLiftPx,\n rendererRef: rRef,\n } = labelDrawRef.current;\n\n if (prep.length === 0) return;\n\n const zoom = Math.max(1e-6, rRef.current?.getViewState?.().zoom ?? 1);\n const labelAutoLiftOffset =\n typeof autoLiftPx === \"number\" && Number.isFinite(autoLiftPx)\n ? Math.max(0, autoLiftPx)\n : resolveRegionLabelAutoLiftOffsetPx(autoLift, zoom, rRef.current?.getZoomRange?.(), rRef.current?.getRegionLabelAutoLiftCapZoom?.());\n\n for (const entry of prep) {\n if (!entry.region.label) continue;\n const anchorScreen = getTopAnchorFromProjectedPolygons(\n entry.polygons,\n points => {\n const projector = rRef.current;\n if (!projector) return [];\n const out: DrawCoordinate[] = [];\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out.push(coord);\n }\n return out;\n },\n anchor\n );\n if (!anchorScreen) continue;\n\n let style = mergeRegionLabelStyle(labelS, resolver?.({ region: entry.region, regionId: entry.regionKey, regionIndex: entry.regionIndex, zoom }));\n if (labelAutoLiftOffset > 0) {\n style = { ...style, offsetY: style.offsetY + labelAutoLiftOffset };\n }\n drawRegionLabel(ctx, entry.region.label, anchorScreen, canvasWidth, canvasHeight, style, clampVp);\n }\n };\n\n const drawId = labelDrawCallbackIdRef.current;\n if (!drawId) return;\n registerDrawCallback(drawId, 50, drawLabels);\n return () => unregisterDrawCallback(drawId);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n // redraw when deps change\n useEffect(() => {\n requestOverlayRedraw();\n }, [preparedRegions, hoveredRegionId, activeRegionId, resolvedStrokeStyle, resolvedLabelStyle, regionLabelAutoLiftOffsetPx, requestOverlayRedraw]);\n\n // --- pointer event handling for hover / click ---\n\n const pointerHitRef = useRef({\n preparedRegionHits,\n labelAnchor,\n resolvedLabelStyle,\n labelStyleResolver,\n regionLabelAutoLiftOffsetPx,\n clampLabelToViewport,\n onHover,\n onClick,\n commitActive,\n });\n pointerHitRef.current = {\n preparedRegionHits,\n labelAnchor,\n resolvedLabelStyle,\n labelStyleResolver,\n regionLabelAutoLiftOffsetPx,\n clampLabelToViewport,\n onHover,\n onClick,\n commitActive,\n };\n\n useEffect(() => {\n if (!interactive) return;\n const container = containerRef.current;\n if (!container) return;\n\n const handlePointerMove = (e: PointerEvent) => {\n if (isInteractionLocked()) return;\n const renderer = rendererRef.current;\n if (!renderer) return;\n\n const { preparedRegionHits: hits, labelAnchor: currentLabelAnchor, resolvedLabelStyle: labelS, labelStyleResolver: resolver,\n regionLabelAutoLiftOffsetPx: autoLiftPx, clampLabelToViewport: clampVp, onHover: hoverCb } = pointerHitRef.current;\n\n const worldCoord = screenToWorld(e.clientX, e.clientY);\n if (!worldCoord) return;\n\n let nextId: string | number | null = null;\n let hitResult: { region: WsiRegion; regionIndex: number; regionId: string | number } | null = null;\n\n if (hits.length > 0) {\n const screenCoord = worldToScreen(worldCoord[0], worldCoord[1]);\n if (screenCoord) {\n const rect = canvasRef.current?.getBoundingClientRect();\n hitResult = pickPreparedRegionAt(\n worldCoord, screenCoord, hits, renderer, currentLabelAnchor, labelS, resolver,\n typeof autoLiftPx === \"number\" ? autoLiftPx : 0,\n rect?.width ?? 0, rect?.height ?? 0, clampVp,\n );\n nextId = hitResult?.regionId ?? null;\n }\n }\n\n const prevId = hoveredRegionIdRef.current;\n if (String(prevId) === String(nextId)) return;\n\n hoveredRegionIdRef.current = nextId;\n if (!isHoverControlled) setUncontrolledHoveredRegionId(nextId);\n hoverCb?.({\n region: hitResult?.region ?? null,\n regionId: nextId,\n regionIndex: hitResult?.regionIndex ?? -1,\n coordinate: worldCoord,\n });\n requestOverlayRedraw();\n };\n\n const handleClick = (e: MouseEvent) => {\n if (isInteractionLocked()) return;\n const renderer = rendererRef.current;\n if (!renderer) return;\n\n const { preparedRegionHits: hits, labelAnchor: currentLabelAnchor, resolvedLabelStyle: labelS, labelStyleResolver: resolver,\n regionLabelAutoLiftOffsetPx: autoLiftPx, clampLabelToViewport: clampVp,\n onClick: clickCb, commitActive: commit } = pointerHitRef.current;\n\n if (hits.length === 0) return;\n\n const worldCoord = screenToWorld(e.clientX, e.clientY);\n if (!worldCoord) return;\n\n const screenCoord = worldToScreen(worldCoord[0], worldCoord[1]);\n if (!screenCoord) return;\n\n const rect = canvasRef.current?.getBoundingClientRect();\n const hitResult = pickPreparedRegionAt(\n worldCoord, screenCoord, hits, renderer, currentLabelAnchor, labelS, resolver,\n typeof autoLiftPx === \"number\" ? autoLiftPx : 0,\n rect?.width ?? 0, rect?.height ?? 0, clampVp,\n );\n\n const nextId = hitResult?.regionId ?? null;\n commit(nextId);\n\n if (hitResult && clickCb) {\n clickCb({\n region: hitResult.region,\n regionId: hitResult.regionId,\n regionIndex: hitResult.regionIndex,\n coordinate: worldCoord,\n });\n }\n };\n\n const handlePointerLeave = () => {\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n if (!isHoverControlled) setUncontrolledHoveredRegionId(null);\n pointerHitRef.current.onHover?.({ region: null, regionId: null, regionIndex: -1, coordinate: null });\n requestOverlayRedraw();\n };\n\n container.addEventListener(\"pointermove\", handlePointerMove);\n container.addEventListener(\"click\", handleClick);\n container.addEventListener(\"pointerleave\", handlePointerLeave);\n return () => {\n container.removeEventListener(\"pointermove\", handlePointerMove);\n container.removeEventListener(\"click\", handleClick);\n container.removeEventListener(\"pointerleave\", handlePointerLeave);\n };\n }, [containerRef, rendererRef, canvasRef, interactive, isHoverControlled, screenToWorld, worldToScreen, isInteractionLocked, requestOverlayRedraw]);\n\n return null;\n}\n","import { type CSSProperties, useEffect, useMemo, useRef } from \"react\";\nimport { M1TileRenderer } from \"../core/m1-tile-renderer\";\nimport type { ViewState } from \"../core/ortho-camera\";\nimport type { TileDefinition } from \"../core/types\";\n\nexport interface TileViewerCanvasProps {\n\timageWidth: number;\n\timageHeight: number;\n\ttiles: TileDefinition[];\n\tviewState?: Partial<ViewState>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nexport function TileViewerCanvas({\n\timageWidth,\n\timageHeight,\n\ttiles,\n\tviewState,\n\tclassName,\n\tstyle,\n}: TileViewerCanvasProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst rendererRef = useRef<M1TileRenderer | null>(null);\n\tconst mergedStyle = useMemo(\n\t\t() => ({ width: \"100%\", height: \"100%\", display: \"block\", ...style }),\n\t\t[style],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst renderer = new M1TileRenderer({\n\t\t\tcanvas,\n\t\t\timageWidth,\n\t\t\timageHeight,\n\t\t\tinitialViewState: viewState,\n\t\t});\n\n\t\trendererRef.current = renderer;\n\t\tvoid renderer.setTiles(tiles);\n\n\t\treturn () => {\n\t\t\trenderer.destroy();\n\t\t\trendererRef.current = null;\n\t\t};\n\t}, [imageWidth, imageHeight]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid renderer.setTiles(tiles);\n\t}, [tiles]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !viewState) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderer.setViewState(viewState);\n\t}, [viewState]);\n\n\treturn <canvas ref={canvasRef} className={className} style={mergedStyle} />;\n}\n","import { nowMs } from \"./utils\";\n\nexport type TileBounds = [number, number, number, number];\n\nexport interface ScheduledTile {\n\tkey: string;\n\ttier: number;\n\tx: number;\n\ty: number;\n\tbounds: TileBounds;\n\tdistance2: number;\n\turl: string;\n}\n\nexport interface TileSchedulerSnapshot {\n\tinflight: number;\n\tqueued: number;\n\taborted: number;\n\tretries: number;\n\tfailed: number;\n}\n\nexport interface TileSchedulerOptions {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n\tauthToken?: string;\n\tonTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tonTileError?: (\n\t\ttile: ScheduledTile,\n\t\terror: unknown,\n\t\tattemptCount: number,\n\t) => void;\n\tonStateChange?: (snapshot: TileSchedulerSnapshot) => void;\n}\n\ninterface QueueItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\treadyAt: number;\n}\n\ninterface InflightItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\tcontroller: AbortController;\n}\n\nfunction shouldAttachAuthHeader(url: string, authToken: string): boolean {\n\tif (!authToken) return false;\n\ttry {\n\t\tconst parsed = new URL(url, typeof window !== \"undefined\" ? window.location.href : undefined);\n\t\tconst host = parsed.hostname.toLowerCase();\n\t\tconst isAwsS3 =\n\t\t\thost.includes(\"amazonaws.com\") || host.startsWith(\"s3.\") || host.includes(\".s3.\");\n\t\tif (isAwsS3) return false;\n\t} catch {\n\t\t// Fallback to attaching auth if URL parsing fails.\n\t}\n\treturn true;\n}\n\nexport class TileScheduler {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly maxRetries: number;\n\tprivate readonly retryBaseDelayMs: number;\n\tprivate readonly retryMaxDelayMs: number;\n\tprivate readonly onTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tprivate readonly onTileError?:\n\t\t| ((tile: ScheduledTile, error: unknown, attemptCount: number) => void)\n\t\t| undefined;\n\tprivate readonly onStateChange?:\n\t\t| ((snapshot: TileSchedulerSnapshot) => void)\n\t\t| undefined;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate queue: QueueItem[] = [];\n\tprivate queuedByKey = new Map<string, QueueItem>();\n\tprivate inflight = new Map<string, InflightItem>();\n\tprivate visibleKeys = new Set<string>();\n\tprivate timerId: number | null = null;\n\tprivate abortedCount = 0;\n\tprivate retryCount = 0;\n\tprivate failedCount = 0;\n\n\tconstructor(options: TileSchedulerOptions) {\n\t\tthis.maxConcurrency = Math.max(1, Math.floor(options.maxConcurrency ?? 12));\n\t\tthis.maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 2));\n\t\tthis.retryBaseDelayMs = Math.max(\n\t\t\t10,\n\t\t\tMath.floor(options.retryBaseDelayMs ?? 120),\n\t\t);\n\t\tthis.retryMaxDelayMs = Math.max(\n\t\t\tthis.retryBaseDelayMs,\n\t\t\tMath.floor(options.retryMaxDelayMs ?? 1200),\n\t\t);\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.onTileLoad = options.onTileLoad;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onStateChange = options.onStateChange;\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t}\n\n\tschedule(tiles: readonly ScheduledTile[]): void {\n\t\tif (this.destroyed) return;\n\n\t\tconst nextVisibleKeys = new Set<string>();\n\t\tfor (const tile of tiles) {\n\t\t\tnextVisibleKeys.add(tile.key);\n\t\t}\n\t\tthis.visibleKeys = nextVisibleKeys;\n\n\t\tthis.dropInvisibleQueued(nextVisibleKeys);\n\t\tthis.abortInvisibleInflight(nextVisibleKeys);\n\n\t\tfor (const tile of tiles) {\n\t\t\tif (this.inflight.has(tile.key)) {\n\t\t\t\tconst inflight = this.inflight.get(tile.key);\n\t\t\t\tif (inflight) inflight.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst queued = this.queuedByKey.get(tile.key);\n\t\t\tif (queued) {\n\t\t\t\tqueued.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst item: QueueItem = {\n\t\t\t\ttile,\n\t\t\t\tattempt: 0,\n\t\t\t\treadyAt: nowMs(),\n\t\t\t};\n\t\t\tthis.queue.push(item);\n\t\t\tthis.queuedByKey.set(tile.key, item);\n\t\t}\n\n\t\tthis.sortQueue();\n\t\tthis.pump();\n\t\tthis.emitStateChange();\n\t}\n\n\tclear(): void {\n\t\tthis.clearPumpTimer();\n\t\tthis.visibleKeys.clear();\n\t\tthis.queue = [];\n\t\tthis.queuedByKey.clear();\n\n\t\tfor (const [, item] of this.inflight) {\n\t\t\titem.controller.abort();\n\t\t}\n\t\tthis.inflight.clear();\n\t\tthis.emitStateChange();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.clear();\n\t}\n\n\tgetInflightCount(): number {\n\t\treturn this.inflight.size;\n\t}\n\n\tgetSnapshot(): TileSchedulerSnapshot {\n\t\treturn {\n\t\t\tinflight: this.inflight.size,\n\t\t\tqueued: this.queue.length,\n\t\t\taborted: this.abortedCount,\n\t\t\tretries: this.retryCount,\n\t\t\tfailed: this.failedCount,\n\t\t};\n\t}\n\n\tprivate dropInvisibleQueued(visibleKeys: Set<string>): void {\n\t\tif (this.queue.length === 0) return;\n\t\tconst nextQueue: QueueItem[] = [];\n\t\tfor (const item of this.queue) {\n\t\t\tif (!visibleKeys.has(item.tile.key)) {\n\t\t\t\tthis.queuedByKey.delete(item.tile.key);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnextQueue.push(item);\n\t\t}\n\t\tthis.queue = nextQueue;\n\t}\n\n\tprivate abortInvisibleInflight(visibleKeys: Set<string>): void {\n\t\tfor (const [key, item] of this.inflight) {\n\t\t\tif (visibleKeys.has(key)) continue;\n\t\t\tthis.inflight.delete(key);\n\t\t\tthis.abortedCount += 1;\n\t\t\titem.controller.abort();\n\t\t}\n\t}\n\n\tprivate sortQueue(): void {\n\t\tthis.queue.sort((a, b) => {\n\t\t\tif (a.readyAt !== b.readyAt) return a.readyAt - b.readyAt;\n\t\t\tif (a.tile.distance2 !== b.tile.distance2) {\n\t\t\t\treturn a.tile.distance2 - b.tile.distance2;\n\t\t\t}\n\t\t\tif (a.tile.tier !== b.tile.tier) return b.tile.tier - a.tile.tier;\n\t\t\treturn a.tile.key.localeCompare(b.tile.key);\n\t\t});\n\t}\n\n\tprivate pump(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.clearPumpTimer();\n\n\t\twhile (this.inflight.size < this.maxConcurrency) {\n\t\t\tconst next = this.takeNextReadyQueueItem();\n\t\t\tif (!next) break;\n\t\t\tthis.startFetch(next);\n\t\t}\n\n\t\tif (this.inflight.size >= this.maxConcurrency) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.queue.length === 0) return;\n\n\t\tconst earliestReadyAt = this.queue[0]?.readyAt;\n\t\tif (typeof earliestReadyAt !== \"number\") return;\n\t\tconst delay = Math.max(0, earliestReadyAt - nowMs());\n\t\tthis.timerId = globalThis.setTimeout(() => {\n\t\t\tthis.timerId = null;\n\t\t\tthis.pump();\n\t\t}, delay);\n\t}\n\n\tprivate takeNextReadyQueueItem(): QueueItem | null {\n\t\tif (this.queue.length === 0) return null;\n\t\tconst now = nowMs();\n\t\tconst first = this.queue[0];\n\t\tif (!first || first.readyAt > now) return null;\n\n\t\tthis.queue.shift();\n\t\tthis.queuedByKey.delete(first.tile.key);\n\t\treturn first;\n\t}\n\n\tprivate startFetch(item: QueueItem): void {\n\t\tconst controller = new AbortController();\n\t\tconst inflightEntry: InflightItem = {\n\t\t\ttile: item.tile,\n\t\t\tattempt: item.attempt,\n\t\t\tcontroller,\n\t\t};\n\t\tthis.inflight.set(item.tile.key, inflightEntry);\n\t\tthis.emitStateChange();\n\n\t\tconst useAuthHeader = shouldAttachAuthHeader(item.tile.url, this.authToken);\n\t\tfetch(item.tile.url, {\n\t\t\tsignal: controller.signal,\n\t\t\theaders: useAuthHeader ? { Authorization: this.authToken } : undefined,\n\t\t})\n\t\t\t.then((response) => {\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\treturn response.blob();\n\t\t\t})\n\t\t\t.then((blob) => createImageBitmap(blob))\n\t\t\t.then((bitmap) => {\n\t\t\t\tif (this.destroyed || controller.signal.aborted) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!this.visibleKeys.has(item.tile.key)) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.onTileLoad(item.tile, bitmap);\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (controller.signal.aborted || this.destroyed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst shouldRetry =\n\t\t\t\t\titem.attempt < this.maxRetries && this.visibleKeys.has(item.tile.key);\n\t\t\t\tif (shouldRetry) {\n\t\t\t\t\tthis.retryCount += 1;\n\t\t\t\t\tconst nextAttempt = item.attempt + 1;\n\t\t\t\t\tconst retryDelay = this.getRetryDelay(nextAttempt);\n\t\t\t\t\tconst queued: QueueItem = {\n\t\t\t\t\t\ttile: item.tile,\n\t\t\t\t\t\tattempt: nextAttempt,\n\t\t\t\t\t\treadyAt: nowMs() + retryDelay,\n\t\t\t\t\t};\n\t\t\t\t\tconst existing = this.queuedByKey.get(item.tile.key);\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.tile = queued.tile;\n\t\t\t\t\t\texisting.readyAt = Math.min(existing.readyAt, queued.readyAt);\n\t\t\t\t\t\texisting.attempt = Math.max(existing.attempt, queued.attempt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.queue.push(queued);\n\t\t\t\t\t\tthis.queuedByKey.set(queued.tile.key, queued);\n\t\t\t\t\t}\n\t\t\t\t\tthis.sortQueue();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.failedCount += 1;\n\t\t\t\tthis.onTileError?.(item.tile, error, item.attempt + 1);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tthis.inflight.delete(item.tile.key);\n\t\t\t\tthis.pump();\n\t\t\t\tthis.emitStateChange();\n\t\t\t});\n\t}\n\n\tprivate getRetryDelay(attempt: number): number {\n\t\tconst exp = Math.max(0, attempt - 1);\n\t\tconst delay = Math.min(\n\t\t\tthis.retryMaxDelayMs,\n\t\t\tthis.retryBaseDelayMs * 2 ** exp,\n\t\t);\n\t\tconst jitter = 0.85 + Math.random() * 0.3;\n\t\treturn Math.round(delay * jitter);\n\t}\n\n\tprivate clearPumpTimer(): void {\n\t\tif (this.timerId === null) return;\n\t\tglobalThis.clearTimeout(this.timerId);\n\t\tthis.timerId = null;\n\t}\n\n\tprivate emitStateChange(): void {\n\t\tthis.onStateChange?.(this.getSnapshot());\n\t}\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\n\nexport interface RendererCanvasHandlers {\n pointerDown: (event: PointerEvent) => void;\n pointerMove: (event: PointerEvent) => void;\n pointerUp: (event: PointerEvent) => void;\n wheel: (event: WheelEvent) => void;\n doubleClick: (event: MouseEvent) => void;\n contextMenu: (event: MouseEvent) => void;\n contextLost: (event: Event) => void;\n contextRestored: (event: Event) => void;\n}\n\nexport function addRendererCanvasEventListeners(canvas: HTMLCanvasElement, handlers: RendererCanvasHandlers): void {\n canvas.addEventListener(\"pointerdown\", handlers.pointerDown);\n canvas.addEventListener(\"pointermove\", handlers.pointerMove);\n canvas.addEventListener(\"pointerup\", handlers.pointerUp);\n canvas.addEventListener(\"pointercancel\", handlers.pointerUp);\n canvas.addEventListener(\"wheel\", handlers.wheel, { passive: false });\n canvas.addEventListener(\"dblclick\", handlers.doubleClick);\n canvas.addEventListener(\"contextmenu\", handlers.contextMenu);\n canvas.addEventListener(\"webglcontextlost\", handlers.contextLost);\n canvas.addEventListener(\"webglcontextrestored\", handlers.contextRestored);\n}\n\nexport function removeRendererCanvasEventListeners(canvas: HTMLCanvasElement, handlers: RendererCanvasHandlers): void {\n canvas.removeEventListener(\"pointerdown\", handlers.pointerDown);\n canvas.removeEventListener(\"pointermove\", handlers.pointerMove);\n canvas.removeEventListener(\"pointerup\", handlers.pointerUp);\n canvas.removeEventListener(\"pointercancel\", handlers.pointerUp);\n canvas.removeEventListener(\"wheel\", handlers.wheel);\n canvas.removeEventListener(\"dblclick\", handlers.doubleClick);\n canvas.removeEventListener(\"contextmenu\", handlers.contextMenu);\n canvas.removeEventListener(\"webglcontextlost\", handlers.contextLost);\n canvas.removeEventListener(\"webglcontextrestored\", handlers.contextRestored);\n}\n\nexport function resizeCanvasViewport(canvas: HTMLCanvasElement, gl: WebGL2RenderingContext, camera: OrthoCamera): void {\n const rect = canvas.getBoundingClientRect();\n const cssW = Math.max(1, rect.width || canvas.clientWidth || 1);\n const cssH = Math.max(1, rect.height || canvas.clientHeight || 1);\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const pixelW = Math.max(1, Math.round(cssW * dpr));\n const pixelH = Math.max(1, Math.round(cssH * dpr));\n\n if (canvas.width !== pixelW || canvas.height !== pixelH) {\n canvas.width = pixelW;\n canvas.height = pixelH;\n }\n\n camera.setViewport(cssW, cssH);\n gl.viewport(0, 0, pixelW, pixelH);\n}\n","import type { WsiImageColorSettings } from \"./types\";\nimport { clamp, parseHexColorToRgba } from \"./utils\";\nimport type {\n NormalizedImageColorSettings,\n PointSizeByMagnification,\n PointSizeByZoom,\n PointSizeMagnificationStop,\n PointSizeStop,\n PointWeightByMagnification,\n PointWeightMagnificationStop,\n} from \"./wsi-renderer-types\";\n\nexport const DEFAULT_ROTATION_DRAG_SENSITIVITY = 0.35;\nexport const MIN_POINT_SIZE_PX = 0.5;\nexport const MAX_POINT_SIZE_PX = 256;\n\nexport const DEFAULT_POINT_SIZE_STOPS: readonly PointSizeStop[] = [\n { zoom: 1, size: 2.8 },\n { zoom: 2, size: 3.4 },\n { zoom: 3, size: 4.2 },\n { zoom: 4, size: 5.3 },\n { zoom: 5, size: 6.8 },\n { zoom: 6, size: 8.4 },\n { zoom: 7, size: 9.8 },\n { zoom: 8, size: 11.2 },\n { zoom: 9, size: 14.0 },\n { zoom: 10, size: 17.5 },\n { zoom: 11, size: 22.0 },\n { zoom: 12, size: 28.0 },\n];\n\nconst MIN_STROKE_SCALE = 0.1;\nconst MAX_STROKE_SCALE = 5.0;\nconst MIN_POINT_OPACITY = 0;\nconst MAX_POINT_OPACITY = 1;\nconst MIN_POINT_INNER_FILL_OPACITY = 0;\nconst MAX_POINT_INNER_FILL_OPACITY = 1;\nconst MIN_IMAGE_COLOR_INPUT = -100;\nconst MAX_IMAGE_COLOR_INPUT = 100;\nconst MAX_VIEW_TRANSITION_DURATION_MS = 2000;\nexport const DEFAULT_POINT_INNER_FILL_COLOR: readonly [number, number, number] = [255, 255, 255];\n\nexport function toRadians(deg: number): number {\n return (deg * Math.PI) / 180;\n}\n\nexport function isSameArrayView(a: ArrayBufferView | null | undefined, b: ArrayBufferView | null | undefined): boolean {\n if (!a || !b) return a === b;\n return a.buffer === b.buffer && a.byteOffset === b.byteOffset && a.byteLength === b.byteLength;\n}\n\nexport function clonePointSizeStops(stops: readonly PointSizeStop[]): PointSizeStop[] {\n return stops.map(stop => ({ zoom: stop.zoom, size: stop.size }));\n}\n\nexport function clonePointSizeMagnificationStops(stops: readonly PointSizeMagnificationStop[] | null | undefined): PointSizeMagnificationStop[] | null {\n if (!stops || stops.length === 0) return null;\n return stops.map(stop => ({ magnification: stop.magnification, size: stop.size }));\n}\n\nexport function clonePointWeightMagnificationStops(\n stops: readonly PointWeightMagnificationStop[] | null | undefined\n): PointWeightMagnificationStop[] | null {\n if (!stops || stops.length === 0) return null;\n return stops.map(stop => ({ magnification: stop.magnification, weight: stop.weight }));\n}\n\nexport function normalizePointSizeStops(pointSizeByZoom: PointSizeByZoom | null | undefined): PointSizeStop[] {\n if (!pointSizeByZoom) return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\n const parsed = new Map<number, number>();\n for (const [zoomKey, rawSize] of Object.entries(pointSizeByZoom)) {\n const zoom = Number(zoomKey);\n const size = Number(rawSize);\n if (!Number.isFinite(zoom) || !Number.isFinite(size) || size <= 0) continue;\n parsed.set(zoom, size);\n }\n\n if (parsed.size === 0) {\n return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n }\n\n return Array.from(parsed.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([zoom, size]) => ({ zoom, size }));\n}\n\nexport function normalizePointSizeMagnificationStops(pointSizeByMagnification: PointSizeByMagnification | null | undefined): PointSizeMagnificationStop[] | null {\n if (!pointSizeByMagnification) return null;\n\n const parsed = new Map<number, number>();\n for (const [magnificationKey, rawSize] of Object.entries(pointSizeByMagnification)) {\n const magnification = Number(magnificationKey);\n const size = Number(rawSize);\n if (!Number.isFinite(magnification) || magnification <= 0 || !Number.isFinite(size) || size <= 0) continue;\n parsed.set(magnification, size);\n }\n\n if (parsed.size === 0) {\n return null;\n }\n\n return Array.from(parsed.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([magnification, size]) => ({ magnification, size }));\n}\n\nexport function normalizePointWeightMagnificationStops(\n pointWeightByMagnification: PointWeightByMagnification | null | undefined\n): PointWeightMagnificationStop[] | null {\n if (!pointWeightByMagnification) return null;\n\n const parsed = new Map<number, number>();\n for (const [magnificationKey, rawWeight] of Object.entries(pointWeightByMagnification)) {\n const magnification = Number(magnificationKey);\n const weight = normalizeStrokeScale(rawWeight);\n if (!Number.isFinite(magnification) || magnification <= 0) continue;\n parsed.set(magnification, weight);\n }\n\n if (parsed.size === 0) {\n return null;\n }\n\n return Array.from(parsed.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([magnification, weight]) => ({ magnification, weight }));\n}\n\nexport function arePointSizeStopsEqual(a: readonly PointSizeStop[], b: readonly PointSizeStop[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i].zoom !== b[i].zoom || a[i].size !== b[i].size) {\n return false;\n }\n }\n return true;\n}\n\nexport function arePointSizeMagnificationStopsEqual(\n a: readonly PointSizeMagnificationStop[] | null | undefined,\n b: readonly PointSizeMagnificationStop[] | null | undefined\n): boolean {\n if (a === b) return true;\n if (!a || !b) return a === b;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i].magnification !== b[i].magnification || a[i].size !== b[i].size) {\n return false;\n }\n }\n return true;\n}\n\nexport function arePointWeightMagnificationStopsEqual(\n a: readonly PointWeightMagnificationStop[] | null | undefined,\n b: readonly PointWeightMagnificationStop[] | null | undefined\n): boolean {\n if (a === b) return true;\n if (!a || !b) return a === b;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i].magnification !== b[i].magnification || a[i].weight !== b[i].weight) {\n return false;\n }\n }\n return true;\n}\n\nexport function resolvePointSizeByZoomStops(continuousZoom: number, stops: readonly PointSizeStop[]): number {\n if (!Number.isFinite(continuousZoom)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n if (stops.length === 0) return MIN_POINT_SIZE_PX;\n if (stops.length === 1) return stops[0].size;\n if (continuousZoom <= stops[0].zoom) return stops[0].size;\n\n for (let i = 1; i < stops.length; i += 1) {\n const prev = stops[i - 1];\n const next = stops[i];\n if (continuousZoom > next.zoom) continue;\n const span = Math.max(1e-6, next.zoom - prev.zoom);\n const t = clamp((continuousZoom - prev.zoom) / span, 0, 1);\n return prev.size + (next.size - prev.size) * t;\n }\n\n const last = stops[stops.length - 1];\n const prev = stops[stops.length - 2];\n const span = Math.max(1e-6, last.zoom - prev.zoom);\n const slope = (last.size - prev.size) / span;\n return last.size + (continuousZoom - last.zoom) * slope;\n}\n\nexport function resolvePointSizeByMagnificationStops(magnification: number, stops: readonly PointSizeMagnificationStop[]): number {\n if (!Number.isFinite(magnification)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n if (stops.length === 0) return MIN_POINT_SIZE_PX;\n if (stops.length === 1) return stops[0].size;\n if (magnification <= stops[0].magnification) return stops[0].size;\n\n for (let i = 1; i < stops.length; i += 1) {\n const prev = stops[i - 1];\n const next = stops[i];\n if (magnification > next.magnification) continue;\n const span = Math.max(1e-6, next.magnification - prev.magnification);\n const t = clamp((magnification - prev.magnification) / span, 0, 1);\n return prev.size + (next.size - prev.size) * t;\n }\n\n const last = stops[stops.length - 1];\n const prev = stops[stops.length - 2];\n const span = Math.max(1e-6, last.magnification - prev.magnification);\n const slope = (last.size - prev.size) / span;\n return last.size + (magnification - last.magnification) * slope;\n}\n\nexport function resolvePointWeightByMagnificationStops(magnification: number, stops: readonly PointWeightMagnificationStop[]): number {\n if (!Number.isFinite(magnification)) return stops[0]?.weight ?? 1.0;\n if (stops.length === 0) return 1.0;\n if (stops.length === 1) return stops[0].weight;\n if (magnification <= stops[0].magnification) return stops[0].weight;\n\n for (let i = 1; i < stops.length; i += 1) {\n const prev = stops[i - 1];\n const next = stops[i];\n if (magnification > next.magnification) continue;\n const span = Math.max(1e-6, next.magnification - prev.magnification);\n const t = clamp((magnification - prev.magnification) / span, 0, 1);\n return prev.weight + (next.weight - prev.weight) * t;\n }\n\n const last = stops[stops.length - 1];\n const prev = stops[stops.length - 2];\n const span = Math.max(1e-6, last.magnification - prev.magnification);\n const slope = (last.weight - prev.weight) / span;\n return last.weight + (magnification - last.magnification) * slope;\n}\n\nexport function normalizeStrokeScale(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 1.0;\n return clamp(value, MIN_STROKE_SCALE, MAX_STROKE_SCALE);\n}\n\nexport function normalizePointOpacity(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 1;\n return clamp(value, MIN_POINT_OPACITY, MAX_POINT_OPACITY);\n}\n\nexport function normalizePointLineDash(dashed: [number, number] | null | undefined): [number, number] {\n if (!dashed) return [1, 0];\n return [clamp(dashed[0], 0, 100), clamp(dashed[1], 0, 100)];\n}\n\nexport function normalizePointInnerFillOpacity(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n return clamp(value, MIN_POINT_INNER_FILL_OPACITY, MAX_POINT_INNER_FILL_OPACITY);\n}\n\nexport function normalizePointInnerFillColor(value: string | null | undefined): [number, number, number] {\n const rgba = parseHexColorToRgba(value, [...DEFAULT_POINT_INNER_FILL_COLOR, 255]);\n return [rgba[0], rgba[1], rgba[2]];\n}\n\nfunction normalizeImageColorInput(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n return clamp(value, MIN_IMAGE_COLOR_INPUT, MAX_IMAGE_COLOR_INPUT);\n}\n\nexport function toNormalizedImageColorSettings(settings: WsiImageColorSettings | null | undefined): NormalizedImageColorSettings {\n const brightnessInput = normalizeImageColorInput(settings?.brightness);\n const contrastInput = normalizeImageColorInput(settings?.contrast);\n const saturationInput = normalizeImageColorInput(settings?.saturation);\n return {\n brightness: brightnessInput / 200,\n contrast: contrastInput / 100,\n saturation: saturationInput / 100,\n };\n}\n\nexport function linearEasing(t: number): number {\n return t;\n}\n\nexport function normalizeViewTransitionDuration(duration: number | null | undefined): number {\n if (typeof duration !== \"number\" || !Number.isFinite(duration)) return 0;\n return clamp(duration, 0, MAX_VIEW_TRANSITION_DURATION_MS);\n}\n\nexport function normalizeZoomOverride(value: number | null | undefined): number | null {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) return null;\n return Math.max(1e-6, value);\n}\n\nexport function normalizeTransitionEasing(easing: ((t: number) => number) | null | undefined): (t: number) => number {\n return typeof easing === \"function\" ? easing : linearEasing;\n}\n","import { DEFAULT_ROTATION_DRAG_SENSITIVITY, toRadians } from \"./wsi-normalize\";\nimport type { InteractionConfig, InteractionState, ZoomSnapState } from \"./wsi-renderer-types\";\n\ninterface PointerMoveOptions {\n event: PointerEvent;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n config: InteractionConfig;\n camera: {\n getViewState: () => {\n zoom: number;\n offsetX: number;\n offsetY: number;\n rotationDeg: number;\n };\n setViewState: (next: Partial<{ zoom: number; offsetX: number; offsetY: number; rotationDeg: number }>) => void;\n };\n clampViewState: () => void;\n emitViewState: () => void;\n requestRender: () => void;\n}\n\ninterface PointerDownOptions {\n event: PointerEvent;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n config: InteractionConfig;\n cancelViewAnimation: () => void;\n}\n\ninterface WheelOptions {\n event: WheelEvent;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\ninterface DoubleClickOptions {\n event: MouseEvent;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\nfunction getPointerAngleRad(canvas: HTMLCanvasElement, clientX: number, clientY: number): number {\n const rect = canvas.getBoundingClientRect();\n const x = clientX - rect.left - rect.width * 0.5;\n const y = clientY - rect.top - rect.height * 0.5;\n return Math.atan2(y, x);\n}\n\nexport function cancelDrag(canvas: HTMLCanvasElement, state: InteractionState): void {\n if (state.pointerId !== null && canvas.hasPointerCapture(state.pointerId)) {\n try {\n canvas.releasePointerCapture(state.pointerId);\n } catch {\n // noop\n }\n }\n state.dragging = false;\n state.mode = \"none\";\n state.rotateLastAngleRad = null;\n state.pointerId = null;\n canvas.classList.remove(\"dragging\");\n}\n\nexport function handlePointerDown(options: PointerDownOptions): void {\n const { event, canvas, state, config, cancelViewAnimation } = options;\n const wantsRotate = config.ctrlDragRotate && (event.ctrlKey || event.metaKey);\n const allowButton = event.button === 0 || (wantsRotate && event.button === 2);\n if (!allowButton) return;\n\n cancelViewAnimation();\n if (wantsRotate) {\n event.preventDefault();\n }\n\n state.dragging = true;\n state.mode = wantsRotate ? \"rotate\" : \"pan\";\n state.pointerId = event.pointerId;\n state.lastPointerX = event.clientX;\n state.lastPointerY = event.clientY;\n state.rotateLastAngleRad = state.mode === \"rotate\" ? getPointerAngleRad(canvas, event.clientX, event.clientY) : null;\n\n canvas.classList.add(\"dragging\");\n canvas.setPointerCapture(event.pointerId);\n}\n\nexport function handlePointerMove(options: PointerMoveOptions): void {\n const { event, canvas, state, config, camera, clampViewState, emitViewState, requestRender } = options;\n if (!state.dragging || event.pointerId !== state.pointerId) return;\n\n const dx = event.clientX - state.lastPointerX;\n const dy = event.clientY - state.lastPointerY;\n state.lastPointerX = event.clientX;\n state.lastPointerY = event.clientY;\n\n if (state.mode === \"rotate\") {\n const nextAngle = getPointerAngleRad(canvas, event.clientX, event.clientY);\n const prevAngle = state.rotateLastAngleRad;\n state.rotateLastAngleRad = nextAngle;\n if (prevAngle !== null) {\n const rawDelta = nextAngle - prevAngle;\n const delta = Math.atan2(Math.sin(rawDelta), Math.cos(rawDelta));\n const sensitivityScale = DEFAULT_ROTATION_DRAG_SENSITIVITY > 0 ? config.rotationDragSensitivityDegPerPixel / DEFAULT_ROTATION_DRAG_SENSITIVITY : 1;\n const viewState = camera.getViewState();\n camera.setViewState({\n rotationDeg: viewState.rotationDeg - ((delta * 180) / Math.PI) * sensitivityScale,\n });\n }\n } else {\n const viewState = camera.getViewState();\n const zoom = Math.max(1e-6, viewState.zoom);\n const rad = toRadians(viewState.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const worldDx = (dx * cos - dy * sin) / zoom;\n const worldDy = (dx * sin + dy * cos) / zoom;\n camera.setViewState({\n offsetX: viewState.offsetX - worldDx,\n offsetY: viewState.offsetY - worldDy,\n });\n }\n\n clampViewState();\n emitViewState();\n requestRender();\n}\n\nexport function handlePointerUp(event: PointerEvent, canvas: HTMLCanvasElement, state: InteractionState): void {\n if (event.pointerId !== state.pointerId) return;\n cancelDrag(canvas, state);\n}\n\nexport function handleWheel(options: WheelOptions): void {\n const { event, canvas, onZoomBy } = options;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n applyWheelZoomDelta(event.deltaY, x, y, onZoomBy);\n}\n\ninterface WheelSnapOptions {\n event: WheelEvent;\n canvas: HTMLCanvasElement;\n snapState: ZoomSnapState;\n onSnapZoom: (direction: \"in\" | \"out\", x: number, y: number) => boolean;\n}\n\nconst SNAP_DELTA_THRESHOLD = 4;\n\nexport function applyWheelZoomDelta(deltaY: number, x: number, y: number, onZoomBy: (factor: number, x: number, y: number) => void): void {\n const factor = deltaY < 0 ? 1.12 : 0.89;\n onZoomBy(factor, x, y);\n}\n\nexport function applyWheelSnapDelta(\n deltaY: number,\n x: number,\n y: number,\n snapState: ZoomSnapState,\n onSnapZoom: (direction: \"in\" | \"out\", x: number, y: number) => boolean\n): void {\n const inputDirection: \"in\" | \"out\" | null = deltaY < 0 ? \"in\" : deltaY > 0 ? \"out\" : null;\n if (inputDirection && snapState.blockedDirection) {\n if (inputDirection !== snapState.blockedDirection) {\n snapState.blockedDirection = null;\n snapState.accumulatedDelta = 0;\n } else {\n return;\n }\n }\n\n if (snapState.accumulatedDelta !== 0 && deltaY !== 0 && Math.sign(snapState.accumulatedDelta) !== Math.sign(deltaY)) {\n snapState.accumulatedDelta = 0;\n }\n snapState.accumulatedDelta += deltaY;\n\n if (Math.abs(snapState.accumulatedDelta) < SNAP_DELTA_THRESHOLD) return;\n\n const direction: \"in\" | \"out\" = snapState.accumulatedDelta > 0 ? \"out\" : \"in\";\n\n snapState.accumulatedDelta = 0;\n if (!onSnapZoom(direction, x, y)) {\n snapState.blockedDirection = direction;\n return;\n }\n\n snapState.blockedDirection = null;\n}\n\nexport function handleWheelSnap(options: WheelSnapOptions): void {\n const { event, canvas, snapState, onSnapZoom } = options;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n applyWheelSnapDelta(event.deltaY, x, y, snapState, onSnapZoom);\n}\n\nexport function handleDoubleClick(options: DoubleClickOptions): void {\n const { event, canvas, onZoomBy } = options;\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n onZoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n}\n\nexport function handleContextMenu(event: MouseEvent, dragging: boolean): void {\n if (dragging || event.ctrlKey || event.metaKey) {\n event.preventDefault();\n }\n}\n","import { toTileUrl } from \"./image-info\";\nimport type { ScheduledTile } from \"./tile-scheduler\";\nimport type { WsiImageSource } from \"./types\";\nimport { clamp } from \"./utils\";\nimport type { Bounds } from \"./wsi-renderer-types\";\n\ninterface CameraViewLike {\n getViewCorners: () => [readonly [number, number], readonly [number, number], readonly [number, number], readonly [number, number]];\n getViewState: () => { zoom: number };\n getCenter: () => [number, number];\n setCenter: (x: number, y: number) => void;\n}\n\nexport function getViewBounds(camera: CameraViewLike): Bounds {\n const corners = camera.getViewCorners();\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of corners) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n return [minX, minY, maxX, maxY];\n}\n\nexport function clampViewState(camera: CameraViewLike, source: WsiImageSource, extentX = 0.2, extentY = 0.2): void {\n const bounds = getViewBounds(camera);\n const visibleW = Math.max(1e-6, bounds[2] - bounds[0]);\n const visibleH = Math.max(1e-6, bounds[3] - bounds[1]);\n const marginX = visibleW * extentX;\n const marginY = visibleH * extentY;\n\n const [centerX, centerY] = camera.getCenter();\n const halfW = visibleW * 0.5;\n const halfH = visibleH * 0.5;\n\n const minCenterX = halfW - marginX;\n const maxCenterX = source.width - halfW + marginX;\n const minCenterY = halfH - marginY;\n const maxCenterY = source.height - halfH + marginY;\n\n const nextCenterX = minCenterX <= maxCenterX ? clamp(centerX, minCenterX, maxCenterX) : source.width * 0.5;\n const nextCenterY = minCenterY <= maxCenterY ? clamp(centerY, minCenterY, maxCenterY) : source.height * 0.5;\n\n camera.setCenter(nextCenterX, nextCenterY);\n}\n\nexport function selectTier(camera: CameraViewLike, source: WsiImageSource): number {\n const zoom = Math.max(1e-6, camera.getViewState().zoom);\n const rawTier = source.maxTierZoom + Math.log2(zoom);\n return clamp(Math.floor(rawTier), 0, source.maxTierZoom);\n}\n\nexport function intersectsBounds(a: Bounds, b: Bounds): boolean {\n return !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n}\n\nexport function getVisibleTilesForTier(camera: CameraViewLike, source: WsiImageSource, tier: number): ScheduledTile[] {\n const viewBounds = getViewBounds(camera);\n\n const levelScale = Math.pow(2, source.maxTierZoom - tier);\n const levelWidth = Math.ceil(source.width / levelScale);\n const levelHeight = Math.ceil(source.height / levelScale);\n\n const tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n const tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\n const viewMinX = viewBounds[0];\n const viewMinY = viewBounds[1];\n const viewMaxX = viewBounds[2];\n const viewMaxY = viewBounds[3];\n\n const minTileX = clamp(Math.floor(viewMinX / levelScale / source.tileSize), 0, tilesX - 1);\n const maxTileX = clamp(Math.floor((viewMaxX - 1) / levelScale / source.tileSize), 0, tilesX - 1);\n const minTileY = clamp(Math.floor(viewMinY / levelScale / source.tileSize), 0, tilesY - 1);\n const maxTileY = clamp(Math.floor((viewMaxY - 1) / levelScale / source.tileSize), 0, tilesY - 1);\n\n if (minTileX > maxTileX || minTileY > maxTileY) {\n return [];\n }\n\n const centerTileX = ((viewMinX + viewMaxX) * 0.5) / levelScale / source.tileSize;\n const centerTileY = ((viewMinY + viewMaxY) * 0.5) / levelScale / source.tileSize;\n\n const visible: ScheduledTile[] = [];\n for (let y = minTileY; y <= maxTileY; y += 1) {\n for (let x = minTileX; x <= maxTileX; x += 1) {\n const left = x * source.tileSize * levelScale;\n const top = y * source.tileSize * levelScale;\n const right = Math.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n const bottom = Math.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\n const dx = x - centerTileX;\n const dy = y - centerTileY;\n visible.push({\n key: `${tier}/${x}/${y}`,\n tier,\n x,\n y,\n bounds: [left, top, right, bottom],\n distance2: dx * dx + dy * dy,\n url: toTileUrl(source, tier, x, y),\n });\n }\n }\n\n visible.sort((a, b) => a.distance2 - b.distance2);\n return visible;\n}\n\nexport function getVisibleTiles(camera: CameraViewLike, source: WsiImageSource): { tier: number; visible: ScheduledTile[] } {\n const tier = selectTier(camera, source);\n return {\n tier,\n visible: getVisibleTilesForTier(camera, source, tier),\n };\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { WsiImageSource } from \"./types\";\nimport type { RendererCanvasHandlers } from \"./wsi-canvas-lifecycle\";\nimport { cancelDrag as cancelInteractionDrag, handleContextMenu, handleDoubleClick, handlePointerDown, handlePointerMove, handlePointerUp, handleWheel, handleWheelSnap } from \"./wsi-interaction\";\nimport type { InteractionState, ZoomSnapState } from \"./wsi-renderer-types\";\nimport { clampViewState } from \"./wsi-tile-visibility\";\n\ninterface BaseInteractionOptions {\n interactionLocked: boolean;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n}\n\ninterface PointerDownWithLockOptions extends BaseInteractionOptions {\n event: PointerEvent;\n ctrlDragRotate: boolean;\n rotationDragSensitivityDegPerPixel: number;\n cancelViewAnimation: () => void;\n}\n\ninterface PointerMoveWithLockOptions extends BaseInteractionOptions {\n event: PointerEvent;\n ctrlDragRotate: boolean;\n rotationDragSensitivityDegPerPixel: number;\n camera: OrthoCamera;\n source: WsiImageSource;\n panExtentX: number;\n panExtentY: number;\n emitViewState: () => void;\n requestRender: () => void;\n}\n\ninterface PointerUpWithLockOptions extends BaseInteractionOptions {\n event: PointerEvent;\n}\n\ninterface WheelWithLockOptions {\n event: WheelEvent;\n interactionLocked: boolean;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\ninterface DoubleClickWithLockOptions {\n event: MouseEvent;\n interactionLocked: boolean;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\ninterface ContextMenuWithLockOptions {\n event: MouseEvent;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n}\n\nexport function onPointerDownWithLock(options: PointerDownWithLockOptions): void {\n if (options.interactionLocked) return;\n handlePointerDown({\n event: options.event,\n canvas: options.canvas,\n state: options.state,\n config: {\n ctrlDragRotate: options.ctrlDragRotate,\n rotationDragSensitivityDegPerPixel: options.rotationDragSensitivityDegPerPixel,\n },\n cancelViewAnimation: options.cancelViewAnimation,\n });\n}\n\nexport function onPointerMoveWithLock(options: PointerMoveWithLockOptions): void {\n if (options.interactionLocked) return;\n handlePointerMove({\n event: options.event,\n canvas: options.canvas,\n state: options.state,\n config: {\n ctrlDragRotate: options.ctrlDragRotate,\n rotationDragSensitivityDegPerPixel: options.rotationDragSensitivityDegPerPixel,\n },\n camera: options.camera,\n clampViewState: () => clampViewState(options.camera, options.source, options.panExtentX, options.panExtentY),\n emitViewState: options.emitViewState,\n requestRender: options.requestRender,\n });\n}\n\nexport function onPointerUpWithLock(options: PointerUpWithLockOptions): void {\n if (options.interactionLocked) return;\n handlePointerUp(options.event, options.canvas, options.state);\n}\n\nexport function onWheelWithLock(options: WheelWithLockOptions): void {\n if (options.interactionLocked) {\n options.event.preventDefault();\n return;\n }\n handleWheel({\n event: options.event,\n canvas: options.canvas,\n onZoomBy: options.onZoomBy,\n });\n}\n\nexport function onDoubleClickWithLock(options: DoubleClickWithLockOptions): void {\n if (options.interactionLocked) return;\n handleDoubleClick({\n event: options.event,\n canvas: options.canvas,\n onZoomBy: options.onZoomBy,\n });\n}\n\nexport function onContextMenuWithLock(options: ContextMenuWithLockOptions): void {\n handleContextMenu(options.event, options.state.dragging);\n}\n\nexport function cancelDrag(canvas: HTMLCanvasElement, state: InteractionState): void {\n cancelInteractionDrag(canvas, state);\n}\n\nexport interface CreateRendererInputHandlersOptions {\n canvas: HTMLCanvasElement;\n state: InteractionState;\n getInteractionLocked: () => boolean;\n getCtrlDragRotate: () => boolean;\n getRotationDragSensitivityDegPerPixel: () => number;\n cancelViewAnimation: () => void;\n camera: OrthoCamera;\n source: WsiImageSource;\n emitViewState: () => void;\n requestRender: () => void;\n getPanExtentX: () => number;\n getPanExtentY: () => number;\n zoomBy: (factor: number, x: number, y: number) => void;\n getUseZoomSnaps?: () => boolean;\n onSnapZoom?: (direction: \"in\" | \"out\", x: number, y: number) => boolean;\n zoomSnapState?: ZoomSnapState;\n}\n\nexport function createRendererInputHandlers(\n options: CreateRendererInputHandlersOptions\n): Pick<RendererCanvasHandlers, \"pointerDown\" | \"pointerMove\" | \"pointerUp\" | \"wheel\" | \"doubleClick\" | \"contextMenu\"> {\n return {\n pointerDown: (event: PointerEvent) =>\n onPointerDownWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n state: options.state,\n ctrlDragRotate: options.getCtrlDragRotate(),\n rotationDragSensitivityDegPerPixel: options.getRotationDragSensitivityDegPerPixel(),\n cancelViewAnimation: options.cancelViewAnimation,\n }),\n pointerMove: (event: PointerEvent) =>\n onPointerMoveWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n state: options.state,\n ctrlDragRotate: options.getCtrlDragRotate(),\n rotationDragSensitivityDegPerPixel: options.getRotationDragSensitivityDegPerPixel(),\n camera: options.camera,\n source: options.source,\n panExtentX: options.getPanExtentX(),\n panExtentY: options.getPanExtentY(),\n emitViewState: options.emitViewState,\n requestRender: options.requestRender,\n }),\n pointerUp: (event: PointerEvent) =>\n onPointerUpWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n state: options.state,\n }),\n wheel: (event: WheelEvent) => {\n if (options.getInteractionLocked()) {\n event.preventDefault();\n return;\n }\n if (options.getUseZoomSnaps?.() && options.onSnapZoom && options.zoomSnapState) {\n handleWheelSnap({\n event,\n canvas: options.canvas,\n snapState: options.zoomSnapState,\n onSnapZoom: options.onSnapZoom,\n });\n return;\n }\n handleWheel({\n event,\n canvas: options.canvas,\n onZoomBy: options.zoomBy,\n });\n },\n doubleClick: (event: MouseEvent) =>\n onDoubleClickWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n onZoomBy: options.zoomBy,\n }),\n contextMenu: (event: MouseEvent) =>\n onContextMenuWithLock({\n event,\n canvas: options.canvas,\n state: options.state,\n }),\n };\n}\n","import type {\n HandleTileLoadedOptions,\n TileCacheTrimOptions,\n} from \"./wsi-renderer-types\";\n\nexport function trimTileCache(options: TileCacheTrimOptions): void {\n const { gl, cache, maxCacheTiles } = options;\n if (cache.size <= maxCacheTiles) return;\n const targetSize = Math.max(0, Math.floor(maxCacheTiles));\n while (cache.size > targetSize) {\n let oldestKey: string | null = null;\n let oldestValue: { texture: WebGLTexture; lastUsed: number } | null = null;\n for (const [key, value] of cache) {\n if (!oldestValue || value.lastUsed < oldestValue.lastUsed) {\n oldestKey = key;\n oldestValue = value;\n }\n }\n if (!oldestKey || !oldestValue) break;\n gl.deleteTexture(oldestValue.texture);\n cache.delete(oldestKey);\n }\n}\n\nexport function createTextureFromBitmap(gl: WebGL2RenderingContext, bitmap: ImageBitmap): WebGLTexture | null {\n if (gl.isContextLost()) return null;\n\n const texture = gl.createTexture();\n if (!texture) return null;\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return texture;\n}\n\nexport function handleTileLoaded(options: HandleTileLoadedOptions): void {\n const { gl, cache, tile, bitmap, frameSerial, maxCacheTiles, destroyed, contextLost, requestRender } = options;\n\n if (destroyed || contextLost || gl.isContextLost()) {\n bitmap.close();\n return;\n }\n if (cache.has(tile.key)) {\n bitmap.close();\n return;\n }\n\n const texture = createTextureFromBitmap(gl, bitmap);\n bitmap.close();\n if (!texture) return;\n\n cache.set(tile.key, {\n key: tile.key,\n texture,\n bounds: tile.bounds,\n tier: tile.tier,\n lastUsed: frameSerial,\n });\n trimTileCache({ gl, cache, maxCacheTiles });\n requestRender();\n}\n\nexport function deleteCachedTextures(gl: WebGL2RenderingContext, cache: Map<string, { texture: WebGLTexture }>): void {\n for (const [, value] of cache) {\n gl.deleteTexture(value.texture);\n }\n}\n","import type { TileScheduler } from \"./tile-scheduler\";\nimport type { CachedTile, PointProgram, TileVertexProgram } from \"./wsi-renderer-types\";\nimport { deleteCachedTextures } from \"./wsi-tile-cache\";\n\nexport interface ContextLostOptions {\n event: Event;\n destroyed: boolean;\n contextLost: boolean;\n frame: number | null;\n cancelViewAnimation: () => void;\n cancelDrag: () => void;\n tileScheduler: TileScheduler;\n cache: Map<string, CachedTile>;\n onContextLost?: () => void;\n}\n\nexport interface ContextLostResult {\n handled: boolean;\n frame: number | null;\n}\n\nexport function handleContextLost(options: ContextLostOptions): ContextLostResult {\n const { event, destroyed, contextLost, cancelViewAnimation, cancelDrag, tileScheduler, cache, onContextLost } = options;\n event.preventDefault();\n if (destroyed || contextLost) {\n return {\n handled: false,\n frame: options.frame,\n };\n }\n\n let frame = options.frame;\n if (frame !== null) {\n cancelAnimationFrame(frame);\n frame = null;\n }\n cancelViewAnimation();\n\n cancelDrag();\n tileScheduler.clear();\n cache.clear();\n onContextLost?.();\n\n return {\n handled: true,\n frame,\n };\n}\n\nexport interface DestroyRendererOptions {\n destroyed: boolean;\n frame: number | null;\n cancelViewAnimation: () => void;\n resizeObserver: ResizeObserver;\n removeDprListener: () => void;\n removeCanvasEventListeners: () => void;\n cancelDrag: () => void;\n tileScheduler: TileScheduler;\n contextLost: boolean;\n gl: WebGL2RenderingContext;\n cache: Map<string, CachedTile>;\n tileProgram: TileVertexProgram;\n pointPrograms: PointProgram[];\n}\n\nexport interface DestroyRendererResult {\n didDestroy: boolean;\n frame: number | null;\n}\n\nexport function destroyRenderer(options: DestroyRendererOptions): DestroyRendererResult {\n if (options.destroyed) {\n return {\n didDestroy: false,\n frame: options.frame,\n };\n }\n\n let frame = options.frame;\n if (frame !== null) {\n cancelAnimationFrame(frame);\n frame = null;\n }\n options.cancelViewAnimation();\n\n options.resizeObserver.disconnect();\n options.removeDprListener();\n options.removeCanvasEventListeners();\n options.cancelDrag();\n options.tileScheduler.destroy();\n\n if (!options.contextLost && !options.gl.isContextLost()) {\n deleteCachedTextures(options.gl, options.cache);\n options.gl.deleteBuffer(options.tileProgram.vbo);\n options.gl.deleteVertexArray(options.tileProgram.vao);\n options.gl.deleteProgram(options.tileProgram.program);\n\n for (let i = 0; i < options.pointPrograms.length; i += 1) {\n const pointProgram = options.pointPrograms[i];\n options.gl.deleteBuffer(pointProgram.posBuffer);\n options.gl.deleteBuffer(pointProgram.classBuffer);\n options.gl.deleteBuffer(pointProgram.fillModeBuffer);\n options.gl.deleteBuffer(pointProgram.indexBuffer);\n options.gl.deleteTexture(pointProgram.paletteTexture);\n options.gl.deleteVertexArray(pointProgram.vao);\n options.gl.deleteProgram(pointProgram.program);\n }\n }\n options.cache.clear();\n\n return {\n didDestroy: true,\n frame,\n };\n}\n","import type { WsiPointData } from \"./types\";\nimport { isSameArrayView } from \"./wsi-normalize\";\nimport type { PointProgram } from \"./wsi-renderer-types\";\n\nexport interface PointBufferRuntime {\n pointCount: number;\n usePointIndices: boolean;\n pointBuffersDirty: boolean;\n lastPointData: WsiPointData | null;\n zeroFillModes: Uint8Array<ArrayBufferLike>;\n lastPointPalette: Uint8Array<ArrayBufferLike> | null;\n pointPaletteSize: number;\n}\n\nfunction sanitizeDrawIndices(drawIndices: Uint32Array, maxExclusive: number): Uint32Array {\n if (maxExclusive <= 0 || drawIndices.length === 0) {\n return new Uint32Array(0);\n }\n\n let validCount = drawIndices.length;\n for (let i = 0; i < drawIndices.length; i += 1) {\n if (drawIndices[i] < maxExclusive) continue;\n validCount -= 1;\n }\n if (validCount === drawIndices.length) {\n return drawIndices;\n }\n if (validCount <= 0) {\n return new Uint32Array(0);\n }\n\n const filtered = new Uint32Array(validCount);\n let cursor = 0;\n for (let i = 0; i < drawIndices.length; i += 1) {\n const idx = drawIndices[i];\n if (idx >= maxExclusive) continue;\n filtered[cursor] = idx;\n cursor += 1;\n }\n return filtered;\n}\n\nfunction getZeroFillModes(zeroFillModes: Uint8Array<ArrayBufferLike>, count: number): Uint8Array<ArrayBufferLike> {\n if (count <= 0) return new Uint8Array(0);\n if (zeroFillModes.length < count) {\n return new Uint8Array(count);\n }\n return zeroFillModes.subarray(0, count);\n}\n\nexport function setPointPalette(runtime: PointBufferRuntime, gl: WebGL2RenderingContext, pointProgram: PointProgram, contextLost: boolean, colors: Uint8Array | null | undefined): PointBufferRuntime {\n if (!colors || colors.length === 0) {\n return {\n ...runtime,\n lastPointPalette: null,\n };\n }\n\n const nextPalette = new Uint8Array(colors);\n if (contextLost || gl.isContextLost()) {\n return {\n ...runtime,\n lastPointPalette: nextPalette,\n };\n }\n\n const paletteSize = Math.max(1, Math.floor(nextPalette.length / 4));\n gl.bindTexture(gl.TEXTURE_2D, pointProgram.paletteTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, paletteSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, nextPalette);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n ...runtime,\n lastPointPalette: nextPalette,\n pointPaletteSize: paletteSize,\n };\n}\n\nexport function setPointData(runtime: PointBufferRuntime, gl: WebGL2RenderingContext, pointProgram: PointProgram, contextLost: boolean, points: WsiPointData | null | undefined): PointBufferRuntime {\n if (!points || !points.count || !points.positions || !points.paletteIndices) {\n return {\n ...runtime,\n lastPointData: null,\n pointCount: 0,\n usePointIndices: false,\n };\n }\n\n const pointFillModes = points.fillModes instanceof Uint8Array ? points.fillModes : null;\n const hasFillModes = pointFillModes !== null;\n const safeCount = Math.max(0, Math.min(points.count, Math.floor(points.positions.length / 2), points.paletteIndices.length, hasFillModes ? pointFillModes.length : Number.MAX_SAFE_INTEGER));\n const nextPositions = points.positions.subarray(0, safeCount * 2);\n const nextPaletteIndices = points.paletteIndices.subarray(0, safeCount);\n const nextFillModes = hasFillModes ? pointFillModes.subarray(0, safeCount) : undefined;\n const hasDrawIndices = points.drawIndices instanceof Uint32Array;\n const nextDrawIndices = hasDrawIndices ? sanitizeDrawIndices(points.drawIndices as Uint32Array, safeCount) : null;\n\n const prev = runtime.lastPointData;\n const prevHasFillModes = prev?.fillModes instanceof Uint8Array;\n const geometryChanged =\n runtime.pointBuffersDirty ||\n !prev ||\n prev.count !== safeCount ||\n !isSameArrayView(prev.positions, nextPositions) ||\n !isSameArrayView(prev.paletteIndices, nextPaletteIndices) ||\n prevHasFillModes !== hasFillModes ||\n (hasFillModes && (!prev?.fillModes || !isSameArrayView(prev.fillModes, nextFillModes)));\n const drawIndicesChanged = runtime.pointBuffersDirty || (hasDrawIndices && (!prev?.drawIndices || !isSameArrayView(prev.drawIndices, nextDrawIndices))) || (!hasDrawIndices && !!prev?.drawIndices);\n\n const nextRuntime: PointBufferRuntime = {\n ...runtime,\n lastPointData: {\n count: safeCount,\n positions: nextPositions,\n paletteIndices: nextPaletteIndices,\n fillModes: nextFillModes,\n drawIndices: hasDrawIndices ? (nextDrawIndices ?? undefined) : undefined,\n },\n };\n\n if (contextLost || gl.isContextLost()) {\n return nextRuntime;\n }\n\n const currentPointData = nextRuntime.lastPointData;\n if (!currentPointData) {\n return nextRuntime;\n }\n\n if (geometryChanged) {\n gl.bindBuffer(gl.ARRAY_BUFFER, pointProgram.posBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, currentPointData.positions, gl.STATIC_DRAW);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, pointProgram.classBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, currentPointData.paletteIndices, gl.STATIC_DRAW);\n\n const zeroFillModes = getZeroFillModes(nextRuntime.zeroFillModes, safeCount);\n gl.bindBuffer(gl.ARRAY_BUFFER, pointProgram.fillModeBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, currentPointData.fillModes ?? zeroFillModes, gl.STATIC_DRAW);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n nextRuntime.zeroFillModes = zeroFillModes;\n }\n\n if (hasDrawIndices && drawIndicesChanged) {\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pointProgram.indexBuffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, nextDrawIndices ?? new Uint32Array(0), gl.DYNAMIC_DRAW);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n }\n\n nextRuntime.usePointIndices = hasDrawIndices;\n nextRuntime.pointCount = hasDrawIndices ? (nextDrawIndices?.length ?? 0) : currentPointData.count;\n if (geometryChanged || drawIndicesChanged) {\n nextRuntime.pointBuffersDirty = false;\n }\n\n return nextRuntime;\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { ScheduledTile, TileScheduler } from \"./tile-scheduler\";\nimport type { WsiImageSource } from \"./types\";\nimport type { Bounds, CachedTile, NormalizedImageColorSettings, PointProgram, TileVertexProgram } from \"./wsi-renderer-types\";\n\nexport interface RenderPointLayer {\n pointProgram: PointProgram;\n pointCount: number;\n usePointIndices: boolean;\n pointPaletteSize: number;\n pointLineDash: [number, number];\n pointOpacity: number;\n pointStrokeScale: number;\n pointInnerFillOpacity: number;\n pointInnerFillColor: [number, number, number];\n pointCssSizePx: number;\n pointSizePx: number;\n}\n\nexport interface RenderFrameOptions {\n gl: WebGL2RenderingContext;\n camera: OrthoCamera;\n source: WsiImageSource;\n cache: Map<string, CachedTile>;\n frameSerial: number;\n tileProgram: TileVertexProgram;\n imageColorSettings: NormalizedImageColorSettings;\n pointLayers: readonly RenderPointLayer[];\n tileScheduler: TileScheduler;\n getVisibleTiles: () => { tier: number; visible: ScheduledTile[] };\n getVisibleTilesForTier: (tier: number) => ScheduledTile[];\n getViewBounds: () => Bounds;\n intersectsBounds: (a: Bounds, b: Bounds) => boolean;\n}\n\nexport interface RenderFrameResult {\n tier: number;\n visible: number;\n rendered: number;\n points: number;\n fallback: number;\n cacheHits: number;\n cacheMisses: number;\n drawCalls: number;\n}\n\nexport function renderFrame(options: RenderFrameOptions): RenderFrameResult {\n const {\n gl,\n camera,\n source,\n cache,\n frameSerial,\n tileProgram,\n imageColorSettings,\n pointLayers,\n tileScheduler,\n getVisibleTiles,\n getVisibleTilesForTier,\n getViewBounds,\n intersectsBounds,\n } = options;\n\n gl.clearColor(0.03, 0.06, 0.1, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n const { tier, visible } = getVisibleTiles();\n const viewBounds = getViewBounds();\n const visibleKeys = new Set(visible.map(tile => tile.key));\n\n gl.useProgram(tileProgram.program);\n gl.bindVertexArray(tileProgram.vao);\n gl.uniformMatrix3fv(tileProgram.uCamera, false, camera.getMatrix());\n gl.uniform1i(tileProgram.uTexture, 0);\n gl.uniform1f(tileProgram.uBrightness, imageColorSettings.brightness);\n gl.uniform1f(tileProgram.uContrast, imageColorSettings.contrast);\n gl.uniform1f(tileProgram.uSaturation, imageColorSettings.saturation);\n\n const fallbackTiles: CachedTile[] = [];\n for (const [, cached] of cache) {\n if (visibleKeys.has(cached.key)) continue;\n if (!intersectsBounds(cached.bounds, viewBounds)) continue;\n fallbackTiles.push(cached);\n }\n fallbackTiles.sort((a, b) => a.tier - b.tier);\n\n for (const cached of fallbackTiles) {\n cached.lastUsed = frameSerial;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, cached.texture);\n gl.uniform4f(tileProgram.uBounds, cached.bounds[0], cached.bounds[1], cached.bounds[2], cached.bounds[3]);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n let renderedTiles = 0;\n const missingTiles: ScheduledTile[] = [];\n for (const tile of visible) {\n const cached = cache.get(tile.key);\n if (!cached) {\n missingTiles.push(tile);\n continue;\n }\n cached.lastUsed = frameSerial;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, cached.texture);\n gl.uniform4f(tileProgram.uBounds, cached.bounds[0], cached.bounds[1], cached.bounds[2], cached.bounds[3]);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n renderedTiles += 1;\n }\n\n const tilesToSchedule: ScheduledTile[] = missingTiles.slice();\n const PREFETCH_DISTANCE_PENALTY = 1e6;\n const prefetchTiers: number[] = [];\n if (tier > 0) prefetchTiers.push(tier - 1);\n if (tier < source.maxTierZoom) prefetchTiers.push(tier + 1);\n for (const prefetchTier of prefetchTiers) {\n const prefetchCandidates = getVisibleTilesForTier(prefetchTier);\n for (const tile of prefetchCandidates) {\n if (cache.has(tile.key)) continue;\n tile.distance2 += PREFETCH_DISTANCE_PENALTY;\n tilesToSchedule.push(tile);\n }\n }\n tileScheduler.schedule(tilesToSchedule);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindVertexArray(null);\n\n let renderedPoints = 0;\n let pointDrawCalls = 0;\n if (pointLayers.length > 0) {\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n for (let i = 0; i < pointLayers.length; i += 1) {\n const layer = pointLayers[i];\n if (layer.pointCount <= 0) continue;\n\n gl.useProgram(layer.pointProgram.program);\n gl.bindVertexArray(layer.pointProgram.vao);\n gl.uniformMatrix3fv(layer.pointProgram.uCamera, false, camera.getMatrix());\n gl.uniform1f(layer.pointProgram.uPointSize, layer.pointSizePx);\n gl.uniform1f(layer.pointProgram.uPointCssSize, layer.pointCssSizePx);\n gl.uniform2f(layer.pointProgram.uPointLineDash, layer.pointLineDash[0], layer.pointLineDash[1]);\n gl.uniform1f(layer.pointProgram.uPointOpacity, layer.pointOpacity);\n gl.uniform1f(layer.pointProgram.uPointStrokeScale, layer.pointStrokeScale);\n gl.uniform1f(layer.pointProgram.uPointInnerFillAlpha, layer.pointInnerFillOpacity);\n gl.uniform3f(layer.pointProgram.uPointInnerFillColor, layer.pointInnerFillColor[0], layer.pointInnerFillColor[1], layer.pointInnerFillColor[2]);\n gl.uniform1f(layer.pointProgram.uPaletteSize, layer.pointPaletteSize);\n gl.uniform1i(layer.pointProgram.uPalette, 1);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, layer.pointProgram.paletteTexture);\n if (layer.usePointIndices) {\n gl.drawElements(gl.POINTS, layer.pointCount, gl.UNSIGNED_INT, 0);\n } else {\n gl.drawArrays(gl.POINTS, 0, layer.pointCount);\n }\n renderedPoints += layer.pointCount;\n pointDrawCalls += 1;\n }\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindVertexArray(null);\n }\n\n return {\n tier,\n visible: visible.length,\n rendered: renderedTiles,\n points: renderedPoints,\n fallback: fallbackTiles.length,\n cacheHits: renderedTiles,\n cacheMisses: missingTiles.length,\n drawCalls: fallbackTiles.length + renderedTiles + pointDrawCalls,\n };\n}\n","import { createProgram, requireUniformLocation } from \"../core/gl-utils\";\nimport type { PointProgram, TileVertexProgram } from \"./wsi-renderer-types\";\n\nexport function initTileProgram(gl: WebGL2RenderingContext): TileVertexProgram {\n const vertex = `#version 300 es\n precision highp float;\n in vec2 aUnit;\n in vec2 aUv;\n uniform mat3 uCamera;\n uniform vec4 uBounds;\n out vec2 vUv;\n void main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n }`;\n\n const fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n uniform float uBrightness;\n uniform float uContrast;\n uniform float uSaturation;\n out vec4 outColor;\n void main() {\n vec4 color = texture(uTexture, vUv);\n\n color.rgb = clamp(\n (uContrast + 1.0) * color.rgb - (uContrast / 2.0),\n vec3(0.0),\n vec3(1.0)\n );\n\n float saturation = uSaturation + 1.0;\n float sr = (1.0 - saturation) * 0.2126;\n float sg = (1.0 - saturation) * 0.7152;\n float sb = (1.0 - saturation) * 0.0722;\n mat3 saturationMatrix = mat3(\n sr + saturation, sr, sr,\n sg, sg + saturation, sg,\n sb, sb, sb + saturation\n );\n color.rgb = clamp(saturationMatrix * color.rgb, vec3(0.0), vec3(1.0));\n\n color.rgb = clamp(color.rgb + uBrightness, vec3(0.0), vec3(1.0));\n outColor = color;\n }`;\n\n const program = createProgram(gl, vertex, fragment);\n const uCamera = requireUniformLocation(gl, program, \"uCamera\");\n const uBounds = requireUniformLocation(gl, program, \"uBounds\");\n const uTexture = requireUniformLocation(gl, program, \"uTexture\");\n const uBrightness = requireUniformLocation(gl, program, \"uBrightness\");\n const uContrast = requireUniformLocation(gl, program, \"uContrast\");\n const uSaturation = requireUniformLocation(gl, program, \"uSaturation\");\n\n const vao = gl.createVertexArray();\n const vbo = gl.createBuffer();\n if (!vao || !vbo) {\n throw new Error(\"buffer allocation failed\");\n }\n\n gl.bindVertexArray(vao);\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]), gl.STATIC_DRAW);\n\n const aUnit = gl.getAttribLocation(program, \"aUnit\");\n const aUv = gl.getAttribLocation(program, \"aUv\");\n if (aUnit < 0 || aUv < 0) {\n throw new Error(\"tile attribute lookup failed\");\n }\n gl.enableVertexAttribArray(aUnit);\n gl.enableVertexAttribArray(aUv);\n gl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n return {\n program,\n vao,\n vbo,\n uCamera,\n uBounds,\n uTexture,\n uBrightness,\n uContrast,\n uSaturation,\n };\n}\n\nexport function initPointProgram(gl: WebGL2RenderingContext): PointProgram {\n const pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aClass;\n in uint aFillMode;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vClass;\n flat out uint vFillMode;\n void main() {\n vec3 clip = uCamera * vec3(aPosition, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vClass = aClass;\n vFillMode = aFillMode;\n }`;\n\n const pointFragment = `#version 300 es\n precision highp float;\n const float PI = 3.14159265358979323846;\n flat in uint vClass;\n flat in uint vFillMode;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\n uniform float uPointCssSize;\n uniform float uPointOpacity;\n uniform float uPointStrokeScale;\n uniform float uPointInnerFillAlpha;\n uniform vec3 uPointInnerFillColor;\n uniform vec2 uPointLineDash;\n out vec4 outColor;\n void main() {\n vec2 pc = gl_PointCoord * 2.0 - 1.0;\n float r = length(pc);\n if (r > 1.0) discard;\n\n float idx = clamp(float(vClass), 0.0, max(0.0, uPaletteSize - 1.0));\n vec2 uv = vec2((idx + 0.5) / uPaletteSize, 0.5);\n vec4 color = texture(uPalette, uv);\n if (color.a <= 0.0) discard;\n\n float aa = 1.5 / max(1.0, uPointSize);\n float pointOpacity = clamp(uPointOpacity, 0.0, 1.0);\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n if (vFillMode != 0u) {\n float alpha = outerMask * color.a * pointOpacity;\n if (alpha <= 0.001) discard;\n outColor = vec4(color.rgb * alpha, alpha);\n } else {\n float s = uPointStrokeScale;\n float ringWidth = s * mix(0.18, 0.28, smoothstep(3.0, 12.0, uPointCssSize));\n float innerRadius = 1.0 - ringWidth;\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float dashMask = 1.0;\n if (uPointLineDash.x > 0.0 && uPointLineDash.y > 0.0) {\n float angle01 = (atan(pc.y, pc.x) + PI) / (2.0 * PI);\n float circumferencePx = max(1.0, 2.0 * PI * max(0.5, uPointCssSize * 0.5));\n float dashCycle = uPointLineDash.x + uPointLineDash.y;\n float dashOffset = mod(angle01 * circumferencePx, dashCycle);\n dashMask = dashOffset <= uPointLineDash.x ? 1.0 : 0.0;\n }\n float ringAlpha = outerMask * innerMask * dashMask * color.a;\n float fillAlpha = outerMask * (1.0 - innerMask) * clamp(uPointInnerFillAlpha, 0.0, 1.0);\n float alpha = (ringAlpha + fillAlpha) * pointOpacity;\n if (alpha <= 0.001) discard;\n vec3 fillRgb = (uPointInnerFillColor / 255.0) * fillAlpha * pointOpacity;\n outColor = vec4(color.rgb * ringAlpha * pointOpacity + fillRgb, alpha);\n }\n }`;\n\n const program = createProgram(gl, pointVertex, pointFragment);\n const uCamera = requireUniformLocation(gl, program, \"uCamera\");\n const uPointSize = requireUniformLocation(gl, program, \"uPointSize\");\n const uPointCssSize = requireUniformLocation(gl, program, \"uPointCssSize\");\n const uPointOpacity = requireUniformLocation(gl, program, \"uPointOpacity\");\n const uPointStrokeScale = requireUniformLocation(gl, program, \"uPointStrokeScale\");\n const uPointInnerFillAlpha = requireUniformLocation(gl, program, \"uPointInnerFillAlpha\");\n const uPointInnerFillColor = requireUniformLocation(gl, program, \"uPointInnerFillColor\");\n const uPalette = requireUniformLocation(gl, program, \"uPalette\");\n const uPaletteSize = requireUniformLocation(gl, program, \"uPaletteSize\");\n const uPointLineDash = requireUniformLocation(gl, program, \"uPointLineDash\");\n\n const vao = gl.createVertexArray();\n const posBuffer = gl.createBuffer();\n const classBuffer = gl.createBuffer();\n const fillModeBuffer = gl.createBuffer();\n const indexBuffer = gl.createBuffer();\n const paletteTexture = gl.createTexture();\n if (!vao || !posBuffer || !classBuffer || !fillModeBuffer || !indexBuffer || !paletteTexture) {\n throw new Error(\"point buffer allocation failed\");\n }\n\n gl.bindVertexArray(vao);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const posLoc = gl.getAttribLocation(program, \"aPosition\");\n if (posLoc < 0) {\n throw new Error(\"point position attribute not found\");\n }\n gl.enableVertexAttribArray(posLoc);\n gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, classBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const classLoc = gl.getAttribLocation(program, \"aClass\");\n if (classLoc < 0) {\n throw new Error(\"point class attribute not found\");\n }\n gl.enableVertexAttribArray(classLoc);\n gl.vertexAttribIPointer(classLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, fillModeBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const fillModeLoc = gl.getAttribLocation(program, \"aFillMode\");\n if (fillModeLoc < 0) {\n throw new Error(\"point fill mode attribute not found\");\n }\n gl.enableVertexAttribArray(fillModeLoc);\n gl.vertexAttribIPointer(fillModeLoc, 1, gl.UNSIGNED_BYTE, 0, 0);\n\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\n gl.bindTexture(gl.TEXTURE_2D, paletteTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([160, 160, 160, 255]));\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n program,\n vao,\n posBuffer,\n classBuffer,\n fillModeBuffer,\n indexBuffer,\n paletteTexture,\n uCamera,\n uPointSize,\n uPointCssSize,\n uPointOpacity,\n uPointLineDash,\n uPointStrokeScale,\n uPointInnerFillAlpha,\n uPointInnerFillColor,\n uPalette,\n uPaletteSize,\n };\n}\n","import { clamp, nowMs } from \"./utils\";\nimport type { ViewAnimationRuntimeState, ViewAnimationStartOptions } from \"./wsi-renderer-types\";\n\nexport function cancelViewAnimation(state: ViewAnimationRuntimeState): void {\n state.animation = null;\n if (state.frame !== null) {\n cancelAnimationFrame(state.frame);\n state.frame = null;\n }\n}\n\nexport function startViewAnimation(options: ViewAnimationStartOptions): void {\n const { state, camera, target, durationMs, easing, onUpdate } = options;\n const from = camera.getViewState();\n cancelViewAnimation(state);\n state.animation = {\n startMs: nowMs(),\n durationMs: Math.max(0, durationMs),\n from,\n to: target,\n easing,\n };\n\n const step = (): void => {\n const animation = state.animation;\n if (!animation) return;\n\n const elapsed = Math.max(0, nowMs() - animation.startMs);\n const rawT = animation.durationMs <= 0 ? 1 : clamp(elapsed / animation.durationMs, 0, 1);\n let eased = rawT;\n try {\n eased = animation.easing(rawT);\n } catch {\n eased = rawT;\n }\n if (!Number.isFinite(eased)) {\n eased = rawT;\n }\n eased = clamp(eased, 0, 1);\n\n camera.setViewState({\n zoom: animation.from.zoom + (animation.to.zoom - animation.from.zoom) * eased,\n offsetX: animation.from.offsetX + (animation.to.offsetX - animation.from.offsetX) * eased,\n offsetY: animation.from.offsetY + (animation.to.offsetY - animation.from.offsetY) * eased,\n rotationDeg: animation.from.rotationDeg + (animation.to.rotationDeg - animation.from.rotationDeg) * eased,\n });\n onUpdate();\n\n if (rawT >= 1) {\n state.animation = null;\n state.frame = null;\n return;\n }\n\n state.frame = requestAnimationFrame(step);\n };\n\n state.frame = requestAnimationFrame(step);\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { WsiImageSource, WsiViewState } from \"./types\";\nimport { clamp } from \"./utils\";\nimport { toRadians } from \"./wsi-normalize\";\n\nexport function resolveDefaultZoomBounds(fitZoom: number): { minZoom: number; maxZoom: number } {\n const minZoom = Math.max(fitZoom * 0.5, 1e-6);\n const maxZoom = Math.max(1, fitZoom * 8);\n return {\n minZoom,\n maxZoom: Math.max(minZoom, maxZoom),\n };\n}\n\nexport function resolveZoomBounds(fitZoom: number, minZoomOverride: number | null, maxZoomOverride: number | null): { minZoom: number; maxZoom: number } {\n const defaults = resolveDefaultZoomBounds(fitZoom);\n let minZoom = minZoomOverride ?? defaults.minZoom;\n let maxZoom = maxZoomOverride ?? defaults.maxZoom;\n minZoom = Math.max(1e-6, minZoom);\n maxZoom = Math.max(1e-6, maxZoom);\n if (minZoom > maxZoom) {\n minZoom = maxZoom;\n }\n return { minZoom, maxZoom };\n}\n\nexport function resolveTargetViewState(\n camera: OrthoCamera,\n minZoom: number,\n maxZoom: number,\n next: Partial<WsiViewState>,\n clampViewState: () => void,\n): WsiViewState {\n const current = camera.getViewState();\n const candidate: WsiViewState = {\n zoom: typeof next.zoom === \"number\" && Number.isFinite(next.zoom) ? clamp(next.zoom, minZoom, maxZoom) : current.zoom,\n offsetX: typeof next.offsetX === \"number\" && Number.isFinite(next.offsetX) ? next.offsetX : current.offsetX,\n offsetY: typeof next.offsetY === \"number\" && Number.isFinite(next.offsetY) ? next.offsetY : current.offsetY,\n rotationDeg: typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg) ? next.rotationDeg : current.rotationDeg,\n };\n\n camera.setViewState(candidate);\n clampViewState();\n const target = camera.getViewState();\n camera.setViewState(current);\n return target;\n}\n\nexport function computeFitToImageTarget(\n source: WsiImageSource,\n viewportWidth: number,\n viewportHeight: number,\n minZoom: number,\n maxZoom: number,\n rotationDeg = 0,\n): { fitZoom: number; target: WsiViewState } {\n const zoom = Math.min(viewportWidth / source.width, viewportHeight / source.height);\n const safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n const clampedZoom = clamp(safeZoom, minZoom, maxZoom);\n const visibleWorldW = viewportWidth / clampedZoom;\n const visibleWorldH = viewportHeight / clampedZoom;\n\n return {\n fitZoom: safeZoom,\n target: {\n zoom: clampedZoom,\n offsetX: (source.width - visibleWorldW) * 0.5,\n offsetY: (source.height - visibleWorldH) * 0.5,\n rotationDeg,\n },\n };\n}\n\nexport function computeZoomByTarget(\n camera: OrthoCamera,\n minZoom: number,\n maxZoom: number,\n factor: number,\n screenX: number,\n screenY: number,\n): Partial<WsiViewState> | null {\n const state = camera.getViewState();\n const nextZoom = clamp(state.zoom * factor, minZoom, maxZoom);\n if (nextZoom === state.zoom) return null;\n\n const [worldX, worldY] = camera.screenToWorld(screenX, screenY);\n const vp = camera.getViewportSize();\n const dx = screenX - vp.width * 0.5;\n const dy = screenY - vp.height * 0.5;\n const rad = toRadians(state.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n const worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n const nextCenterX = worldX - worldDx;\n const nextCenterY = worldY - worldDy;\n\n return {\n zoom: nextZoom,\n offsetX: nextCenterX - vp.width / (2 * nextZoom),\n offsetY: nextCenterY - vp.height / (2 * nextZoom),\n };\n}\n\nexport function computeZoomToTarget(\n camera: OrthoCamera,\n minZoom: number,\n maxZoom: number,\n targetZoom: number,\n screenX: number,\n screenY: number,\n): Partial<WsiViewState> | null {\n const state = camera.getViewState();\n const nextZoom = clamp(targetZoom, minZoom, maxZoom);\n if (nextZoom === state.zoom) return null;\n\n const [worldX, worldY] = camera.screenToWorld(screenX, screenY);\n const vp = camera.getViewportSize();\n const dx = screenX - vp.width * 0.5;\n const dy = screenY - vp.height * 0.5;\n const rad = toRadians(state.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n const worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n const nextCenterX = worldX - worldDx;\n const nextCenterY = worldY - worldDy;\n\n return {\n zoom: nextZoom,\n offsetX: nextCenterX - vp.width / (2 * nextZoom),\n offsetY: nextCenterY - vp.height / (2 * nextZoom),\n };\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { WsiViewState } from \"./types\";\nimport { clamp, nowMs } from \"./utils\";\nimport { linearEasing, toRadians } from \"./wsi-normalize\";\nimport type { ViewAnimationRuntimeState } from \"./wsi-renderer-types\";\n\nexport const SNAP_ZOOM_DURATION_MS = 250;\n\nexport function normalizeZoomSnaps(magnifications: number[] | null | undefined, mpp: number | undefined): number[] {\n if (!magnifications || magnifications.length === 0) return [];\n if (!mpp || mpp <= 0) return [];\n const maxMag = 10 / mpp;\n return magnifications\n .map(mag => mag / maxMag)\n .filter(z => Number.isFinite(z) && z > 0)\n .sort((a, b) => a - b);\n}\n\nexport type SnapZoomResult = { type: \"snap\"; zoom: number } | { type: \"fit\" } | null;\n\nexport function resolveSnapTarget(validSnaps: number[], currentZoom: number, direction: \"in\" | \"out\", fitAsMin: boolean): SnapZoomResult {\n if (validSnaps.length === 0) return null;\n\n const epsilon = Math.max(currentZoom * 0.005, 1e-8);\n\n if (direction === \"in\") {\n for (const snap of validSnaps) {\n if (snap > currentZoom + epsilon) {\n return { type: \"snap\", zoom: snap };\n }\n }\n return null;\n }\n\n for (let i = validSnaps.length - 1; i >= 0; i--) {\n if (validSnaps[i] < currentZoom - epsilon) {\n return { type: \"snap\", zoom: validSnaps[i] };\n }\n }\n\n if (fitAsMin && currentZoom <= validSnaps[0] + epsilon) {\n return { type: \"fit\" };\n }\n\n return null;\n}\n\nexport interface ZoomPivotAnimationContext {\n camera: OrthoCamera;\n viewAnimationState: ViewAnimationRuntimeState;\n minZoom: number;\n maxZoom: number;\n cancelViewAnimation: () => void;\n clampViewState: () => void;\n onViewStateChange: (state: WsiViewState) => void;\n requestRender: () => void;\n}\n\nexport function startZoomPivotAnimation(ctx: ZoomPivotAnimationContext, targetZoom: number, pivotScreenX: number, pivotScreenY: number, durationMs: number): void {\n const fromState = ctx.camera.getViewState();\n const [pivotWorldX, pivotWorldY] = ctx.camera.screenToWorld(pivotScreenX, pivotScreenY);\n const vp = ctx.camera.getViewportSize();\n const safeTargetZoom = clamp(targetZoom, ctx.minZoom, ctx.maxZoom);\n if (safeTargetZoom === fromState.zoom) return;\n\n const rad = toRadians(fromState.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const screenDx = pivotScreenX - vp.width * 0.5;\n const screenDy = pivotScreenY - vp.height * 0.5;\n\n ctx.cancelViewAnimation();\n\n const computeOffsetForZoom = (z: number): { offsetX: number; offsetY: number } => {\n const worldDx = (screenDx / z) * cos - (screenDy / z) * sin;\n const worldDy = (screenDx / z) * sin + (screenDy / z) * cos;\n return {\n offsetX: pivotWorldX - worldDx - vp.width / (2 * z),\n offsetY: pivotWorldY - worldDy - vp.height / (2 * z),\n };\n };\n\n const finalOffset = computeOffsetForZoom(safeTargetZoom);\n ctx.viewAnimationState.animation = {\n startMs: nowMs(),\n durationMs: Math.max(0, durationMs),\n from: fromState,\n to: { zoom: safeTargetZoom, offsetX: finalOffset.offsetX, offsetY: finalOffset.offsetY, rotationDeg: fromState.rotationDeg },\n easing: linearEasing,\n };\n\n const step = (): void => {\n const animation = ctx.viewAnimationState.animation;\n if (!animation) return;\n\n const elapsed = Math.max(0, nowMs() - animation.startMs);\n const rawT = durationMs <= 0 ? 1 : clamp(elapsed / durationMs, 0, 1);\n const eased = clamp(rawT * rawT * (3 - 2 * rawT), 0, 1);\n\n const z = fromState.zoom + (safeTargetZoom - fromState.zoom) * eased;\n const { offsetX, offsetY } = computeOffsetForZoom(z);\n\n ctx.camera.setViewState({ zoom: z, offsetX, offsetY, rotationDeg: fromState.rotationDeg });\n\n const isComplete = rawT >= 1;\n if (isComplete) {\n ctx.clampViewState();\n ctx.viewAnimationState.animation = null;\n ctx.viewAnimationState.frame = null;\n }\n\n ctx.onViewStateChange(ctx.camera.getViewState());\n ctx.requestRender();\n\n if (!isComplete) {\n ctx.viewAnimationState.frame = requestAnimationFrame(step);\n }\n };\n\n ctx.viewAnimationState.frame = requestAnimationFrame(step);\n}\n","import { OrthoCamera } from \"../core/ortho-camera\";\nimport { observeDevicePixelRatioChanges } from \"./device-pixel-ratio\";\nimport { TileScheduler } from \"./tile-scheduler\";\nimport type { WsiImageColorSettings, WsiImageSource, WsiPointData, WsiRenderStats, WsiViewState } from \"./types\";\nimport { calcViewingMagnification, clamp, isSameViewState, nowMs } from \"./utils\";\nimport { addRendererCanvasEventListeners, type RendererCanvasHandlers, removeRendererCanvasEventListeners, resizeCanvasViewport } from \"./wsi-canvas-lifecycle\";\nimport { cancelDrag as cancelInputDrag, createRendererInputHandlers } from \"./wsi-input-handlers\";\nimport { applyWheelSnapDelta, applyWheelZoomDelta } from \"./wsi-interaction\";\nimport { destroyRenderer, handleContextLost } from \"./wsi-lifecycle-ops\";\nimport {\n arePointSizeMagnificationStopsEqual,\n arePointSizeStopsEqual,\n arePointWeightMagnificationStopsEqual,\n clonePointSizeMagnificationStops,\n clonePointSizeStops,\n clonePointWeightMagnificationStops,\n DEFAULT_POINT_INNER_FILL_COLOR,\n DEFAULT_POINT_SIZE_STOPS,\n DEFAULT_ROTATION_DRAG_SENSITIVITY,\n linearEasing,\n MAX_POINT_SIZE_PX,\n MIN_POINT_SIZE_PX,\n normalizePointInnerFillColor,\n normalizePointInnerFillOpacity,\n normalizePointLineDash,\n normalizePointOpacity,\n normalizePointSizeMagnificationStops,\n normalizePointSizeStops,\n normalizePointWeightMagnificationStops,\n normalizeStrokeScale,\n normalizeTransitionEasing,\n normalizeViewTransitionDuration,\n normalizeZoomOverride,\n resolvePointSizeByMagnificationStops,\n resolvePointSizeByZoomStops,\n resolvePointWeightByMagnificationStops,\n toNormalizedImageColorSettings,\n} from \"./wsi-normalize\";\nimport type { PointBufferRuntime } from \"./wsi-point-data\";\nimport { setPointData as setManagedPointData, setPointPalette as setManagedPointPalette } from \"./wsi-point-data\";\nimport type { RenderPointLayer } from \"./wsi-render-pass\";\nimport { renderFrame } from \"./wsi-render-pass\";\nimport type {\n Bounds,\n CachedTile,\n InteractionState,\n NormalizedImageColorSettings,\n PointProgram,\n PointSizeByMagnification,\n PointSizeByZoom,\n PointSizeMagnificationStop,\n PointSizeStop,\n PointWeightByMagnification,\n PointWeightMagnificationStop,\n TileVertexProgram,\n ViewAnimationRuntimeState,\n WorldPoint,\n WsiTileErrorEvent,\n WsiTileRendererOptions,\n WsiViewTransitionOptions,\n ZoomSnapState,\n} from \"./wsi-renderer-types\";\nimport { initPointProgram, initTileProgram } from \"./wsi-shaders\";\nimport { handleTileLoaded as cacheTileLoaded } from \"./wsi-tile-cache\";\nimport {\n clampViewState as clampManagedViewState,\n getViewBounds as getManagedViewBounds,\n getVisibleTiles as getManagedVisibleTiles,\n getVisibleTilesForTier as getManagedVisibleTilesForTier,\n intersectsBounds as intersectsManagedBounds,\n} from \"./wsi-tile-visibility\";\nimport { cancelViewAnimation as cancelManagedViewAnimation, startViewAnimation } from \"./wsi-view-animation\";\nimport { computeFitToImageTarget, computeZoomByTarget, computeZoomToTarget, resolveTargetViewState as resolveManagedTargetViewState, resolveZoomBounds } from \"./wsi-view-ops\";\nimport { normalizeZoomSnaps, resolveSnapTarget, SNAP_ZOOM_DURATION_MS, startZoomPivotAnimation, type ZoomPivotAnimationContext } from \"./wsi-zoom-snap\";\n\nexport type {\n PointSizeByMagnification,\n PointSizeByZoom,\n PointWeightByMagnification,\n WsiTileErrorEvent,\n WsiTileRendererOptions,\n WsiTileSchedulerConfig,\n WsiViewTransitionOptions,\n} from \"./wsi-renderer-types\";\n\nconst DEFAULT_POINT_LAYER_ID = \"__default_point_layer__\";\n\ninterface ManagedPointLayerState {\n id: string;\n program: PointProgram;\n runtime: PointBufferRuntime;\n pointSizeZoomStops: PointSizeStop[];\n pointSizeMagnificationStops: PointSizeMagnificationStop[] | null;\n pointWeightMagnificationStops: PointWeightMagnificationStop[] | null;\n pointOpacity: number;\n pointLineDash: [number, number];\n pointStrokeScale: number;\n pointInnerFillOpacity: number;\n pointInnerFillColor: [number, number, number];\n}\n\nexport class WsiTileRenderer {\n private readonly canvas: HTMLCanvasElement;\n private readonly source: WsiImageSource;\n private readonly gl: WebGL2RenderingContext;\n private readonly camera = new OrthoCamera();\n private readonly onViewStateChange?: (next: WsiViewState) => void;\n private readonly onStats?: (stats: WsiRenderStats) => void;\n private readonly onTileError?: (event: WsiTileErrorEvent) => void;\n private readonly onContextLost?: () => void;\n private readonly onContextRestored?: () => void;\n private readonly resizeObserver: ResizeObserver;\n private readonly removeDprListener: () => void;\n private tileProgram: TileVertexProgram;\n private readonly tileScheduler: TileScheduler;\n\n private authToken: string;\n private destroyed = false;\n private contextLost = false;\n private frame: number | null = null;\n private frameSerial = 0;\n private interactionState: InteractionState = {\n dragging: false,\n mode: \"none\",\n rotateLastAngleRad: null,\n pointerId: null,\n lastPointerX: 0,\n lastPointerY: 0,\n };\n private interactionLocked = false;\n private ctrlDragRotate = true;\n private rotationDragSensitivityDegPerPixel = DEFAULT_ROTATION_DRAG_SENSITIVITY;\n private maxCacheTiles: number;\n private fitZoom = 1;\n private initialRotationDeg = 0;\n private minZoom = 1e-6;\n private maxZoom = 1;\n private minZoomOverride: number | null = null;\n private maxZoomOverride: number | null = null;\n private viewTransitionDurationMs = 0;\n private viewTransitionEasing: (t: number) => number = linearEasing;\n private viewAnimationState: ViewAnimationRuntimeState = {\n animation: null,\n frame: null,\n };\n private readonly pointLayers = new Map<string, ManagedPointLayerState>();\n private defaultPointSizeZoomStops: PointSizeStop[] = clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n private defaultPointSizeMagnificationStops: PointSizeMagnificationStop[] | null = null;\n private defaultPointWeightMagnificationStops: PointWeightMagnificationStop[] | null = null;\n private defaultPointOpacity = 1.0;\n private defaultPointLineDash: [number, number] = [1, 0];\n private defaultPointStrokeScale = 1.0;\n private defaultPointInnerFillOpacity = 0;\n private defaultPointInnerFillColor: [number, number, number] = [...DEFAULT_POINT_INNER_FILL_COLOR];\n private imageColorSettings: NormalizedImageColorSettings = {\n brightness: 0,\n contrast: 0,\n saturation: 0,\n };\n private cache = new Map<string, CachedTile>();\n private zoomSnaps: number[] = [];\n private zoomSnapFitAsMin = false;\n private zoomSnapState: ZoomSnapState = { accumulatedDelta: 0, lastSnapTimeMs: 0, blockedDirection: null };\n private panExtentX = 0.2;\n private panExtentY = 0.2;\n\n private readonly boundPointerDown: (event: PointerEvent) => void;\n private readonly boundPointerMove: (event: PointerEvent) => void;\n private readonly boundPointerUp: (event: PointerEvent) => void;\n private readonly boundWheel: (event: WheelEvent) => void;\n private readonly boundDoubleClick: (event: MouseEvent) => void;\n private readonly boundContextMenu: (event: MouseEvent) => void;\n private readonly boundContextLost: (event: Event) => void;\n private readonly boundContextRestored: (event: Event) => void;\n\n private getCanvasHandlers(): RendererCanvasHandlers {\n return {\n pointerDown: this.boundPointerDown,\n pointerMove: this.boundPointerMove,\n pointerUp: this.boundPointerUp,\n wheel: this.boundWheel,\n doubleClick: this.boundDoubleClick,\n contextMenu: this.boundContextMenu,\n contextLost: this.boundContextLost,\n contextRestored: this.boundContextRestored,\n };\n }\n\n constructor(canvas: HTMLCanvasElement, source: WsiImageSource, options: WsiTileRendererOptions = {}) {\n this.canvas = canvas;\n this.source = source;\n this.onViewStateChange = options.onViewStateChange;\n this.onStats = options.onStats;\n this.onTileError = options.onTileError;\n this.onContextLost = options.onContextLost;\n this.onContextRestored = options.onContextRestored;\n this.authToken = options.authToken ?? \"\";\n this.maxCacheTiles = Math.max(32, Math.floor(options.maxCacheTiles ?? 320));\n this.initialRotationDeg = typeof options.initialRotationDeg === \"number\" && Number.isFinite(options.initialRotationDeg) ? options.initialRotationDeg : 0;\n this.ctrlDragRotate = options.ctrlDragRotate ?? true;\n this.rotationDragSensitivityDegPerPixel =\n typeof options.rotationDragSensitivityDegPerPixel === \"number\" && Number.isFinite(options.rotationDragSensitivityDegPerPixel)\n ? Math.max(0, options.rotationDragSensitivityDegPerPixel)\n : DEFAULT_ROTATION_DRAG_SENSITIVITY;\n this.defaultPointSizeZoomStops = normalizePointSizeStops(options.pointSizeByZoom);\n this.defaultPointSizeMagnificationStops = normalizePointSizeMagnificationStops(options.pointSizeByMagnification);\n this.defaultPointWeightMagnificationStops = normalizePointWeightMagnificationStops(options.pointWeightByMagnification);\n this.defaultPointOpacity = normalizePointOpacity(options.pointOpacity);\n this.defaultPointStrokeScale = normalizeStrokeScale(options.pointStrokeScale);\n this.defaultPointInnerFillOpacity = normalizePointInnerFillOpacity(options.pointInnerFillOpacity);\n this.defaultPointInnerFillColor = normalizePointInnerFillColor(options.pointInnerFillColor);\n this.imageColorSettings = toNormalizedImageColorSettings(options.imageColorSettings);\n this.minZoomOverride = normalizeZoomOverride(options.minZoom);\n this.maxZoomOverride = normalizeZoomOverride(options.maxZoom);\n this.viewTransitionDurationMs = normalizeViewTransitionDuration(options.viewTransition?.duration);\n this.viewTransitionEasing = normalizeTransitionEasing(options.viewTransition?.easing);\n this.zoomSnaps = normalizeZoomSnaps(options.zoomSnaps, this.source.mpp);\n this.zoomSnapFitAsMin = Boolean(options.zoomSnapFitAsMin);\n this.applyPanExtent(options.panExtent);\n\n const gl = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n powerPreference: \"high-performance\",\n preserveDrawingBuffer: options.preserveDrawingBuffer ?? false,\n });\n if (!gl) {\n throw new Error(\"WebGL2 not supported\");\n }\n this.gl = gl;\n\n this.tileProgram = initTileProgram(this.gl);\n this.tileScheduler = new TileScheduler({\n authToken: this.authToken,\n maxConcurrency: options.tileScheduler?.maxConcurrency ?? 12,\n maxRetries: options.tileScheduler?.maxRetries ?? 2,\n retryBaseDelayMs: options.tileScheduler?.retryBaseDelayMs ?? 120,\n retryMaxDelayMs: options.tileScheduler?.retryMaxDelayMs ?? 1200,\n onTileLoad: (tile, bitmap) =>\n cacheTileLoaded({\n gl: this.gl,\n cache: this.cache,\n tile,\n bitmap,\n frameSerial: this.frameSerial,\n maxCacheTiles: this.maxCacheTiles,\n destroyed: this.destroyed,\n contextLost: this.contextLost,\n requestRender: () => this.requestRender(),\n }),\n onTileError: (tile, error, attemptCount) => {\n this.onTileError?.({ tile, error, attemptCount });\n console.warn(\"tile load failed\", tile.url, error);\n },\n });\n\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(canvas);\n this.removeDprListener = observeDevicePixelRatioChanges(() => this.resize());\n\n const inputHandlers = createRendererInputHandlers({\n canvas: this.canvas,\n state: this.interactionState,\n getInteractionLocked: () => this.interactionLocked,\n getCtrlDragRotate: () => this.ctrlDragRotate,\n getRotationDragSensitivityDegPerPixel: () => this.rotationDragSensitivityDegPerPixel,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n camera: this.camera,\n source: this.source,\n emitViewState: () => this.onViewStateChange?.(this.camera.getViewState()),\n requestRender: () => this.requestRender(),\n getPanExtentX: () => this.panExtentX,\n getPanExtentY: () => this.panExtentY,\n zoomBy: (factor, x, y) => this.zoomBy(factor, x, y),\n getUseZoomSnaps: () => this.zoomSnaps.length > 0,\n onSnapZoom: (direction, x, y) => this.handleSnapZoom(direction, x, y),\n zoomSnapState: this.zoomSnapState,\n });\n this.boundPointerDown = inputHandlers.pointerDown;\n this.boundPointerMove = inputHandlers.pointerMove;\n this.boundPointerUp = inputHandlers.pointerUp;\n this.boundWheel = inputHandlers.wheel;\n this.boundDoubleClick = inputHandlers.doubleClick;\n this.boundContextMenu = inputHandlers.contextMenu;\n this.boundContextLost = (event: Event) => this.onWebGlContextLost(event);\n this.boundContextRestored = (event: Event) => this.onWebGlContextRestored(event);\n\n addRendererCanvasEventListeners(canvas, this.getCanvasHandlers());\n\n this.fitToImage({ duration: 0 });\n this.resize();\n }\n\n private applyZoomBounds(): void {\n const bounds = resolveZoomBounds(this.fitZoom, this.minZoomOverride, this.maxZoomOverride);\n this.minZoom = bounds.minZoom;\n this.maxZoom = bounds.maxZoom;\n }\n\n private resolveTargetViewState(next: Partial<WsiViewState>): WsiViewState {\n return resolveManagedTargetViewState(this.camera, this.minZoom, this.maxZoom, next, () => clampManagedViewState(this.camera, this.source, this.panExtentX, this.panExtentY));\n }\n\n private cancelViewAnimation(): void {\n cancelManagedViewAnimation(this.viewAnimationState);\n }\n\n private startViewAnimation(target: WsiViewState, durationMs: number, easing: (t: number) => number): void {\n startViewAnimation({\n state: this.viewAnimationState,\n camera: this.camera,\n target,\n durationMs,\n easing,\n onUpdate: () => {\n clampManagedViewState(this.camera, this.source, this.panExtentX, this.panExtentY);\n this.onViewStateChange?.(this.camera.getViewState());\n this.requestRender();\n },\n });\n }\n\n private createPointBufferRuntime(): PointBufferRuntime {\n return {\n pointCount: 0,\n usePointIndices: false,\n pointBuffersDirty: true,\n lastPointData: null,\n zeroFillModes: new Uint8Array(0),\n lastPointPalette: null,\n pointPaletteSize: 1,\n };\n }\n\n private createPointLayerState(id: string): ManagedPointLayerState {\n return {\n id,\n program: initPointProgram(this.gl),\n runtime: this.createPointBufferRuntime(),\n pointSizeZoomStops: clonePointSizeStops(this.defaultPointSizeZoomStops),\n pointSizeMagnificationStops: clonePointSizeMagnificationStops(this.defaultPointSizeMagnificationStops),\n pointWeightMagnificationStops: clonePointWeightMagnificationStops(this.defaultPointWeightMagnificationStops),\n pointOpacity: this.defaultPointOpacity,\n pointLineDash: [...this.defaultPointLineDash] as [number, number],\n pointStrokeScale: this.defaultPointStrokeScale,\n pointInnerFillOpacity: this.defaultPointInnerFillOpacity,\n pointInnerFillColor: [...this.defaultPointInnerFillColor],\n };\n }\n\n private ensurePointLayer(layerId: string = DEFAULT_POINT_LAYER_ID): ManagedPointLayerState {\n const nextId = String(layerId || DEFAULT_POINT_LAYER_ID);\n const existing = this.pointLayers.get(nextId);\n if (existing) return existing;\n\n const created = this.createPointLayerState(nextId);\n this.pointLayers.set(nextId, created);\n return created;\n }\n\n private deletePointProgram(program: PointProgram): void {\n if (this.contextLost || this.gl.isContextLost()) return;\n this.gl.deleteBuffer(program.posBuffer);\n this.gl.deleteBuffer(program.classBuffer);\n this.gl.deleteBuffer(program.fillModeBuffer);\n this.gl.deleteBuffer(program.indexBuffer);\n this.gl.deleteTexture(program.paletteTexture);\n this.gl.deleteVertexArray(program.vao);\n this.gl.deleteProgram(program.program);\n }\n\n private getPointRenderLayers(): RenderPointLayer[] {\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const out: RenderPointLayer[] = [];\n for (const layer of this.pointLayers.values()) {\n const pointCssSizePx = this.getPointSize(layer.id);\n out.push({\n pointProgram: layer.program,\n pointCount: layer.runtime.pointCount,\n usePointIndices: layer.runtime.usePointIndices,\n pointPaletteSize: layer.runtime.pointPaletteSize,\n pointLineDash: layer.pointLineDash,\n pointOpacity: layer.pointOpacity,\n pointStrokeScale: this.getPointStrokeScale(layer.id),\n pointInnerFillOpacity: layer.pointInnerFillOpacity,\n pointInnerFillColor: layer.pointInnerFillColor,\n pointCssSizePx,\n pointSizePx: pointCssSizePx * dpr,\n });\n }\n return out;\n }\n\n private applyViewStateAndRender(next: WsiViewState, cancelAnimation = true): void {\n if (cancelAnimation) {\n this.cancelViewAnimation();\n }\n this.camera.setViewState(next);\n this.onViewStateChange?.(this.camera.getViewState());\n this.requestRender();\n }\n\n setAuthToken(token: string): void {\n this.authToken = String(token ?? \"\");\n this.tileScheduler.setAuthToken(this.authToken);\n }\n\n setZoomRange(minZoom: number | null | undefined, maxZoom: number | null | undefined): void {\n const nextMinOverride = normalizeZoomOverride(minZoom);\n const nextMaxOverride = normalizeZoomOverride(maxZoom);\n if (this.minZoomOverride === nextMinOverride && this.maxZoomOverride === nextMaxOverride) {\n return;\n }\n\n this.minZoomOverride = nextMinOverride;\n this.maxZoomOverride = nextMaxOverride;\n this.applyZoomBounds();\n\n const target = this.resolveTargetViewState({});\n const current = this.camera.getViewState();\n if (isSameViewState(current, target)) {\n return;\n }\n this.applyViewStateAndRender(target);\n }\n\n setViewTransition(options: WsiViewTransitionOptions | null | undefined): void {\n this.viewTransitionDurationMs = normalizeViewTransitionDuration(options?.duration);\n this.viewTransitionEasing = normalizeTransitionEasing(options?.easing);\n }\n\n setViewState(next: Partial<WsiViewState>, transition?: WsiViewTransitionOptions): void {\n const target = this.resolveTargetViewState(next);\n const current = this.camera.getViewState();\n if (isSameViewState(current, target)) return;\n\n const durationMs = normalizeViewTransitionDuration(transition?.duration ?? this.viewTransitionDurationMs);\n const easing = normalizeTransitionEasing(transition?.easing ?? this.viewTransitionEasing);\n if (durationMs <= 0) {\n this.applyViewStateAndRender(target);\n return;\n }\n\n this.startViewAnimation(target, durationMs, easing);\n }\n\n getViewState(): WsiViewState {\n return this.camera.getViewState();\n }\n\n getZoomRange(): { minZoom: number; maxZoom: number } {\n return { minZoom: this.minZoom, maxZoom: this.maxZoom };\n }\n\n getRegionLabelAutoLiftCapZoom(): number {\n const valid = this.zoomSnaps.filter(z => z >= this.minZoom && z <= this.maxZoom);\n if (valid.length > 0) {\n return valid[valid.length - 1];\n }\n return this.maxZoom;\n }\n\n isViewAnimating(): boolean {\n return this.viewAnimationState.animation !== null;\n }\n\n registerPointLayer(layerId: string): void {\n this.ensurePointLayer(layerId);\n }\n\n unregisterPointLayer(layerId: string): void {\n const nextId = String(layerId || DEFAULT_POINT_LAYER_ID);\n const layer = this.pointLayers.get(nextId);\n if (!layer) return;\n this.pointLayers.delete(nextId);\n this.deletePointProgram(layer.program);\n this.requestRender();\n }\n\n setPointPalette(colors: Uint8Array | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n layer.runtime = setManagedPointPalette(layer.runtime, this.gl, layer.program, this.contextLost, colors);\n if (!colors || colors.length === 0) {\n return;\n }\n this.requestRender();\n }\n\n setPointLineDash(dashed: [number, number] | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointLineDash(dashed);\n if (layer.pointLineDash[0] === next[0] && layer.pointLineDash[1] === next[1]) return;\n layer.pointLineDash = next;\n this.requestRender();\n }\n\n setPointData(points: WsiPointData | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n layer.runtime = setManagedPointData(layer.runtime, this.gl, layer.program, this.contextLost, points);\n this.requestRender();\n }\n\n setInteractionLock(locked: boolean): void {\n const next = Boolean(locked);\n if (this.interactionLocked === next) return;\n this.interactionLocked = next;\n if (next) this.cancelDrag();\n }\n\n setPointSizeByZoom(pointSizeByZoom: PointSizeByZoom | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const nextStops = normalizePointSizeStops(pointSizeByZoom);\n if (arePointSizeStopsEqual(layer.pointSizeZoomStops, nextStops)) return;\n layer.pointSizeZoomStops = nextStops;\n this.requestRender();\n }\n\n setPointSizeByMagnification(pointSizeByMagnification: PointSizeByMagnification | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const nextStops = normalizePointSizeMagnificationStops(pointSizeByMagnification);\n if (arePointSizeMagnificationStopsEqual(layer.pointSizeMagnificationStops, nextStops)) return;\n layer.pointSizeMagnificationStops = nextStops;\n this.requestRender();\n }\n\n setPointWeightByMagnification(pointWeightByMagnification: PointWeightByMagnification | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const nextStops = normalizePointWeightMagnificationStops(pointWeightByMagnification);\n if (arePointWeightMagnificationStopsEqual(layer.pointWeightMagnificationStops, nextStops)) return;\n layer.pointWeightMagnificationStops = nextStops;\n this.requestRender();\n }\n\n setPointOpacity(opacity: number | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointOpacity(opacity);\n if (layer.pointOpacity === next) return;\n layer.pointOpacity = next;\n this.requestRender();\n }\n\n setPointStrokeScale(scale: number | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizeStrokeScale(scale);\n if (layer.pointStrokeScale === next) return;\n layer.pointStrokeScale = next;\n this.requestRender();\n }\n\n setPointInnerFillOpacity(opacity: number | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointInnerFillOpacity(opacity);\n if (layer.pointInnerFillOpacity === next) return;\n layer.pointInnerFillOpacity = next;\n this.requestRender();\n }\n\n setPointInnerFillColor(color: string | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointInnerFillColor(color);\n if (layer.pointInnerFillColor[0] === next[0] && layer.pointInnerFillColor[1] === next[1] && layer.pointInnerFillColor[2] === next[2]) {\n return;\n }\n layer.pointInnerFillColor = next;\n this.requestRender();\n }\n\n setImageColorSettings(settings: WsiImageColorSettings | null | undefined): void {\n const next = toNormalizedImageColorSettings(settings);\n const prev = this.imageColorSettings;\n if (prev.brightness === next.brightness && prev.contrast === next.contrast && prev.saturation === next.saturation) {\n return;\n }\n this.imageColorSettings = next;\n this.requestRender();\n }\n\n cancelDrag(): void {\n cancelInputDrag(this.canvas, this.interactionState);\n }\n\n screenToWorld(clientX: number, clientY: number): [number, number] {\n const rect = this.canvas.getBoundingClientRect();\n const sx = clientX - rect.left;\n const sy = clientY - rect.top;\n return this.camera.screenToWorld(sx, sy);\n }\n\n worldToScreen(worldX: number, worldY: number): [number, number] {\n return this.camera.worldToScreen(worldX, worldY);\n }\n\n setViewCenter(worldX: number, worldY: number, transition?: WsiViewTransitionOptions): void {\n if (!Number.isFinite(worldX) || !Number.isFinite(worldY)) return;\n const state = this.camera.getViewState();\n const zoom = Math.max(1e-6, state.zoom);\n const vp = this.camera.getViewportSize();\n this.setViewState(\n {\n offsetX: worldX - vp.width / (2 * zoom),\n offsetY: worldY - vp.height / (2 * zoom),\n },\n transition\n );\n }\n\n getViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n return this.camera.getViewCorners();\n }\n\n getInitialRotationDeg(): number {\n return this.initialRotationDeg;\n }\n\n getViewBounds(): Bounds {\n return getManagedViewBounds(this.camera);\n }\n\n resetRotation(transition?: WsiViewTransitionOptions): void {\n const state = this.camera.getViewState();\n if (Math.abs(state.rotationDeg - this.initialRotationDeg) < 1e-6) return;\n this.setViewState({ rotationDeg: this.initialRotationDeg }, transition);\n }\n\n getPointSize(layerId: string = DEFAULT_POINT_LAYER_ID): number {\n const layer = this.pointLayers.get(String(layerId || DEFAULT_POINT_LAYER_ID));\n const magnificationStops = layer?.pointSizeMagnificationStops ?? this.defaultPointSizeMagnificationStops;\n if (magnificationStops && magnificationStops.length > 0) {\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const magnification = calcViewingMagnification(this.source.mpp ?? 0, zoom);\n if (magnification > 0) {\n const size = resolvePointSizeByMagnificationStops(magnification, magnificationStops);\n return clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n }\n }\n\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n const stops = layer?.pointSizeZoomStops ?? this.defaultPointSizeZoomStops;\n const size = resolvePointSizeByZoomStops(continuousZoom, stops);\n return clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n }\n\n getPointSizeByZoom(layerId: string = DEFAULT_POINT_LAYER_ID): number {\n return this.getPointSize(layerId);\n }\n\n getPointStrokeScale(layerId: string = DEFAULT_POINT_LAYER_ID): number {\n const layer = this.pointLayers.get(String(layerId || DEFAULT_POINT_LAYER_ID));\n const magnificationStops = layer?.pointWeightMagnificationStops ?? this.defaultPointWeightMagnificationStops;\n if (magnificationStops && magnificationStops.length > 0) {\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const magnification = calcViewingMagnification(this.source.mpp ?? 0, zoom);\n if (magnification > 0) {\n return normalizeStrokeScale(resolvePointWeightByMagnificationStops(magnification, magnificationStops));\n }\n }\n return layer?.pointStrokeScale ?? this.defaultPointStrokeScale;\n }\n\n fitToImage(transition?: WsiViewTransitionOptions): void {\n const rect = this.canvas.getBoundingClientRect();\n const vw = Math.max(1, rect.width || 1);\n const vh = Math.max(1, rect.height || 1);\n const fitTarget = computeFitToImageTarget(this.source, vw, vh, this.minZoom, this.maxZoom, this.initialRotationDeg);\n this.fitZoom = fitTarget.fitZoom;\n this.applyZoomBounds();\n this.setViewState(fitTarget.target, transition);\n }\n\n zoomBy(factor: number, screenX: number, screenY: number, transition?: WsiViewTransitionOptions): void {\n const target = computeZoomByTarget(this.camera, this.minZoom, this.maxZoom, factor, screenX, screenY);\n if (!target) return;\n this.setViewState(target, transition);\n }\n\n handleWheelZoom(deltaY: number, screenX: number, screenY: number): void {\n if (this.zoomSnaps.length > 0) {\n applyWheelSnapDelta(deltaY, screenX, screenY, this.zoomSnapState, (direction, x, y) => this.handleSnapZoom(direction, x, y));\n return;\n }\n applyWheelZoomDelta(deltaY, screenX, screenY, (factor, x, y) => this.zoomBy(factor, x, y));\n }\n\n zoomTo(zoom: number, screenX: number, screenY: number, transition?: WsiViewTransitionOptions): void {\n const target = computeZoomToTarget(this.camera, this.minZoom, this.maxZoom, zoom, screenX, screenY);\n if (!target) return;\n this.setViewState(target, transition);\n }\n\n setZoomSnaps(magnifications: number[] | null | undefined, fitAsMin?: boolean): void {\n this.zoomSnaps = normalizeZoomSnaps(magnifications, this.source.mpp);\n this.zoomSnapFitAsMin = Boolean(fitAsMin);\n }\n\n setPanExtent(extent: number | { x: number; y: number } | null | undefined): void {\n this.applyPanExtent(extent);\n }\n\n private applyPanExtent(extent: number | { x: number; y: number } | null | undefined): void {\n if (typeof extent === \"number\" && Number.isFinite(extent)) {\n this.panExtentX = Math.max(0, extent);\n this.panExtentY = Math.max(0, extent);\n } else if (extent != null && typeof extent === \"object\") {\n this.panExtentX = typeof extent.x === \"number\" && Number.isFinite(extent.x) ? Math.max(0, extent.x) : 0.2;\n this.panExtentY = typeof extent.y === \"number\" && Number.isFinite(extent.y) ? Math.max(0, extent.y) : 0.2;\n } else {\n this.panExtentX = 0.2;\n this.panExtentY = 0.2;\n }\n }\n\n private getZoomPivotAnimationContext(): ZoomPivotAnimationContext {\n return {\n camera: this.camera,\n viewAnimationState: this.viewAnimationState,\n minZoom: this.minZoom,\n maxZoom: this.maxZoom,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n clampViewState: () => clampManagedViewState(this.camera, this.source, this.panExtentX, this.panExtentY),\n onViewStateChange: state => this.onViewStateChange?.(state),\n requestRender: () => this.requestRender(),\n };\n }\n\n private handleSnapZoom(direction: \"in\" | \"out\", screenX: number, screenY: number): boolean {\n const ongoing = this.viewAnimationState.animation;\n const baseZoom = ongoing ? ongoing.to.zoom : this.camera.getViewState().zoom;\n const validSnaps = this.zoomSnaps.filter(z => z >= this.minZoom && z <= this.maxZoom);\n const result = resolveSnapTarget(validSnaps, baseZoom, direction, this.zoomSnapFitAsMin);\n if (!result) return false;\n\n let targetZoom: number;\n\n if (result.type === \"fit\") {\n const rect = this.canvas.getBoundingClientRect();\n const vw = Math.max(1, rect.width || 1);\n const vh = Math.max(1, rect.height || 1);\n const fitTarget = computeFitToImageTarget(this.source, vw, vh, this.minZoom, this.maxZoom, this.initialRotationDeg);\n this.fitZoom = fitTarget.fitZoom;\n this.applyZoomBounds();\n targetZoom = fitTarget.target.zoom;\n } else {\n targetZoom = result.zoom;\n }\n\n const epsilon = Math.max(Math.abs(targetZoom) * 0.005, 1e-8);\n\n if (ongoing) {\n const ongoingDirection: \"in\" | \"out\" | null = ongoing.to.zoom > ongoing.from.zoom + epsilon ? \"in\" : ongoing.to.zoom < ongoing.from.zoom - epsilon ? \"out\" : null;\n if (ongoingDirection === direction && Math.abs(ongoing.to.zoom - targetZoom) <= epsilon) {\n return false;\n }\n } else if (Math.abs(baseZoom - targetZoom) <= epsilon) {\n return false;\n }\n\n startZoomPivotAnimation(this.getZoomPivotAnimationContext(), targetZoom, screenX, screenY, SNAP_ZOOM_DURATION_MS);\n return true;\n }\n\n render(): void {\n if (this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n const frameStartMs = this.onStats ? nowMs() : 0;\n this.frameSerial += 1;\n\n const result = renderFrame({\n gl: this.gl,\n camera: this.camera,\n source: this.source,\n cache: this.cache,\n frameSerial: this.frameSerial,\n tileProgram: this.tileProgram,\n imageColorSettings: this.imageColorSettings,\n pointLayers: this.getPointRenderLayers(),\n tileScheduler: this.tileScheduler,\n getVisibleTiles: () => getManagedVisibleTiles(this.camera, this.source),\n getVisibleTilesForTier: tier => getManagedVisibleTilesForTier(this.camera, this.source, tier),\n getViewBounds: () => getManagedViewBounds(this.camera),\n intersectsBounds: intersectsManagedBounds,\n });\n if (this.onStats) {\n const schedulerStats = this.tileScheduler.getSnapshot();\n this.onStats({\n tier: result.tier,\n visible: result.visible,\n rendered: result.rendered,\n points: result.points,\n fallback: result.fallback,\n cache: this.cache.size,\n inflight: schedulerStats.inflight,\n queued: schedulerStats.queued,\n retries: schedulerStats.retries,\n failed: schedulerStats.failed,\n aborted: schedulerStats.aborted,\n cacheHits: result.cacheHits,\n cacheMisses: result.cacheMisses,\n drawCalls: result.drawCalls,\n frameMs: nowMs() - frameStartMs,\n });\n }\n }\n\n requestRender(): void {\n if (this.frame !== null || this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n this.frame = requestAnimationFrame(() => {\n this.frame = null;\n this.render();\n });\n }\n\n resize(): void {\n resizeCanvasViewport(this.canvas, this.gl, this.camera);\n this.requestRender();\n }\n\n private onWebGlContextLost(event: Event): void {\n const result = handleContextLost({\n event,\n destroyed: this.destroyed,\n contextLost: this.contextLost,\n frame: this.frame,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n cancelDrag: () => this.cancelDrag(),\n tileScheduler: this.tileScheduler,\n cache: this.cache,\n onContextLost: this.onContextLost,\n });\n if (!result.handled) return;\n this.frame = result.frame;\n this.contextLost = true;\n for (const layer of this.pointLayers.values()) {\n layer.runtime = {\n ...layer.runtime,\n pointBuffersDirty: true,\n };\n }\n }\n\n private onWebGlContextRestored(_event: Event): void {\n if (this.destroyed) return;\n this.contextLost = false;\n this.cache.clear();\n\n this.tileProgram = initTileProgram(this.gl);\n for (const layer of this.pointLayers.values()) {\n layer.program = initPointProgram(this.gl);\n layer.runtime = {\n ...layer.runtime,\n pointBuffersDirty: true,\n };\n if (layer.runtime.lastPointPalette && layer.runtime.lastPointPalette.length > 0) {\n layer.runtime = setManagedPointPalette(layer.runtime, this.gl, layer.program, this.contextLost, layer.runtime.lastPointPalette);\n }\n if (layer.runtime.lastPointData) {\n layer.runtime = setManagedPointData(layer.runtime, this.gl, layer.program, this.contextLost, layer.runtime.lastPointData);\n }\n }\n\n this.resize();\n this.onContextRestored?.();\n }\n\n destroy(): void {\n const result = destroyRenderer({\n destroyed: this.destroyed,\n frame: this.frame,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n resizeObserver: this.resizeObserver,\n removeDprListener: this.removeDprListener,\n removeCanvasEventListeners: () => removeRendererCanvasEventListeners(this.canvas, this.getCanvasHandlers()),\n cancelDrag: () => this.cancelDrag(),\n tileScheduler: this.tileScheduler,\n contextLost: this.contextLost,\n gl: this.gl,\n cache: this.cache,\n tileProgram: this.tileProgram,\n pointPrograms: Array.from(this.pointLayers.values(), layer => layer.program),\n });\n if (!result.didDestroy) return;\n this.destroyed = true;\n this.frame = result.frame;\n }\n}\n","import { type CSSProperties, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { observeDevicePixelRatioChanges } from \"../wsi/device-pixel-ratio\";\nimport type { WsiImageColorSettings, WsiImageSource, WsiRenderStats, WsiViewState } from \"../wsi/types\";\nimport type { WsiTileErrorEvent, WsiViewTransitionOptions } from \"../wsi/wsi-tile-renderer\";\nimport { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate } from \"./draw-layer-types\";\nimport { toDrawCoordinate } from \"./draw-layer-utils\";\nimport type { OverlayDrawFn, ViewerContextValue } from \"./viewer-context\";\nimport { ViewerContextProvider } from \"./viewer-context\";\nimport type { PointerWorldMoveEvent } from \"./wsi-viewer-canvas-types\";\n\nexport interface WsiViewerProps {\n source: WsiImageSource | null;\n viewState?: Partial<WsiViewState> | null;\n onViewStateChange?: (next: WsiViewState) => void;\n onStats?: (stats: WsiRenderStats) => void;\n onTileError?: (event: WsiTileErrorEvent) => void;\n onContextLost?: () => void;\n onContextRestored?: () => void;\n imageColorSettings?: WsiImageColorSettings | null;\n initialRotate?: number;\n fitNonce?: number;\n rotationResetNonce?: number;\n authToken?: string;\n ctrlDragRotate?: boolean;\n minZoom?: number;\n maxZoom?: number;\n viewTransition?: WsiViewTransitionOptions;\n zoomSnaps?: number[];\n zoomSnapFitAsMin?: boolean;\n panExtent?: number | { x: number; y: number };\n preserveDrawingBuffer?: boolean;\n onPointerWorldMove?: (event: PointerWorldMoveEvent) => void;\n debugOverlay?: boolean;\n debugOverlayStyle?: CSSProperties;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\ninterface DrawCallbackEntry {\n id: string;\n priority: number;\n draw: OverlayDrawFn;\n}\n\nconst EMPTY_DRAW_CALLBACKS: DrawCallbackEntry[] = [];\n\nfunction toFiniteRotation(value: number | undefined): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nexport function WsiViewer({\n source,\n viewState,\n onViewStateChange,\n onStats,\n onTileError,\n onContextLost,\n onContextRestored,\n imageColorSettings = null,\n initialRotate = 0,\n fitNonce = 0,\n rotationResetNonce = 0,\n authToken = \"\",\n ctrlDragRotate = true,\n minZoom,\n maxZoom,\n viewTransition,\n zoomSnaps,\n zoomSnapFitAsMin,\n panExtent,\n preserveDrawingBuffer,\n onPointerWorldMove,\n debugOverlay = false,\n debugOverlayStyle,\n className,\n style,\n children,\n}: WsiViewerProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const overlayCanvasRef = useRef<HTMLCanvasElement | null>(null);\n const rendererRef = useRef<WsiTileRenderer | null>(null);\n const drawInvalidateRef = useRef<(() => void) | null>(null);\n const overviewInvalidateRef = useRef<(() => void) | null>(null);\n const drawCallbacksRef = useRef<DrawCallbackEntry[]>(EMPTY_DRAW_CALLBACKS);\n const overlayPendingRef = useRef(false);\n const interactionLocksRef = useRef<Set<string>>(new Set());\n const viewStateListenersRef = useRef<Set<(state: WsiViewState) => void>>(new Set());\n\n const onViewStateChangeRef = useRef(onViewStateChange);\n const onStatsRef = useRef(onStats);\n const onTileErrorRef = useRef(onTileError);\n const onContextLostRef = useRef(onContextLost);\n const onContextRestoredRef = useRef(onContextRestored);\n\n const [rendererSerial, setRendererSerial] = useState(0);\n const [debugStats, setDebugStats] = useState<WsiRenderStats | null>(null);\n const debugOverlayRef = useRef(debugOverlay);\n\n useEffect(() => {\n onViewStateChangeRef.current = onViewStateChange;\n }, [onViewStateChange]);\n useEffect(() => {\n onStatsRef.current = onStats;\n }, [onStats]);\n useEffect(() => {\n onTileErrorRef.current = onTileError;\n }, [onTileError]);\n useEffect(() => {\n onContextLostRef.current = onContextLost;\n }, [onContextLost]);\n useEffect(() => {\n onContextRestoredRef.current = onContextRestored;\n }, [onContextRestored]);\n useEffect(() => {\n debugOverlayRef.current = debugOverlay;\n if (!debugOverlay) setDebugStats(null);\n }, [debugOverlay]);\n\n const mergedStyle = useMemo<CSSProperties>(() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }), [style]);\n\n const mergedDebugOverlayStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n top: 8,\n left: 8,\n zIndex: 7,\n margin: 0,\n padding: \"8px 10px\",\n maxWidth: \"min(420px, 80%)\",\n pointerEvents: \"none\",\n whiteSpace: \"pre-wrap\",\n lineHeight: 1.35,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 11,\n color: \"#cde6ff\",\n background: \"rgba(6, 12, 20, 0.82)\",\n border: \"1px solid rgba(173, 216, 255, 0.28)\",\n borderRadius: 8,\n boxShadow: \"0 8px 22px rgba(0,0,0,0.35)\",\n ...debugOverlayStyle,\n }),\n [debugOverlayStyle]\n );\n\n const initialRotateValue = toFiniteRotation(initialRotate);\n\n const toExternalViewState = useCallback(\n (state: WsiViewState): WsiViewState => ({\n ...state,\n rotationDeg: state.rotationDeg - initialRotateValue,\n }),\n [initialRotateValue]\n );\n\n const toInternalViewState = useCallback(\n (state: Partial<WsiViewState>): Partial<WsiViewState> => {\n if (typeof state.rotationDeg !== \"number\" || !Number.isFinite(state.rotationDeg)) {\n return state;\n }\n return {\n ...state,\n rotationDeg: state.rotationDeg + initialRotateValue,\n };\n },\n [initialRotateValue]\n );\n\n const handleRendererStats = useCallback((stats: WsiRenderStats): void => {\n onStatsRef.current?.(stats);\n if (debugOverlayRef.current) setDebugStats(stats);\n }, []);\n\n const debugOverlayText = useMemo(() => {\n if (!debugStats) return \"stats: waiting for first frame...\";\n return [\n `tier ${debugStats.tier} | frame ${debugStats.frameMs?.toFixed(2) ?? \"-\"} ms | drawCalls ${debugStats.drawCalls ?? \"-\"}`,\n `tiles visible ${debugStats.visible} | rendered ${debugStats.rendered} | fallback ${debugStats.fallback}`,\n `cache size ${debugStats.cache} | hit ${debugStats.cacheHits ?? \"-\"} | miss ${debugStats.cacheMisses ?? \"-\"}`,\n `queue inflight ${debugStats.inflight} | queued ${debugStats.queued ?? \"-\"} | retries ${debugStats.retries ?? \"-\"} | failed ${debugStats.failed ?? \"-\"} | aborted ${debugStats.aborted ?? \"-\"}`,\n `points ${debugStats.points}`,\n ].join(\"\\n\");\n }, [debugStats]);\n\n // --- overlay draw registry ---\n\n const drawOverlayFrame = useCallback(() => {\n const canvas = overlayCanvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const rect = canvas.getBoundingClientRect();\n const w = Math.max(1, Math.round(rect.width * dpr));\n const h = Math.max(1, Math.round(rect.height * dpr));\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n\n const logicalWidth = rect.width;\n const logicalHeight = rect.height;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n const entries = drawCallbacksRef.current;\n for (let i = 0; i < entries.length; i += 1) {\n ctx.save();\n entries[i].draw(ctx, logicalWidth, logicalHeight);\n ctx.restore();\n }\n }, []);\n\n const requestOverlayRedraw = useCallback(() => {\n if (overlayPendingRef.current) return;\n overlayPendingRef.current = true;\n requestAnimationFrame(() => {\n overlayPendingRef.current = false;\n drawOverlayFrame();\n });\n }, [drawOverlayFrame]);\n\n const registerDrawCallback = useCallback(\n (id: string, priority: number, draw: OverlayDrawFn) => {\n const entries = drawCallbacksRef.current.filter(e => e.id !== id);\n entries.push({ id, priority, draw });\n entries.sort((a, b) => a.priority - b.priority);\n drawCallbacksRef.current = entries;\n requestOverlayRedraw();\n },\n [requestOverlayRedraw]\n );\n\n const unregisterDrawCallback = useCallback(\n (id: string) => {\n drawCallbacksRef.current = drawCallbacksRef.current.filter(e => e.id !== id);\n requestOverlayRedraw();\n },\n [requestOverlayRedraw]\n );\n\n const setInteractionLock = useCallback((id: string, locked: boolean) => {\n if (locked) {\n interactionLocksRef.current.add(id);\n } else {\n interactionLocksRef.current.delete(id);\n }\n rendererRef.current?.setInteractionLock(interactionLocksRef.current.size > 0);\n }, []);\n\n const isInteractionLocked = useCallback(() => interactionLocksRef.current.size > 0, []);\n\n // --- coordinate transforms ---\n\n const worldToScreen = useCallback((worldX: number, worldY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n return toDrawCoordinate(renderer.worldToScreen(worldX, worldY));\n }, []);\n\n const screenToWorld = useCallback((clientX: number, clientY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.screenToWorld(clientX, clientY);\n if (!Array.isArray(raw) || raw.length < 2) return null;\n const x = Number(raw[0]);\n const y = Number(raw[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const registerViewStateListener = useCallback((listener: (state: WsiViewState) => void) => {\n viewStateListenersRef.current.add(listener);\n return () => {\n viewStateListenersRef.current.delete(listener);\n };\n }, []);\n\n // --- viewState change propagation ---\n\n const emitViewStateChange = useCallback(\n (nextInternal: WsiViewState): void => {\n onViewStateChangeRef.current?.(toExternalViewState(nextInternal));\n const listeners = viewStateListenersRef.current;\n if (listeners.size > 0) {\n const snapshot = Array.from(listeners);\n for (let i = 0; i < snapshot.length; i += 1) {\n snapshot[i](nextInternal);\n }\n }\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n requestOverlayRedraw();\n },\n [requestOverlayRedraw, toExternalViewState]\n );\n\n // --- renderer lifecycle ---\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !source) return;\n\n const renderer = new WsiTileRenderer(canvas, source, {\n onViewStateChange: emitViewStateChange,\n onStats: handleRendererStats,\n onTileError: event => {\n onTileErrorRef.current?.(event);\n },\n onContextLost: () => {\n onContextLostRef.current?.();\n },\n onContextRestored: () => {\n onContextRestoredRef.current?.();\n },\n authToken,\n imageColorSettings,\n initialRotationDeg: initialRotate,\n ctrlDragRotate,\n minZoom,\n maxZoom,\n viewTransition,\n zoomSnaps,\n zoomSnapFitAsMin,\n panExtent,\n preserveDrawingBuffer,\n });\n\n rendererRef.current = renderer;\n setRendererSerial(s => s + 1);\n if (viewState) renderer.setViewState(toInternalViewState(viewState));\n renderer.setInteractionLock(interactionLocksRef.current.size > 0);\n\n return () => {\n renderer.destroy();\n rendererRef.current = null;\n };\n }, [source, handleRendererStats, ctrlDragRotate, emitViewStateChange, initialRotateValue, toInternalViewState]);\n\n // --- core renderer sync effects ---\n\n useEffect(() => {\n rendererRef.current?.setAuthToken(authToken);\n }, [authToken]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !viewState) return;\n if (renderer.isViewAnimating()) return;\n renderer.setViewState(toInternalViewState(viewState));\n }, [viewState, toInternalViewState]);\n\n useEffect(() => {\n rendererRef.current?.fitToImage();\n }, [fitNonce]);\n useEffect(() => {\n rendererRef.current?.resetRotation();\n }, [rotationResetNonce]);\n\n useEffect(() => {\n rendererRef.current?.setZoomRange(minZoom, maxZoom);\n }, [minZoom, maxZoom]);\n useEffect(() => {\n rendererRef.current?.setViewTransition(viewTransition);\n }, [viewTransition]);\n useEffect(() => {\n rendererRef.current?.setZoomSnaps(zoomSnaps, zoomSnapFitAsMin);\n }, [zoomSnaps, zoomSnapFitAsMin]);\n useEffect(() => {\n rendererRef.current?.setPanExtent(panExtent);\n }, [panExtent]);\n useEffect(() => {\n rendererRef.current?.setImageColorSettings(imageColorSettings);\n }, [imageColorSettings]);\n\n // --- overlay canvas setup ---\n\n useEffect(() => {\n const canvas = overlayCanvasRef.current;\n if (!canvas) return;\n drawInvalidateRef.current = requestOverlayRedraw;\n requestOverlayRedraw();\n\n const observer = new ResizeObserver(() => requestOverlayRedraw());\n observer.observe(canvas);\n return () => {\n observer.disconnect();\n if (drawInvalidateRef.current === requestOverlayRedraw) {\n drawInvalidateRef.current = null;\n }\n };\n }, [requestOverlayRedraw]);\n\n useEffect(() => observeDevicePixelRatioChanges(() => requestOverlayRedraw()), [requestOverlayRedraw]);\n\n // --- context value ---\n\n const contextValue = useMemo<ViewerContextValue>(\n () => ({\n source,\n rendererRef,\n rendererSerial,\n canvasRef,\n containerRef,\n drawInvalidateRef,\n overviewInvalidateRef,\n worldToScreen,\n screenToWorld,\n registerDrawCallback,\n unregisterDrawCallback,\n requestOverlayRedraw,\n registerViewStateListener,\n setInteractionLock,\n isInteractionLocked,\n }),\n [source, rendererSerial, worldToScreen, screenToWorld, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw, registerViewStateListener, setInteractionLock, isInteractionLocked]\n );\n\n const onPointerWorldMoveRef = useRef(onPointerWorldMove);\n useEffect(() => {\n onPointerWorldMoveRef.current = onPointerWorldMove;\n }, [onPointerWorldMove]);\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n const cb = onPointerWorldMoveRef.current;\n if (!cb) return;\n const coord = screenToWorld(e.clientX, e.clientY);\n const insideImage = !!coord && coord[0] >= 0 && coord[1] >= 0 && !!source && coord[0] <= source.width && coord[1] <= source.height;\n cb({ coordinate: coord, clientX: e.clientX, clientY: e.clientY, insideImage });\n },\n [screenToWorld, source]\n );\n\n const handlePointerLeave = useCallback(() => {\n onPointerWorldMoveRef.current?.({ coordinate: null, clientX: -1, clientY: -1, insideImage: false });\n }, []);\n\n return (\n <ViewerContextProvider value={contextValue}>\n <div\n ref={containerRef}\n className={className}\n style={mergedStyle}\n onPointerMove={onPointerWorldMove ? handlePointerMove : undefined}\n onPointerLeave={onPointerWorldMove ? handlePointerLeave : undefined}\n >\n <canvas\n ref={canvasRef}\n className=\"wsi-render-canvas\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 1,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n }}\n />\n <canvas\n ref={overlayCanvasRef}\n className=\"wsi-overlay-canvas\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 2,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n pointerEvents: \"none\",\n touchAction: \"none\",\n }}\n />\n {children}\n {debugOverlay && (\n <pre data-open-plant-debug-overlay style={mergedDebugOverlayStyle}>\n {debugOverlayText}\n </pre>\n )}\n </div>\n </ViewerContextProvider>\n );\n}\n","import { type PreparedRoiPolygon, pointInPreparedPolygon, prepareRoiPolygons, toRoiGeometry } from \"./roi-geometry\";\nimport type { WsiPointData, WsiRegion } from \"./types\";\n\nexport interface RoiClassCount {\n classId: string;\n paletteIndex: number;\n count: number;\n}\n\nexport interface RoiPointGroup {\n regionId: string | number;\n regionIndex: number;\n totalCount: number;\n classCounts: RoiClassCount[];\n}\n\nexport interface RoiPointGroupOptions {\n paletteIndexToClassId?: ReadonlyMap<number, string> | readonly string[];\n includeEmptyRegions?: boolean;\n}\n\nexport interface RoiPointGroupStats {\n groups: RoiPointGroup[];\n inputPointCount: number;\n pointsInsideAnyRegion: number;\n unmatchedPointCount: number;\n}\n\ninterface PreparedRegion {\n regionId: string | number;\n regionIndex: number;\n polygons: PreparedRoiPolygon[];\n area: number;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nfunction prepareRegions(regions: readonly WsiRegion[]): PreparedRegion[] {\n const prepared: PreparedRegion[] = [];\n for (let i = 0; i < regions.length; i += 1) {\n const region = regions[i];\n const polygons = prepareRoiPolygons([toRoiGeometry(region?.coordinates)]);\n if (polygons.length === 0) continue;\n\n let area = 0;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const polygon of polygons) {\n area += polygon.area;\n if (polygon.minX < minX) minX = polygon.minX;\n if (polygon.minY < minY) minY = polygon.minY;\n if (polygon.maxX > maxX) maxX = polygon.maxX;\n if (polygon.maxY > maxY) maxY = polygon.maxY;\n }\n if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) continue;\n\n prepared.push({\n regionId: region.id ?? i,\n regionIndex: i,\n polygons,\n area: Math.max(1e-6, area),\n minX,\n minY,\n maxX,\n maxY,\n });\n }\n return prepared;\n}\n\ninterface PreparedRegionGridIndex {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n gridSize: number;\n cellWidth: number;\n cellHeight: number;\n buckets: number[][];\n}\n\nconst MAX_REGION_GRID_SIZE = 128;\nconst EMPTY_CANDIDATE_REGION_INDICES: number[] = [];\n\nfunction toGridCell(value: number, min: number, max: number, cellSize: number, gridSize: number): number {\n if (gridSize <= 1 || max <= min) return 0;\n const ratio = (value - min) / cellSize;\n if (!Number.isFinite(ratio) || ratio <= 0) return 0;\n if (ratio >= gridSize - 1) return gridSize - 1;\n return Math.floor(ratio);\n}\n\nfunction buildPreparedRegionGridIndex(regions: readonly PreparedRegion[]): PreparedRegionGridIndex | null {\n if (regions.length === 0) return null;\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const region of regions) {\n if (region.minX < minX) minX = region.minX;\n if (region.minY < minY) minY = region.minY;\n if (region.maxX > maxX) maxX = region.maxX;\n if (region.maxY > maxY) maxY = region.maxY;\n }\n if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {\n return null;\n }\n\n const estimated = Math.ceil(Math.sqrt(regions.length * 2));\n const gridSize = Math.max(1, Math.min(MAX_REGION_GRID_SIZE, estimated));\n const cellWidth = maxX > minX ? (maxX - minX) / gridSize : 1;\n const cellHeight = maxY > minY ? (maxY - minY) / gridSize : 1;\n const buckets = Array.from({ length: gridSize * gridSize }, () => [] as number[]);\n\n for (let regionArrayIndex = 0; regionArrayIndex < regions.length; regionArrayIndex += 1) {\n const region = regions[regionArrayIndex];\n const minCellX = toGridCell(region.minX, minX, maxX, cellWidth, gridSize);\n const maxCellX = toGridCell(region.maxX, minX, maxX, cellWidth, gridSize);\n const minCellY = toGridCell(region.minY, minY, maxY, cellHeight, gridSize);\n const maxCellY = toGridCell(region.maxY, minY, maxY, cellHeight, gridSize);\n for (let cellY = minCellY; cellY <= maxCellY; cellY += 1) {\n for (let cellX = minCellX; cellX <= maxCellX; cellX += 1) {\n buckets[cellY * gridSize + cellX].push(regionArrayIndex);\n }\n }\n }\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n gridSize,\n cellWidth,\n cellHeight,\n buckets,\n };\n}\n\nfunction getCandidateRegionIndices(index: PreparedRegionGridIndex | null, x: number, y: number): readonly number[] {\n if (!index) return EMPTY_CANDIDATE_REGION_INDICES;\n if (x < index.minX || x > index.maxX || y < index.minY || y > index.maxY) {\n return EMPTY_CANDIDATE_REGION_INDICES;\n }\n const cellX = toGridCell(x, index.minX, index.maxX, index.cellWidth, index.gridSize);\n const cellY = toGridCell(y, index.minY, index.maxY, index.cellHeight, index.gridSize);\n return index.buckets[cellY * index.gridSize + cellX] ?? EMPTY_CANDIDATE_REGION_INDICES;\n}\n\nfunction resolveClassId(paletteIndex: number, paletteIndexToClassId: RoiPointGroupOptions[\"paletteIndexToClassId\"]): string {\n if (Array.isArray(paletteIndexToClassId)) {\n const fromArray = paletteIndexToClassId[paletteIndex];\n if (typeof fromArray === \"string\" && fromArray.length > 0) return fromArray;\n }\n if (paletteIndexToClassId instanceof Map) {\n const fromMap = paletteIndexToClassId.get(paletteIndex);\n if (typeof fromMap === \"string\" && fromMap.length > 0) return fromMap;\n }\n return String(paletteIndex);\n}\n\nexport function computeRoiPointGroups(pointData: WsiPointData | null | undefined, regions: readonly WsiRegion[] | null | undefined, options: RoiPointGroupOptions = {}): RoiPointGroupStats {\n const baseCount = Math.max(\n 0,\n Math.min(\n Math.floor(pointData?.count ?? 0),\n Math.floor((pointData?.positions?.length ?? 0) / 2),\n pointData?.paletteIndices?.length ?? 0,\n pointData?.fillModes instanceof Uint8Array ? pointData.fillModes.length : Number.MAX_SAFE_INTEGER\n )\n );\n\n let drawIndices: Uint32Array | null = null;\n if (pointData?.drawIndices instanceof Uint32Array) {\n const source = pointData.drawIndices;\n let valid = source.length;\n for (let i = 0; i < source.length; i += 1) {\n const idx = source[i];\n if (idx < baseCount) continue;\n valid -= 1;\n }\n if (valid === source.length) {\n drawIndices = source;\n } else if (valid > 0) {\n const filtered = new Uint32Array(valid);\n let cursor = 0;\n for (let i = 0; i < source.length; i += 1) {\n const idx = source[i];\n if (idx >= baseCount) continue;\n filtered[cursor] = idx;\n cursor += 1;\n }\n drawIndices = filtered;\n } else {\n drawIndices = new Uint32Array(0);\n }\n }\n\n const inputCount = drawIndices ? drawIndices.length : baseCount;\n\n const preparedRegions = prepareRegions(regions ?? []);\n if (!pointData || inputCount === 0 || preparedRegions.length === 0) {\n return {\n groups: [],\n inputPointCount: inputCount,\n pointsInsideAnyRegion: 0,\n unmatchedPointCount: inputCount,\n };\n }\n\n const regionClassCounters = new Map<number, Map<number, number>>();\n const regionTotalCounters = new Map<number, number>();\n const preparedRegionIndex = buildPreparedRegionGridIndex(preparedRegions);\n let insideCount = 0;\n\n for (let i = 0; i < inputCount; i += 1) {\n const pointIndex = drawIndices ? drawIndices[i] : i;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n let bestRegion: PreparedRegion | null = null;\n const candidateRegionIndices = getCandidateRegionIndices(preparedRegionIndex, x, y);\n if (candidateRegionIndices.length === 0) continue;\n\n for (const regionArrayIndex of candidateRegionIndices) {\n const region = preparedRegions[regionArrayIndex];\n let inside = false;\n for (const polygon of region.polygons) {\n if (!pointInPreparedPolygon(x, y, polygon)) continue;\n inside = true;\n break;\n }\n if (!inside) continue;\n if (!bestRegion || region.area < bestRegion.area) {\n bestRegion = region;\n }\n }\n\n if (!bestRegion) continue;\n insideCount += 1;\n\n const paletteIndex = pointData.paletteIndices[pointIndex] ?? 0;\n const regionClassMap = regionClassCounters.get(bestRegion.regionIndex) ?? new Map<number, number>();\n regionClassMap.set(paletteIndex, (regionClassMap.get(paletteIndex) ?? 0) + 1);\n regionClassCounters.set(bestRegion.regionIndex, regionClassMap);\n regionTotalCounters.set(bestRegion.regionIndex, (regionTotalCounters.get(bestRegion.regionIndex) ?? 0) + 1);\n }\n\n const includeEmptyRegions = options.includeEmptyRegions ?? false;\n const groups: RoiPointGroup[] = [];\n for (const region of preparedRegions) {\n const totalCount = regionTotalCounters.get(region.regionIndex) ?? 0;\n if (!includeEmptyRegions && totalCount <= 0) continue;\n const classMap = regionClassCounters.get(region.regionIndex) ?? new Map();\n const classCounts: RoiClassCount[] = Array.from(classMap.entries())\n .map(([paletteIndex, count]) => ({\n classId: resolveClassId(paletteIndex, options.paletteIndexToClassId),\n paletteIndex,\n count,\n }))\n .sort((a, b) => b.count - a.count || a.paletteIndex - b.paletteIndex);\n\n groups.push({\n regionId: region.regionId,\n regionIndex: region.regionIndex,\n totalCount,\n classCounts,\n });\n }\n\n return {\n groups,\n inputPointCount: inputCount,\n pointsInsideAnyRegion: insideCount,\n unmatchedPointCount: Math.max(0, inputCount - insideCount),\n };\n}\n","import type { WsiCoordinate, WsiMultiPolygonCoordinates, WsiPolygonCoordinates } from \"./types\";\n\nexport interface ParsedWktPolygon {\n type: \"Polygon\";\n coordinates: WsiPolygonCoordinates;\n}\n\nexport interface ParsedWktMultiPolygon {\n type: \"MultiPolygon\";\n coordinates: WsiMultiPolygonCoordinates;\n}\n\nexport type ParsedWktGeometry = ParsedWktPolygon | ParsedWktMultiPolygon;\n\nfunction stripSridPrefix(value: string): string {\n return value.replace(/^\\s*SRID\\s*=\\s*\\d+\\s*;\\s*/i, \"\");\n}\n\nfunction isWordChar(ch: string): boolean {\n return (ch >= \"A\" && ch <= \"Z\") || (ch >= \"a\" && ch <= \"z\");\n}\n\nfunction isDigitChar(ch: string): boolean {\n return ch >= \"0\" && ch <= \"9\";\n}\n\nfunction isNumberStartChar(ch: string): boolean {\n return ch === \"+\" || ch === \"-\" || ch === \".\" || isDigitChar(ch);\n}\n\nclass WktParser {\n private readonly text: string;\n\n private index = 0;\n\n constructor(rawInput: string) {\n this.text = stripSridPrefix(rawInput.trim());\n }\n\n parse(): ParsedWktGeometry | null {\n if (!this.text) return null;\n\n const geometryType = this.readWord();\n if (!geometryType) return null;\n\n const geometryTypeUpper = geometryType.toUpperCase();\n if (geometryTypeUpper !== \"POLYGON\" && geometryTypeUpper !== \"MULTIPOLYGON\") {\n return null;\n }\n\n this.skipWhitespace();\n const maybeDimension = this.peekWord();\n if (maybeDimension) {\n const dimUpper = maybeDimension.toUpperCase();\n if (dimUpper === \"Z\" || dimUpper === \"M\" || dimUpper === \"ZM\") {\n this.readWord();\n this.skipWhitespace();\n }\n }\n\n if (this.consumeWordIf(\"EMPTY\")) {\n this.skipWhitespace();\n if (!this.isEof()) return null;\n if (geometryTypeUpper === \"POLYGON\") {\n return { type: \"Polygon\", coordinates: [] };\n }\n return { type: \"MultiPolygon\", coordinates: [] };\n }\n\n let nested: unknown;\n try {\n nested = this.parseNestedList();\n } catch {\n return null;\n }\n\n this.skipWhitespace();\n if (!this.isEof()) return null;\n\n if (geometryTypeUpper === \"POLYGON\") {\n const polygon = toPolygonCoordinates(nested);\n if (!polygon) return null;\n return {\n type: \"Polygon\",\n coordinates: polygon,\n };\n }\n\n const multipolygon = toMultiPolygonCoordinates(nested);\n if (!multipolygon) return null;\n return {\n type: \"MultiPolygon\",\n coordinates: multipolygon,\n };\n }\n\n private isEof(): boolean {\n return this.index >= this.text.length;\n }\n\n private currentChar(): string {\n return this.text[this.index] ?? \"\";\n }\n\n private skipWhitespace(): void {\n while (!this.isEof() && /\\s/.test(this.currentChar())) {\n this.index += 1;\n }\n }\n\n private readWord(): string | null {\n this.skipWhitespace();\n if (this.isEof()) return null;\n\n const start = this.index;\n while (!this.isEof() && isWordChar(this.currentChar())) {\n this.index += 1;\n }\n if (this.index === start) return null;\n return this.text.slice(start, this.index);\n }\n\n private peekWord(): string | null {\n const saved = this.index;\n const word = this.readWord();\n this.index = saved;\n return word;\n }\n\n private consumeWordIf(target: string): boolean {\n const saved = this.index;\n const word = this.readWord();\n if (!word || word.toUpperCase() !== target.toUpperCase()) {\n this.index = saved;\n return false;\n }\n return true;\n }\n\n private parseNestedList(): unknown[] {\n this.skipWhitespace();\n if (this.currentChar() !== \"(\") {\n throw new Error(\"Expected '('\");\n }\n this.index += 1;\n\n const values: unknown[] = [];\n while (true) {\n this.skipWhitespace();\n if (this.currentChar() === \"(\") {\n values.push(this.parseNestedList());\n } else {\n values.push(this.parseCoordinateTuple());\n }\n\n this.skipWhitespace();\n const ch = this.currentChar();\n if (ch === \",\") {\n this.index += 1;\n continue;\n }\n if (ch === \")\") {\n this.index += 1;\n break;\n }\n throw new Error(\"Expected ',' or ')'\");\n }\n\n return values;\n }\n\n private parseCoordinateTuple(): WsiCoordinate {\n this.skipWhitespace();\n const values: number[] = [];\n while (true) {\n this.skipWhitespace();\n const ch = this.currentChar();\n if (!ch || !isNumberStartChar(ch)) break;\n const num = this.readNumber();\n if (num === null) break;\n values.push(num);\n this.skipWhitespace();\n const next = this.currentChar();\n if (!next || next === \",\" || next === \")\") break;\n if (!isNumberStartChar(next)) {\n throw new Error(\"Invalid coordinate\");\n }\n }\n\n if (values.length < 2) {\n throw new Error(\"Coordinate requires at least x y\");\n }\n return [values[0], values[1]];\n }\n\n private readNumber(): number | null {\n this.skipWhitespace();\n if (this.isEof()) return null;\n const chunk = this.text.slice(this.index);\n const match = chunk.match(/^[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/);\n if (!match) return null;\n const value = Number(match[0]);\n if (!Number.isFinite(value)) return null;\n this.index += match[0].length;\n return value;\n }\n}\n\nfunction isCoordinate(value: unknown): value is WsiCoordinate {\n return (\n Array.isArray(value) &&\n value.length >= 2 &&\n typeof value[0] === \"number\" &&\n Number.isFinite(value[0]) &&\n typeof value[1] === \"number\" &&\n Number.isFinite(value[1])\n );\n}\n\nfunction toPolygonCoordinates(value: unknown): WsiPolygonCoordinates | null {\n if (!Array.isArray(value)) return null;\n const polygon: WsiPolygonCoordinates = [];\n for (const ringValue of value) {\n if (!Array.isArray(ringValue)) return null;\n const ring: WsiCoordinate[] = [];\n for (const coordValue of ringValue) {\n if (!isCoordinate(coordValue)) return null;\n ring.push([coordValue[0], coordValue[1]]);\n }\n polygon.push(ring);\n }\n return polygon;\n}\n\nfunction toMultiPolygonCoordinates(value: unknown): WsiMultiPolygonCoordinates | null {\n if (!Array.isArray(value)) return null;\n const multipolygon: WsiMultiPolygonCoordinates = [];\n for (const polygonValue of value) {\n const polygon = toPolygonCoordinates(polygonValue);\n if (!polygon) return null;\n multipolygon.push(polygon);\n }\n return multipolygon;\n}\n\nexport function parseWkt(wkt: string): ParsedWktGeometry | null {\n if (typeof wkt !== \"string\") return null;\n return new WktParser(wkt).parse();\n}\n\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","options","context","toRadians","deg","OrthoCamera","__publicField","width","height","next","zoom","centerX","centerY","screenX","screenY","rotationDeg","dx","dy","rad","cos","sin","worldX","worldY","rx","ry","w","h","viewWidth","viewHeight","sx","sy","tx","ty","ax","bx","ay","by","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","f","e","d","n","u","l","i","o","s","c","m","_","z","k","g","a","y","x","p","epsilon","splitter","resulterrbound","sum","elen","flen","Q","Qnew","hh","bvirt","enow","fnow","eindex","findex","hindex","estimate","vec","ccwerrboundA","ccwerrboundB","ccwerrboundC","B","C1","C2","D","orient2dadapt","cx","cy","detsum","acxtail","acytail","bcxtail","bcytail","ahi","alo","bhi","blo","_i","_j","_0","s1","s0","t1","t0","u3","acx","bcx","acy","bcy","det","errbound","C1len","C2len","Dlen","orient2d","detleft","detright","isInBbox","bbox","point","getBboxOverlap","b1","b2","lowerX","upperX","lowerY","upperY","EPSILON_SQ","cmp","b","ab","PtRounder","CoordRounder","SplayTree","coord","node","prevNode","nextNode","rounder","crossProduct","dotProduct","compareVectorAngles","basePt","endPt1","endPt2","res","length","v","sineOfAngle","pShared","pBase","pAngle","vBase","vAngle","cosineOfAngle","horizontalIntersection","pt","verticalIntersection","intersection$1","pt1","v1","pt2","v2","kross","ve","d1","d2","x1","x2","y1","y2","SweepEvent","ptCmp","Segment","aPt","bPt","isLeft","other","otherEvents","iMax","evt","numEvents","evt1","j","evt2","events","baseEvent","cache","fillCache","linkedEvent","nextEvent","asine","acosine","bsine","bcosine","segmentId","alx","blx","arx","brx","aly","bly","ary","bry","aCmpBLeft","bCmpARight","bCmpALeft","aCmpBRight","leftSE","rightSE","rings","windings","ring","leftPt","rightPt","winding","cmpPts","newRightSE","lPt","rPt","yDist","xFromYDist","xDist","yFromXDist","tBbox","oBbox","bboxOverlap","tlp","trp","olp","orp","touchesOtherLSE","touchesThisLSE","touchesOtherRSE","touchesThisRSE","newEvents","alreadyLinked","newLeftSE","oldRightSE","newSeg","tmpEvt","consumer","consumee","tmp","index","seg","beforeState","ringsAfter","windingsAfter","mpsAfter","polysAfter","polysExclude","poly","mp","mpsBefore","operation","noBefores","noAfters","least","most","diff","isJustSubject","mps","RingIn","geomRing","isExterior","firstPoint","prevPoint","sweepEvents","segment","PolyIn","geomPoly","multiPoly","ringSweepEvents","jMax","MultiPolyIn","geom","isSubject","polySweepEvents","RingOut","allSegments","ringsOut","prevEvent","event","startingPoint","intersectionLEs","availableLEs","firstPt","lastPt","indexLE","intersectionLE","ringEvents","comparator","prevPt","points","nextPt","step","iStart","iEnd","orderedPoints","enclosing","leftMostEvt","prevSeg","prevPrevSeg","PolyOut","exteriorRing","ringGeom","MultiPolyOut","polyGeom","polys","enclosingRing","SweepLine","queue","nextSeg","prevMySplitter","prevInter","newEventsFromSplit","nextMySplitter","nextInter","mySplitter","inter","POLYGON_CLIPPING_MAX_QUEUE_SIZE","POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS","Operation","moreGeoms","multipolys","subject","mpA","sweepLine","prevQueueSize","union","_len","_key","intersection","_len2","_key2","xor","_len3","_key3","difference","subjectGeom","_len4","clippingGeoms","_key4","toRoiGeometry","coords","isLinearRing","isPolygonRings","isMultiPolygon","isFiniteNumber","value","isCoordinatePair","polygon","closeRoiRing","coordinates","out","prev","first","last","polygonSignedArea","normalizePolygonRings","normalized","closed","outerIndex","outerArea","area","normalizeRoiGeometry","geometry","second","pointInRing","inside","xi","yi","xj","yj","prepareRoiPolygons","geometries","prepared","multipolygon","outer","minX","minY","maxX","maxY","pointInPreparedPolygon","hole","pointInAnyPreparedPolygon","polygons","DEFAULT_POINT_COLOR","clamp","min","max","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcViewingMagnification","viewZoom","calcScaleLength","unit","nowMs","sanitizePointCount","pointData","fillModesLength","isSameViewState","toBearerToken","trimmed","token","hexToRgba","hex","match","parseHexColorToRgba","fallback","input","hexMatch","ch","resolvePaletteClassKey","item","classId","buildClassPalette","classes","palette","classToPaletteIndex","classKey","colors","ROUND_PRECISIONS","DEFAULT_CIRCLE_SIDES","DEFAULT_SIMPLIFY_FACTOR","DEFAULT_SMOOTHING_PASSES","MAX_SMOOTHING_PASSES","MIN_RADIUS","MIN_TUNNEL_LENGTH_FACTOR","sanitizePath","createCircleRing","center","radius","sides","t","closeRing","createTunnelRing","start","end","minLength","ux","perpX","perpY","r","createBoundsFallback","pad","clampRingToBounds","bounds","round","precision","sanitizeRing","sanitized","sanitizePolygon","tryUnionWithPrecision","current","polygonClipping","unionPolygons","result","toBrushRing","selectLargestOuterRing","multiPolygon","best","bestArea","removeCollinearVertices","curr","cross","pointLineDistanceSquared","abx","aby","len2","simplifyRdp","tolerance","keep","tolerance2","stack","maxDist2","split","dist2","simplifyClosedRing","open","simplified","smoothClosedRingChaikin","iterations","pass","buildBrushStrokePolygon","path","circleSides","minTunnelLength","circle","tunnel","unioned","unionRing","smoothingPasses","optimized","readDevicePixelRatio","raw","observeDevicePixelRatioChanges","onChange","active","lastDpr","mediaQuery","removeMediaQueryListener","unbindMediaQuery","bindMediaQuery","handleMediaQueryChange","emitIfChanged","trigger","nextDpr","previousDpr","handleWindowResize","handleVisualViewportResize","EMPTY_DASH","EMPTY_REGIONS","DEFAULT_REGION_STROKE_STYLE","DEFAULT_PATCH_STROKE_STYLE","REGION_INTERACTION_SHADOW_COLOR","REGION_INTERACTION_SHADOW_WIDTH","DEFAULT_REGION_LABEL_STYLE","DEFAULT_DRAW_AREA_TOOLTIP_STYLE","DEFAULT_DRAW_AREA_TOOLTIP_OFFSET","REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX","REGION_LABEL_AUTO_LIFT_MAX_EPSILON","DEFAULT_DRAW_PREVIEW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","MICRONS_PER_MM","DEFAULT_STAMP_RECTANGLE_AREA_MM2","DEFAULT_STAMP_CIRCLE_AREA_MM2","DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE","LEGACY_HPF_CIRCLE_AREA_MM2","WHEEL_ZOOM_IN_FACTOR","WHEEL_ZOOM_OUT_FACTOR","DEFAULT_BRUSH_RADIUS","DEFAULT_BRUSH_FILL_COLOR","DEFAULT_BRUSH_FILL_OPACITY","DEFAULT_BRUSH_CURSOR_COLOR","DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR","DEFAULT_BRUSH_CURSOR_LINE_WIDTH","DEFAULT_BRUSH_CURSOR_DASH","DEFAULT_BRUSH_EDGE_DETAIL","MIN_BRUSH_EDGE_DETAIL","MAX_BRUSH_EDGE_DETAIL","DEFAULT_BRUSH_EDGE_SMOOTHING","MIN_BRUSH_EDGE_SMOOTHING","MAX_BRUSH_EDGE_SMOOTHING","BRUSH_SCREEN_STEP","clampWorld","imageWidth","imageHeight","toDrawCoordinate","toCoord","polygonArea","computeBounds","tracePath","ctx","close","drawPath","strokeStyle","fill","fillColor","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","isCoordinateRing","collectOverlayRings","normalizeOverlayRings","sourceRings","clampPositiveOrFallback","clampUnitOpacity","drawRoundedRect","isNestedRingCoordinates","createRectangle","projection","startScreen","endScreen","screenCorners","worldCorners","corner","world","createCircle","normalizeDrawRegionPolygons","normalizedOuter","holes","sanitizeBrushLineDash","resolveBrushEdgeDetail","resolveBrushEdgeSmoothing","resolveBrushOptions","cursorLineWidth","edgeDetail","edgeSmoothing","drawBrushStrokePreview","session","resolvedBrushOptions","screenPoints","radiusPx","drawBrushCursor","projector","cursor","screen","LABEL_MEASURE_FALLBACK_EM","LABEL_MEASURE_CACHE_LIMIT","TOP_ANCHOR_Y_TOLERANCE","sharedLabelMeasureContext","labelTextWidthCache","getLabelMeasureContext","measureLabelTextWidth","label","labelStyle","key","cached","measured","getTopAnchor","anchorMode","getTopAnchorFromProjectedPolygons","project","projectedOuter","anchor","resolveRegionLabelStyle","px","py","fs","bw","oy","br","mergeRegionLabelStyle","resolveRegionLabelAutoLiftOffsetPx","enabled","zoomRange","liftCapZoom","minZoom","maxZoom","cap","tol","resolveDrawAreaTooltipStyle","fontSize","borderRadius","paddingX","paddingY","resolveTooltipCursorOffset","defaultDrawAreaTooltipFormatter","areaMm2","resolveDrawAreaTooltipOptions","format","cursorOffset","drawRegionLabel","text","canvasWidth","canvasHeight","clampToViewport","boxWidth","boxHeight","rawX","rawY","left","top","drawAreaTooltipBox","cursorScreen","drawInvertedFillMask","outerRing","holeRings","drawOverlayShapes","params","overlayShapes","imageOuterRing","worldToScreenPoints","baseStrokeStyle","onInvertedFillDebug","debugOverlay","shape","renderRings","closedRings","isStampTool","tool","resolveStampOptions","mm2ToUm2","createSquareFromCenter","halfLength","screenCenter","screenEdge","screenHL","createCircleFromCenter","buildStampCoords","stampTool","resolvedStampOptions","micronsToWorldPixels","getRectangleProjection","areaUm2","resolveRegionInteractionShadowStyle","resolveDrawPreviewFillColor","isValidPolygon","DrawLayer","stampOptions","brushOptions","projectorRef","onBrushTap","onDrawComplete","onPatchComplete","viewStateSignal","persistedRegions","patchRegions","persistedPolygons","drawFillColor","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","patchStrokeStyle","resolveRegionStrokeStyle","resolveRegionLabelStyleProp","hoveredRegionId","activeRegionId","regionLabelStyle","drawAreaTooltip","autoLiftRegionLabelAtMaxZoom","regionLabelAnchor","clampRegionLabelToViewport","regionLabelAutoLiftOffsetPx","invalidateRef","className","canvasRef","useRef","drawPendingRef","overlayDebugSnapshotRef","lastToolRef","sessionRef","mergedPersistedRegions","useMemo","mergedPatchRegions","preparedPersistedRegions","region","preparedPatchRegions","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedPatchStrokeStyle","resolvedDrawPreviewFillColor","resolvedLabelStyle","resolvedDrawAreaTooltipOptions","mergedStyle","resizeCanvas","useCallback","localScreenToWorld","lengthUm","mppValue","imageZoomValue","viewZoomRaw","continuousZoom","umPerScreenPixel","buildStampCoordsCallback","buildPreviewCoords","drawOverlay","entry","regionIndex","regionKey","state","resolved","interactionShadowStyle","screenOuter","screenHole","info","debugKey","debugSignature","preview","line","labelAutoLiftOffset","anchorScreen","dynamicLabelStyle","areaCoords","areaPx","requestDraw","resetSession","preserveCursor","toWorld","toLocalScreen","finishSession","tapPoint","screenPath","simplifyTolerance","screenPolygon","worldPolygon","handleStampAt","intent","appendBrushPoint","minScreenStep","minScreenStep2","prevScreen","handlePointerDown","handlePointerMove","minWorldStep","minWorldStep2","handlePointerUp","handlePointerLeave","changed","useEffect","observer","onKeyDown","jsx","hasWheelZoom","hasLegacyZoom","ViewerContext","createContext","ViewerContextProvider","useViewerContext","useContext","DrawingLayer","areaTooltip","onComplete","rendererRef","rendererSerial","setInteractionLock","normalizeExtent","intersects","GridSpatialIndex","nodeSize","finite","items","spanX","spanY","bucketCount","minCellX","maxCellX","minCellY","maxCellY","extent","query","serial","bucket","itemIndex","ratio","createSpatialIndex","ACCUM_VERTEX_SHADER","ACCUM_FRAGMENT_SHADER","COLOR_VERTEX_SHADER","COLOR_FRAGMENT_SHADER","HeatmapWebGLRenderer","supportsFloatAccum","accumVao","colorVao","pointBuffer","accumTexture","gradientTexture","framebuffer","accumResolution","accumPointSize","accumCoreRatio","accumPointAlpha","colorAccumTexture","colorGradientTexture","colorOpacity","colorCutoff","colorGain","colorGamma","colorBias","colorStretch","colorResolution","centerLocation","weightLocation","positionLocation","safeWidth","safeHeight","framebufferStatus","nextKey","gradient","stops","pixels","positions","weights","count","requiredFloats","bytes","interleaved","sourceOffset","targetOffset","HEATMAP_DRAW_ID","DEFAULT_GRADIENT","DEFAULT_RADIUS","DEFAULT_BLUR","DEFAULT_OPACITY","DEFAULT_MAX_RENDERED_POINTS","DEFAULT_SCALE_MODE","DEFAULT_DENSITY_CONTRAST","MIN_RASTER_SIZE","MAX_RASTER_SIZE","BASE_RADIUS_UNIT_PX","BASE_BLUR_UNIT_PX","MIN_VISIBLE_BUDGET","PYRAMID_SCALE_STEP","NORMALIZATION_SAMPLE_SIZE","NORMALIZATION_PERCENTILE","MAX_DENSITY_CONTRAST","resolveContinuousZoom","rawZoom","resolveRawZoomFromContinuousZoom","applyZoomThreshold","zoomThreshold","shiftedZoom","resolveThresholdLevelBias","resolveDensityWeightExponent","densityContrast","contrast","resolveCellSupportFactor","cellCount","resolveDensityCutoff","resolveDensityGain","resolveDensityGamma","resolveDensityBias","resolveDensityStretch","contrastT","zoomStart","zoomEnd","zoomT","baseStretch","zoomStretch","resolveNormalizedDensityWeight","weight","normalizationMaxWeight","safeWeight","safeMaxWeight","resolveNormalizationPercentile","resolveNormalizationUpperWeight","cells","sampleCount","sampledWeights","maxWeight","sampleIndex","cellIndex","right","percentile","percentileIndex","percentileWeight","resolveZoomVisibilityStrength","fadeStart","fadeEnd","baseStrength","resolveSampleWeightBoost","sampleProbability","effectiveStride","resolveLowResScale","totalPointCount","longestSide","deviceScale","lowZoomBoost","targetMaxSize","minScale","maxScale","buildViewportFrame","heatmapScale","rasterWidth","rasterHeight","rasterScaleX","rasterScaleY","effectiveScale","kernelRadiusPx","blurRadiusPx","outerWorldRadius","desiredCellWorldSize","resolvePointCount","data","maxByPosition","maxByWeight","hashCoordinate","seed","hashIntPair","hash","hashToUnitFloat","buildClipKey","polygonIndex","pointIndex","holeIndex","isSameHeatmapInput","clipKey","buildSourceData","clipPolygons","pointCount","xs","ys","ws","acceptedCount","rawWeight","pointIndexItems","maxDimension","cellSizes","cellSize","guard","collectVisiblePointIndices","sourceData","viewBounds","hits","visible","hit","resolveSampleProbability","visiblePointCount","maxRenderedPoints","budget","resolveSampleStride","shouldKeepSample","sampleHash","resolvePointAlpha","binCount","kernelOuterRadiusPx","rasterArea","kernelArea","coverage","smoothHeatmapValue","previousValue","nextValue","riseFactor","fallFactor","factor","getWebglRenderer","runtime","reason","projectClipRing","renderer","projected","applyClipPath","ensureSourceData","buildFixedState","logicalWidth","logicalHeight","blur","fixedZoom","currentRawZoom","referenceZoom","referenceRawZoom","frame","visiblePointIndices","sampleStride","drawHeatmapWebglPoints","pointAlpha","opacity","backgroundColor","webgl","targetCapacity","outerRadiusPx","sampleWeightBoost","drawCount","visibleIndex","rasterX","rasterY","offset","drawHeatmap","zoomVisibilityStrength","targetPointAlpha","renderedPointCount","fixedState","HeatmapLayer","scaleMode","clipToRegions","zIndex","onStats","registerDrawCallback","unregisterDrawCallback","requestOverlayRedraw","runtimeRef","stateRef","startedAt","stats","__heatmapLayerInternals","OVERLAY_DRAW_ID","OverlayLayer","shapes","drawRef","w2s","src","normalizeImageClasses","trimTrailingSlash","ensureLeadingSlash","joinImsTileRoot","tileBaseUrl","parsed","origin","normalizeImageInfo","ims","isIms","tileSize","maxTierZoom","tilePath","normalizedPath","imsTileRoot","tileUrlBuilder","tier","toTileUrl","shouldAttachAuthHeaderToOverviewTile","url","authToken","host","DEFAULT_OVERVIEW_MAP_OPTIONS","strokeSymmetricDashedPolygon","dashLen","gapLen","len","from","to","sideLen","fittedLen","scale","adjDash","adjGap","isSamePoint","compactPolygonPoints","compact","intersectAtX","intersectAtY","clipPolygonToRect","output","edges","edge","prevInside","currInside","toPositiveNumber","toFiniteRotation","getRotatedImageMetrics","safeRotation","translateX","translateY","corners","getOverviewImageLayout","metrics","imageAspect","boxAspect","contentWidth","contentHeight","worldToOverviewPoint","layout","contentX","contentY","rotatedX","rotatedY","overviewPointToWorld","pointX","pointY","boundsToCorners","isFiniteBounds","DEFAULT_CLOSE_BUTTON_STYLE","OverviewMap","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderWidth","maxThumbnailTiles","borderColor","viewportBorderColor","viewportBorderStyle","viewportFillColor","interactive","showThumbnail","position","onClose","closeIcon","closeButtonStyle","pos","draw","cssW","cssH","pixelW","pixelH","initialRotationDeg","cw","safeCorners","safeBounds","isDash","clippedCorners","fallbackCorners","toWorldFromClient","clientX","clientY","scaleX","scaleY","cxPx","cyPx","cwPx","chPx","nx","ny","recenterTo","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","previewScale","requests","bottom","useAuthHeader","results","dw","dh","rafId","tick","jsxs","PATCH_DRAW_ID","PatchLayer","regions","safeRegions","prep","filterPointDataByPolygons","empty","fillModes","pointIds","nextPositions","nextClasses","nextFillModes","nextIds","filterPointIndicesByPolygons","contextPromise","BBOX_PREFILTER_SHADER","hasWebGpu","nav","getNavigatorGpu","gpu","candidate","GPU_SHADER_STAGE_COMPUTE","GPU_BUFFER_USAGE_STORAGE","GPU_BUFFER_USAGE_COPY_DST","GPU_BUFFER_USAGE_COPY_SRC","GPU_BUFFER_USAGE_UNIFORM","GPU_BUFFER_USAGE_MAP_READ","GPU_MAP_MODE_READ","getWebGpuCapabilities","navGpu","adapter","getContext","device","bindGroupLayout","pipeline","align","prefilterPointsByBoundsWebGpu","boundsCount","safePointCount","positionBytes","boundsBytes","outputBytes","limit","positionsBuffer","boundsBuffer","outputBuffer","uniformBuffer","readBuffer","readBufferMapped","bindGroup","commandEncoder","mapped","filterPointDataByPolygonsHybrid","bridgeToDraw","safeCount","pointFillModes","bboxFlat","candidateMask","usedWebGpu","candidateCount","candidateIndices","candidateCursor","drawIndices","visibleCount","compactData","WorkerClient","createWorker","handlers","message","pending","worker","id","workerClient","msg","indices","paletteIndices","ids","terminateRoiClipWorker","filterPointDataByPolygonsInWorker","positionsCopy","classesCopy","fillModesCopy","idsCopy","resolve","reject","startMs","requestTicket","transfer","canceled","filterPointIndicesByPolygonsInWorker","EMPTY_CLIPPED_POINTS","usePointClipping","clipPointsToRois","clipMode","effectiveRoiRegions","onClipStats","clipRunIdRef","renderPointData","setRenderPointData","useState","runId","applyResult","inputCount","outputCount","MIN_POINT_HIT_GRID_SIZE","MAX_POINT_HIT_GRID_SIZE","POINT_HIT_GRID_DENSITY_SCALE","HASH_EMPTY","cellHash","cellX","cellY","mask","resolveGridSize","sourceWidth","sourceHeight","sanitizeDrawIndices","allValid","filtered","buildPointHitIndex","maxCountByPositions","invCellSize","pointCellX","pointCellY","validCount","pi","estimatedCells","hashCapacity","hashMask","tempHashKeys","tempHashCounts","pointCellSlot","slot","kx","oldCap","newKeys","newCounts","ocx","ocy","ns","cellKeys","cellOffsets","cellLengths","slotToCellIndex","cellIdx","pointIndices","fillCursor","ci","srcIdx","finalCap","finalMask","hashTable","lookupCellIndex","buildFromResponse","terminatePointHitIndexWorker","buildSyncFallback","buildPointSpatialIndexAsync","drawIndicesCopy","POINT_HIT_RADIUS_SCALE","MIN_POINT_HIT_RADIUS_PX","usePointHitTest","onPointHover","onPointClick","getCellByCoordinatesRef","drawTool","pointLayerId","shouldEnablePointHitTest","pointSpatialIndex","setPointSpatialIndex","hoveredPointIndexRef","hoveredPointIdRef","nextIndex","getCellByCoordinates","coordinate","pointSizePx","hitRadiusWorld","idxBuf","posBuf","baseCellX","baseCellY","cellRadius","nearestIndex","nearestDist2","nearestX","nearestY","off","pointId","emitPointHover","nextId","emitPointClick","button","hoveredPointIndex","nextPointLayerId","PointLayer","forwardRef","sizeByZoom","sizeByMagnification","weightByMagnification","strokeScale","innerFillOpacity","innerFillColor","clipEnabled","onHover","onClick","dashed","ref","layerIdRef","useImperativeHandle","layerId","REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS","smoothstep01","useRegionLabelAutoLift","drawInvalidateRef","setRegionLabelAutoLiftOffsetPx","regionLabelAutoLiftOffsetRef","regionLabelAutoLiftAnimationRef","applyRegionLabelAutoLiftOffset","clamped","cancelRegionLabelAutoLiftAnimation","animation","animateRegionLabelAutoLiftTo","target","clampedTarget","timestamp","elapsed","rawT","eased","syncRegionLabelAutoLiftTarget","REGION_CONTOUR_HIT_DISTANCE_PX","resolveRegionId","pointSegmentDistanceSq","lengthSq","isPointNearRing","maxDistanceSq","isPointNearPolygonContour","maxDistance","isScreenPointInsideLabel","screenCoord","prepareRegionHits","pickPreparedRegionAt","labelStyleResolver","labelAutoLiftOffsetPx","contourHitDistance","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","nextRegionLayerInstanceId","resolveRegionInteractionShadow","RegionLayer","strokeStyleProp","hoverStrokeStyleProp","activeStrokeStyleProp","resolveStrokeStyleProp","labelStyleProp","labelAnchor","autoLiftLabelAtMaxZoom","clampLabelToViewport","controlledHoveredRegionId","controlledActiveRegionId","onActiveChange","containerRef","registerViewStateListener","screenToWorld","worldToScreen","isInteractionLocked","safePolygons","effectiveRegions","uncontrolledHoveredRegionId","setUncontrolledHoveredRegionId","uncontrolledActiveRegionId","setUncontrolledActiveRegionId","isHoverControlled","isControlled","hoveredRegionIdRef","drawCallbackIdRef","labelDrawCallbackIdRef","instanceId","commitActive","staticLabelStyle","preparedRegions","preparedRegionHits","currentHover","regionDrawRef","drawRegions","_ctx","hovered","hover","activeS","resolver","shadow","drawId","labelDrawRef","drawLabels","labelS","autoLift","clampVp","autoLiftPx","rRef","pointerHitRef","container","currentLabelAnchor","hoverCb","worldCoord","hitResult","prevId","handleClick","clickCb","commit","TileViewerCanvas","shouldAttachAuthHeader","TileScheduler","nextVisibleKeys","inflight","queued","visibleKeys","nextQueue","earliestReadyAt","delay","now","controller","inflightEntry","nextAttempt","retryDelay","existing","attempt","exp","jitter","addRendererCanvasEventListeners","removeRendererCanvasEventListeners","resizeCanvasViewport","camera","DEFAULT_ROTATION_DRAG_SENSITIVITY","MIN_POINT_SIZE_PX","MAX_POINT_SIZE_PX","DEFAULT_POINT_SIZE_STOPS","MIN_STROKE_SCALE","MAX_STROKE_SCALE","MIN_POINT_OPACITY","MAX_POINT_OPACITY","MIN_POINT_INNER_FILL_OPACITY","MAX_POINT_INNER_FILL_OPACITY","MIN_IMAGE_COLOR_INPUT","MAX_IMAGE_COLOR_INPUT","MAX_VIEW_TRANSITION_DURATION_MS","DEFAULT_POINT_INNER_FILL_COLOR","isSameArrayView","clonePointSizeStops","stop","clonePointSizeMagnificationStops","clonePointWeightMagnificationStops","normalizePointSizeStops","pointSizeByZoom","zoomKey","rawSize","size","normalizePointSizeMagnificationStops","pointSizeByMagnification","magnificationKey","magnification","normalizePointWeightMagnificationStops","pointWeightByMagnification","normalizeStrokeScale","arePointSizeStopsEqual","arePointSizeMagnificationStopsEqual","arePointWeightMagnificationStopsEqual","resolvePointSizeByZoomStops","span","slope","resolvePointSizeByMagnificationStops","resolvePointWeightByMagnificationStops","normalizePointOpacity","normalizePointLineDash","normalizePointInnerFillOpacity","normalizePointInnerFillColor","rgba","normalizeImageColorInput","toNormalizedImageColorSettings","settings","brightnessInput","contrastInput","saturationInput","linearEasing","normalizeViewTransitionDuration","duration","normalizeZoomOverride","normalizeTransitionEasing","easing","getPointerAngleRad","cancelDrag","config","cancelViewAnimation","wantsRotate","clampViewState","emitViewState","requestRender","nextAngle","prevAngle","rawDelta","delta","sensitivityScale","worldDx","worldDy","handleWheel","onZoomBy","applyWheelZoomDelta","SNAP_DELTA_THRESHOLD","deltaY","applyWheelSnapDelta","snapState","onSnapZoom","inputDirection","direction","handleWheelSnap","handleDoubleClick","handleContextMenu","dragging","getViewBounds","extentX","extentY","marginX","marginY","halfW","halfH","minCenterX","maxCenterX","minCenterY","maxCenterY","nextCenterX","nextCenterY","selectTier","rawTier","intersectsBounds","getVisibleTilesForTier","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","getVisibleTiles","onPointerDownWithLock","onPointerMoveWithLock","onPointerUpWithLock","onDoubleClickWithLock","onContextMenuWithLock","cancelInteractionDrag","createRendererInputHandlers","trimTileCache","maxCacheTiles","targetSize","oldestKey","oldestValue","createTextureFromBitmap","handleTileLoaded","frameSerial","destroyed","contextLost","deleteCachedTextures","handleContextLost","tileScheduler","onContextLost","destroyRenderer","pointProgram","maxExclusive","idx","getZeroFillModes","zeroFillModes","setPointPalette","nextPalette","paletteSize","setPointData","hasFillModes","nextPaletteIndices","hasDrawIndices","nextDrawIndices","prevHasFillModes","geometryChanged","drawIndicesChanged","nextRuntime","currentPointData","renderFrame","tileProgram","imageColorSettings","pointLayers","fallbackTiles","renderedTiles","missingTiles","tilesToSchedule","PREFETCH_DISTANCE_PENALTY","prefetchTiers","prefetchTier","prefetchCandidates","renderedPoints","pointDrawCalls","layer","initTileProgram","uCamera","uBounds","uTexture","uBrightness","uContrast","uSaturation","vbo","aUnit","aUv","initPointProgram","uPointSize","uPointCssSize","uPointOpacity","uPointStrokeScale","uPointInnerFillAlpha","uPointInnerFillColor","uPalette","uPaletteSize","uPointLineDash","posBuffer","classBuffer","fillModeBuffer","indexBuffer","paletteTexture","posLoc","classLoc","fillModeLoc","startViewAnimation","durationMs","onUpdate","resolveDefaultZoomBounds","fitZoom","resolveZoomBounds","minZoomOverride","maxZoomOverride","defaults","resolveTargetViewState","computeFitToImageTarget","viewportWidth","viewportHeight","clampedZoom","visibleWorldW","visibleWorldH","computeZoomByTarget","nextZoom","vp","computeZoomToTarget","targetZoom","SNAP_ZOOM_DURATION_MS","normalizeZoomSnaps","magnifications","maxMag","mag","resolveSnapTarget","validSnaps","fitAsMin","snap","startZoomPivotAnimation","pivotScreenX","pivotScreenY","fromState","pivotWorldX","pivotWorldY","safeTargetZoom","screenDx","screenDy","computeOffsetForZoom","finalOffset","isComplete","DEFAULT_POINT_LAYER_ID","WsiTileRenderer","cacheTileLoaded","attemptCount","inputHandlers","resolveManagedTargetViewState","clampManagedViewState","cancelManagedViewAnimation","created","pointCssSizePx","cancelAnimation","nextMinOverride","nextMaxOverride","transition","valid","setManagedPointPalette","setManagedPointData","locked","nextStops","color","cancelInputDrag","getManagedViewBounds","magnificationStops","vw","vh","fitTarget","ongoing","baseZoom","frameStartMs","getManagedVisibleTiles","getManagedVisibleTilesForTier","intersectsManagedBounds","schedulerStats","_event","EMPTY_DRAW_CALLBACKS","WsiViewer","onViewStateChange","onTileError","onContextRestored","initialRotate","fitNonce","rotationResetNonce","ctrlDragRotate","viewTransition","zoomSnaps","zoomSnapFitAsMin","panExtent","preserveDrawingBuffer","onPointerWorldMove","debugOverlayStyle","children","overlayCanvasRef","overviewInvalidateRef","drawCallbacksRef","overlayPendingRef","interactionLocksRef","viewStateListenersRef","onViewStateChangeRef","onStatsRef","onTileErrorRef","onContextLostRef","onContextRestoredRef","setRendererSerial","debugStats","setDebugStats","debugOverlayRef","mergedDebugOverlayStyle","initialRotateValue","toExternalViewState","toInternalViewState","handleRendererStats","debugOverlayText","drawOverlayFrame","entries","priority","listener","emitViewStateChange","nextInternal","listeners","snapshot","contextValue","onPointerWorldMoveRef","cb","insideImage","prepareRegions","MAX_REGION_GRID_SIZE","EMPTY_CANDIDATE_REGION_INDICES","toGridCell","gridSize","buildPreparedRegionGridIndex","estimated","cellWidth","cellHeight","buckets","regionArrayIndex","getCandidateRegionIndices","resolveClassId","paletteIndex","paletteIndexToClassId","fromArray","fromMap","computeRoiPointGroups","baseCount","regionClassCounters","regionTotalCounters","preparedRegionIndex","insideCount","bestRegion","candidateRegionIndices","regionClassMap","includeEmptyRegions","groups","totalCount","classMap","classCounts","stripSridPrefix","isWordChar","isDigitChar","isNumberStartChar","WktParser","rawInput","geometryType","geometryTypeUpper","maybeDimension","dimUpper","nested","toPolygonCoordinates","toMultiPolygonCoordinates","saved","word","values","num","isCoordinate","ringValue","coordValue","polygonValue","parseWkt","wkt"],"mappings":"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","x_google_ignoreList":[3,4,5,6]}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/core/gl-utils.ts","../src/core/ortho-camera.ts","../src/core/m1-tile-renderer.ts","../node_modules/splaytree/dist/splaytree.js","../node_modules/robust-predicates/esm/util.js","../node_modules/robust-predicates/esm/orient2d.js","../node_modules/polygon-clipping/dist/polygon-clipping.esm.js","../src/wsi/roi-geometry.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/wsi/brush-stroke.ts","../src/wsi/device-pixel-ratio.ts","../src/react/draw-layer-types.ts","../src/react/draw-layer-utils.ts","../src/react/draw-layer-brush.ts","../src/react/draw-layer-label.ts","../src/react/draw-layer-overlay.ts","../src/react/draw-layer-stamp.ts","../src/react/draw-layer.tsx","../src/react/viewer-context.ts","../src/react/drawing-layer.tsx","../src/wsi/spatial-index.ts","../src/react/heatmap-webgl.ts","../src/react/heatmap-layer.tsx","../src/react/overlay-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/patch-layer.tsx","../src/wsi/point-clip.ts","../src/wsi/webgpu.ts","../src/wsi/point-clip-hybrid.ts","../src/wsi/worker-client.ts","../src/wsi/point-clip-worker-client.ts","../src/react/use-point-clipping.ts","../src/wsi/point-hit-index-shared.ts","../src/wsi/point-hit-index-worker-client.ts","../src/react/use-point-hit-test.ts","../src/react/point-layer.tsx","../src/react/use-region-label-auto-lift.ts","../src/react/wsi-region-hit-utils.ts","../src/react/region-layer.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/tile-scheduler.ts","../src/wsi/wsi-canvas-lifecycle.ts","../src/wsi/wsi-normalize.ts","../src/wsi/wsi-interaction.ts","../src/wsi/wsi-tile-visibility.ts","../src/wsi/wsi-input-handlers.ts","../src/wsi/wsi-tile-cache.ts","../src/wsi/wsi-lifecycle-ops.ts","../src/wsi/wsi-point-data.ts","../src/wsi/wsi-render-pass.ts","../src/wsi/wsi-shaders.ts","../src/wsi/wsi-view-animation.ts","../src/wsi/wsi-view-ops.ts","../src/wsi/wsi-zoom-snap.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer.tsx","../src/wsi/roi-class-stats.ts","../src/wsi/wkt.ts"],"sourcesContent":["function compileShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new Error(\"Failed to create shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);\n if (!ok) {\n const log = gl.getShaderInfoLog(shader) ?? \"unknown shader error\";\n gl.deleteShader(shader);\n throw new Error(log);\n }\n\n return shader;\n}\n\nexport function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\n const program = gl.createProgram();\n if (!program) {\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n throw new Error(\"Failed to create program.\");\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const ok = gl.getProgramParameter(program, gl.LINK_STATUS);\n if (!ok) {\n const log = gl.getProgramInfoLog(program) ?? \"unknown link error\";\n gl.deleteProgram(program);\n throw new Error(log);\n }\n\n return program;\n}\n\nexport function requireUniformLocation(gl: WebGL2RenderingContext, program: WebGLProgram, uniformName: string): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, uniformName);\n if (!location) {\n throw new Error(`Failed to get uniform location: ${uniformName}`);\n }\n return location;\n}\n\nexport function requireWebGL2(canvas: HTMLCanvasElement, options?: { preserveDrawingBuffer?: boolean }): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: options?.preserveDrawingBuffer ?? false,\n powerPreference: \"high-performance\",\n });\n\n if (!context) {\n throw new Error(\"WebGL2 is not available.\");\n }\n\n return context;\n}\n","export interface ViewState {\n offsetX: number;\n offsetY: number;\n zoom: number;\n rotationDeg: number;\n}\n\nexport type WorldPoint = [number, number];\n\nfunction toRadians(deg: number): number {\n return (deg * Math.PI) / 180;\n}\n\nexport class OrthoCamera {\n private viewportWidth = 1;\n private viewportHeight = 1;\n\n private viewState: ViewState = {\n offsetX: 0,\n offsetY: 0,\n zoom: 1,\n rotationDeg: 0,\n };\n\n setViewport(width: number, height: number): void {\n this.viewportWidth = Math.max(1, width);\n this.viewportHeight = Math.max(1, height);\n }\n\n getViewportSize(): { width: number; height: number } {\n return {\n width: this.viewportWidth,\n height: this.viewportHeight,\n };\n }\n\n setViewState(next: Partial<ViewState>): void {\n if (next.offsetX !== undefined) {\n this.viewState.offsetX = next.offsetX;\n }\n\n if (next.offsetY !== undefined) {\n this.viewState.offsetY = next.offsetY;\n }\n\n if (next.zoom !== undefined) {\n this.viewState.zoom = Math.max(0.0001, next.zoom);\n }\n\n if (typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg)) {\n this.viewState.rotationDeg = next.rotationDeg;\n }\n }\n\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getCenter(): WorldPoint {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n return [\n this.viewState.offsetX + this.viewportWidth / (2 * zoom),\n this.viewState.offsetY + this.viewportHeight / (2 * zoom),\n ];\n }\n\n setCenter(centerX: number, centerY: number): void {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n this.viewState.offsetX = centerX - this.viewportWidth / (2 * zoom);\n this.viewState.offsetY = centerY - this.viewportHeight / (2 * zoom);\n }\n\n screenToWorld(screenX: number, screenY: number): WorldPoint {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n const [centerX, centerY] = this.getCenter();\n const rotationDeg = this.viewState.rotationDeg ?? 0;\n const dx = (screenX - this.viewportWidth * 0.5) / zoom;\n const dy = (screenY - this.viewportHeight * 0.5) / zoom;\n const rad = toRadians(rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n return [centerX + dx * cos - dy * sin, centerY + dx * sin + dy * cos];\n }\n\n worldToScreen(worldX: number, worldY: number): WorldPoint {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n const [centerX, centerY] = this.getCenter();\n const rotationDeg = this.viewState.rotationDeg ?? 0;\n const dx = worldX - centerX;\n const dy = worldY - centerY;\n const rad = toRadians(rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const rx = dx * cos + dy * sin;\n const ry = -dx * sin + dy * cos;\n return [\n this.viewportWidth * 0.5 + rx * zoom,\n this.viewportHeight * 0.5 + ry * zoom,\n ];\n }\n\n getViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n const w = this.viewportWidth;\n const h = this.viewportHeight;\n return [\n this.screenToWorld(0, 0),\n this.screenToWorld(w, 0),\n this.screenToWorld(w, h),\n this.screenToWorld(0, h),\n ];\n }\n\n getMatrix(): Float32Array {\n const zoom = Math.max(1e-6, this.viewState.zoom);\n const rotationDeg = this.viewState.rotationDeg ?? 0;\n\n if (rotationDeg === 0) {\n const viewWidth = this.viewportWidth / zoom;\n const viewHeight = this.viewportHeight / zoom;\n const sx = 2 / viewWidth;\n const sy = -2 / viewHeight;\n const tx = -1 - this.viewState.offsetX * sx;\n const ty = 1 - this.viewState.offsetY * sy;\n return new Float32Array([sx, 0, 0, 0, sy, 0, tx, ty, 1]);\n }\n\n const [centerX, centerY] = this.getCenter();\n const rad = toRadians(rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const ax = (2 * zoom * cos) / this.viewportWidth;\n const bx = (2 * zoom * sin) / this.viewportWidth;\n const ay = (2 * zoom * sin) / this.viewportHeight;\n const by = (-2 * zoom * cos) / this.viewportHeight;\n const tx = -(ax * centerX + bx * centerY);\n const ty = -(ay * centerX + by * centerY);\n return new Float32Array([ax, ay, 0, bx, by, 0, tx, ty, 1]);\n }\n}\n","import { createProgram, requireUniformLocation, requireWebGL2 } from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n id: string;\n bounds: Bounds;\n texture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n canvas: HTMLCanvasElement;\n imageWidth: number;\n imageHeight: number;\n clearColor?: [number, number, number, number];\n initialViewState?: Partial<ViewState>;\n preserveDrawingBuffer?: boolean;\n}\n\nconst VERTEX_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 aUnit;\nin vec2 aUv;\n\nuniform mat3 uCamera;\nuniform vec4 uBounds;\n\nout vec2 vUv;\n\nvoid main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n}\n`;\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nuniform sampler2D uTexture;\n\nout vec4 outColor;\n\nvoid main() {\n outColor = texture(uTexture, vUv);\n}\n`;\n\nexport class M1TileRenderer {\n private readonly canvas: HTMLCanvasElement;\n private readonly gl: WebGL2RenderingContext;\n private readonly camera = new OrthoCamera();\n private readonly imageWidth: number;\n private readonly imageHeight: number;\n private readonly clearColor: [number, number, number, number];\n private readonly program: WebGLProgram;\n private readonly vao: WebGLVertexArrayObject;\n private readonly quadBuffer: WebGLBuffer;\n private readonly uCameraLocation: WebGLUniformLocation;\n private readonly uBoundsLocation: WebGLUniformLocation;\n private readonly uTextureLocation: WebGLUniformLocation;\n private readonly resizeObserver: ResizeObserver;\n\n private tiles: LoadedTile[] = [];\n private frameId: number | null = null;\n private loadVersion = 0;\n private destroyed = false;\n private fitted = false;\n private controlledViewState = false;\n\n constructor(options: M1TileRendererOptions) {\n this.canvas = options.canvas;\n this.imageWidth = Math.max(1, options.imageWidth);\n this.imageHeight = Math.max(1, options.imageHeight);\n this.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n this.gl = requireWebGL2(this.canvas, { preserveDrawingBuffer: options.preserveDrawingBuffer });\n this.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n const vao = this.gl.createVertexArray();\n const quadBuffer = this.gl.createBuffer();\n if (!vao || !quadBuffer) {\n throw new Error(\"Failed to create WebGL buffers.\");\n }\n\n this.vao = vao;\n this.quadBuffer = quadBuffer;\n\n this.gl.bindVertexArray(this.vao);\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n const quadVertices = new Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]);\n\n this.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n const unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n const uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n if (unitLocation < 0 || uvLocation < 0) {\n throw new Error(\"Failed to get attribute locations.\");\n }\n\n const stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n this.gl.enableVertexAttribArray(unitLocation);\n this.gl.vertexAttribPointer(unitLocation, 2, this.gl.FLOAT, false, stride, 0);\n this.gl.enableVertexAttribArray(uvLocation);\n this.gl.vertexAttribPointer(uvLocation, 2, this.gl.FLOAT, false, stride, 2 * Float32Array.BYTES_PER_ELEMENT);\n\n this.gl.bindVertexArray(null);\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n this.uCameraLocation = requireUniformLocation(this.gl, this.program, \"uCamera\");\n this.uBoundsLocation = requireUniformLocation(this.gl, this.program, \"uBounds\");\n this.uTextureLocation = requireUniformLocation(this.gl, this.program, \"uTexture\");\n\n if (options.initialViewState) {\n this.controlledViewState = true;\n this.camera.setViewState(options.initialViewState);\n }\n\n this.resizeObserver = new ResizeObserver(() => {\n this.resize();\n });\n\n this.resizeObserver.observe(this.canvas);\n this.resize();\n }\n\n async setTiles(tiles: TileDefinition[]): Promise<void> {\n if (this.destroyed) {\n return;\n }\n\n const version = ++this.loadVersion;\n\n const loaded = await Promise.all(\n tiles.map(async tile => {\n const loadedTile = await this.loadTile(tile, version);\n return loadedTile;\n })\n );\n\n if (this.destroyed || version !== this.loadVersion) {\n for (const tile of loaded) {\n if (tile) {\n this.gl.deleteTexture(tile.texture);\n }\n }\n return;\n }\n\n this.disposeTiles(this.tiles);\n this.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n this.requestRender();\n }\n\n setViewState(viewState: Partial<ViewState>): void {\n this.controlledViewState = true;\n this.camera.setViewState(viewState);\n this.requestRender();\n }\n\n getViewState(): ViewState {\n return this.camera.getViewState();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n this.destroyed = true;\n this.loadVersion += 1;\n\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n\n this.resizeObserver.disconnect();\n this.disposeTiles(this.tiles);\n this.tiles = [];\n\n this.gl.deleteBuffer(this.quadBuffer);\n this.gl.deleteVertexArray(this.vao);\n this.gl.deleteProgram(this.program);\n }\n\n private async loadTile(tile: TileDefinition, version: number): Promise<LoadedTile | null> {\n try {\n const response = await fetch(tile.url);\n if (!response.ok) {\n throw new Error(`Tile fetch failed: ${response.status} ${response.statusText}`);\n }\n\n const blob = await response.blob();\n const bitmap = await createImageBitmap(blob);\n\n if (this.destroyed || version !== this.loadVersion) {\n bitmap.close();\n return null;\n }\n\n const texture = this.gl.createTexture();\n if (!texture) {\n bitmap.close();\n throw new Error(\"Failed to create tile texture.\");\n }\n\n this.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, bitmap);\n this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n bitmap.close();\n\n return {\n id: tile.id,\n bounds: tile.bounds,\n texture,\n };\n } catch (error) {\n console.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n return null;\n }\n }\n\n private resize(): void {\n if (this.destroyed) {\n return;\n }\n\n const rect = this.canvas.getBoundingClientRect();\n const cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n const cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n const targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n if (this.canvas.width !== targetWidth || this.canvas.height !== targetHeight) {\n this.canvas.width = targetWidth;\n this.canvas.height = targetHeight;\n }\n\n this.camera.setViewport(cssWidth, cssHeight);\n this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n if (!this.fitted && !this.controlledViewState) {\n this.fitToImage();\n this.fitted = true;\n }\n\n this.requestRender();\n }\n\n private fitToImage(): void {\n const viewport = this.camera.getViewportSize();\n\n const zoom = Math.min(viewport.width / this.imageWidth, viewport.height / this.imageHeight);\n const safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n const visibleWorldWidth = viewport.width / safeZoom;\n const visibleWorldHeight = viewport.height / safeZoom;\n\n const offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n const offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n this.camera.setViewState({\n zoom: safeZoom,\n offsetX,\n offsetY,\n });\n }\n\n private requestRender(): void {\n if (this.frameId !== null || this.destroyed) {\n return;\n }\n\n this.frameId = requestAnimationFrame(() => {\n this.frameId = null;\n this.render();\n });\n }\n\n private render(): void {\n if (this.destroyed) {\n return;\n }\n\n this.gl.clearColor(this.clearColor[0], this.clearColor[1], this.clearColor[2], this.clearColor[3]);\n this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n this.gl.useProgram(this.program);\n this.gl.bindVertexArray(this.vao);\n this.gl.uniformMatrix3fv(this.uCameraLocation, false, this.camera.getMatrix());\n this.gl.uniform1i(this.uTextureLocation, 0);\n\n for (const tile of this.tiles) {\n this.gl.activeTexture(this.gl.TEXTURE0);\n this.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n this.gl.uniform4f(this.uBoundsLocation, tile.bounds[0], tile.bounds[1], tile.bounds[2], tile.bounds[3]);\n this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n }\n\n this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n this.gl.bindVertexArray(null);\n }\n\n private disposeTiles(tiles: LoadedTile[]): void {\n for (const tile of tiles) {\n this.gl.deleteTexture(tile.texture);\n }\n }\n}\n","class f {\n constructor(t, e) {\n this.next = null, this.key = t, this.data = e, this.left = null, this.right = null;\n }\n}\nfunction d(n, t) {\n return n > t ? 1 : n < t ? -1 : 0;\n}\nfunction u(n, t, e) {\n const r = new f(null, null);\n let l = r, i = r;\n for (; ; ) {\n const o = e(n, t.key);\n if (o < 0) {\n if (t.left === null) break;\n if (e(n, t.left.key) < 0) {\n const s = t.left;\n if (t.left = s.right, s.right = t, t = s, t.left === null) break;\n }\n i.left = t, i = t, t = t.left;\n } else if (o > 0) {\n if (t.right === null) break;\n if (e(n, t.right.key) > 0) {\n const s = t.right;\n if (t.right = s.left, s.left = t, t = s, t.right === null) break;\n }\n l.right = t, l = t, t = t.right;\n } else break;\n }\n return l.right = t.left, i.left = t.right, t.left = r.right, t.right = r.left, t;\n}\nfunction c(n, t, e, r) {\n const l = new f(n, t);\n if (e === null)\n return l.left = l.right = null, l;\n e = u(n, e, r);\n const i = r(n, e.key);\n return i < 0 ? (l.left = e.left, l.right = e, e.left = null) : i >= 0 && (l.right = e.right, l.left = e, e.right = null), l;\n}\nfunction m(n, t, e) {\n let r = null, l = null;\n if (t) {\n t = u(n, t, e);\n const i = e(t.key, n);\n i === 0 ? (r = t.left, l = t.right) : i < 0 ? (l = t.right, t.right = null, r = t) : (r = t.left, t.left = null, l = t);\n }\n return { left: r, right: l };\n}\nfunction w(n, t, e) {\n return t === null ? n : (n === null || (t = u(n.key, t, e), t.left = n), t);\n}\nfunction _(n, t, e, r, l) {\n if (n) {\n r(`${t}${e ? \"└── \" : \"├── \"}${l(n)}\n`);\n const i = t + (e ? \" \" : \"│ \");\n n.left && _(n.left, i, !1, r, l), n.right && _(n.right, i, !0, r, l);\n }\n}\nclass z {\n constructor(t = d) {\n this._root = null, this._size = 0, this._comparator = t;\n }\n /**\n * Inserts a key, allows duplicates\n */\n insert(t, e) {\n return this._size++, this._root = c(t, e, this._root, this._comparator);\n }\n /**\n * Adds a key, if it is not present in the tree\n */\n add(t, e) {\n const r = new f(t, e);\n this._root === null && (r.left = r.right = null, this._size++, this._root = r);\n const l = this._comparator, i = u(t, this._root, l), o = l(t, i.key);\n return o === 0 ? this._root = i : (o < 0 ? (r.left = i.left, r.right = i, i.left = null) : o > 0 && (r.right = i.right, r.left = i, i.right = null), this._size++, this._root = r), this._root;\n }\n /**\n * @param {Key} key\n * @return {Node|null}\n */\n remove(t) {\n this._root = this._remove(t, this._root, this._comparator);\n }\n /**\n * Deletes i from the tree if it's there\n */\n _remove(t, e, r) {\n let l;\n return e === null ? null : (e = u(t, e, r), r(t, e.key) === 0 ? (e.left === null ? l = e.right : (l = u(t, e.left, r), l.right = e.right), this._size--, l) : e);\n }\n /**\n * Removes and returns the node with smallest key\n */\n pop() {\n let t = this._root;\n if (t) {\n for (; t.left; ) t = t.left;\n return this._root = u(t.key, this._root, this._comparator), this._root = this._remove(t.key, this._root, this._comparator), { key: t.key, data: t.data };\n }\n return null;\n }\n /**\n * Find without splaying\n */\n findStatic(t) {\n let e = this._root;\n const r = this._comparator;\n for (; e; ) {\n const l = r(t, e.key);\n if (l === 0) return e;\n l < 0 ? e = e.left : e = e.right;\n }\n return null;\n }\n find(t) {\n return this._root && (this._root = u(t, this._root, this._comparator), this._comparator(t, this._root.key) !== 0) ? null : this._root;\n }\n contains(t) {\n let e = this._root;\n const r = this._comparator;\n for (; e; ) {\n const l = r(t, e.key);\n if (l === 0) return !0;\n l < 0 ? e = e.left : e = e.right;\n }\n return !1;\n }\n forEach(t, e) {\n let r = this._root;\n const l = [];\n let i = !1;\n for (; !i; )\n r !== null ? (l.push(r), r = r.left) : l.length !== 0 ? (r = l.pop(), t.call(e, r), r = r.right) : i = !0;\n return this;\n }\n /**\n * Walk key range from `low` to `high`. Stops if `fn` returns a value.\n */\n range(t, e, r, l) {\n const i = [], o = this._comparator;\n let s = this._root, h;\n for (; i.length !== 0 || s; )\n if (s)\n i.push(s), s = s.left;\n else {\n if (s = i.pop(), h = o(s.key, e), h > 0)\n break;\n if (o(s.key, t) >= 0 && r.call(l, s))\n return this;\n s = s.right;\n }\n return this;\n }\n /**\n * Returns array of keys\n */\n keys() {\n const t = [];\n return this.forEach(({ key: e }) => {\n t.push(e);\n }), t;\n }\n /**\n * Returns array of all the data in the nodes\n */\n values() {\n const t = [];\n return this.forEach(({ data: e }) => {\n t.push(e);\n }), t;\n }\n min() {\n return this._root ? this.minNode(this._root).key : null;\n }\n max() {\n return this._root ? this.maxNode(this._root).key : null;\n }\n minNode(t = this._root) {\n if (t) for (; t.left; ) t = t.left;\n return t;\n }\n maxNode(t = this._root) {\n if (t) for (; t.right; ) t = t.right;\n return t;\n }\n /**\n * Returns node at given index\n */\n at(t) {\n let e = this._root, r = !1, l = 0;\n const i = [];\n for (; !r; )\n if (e)\n i.push(e), e = e.left;\n else if (i.length > 0) {\n if (e = i.pop(), l === t) return e;\n l++, e = e.right;\n } else r = !0;\n return null;\n }\n next(t) {\n let e = this._root, r = null;\n if (t.right) {\n for (r = t.right; r.left; ) r = r.left;\n return r;\n }\n const l = this._comparator;\n for (; e; ) {\n const i = l(t.key, e.key);\n if (i === 0) break;\n i < 0 ? (r = e, e = e.left) : e = e.right;\n }\n return r;\n }\n prev(t) {\n let e = this._root, r = null;\n if (t.left !== null) {\n for (r = t.left; r.right; ) r = r.right;\n return r;\n }\n const l = this._comparator;\n for (; e; ) {\n const i = l(t.key, e.key);\n if (i === 0) break;\n i < 0 ? e = e.left : (r = e, e = e.right);\n }\n return r;\n }\n clear() {\n return this._root = null, this._size = 0, this;\n }\n toList() {\n return k(this._root);\n }\n /**\n * Bulk-load items. Both array have to be same size\n */\n load(t, e = [], r = !1) {\n let l = t.length;\n const i = this._comparator;\n if (r && g(t, e, 0, l - 1, i), this._root === null)\n this._root = a(t, e, 0, l), this._size = l;\n else {\n const o = y(\n this.toList(),\n x(t, e),\n i\n );\n l = this._size + l, this._root = p({ head: o }, 0, l);\n }\n return this;\n }\n isEmpty() {\n return this._root === null;\n }\n get size() {\n return this._size;\n }\n get root() {\n return this._root;\n }\n toString(t = (e) => String(e.key)) {\n const e = [];\n return _(this._root, \"\", !0, (r) => e.push(r), t), e.join(\"\");\n }\n update(t, e, r) {\n const l = this._comparator;\n let { left: i, right: o } = m(t, this._root, l);\n l(t, e) < 0 ? o = c(e, r, o, l) : i = c(e, r, i, l), this._root = w(i, o, l);\n }\n split(t) {\n return m(t, this._root, this._comparator);\n }\n *[Symbol.iterator]() {\n let t = this._root;\n const e = [];\n let r = !1;\n for (; !r; )\n t !== null ? (e.push(t), t = t.left) : e.length !== 0 ? (t = e.pop(), yield t, t = t.right) : r = !0;\n }\n}\nfunction a(n, t, e, r) {\n const l = r - e;\n if (l > 0) {\n const i = e + Math.floor(l / 2), o = n[i], s = t[i], h = new f(o, s);\n return h.left = a(n, t, e, i), h.right = a(n, t, i + 1, r), h;\n }\n return null;\n}\nfunction x(n, t) {\n const e = new f(null, null);\n let r = e;\n for (let l = 0; l < n.length; l++)\n r = r.next = new f(n[l], t[l]);\n return r.next = null, e.next;\n}\nfunction k(n) {\n let t = n;\n const e = [];\n let r = !1;\n const l = new f(null, null);\n let i = l;\n for (; !r; )\n t ? (e.push(t), t = t.left) : e.length > 0 ? (t = i = i.next = e.pop(), t = t.right) : r = !0;\n return i.next = null, l.next;\n}\nfunction p(n, t, e) {\n const r = e - t;\n if (r > 0) {\n const l = t + Math.floor(r / 2), i = p(n, t, l), o = n.head;\n return o.left = i, n.head = n.head.next, o.right = p(n, l + 1, e), o;\n }\n return null;\n}\nfunction y(n, t, e) {\n const r = new f(null, null);\n let l = r, i = n, o = t;\n for (; i !== null && o !== null; )\n e(i.key, o.key) < 0 ? (l.next = i, i = i.next) : (l.next = o, o = o.next), l = l.next;\n return i !== null ? l.next = i : o !== null && (l.next = o), r.next;\n}\nfunction g(n, t, e, r, l) {\n if (e >= r) return;\n const i = n[e + r >> 1];\n let o = e - 1, s = r + 1;\n for (; ; ) {\n do\n o++;\n while (l(n[o], i) < 0);\n do\n s--;\n while (l(n[s], i) > 0);\n if (o >= s) break;\n let h = n[o];\n n[o] = n[s], n[s] = h, h = t[o], t[o] = t[s], t[s] = h;\n }\n g(n, t, e, s, l), g(n, t, s + 1, r, l);\n}\nexport {\n z as default\n};\n//# sourceMappingURL=splaytree.js.map\n","export const epsilon = 1.1102230246251565e-16;\nexport const splitter = 134217729;\nexport const resulterrbound = (3 + 8 * epsilon) * epsilon;\n\n// fast_expansion_sum_zeroelim routine from oritinal code\nexport function sum(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if ((fnow > enow) === (fnow > -enow)) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function sum_three(alen, a, blen, b, clen, c, tmp, out) {\n return sum(sum(alen, a, blen, b, tmp), tmp, clen, c, out);\n}\n\n// scale_expansion_zeroelim routine from oritinal code\nexport function scale(elen, e, b, h) {\n let Q, sum, hh, product1, product0;\n let bvirt, c, ahi, alo, bhi, blo;\n\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n let enow = e[0];\n Q = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);\n let hindex = 0;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n for (let i = 1; i < elen; i++) {\n enow = e[i];\n product1 = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);\n sum = Q + product0;\n bvirt = sum - Q;\n hh = Q - (sum - bvirt) + (product0 - bvirt);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n Q = product1 + sum;\n hh = sum - (Q - product1);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function negate(elen, e) {\n for (let i = 0; i < elen; i++) e[i] = -e[i];\n return elen;\n}\n\nexport function estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\n\nexport function vec(n) {\n return new Float64Array(n);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum} from './util.js';\n\nconst ccwerrboundA = (3 + 16 * epsilon) * epsilon;\nconst ccwerrboundB = (2 + 12 * epsilon) * epsilon;\nconst ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;\n\nconst B = vec(4);\nconst C1 = vec(8);\nconst C2 = vec(12);\nconst D = vec(16);\nconst u = vec(4);\n\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n\n s1 = acx * bcy;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcx;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n B[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n B[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n B[2] = _j - (u3 - bvirt) + (_i - bvirt);\n B[3] = u3;\n\n let det = estimate(4, B);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n\n s1 = acxtail * bcy;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcx;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C1len = sum(4, B, 4, u, C1);\n\n s1 = acx * bcytail;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcxtail;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C2len = sum(C1len, C1, 4, u, C2);\n\n s1 = acxtail * bcytail;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcxtail;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const Dlen = sum(C2len, C2, 4, u, D);\n\n return D[Dlen - 1];\n}\n\nexport function orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\nexport function orient2dfast(ax, ay, bx, by, cx, cy) {\n return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);\n}\n","import SplayTree from 'splaytree';\nimport { orient2d } from 'robust-predicates';\n\n/**\n * A bounding box has the format:\n *\n * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }\n *\n */\n\nconst isInBbox = (bbox, point) => {\n return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;\n};\n\n/* Returns either null, or a bbox (aka an ordered pair of points)\n * If there is only one point of overlap, a bbox with identical points\n * will be returned */\nconst getBboxOverlap = (b1, b2) => {\n // check if the bboxes overlap at all\n if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null;\n\n // find the middle two X values\n const lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;\n const upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x;\n\n // find the middle two Y values\n const lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;\n const upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y;\n\n // put those middle values together to get the overlap\n return {\n ll: {\n x: lowerX,\n y: lowerY\n },\n ur: {\n x: upperX,\n y: upperY\n }\n };\n};\n\n/* Javascript doesn't do integer math. Everything is\n * floating point with percision Number.EPSILON.\n *\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON\n */\n\nlet epsilon = Number.EPSILON;\n\n// IE Polyfill\nif (epsilon === undefined) epsilon = Math.pow(2, -52);\nconst EPSILON_SQ = epsilon * epsilon;\n\n/* FLP comparator */\nconst cmp = (a, b) => {\n // check if they're both 0\n if (-epsilon < a && a < epsilon) {\n if (-epsilon < b && b < epsilon) {\n return 0;\n }\n }\n\n // check if they're flp equal\n const ab = a - b;\n if (ab * ab < EPSILON_SQ * a * b) {\n return 0;\n }\n\n // normal comparison\n return a < b ? -1 : 1;\n};\n\n/**\n * This class rounds incoming values sufficiently so that\n * floating points problems are, for the most part, avoided.\n *\n * Incoming points are have their x & y values tested against\n * all previously seen x & y values. If either is 'too close'\n * to a previously seen value, it's value is 'snapped' to the\n * previously seen value.\n *\n * All points should be rounded by this class before being\n * stored in any data structures in the rest of this algorithm.\n */\n\nclass PtRounder {\n constructor() {\n this.reset();\n }\n reset() {\n this.xRounder = new CoordRounder();\n this.yRounder = new CoordRounder();\n }\n round(x, y) {\n return {\n x: this.xRounder.round(x),\n y: this.yRounder.round(y)\n };\n }\n}\nclass CoordRounder {\n constructor() {\n this.tree = new SplayTree();\n // preseed with 0 so we don't end up with values < Number.EPSILON\n this.round(0);\n }\n\n // Note: this can rounds input values backwards or forwards.\n // You might ask, why not restrict this to just rounding\n // forwards? Wouldn't that allow left endpoints to always\n // remain left endpoints during splitting (never change to\n // right). No - it wouldn't, because we snap intersections\n // to endpoints (to establish independence from the segment\n // angle for t-intersections).\n round(coord) {\n const node = this.tree.add(coord);\n const prevNode = this.tree.prev(node);\n if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {\n this.tree.remove(coord);\n return prevNode.key;\n }\n const nextNode = this.tree.next(node);\n if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {\n this.tree.remove(coord);\n return nextNode.key;\n }\n return coord;\n }\n}\n\n// singleton available by import\nconst rounder = new PtRounder();\n\n/* Cross Product of two vectors with first point at origin */\nconst crossProduct = (a, b) => a.x * b.y - a.y * b.x;\n\n/* Dot Product of two vectors with first point at origin */\nconst dotProduct = (a, b) => a.x * b.x + a.y * b.y;\n\n/* Comparator for two vectors with same starting point */\nconst compareVectorAngles = (basePt, endPt1, endPt2) => {\n const res = orient2d(basePt.x, basePt.y, endPt1.x, endPt1.y, endPt2.x, endPt2.y);\n if (res > 0) return -1;\n if (res < 0) return 1;\n return 0;\n};\nconst length = v => Math.sqrt(dotProduct(v, v));\n\n/* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */\nconst sineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = {\n x: pBase.x - pShared.x,\n y: pBase.y - pShared.y\n };\n const vAngle = {\n x: pAngle.x - pShared.x,\n y: pAngle.y - pShared.y\n };\n return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);\n};\n\n/* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */\nconst cosineOfAngle = (pShared, pBase, pAngle) => {\n const vBase = {\n x: pBase.x - pShared.x,\n y: pBase.y - pShared.y\n };\n const vAngle = {\n x: pAngle.x - pShared.x,\n y: pAngle.y - pShared.y\n };\n return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);\n};\n\n/* Get the x coordinate where the given line (defined by a point and vector)\n * crosses the horizontal line with the given y coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst horizontalIntersection = (pt, v, y) => {\n if (v.y === 0) return null;\n return {\n x: pt.x + v.x / v.y * (y - pt.y),\n y: y\n };\n};\n\n/* Get the y coordinate where the given line (defined by a point and vector)\n * crosses the vertical line with the given x coordiante.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst verticalIntersection = (pt, v, x) => {\n if (v.x === 0) return null;\n return {\n x: x,\n y: pt.y + v.y / v.x * (x - pt.x)\n };\n};\n\n/* Get the intersection of two lines, each defined by a base point and a vector.\n * In the case of parrallel lines (including overlapping ones) returns null. */\nconst intersection$1 = (pt1, v1, pt2, v2) => {\n // take some shortcuts for vertical and horizontal lines\n // this also ensures we don't calculate an intersection and then discover\n // it's actually outside the bounding box of the line\n if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);\n if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);\n if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);\n if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y);\n\n // General case for non-overlapping segments.\n // This algorithm is based on Schneider and Eberly.\n // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244\n\n const kross = crossProduct(v1, v2);\n if (kross == 0) return null;\n const ve = {\n x: pt2.x - pt1.x,\n y: pt2.y - pt1.y\n };\n const d1 = crossProduct(ve, v1) / kross;\n const d2 = crossProduct(ve, v2) / kross;\n\n // take the average of the two calculations to minimize rounding error\n const x1 = pt1.x + d2 * v1.x,\n x2 = pt2.x + d1 * v2.x;\n const y1 = pt1.y + d2 * v1.y,\n y2 = pt2.y + d1 * v2.y;\n const x = (x1 + x2) / 2;\n const y = (y1 + y2) / 2;\n return {\n x: x,\n y: y\n };\n};\n\nclass SweepEvent {\n // for ordering sweep events in the sweep event queue\n static compare(a, b) {\n // favor event with a point that the sweep line hits first\n const ptCmp = SweepEvent.comparePoints(a.point, b.point);\n if (ptCmp !== 0) return ptCmp;\n\n // the points are the same, so link them if needed\n if (a.point !== b.point) a.link(b);\n\n // favor right events over left\n if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1;\n\n // we have two matching left or right endpoints\n // ordering of this case is the same as for their segments\n return Segment.compare(a.segment, b.segment);\n }\n\n // for ordering points in sweep line order\n static comparePoints(aPt, bPt) {\n if (aPt.x < bPt.x) return -1;\n if (aPt.x > bPt.x) return 1;\n if (aPt.y < bPt.y) return -1;\n if (aPt.y > bPt.y) return 1;\n return 0;\n }\n\n // Warning: 'point' input will be modified and re-used (for performance)\n constructor(point, isLeft) {\n if (point.events === undefined) point.events = [this];else point.events.push(this);\n this.point = point;\n this.isLeft = isLeft;\n // this.segment, this.otherSE set by factory\n }\n link(other) {\n if (other.point === this.point) {\n throw new Error(\"Tried to link already linked events\");\n }\n const otherEvents = other.point.events;\n for (let i = 0, iMax = otherEvents.length; i < iMax; i++) {\n const evt = otherEvents[i];\n this.point.events.push(evt);\n evt.point = this.point;\n }\n this.checkForConsuming();\n }\n\n /* Do a pass over our linked events and check to see if any pair\n * of segments match, and should be consumed. */\n checkForConsuming() {\n // FIXME: The loops in this method run O(n^2) => no good.\n // Maintain little ordered sweep event trees?\n // Can we maintaining an ordering that avoids the need\n // for the re-sorting with getLeftmostComparator in geom-out?\n\n // Compare each pair of events to see if other events also match\n const numEvents = this.point.events.length;\n for (let i = 0; i < numEvents; i++) {\n const evt1 = this.point.events[i];\n if (evt1.segment.consumedBy !== undefined) continue;\n for (let j = i + 1; j < numEvents; j++) {\n const evt2 = this.point.events[j];\n if (evt2.consumedBy !== undefined) continue;\n if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;\n evt1.segment.consume(evt2.segment);\n }\n }\n }\n getAvailableLinkedEvents() {\n // point.events is always of length 2 or greater\n const events = [];\n for (let i = 0, iMax = this.point.events.length; i < iMax; i++) {\n const evt = this.point.events[i];\n if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {\n events.push(evt);\n }\n }\n return events;\n }\n\n /**\n * Returns a comparator function for sorting linked events that will\n * favor the event that will give us the smallest left-side angle.\n * All ring construction starts as low as possible heading to the right,\n * so by always turning left as sharp as possible we'll get polygons\n * without uncessary loops & holes.\n *\n * The comparator function has a compute cache such that it avoids\n * re-computing already-computed values.\n */\n getLeftmostComparator(baseEvent) {\n const cache = new Map();\n const fillCache = linkedEvent => {\n const nextEvent = linkedEvent.otherSE;\n cache.set(linkedEvent, {\n sine: sineOfAngle(this.point, baseEvent.point, nextEvent.point),\n cosine: cosineOfAngle(this.point, baseEvent.point, nextEvent.point)\n });\n };\n return (a, b) => {\n if (!cache.has(a)) fillCache(a);\n if (!cache.has(b)) fillCache(b);\n const {\n sine: asine,\n cosine: acosine\n } = cache.get(a);\n const {\n sine: bsine,\n cosine: bcosine\n } = cache.get(b);\n\n // both on or above x-axis\n if (asine >= 0 && bsine >= 0) {\n if (acosine < bcosine) return 1;\n if (acosine > bcosine) return -1;\n return 0;\n }\n\n // both below x-axis\n if (asine < 0 && bsine < 0) {\n if (acosine < bcosine) return -1;\n if (acosine > bcosine) return 1;\n return 0;\n }\n\n // one above x-axis, one below\n if (bsine < asine) return -1;\n if (bsine > asine) return 1;\n return 0;\n };\n }\n}\n\n// Give segments unique ID's to get consistent sorting of\n// segments and sweep events when all else is identical\nlet segmentId = 0;\nclass Segment {\n /* This compare() function is for ordering segments in the sweep\n * line tree, and does so according to the following criteria:\n *\n * Consider the vertical line that lies an infinestimal step to the\n * right of the right-more of the two left endpoints of the input\n * segments. Imagine slowly moving a point up from negative infinity\n * in the increasing y direction. Which of the two segments will that\n * point intersect first? That segment comes 'before' the other one.\n *\n * If neither segment would be intersected by such a line, (if one\n * or more of the segments are vertical) then the line to be considered\n * is directly on the right-more of the two left inputs.\n */\n static compare(a, b) {\n const alx = a.leftSE.point.x;\n const blx = b.leftSE.point.x;\n const arx = a.rightSE.point.x;\n const brx = b.rightSE.point.x;\n\n // check if they're even in the same vertical plane\n if (brx < alx) return 1;\n if (arx < blx) return -1;\n const aly = a.leftSE.point.y;\n const bly = b.leftSE.point.y;\n const ary = a.rightSE.point.y;\n const bry = b.rightSE.point.y;\n\n // is left endpoint of segment B the right-more?\n if (alx < blx) {\n // are the two segments in the same horizontal plane?\n if (bly < aly && bly < ary) return 1;\n if (bly > aly && bly > ary) return -1;\n\n // is the B left endpoint colinear to segment A?\n const aCmpBLeft = a.comparePoint(b.leftSE.point);\n if (aCmpBLeft < 0) return 1;\n if (aCmpBLeft > 0) return -1;\n\n // is the A right endpoint colinear to segment B ?\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0) return bCmpARight;\n\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return -1;\n }\n\n // is left endpoint of segment A the right-more?\n if (alx > blx) {\n if (aly < bly && aly < bry) return -1;\n if (aly > bly && aly > bry) return 1;\n\n // is the A left endpoint colinear to segment B?\n const bCmpALeft = b.comparePoint(a.leftSE.point);\n if (bCmpALeft !== 0) return bCmpALeft;\n\n // is the B right endpoint colinear to segment A?\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0) return 1;\n if (aCmpBRight > 0) return -1;\n\n // colinear segments, consider the one with left-more\n // left endpoint to be first (arbitrary?)\n return 1;\n }\n\n // if we get here, the two left endpoints are in the same\n // vertical plane, ie alx === blx\n\n // consider the lower left-endpoint to come first\n if (aly < bly) return -1;\n if (aly > bly) return 1;\n\n // left endpoints are identical\n // check for colinearity by using the left-more right endpoint\n\n // is the A right endpoint more left-more?\n if (arx < brx) {\n const bCmpARight = b.comparePoint(a.rightSE.point);\n if (bCmpARight !== 0) return bCmpARight;\n }\n\n // is the B right endpoint more left-more?\n if (arx > brx) {\n const aCmpBRight = a.comparePoint(b.rightSE.point);\n if (aCmpBRight < 0) return 1;\n if (aCmpBRight > 0) return -1;\n }\n if (arx !== brx) {\n // are these two [almost] vertical segments with opposite orientation?\n // if so, the one with the lower right endpoint comes first\n const ay = ary - aly;\n const ax = arx - alx;\n const by = bry - bly;\n const bx = brx - blx;\n if (ay > ax && by < bx) return 1;\n if (ay < ax && by > bx) return -1;\n }\n\n // we have colinear segments with matching orientation\n // consider the one with more left-more right endpoint to be first\n if (arx > brx) return 1;\n if (arx < brx) return -1;\n\n // if we get here, two two right endpoints are in the same\n // vertical plane, ie arx === brx\n\n // consider the lower right-endpoint to come first\n if (ary < bry) return -1;\n if (ary > bry) return 1;\n\n // right endpoints identical as well, so the segments are idential\n // fall back on creation order as consistent tie-breaker\n if (a.id < b.id) return -1;\n if (a.id > b.id) return 1;\n\n // identical segment, ie a === b\n return 0;\n }\n\n /* Warning: a reference to ringWindings input will be stored,\n * and possibly will be later modified */\n constructor(leftSE, rightSE, rings, windings) {\n this.id = ++segmentId;\n this.leftSE = leftSE;\n leftSE.segment = this;\n leftSE.otherSE = rightSE;\n this.rightSE = rightSE;\n rightSE.segment = this;\n rightSE.otherSE = leftSE;\n this.rings = rings;\n this.windings = windings;\n // left unset for performance, set later in algorithm\n // this.ringOut, this.consumedBy, this.prev\n }\n static fromRing(pt1, pt2, ring) {\n let leftPt, rightPt, winding;\n\n // ordering the two points according to sweep line ordering\n const cmpPts = SweepEvent.comparePoints(pt1, pt2);\n if (cmpPts < 0) {\n leftPt = pt1;\n rightPt = pt2;\n winding = 1;\n } else if (cmpPts > 0) {\n leftPt = pt2;\n rightPt = pt1;\n winding = -1;\n } else throw new Error(`Tried to create degenerate segment at [${pt1.x}, ${pt1.y}]`);\n const leftSE = new SweepEvent(leftPt, true);\n const rightSE = new SweepEvent(rightPt, false);\n return new Segment(leftSE, rightSE, [ring], [winding]);\n }\n\n /* When a segment is split, the rightSE is replaced with a new sweep event */\n replaceRightSE(newRightSE) {\n this.rightSE = newRightSE;\n this.rightSE.segment = this;\n this.rightSE.otherSE = this.leftSE;\n this.leftSE.otherSE = this.rightSE;\n }\n bbox() {\n const y1 = this.leftSE.point.y;\n const y2 = this.rightSE.point.y;\n return {\n ll: {\n x: this.leftSE.point.x,\n y: y1 < y2 ? y1 : y2\n },\n ur: {\n x: this.rightSE.point.x,\n y: y1 > y2 ? y1 : y2\n }\n };\n }\n\n /* A vector from the left point to the right */\n vector() {\n return {\n x: this.rightSE.point.x - this.leftSE.point.x,\n y: this.rightSE.point.y - this.leftSE.point.y\n };\n }\n isAnEndpoint(pt) {\n return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;\n }\n\n /* Compare this segment with a point.\n *\n * A point P is considered to be colinear to a segment if there\n * exists a distance D such that if we travel along the segment\n * from one * endpoint towards the other a distance D, we find\n * ourselves at point P.\n *\n * Return value indicates:\n *\n * 1: point lies above the segment (to the left of vertical)\n * 0: point is colinear to segment\n * -1: point lies below the segment (to the right of vertical)\n */\n comparePoint(point) {\n if (this.isAnEndpoint(point)) return 0;\n const lPt = this.leftSE.point;\n const rPt = this.rightSE.point;\n const v = this.vector();\n\n // Exactly vertical segments.\n if (lPt.x === rPt.x) {\n if (point.x === lPt.x) return 0;\n return point.x < lPt.x ? 1 : -1;\n }\n\n // Nearly vertical segments with an intersection.\n // Check to see where a point on the line with matching Y coordinate is.\n const yDist = (point.y - lPt.y) / v.y;\n const xFromYDist = lPt.x + yDist * v.x;\n if (point.x === xFromYDist) return 0;\n\n // General case.\n // Check to see where a point on the line with matching X coordinate is.\n const xDist = (point.x - lPt.x) / v.x;\n const yFromXDist = lPt.y + xDist * v.y;\n if (point.y === yFromXDist) return 0;\n return point.y < yFromXDist ? -1 : 1;\n }\n\n /**\n * Given another segment, returns the first non-trivial intersection\n * between the two segments (in terms of sweep line ordering), if it exists.\n *\n * A 'non-trivial' intersection is one that will cause one or both of the\n * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:\n *\n * * endpoint of segA with endpoint of segB --> trivial\n * * endpoint of segA with point along segB --> non-trivial\n * * endpoint of segB with point along segA --> non-trivial\n * * point along segA with point along segB --> non-trivial\n *\n * If no non-trivial intersection exists, return null\n * Else, return null.\n */\n getIntersection(other) {\n // If bboxes don't overlap, there can't be any intersections\n const tBbox = this.bbox();\n const oBbox = other.bbox();\n const bboxOverlap = getBboxOverlap(tBbox, oBbox);\n if (bboxOverlap === null) return null;\n\n // We first check to see if the endpoints can be considered intersections.\n // This will 'snap' intersections to endpoints if possible, and will\n // handle cases of colinearity.\n\n const tlp = this.leftSE.point;\n const trp = this.rightSE.point;\n const olp = other.leftSE.point;\n const orp = other.rightSE.point;\n\n // does each endpoint touch the other segment?\n // note that we restrict the 'touching' definition to only allow segments\n // to touch endpoints that lie forward from where we are in the sweep line pass\n const touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;\n const touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;\n const touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;\n const touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0;\n\n // do left endpoints match?\n if (touchesThisLSE && touchesOtherLSE) {\n // these two cases are for colinear segments with matching left\n // endpoints, and one segment being longer than the other\n if (touchesThisRSE && !touchesOtherRSE) return trp;\n if (!touchesThisRSE && touchesOtherRSE) return orp;\n // either the two segments match exactly (two trival intersections)\n // or just on their left endpoint (one trivial intersection\n return null;\n }\n\n // does this left endpoint matches (other doesn't)\n if (touchesThisLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesOtherRSE) {\n if (tlp.x === orp.x && tlp.y === orp.y) return null;\n }\n // t-intersection on left endpoint\n return tlp;\n }\n\n // does other left endpoint matches (this doesn't)\n if (touchesOtherLSE) {\n // check for segments that just intersect on opposing endpoints\n if (touchesThisRSE) {\n if (trp.x === olp.x && trp.y === olp.y) return null;\n }\n // t-intersection on left endpoint\n return olp;\n }\n\n // trivial intersection on right endpoints\n if (touchesThisRSE && touchesOtherRSE) return null;\n\n // t-intersections on just one right endpoint\n if (touchesThisRSE) return trp;\n if (touchesOtherRSE) return orp;\n\n // None of our endpoints intersect. Look for a general intersection between\n // infinite lines laid over the segments\n const pt = intersection$1(tlp, this.vector(), olp, other.vector());\n\n // are the segments parrallel? Note that if they were colinear with overlap,\n // they would have an endpoint intersection and that case was already handled above\n if (pt === null) return null;\n\n // is the intersection found between the lines not on the segments?\n if (!isInBbox(bboxOverlap, pt)) return null;\n\n // round the the computed point if needed\n return rounder.round(pt.x, pt.y);\n }\n\n /**\n * Split the given segment into multiple segments on the given points.\n * * Each existing segment will retain its leftSE and a new rightSE will be\n * generated for it.\n * * A new segment will be generated which will adopt the original segment's\n * rightSE, and a new leftSE will be generated for it.\n * * If there are more than two points given to split on, new segments\n * in the middle will be generated with new leftSE and rightSE's.\n * * An array of the newly generated SweepEvents will be returned.\n *\n * Warning: input array of points is modified\n */\n split(point) {\n const newEvents = [];\n const alreadyLinked = point.events !== undefined;\n const newLeftSE = new SweepEvent(point, true);\n const newRightSE = new SweepEvent(point, false);\n const oldRightSE = this.rightSE;\n this.replaceRightSE(newRightSE);\n newEvents.push(newRightSE);\n newEvents.push(newLeftSE);\n const newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice());\n\n // when splitting a nearly vertical downward-facing segment,\n // sometimes one of the resulting new segments is vertical, in which\n // case its left and right events may need to be swapped\n if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {\n newSeg.swapEvents();\n }\n if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {\n this.swapEvents();\n }\n\n // in the point we just used to create new sweep events with was already\n // linked to other events, we need to check if either of the affected\n // segments should be consumed\n if (alreadyLinked) {\n newLeftSE.checkForConsuming();\n newRightSE.checkForConsuming();\n }\n return newEvents;\n }\n\n /* Swap which event is left and right */\n swapEvents() {\n const tmpEvt = this.rightSE;\n this.rightSE = this.leftSE;\n this.leftSE = tmpEvt;\n this.leftSE.isLeft = true;\n this.rightSE.isLeft = false;\n for (let i = 0, iMax = this.windings.length; i < iMax; i++) {\n this.windings[i] *= -1;\n }\n }\n\n /* Consume another segment. We take their rings under our wing\n * and mark them as consumed. Use for perfectly overlapping segments */\n consume(other) {\n let consumer = this;\n let consumee = other;\n while (consumer.consumedBy) consumer = consumer.consumedBy;\n while (consumee.consumedBy) consumee = consumee.consumedBy;\n const cmp = Segment.compare(consumer, consumee);\n if (cmp === 0) return; // already consumed\n // the winner of the consumption is the earlier segment\n // according to sweep line ordering\n if (cmp > 0) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n\n // make sure a segment doesn't consume it's prev\n if (consumer.prev === consumee) {\n const tmp = consumer;\n consumer = consumee;\n consumee = tmp;\n }\n for (let i = 0, iMax = consumee.rings.length; i < iMax; i++) {\n const ring = consumee.rings[i];\n const winding = consumee.windings[i];\n const index = consumer.rings.indexOf(ring);\n if (index === -1) {\n consumer.rings.push(ring);\n consumer.windings.push(winding);\n } else consumer.windings[index] += winding;\n }\n consumee.rings = null;\n consumee.windings = null;\n consumee.consumedBy = consumer;\n\n // mark sweep events consumed as to maintain ordering in sweep event queue\n consumee.leftSE.consumedBy = consumer.leftSE;\n consumee.rightSE.consumedBy = consumer.rightSE;\n }\n\n /* The first segment previous segment chain that is in the result */\n prevInResult() {\n if (this._prevInResult !== undefined) return this._prevInResult;\n if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();\n return this._prevInResult;\n }\n beforeState() {\n if (this._beforeState !== undefined) return this._beforeState;\n if (!this.prev) this._beforeState = {\n rings: [],\n windings: [],\n multiPolys: []\n };else {\n const seg = this.prev.consumedBy || this.prev;\n this._beforeState = seg.afterState();\n }\n return this._beforeState;\n }\n afterState() {\n if (this._afterState !== undefined) return this._afterState;\n const beforeState = this.beforeState();\n this._afterState = {\n rings: beforeState.rings.slice(0),\n windings: beforeState.windings.slice(0),\n multiPolys: []\n };\n const ringsAfter = this._afterState.rings;\n const windingsAfter = this._afterState.windings;\n const mpsAfter = this._afterState.multiPolys;\n\n // calculate ringsAfter, windingsAfter\n for (let i = 0, iMax = this.rings.length; i < iMax; i++) {\n const ring = this.rings[i];\n const winding = this.windings[i];\n const index = ringsAfter.indexOf(ring);\n if (index === -1) {\n ringsAfter.push(ring);\n windingsAfter.push(winding);\n } else windingsAfter[index] += winding;\n }\n\n // calcualte polysAfter\n const polysAfter = [];\n const polysExclude = [];\n for (let i = 0, iMax = ringsAfter.length; i < iMax; i++) {\n if (windingsAfter[i] === 0) continue; // non-zero rule\n const ring = ringsAfter[i];\n const poly = ring.poly;\n if (polysExclude.indexOf(poly) !== -1) continue;\n if (ring.isExterior) polysAfter.push(poly);else {\n if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);\n const index = polysAfter.indexOf(ring.poly);\n if (index !== -1) polysAfter.splice(index, 1);\n }\n }\n\n // calculate multiPolysAfter\n for (let i = 0, iMax = polysAfter.length; i < iMax; i++) {\n const mp = polysAfter[i].multiPoly;\n if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);\n }\n return this._afterState;\n }\n\n /* Is this segment part of the final result? */\n isInResult() {\n // if we've been consumed, we're not in the result\n if (this.consumedBy) return false;\n if (this._isInResult !== undefined) return this._isInResult;\n const mpsBefore = this.beforeState().multiPolys;\n const mpsAfter = this.afterState().multiPolys;\n switch (operation.type) {\n case \"union\":\n {\n // UNION - included iff:\n // * On one side of us there is 0 poly interiors AND\n // * On the other side there is 1 or more.\n const noBefores = mpsBefore.length === 0;\n const noAfters = mpsAfter.length === 0;\n this._isInResult = noBefores !== noAfters;\n break;\n }\n case \"intersection\":\n {\n // INTERSECTION - included iff:\n // * on one side of us all multipolys are rep. with poly interiors AND\n // * on the other side of us, not all multipolys are repsented\n // with poly interiors\n let least;\n let most;\n if (mpsBefore.length < mpsAfter.length) {\n least = mpsBefore.length;\n most = mpsAfter.length;\n } else {\n least = mpsAfter.length;\n most = mpsBefore.length;\n }\n this._isInResult = most === operation.numMultiPolys && least < most;\n break;\n }\n case \"xor\":\n {\n // XOR - included iff:\n // * the difference between the number of multipolys represented\n // with poly interiors on our two sides is an odd number\n const diff = Math.abs(mpsBefore.length - mpsAfter.length);\n this._isInResult = diff % 2 === 1;\n break;\n }\n case \"difference\":\n {\n // DIFFERENCE included iff:\n // * on exactly one side, we have just the subject\n const isJustSubject = mps => mps.length === 1 && mps[0].isSubject;\n this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);\n break;\n }\n default:\n throw new Error(`Unrecognized operation type found ${operation.type}`);\n }\n return this._isInResult;\n }\n}\n\nclass RingIn {\n constructor(geomRing, poly, isExterior) {\n if (!Array.isArray(geomRing) || geomRing.length === 0) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.poly = poly;\n this.isExterior = isExterior;\n this.segments = [];\n if (typeof geomRing[0][0] !== \"number\" || typeof geomRing[0][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n const firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);\n this.bbox = {\n ll: {\n x: firstPoint.x,\n y: firstPoint.y\n },\n ur: {\n x: firstPoint.x,\n y: firstPoint.y\n }\n };\n let prevPoint = firstPoint;\n for (let i = 1, iMax = geomRing.length; i < iMax; i++) {\n if (typeof geomRing[i][0] !== \"number\" || typeof geomRing[i][1] !== \"number\") {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n let point = rounder.round(geomRing[i][0], geomRing[i][1]);\n // skip repeated points\n if (point.x === prevPoint.x && point.y === prevPoint.y) continue;\n this.segments.push(Segment.fromRing(prevPoint, point, this));\n if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;\n if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y;\n if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;\n if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;\n prevPoint = point;\n }\n // add segment from last to first if last is not the same as first\n if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {\n this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));\n }\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.segments.length; i < iMax; i++) {\n const segment = this.segments[i];\n sweepEvents.push(segment.leftSE);\n sweepEvents.push(segment.rightSE);\n }\n return sweepEvents;\n }\n}\nclass PolyIn {\n constructor(geomPoly, multiPoly) {\n if (!Array.isArray(geomPoly)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n this.exteriorRing = new RingIn(geomPoly[0], this, true);\n // copy by value\n this.bbox = {\n ll: {\n x: this.exteriorRing.bbox.ll.x,\n y: this.exteriorRing.bbox.ll.y\n },\n ur: {\n x: this.exteriorRing.bbox.ur.x,\n y: this.exteriorRing.bbox.ur.y\n }\n };\n this.interiorRings = [];\n for (let i = 1, iMax = geomPoly.length; i < iMax; i++) {\n const ring = new RingIn(geomPoly[i], this, false);\n if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;\n if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;\n if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;\n if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;\n this.interiorRings.push(ring);\n }\n this.multiPoly = multiPoly;\n }\n getSweepEvents() {\n const sweepEvents = this.exteriorRing.getSweepEvents();\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringSweepEvents = this.interiorRings[i].getSweepEvents();\n for (let j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {\n sweepEvents.push(ringSweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\nclass MultiPolyIn {\n constructor(geom, isSubject) {\n if (!Array.isArray(geom)) {\n throw new Error(\"Input geometry is not a valid Polygon or MultiPolygon\");\n }\n try {\n // if the input looks like a polygon, convert it to a multipolygon\n if (typeof geom[0][0][0] === \"number\") geom = [geom];\n } catch (ex) {\n // The input is either malformed or has empty arrays.\n // In either case, it will be handled later on.\n }\n this.polys = [];\n this.bbox = {\n ll: {\n x: Number.POSITIVE_INFINITY,\n y: Number.POSITIVE_INFINITY\n },\n ur: {\n x: Number.NEGATIVE_INFINITY,\n y: Number.NEGATIVE_INFINITY\n }\n };\n for (let i = 0, iMax = geom.length; i < iMax; i++) {\n const poly = new PolyIn(geom[i], this);\n if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;\n if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;\n if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;\n if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;\n this.polys.push(poly);\n }\n this.isSubject = isSubject;\n }\n getSweepEvents() {\n const sweepEvents = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polySweepEvents = this.polys[i].getSweepEvents();\n for (let j = 0, jMax = polySweepEvents.length; j < jMax; j++) {\n sweepEvents.push(polySweepEvents[j]);\n }\n }\n return sweepEvents;\n }\n}\n\nclass RingOut {\n /* Given the segments from the sweep line pass, compute & return a series\n * of closed rings from all the segments marked to be part of the result */\n static factory(allSegments) {\n const ringsOut = [];\n for (let i = 0, iMax = allSegments.length; i < iMax; i++) {\n const segment = allSegments[i];\n if (!segment.isInResult() || segment.ringOut) continue;\n let prevEvent = null;\n let event = segment.leftSE;\n let nextEvent = segment.rightSE;\n const events = [event];\n const startingPoint = event.point;\n const intersectionLEs = [];\n\n /* Walk the chain of linked events to form a closed ring */\n while (true) {\n prevEvent = event;\n event = nextEvent;\n events.push(event);\n\n /* Is the ring complete? */\n if (event.point === startingPoint) break;\n while (true) {\n const availableLEs = event.getAvailableLinkedEvents();\n\n /* Did we hit a dead end? This shouldn't happen.\n * Indicates some earlier part of the algorithm malfunctioned. */\n if (availableLEs.length === 0) {\n const firstPt = events[0].point;\n const lastPt = events[events.length - 1].point;\n throw new Error(`Unable to complete output ring starting at [${firstPt.x},` + ` ${firstPt.y}]. Last matching segment found ends at` + ` [${lastPt.x}, ${lastPt.y}].`);\n }\n\n /* Only one way to go, so cotinue on the path */\n if (availableLEs.length === 1) {\n nextEvent = availableLEs[0].otherSE;\n break;\n }\n\n /* We must have an intersection. Check for a completed loop */\n let indexLE = null;\n for (let j = 0, jMax = intersectionLEs.length; j < jMax; j++) {\n if (intersectionLEs[j].point === event.point) {\n indexLE = j;\n break;\n }\n }\n /* Found a completed loop. Cut that off and make a ring */\n if (indexLE !== null) {\n const intersectionLE = intersectionLEs.splice(indexLE)[0];\n const ringEvents = events.splice(intersectionLE.index);\n ringEvents.unshift(ringEvents[0].otherSE);\n ringsOut.push(new RingOut(ringEvents.reverse()));\n continue;\n }\n /* register the intersection */\n intersectionLEs.push({\n index: events.length,\n point: event.point\n });\n /* Choose the left-most option to continue the walk */\n const comparator = event.getLeftmostComparator(prevEvent);\n nextEvent = availableLEs.sort(comparator)[0].otherSE;\n break;\n }\n }\n ringsOut.push(new RingOut(events));\n }\n return ringsOut;\n }\n constructor(events) {\n this.events = events;\n for (let i = 0, iMax = events.length; i < iMax; i++) {\n events[i].segment.ringOut = this;\n }\n this.poly = null;\n }\n getGeom() {\n // Remove superfluous points (ie extra points along a straight line),\n let prevPt = this.events[0].point;\n const points = [prevPt];\n for (let i = 1, iMax = this.events.length - 1; i < iMax; i++) {\n const pt = this.events[i].point;\n const nextPt = this.events[i + 1].point;\n if (compareVectorAngles(pt, prevPt, nextPt) === 0) continue;\n points.push(pt);\n prevPt = pt;\n }\n\n // ring was all (within rounding error of angle calc) colinear points\n if (points.length === 1) return null;\n\n // check if the starting point is necessary\n const pt = points[0];\n const nextPt = points[1];\n if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();\n points.push(points[0]);\n const step = this.isExteriorRing() ? 1 : -1;\n const iStart = this.isExteriorRing() ? 0 : points.length - 1;\n const iEnd = this.isExteriorRing() ? points.length : -1;\n const orderedPoints = [];\n for (let i = iStart; i != iEnd; i += step) orderedPoints.push([points[i].x, points[i].y]);\n return orderedPoints;\n }\n isExteriorRing() {\n if (this._isExteriorRing === undefined) {\n const enclosing = this.enclosingRing();\n this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;\n }\n return this._isExteriorRing;\n }\n enclosingRing() {\n if (this._enclosingRing === undefined) {\n this._enclosingRing = this._calcEnclosingRing();\n }\n return this._enclosingRing;\n }\n\n /* Returns the ring that encloses this one, if any */\n _calcEnclosingRing() {\n // start with the ealier sweep line event so that the prevSeg\n // chain doesn't lead us inside of a loop of ours\n let leftMostEvt = this.events[0];\n for (let i = 1, iMax = this.events.length; i < iMax; i++) {\n const evt = this.events[i];\n if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;\n }\n let prevSeg = leftMostEvt.segment.prevInResult();\n let prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n while (true) {\n // no segment found, thus no ring can enclose us\n if (!prevSeg) return null;\n\n // no segments below prev segment found, thus the ring of the prev\n // segment must loop back around and enclose us\n if (!prevPrevSeg) return prevSeg.ringOut;\n\n // if the two segments are of different rings, the ring of the prev\n // segment must either loop around us or the ring of the prev prev\n // seg, which would make us and the ring of the prev peers\n if (prevPrevSeg.ringOut !== prevSeg.ringOut) {\n if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {\n return prevSeg.ringOut;\n } else return prevSeg.ringOut.enclosingRing();\n }\n\n // two segments are from the same ring, so this was a penisula\n // of that ring. iterate downward, keep searching\n prevSeg = prevPrevSeg.prevInResult();\n prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;\n }\n }\n}\nclass PolyOut {\n constructor(exteriorRing) {\n this.exteriorRing = exteriorRing;\n exteriorRing.poly = this;\n this.interiorRings = [];\n }\n addInterior(ring) {\n this.interiorRings.push(ring);\n ring.poly = this;\n }\n getGeom() {\n const geom = [this.exteriorRing.getGeom()];\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (geom[0] === null) return null;\n for (let i = 0, iMax = this.interiorRings.length; i < iMax; i++) {\n const ringGeom = this.interiorRings[i].getGeom();\n // interior ring was all (within rounding error of angle calc) colinear points\n if (ringGeom === null) continue;\n geom.push(ringGeom);\n }\n return geom;\n }\n}\nclass MultiPolyOut {\n constructor(rings) {\n this.rings = rings;\n this.polys = this._composePolys(rings);\n }\n getGeom() {\n const geom = [];\n for (let i = 0, iMax = this.polys.length; i < iMax; i++) {\n const polyGeom = this.polys[i].getGeom();\n // exterior ring was all (within rounding error of angle calc) colinear points\n if (polyGeom === null) continue;\n geom.push(polyGeom);\n }\n return geom;\n }\n _composePolys(rings) {\n const polys = [];\n for (let i = 0, iMax = rings.length; i < iMax; i++) {\n const ring = rings[i];\n if (ring.poly) continue;\n if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {\n const enclosingRing = ring.enclosingRing();\n if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));\n enclosingRing.poly.addInterior(ring);\n }\n }\n return polys;\n }\n}\n\n/**\n * NOTE: We must be careful not to change any segments while\n * they are in the SplayTree. AFAIK, there's no way to tell\n * the tree to rebalance itself - thus before splitting\n * a segment that's in the tree, we remove it from the tree,\n * do the split, then re-insert it. (Even though splitting a\n * segment *shouldn't* change its correct position in the\n * sweep line tree, the reality is because of rounding errors,\n * it sometimes does.)\n */\n\nclass SweepLine {\n constructor(queue) {\n let comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;\n this.queue = queue;\n this.tree = new SplayTree(comparator);\n this.segments = [];\n }\n process(event) {\n const segment = event.segment;\n const newEvents = [];\n\n // if we've already been consumed by another segment,\n // clean up our body parts and get out\n if (event.consumedBy) {\n if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);\n return newEvents;\n }\n const node = event.isLeft ? this.tree.add(segment) : this.tree.find(segment);\n if (!node) throw new Error(`Unable to find segment #${segment.id} ` + `[${segment.leftSE.point.x}, ${segment.leftSE.point.y}] -> ` + `[${segment.rightSE.point.x}, ${segment.rightSE.point.y}] ` + \"in SweepLine tree.\");\n let prevNode = node;\n let nextNode = node;\n let prevSeg = undefined;\n let nextSeg = undefined;\n\n // skip consumed segments still in tree\n while (prevSeg === undefined) {\n prevNode = this.tree.prev(prevNode);\n if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;\n }\n\n // skip consumed segments still in tree\n while (nextSeg === undefined) {\n nextNode = this.tree.next(nextNode);\n if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;\n }\n if (event.isLeft) {\n // Check for intersections against the previous segment in the sweep line\n let prevMySplitter = null;\n if (prevSeg) {\n const prevInter = prevSeg.getIntersection(segment);\n if (prevInter !== null) {\n if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;\n if (!prevSeg.isAnEndpoint(prevInter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, prevInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n\n // Check for intersections against the next segment in the sweep line\n let nextMySplitter = null;\n if (nextSeg) {\n const nextInter = nextSeg.getIntersection(segment);\n if (nextInter !== null) {\n if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;\n if (!nextSeg.isAnEndpoint(nextInter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, nextInter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n\n // For simplicity, even if we find more than one intersection we only\n // spilt on the 'earliest' (sweep-line style) of the intersections.\n // The other intersection will be handled in a future process().\n if (prevMySplitter !== null || nextMySplitter !== null) {\n let mySplitter = null;\n if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {\n const cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);\n mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;\n }\n\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n this.queue.remove(segment.rightSE);\n newEvents.push(segment.rightSE);\n const newEventsFromSplit = segment.split(mySplitter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (newEvents.length > 0) {\n // We found some intersections, so re-do the current event to\n // make sure sweep line ordering is totally consistent for later\n // use with the segment 'prev' pointers\n this.tree.remove(segment);\n newEvents.push(event);\n } else {\n // done with left event\n this.segments.push(segment);\n segment.prev = prevSeg;\n }\n } else {\n // event.isRight\n\n // since we're about to be removed from the sweep line, check for\n // intersections between our previous and next segments\n if (prevSeg && nextSeg) {\n const inter = prevSeg.getIntersection(nextSeg);\n if (inter !== null) {\n if (!prevSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(prevSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n if (!nextSeg.isAnEndpoint(inter)) {\n const newEventsFromSplit = this._splitSafely(nextSeg, inter);\n for (let i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {\n newEvents.push(newEventsFromSplit[i]);\n }\n }\n }\n }\n this.tree.remove(segment);\n }\n return newEvents;\n }\n\n /* Safely split a segment that is currently in the datastructures\n * IE - a segment other than the one that is currently being processed. */\n _splitSafely(seg, pt) {\n // Rounding errors can cause changes in ordering,\n // so remove afected segments and right sweep events before splitting\n // removeNode() doesn't work, so have re-find the seg\n // https://github.com/w8r/splay-tree/pull/5\n this.tree.remove(seg);\n const rightSE = seg.rightSE;\n this.queue.remove(rightSE);\n const newEvents = seg.split(pt);\n newEvents.push(rightSE);\n // splitting can trigger consumption\n if (seg.consumedBy === undefined) this.tree.add(seg);\n return newEvents;\n }\n}\n\n// Limits on iterative processes to prevent infinite loops - usually caused by floating-point math round-off errors.\nconst POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== \"undefined\" && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;\nconst POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== \"undefined\" && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;\nclass Operation {\n run(type, geom, moreGeoms) {\n operation.type = type;\n rounder.reset();\n\n /* Convert inputs to MultiPoly objects */\n const multipolys = [new MultiPolyIn(geom, true)];\n for (let i = 0, iMax = moreGeoms.length; i < iMax; i++) {\n multipolys.push(new MultiPolyIn(moreGeoms[i], false));\n }\n operation.numMultiPolys = multipolys.length;\n\n /* BBox optimization for difference operation\n * If the bbox of a multipolygon that's part of the clipping doesn't\n * intersect the bbox of the subject at all, we can just drop that\n * multiploygon. */\n if (operation.type === \"difference\") {\n // in place removal\n const subject = multipolys[0];\n let i = 1;\n while (i < multipolys.length) {\n if (getBboxOverlap(multipolys[i].bbox, subject.bbox) !== null) i++;else multipolys.splice(i, 1);\n }\n }\n\n /* BBox optimization for intersection operation\n * If we can find any pair of multipolygons whose bbox does not overlap,\n * then the result will be empty. */\n if (operation.type === \"intersection\") {\n // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,\n // it could be optimized to O(n * ln(n))\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const mpA = multipolys[i];\n for (let j = i + 1, jMax = multipolys.length; j < jMax; j++) {\n if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];\n }\n }\n }\n\n /* Put segment endpoints in a priority queue */\n const queue = new SplayTree(SweepEvent.compare);\n for (let i = 0, iMax = multipolys.length; i < iMax; i++) {\n const sweepEvents = multipolys[i].getSweepEvents();\n for (let j = 0, jMax = sweepEvents.length; j < jMax; j++) {\n queue.insert(sweepEvents[j]);\n if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when putting segment endpoints in a priority queue \" + \"(queue size too big).\");\n }\n }\n }\n\n /* Pass the sweep line over those endpoints */\n const sweepLine = new SweepLine(queue);\n let prevQueueSize = queue.size;\n let node = queue.pop();\n while (node) {\n const evt = node.key;\n if (queue.size === prevQueueSize) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n const seg = evt.segment;\n throw new Error(`Unable to pop() ${evt.isLeft ? \"left\" : \"right\"} SweepEvent ` + `[${evt.point.x}, ${evt.point.y}] from segment #${seg.id} ` + `[${seg.leftSE.point.x}, ${seg.leftSE.point.y}] -> ` + `[${seg.rightSE.point.x}, ${seg.rightSE.point.y}] from queue.`);\n }\n if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when passing sweep line over endpoints \" + \"(queue size too big).\");\n }\n if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {\n // prevents an infinite loop, an otherwise common manifestation of bugs\n throw new Error(\"Infinite loop when passing sweep line over endpoints \" + \"(too many sweep line segments).\");\n }\n const newEvents = sweepLine.process(evt);\n for (let i = 0, iMax = newEvents.length; i < iMax; i++) {\n const evt = newEvents[i];\n if (evt.consumedBy === undefined) queue.insert(evt);\n }\n prevQueueSize = queue.size;\n node = queue.pop();\n }\n\n // free some memory we don't need anymore\n rounder.reset();\n\n /* Collect and compile segments we're keeping into a multipolygon */\n const ringsOut = RingOut.factory(sweepLine.segments);\n const result = new MultiPolyOut(ringsOut);\n return result.getGeom();\n }\n}\n\n// singleton available by import\nconst operation = new Operation();\n\nconst union = function (geom) {\n for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n moreGeoms[_key - 1] = arguments[_key];\n }\n return operation.run(\"union\", geom, moreGeoms);\n};\nconst intersection = function (geom) {\n for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n moreGeoms[_key2 - 1] = arguments[_key2];\n }\n return operation.run(\"intersection\", geom, moreGeoms);\n};\nconst xor = function (geom) {\n for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n moreGeoms[_key3 - 1] = arguments[_key3];\n }\n return operation.run(\"xor\", geom, moreGeoms);\n};\nconst difference = function (subjectGeom) {\n for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n clippingGeoms[_key4 - 1] = arguments[_key4];\n }\n return operation.run(\"difference\", subjectGeom, clippingGeoms);\n};\nvar index = {\n union: union,\n intersection: intersection,\n xor: xor,\n difference: difference\n};\n\nexport { index as default };\n","import type { WsiRegionCoordinates } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiLinearRing = RoiCoordinate[];\nexport type RoiPolygonRings = RoiLinearRing[];\nexport type RoiMultiPolygon = RoiPolygonRings[];\nexport type RoiGeometry = RoiLinearRing | RoiPolygonRings | RoiMultiPolygon;\n\nexport function toRoiGeometry(coords: WsiRegionCoordinates | null | undefined): RoiGeometry | null | undefined;\nexport function toRoiGeometry(coords: unknown): RoiGeometry | null | undefined;\nexport function toRoiGeometry(coords: unknown): RoiGeometry | null | undefined {\n\tif (coords == null) return null;\n\tif (isLinearRing(coords) || isPolygonRings(coords) || isMultiPolygon(coords)) {\n\t\treturn coords;\n\t}\n\treturn null;\n}\n\nexport interface PreparedRoiPolygon {\n\touter: RoiLinearRing;\n\tholes: RoiLinearRing[];\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n\tarea: number;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is RoiCoordinate {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length >= 2 &&\n\t\tisFiniteNumber(value[0]) &&\n\t\tisFiniteNumber(value[1])\n\t);\n}\n\nfunction isLinearRing(value: unknown): value is RoiLinearRing {\n\treturn Array.isArray(value) && value.length > 0 && value.every(point => isCoordinatePair(point));\n}\n\nfunction isPolygonRings(value: unknown): value is RoiPolygonRings {\n\treturn Array.isArray(value) && value.length > 0 && value.every(ring => isLinearRing(ring));\n}\n\nfunction isMultiPolygon(value: unknown): value is RoiMultiPolygon {\n\treturn Array.isArray(value) && value.length > 0 && value.every(polygon => isPolygonRings(polygon));\n}\n\nexport function closeRoiRing(coordinates: readonly RoiCoordinate[]): RoiLinearRing {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out: RoiLinearRing = [];\n\tfor (const point of coordinates) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue;\n\t\tconst x = Number(point[0]);\n\t\tconst y = Number(point[1]);\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n\t\tconst prev = out[out.length - 1];\n\t\tif (prev && prev[0] === x && prev[1] === y) continue;\n\t\tout.push([x, y]);\n\t}\n\tif (out.length < 3) return [];\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out.length >= 4 ? out : [];\n}\n\nexport function polygonSignedArea(ring: RoiLinearRing): number {\n\tif (!Array.isArray(ring) || ring.length < 4) return 0;\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst a = ring[i];\n\t\tconst b = ring[i + 1];\n\t\tsum += a[0] * b[1] - b[0] * a[1];\n\t}\n\treturn sum * 0.5;\n}\n\nfunction normalizePolygonRings(rings: RoiPolygonRings): RoiPolygonRings {\n\tif (!Array.isArray(rings) || rings.length === 0) return [];\n\tconst normalized: RoiLinearRing[] = [];\n\tfor (const ring of rings) {\n\t\tconst closed = closeRoiRing(ring);\n\t\tif (closed.length >= 4) normalized.push(closed);\n\t}\n\tif (normalized.length === 0) return [];\n\tif (normalized.length === 1) return [normalized[0]];\n\n\tlet outerIndex = 0;\n\tlet outerArea = 0;\n\tfor (let i = 0; i < normalized.length; i += 1) {\n\t\tconst area = Math.abs(polygonSignedArea(normalized[i]));\n\t\tif (area <= outerArea) continue;\n\t\touterArea = area;\n\t\touterIndex = i;\n\t}\n\n\tconst out: RoiPolygonRings = [normalized[outerIndex]];\n\tfor (let i = 0; i < normalized.length; i += 1) {\n\t\tif (i === outerIndex) continue;\n\t\tout.push(normalized[i]);\n\t}\n\treturn out;\n}\n\nexport function normalizeRoiGeometry(geometry: RoiGeometry | null | undefined): RoiMultiPolygon {\n\tif (!Array.isArray(geometry) || geometry.length === 0) return [];\n\n\tconst first = geometry[0];\n\tif (isCoordinatePair(first)) {\n\t\tconst polygon = normalizePolygonRings([geometry as RoiLinearRing]);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (!Array.isArray(first) || first.length === 0) return [];\n\tconst second = first[0];\n\tif (isCoordinatePair(second)) {\n\t\tconst polygon = normalizePolygonRings(geometry as RoiPolygonRings);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (!Array.isArray(second) || second.length === 0 || !isCoordinatePair(second[0])) {\n\t\treturn [];\n\t}\n\n\tconst out: RoiMultiPolygon = [];\n\tfor (const polygon of geometry as RoiMultiPolygon) {\n\t\tconst normalized = normalizePolygonRings(polygon);\n\t\tif (normalized.length > 0) out.push(normalized);\n\t}\n\treturn out;\n}\n\nexport function pointInRing(x: number, y: number, ring: RoiLinearRing): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tif (yi === yj) continue;\n\t\tif ((yi > y) === (yj > y)) continue;\n\t\tconst intersect = x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nexport function pointInPolygonWithHoles(\n\tx: number,\n\ty: number,\n\tpolygon: RoiPolygonRings,\n): boolean {\n\tif (!Array.isArray(polygon) || polygon.length === 0) return false;\n\tconst outer = polygon[0];\n\tif (!outer || outer.length < 4) return false;\n\tif (!pointInRing(x, y, outer)) return false;\n\tfor (let i = 1; i < polygon.length; i += 1) {\n\t\tconst hole = polygon[i];\n\t\tif (!hole || hole.length < 4) continue;\n\t\tif (pointInRing(x, y, hole)) return false;\n\t}\n\treturn true;\n}\n\nexport function prepareRoiPolygons(\n\tgeometries: readonly (RoiGeometry | null | undefined)[] | null | undefined,\n): PreparedRoiPolygon[] {\n\tconst prepared: PreparedRoiPolygon[] = [];\n\tfor (const geometry of geometries ?? []) {\n\t\tconst multipolygon = normalizeRoiGeometry(geometry);\n\t\tfor (const polygon of multipolygon) {\n\t\t\tconst outer = polygon[0];\n\t\t\tif (!outer || outer.length < 4) continue;\n\t\t\tlet minX = Infinity;\n\t\t\tlet minY = Infinity;\n\t\t\tlet maxX = -Infinity;\n\t\t\tlet maxY = -Infinity;\n\t\t\tfor (const [x, y] of outer) {\n\t\t\t\tif (x < minX) minX = x;\n\t\t\t\tif (x > maxX) maxX = x;\n\t\t\t\tif (y < minY) minY = y;\n\t\t\t\tif (y > maxY) maxY = y;\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!Number.isFinite(minX) ||\n\t\t\t\t!Number.isFinite(minY) ||\n\t\t\t\t!Number.isFinite(maxX) ||\n\t\t\t\t!Number.isFinite(maxY)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet area = Math.abs(polygonSignedArea(outer));\n\t\t\tfor (let i = 1; i < polygon.length; i += 1) {\n\t\t\t\tarea -= Math.abs(polygonSignedArea(polygon[i]));\n\t\t\t}\n\t\t\tprepared.push({\n\t\t\t\touter,\n\t\t\t\tholes: polygon.slice(1),\n\t\t\t\tminX,\n\t\t\t\tminY,\n\t\t\t\tmaxX,\n\t\t\t\tmaxY,\n\t\t\t\tarea: Math.max(1e-6, area),\n\t\t\t});\n\t\t}\n\t}\n\treturn prepared;\n}\n\nexport function pointInPreparedPolygon(\n\tx: number,\n\ty: number,\n\tpolygon: PreparedRoiPolygon,\n): boolean {\n\tif (x < polygon.minX || x > polygon.maxX || y < polygon.minY || y > polygon.maxY) {\n\t\treturn false;\n\t}\n\tif (!pointInRing(x, y, polygon.outer)) return false;\n\tfor (const hole of polygon.holes) {\n\t\tif (pointInRing(x, y, hole)) return false;\n\t}\n\treturn true;\n}\n\nexport function pointInAnyPreparedPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: readonly PreparedRoiPolygon[],\n): boolean {\n\tfor (const polygon of polygons) {\n\t\tif (!pointInPreparedPolygon(x, y, polygon)) continue;\n\t\treturn true;\n\t}\n\treturn false;\n}\n","export const DEFAULT_POINT_COLOR: [number, number, number, number] = [\n\t160, 160, 160, 255,\n];\n","import { DEFAULT_POINT_COLOR } from \"./constants\";\nimport type { ClassPalette, WsiPointData, WsiViewState } from \"./types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nexport function calcScaleResolution(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst z0 = Number(imageZoom);\n\tconst z1 = Number(currentZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 1;\n\tif (!Number.isFinite(z0) || !Number.isFinite(z1)) return mpp;\n\treturn Math.pow(2, z0 - z1) * mpp;\n}\n\nexport function calcViewingMagnification(\n\timageMpp: number,\n\tviewZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst zoom = Number(viewZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 0;\n\tif (!Number.isFinite(zoom) || zoom <= 0) return 0;\n\treturn zoom * (10 / mpp);\n}\n\nexport function calcScaleLength(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): string {\n\tconst resolution = calcScaleResolution(imageMpp, imageZoom, currentZoom);\n\tlet length = 100 * resolution;\n\tif (Number(imageMpp)) {\n\t\tlet unit = \"μm\";\n\t\tif (length > 1000) {\n\t\t\tlength /= 1000;\n\t\t\tunit = \"mm\";\n\t\t}\n\t\treturn `${length.toPrecision(3)} ${unit}`;\n\t}\n\treturn `${Math.round(length * 1000) / 1000} pixels`;\n}\n\nexport function nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nexport function sanitizePointCount(pointData: WsiPointData): number {\n\tconst fillModesLength =\n\t\tpointData.fillModes instanceof Uint8Array\n\t\t\t? pointData.fillModes.length\n\t\t\t: Number.MAX_SAFE_INTEGER;\n\treturn Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData.count ?? 0),\n\t\t\tMath.floor((pointData.positions?.length ?? 0) / 2),\n\t\t\tpointData.paletteIndices?.length ?? 0,\n\t\t\tfillModesLength,\n\t\t),\n\t);\n}\n\nexport function isSameViewState(\n\ta: Partial<WsiViewState> | null | undefined,\n\tb: Partial<WsiViewState> | null | undefined,\n): boolean {\n\tif (!a && !b) return true;\n\tif (!a || !b) return false;\n\treturn (\n\t\tMath.abs((a.zoom ?? 0) - (b.zoom ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetX ?? 0) - (b.offsetX ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetY ?? 0) - (b.offsetY ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.rotationDeg ?? 0) - (b.rotationDeg ?? 0)) < 1e-6\n\t);\n}\n\nexport function toBearerToken(value: string | null | undefined): string {\n\tconst trimmed = String(value ?? \"\").trim();\n\tif (!trimmed) return \"\";\n\tif (/^bearer\\s+/i.test(trimmed)) {\n\t\tconst token = trimmed.replace(/^bearer\\s+/i, \"\").trim();\n\t\treturn token ? `Bearer ${token}` : \"\";\n\t}\n\treturn `Bearer ${trimmed}`;\n}\n\nexport function hexToRgba(\n\thex: string | null | undefined,\n): [number, number, number, number] {\n\tconst value = String(hex ?? \"\").trim();\n\tconst match = value.match(/^#?([0-9a-fA-F]{6})$/);\n\tif (!match) return [...DEFAULT_POINT_COLOR];\n\n\tconst n = Number.parseInt(match[1], 16);\n\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n}\n\nexport function parseHexColorToRgba(\n\tvalue: string | null | undefined,\n\tfallback: [number, number, number, number],\n): [number, number, number, number] {\n\tconst input = String(value ?? \"\").trim();\n\tif (!input) return [...fallback];\n\n\tconst hexMatch = input.match(/^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);\n\tif (hexMatch) {\n\t\tconst hex = hexMatch[1].length === 3 ? hexMatch[1].split(\"\").map(ch => ch + ch).join(\"\") : hexMatch[1];\n\t\tconst n = Number.parseInt(hex, 16);\n\t\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n\t}\n\n\treturn [...fallback];\n}\n\nfunction resolvePaletteClassKey(\n\titem:\n\t\t| { classId?: string | null; className?: string | null }\n\t\t| null\n\t\t| undefined,\n): string {\n\tconst classId = String(item?.classId ?? \"\").trim();\n\tif (classId) return classId;\n\treturn String(item?.className ?? \"\").trim();\n}\n\nexport function buildClassPalette(\n\tclasses:\n\t\t| Array<{ classId?: string | null; className?: string | null; classColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): ClassPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst classToPaletteIndex = new Map<string, number>();\n\n\tfor (const item of classes ?? []) {\n\t\tconst classKey = resolvePaletteClassKey(item);\n\t\tif (!classKey || classToPaletteIndex.has(classKey)) continue;\n\n\t\tclassToPaletteIndex.set(classKey, palette.length);\n\t\tpalette.push(hexToRgba(item?.classColor));\n\t}\n\n\tconst colors = new Uint8Array(palette.length * 4);\n\tfor (let i = 0; i < palette.length; i += 1) {\n\t\tcolors[i * 4] = palette[i][0];\n\t\tcolors[i * 4 + 1] = palette[i][1];\n\t\tcolors[i * 4 + 2] = palette[i][2];\n\t\tcolors[i * 4 + 3] = palette[i][3];\n\t}\n\n\treturn { colors, classToPaletteIndex };\n}\n","import polygonClipping from \"polygon-clipping\"\nimport { closeRoiRing as closeRing, polygonSignedArea } from \"./roi-geometry\"\nimport { clamp } from \"./utils\"\n\nexport type BrushStrokeCoordinate = [number, number]\nexport type BrushStrokeBounds = [number, number, number, number]\n\nexport interface BrushStrokePolygonOptions {\n\tradius: number\n\tclipBounds?: BrushStrokeBounds\n\tminRasterStep?: number\n\tmaxRasterPixels?: number\n\tmaxRasterSize?: number\n\tsimplifyTolerance?: number\n\tcircleSides?: number\n\tsmoothingPasses?: number\n}\n\nconst ROUND_PRECISIONS = [6, 4, 2] as const\nconst DEFAULT_CIRCLE_SIDES = 64\nconst DEFAULT_SIMPLIFY_FACTOR = 0.04\nconst DEFAULT_SMOOTHING_PASSES = 1\nconst MAX_SMOOTHING_PASSES = 4\nconst MIN_RADIUS = 1e-6\nconst MIN_TUNNEL_LENGTH_FACTOR = 0.1\n\nfunction sanitizePath(points: BrushStrokeCoordinate[]): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(points) || points.length === 0) return []\n\tconst out: BrushStrokeCoordinate[] = []\n\tfor (const point of points) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue\n\t\tconst x = Number(point[0])\n\t\tconst y = Number(point[1])\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue\n\t\tconst prev = out[out.length - 1]\n\t\tif (prev && Math.abs(prev[0] - x) < 1e-9 && Math.abs(prev[1] - y) < 1e-9) {\n\t\t\tcontinue\n\t\t}\n\t\tout.push([x, y])\n\t}\n\treturn out\n}\n\nfunction createCircleRing(center: BrushStrokeCoordinate, radius: number, sides: number): BrushStrokeCoordinate[] {\n\tif (radius <= MIN_RADIUS || sides < 8) return []\n\tconst ring: BrushStrokeCoordinate[] = []\n\tfor (let i = 0; i <= sides; i += 1) {\n\t\tconst t = (i / sides) * Math.PI * 2\n\t\tring.push([center[0] + Math.cos(t) * radius, center[1] + Math.sin(t) * radius])\n\t}\n\treturn closeRing(ring)\n}\n\nfunction createTunnelRing(\n\tstart: BrushStrokeCoordinate,\n\tend: BrushStrokeCoordinate,\n\tradius: number,\n\tminLength: number,\n): BrushStrokeCoordinate[] {\n\tconst dx = end[0] - start[0]\n\tconst dy = end[1] - start[1]\n\tconst length = Math.sqrt(dx * dx + dy * dy)\n\tif (!Number.isFinite(length) || length <= minLength) return []\n\n\tconst ux = dx / length\n\tconst uy = dy / length\n\tconst perpX = -uy\n\tconst perpY = ux\n\tconst r = Math.max(MIN_RADIUS, radius)\n\treturn closeRing([\n\t\t[start[0] + perpX * r, start[1] + perpY * r],\n\t\t[end[0] + perpX * r, end[1] + perpY * r],\n\t\t[end[0] - perpX * r, end[1] - perpY * r],\n\t\t[start[0] - perpX * r, start[1] - perpY * r],\n\t])\n}\n\nfunction createBoundsFallback(points: BrushStrokeCoordinate[], radius: number): BrushStrokeCoordinate[] {\n\tif (!points.length) return []\n\tlet minX = Infinity\n\tlet minY = Infinity\n\tlet maxX = -Infinity\n\tlet maxY = -Infinity\n\tfor (const [x, y] of points) {\n\t\tif (x < minX) minX = x\n\t\tif (x > maxX) maxX = x\n\t\tif (y < minY) minY = y\n\t\tif (y > maxY) maxY = y\n\t}\n\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) return []\n\tconst pad = Math.max(radius, 1)\n\treturn closeRing([\n\t\t[minX - pad, minY - pad],\n\t\t[maxX + pad, minY - pad],\n\t\t[maxX + pad, maxY + pad],\n\t\t[minX - pad, maxY + pad],\n\t])\n}\n\nfunction clampRingToBounds(\n\tring: BrushStrokeCoordinate[],\n\tbounds: BrushStrokeBounds | undefined,\n): BrushStrokeCoordinate[] {\n\tif (!bounds) return closeRing(ring)\n\treturn closeRing(\n\t\tring.map(([x, y]) => [\n\t\t\tclamp(x, bounds[0], bounds[2]),\n\t\t\tclamp(y, bounds[1], bounds[3]),\n\t\t] as BrushStrokeCoordinate),\n\t)\n}\n\nfunction round(value: number, precision: number): number {\n\tif (!Number.isFinite(value)) return value\n\treturn Number(value.toFixed(precision))\n}\n\nfunction sanitizeRing(ring: polygonClipping.Ring, precision: number): polygonClipping.Ring {\n\tif (!Array.isArray(ring) || ring.length === 0) return []\n\tconst sanitized: polygonClipping.Ring = []\n\tfor (const point of ring) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue\n\t\tconst x = round(Number(point[0]), precision)\n\t\tconst y = round(Number(point[1]), precision)\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue\n\t\tconst prev = sanitized[sanitized.length - 1]\n\t\tif (!prev || prev[0] !== x || prev[1] !== y) {\n\t\t\tsanitized.push([x, y])\n\t\t}\n\t}\n\n\tif (sanitized.length >= 2) {\n\t\tconst first = sanitized[0]\n\t\tconst last = sanitized[sanitized.length - 1]\n\t\tif (!first || !last) return []\n\t\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\t\tsanitized.push([first[0], first[1]])\n\t\t}\n\t}\n\n\treturn sanitized.length >= 4 ? sanitized : []\n}\n\nfunction sanitizePolygon(polygon: polygonClipping.Polygon, precision: number): polygonClipping.Polygon {\n\tif (!Array.isArray(polygon) || polygon.length === 0) return []\n\tconst rings = polygon\n\t\t.map(ring => sanitizeRing(ring, precision))\n\t\t.filter(ring => ring.length >= 4)\n\treturn rings.length > 0 ? rings : []\n}\n\nfunction tryUnionWithPrecision(\n\tpolygons: polygonClipping.Polygon[],\n\tprecision: number,\n): polygonClipping.MultiPolygon | null {\n\tconst sanitized = polygons\n\t\t.map(polygon => sanitizePolygon(polygon, precision))\n\t\t.filter(polygon => polygon.length > 0)\n\tif (sanitized.length === 0) return null\n\n\tlet current: polygonClipping.MultiPolygon = [sanitized[0]]\n\ttry {\n\t\tfor (let i = 1; i < sanitized.length; i += 1) {\n\t\t\tcurrent = polygonClipping.union(current, [sanitized[i]])\n\t\t\tif (!Array.isArray(current) || current.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\t/* biome-ignore lint/suspicious/noConsole: fallback logging for polygon union */\n\t\tconsole.error(\"buildBrushStrokePolygon union failed\", precision, error)\n\t\treturn null\n\t}\n\n\treturn current.length > 0 ? current : null\n}\n\nfunction unionPolygons(polygons: polygonClipping.Polygon[]): polygonClipping.MultiPolygon | null {\n\tif (polygons.length === 0) return null\n\tfor (const precision of ROUND_PRECISIONS) {\n\t\tconst result = tryUnionWithPrecision(polygons, precision)\n\t\tif (result) return result\n\t}\n\treturn null\n}\n\nfunction toBrushRing(ring: polygonClipping.Ring): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(ring) || ring.length === 0) return []\n\tconst out: BrushStrokeCoordinate[] = []\n\tfor (const point of ring) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue\n\t\tconst x = Number(point[0])\n\t\tconst y = Number(point[1])\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue\n\t\tout.push([x, y])\n\t}\n\treturn closeRing(out)\n}\n\nfunction selectLargestOuterRing(multiPolygon: polygonClipping.MultiPolygon): BrushStrokeCoordinate[] {\n\tlet best: BrushStrokeCoordinate[] = []\n\tlet bestArea = 0\n\tfor (const polygon of multiPolygon) {\n\t\tif (!Array.isArray(polygon) || polygon.length === 0) continue\n\t\tconst outer = toBrushRing(polygon[0] ?? [])\n\t\tif (outer.length < 4) continue\n\t\tconst area = Math.abs(polygonSignedArea(outer))\n\t\tif (area <= bestArea) continue\n\t\tbestArea = area\n\t\tbest = outer\n\t}\n\treturn best\n}\n\nfunction removeCollinearVertices(\n\tring: BrushStrokeCoordinate[],\n\tepsilon = 1e-9,\n): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring)\n\tif (closed.length < 5) return closed\n\tconst out: BrushStrokeCoordinate[] = [closed[0]]\n\tfor (let i = 1; i < closed.length - 1; i += 1) {\n\t\tconst prev = out[out.length - 1]\n\t\tconst curr = closed[i]\n\t\tconst next = closed[i + 1]\n\t\tconst cross =\n\t\t\t(curr[0] - prev[0]) * (next[1] - curr[1]) -\n\t\t\t(curr[1] - prev[1]) * (next[0] - curr[0])\n\t\tif (Math.abs(cross) <= epsilon) continue\n\t\tout.push(curr)\n\t}\n\tout.push(out[0])\n\treturn closeRing(out)\n}\n\nfunction pointLineDistanceSquared(\n\tp: BrushStrokeCoordinate,\n\ta: BrushStrokeCoordinate,\n\tb: BrushStrokeCoordinate,\n): number {\n\tconst abx = b[0] - a[0]\n\tconst aby = b[1] - a[1]\n\tconst len2 = abx * abx + aby * aby\n\tif (len2 <= 1e-12) {\n\t\tconst dx = p[0] - a[0]\n\t\tconst dy = p[1] - a[1]\n\t\treturn dx * dx + dy * dy\n\t}\n\tconst t = clamp(\n\t\t((p[0] - a[0]) * abx + (p[1] - a[1]) * aby) / len2,\n\t\t0,\n\t\t1,\n\t)\n\tconst x = a[0] + abx * t\n\tconst y = a[1] + aby * t\n\tconst dx = p[0] - x\n\tconst dy = p[1] - y\n\treturn dx * dx + dy * dy\n}\n\nfunction simplifyRdp(points: BrushStrokeCoordinate[], tolerance: number): BrushStrokeCoordinate[] {\n\tif (points.length <= 2 || tolerance <= 0) return points.slice()\n\n\tconst keep = new Uint8Array(points.length)\n\tkeep[0] = 1\n\tkeep[points.length - 1] = 1\n\tconst tolerance2 = tolerance * tolerance\n\tconst stack: Array<[number, number]> = [[0, points.length - 1]]\n\n\twhile (stack.length > 0) {\n\t\tconst next = stack.pop()\n\t\tif (!next) break\n\t\tconst [start, end] = next\n\t\tif (end - start <= 1) continue\n\n\t\tlet maxDist2 = 0\n\t\tlet split = -1\n\t\tfor (let i = start + 1; i < end; i += 1) {\n\t\t\tconst dist2 = pointLineDistanceSquared(points[i], points[start], points[end])\n\t\t\tif (dist2 > maxDist2) {\n\t\t\t\tmaxDist2 = dist2\n\t\t\t\tsplit = i\n\t\t\t}\n\t\t}\n\n\t\tif (split >= 0 && maxDist2 > tolerance2) {\n\t\t\tkeep[split] = 1\n\t\t\tstack.push([start, split], [split, end])\n\t\t}\n\t}\n\n\tconst out: BrushStrokeCoordinate[] = []\n\tfor (let i = 0; i < points.length; i += 1) {\n\t\tif (keep[i]) out.push(points[i])\n\t}\n\treturn out\n}\n\nfunction simplifyClosedRing(ring: BrushStrokeCoordinate[], tolerance: number): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring)\n\tif (closed.length < 5 || tolerance <= 0) return closed\n\tconst open = closed.slice(0, -1)\n\tconst simplified = simplifyRdp(open, tolerance)\n\tif (simplified.length < 3) return closed\n\treturn closeRing(simplified)\n}\n\nfunction smoothClosedRingChaikin(\n\tring: BrushStrokeCoordinate[],\n\titerations: number,\n): BrushStrokeCoordinate[] {\n\tlet out = closeRing(ring)\n\tif (iterations <= 0 || out.length < 5) return out\n\n\tfor (let pass = 0; pass < iterations; pass += 1) {\n\t\tconst open = out.slice(0, -1)\n\t\tif (open.length < 3) break\n\t\tconst next: BrushStrokeCoordinate[] = []\n\t\tfor (let i = 0; i < open.length; i += 1) {\n\t\t\tconst a = open[i]\n\t\t\tconst b = open[(i + 1) % open.length]\n\t\t\tnext.push(\n\t\t\t\t[a[0] * 0.75 + b[0] * 0.25, a[1] * 0.75 + b[1] * 0.25],\n\t\t\t\t[a[0] * 0.25 + b[0] * 0.75, a[1] * 0.25 + b[1] * 0.75],\n\t\t\t)\n\t\t}\n\t\tout = closeRing(next)\n\t}\n\treturn out\n}\n\nexport function buildBrushStrokePolygon(\n\tpath: BrushStrokeCoordinate[],\n\toptions: BrushStrokePolygonOptions,\n): BrushStrokeCoordinate[] {\n\tconst points = sanitizePath(path)\n\tconst radius = Math.max(MIN_RADIUS, Number(options.radius) || 0)\n\tif (points.length === 0 || !Number.isFinite(radius)) return []\n\n\tconst circleSides = Math.max(12, Math.floor(options.circleSides || DEFAULT_CIRCLE_SIDES))\n\tif (points.length === 1) {\n\t\treturn clampRingToBounds(createCircleRing(points[0], radius, circleSides), options.clipBounds)\n\t}\n\n\tconst polygons: polygonClipping.Polygon[] = []\n\tconst minTunnelLength = Math.max(MIN_RADIUS, radius * MIN_TUNNEL_LENGTH_FACTOR)\n\tfor (let i = 0; i < points.length; i += 1) {\n\t\tconst center = points[i]\n\t\tconst circle = createCircleRing(center, radius, circleSides)\n\t\tif (circle.length >= 4) {\n\t\t\tpolygons.push([circle])\n\t\t}\n\t\tif (i === 0) continue\n\t\tconst tunnel = createTunnelRing(points[i - 1], center, radius, minTunnelLength)\n\t\tif (tunnel.length >= 4) {\n\t\t\tpolygons.push([tunnel])\n\t\t}\n\t}\n\n\tconst unioned = unionPolygons(polygons)\n\tconst unionRing = unioned ? selectLargestOuterRing(unioned) : []\n\tif (!unionRing.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds)\n\t}\n\n\tconst tolerance =\n\t\ttypeof options.simplifyTolerance === \"number\" && Number.isFinite(options.simplifyTolerance)\n\t\t\t? Math.max(0, options.simplifyTolerance)\n\t\t\t: Math.max(0.25, radius * DEFAULT_SIMPLIFY_FACTOR)\n\tconst smoothingPasses =\n\t\ttypeof options.smoothingPasses === \"number\" && Number.isFinite(options.smoothingPasses)\n\t\t\t? Math.round(clamp(options.smoothingPasses, 0, MAX_SMOOTHING_PASSES))\n\t\t\t: DEFAULT_SMOOTHING_PASSES\n\n\tconst optimized = simplifyClosedRing(\n\t\tsmoothClosedRingChaikin(\n\t\t\tremoveCollinearVertices(unionRing, 1e-9),\n\t\t\tsmoothingPasses,\n\t\t),\n\t\ttolerance,\n\t)\n\n\tif (optimized.length < 4) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds)\n\t}\n\treturn clampRingToBounds(optimized, options.clipBounds)\n}\n","function readDevicePixelRatio(): number {\n if (typeof window === \"undefined\") return 1;\n const raw = window.devicePixelRatio || 1;\n return Number.isFinite(raw) && raw > 0 ? raw : 1;\n}\n\nexport interface DevicePixelRatioChangeEvent {\n previousDpr: number;\n nextDpr: number;\n trigger: \"match-media\" | \"window-resize\" | \"visual-viewport-resize\";\n}\n\nexport function observeDevicePixelRatioChanges(onChange: (event: DevicePixelRatioChangeEvent) => void): () => void {\n if (typeof window === \"undefined\") {\n return () => {\n // noop\n };\n }\n\n let active = true;\n let lastDpr = readDevicePixelRatio();\n let mediaQuery: MediaQueryList | null = null;\n let removeMediaQueryListener: (() => void) | null = null;\n\n const unbindMediaQuery = () => {\n removeMediaQueryListener?.();\n removeMediaQueryListener = null;\n mediaQuery = null;\n };\n\n const bindMediaQuery = () => {\n unbindMediaQuery();\n mediaQuery = window.matchMedia(`(resolution: ${lastDpr}dppx)`);\n const handleMediaQueryChange = () => {\n emitIfChanged(\"match-media\");\n };\n if (typeof mediaQuery.addEventListener === \"function\") {\n mediaQuery.addEventListener(\"change\", handleMediaQueryChange);\n removeMediaQueryListener = () => mediaQuery?.removeEventListener(\"change\", handleMediaQueryChange);\n return;\n }\n mediaQuery.addListener(handleMediaQueryChange);\n removeMediaQueryListener = () => mediaQuery?.removeListener(handleMediaQueryChange);\n };\n\n const emitIfChanged = (trigger: DevicePixelRatioChangeEvent[\"trigger\"]) => {\n if (!active) return;\n const nextDpr = readDevicePixelRatio();\n if (Math.abs(nextDpr - lastDpr) <= 1e-4) return;\n const previousDpr = lastDpr;\n lastDpr = nextDpr;\n bindMediaQuery();\n onChange({ previousDpr, nextDpr, trigger });\n };\n\n const handleWindowResize = () => emitIfChanged(\"window-resize\");\n const handleVisualViewportResize = () => emitIfChanged(\"visual-viewport-resize\");\n\n bindMediaQuery();\n window.addEventListener(\"resize\", handleWindowResize);\n window.visualViewport?.addEventListener(\"resize\", handleVisualViewportResize);\n\n return () => {\n active = false;\n unbindMediaQuery();\n window.removeEventListener(\"resize\", handleWindowResize);\n window.visualViewport?.removeEventListener(\"resize\", handleVisualViewportResize);\n };\n}\n","import type { CSSProperties, MutableRefObject, RefObject } from \"react\";\n\nexport type StampDrawTool =\n | \"stamp-rectangle\"\n | \"stamp-circle\"\n | \"stamp-rectangle-4096px\"\n | \"stamp-rectangle-2mm2\"\n | \"stamp-circle-2mm2\"\n | \"stamp-circle-hpf-0.2mm2\";\n\nexport type StampShape = \"rectangle\" | \"circle\";\n\nexport interface StampToolConfig {\n shape: StampShape;\n areaMm2?: number;\n pixelSize?: number;\n}\n\nexport type DrawTool =\n | \"cursor\"\n | \"freehand\"\n | \"rectangle\"\n | \"circular\"\n | \"brush\"\n | \"eraser\"\n | \"region-brush\"\n | \"region-eraser\"\n | StampDrawTool\n | { stamp: StampToolConfig };\n\nexport type DrawCoordinate = [number, number];\n\nexport type DrawBounds = [number, number, number, number];\nexport type DrawRegionCoordinates = DrawCoordinate[] | DrawCoordinate[][] | DrawCoordinate[][][];\n\nexport type DrawIntent = \"roi\" | \"patch\" | \"brush\";\n\nexport interface DrawResult {\n tool: Exclude<DrawTool, \"cursor\">;\n intent: DrawIntent;\n coordinates: DrawCoordinate[];\n bbox: DrawBounds;\n areaPx: number;\n}\n\nexport type PatchDrawResult = DrawResult & {\n tool: \"stamp-rectangle-4096px\";\n intent: \"patch\";\n};\n\nexport interface DrawRegion {\n id?: string | number;\n coordinates: DrawRegionCoordinates;\n label?: string;\n}\n\nexport interface RegionStyleContext {\n region: DrawRegion;\n regionId: string | number;\n regionIndex: number;\n state: \"default\" | \"hover\" | \"active\";\n}\n\nexport type RegionStrokeStyleResolver = (context: RegionStyleContext) => Partial<RegionStrokeStyle> | null | undefined;\n\nexport interface RegionLabelStyleContext {\n region: DrawRegion;\n regionId: string | number;\n regionIndex: number;\n zoom: number;\n}\n\nexport type RegionLabelStyleResolver = (context: RegionLabelStyleContext) => Partial<RegionLabelStyle> | null | undefined;\n\nexport type DrawOverlayCoordinates = DrawCoordinate[] | DrawCoordinate[][] | DrawCoordinate[][][];\n\nexport interface DrawOverlayShape {\n id?: string | number;\n coordinates: DrawOverlayCoordinates;\n closed?: boolean;\n fill?: boolean;\n stroke?: Partial<RegionStrokeStyle>;\n strokeStyle?: Partial<RegionStrokeStyle>;\n invertedFill?: DrawOverlayInvertedFillStyle;\n visible?: boolean;\n}\n\nexport interface DrawOverlayInvertedFillStyle {\n fillColor: string;\n}\n\nexport interface RegionStrokeStyle {\n color: string;\n width: number;\n lineDash: number[];\n lineJoin: CanvasLineJoin;\n lineCap: CanvasLineCap;\n shadowColor: string;\n shadowBlur: number;\n shadowOffsetX: number;\n shadowOffsetY: number;\n}\n\nexport interface RegionLabelStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: string | number;\n textColor: string;\n backgroundColor: string;\n borderColor: string;\n borderWidth: number;\n paddingX: number;\n paddingY: number;\n offsetY: number;\n borderRadius: number;\n}\n\nexport type RegionLabelAnchorMode = \"top-center\" | \"top-left\";\n\nexport interface DrawAreaTooltipStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: string | number;\n textColor: string;\n backgroundColor: string;\n borderRadius: number;\n paddingX: number;\n paddingY: number;\n}\n\nexport interface DrawAreaTooltipOptions {\n enabled?: boolean;\n format?: (areaMm2: number) => string;\n style?: Partial<DrawAreaTooltipStyle>;\n cursorOffset?: {\n x: number;\n y: number;\n };\n}\n\nexport interface DrawProjector {\n screenToWorld(clientX: number, clientY: number): DrawCoordinate | number[];\n worldToScreen(worldX: number, worldY: number): DrawCoordinate | number[];\n getViewState?: () => { zoom: number; rotationDeg?: number };\n getZoomRange?: () => { minZoom: number; maxZoom: number };\n getRegionLabelAutoLiftCapZoom?: () => number;\n handleWheelZoom?: (deltaY: number, screenX: number, screenY: number) => void;\n zoomBy?: (factor: number, screenX: number, screenY: number) => void;\n}\n\nexport interface StampOptions {\n rectangleAreaMm2?: number;\n circleAreaMm2?: number;\n rectanglePixelSize?: number;\n}\n\nexport interface BrushOptions {\n radius: number;\n edgeDetail?: number;\n edgeSmoothing?: number;\n clickSelectRoi?: boolean;\n fillColor?: string;\n fillOpacity?: number;\n cursorColor?: string;\n cursorActiveColor?: string;\n cursorLineWidth?: number;\n cursorLineDash?: number[];\n}\n\nexport interface DrawLayerProps {\n tool: DrawTool;\n imageWidth: number;\n imageHeight: number;\n imageMpp?: number;\n imageZoom?: number;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n projectorRef: RefObject<DrawProjector | null>;\n onBrushTap?: (coordinate: DrawCoordinate) => boolean;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n enabled?: boolean;\n viewStateSignal?: unknown;\n persistedRegions?: DrawRegion[];\n patchRegions?: DrawRegion[];\n persistedPolygons?: DrawRegionCoordinates[];\n drawFillColor?: string;\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n resolveRegionLabelStyle?: RegionLabelStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n regionLabelStyle?: Partial<RegionLabelStyle>;\n drawAreaTooltip?: DrawAreaTooltipOptions;\n autoLiftRegionLabelAtMaxZoom?: boolean;\n regionLabelAnchor?: RegionLabelAnchorMode;\n clampRegionLabelToViewport?: boolean;\n regionLabelAutoLiftOffsetPx?: number;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\nexport interface DrawSession {\n isDrawing: boolean;\n pointerId: number | null;\n start: DrawCoordinate | null;\n current: DrawCoordinate | null;\n cursor: DrawCoordinate | null;\n cursorScreen: DrawCoordinate | null;\n points: DrawCoordinate[];\n screenPoints: DrawCoordinate[];\n stampCenter: DrawCoordinate | null;\n}\n\nexport interface NormalizedDrawRegionPolygon {\n outer: DrawCoordinate[];\n holes: DrawCoordinate[][];\n}\n\nexport interface PreparedRenderedRegion {\n region: DrawRegion;\n regionIndex: number;\n regionKey: string | number;\n polygons: NormalizedDrawRegionPolygon[];\n}\n\nexport interface ResolvedBrushOptions {\n radius: number;\n edgeDetail: number;\n edgeSmoothing: number;\n clickSelectRoi: boolean;\n fillColor: string;\n fillOpacity: number;\n cursorColor: string;\n cursorActiveColor: string;\n cursorLineWidth: number;\n cursorLineDash: number[];\n}\n\nexport interface ResolvedDrawAreaTooltipOptions {\n enabled: boolean;\n format: (areaMm2: number) => string;\n style: DrawAreaTooltipStyle;\n cursorOffsetX: number;\n cursorOffsetY: number;\n}\n\nexport const EMPTY_DASH: number[] = [];\nexport const EMPTY_REGIONS: DrawRegion[] = [];\n\nexport const DEFAULT_REGION_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#ff4d4f\",\n width: 2,\n lineDash: EMPTY_DASH,\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nexport const DEFAULT_PATCH_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#4cc9f0\",\n width: 2,\n lineDash: [10, 8],\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nexport const REGION_INTERACTION_SHADOW_COLOR = \"rgba(23, 23, 25, 0.1)\";\nexport const REGION_INTERACTION_SHADOW_WIDTH = 6;\n\nexport const DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n fontFamily: \"Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: 11,\n fontWeight: 600,\n textColor: \"#171719\",\n backgroundColor: \"#FFCC00\",\n borderColor: \"rgba(0, 0, 0, 0)\",\n borderWidth: 0,\n paddingX: 8,\n paddingY: 4,\n offsetY: 10,\n borderRadius: 4,\n};\n\nexport const DEFAULT_DRAW_AREA_TOOLTIP_STYLE: DrawAreaTooltipStyle = {\n fontFamily: \"Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: 13,\n fontWeight: 500,\n textColor: \"#FFFFFF\",\n backgroundColor: \"rgba(23, 23, 25, 0.5)\",\n borderRadius: 4,\n paddingX: 6,\n paddingY: 3,\n};\n\nexport const DEFAULT_DRAW_AREA_TOOLTIP_OFFSET = {\n x: 16,\n y: -24,\n} as const;\n\nexport const REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX = 20;\nexport const REGION_LABEL_AUTO_LIFT_MAX_EPSILON = 1e-6;\n\nexport const DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nexport const DEFAULT_DRAW_PREVIEW_FILL = \"transparent\";\nexport const FREEHAND_MIN_POINTS = 3;\nexport const FREEHAND_SCREEN_STEP = 2;\nexport const CIRCLE_SIDES = 96;\nexport const MIN_AREA_PX = 1;\nexport const MICRONS_PER_MM = 1000;\nexport const DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nexport const DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nexport const DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE = 4096;\nexport const LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\nexport const WHEEL_ZOOM_IN_FACTOR = 1.12;\nexport const WHEEL_ZOOM_OUT_FACTOR = 0.89;\nexport const DEFAULT_BRUSH_RADIUS = 32;\nexport const DEFAULT_BRUSH_FILL_COLOR = \"#000000\";\nexport const DEFAULT_BRUSH_FILL_OPACITY = 0.1;\nexport const DEFAULT_BRUSH_CURSOR_COLOR = \"#FFCF00\";\nexport const DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR = \"#FF0000\";\nexport const DEFAULT_BRUSH_CURSOR_LINE_WIDTH = 1.5;\nexport const DEFAULT_BRUSH_CURSOR_DASH = [2, 2];\nexport const DEFAULT_BRUSH_EDGE_DETAIL = 1;\nexport const MIN_BRUSH_EDGE_DETAIL = 0.25;\nexport const MAX_BRUSH_EDGE_DETAIL = 4;\nexport const DEFAULT_BRUSH_EDGE_SMOOTHING = 1;\nexport const MIN_BRUSH_EDGE_SMOOTHING = 0;\nexport const MAX_BRUSH_EDGE_SMOOTHING = 4;\nexport const MIN_BRUSH_RASTER_STEP = 0.05;\nexport const BRUSH_RASTER_DIAMETER_SAMPLES = 256;\nexport const BRUSH_SCREEN_STEP = 1.5;\n","import { closeRoiRing, normalizeRoiGeometry, polygonSignedArea, toRoiGeometry } from \"../wsi/roi-geometry\";\nimport { clamp } from \"../wsi/utils\";\nimport type { DrawCoordinate, DrawOverlayCoordinates, DrawRegionCoordinates, NormalizedDrawRegionPolygon, RegionStrokeStyle } from \"./draw-layer-types\";\nimport { CIRCLE_SIDES, DEFAULT_REGION_STROKE_STYLE, type DrawBounds, EMPTY_DASH } from \"./draw-layer-types\";\n\nexport { clamp };\n\nexport function clampWorld(coord: DrawCoordinate, imageWidth: number, imageHeight: number): DrawCoordinate {\n return [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nexport function toDrawCoordinate(value: unknown): DrawCoordinate | null {\n if (!Array.isArray(value) || value.length < 2) return null;\n const x = Number(value[0]);\n const y = Number(value[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n}\n\nexport const toCoord = toDrawCoordinate;\n\nexport function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n return closeRoiRing(coords) as DrawCoordinate[];\n}\n\nexport function polygonArea(coords: DrawCoordinate[]): number {\n return Math.abs(polygonSignedArea(closeRing(coords)));\n}\n\nexport function computeBounds(coords: DrawCoordinate[]): DrawBounds {\n if (!Array.isArray(coords) || coords.length === 0) return [0, 0, 0, 0];\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of coords) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n return [minX, minY, maxX, maxY];\n}\n\nexport function tracePath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], close = false): void {\n if (points.length === 0) return;\n\n ctx.moveTo(points[0][0], points[0][1]);\n for (let i = 1; i < points.length; i += 1) {\n ctx.lineTo(points[i][0], points[i][1]);\n }\n\n if (close) {\n ctx.closePath();\n }\n}\n\nexport function drawPath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], strokeStyle: RegionStrokeStyle, close = false, fill = false, fillColor = \"rgba(255, 77, 79, 0.16)\"): void {\n if (points.length === 0) return;\n\n ctx.beginPath();\n tracePath(ctx, points, close);\n if (fill && close) {\n ctx.fillStyle = fillColor;\n ctx.fill();\n }\n\n ctx.strokeStyle = strokeStyle.color;\n ctx.lineWidth = strokeStyle.width;\n ctx.lineJoin = strokeStyle.lineJoin;\n ctx.lineCap = strokeStyle.lineCap;\n ctx.shadowColor = strokeStyle.shadowColor;\n ctx.shadowBlur = strokeStyle.shadowBlur;\n ctx.shadowOffsetX = strokeStyle.shadowOffsetX;\n ctx.shadowOffsetY = strokeStyle.shadowOffsetY;\n ctx.setLineDash(strokeStyle.lineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.shadowColor = \"rgba(0, 0, 0, 0)\";\n ctx.shadowBlur = 0;\n ctx.shadowOffsetX = 0;\n ctx.shadowOffsetY = 0;\n}\n\nexport function resolveStrokeStyle(style: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n const dash = Array.isArray(style?.lineDash) ? style.lineDash.filter(value => Number.isFinite(value) && value >= 0) : EMPTY_DASH;\n const width = typeof style?.width === \"number\" && Number.isFinite(style.width) ? Math.max(0, style.width) : DEFAULT_REGION_STROKE_STYLE.width;\n const shadowBlur = typeof style?.shadowBlur === \"number\" && Number.isFinite(style.shadowBlur) ? Math.max(0, style.shadowBlur) : DEFAULT_REGION_STROKE_STYLE.shadowBlur;\n const shadowOffsetX = typeof style?.shadowOffsetX === \"number\" && Number.isFinite(style.shadowOffsetX) ? style.shadowOffsetX : DEFAULT_REGION_STROKE_STYLE.shadowOffsetX;\n const shadowOffsetY = typeof style?.shadowOffsetY === \"number\" && Number.isFinite(style.shadowOffsetY) ? style.shadowOffsetY : DEFAULT_REGION_STROKE_STYLE.shadowOffsetY;\n return {\n color: style?.color || DEFAULT_REGION_STROKE_STYLE.color,\n width,\n lineDash: dash.length ? dash : EMPTY_DASH,\n lineJoin: style?.lineJoin || DEFAULT_REGION_STROKE_STYLE.lineJoin,\n lineCap: style?.lineCap || DEFAULT_REGION_STROKE_STYLE.lineCap,\n shadowColor: style?.shadowColor || DEFAULT_REGION_STROKE_STYLE.shadowColor,\n shadowBlur,\n shadowOffsetX,\n shadowOffsetY,\n };\n}\n\nexport function mergeStrokeStyle(base: RegionStrokeStyle, override: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n if (!override) return base;\n return resolveStrokeStyle({\n color: override.color ?? base.color,\n width: override.width ?? base.width,\n lineDash: override.lineDash ?? base.lineDash,\n lineJoin: override.lineJoin ?? base.lineJoin,\n lineCap: override.lineCap ?? base.lineCap,\n shadowColor: override.shadowColor ?? base.shadowColor,\n shadowBlur: override.shadowBlur ?? base.shadowBlur,\n shadowOffsetX: override.shadowOffsetX ?? base.shadowOffsetX,\n shadowOffsetY: override.shadowOffsetY ?? base.shadowOffsetY,\n });\n}\n\nexport function isSameRegionId(a: string | number | null | undefined, b: string | number | null | undefined): boolean {\n if (a === null || a === undefined || b === null || b === undefined) {\n return false;\n }\n return String(a) === String(b);\n}\n\nexport function isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nexport function isCoordinatePair(value: unknown): value is [number, number] {\n return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);\n}\n\nexport function isCoordinateRing(value: unknown): value is DrawCoordinate[] {\n return Array.isArray(value) && value.length >= 2 && value.every(point => isCoordinatePair(point));\n}\n\nfunction collectOverlayRings(value: unknown, out: DrawCoordinate[][]): void {\n if (!Array.isArray(value) || value.length === 0) return;\n if (isCoordinateRing(value)) {\n out.push(value.map(([x, y]) => [x, y] as DrawCoordinate));\n return;\n }\n for (const item of value) {\n collectOverlayRings(item, out);\n }\n}\n\nexport function normalizeOverlayRings(coordinates: DrawOverlayCoordinates, close: boolean): DrawCoordinate[][] {\n const sourceRings: DrawCoordinate[][] = [];\n collectOverlayRings(coordinates, sourceRings);\n const out: DrawCoordinate[][] = [];\n for (const ring of sourceRings) {\n if (ring.length < 2) continue;\n const normalized = close ? closeRing(ring) : ring;\n if (normalized.length >= (close ? 4 : 2)) {\n out.push(normalized);\n }\n }\n return out;\n}\n\nexport function clampPositiveOrFallback(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n return fallback;\n }\n return value;\n}\n\nexport function clampUnitOpacity(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n return clamp(value, 0, 1);\n}\n\nexport function drawRoundedRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number): void {\n const r = Math.max(0, Math.min(radius, width * 0.5, height * 0.5));\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + r);\n ctx.lineTo(x + width, y + height - r);\n ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n ctx.lineTo(x + r, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n}\n\nexport function isNestedRingCoordinates(coordinates: DrawOverlayCoordinates): boolean {\n const first = coordinates[0];\n return Array.isArray(first) && Array.isArray(first[0]);\n}\n\nexport function createRectangle(\n start: DrawCoordinate | null,\n end: DrawCoordinate | null,\n projection?: {\n worldToScreen: (x: number, y: number) => DrawCoordinate | null;\n screenToWorld: (screen: DrawCoordinate) => DrawCoordinate | null;\n }\n): DrawCoordinate[] {\n if (!start || !end) return [];\n\n if (projection) {\n const startScreen = projection.worldToScreen(start[0], start[1]);\n const endScreen = projection.worldToScreen(end[0], end[1]);\n\n if (startScreen && endScreen) {\n const screenCorners: DrawCoordinate[] = [\n [startScreen[0], startScreen[1]],\n [endScreen[0], startScreen[1]],\n [endScreen[0], endScreen[1]],\n [startScreen[0], endScreen[1]],\n ];\n const worldCorners: DrawCoordinate[] = [];\n for (const corner of screenCorners) {\n const world = projection.screenToWorld(corner);\n if (!world) return createRectangle(start, end);\n worldCorners.push(world);\n }\n return closeRing(worldCorners);\n }\n }\n\n return closeRing([\n [start[0], start[1]],\n [end[0], start[1]],\n [end[0], end[1]],\n [start[0], end[1]],\n ]);\n}\n\nexport function createCircle(start: DrawCoordinate | null, end: DrawCoordinate | null, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!start || !end) return [];\n\n const centerX = (start[0] + end[0]) * 0.5;\n const centerY = (start[1] + end[1]) * 0.5;\n const radius = Math.hypot(end[0] - start[0], end[1] - start[1]) * 0.5;\n if (radius < 1) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([centerX + Math.cos(t) * radius, centerY + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nexport function normalizeDrawRegionPolygons(coordinates: DrawRegionCoordinates): NormalizedDrawRegionPolygon[] {\n const multipolygon = normalizeRoiGeometry(toRoiGeometry(coordinates));\n if (multipolygon.length === 0) return [];\n\n const out: NormalizedDrawRegionPolygon[] = [];\n for (const polygon of multipolygon) {\n const outer = polygon[0];\n if (!outer || outer.length < 4) continue;\n const normalizedOuter = outer.map(([x, y]) => [x, y] as DrawCoordinate);\n const holes: DrawCoordinate[][] = [];\n for (let i = 1; i < polygon.length; i += 1) {\n const hole = polygon[i];\n if (!hole || hole.length < 4) continue;\n holes.push(hole.map(([x, y]) => [x, y] as DrawCoordinate));\n }\n out.push({\n outer: normalizedOuter,\n holes,\n });\n }\n return out;\n}\n","import type { BrushOptions, DrawCoordinate, DrawProjector, DrawSession, ResolvedBrushOptions } from \"./draw-layer-types\";\nimport {\n DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR,\n DEFAULT_BRUSH_CURSOR_COLOR,\n DEFAULT_BRUSH_CURSOR_DASH,\n DEFAULT_BRUSH_CURSOR_LINE_WIDTH,\n DEFAULT_BRUSH_EDGE_DETAIL,\n DEFAULT_BRUSH_EDGE_SMOOTHING,\n DEFAULT_BRUSH_FILL_COLOR,\n DEFAULT_BRUSH_FILL_OPACITY,\n DEFAULT_BRUSH_RADIUS,\n EMPTY_DASH,\n MAX_BRUSH_EDGE_DETAIL,\n MAX_BRUSH_EDGE_SMOOTHING,\n MIN_BRUSH_EDGE_DETAIL,\n MIN_BRUSH_EDGE_SMOOTHING,\n} from \"./draw-layer-types\";\nimport { clamp, clampPositiveOrFallback, clampUnitOpacity, toCoord } from \"./draw-layer-utils\";\n\nexport type { BrushOptions, ResolvedBrushOptions };\n\nexport function sanitizeBrushLineDash(value: number[] | undefined): number[] {\n if (!Array.isArray(value)) return DEFAULT_BRUSH_CURSOR_DASH;\n const out = value.filter(item => Number.isFinite(item) && item >= 0);\n return out.length > 0 ? out : DEFAULT_BRUSH_CURSOR_DASH;\n}\n\nexport function resolveBrushEdgeDetail(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_BRUSH_EDGE_DETAIL;\n return clamp(value, MIN_BRUSH_EDGE_DETAIL, MAX_BRUSH_EDGE_DETAIL);\n}\n\nexport function resolveBrushEdgeSmoothing(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_BRUSH_EDGE_SMOOTHING;\n return Math.round(clamp(value, MIN_BRUSH_EDGE_SMOOTHING, MAX_BRUSH_EDGE_SMOOTHING));\n}\n\nexport function resolveBrushOptions(options: BrushOptions | undefined): ResolvedBrushOptions {\n const radius = clampPositiveOrFallback(options?.radius, DEFAULT_BRUSH_RADIUS);\n const cursorLineWidth = clampPositiveOrFallback(options?.cursorLineWidth, DEFAULT_BRUSH_CURSOR_LINE_WIDTH);\n const edgeDetail = resolveBrushEdgeDetail(options?.edgeDetail);\n const edgeSmoothing = resolveBrushEdgeSmoothing(options?.edgeSmoothing);\n return {\n radius,\n edgeDetail,\n edgeSmoothing,\n clickSelectRoi: options?.clickSelectRoi === true,\n fillColor: options?.fillColor || DEFAULT_BRUSH_FILL_COLOR,\n fillOpacity: clampUnitOpacity(options?.fillOpacity, DEFAULT_BRUSH_FILL_OPACITY),\n cursorColor: options?.cursorColor || DEFAULT_BRUSH_CURSOR_COLOR,\n cursorActiveColor: options?.cursorActiveColor || DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR,\n cursorLineWidth,\n cursorLineDash: sanitizeBrushLineDash(options?.cursorLineDash),\n };\n}\n\nexport function drawBrushStrokePreview(ctx: CanvasRenderingContext2D, session: DrawSession, resolvedBrushOptions: ResolvedBrushOptions): void {\n if (!session.isDrawing || session.screenPoints.length === 0) return;\n const screenPoints = session.screenPoints;\n if (screenPoints.length === 0) return;\n const radiusPx = resolvedBrushOptions.radius;\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.globalAlpha = resolvedBrushOptions.fillOpacity;\n ctx.fillStyle = resolvedBrushOptions.fillColor;\n ctx.strokeStyle = resolvedBrushOptions.fillColor;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.lineWidth = radiusPx * 2;\n if (screenPoints.length === 1) {\n ctx.beginPath();\n ctx.arc(screenPoints[0][0], screenPoints[0][1], radiusPx, 0, Math.PI * 2);\n ctx.fill();\n } else {\n ctx.beginPath();\n ctx.moveTo(screenPoints[0][0], screenPoints[0][1]);\n for (let i = 1; i < screenPoints.length; i += 1) {\n ctx.lineTo(screenPoints[i][0], screenPoints[i][1]);\n }\n ctx.stroke();\n }\n ctx.restore();\n}\n\nexport function drawBrushCursor(ctx: CanvasRenderingContext2D, session: DrawSession, projector: DrawProjector | null, resolvedBrushOptions: ResolvedBrushOptions): void {\n const cursor = session.cursor;\n if (!cursor) return;\n const screen = session.cursorScreen ?? toCoord(projector?.worldToScreen(cursor[0], cursor[1]) ?? []);\n if (!screen) return;\n const radiusPx = resolvedBrushOptions.radius;\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.beginPath();\n ctx.arc(screen[0], screen[1], radiusPx, 0, Math.PI * 2);\n ctx.strokeStyle = session.isDrawing ? resolvedBrushOptions.cursorActiveColor : resolvedBrushOptions.cursorColor;\n ctx.lineWidth = resolvedBrushOptions.cursorLineWidth;\n ctx.setLineDash(resolvedBrushOptions.cursorLineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.restore();\n}\n","import type { DrawAreaTooltipOptions, DrawAreaTooltipStyle, DrawCoordinate, RegionLabelAnchorMode, RegionLabelStyle, ResolvedDrawAreaTooltipOptions } from \"./draw-layer-types\";\nimport {\n DEFAULT_DRAW_AREA_TOOLTIP_OFFSET,\n DEFAULT_DRAW_AREA_TOOLTIP_STYLE,\n DEFAULT_REGION_LABEL_STYLE,\n REGION_LABEL_AUTO_LIFT_MAX_EPSILON,\n REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX,\n} from \"./draw-layer-types\";\nimport { clamp, drawRoundedRect } from \"./draw-layer-utils\";\n\nconst LABEL_MEASURE_FALLBACK_EM = 0.58;\nconst LABEL_MEASURE_CACHE_LIMIT = 4096;\nconst TOP_ANCHOR_Y_TOLERANCE = 0.5;\n\nlet sharedLabelMeasureContext: CanvasRenderingContext2D | null = null;\nconst labelTextWidthCache = new Map<string, number>();\n\nfunction getLabelMeasureContext(): CanvasRenderingContext2D | null {\n if (sharedLabelMeasureContext) return sharedLabelMeasureContext;\n if (typeof document === \"undefined\") return null;\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return null;\n sharedLabelMeasureContext = ctx;\n return sharedLabelMeasureContext;\n}\n\nexport function measureLabelTextWidth(label: string, labelStyle: { fontFamily: string; fontSize: number; fontWeight: string | number }): number {\n const key = `${labelStyle.fontWeight}|${labelStyle.fontSize}|${labelStyle.fontFamily}|${label}`;\n const cached = labelTextWidthCache.get(key);\n if (cached !== undefined) return cached;\n\n const fallback = label.length * labelStyle.fontSize * LABEL_MEASURE_FALLBACK_EM;\n const ctx = getLabelMeasureContext();\n let width = fallback;\n if (ctx) {\n ctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n const measured = ctx.measureText(label).width;\n if (Number.isFinite(measured) && measured >= 0) {\n width = measured;\n }\n }\n\n if (labelTextWidthCache.size > LABEL_MEASURE_CACHE_LIMIT) {\n labelTextWidthCache.clear();\n }\n labelTextWidthCache.set(key, width);\n return width;\n}\n\nexport function getTopAnchor(coords: DrawCoordinate[], anchorMode: RegionLabelAnchorMode = \"top-center\"): DrawCoordinate | null {\n if (!coords.length) return null;\n\n let minY = Infinity;\n for (const point of coords) {\n if (point[1] < minY) minY = point[1];\n }\n if (!Number.isFinite(minY)) return null;\n\n let minX = Infinity;\n let maxX = -Infinity;\n for (const point of coords) {\n if (Math.abs(point[1] - minY) > TOP_ANCHOR_Y_TOLERANCE) continue;\n if (point[0] < minX) minX = point[0];\n if (point[0] > maxX) maxX = point[0];\n }\n\n if (!Number.isFinite(minX) || !Number.isFinite(maxX)) return null;\n if (anchorMode === \"top-center\") {\n return [(minX + maxX) * 0.5, minY];\n }\n return [minX, minY];\n}\n\nexport function getTopAnchorFromPolygons<T extends { outer: DrawCoordinate[] }>(polygons: T[], anchorMode: RegionLabelAnchorMode = \"top-center\"): DrawCoordinate | null {\n let best: DrawCoordinate | null = null;\n for (const polygon of polygons) {\n const anchor = getTopAnchor(polygon.outer, anchorMode);\n if (!anchor) continue;\n if (!best || anchor[1] < best[1] || (anchor[1] === best[1] && anchor[0] < best[0])) {\n best = anchor;\n }\n }\n return best;\n}\n\nexport function getTopAnchorFromProjectedPolygons<T extends { outer: DrawCoordinate[] }>(\n polygons: T[],\n project: (points: DrawCoordinate[]) => DrawCoordinate[],\n anchorMode: RegionLabelAnchorMode = \"top-center\"\n): DrawCoordinate | null {\n let best: DrawCoordinate | null = null;\n for (const polygon of polygons) {\n const projectedOuter = project(polygon.outer);\n if (projectedOuter.length === 0) continue;\n const anchor = getTopAnchor(projectedOuter, anchorMode);\n if (!anchor) continue;\n if (!best || anchor[1] < best[1] || (anchor[1] === best[1] && anchor[0] < best[0])) {\n best = anchor;\n }\n }\n return best;\n}\n\nexport function resolveRegionLabelStyle(style: Partial<RegionLabelStyle> | undefined): RegionLabelStyle {\n const px = typeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX) ? Math.max(0, style.paddingX) : DEFAULT_REGION_LABEL_STYLE.paddingX;\n const py = typeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY) ? Math.max(0, style.paddingY) : DEFAULT_REGION_LABEL_STYLE.paddingY;\n const fs = typeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize) ? Math.max(8, style.fontSize) : DEFAULT_REGION_LABEL_STYLE.fontSize;\n const bw = typeof style?.borderWidth === \"number\" && Number.isFinite(style.borderWidth) ? Math.max(0, style.borderWidth) : DEFAULT_REGION_LABEL_STYLE.borderWidth;\n const oy = typeof style?.offsetY === \"number\" && Number.isFinite(style.offsetY) ? style.offsetY : DEFAULT_REGION_LABEL_STYLE.offsetY;\n const br = typeof style?.borderRadius === \"number\" && Number.isFinite(style.borderRadius) ? Math.max(0, style.borderRadius) : DEFAULT_REGION_LABEL_STYLE.borderRadius;\n return {\n fontFamily: style?.fontFamily || DEFAULT_REGION_LABEL_STYLE.fontFamily,\n fontSize: fs,\n fontWeight: style?.fontWeight || DEFAULT_REGION_LABEL_STYLE.fontWeight,\n textColor: style?.textColor || DEFAULT_REGION_LABEL_STYLE.textColor,\n backgroundColor: style?.backgroundColor || DEFAULT_REGION_LABEL_STYLE.backgroundColor,\n borderColor: style?.borderColor || DEFAULT_REGION_LABEL_STYLE.borderColor,\n borderWidth: bw,\n paddingX: px,\n paddingY: py,\n offsetY: oy,\n borderRadius: br,\n };\n}\n\nexport function mergeRegionLabelStyle(base: RegionLabelStyle, override: Partial<RegionLabelStyle> | null | undefined): RegionLabelStyle {\n if (!override) return base;\n return resolveRegionLabelStyle({\n fontFamily: override.fontFamily ?? base.fontFamily,\n fontSize: override.fontSize ?? base.fontSize,\n fontWeight: override.fontWeight ?? base.fontWeight,\n textColor: override.textColor ?? base.textColor,\n backgroundColor: override.backgroundColor ?? base.backgroundColor,\n borderColor: override.borderColor ?? base.borderColor,\n borderWidth: override.borderWidth ?? base.borderWidth,\n paddingX: override.paddingX ?? base.paddingX,\n paddingY: override.paddingY ?? base.paddingY,\n offsetY: override.offsetY ?? base.offsetY,\n borderRadius: override.borderRadius ?? base.borderRadius,\n });\n}\n\nexport function resolveRegionLabelAutoLiftOffsetPx(\n enabled: boolean | undefined,\n zoom: number,\n zoomRange: { minZoom: number; maxZoom: number } | null | undefined,\n liftCapZoom?: number | null | undefined,\n): number {\n if (!enabled) return 0;\n if (!zoomRange) return 0;\n\n const minZoom = Number(zoomRange.minZoom);\n const maxZoom = Number(zoomRange.maxZoom);\n if (!Number.isFinite(minZoom) || !Number.isFinite(maxZoom)) return 0;\n\n if (maxZoom - minZoom <= REGION_LABEL_AUTO_LIFT_MAX_EPSILON) return 0;\n if (!Number.isFinite(zoom)) return 0;\n\n let cap = maxZoom;\n if (liftCapZoom != null && Number.isFinite(liftCapZoom)) {\n cap = clamp(liftCapZoom, minZoom, maxZoom);\n }\n const tol = Math.max(REGION_LABEL_AUTO_LIFT_MAX_EPSILON, Math.abs(cap) * 1e-9);\n return zoom >= cap - tol ? REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX : 0;\n}\n\nfunction resolveDrawAreaTooltipStyle(style: Partial<DrawAreaTooltipStyle> | undefined): DrawAreaTooltipStyle {\n const fontSize = typeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize) ? Math.max(8, style.fontSize) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.fontSize;\n const borderRadius = typeof style?.borderRadius === \"number\" && Number.isFinite(style.borderRadius) ? Math.max(0, style.borderRadius) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.borderRadius;\n const paddingX = typeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX) ? Math.max(0, style.paddingX) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.paddingX;\n const paddingY = typeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY) ? Math.max(0, style.paddingY) : DEFAULT_DRAW_AREA_TOOLTIP_STYLE.paddingY;\n return {\n fontFamily: style?.fontFamily || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.fontFamily,\n fontSize,\n fontWeight: style?.fontWeight || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.fontWeight,\n textColor: style?.textColor || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.textColor,\n backgroundColor: style?.backgroundColor || DEFAULT_DRAW_AREA_TOOLTIP_STYLE.backgroundColor,\n borderRadius,\n paddingX,\n paddingY,\n };\n}\n\nfunction resolveTooltipCursorOffset(value: DrawAreaTooltipOptions[\"cursorOffset\"]): { x: number; y: number } {\n const x = typeof value?.x === \"number\" && Number.isFinite(value.x) ? value.x : DEFAULT_DRAW_AREA_TOOLTIP_OFFSET.x;\n const y = typeof value?.y === \"number\" && Number.isFinite(value.y) ? value.y : DEFAULT_DRAW_AREA_TOOLTIP_OFFSET.y;\n return { x, y };\n}\n\nexport function defaultDrawAreaTooltipFormatter(areaMm2: number): string {\n if (!Number.isFinite(areaMm2)) return \"0.000 mm²\";\n return `${Math.max(0, areaMm2).toFixed(3)} mm²`;\n}\n\nexport function resolveDrawAreaTooltipOptions(options: DrawAreaTooltipOptions | undefined): ResolvedDrawAreaTooltipOptions {\n const format = typeof options?.format === \"function\" ? options.format : defaultDrawAreaTooltipFormatter;\n const cursorOffset = resolveTooltipCursorOffset(options?.cursorOffset);\n return {\n enabled: options?.enabled === true,\n format,\n style: resolveDrawAreaTooltipStyle(options?.style),\n cursorOffsetX: cursorOffset.x,\n cursorOffsetY: cursorOffset.y,\n };\n}\n\nexport function drawRegionLabel(\n ctx: CanvasRenderingContext2D,\n text: string,\n anchor: DrawCoordinate,\n canvasWidth: number,\n canvasHeight: number,\n labelStyle: RegionLabelStyle,\n clampToViewport = true\n): void {\n const label = text.trim();\n if (!label) return;\n\n ctx.save();\n ctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n\n const textWidth = measureLabelTextWidth(label, labelStyle);\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const rawX = anchor[0];\n const rawY = anchor[1] - labelStyle.offsetY;\n const x = clampToViewport ? clamp(rawX, boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1) : rawX;\n const y = clampToViewport ? clamp(rawY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1) : rawY;\n const left = x - boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n\n ctx.fillStyle = labelStyle.backgroundColor;\n ctx.strokeStyle = labelStyle.borderColor;\n ctx.lineWidth = labelStyle.borderWidth;\n drawRoundedRect(ctx, left, top, boxWidth, boxHeight, labelStyle.borderRadius);\n ctx.fill();\n if (labelStyle.borderWidth > 0) {\n ctx.stroke();\n }\n\n ctx.fillStyle = labelStyle.textColor;\n ctx.fillText(label, x, y + 0.5);\n ctx.restore();\n}\n\nexport function drawAreaTooltipBox(\n ctx: CanvasRenderingContext2D,\n text: string,\n cursorScreen: DrawCoordinate,\n canvasWidth: number,\n canvasHeight: number,\n style: DrawAreaTooltipStyle,\n offsetX: number,\n offsetY: number\n): void {\n const label = text.trim();\n if (!label) return;\n\n ctx.save();\n ctx.font = `${style.fontWeight} ${style.fontSize}px ${style.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n\n const textWidth = measureLabelTextWidth(label, style);\n const boxWidth = textWidth + style.paddingX * 2;\n const boxHeight = style.fontSize + style.paddingY * 2;\n\n const x = clamp(cursorScreen[0] + offsetX, boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1);\n const y = clamp(cursorScreen[1] + offsetY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1);\n const left = x - boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n\n ctx.fillStyle = style.backgroundColor;\n drawRoundedRect(ctx, left, top, boxWidth, boxHeight, style.borderRadius);\n ctx.fill();\n\n ctx.fillStyle = style.textColor;\n ctx.fillText(label, x, y + 0.5);\n ctx.restore();\n}\n","import type { DrawCoordinate, DrawOverlayShape, RegionStrokeStyle } from \"./draw-layer-types\";\nimport { drawPath, isNestedRingCoordinates, mergeStrokeStyle, normalizeOverlayRings, tracePath } from \"./draw-layer-utils\";\n\nexport function drawInvertedFillMask(ctx: CanvasRenderingContext2D, outerRing: DrawCoordinate[], holeRings: DrawCoordinate[][], fillColor: string): void {\n if (outerRing.length < 4 || holeRings.length === 0) return;\n ctx.save();\n ctx.beginPath();\n tracePath(ctx, outerRing, true);\n for (const ring of holeRings) {\n if (ring.length < 4) continue;\n tracePath(ctx, ring, true);\n }\n ctx.fillStyle = fillColor;\n ctx.fill(\"evenodd\");\n ctx.restore();\n}\n\nexport interface DrawOverlayShapesParams {\n ctx: CanvasRenderingContext2D;\n overlayShapes: DrawOverlayShape[];\n imageOuterRing: DrawCoordinate[];\n worldToScreenPoints: (points: DrawCoordinate[]) => DrawCoordinate[];\n baseStrokeStyle: RegionStrokeStyle;\n onInvertedFillDebug?: (info: { id: string | number; outerRingPoints: number; sourceRingCount: number; holeRingCount: number; fillColor: string }) => void;\n}\n\nexport function drawOverlayShapes(params: DrawOverlayShapesParams): void {\n const { ctx, overlayShapes, imageOuterRing, worldToScreenPoints, baseStrokeStyle, onInvertedFillDebug } = params;\n\n const debugOverlay = Boolean((globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__);\n\n for (let i = 0; i < overlayShapes.length; i += 1) {\n const shape = overlayShapes[i];\n if (!shape?.coordinates?.length || shape.visible === false) continue;\n\n const closed = shape.closed ?? isNestedRingCoordinates(shape.coordinates);\n const renderRings = normalizeOverlayRings(shape.coordinates, closed);\n\n if (shape.invertedFill?.fillColor) {\n const holeRings: DrawCoordinate[][] = [];\n const closedRings = normalizeOverlayRings(shape.coordinates, true);\n for (const ring of closedRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length >= 4) {\n holeRings.push(screen);\n }\n }\n if (debugOverlay && onInvertedFillDebug) {\n onInvertedFillDebug({\n id: shape.id ?? i,\n outerRingPoints: imageOuterRing.length,\n sourceRingCount: closedRings.length,\n holeRingCount: holeRings.length,\n fillColor: shape.invertedFill.fillColor,\n });\n }\n drawInvertedFillMask(ctx, imageOuterRing, holeRings, shape.invertedFill.fillColor);\n }\n\n if (renderRings.length === 0) continue;\n const strokeStyle = mergeStrokeStyle(baseStrokeStyle, shape.stroke ?? shape.strokeStyle);\n for (const ring of renderRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length < 2) continue;\n drawPath(ctx, screen, strokeStyle, closed, shape.fill ?? false);\n }\n }\n}\n","import type { DrawCoordinate, DrawTool, StampDrawTool, StampOptions, StampToolConfig } from \"./draw-layer-types\";\nimport { CIRCLE_SIDES, DEFAULT_STAMP_CIRCLE_AREA_MM2, DEFAULT_STAMP_RECTANGLE_AREA_MM2, DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE, LEGACY_HPF_CIRCLE_AREA_MM2 } from \"./draw-layer-types\";\nimport { clampPositiveOrFallback, clampWorld, closeRing } from \"./draw-layer-utils\";\n\nexport type { StampDrawTool, StampOptions, StampToolConfig };\n\nexport function isStampTool(tool: DrawTool): tool is StampDrawTool {\n return (\n typeof tool === \"string\" && (\n tool === \"stamp-rectangle\" || tool === \"stamp-circle\" || tool === \"stamp-rectangle-4096px\" || tool === \"stamp-rectangle-2mm2\" || tool === \"stamp-circle-2mm2\" || tool === \"stamp-circle-hpf-0.2mm2\"\n )\n );\n}\n\nexport function isStampConfig(tool: DrawTool): tool is { stamp: StampToolConfig } {\n return typeof tool === \"object\" && tool !== null && \"stamp\" in tool;\n}\n\nexport function isDrawToolString(tool: DrawTool): tool is Exclude<DrawTool, { stamp: StampToolConfig }> {\n return typeof tool === \"string\";\n}\n\nexport function isBrushVariant(tool: DrawTool): boolean {\n return tool === \"brush\" || tool === \"eraser\" || tool === \"region-brush\" || tool === \"region-eraser\";\n}\n\nexport function resolveStampOptions(options: StampOptions | undefined): Required<StampOptions> {\n return {\n rectangleAreaMm2: clampPositiveOrFallback(options?.rectangleAreaMm2, DEFAULT_STAMP_RECTANGLE_AREA_MM2),\n circleAreaMm2: clampPositiveOrFallback(options?.circleAreaMm2, DEFAULT_STAMP_CIRCLE_AREA_MM2),\n rectanglePixelSize: clampPositiveOrFallback(options?.rectanglePixelSize, DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE),\n };\n}\n\nconst MICRONS_PER_MM = 1000;\n\nexport function mm2ToUm2(areaMm2: number): number {\n return areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nexport function createSquareFromCenter(\n center: DrawCoordinate | null,\n halfLength: number,\n projection?: {\n worldToScreen: (x: number, y: number) => DrawCoordinate | null;\n screenToWorld: (screen: DrawCoordinate) => DrawCoordinate | null;\n }\n): DrawCoordinate[] {\n if (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\n\n if (projection) {\n const screenCenter = projection.worldToScreen(center[0], center[1]);\n const screenEdge = projection.worldToScreen(center[0] + halfLength, center[1]);\n if (screenCenter && screenEdge) {\n const screenHL = Math.hypot(screenEdge[0] - screenCenter[0], screenEdge[1] - screenCenter[1]);\n const screenCorners: DrawCoordinate[] = [\n [screenCenter[0] - screenHL, screenCenter[1] - screenHL],\n [screenCenter[0] + screenHL, screenCenter[1] - screenHL],\n [screenCenter[0] + screenHL, screenCenter[1] + screenHL],\n [screenCenter[0] - screenHL, screenCenter[1] + screenHL],\n ];\n const worldCorners: DrawCoordinate[] = [];\n for (const corner of screenCorners) {\n const world = projection.screenToWorld(corner);\n if (!world) throw new Error(\"Failed to create rectangle\");\n worldCorners.push(world);\n }\n return closeRing(worldCorners);\n }\n }\n\n return closeRing([\n [center[0] - halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] + halfLength],\n [center[0] - halfLength, center[1] + halfLength],\n ]);\n}\n\nexport function createCircleFromCenter(center: DrawCoordinate | null, radius: number, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!center || !Number.isFinite(radius) || radius <= 0) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([center[0] + Math.cos(t) * radius, center[1] + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nexport interface BuildStampCoordsParams {\n stampTool: StampDrawTool;\n center: DrawCoordinate | null;\n resolvedStampOptions: Required<StampOptions>;\n imageWidth: number;\n imageHeight: number;\n micronsToWorldPixels: (lengthUm: number) => number;\n getRectangleProjection: () =>\n | {\n worldToScreen: (x: number, y: number) => DrawCoordinate | null;\n screenToWorld: (screen: DrawCoordinate) => DrawCoordinate | null;\n }\n | undefined;\n}\n\nexport function buildStampCoords(params: BuildStampCoordsParams): DrawCoordinate[] {\n const { stampTool, center, resolvedStampOptions, imageWidth, imageHeight, micronsToWorldPixels, getRectangleProjection } = params;\n\n if (!center) return [];\n\n if (stampTool === \"stamp-rectangle-4096px\") {\n const halfLength = resolvedStampOptions.rectanglePixelSize * 0.5;\n return createSquareFromCenter(center, halfLength, getRectangleProjection()).map(point => clampWorld(point, imageWidth, imageHeight));\n }\n\n let areaMm2 = 0;\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n areaMm2 = stampTool === \"stamp-rectangle-2mm2\" ? DEFAULT_STAMP_RECTANGLE_AREA_MM2 : resolvedStampOptions.rectangleAreaMm2;\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n areaMm2 = stampTool === \"stamp-circle-hpf-0.2mm2\" ? LEGACY_HPF_CIRCLE_AREA_MM2 : stampTool === \"stamp-circle-2mm2\" ? DEFAULT_STAMP_CIRCLE_AREA_MM2 : resolvedStampOptions.circleAreaMm2;\n }\n if (!Number.isFinite(areaMm2) || areaMm2 <= 0) return [];\n\n const areaUm2 = mm2ToUm2(areaMm2);\n let coords: DrawCoordinate[] = [];\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n const halfLength = micronsToWorldPixels(Math.sqrt(areaUm2) * 0.5);\n coords = createSquareFromCenter(center, halfLength, getRectangleProjection());\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n const radius = micronsToWorldPixels(Math.sqrt(areaUm2 / Math.PI));\n coords = createCircleFromCenter(center, radius);\n }\n\n if (!coords.length) return [];\n return coords.map(point => clampWorld(point, imageWidth, imageHeight));\n}\n","import { type CSSProperties, type PointerEvent as ReactPointerEvent, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { buildBrushStrokePolygon } from \"../wsi/brush-stroke\";\nimport { observeDevicePixelRatioChanges } from \"../wsi/device-pixel-ratio\";\nimport { calcScaleResolution } from \"../wsi/utils\";\nimport { drawBrushCursor, drawBrushStrokePreview, resolveBrushOptions } from \"./draw-layer-brush\";\nimport {\n drawAreaTooltipBox,\n drawRegionLabel,\n getTopAnchorFromProjectedPolygons,\n mergeRegionLabelStyle,\n resolveDrawAreaTooltipOptions,\n resolveRegionLabelAutoLiftOffsetPx,\n resolveRegionLabelStyle,\n} from \"./draw-layer-label\";\nimport { drawOverlayShapes } from \"./draw-layer-overlay\";\nimport { buildStampCoords, isStampTool, resolveStampOptions } from \"./draw-layer-stamp\";\nimport {\n BRUSH_SCREEN_STEP,\n DEFAULT_DRAW_PREVIEW_FILL,\n DEFAULT_PATCH_STROKE_STYLE,\n type DrawLayerProps,\n type DrawRegion,\n type DrawSession,\n type DrawTool,\n EMPTY_DASH,\n EMPTY_REGIONS,\n FREEHAND_MIN_POINTS,\n FREEHAND_SCREEN_STEP,\n MICRONS_PER_MM,\n MIN_AREA_PX,\n type PreparedRenderedRegion,\n REGION_INTERACTION_SHADOW_COLOR,\n REGION_INTERACTION_SHADOW_WIDTH,\n type StampDrawTool,\n WHEEL_ZOOM_IN_FACTOR,\n WHEEL_ZOOM_OUT_FACTOR,\n} from \"./draw-layer-types\";\nimport {\n clamp,\n clampWorld,\n closeRing,\n computeBounds,\n createCircle,\n createRectangle,\n drawPath,\n isSameRegionId,\n mergeStrokeStyle,\n normalizeDrawRegionPolygons,\n polygonArea,\n resolveStrokeStyle,\n toCoord,\n} from \"./draw-layer-utils\";\n\nexport { mergeRegionLabelStyle, resolveRegionLabelAutoLiftOffsetPx, resolveRegionLabelStyle } from \"./draw-layer-label\";\nexport type {\n BrushOptions,\n DrawAreaTooltipOptions,\n DrawAreaTooltipStyle,\n DrawBounds,\n DrawCoordinate,\n DrawIntent,\n DrawOverlayCoordinates,\n DrawOverlayInvertedFillStyle,\n DrawOverlayShape,\n DrawProjector,\n DrawRegion,\n DrawRegionCoordinates,\n DrawResult,\n DrawTool,\n PatchDrawResult,\n RegionLabelAnchorMode,\n RegionLabelStyle,\n RegionLabelStyleContext,\n RegionLabelStyleResolver,\n RegionStrokeStyle,\n RegionStrokeStyleResolver,\n RegionStyleContext,\n StampDrawTool,\n StampOptions,\n StampShape,\n StampToolConfig,\n} from \"./draw-layer-types\";\nexport { closeRing, createCircle, createRectangle } from \"./draw-layer-utils\";\n\nfunction resolveRegionInteractionShadowStyle(strokeStyle: import(\"./draw-layer-types\").RegionStrokeStyle): import(\"./draw-layer-types\").RegionStrokeStyle {\n return {\n color: REGION_INTERACTION_SHADOW_COLOR,\n width: REGION_INTERACTION_SHADOW_WIDTH,\n lineDash: EMPTY_DASH,\n lineJoin: strokeStyle.lineJoin,\n lineCap: strokeStyle.lineCap,\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n };\n}\n\nfunction resolveDrawPreviewFillColor(value: string | undefined): string {\n if (typeof value !== \"string\") return DEFAULT_DRAW_PREVIEW_FILL;\n const next = value.trim();\n return next.length > 0 ? next : DEFAULT_DRAW_PREVIEW_FILL;\n}\n\nfunction isValidPolygon(coords: import(\"./draw-layer-types\").DrawCoordinate[]): boolean {\n return Array.isArray(coords) && coords.length >= 4 && polygonArea(coords) > MIN_AREA_PX;\n}\n\nexport function DrawLayer({\n tool,\n imageWidth,\n imageHeight,\n imageMpp,\n imageZoom,\n stampOptions,\n brushOptions,\n projectorRef,\n onBrushTap,\n onDrawComplete,\n onPatchComplete,\n enabled,\n viewStateSignal,\n persistedRegions,\n patchRegions,\n persistedPolygons,\n drawFillColor,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n resolveRegionLabelStyle: resolveRegionLabelStyleProp,\n overlayShapes,\n hoveredRegionId = null,\n activeRegionId = null,\n regionLabelStyle,\n drawAreaTooltip,\n autoLiftRegionLabelAtMaxZoom = false,\n regionLabelAnchor = \"top-center\",\n clampRegionLabelToViewport = true,\n regionLabelAutoLiftOffsetPx,\n invalidateRef,\n className,\n style,\n}: DrawLayerProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const drawPendingRef = useRef(false);\n const overlayDebugSnapshotRef = useRef<Map<string, string>>(new Map());\n const lastToolRef = useRef<DrawTool>(tool);\n const sessionRef = useRef<DrawSession>({\n isDrawing: false,\n pointerId: null,\n start: null,\n current: null,\n cursor: null,\n cursorScreen: null,\n points: [],\n screenPoints: [],\n stampCenter: null,\n });\n\n const active = enabled ?? tool !== \"cursor\";\n const mergedPersistedRegions = useMemo<DrawRegion[]>(() => {\n if (persistedRegions && persistedRegions.length > 0) {\n return persistedRegions;\n }\n if (!persistedPolygons || persistedPolygons.length === 0) {\n return EMPTY_REGIONS;\n }\n return persistedPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [persistedRegions, persistedPolygons]);\n const mergedPatchRegions = useMemo<DrawRegion[]>(() => patchRegions ?? EMPTY_REGIONS, [patchRegions]);\n const preparedPersistedRegions = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < mergedPersistedRegions.length; i += 1) {\n const region = mergedPersistedRegions[i];\n const polygons = normalizeDrawRegionPolygons(region.coordinates);\n if (polygons.length === 0) continue;\n out.push({\n region,\n regionIndex: i,\n regionKey: region.id ?? i,\n polygons,\n });\n }\n return out;\n }, [mergedPersistedRegions]);\n const preparedPatchRegions = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < mergedPatchRegions.length; i += 1) {\n const region = mergedPatchRegions[i];\n const polygons = normalizeDrawRegionPolygons(region.coordinates);\n if (polygons.length === 0) continue;\n out.push({\n region,\n regionIndex: i,\n regionKey: region.id ?? i,\n polygons,\n });\n }\n return out;\n }, [mergedPatchRegions]);\n\n const resolvedStrokeStyle = useMemo(() => resolveStrokeStyle(regionStrokeStyle), [regionStrokeStyle]);\n const resolvedHoverStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeHoverStyle), [resolvedStrokeStyle, regionStrokeHoverStyle]);\n const resolvedActiveStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeActiveStyle), [resolvedStrokeStyle, regionStrokeActiveStyle]);\n const resolvedPatchStrokeStyle = useMemo(() => mergeStrokeStyle(DEFAULT_PATCH_STROKE_STYLE, patchStrokeStyle), [patchStrokeStyle]);\n const resolvedDrawPreviewFillColor = useMemo(() => resolveDrawPreviewFillColor(drawFillColor), [drawFillColor]);\n\n const resolvedLabelStyle = useMemo(() => resolveRegionLabelStyle(regionLabelStyle), [regionLabelStyle]);\n const resolvedDrawAreaTooltipOptions = useMemo(() => resolveDrawAreaTooltipOptions(drawAreaTooltip), [drawAreaTooltip]);\n const resolvedStampOptions = useMemo(() => resolveStampOptions(stampOptions), [stampOptions]);\n const resolvedBrushOptions = useMemo(() => resolveBrushOptions(brushOptions), [brushOptions]);\n\n const mergedStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n inset: 0,\n zIndex: 2,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n pointerEvents: active ? \"auto\" : \"none\",\n cursor: active ? (tool === \"brush\" ? \"none\" : \"crosshair\") : \"default\",\n ...style,\n }),\n [active, tool, style]\n );\n\n const resizeCanvas = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const rect = canvas.getBoundingClientRect();\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const w = Math.max(1, Math.round(rect.width * dpr));\n const h = Math.max(1, Math.round(rect.height * dpr));\n\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n }, [active, tool]);\n\n const worldToScreenPoints = useCallback(\n (points: import(\"./draw-layer-types\").DrawCoordinate[]): import(\"./draw-layer-types\").DrawCoordinate[] => {\n const projector = projectorRef.current;\n if (!projector || points.length === 0) return [];\n\n const out = new Array<import(\"./draw-layer-types\").DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [projectorRef]\n );\n\n const localScreenToWorld = useCallback(\n (screen: import(\"./draw-layer-types\").DrawCoordinate): import(\"./draw-layer-types\").DrawCoordinate | null => {\n const projector = projectorRef.current;\n const canvas = canvasRef.current;\n if (!projector || !canvas) return null;\n const rect = canvas.getBoundingClientRect();\n const raw = toCoord(projector.screenToWorld(rect.left + screen[0], rect.top + screen[1]));\n if (!raw) return null;\n return clampWorld(raw, imageWidth, imageHeight);\n },\n [projectorRef, imageWidth, imageHeight]\n );\n\n const getRectangleProjection = useCallback(() => {\n const projector = projectorRef.current;\n const rotationDeg = projector?.getViewState?.().rotationDeg ?? 0;\n if (Math.abs(rotationDeg % 360) < 0.01 || !projector) return undefined;\n\n return {\n worldToScreen: (x: number, y: number): import(\"./draw-layer-types\").DrawCoordinate | null => toCoord(projector.worldToScreen(x, y)),\n screenToWorld: localScreenToWorld,\n };\n }, [projectorRef, localScreenToWorld]);\n\n const micronsToWorldPixels = useCallback(\n (lengthUm: number): number => {\n if (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n const mppValue = typeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0 ? imageMpp : 1;\n const imageZoomValue = typeof imageZoom === \"number\" && Number.isFinite(imageZoom) ? imageZoom : 0;\n const viewZoomRaw = projectorRef.current?.getViewState?.().zoom;\n const viewZoom = typeof viewZoomRaw === \"number\" && Number.isFinite(viewZoomRaw) && viewZoomRaw > 0 ? viewZoomRaw : 1;\n const continuousZoom = imageZoomValue + Math.log2(viewZoom);\n const umPerScreenPixel = Math.max(1e-9, calcScaleResolution(mppValue, imageZoomValue, continuousZoom));\n const screenPixels = lengthUm / umPerScreenPixel;\n return screenPixels / viewZoom;\n },\n [imageMpp, imageZoom, projectorRef]\n );\n\n const buildStampCoordsCallback = useCallback(\n (stampTool: StampDrawTool, center: import(\"./draw-layer-types\").DrawCoordinate | null): import(\"./draw-layer-types\").DrawCoordinate[] => {\n return buildStampCoords({\n stampTool,\n center,\n resolvedStampOptions,\n imageWidth,\n imageHeight,\n micronsToWorldPixels,\n getRectangleProjection,\n });\n },\n [micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions, getRectangleProjection]\n );\n\n const buildPreviewCoords = useCallback((): import(\"./draw-layer-types\").DrawCoordinate[] => {\n const session = sessionRef.current;\n if (isStampTool(tool)) {\n return buildStampCoordsCallback(tool, session.stampCenter);\n }\n if (tool === \"brush\") {\n return [];\n }\n if (!session.isDrawing) return [];\n\n if (tool === \"freehand\") {\n return session.points;\n }\n if (tool === \"rectangle\") {\n return createRectangle(session.start, session.current, getRectangleProjection());\n }\n if (tool === \"circular\") {\n return createCircle(session.start, session.current);\n }\n\n return [];\n }, [tool, buildStampCoordsCallback, getRectangleProjection]);\n\n const drawOverlay = useCallback(() => {\n resizeCanvas();\n\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const canvasWidth = canvas.width / dpr;\n const canvasHeight = canvas.height / dpr;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n if (preparedPersistedRegions.length > 0) {\n for (const entry of preparedPersistedRegions) {\n const { region, polygons, regionIndex, regionKey } = entry;\n const state: \"default\" | \"hover\" | \"active\" = isSameRegionId(activeRegionId, regionKey) ? \"active\" : isSameRegionId(hoveredRegionId, regionKey) ? \"hover\" : \"default\";\n let strokeStyle = state === \"active\" ? resolvedActiveStrokeStyle : state === \"hover\" ? resolvedHoverStrokeStyle : resolvedStrokeStyle;\n\n if (resolveRegionStrokeStyle) {\n const resolved = resolveRegionStrokeStyle({\n region,\n regionId: regionKey,\n regionIndex,\n state,\n });\n strokeStyle = mergeStrokeStyle(strokeStyle, resolved || undefined);\n }\n const interactionShadowStyle = state === \"default\" ? null : resolveRegionInteractionShadowStyle(strokeStyle);\n\n for (const polygon of polygons) {\n const screenOuter = worldToScreenPoints(polygon.outer);\n if (screenOuter.length >= 4) {\n if (interactionShadowStyle) {\n drawPath(ctx, screenOuter, interactionShadowStyle, true, false);\n }\n drawPath(ctx, screenOuter, strokeStyle, true, false);\n }\n for (const hole of polygon.holes) {\n const screenHole = worldToScreenPoints(hole);\n if (screenHole.length >= 4) {\n if (interactionShadowStyle) {\n drawPath(ctx, screenHole, interactionShadowStyle, true, false);\n }\n drawPath(ctx, screenHole, strokeStyle, true, false);\n }\n }\n }\n }\n }\n\n if (preparedPatchRegions.length > 0) {\n for (const entry of preparedPatchRegions) {\n for (const polygon of entry.polygons) {\n const screenOuter = worldToScreenPoints(polygon.outer);\n if (screenOuter.length >= 4) {\n drawPath(ctx, screenOuter, resolvedPatchStrokeStyle, true, false);\n }\n for (const hole of polygon.holes) {\n const screenHole = worldToScreenPoints(hole);\n if (screenHole.length >= 4) {\n drawPath(ctx, screenHole, resolvedPatchStrokeStyle, true, false);\n }\n }\n }\n }\n }\n\n if (Array.isArray(overlayShapes) && overlayShapes.length > 0) {\n const imageOuterRing = worldToScreenPoints(\n closeRing([\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ])\n );\n drawOverlayShapes({\n ctx,\n overlayShapes,\n imageOuterRing,\n worldToScreenPoints,\n baseStrokeStyle: resolvedStrokeStyle,\n onInvertedFillDebug: (globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__\n ? info => {\n const debugKey = String(info.id);\n const debugSignature = `${info.outerRingPoints}|${info.sourceRingCount}|${info.holeRingCount}|${info.fillColor}`;\n if (overlayDebugSnapshotRef.current.get(debugKey) !== debugSignature) {\n overlayDebugSnapshotRef.current.set(debugKey, debugSignature);\n console.debug(\"[open-plant] invertedFill\", info);\n }\n }\n : undefined,\n });\n }\n\n const preview = buildPreviewCoords();\n\n if (active) {\n if (tool === \"brush\") {\n drawBrushStrokePreview(ctx, sessionRef.current, resolvedBrushOptions);\n drawBrushCursor(ctx, sessionRef.current, projectorRef.current, resolvedBrushOptions);\n } else if (preview.length > 0) {\n if (tool === \"freehand\") {\n const line = worldToScreenPoints(preview);\n if (line.length >= 2) {\n drawPath(ctx, line, resolvedStrokeStyle, false, false);\n }\n if (line.length >= 3) {\n drawPath(ctx, worldToScreenPoints(closeRing(preview)), resolvedStrokeStyle, true, true, resolvedDrawPreviewFillColor);\n }\n } else {\n const polygon = worldToScreenPoints(preview);\n if (polygon.length >= 4) {\n drawPath(ctx, polygon, resolvedStrokeStyle, true, true, resolvedDrawPreviewFillColor);\n }\n }\n }\n }\n\n if (preparedPersistedRegions.length > 0) {\n const zoom = Math.max(1e-6, projectorRef.current?.getViewState?.().zoom ?? 1);\n const labelAutoLiftOffset =\n typeof regionLabelAutoLiftOffsetPx === \"number\" && Number.isFinite(regionLabelAutoLiftOffsetPx)\n ? Math.max(0, regionLabelAutoLiftOffsetPx)\n : resolveRegionLabelAutoLiftOffsetPx(\n autoLiftRegionLabelAtMaxZoom,\n zoom,\n projectorRef.current?.getZoomRange?.(),\n projectorRef.current?.getRegionLabelAutoLiftCapZoom?.(),\n );\n for (const entry of preparedPersistedRegions) {\n if (!entry.region.label) continue;\n const anchorScreen = getTopAnchorFromProjectedPolygons(entry.polygons, worldToScreenPoints, regionLabelAnchor);\n if (!anchorScreen) continue;\n let dynamicLabelStyle = mergeRegionLabelStyle(\n resolvedLabelStyle,\n resolveRegionLabelStyleProp?.({\n region: entry.region,\n regionId: entry.regionKey,\n regionIndex: entry.regionIndex,\n zoom,\n })\n );\n if (labelAutoLiftOffset > 0) {\n dynamicLabelStyle = {\n ...dynamicLabelStyle,\n offsetY: dynamicLabelStyle.offsetY + labelAutoLiftOffset,\n };\n }\n drawRegionLabel(ctx, entry.region.label, anchorScreen, canvasWidth, canvasHeight, dynamicLabelStyle, clampRegionLabelToViewport);\n }\n }\n\n if (resolvedDrawAreaTooltipOptions.enabled && active && (tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\")) {\n const session = sessionRef.current;\n if (session.isDrawing) {\n const areaCoords = tool === \"freehand\" ? closeRing(preview) : preview;\n if (areaCoords.length >= 4) {\n const areaPx = polygonArea(areaCoords);\n const mpp = typeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0 ? imageMpp : 0;\n const areaMm2 = mpp > 0 ? (areaPx * mpp * mpp) / (MICRONS_PER_MM * MICRONS_PER_MM) : 0;\n const text = resolvedDrawAreaTooltipOptions.format(areaMm2);\n\n const cursor = session.cursorScreen ?? (session.current ? toCoord(projectorRef.current?.worldToScreen(session.current[0], session.current[1]) ?? []) : null);\n if (cursor) {\n drawAreaTooltipBox(\n ctx,\n text,\n cursor,\n canvasWidth,\n canvasHeight,\n resolvedDrawAreaTooltipOptions.style,\n resolvedDrawAreaTooltipOptions.cursorOffsetX,\n resolvedDrawAreaTooltipOptions.cursorOffsetY\n );\n }\n }\n }\n }\n }, [\n active,\n tool,\n buildPreviewCoords,\n resizeCanvas,\n worldToScreenPoints,\n imageWidth,\n imageHeight,\n projectorRef,\n preparedPersistedRegions,\n overlayShapes,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n resolvedDrawPreviewFillColor,\n preparedPatchRegions,\n resolvedPatchStrokeStyle,\n resolveRegionStrokeStyle,\n resolveRegionLabelStyleProp,\n resolvedLabelStyle,\n resolvedDrawAreaTooltipOptions,\n autoLiftRegionLabelAtMaxZoom,\n regionLabelAnchor,\n clampRegionLabelToViewport,\n regionLabelAutoLiftOffsetPx,\n imageMpp,\n resolvedBrushOptions,\n ]);\n\n const requestDraw = useCallback(() => {\n if (drawPendingRef.current) return;\n drawPendingRef.current = true;\n requestAnimationFrame(() => {\n drawPendingRef.current = false;\n drawOverlay();\n });\n }, [drawOverlay]);\n\n const resetSession = useCallback((preserveCursor = false) => {\n const session = sessionRef.current;\n const canvas = canvasRef.current;\n\n if (canvas && session.pointerId !== null && canvas.hasPointerCapture(session.pointerId)) {\n canvas.releasePointerCapture(session.pointerId);\n }\n\n session.isDrawing = false;\n session.pointerId = null;\n session.start = null;\n session.current = null;\n session.points = [];\n session.screenPoints = [];\n session.stampCenter = null;\n if (!preserveCursor) {\n session.cursor = null;\n session.cursorScreen = null;\n }\n }, []);\n\n const toWorld = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): import(\"./draw-layer-types\").DrawCoordinate | null => {\n const projector = projectorRef.current;\n if (!projector || imageWidth <= 0 || imageHeight <= 0) return null;\n\n const raw = toCoord(projector.screenToWorld(event.clientX, event.clientY));\n if (!raw) return null;\n return clampWorld(raw, imageWidth, imageHeight);\n },\n [projectorRef, imageWidth, imageHeight]\n );\n\n const toLocalScreen = useCallback((event: ReactPointerEvent<HTMLCanvasElement>): import(\"./draw-layer-types\").DrawCoordinate | null => {\n const canvas = canvasRef.current;\n if (!canvas) return null;\n const rect = canvas.getBoundingClientRect();\n const x = clamp(event.clientX - rect.left, 0, rect.width);\n const y = clamp(event.clientY - rect.top, 0, rect.height);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const finishSession = useCallback(() => {\n const session = sessionRef.current;\n if (!session.isDrawing) {\n resetSession(true);\n requestDraw();\n return;\n }\n\n let coordinates: import(\"./draw-layer-types\").DrawCoordinate[] = [];\n if (tool === \"freehand\") {\n if (session.points.length >= FREEHAND_MIN_POINTS) {\n coordinates = closeRing(session.points);\n }\n } else if (tool === \"rectangle\") {\n coordinates = createRectangle(session.start, session.current, getRectangleProjection());\n } else if (tool === \"circular\") {\n coordinates = createCircle(session.start, session.current);\n } else if (tool === \"brush\") {\n const tapPoint = session.points[session.points.length - 1] ?? session.current ?? session.start;\n if (resolvedBrushOptions.clickSelectRoi && tapPoint && session.points.length <= 1 && onBrushTap?.(tapPoint)) {\n resetSession(true);\n requestDraw();\n return;\n }\n const edgeDetail = Math.max(0.25, resolvedBrushOptions.edgeDetail);\n const screenPath = session.screenPoints.length > 0 ? session.screenPoints : worldToScreenPoints(session.points);\n const simplifyTolerance = Math.max(0.5, (resolvedBrushOptions.radius * 0.04) / edgeDetail);\n const screenPolygon = buildBrushStrokePolygon(screenPath, {\n radius: resolvedBrushOptions.radius,\n circleSides: Math.max(16, Math.round(32 * edgeDetail)),\n simplifyTolerance,\n smoothingPasses: resolvedBrushOptions.edgeSmoothing,\n }) as import(\"./draw-layer-types\").DrawCoordinate[];\n const worldPolygon: import(\"./draw-layer-types\").DrawCoordinate[] = [];\n for (const point of screenPolygon) {\n const world = localScreenToWorld(point);\n if (!world) continue;\n worldPolygon.push(world);\n }\n coordinates = closeRing(worldPolygon);\n }\n\n if ((tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\" || tool === \"brush\") && isValidPolygon(coordinates) && onDrawComplete) {\n const intent: import(\"./draw-layer-types\").DrawIntent = tool === \"brush\" ? \"brush\" : \"roi\";\n onDrawComplete({\n tool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n });\n }\n\n resetSession(true);\n requestDraw();\n }, [\n tool,\n onDrawComplete,\n resetSession,\n requestDraw,\n worldToScreenPoints,\n localScreenToWorld,\n getRectangleProjection,\n resolvedBrushOptions.radius,\n resolvedBrushOptions.edgeDetail,\n resolvedBrushOptions.edgeSmoothing,\n resolvedBrushOptions.clickSelectRoi,\n onBrushTap,\n ]);\n\n const handleStampAt = useCallback(\n (stampTool: StampDrawTool, center: import(\"./draw-layer-types\").DrawCoordinate): void => {\n const coordinates = buildStampCoordsCallback(stampTool, center);\n if (!isValidPolygon(coordinates)) return;\n const intent: import(\"./draw-layer-types\").DrawIntent = stampTool === \"stamp-rectangle-4096px\" ? \"patch\" : \"roi\";\n const result: import(\"./draw-layer-types\").DrawResult = {\n tool: stampTool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n };\n onDrawComplete?.(result);\n if (intent === \"patch\" && onPatchComplete) {\n onPatchComplete(result as import(\"./draw-layer-types\").PatchDrawResult);\n }\n },\n [buildStampCoordsCallback, onDrawComplete, onPatchComplete]\n );\n\n const appendBrushPoint = useCallback(\n (session: DrawSession, world: import(\"./draw-layer-types\").DrawCoordinate, screen: import(\"./draw-layer-types\").DrawCoordinate): void => {\n const minScreenStep = Math.max(BRUSH_SCREEN_STEP, resolvedBrushOptions.radius * 0.1);\n const minScreenStep2 = minScreenStep * minScreenStep;\n const prevScreen = session.screenPoints[session.screenPoints.length - 1];\n if (!prevScreen) {\n session.points.push(world);\n session.screenPoints.push(screen);\n session.current = world;\n return;\n }\n const dx = screen[0] - prevScreen[0];\n const dy = screen[1] - prevScreen[1];\n if (dx * dx + dy * dy >= minScreenStep2) {\n session.points.push(world);\n session.screenPoints.push(screen);\n } else {\n session.points[session.points.length - 1] = world;\n session.screenPoints[session.screenPoints.length - 1] = screen;\n }\n session.current = world;\n },\n [resolvedBrushOptions.radius]\n );\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n if (event.button !== 0) return;\n\n const world = toWorld(event);\n if (!world) return;\n const screen = toLocalScreen(event);\n if (!screen) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n handleStampAt(tool, world);\n requestDraw();\n return;\n }\n\n const canvas = canvasRef.current;\n if (canvas) {\n canvas.setPointerCapture(event.pointerId);\n }\n\n const session = sessionRef.current;\n session.isDrawing = true;\n session.pointerId = event.pointerId;\n session.start = world;\n session.current = world;\n session.cursor = world;\n session.cursorScreen = screen;\n session.points = tool === \"freehand\" || tool === \"brush\" ? [world] : [];\n session.screenPoints = tool === \"brush\" ? [screen] : [];\n requestDraw();\n },\n [active, tool, toWorld, toLocalScreen, handleStampAt, requestDraw]\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n\n const world = toWorld(event);\n if (!world) return;\n const screen = toLocalScreen(event);\n if (!screen) return;\n\n const session = sessionRef.current;\n session.cursor = world;\n session.cursorScreen = screen;\n\n if (isStampTool(tool)) {\n session.stampCenter = world;\n event.preventDefault();\n event.stopPropagation();\n requestDraw();\n return;\n }\n\n if (tool === \"brush\") {\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n requestDraw();\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n appendBrushPoint(session, world, screen);\n requestDraw();\n return;\n }\n\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n if (tool === \"freehand\") {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = FREEHAND_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n\n if (!prev) {\n session.points.push(world);\n } else {\n const dx = world[0] - prev[0];\n const dy = world[1] - prev[1];\n if (dx * dx + dy * dy >= minWorldStep2) {\n session.points.push(world);\n }\n }\n } else {\n session.current = world;\n }\n\n requestDraw();\n },\n [active, tool, toWorld, toLocalScreen, requestDraw, projectorRef, appendBrushPoint]\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.pointerId !== event.pointerId) return;\n\n event.preventDefault();\n event.stopPropagation();\n const world = toWorld(event);\n const screen = toLocalScreen(event);\n if (world) {\n session.cursor = world;\n if (screen) {\n session.cursorScreen = screen;\n }\n if (tool === \"brush\") {\n if (screen) {\n appendBrushPoint(session, world, screen);\n }\n } else {\n session.current = world;\n }\n }\n const canvas = canvasRef.current;\n if (canvas && canvas.hasPointerCapture(event.pointerId)) {\n canvas.releasePointerCapture(event.pointerId);\n }\n\n finishSession();\n },\n [finishSession, toWorld, toLocalScreen, tool, appendBrushPoint]\n );\n\n const handlePointerLeave = useCallback(() => {\n const session = sessionRef.current;\n let changed = false;\n if (tool === \"brush\" && !session.isDrawing && session.cursor) {\n session.cursor = null;\n session.cursorScreen = null;\n changed = true;\n }\n if (isStampTool(tool) && session.stampCenter) {\n session.stampCenter = null;\n changed = true;\n }\n if (changed) {\n requestDraw();\n }\n }, [tool, requestDraw]);\n\n useEffect(() => {\n resizeCanvas();\n requestDraw();\n\n const canvas = canvasRef.current;\n if (!canvas) return undefined;\n\n const observer = new ResizeObserver(() => {\n resizeCanvas();\n requestDraw();\n });\n observer.observe(canvas);\n\n return () => {\n observer.disconnect();\n };\n }, [resizeCanvas, requestDraw]);\n\n useEffect(() => observeDevicePixelRatioChanges(() => {\n resizeCanvas();\n requestDraw();\n }), [resizeCanvas, requestDraw]);\n\n useEffect(() => {\n if (!active) {\n resetSession();\n }\n requestDraw();\n }, [active, requestDraw, resetSession]);\n\n useEffect(() => {\n if (lastToolRef.current === tool) {\n return;\n }\n lastToolRef.current = tool;\n resetSession();\n requestDraw();\n }, [tool, resetSession, requestDraw]);\n\n useEffect(() => {\n requestDraw();\n }, [viewStateSignal, mergedPersistedRegions, overlayShapes, requestDraw]);\n\n useEffect(() => {\n if (!invalidateRef) return undefined;\n invalidateRef.current = requestDraw;\n return () => {\n if (invalidateRef.current === requestDraw) {\n invalidateRef.current = null;\n }\n };\n }, [invalidateRef, requestDraw]);\n\n useEffect(() => {\n if (!active) return undefined;\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n resetSession();\n requestDraw();\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [active, resetSession, requestDraw]);\n\n return (\n <canvas\n ref={canvasRef}\n className={className}\n style={mergedStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onPointerLeave={handlePointerLeave}\n onContextMenu={event => {\n if (active) event.preventDefault();\n }}\n onWheel={event => {\n if (!active) return;\n const canvas = canvasRef.current;\n const projector = projectorRef.current;\n const hasWheelZoom = typeof projector?.handleWheelZoom === \"function\";\n const hasLegacyZoom = typeof projector?.zoomBy === \"function\";\n if (!canvas || (!hasWheelZoom && !hasLegacyZoom)) return;\n event.preventDefault();\n event.stopPropagation();\n const rect = canvas.getBoundingClientRect();\n const screenX = event.clientX - rect.left;\n const screenY = event.clientY - rect.top;\n if (hasWheelZoom) {\n projector.handleWheelZoom?.(event.deltaY, screenX, screenY);\n } else {\n projector.zoomBy?.(event.deltaY < 0 ? WHEEL_ZOOM_IN_FACTOR : WHEEL_ZOOM_OUT_FACTOR, screenX, screenY);\n }\n requestDraw();\n }}\n />\n );\n}\n","import { createContext, type MutableRefObject, type RefObject, useContext } from \"react\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate } from \"./draw-layer-types\";\n\nexport type OverlayDrawFn = (ctx: CanvasRenderingContext2D, width: number, height: number) => void;\n\nexport interface ViewerContextValue {\n source: WsiImageSource | null;\n rendererRef: RefObject<WsiTileRenderer | null>;\n rendererSerial: number;\n canvasRef: RefObject<HTMLCanvasElement | null>;\n containerRef: RefObject<HTMLDivElement | null>;\n drawInvalidateRef: MutableRefObject<(() => void) | null>;\n overviewInvalidateRef: MutableRefObject<(() => void) | null>;\n\n worldToScreen: (worldX: number, worldY: number) => DrawCoordinate | null;\n screenToWorld: (clientX: number, clientY: number) => DrawCoordinate | null;\n\n registerDrawCallback: (id: string, priority: number, draw: OverlayDrawFn) => void;\n unregisterDrawCallback: (id: string) => void;\n requestOverlayRedraw: () => void;\n\n registerViewStateListener: (listener: (state: WsiViewState) => void) => () => void;\n\n setInteractionLock: (id: string, locked: boolean) => void;\n isInteractionLocked: () => boolean;\n}\n\nconst ViewerContext = createContext<ViewerContextValue | null>(null);\n\nexport const ViewerContextProvider = ViewerContext.Provider;\n\nexport function useViewerContext(): ViewerContextValue {\n const ctx = useContext(ViewerContext);\n if (!ctx) {\n throw new Error(\"useViewerContext must be used within a <WsiViewer>\");\n }\n return ctx;\n}\n\nexport function useOptionalViewerContext(): ViewerContextValue | null {\n return useContext(ViewerContext);\n}\n","import { useEffect, useMemo } from \"react\";\nimport { DrawLayer } from \"./draw-layer\";\nimport type { BrushOptions, DrawAreaTooltipOptions, DrawCoordinate, DrawResult, DrawTool, PatchDrawResult, StampOptions } from \"./draw-layer-types\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport interface DrawingLayerProps {\n tool?: DrawTool;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n fillColor?: string;\n areaTooltip?: DrawAreaTooltipOptions;\n onComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n onBrushTap?: (coordinate: DrawCoordinate) => boolean;\n}\n\nexport function DrawingLayer({ tool = \"cursor\", stampOptions, brushOptions, fillColor, areaTooltip, onComplete, onPatchComplete, onBrushTap }: DrawingLayerProps): React.ReactElement | null {\n const { source, rendererRef, rendererSerial, setInteractionLock } = useViewerContext();\n\n const active = tool !== \"cursor\";\n\n useEffect(() => {\n setInteractionLock(\"drawing-layer\", active);\n return () => setInteractionLock(\"drawing-layer\", false);\n }, [active, setInteractionLock]);\n\n const viewStateSignal = useMemo(() => rendererRef.current?.getViewState(), [rendererSerial]);\n\n if (!source) return null;\n\n return (\n <DrawLayer\n tool={tool}\n enabled={active}\n imageWidth={source.width}\n imageHeight={source.height}\n imageMpp={source.mpp}\n imageZoom={source.maxTierZoom}\n stampOptions={stampOptions}\n brushOptions={brushOptions}\n drawFillColor={fillColor}\n projectorRef={rendererRef}\n onBrushTap={onBrushTap}\n viewStateSignal={viewStateSignal}\n drawAreaTooltip={areaTooltip}\n onDrawComplete={onComplete}\n onPatchComplete={onPatchComplete}\n />\n );\n}\n","export type SpatialExtent = [number, number, number, number];\n\nexport interface SpatialIndexItem<T> {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n value: T;\n}\n\nexport interface SpatialIndex<T> {\n load(items: SpatialIndexItem<T>[]): void;\n search(extent: SpatialExtent): SpatialIndexItem<T>[];\n}\n\nfunction normalizeExtent(minX: number, minY: number, maxX: number, maxY: number): SpatialExtent {\n return [Math.min(minX, maxX), Math.min(minY, maxY), Math.max(minX, maxX), Math.max(minY, maxY)];\n}\n\nfunction intersects(a: SpatialExtent, b: SpatialExtent): boolean {\n return !(a[2] < b[0] || a[0] > b[2] || a[3] < b[1] || a[1] > b[3]);\n}\n\nclass GridSpatialIndex<T> implements SpatialIndex<T> {\n private readonly targetNodeSize: number;\n\n private items: SpatialIndexItem<T>[] = [];\n\n private globalBounds: SpatialExtent = [0, 0, 0, 0];\n\n private gridSize = 1;\n\n private cellWidth = 1;\n\n private cellHeight = 1;\n\n private buckets: number[][] = [];\n\n private visited = new Uint32Array(0);\n\n private querySerial = 1;\n\n constructor(nodeSize = 16) {\n const finite = Number.isFinite(nodeSize) ? Math.floor(nodeSize) : 16;\n this.targetNodeSize = Math.max(1, finite);\n }\n\n load(items: SpatialIndexItem<T>[]): void {\n if (!Array.isArray(items) || items.length === 0) {\n this.items = [];\n this.globalBounds = [0, 0, 0, 0];\n this.gridSize = 1;\n this.cellWidth = 1;\n this.cellHeight = 1;\n this.buckets = [];\n this.visited = new Uint32Array(0);\n this.querySerial = 1;\n return;\n }\n\n const normalized: SpatialIndexItem<T>[] = [];\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const item of items) {\n if (!item) continue;\n if (!Number.isFinite(item.minX) || !Number.isFinite(item.minY) || !Number.isFinite(item.maxX) || !Number.isFinite(item.maxY)) {\n continue;\n }\n const bounds = normalizeExtent(item.minX, item.minY, item.maxX, item.maxY);\n minX = Math.min(minX, bounds[0]);\n minY = Math.min(minY, bounds[1]);\n maxX = Math.max(maxX, bounds[2]);\n maxY = Math.max(maxY, bounds[3]);\n normalized.push({\n minX: bounds[0],\n minY: bounds[1],\n maxX: bounds[2],\n maxY: bounds[3],\n value: item.value,\n });\n }\n\n this.items = normalized;\n this.visited = new Uint32Array(normalized.length);\n this.querySerial = 1;\n\n if (normalized.length === 0 || !Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {\n this.globalBounds = [0, 0, 0, 0];\n this.gridSize = 1;\n this.cellWidth = 1;\n this.cellHeight = 1;\n this.buckets = [];\n return;\n }\n\n this.globalBounds = [minX, minY, maxX, maxY];\n this.gridSize = Math.max(1, Math.ceil(Math.sqrt(normalized.length / this.targetNodeSize)));\n\n const spanX = Math.max(0, maxX - minX);\n const spanY = Math.max(0, maxY - minY);\n this.cellWidth = spanX > 0 ? spanX / this.gridSize : 1;\n this.cellHeight = spanY > 0 ? spanY / this.gridSize : 1;\n\n const bucketCount = this.gridSize * this.gridSize;\n this.buckets = Array.from({ length: bucketCount }, () => []);\n\n for (let index = 0; index < normalized.length; index += 1) {\n const item = normalized[index];\n const minCellX = this.toCellX(item.minX);\n const maxCellX = this.toCellX(item.maxX);\n const minCellY = this.toCellY(item.minY);\n const maxCellY = this.toCellY(item.maxY);\n for (let y = minCellY; y <= maxCellY; y += 1) {\n for (let x = minCellX; x <= maxCellX; x += 1) {\n this.buckets[y * this.gridSize + x].push(index);\n }\n }\n }\n }\n\n search(extent: SpatialExtent): SpatialIndexItem<T>[] {\n if (this.items.length === 0) return [];\n if (!Array.isArray(extent) || extent.length < 4) return [];\n\n const query = normalizeExtent(extent[0], extent[1], extent[2], extent[3]);\n if (!intersects(query, this.globalBounds)) return [];\n\n const minCellX = this.toCellX(query[0]);\n const maxCellX = this.toCellX(query[2]);\n const minCellY = this.toCellY(query[1]);\n const maxCellY = this.toCellY(query[3]);\n\n const serial = this.nextSerial();\n const out: SpatialIndexItem<T>[] = [];\n\n for (let y = minCellY; y <= maxCellY; y += 1) {\n for (let x = minCellX; x <= maxCellX; x += 1) {\n const bucket = this.buckets[y * this.gridSize + x];\n if (!bucket || bucket.length === 0) continue;\n for (const itemIndex of bucket) {\n if (this.visited[itemIndex] === serial) continue;\n this.visited[itemIndex] = serial;\n const item = this.items[itemIndex];\n if (!intersects(query, [item.minX, item.minY, item.maxX, item.maxY])) continue;\n out.push(item);\n }\n }\n }\n\n return out;\n }\n\n private nextSerial(): number {\n this.querySerial += 1;\n if (this.querySerial === 0xffffffff) {\n this.visited.fill(0);\n this.querySerial = 1;\n }\n return this.querySerial;\n }\n\n private toCellX(x: number): number {\n const minX = this.globalBounds[0];\n const maxX = this.globalBounds[2];\n if (this.gridSize <= 1 || maxX <= minX) return 0;\n const ratio = (x - minX) / this.cellWidth;\n if (!Number.isFinite(ratio)) return 0;\n if (ratio <= 0) return 0;\n if (ratio >= this.gridSize - 1) return this.gridSize - 1;\n return Math.max(0, Math.min(this.gridSize - 1, Math.floor(ratio)));\n }\n\n private toCellY(y: number): number {\n const minY = this.globalBounds[1];\n const maxY = this.globalBounds[3];\n if (this.gridSize <= 1 || maxY <= minY) return 0;\n const ratio = (y - minY) / this.cellHeight;\n if (!Number.isFinite(ratio)) return 0;\n if (ratio <= 0) return 0;\n if (ratio >= this.gridSize - 1) return this.gridSize - 1;\n return Math.max(0, Math.min(this.gridSize - 1, Math.floor(ratio)));\n }\n}\n\nexport function createSpatialIndex<T>(nodeSize?: number): SpatialIndex<T> {\n return new GridSpatialIndex<T>(nodeSize);\n}\n\n","import { createProgram } from \"../core/gl-utils\";\n\nconst ACCUM_VERTEX_SHADER = `#version 300 es\nprecision highp float;\nin vec2 aCenter;\nin float aWeight;\nuniform vec2 uResolution;\nuniform float uPointSize;\nout float vWeight;\nvoid main() {\n vec2 zeroToOne = aCenter / uResolution;\n vec2 clip = vec2(zeroToOne.x * 2.0 - 1.0, 1.0 - zeroToOne.y * 2.0);\n gl_Position = vec4(clip, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vWeight = aWeight;\n}`;\n\nconst ACCUM_FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\nin float vWeight;\nuniform float uCoreRatio;\nuniform float uPointAlpha;\nout vec4 outColor;\nvoid main() {\n vec2 pointCoord = gl_PointCoord * 2.0 - 1.0;\n float radius = length(pointCoord);\n if (radius > 1.0) discard;\n\n float coreRatio = clamp(uCoreRatio, 0.02, 0.98);\n float intensity = 1.0 - smoothstep(coreRatio, 1.0, radius);\n float alpha = intensity * max(0.0, vWeight) * max(0.0, uPointAlpha);\n if (alpha <= 0.0001) discard;\n outColor = vec4(0.0, 0.0, 0.0, alpha);\n}`;\n\nconst COLOR_VERTEX_SHADER = `#version 300 es\nprecision highp float;\nin vec2 aPosition;\nvoid main() {\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}`;\n\nconst COLOR_FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\nuniform sampler2D uAccumTexture;\nuniform sampler2D uGradientTexture;\nuniform float uOpacity;\nuniform float uCutoff;\nuniform float uGain;\nuniform float uGamma;\nuniform float uBias;\nuniform float uStretch;\nuniform vec2 uResolution;\nout vec4 outColor;\nvoid main() {\n vec2 accumUv = vec2(\n (gl_FragCoord.x - 0.5) / max(1.0, uResolution.x),\n (gl_FragCoord.y - 0.5) / max(1.0, uResolution.y)\n );\n float density = texture(uAccumTexture, accumUv).a;\n if (density <= uCutoff) discard;\n\n float boosted = 1.0 - exp(-max(0.0, density - uCutoff) * uGain);\n float contrast = clamp(uGamma, 0.35, 6.0);\n float bias = clamp(uBias, 0.0, 0.92);\n float biased = max(0.0, boosted - bias);\n float stretched = pow(\n biased / max(1e-5, 1.0 - bias),\n 1.0 / clamp(uStretch, 1.0, 4.0)\n );\n float normalized = pow(stretched, 1.0 / contrast);\n float shoulder = 1.0 - pow(max(0.0, 1.0 - normalized), 1.0 + max(0.0, contrast - 1.0));\n float shoulderBlend = clamp((contrast - 1.0) * 0.32, 0.0, 0.78);\n float gradientT = mix(normalized, shoulder, shoulderBlend);\n vec4 gradientColor = texture(uGradientTexture, vec2(gradientT, 0.5));\n float alpha = gradientColor.a * clamp(uOpacity, 0.0, 1.0);\n if (alpha <= 0.0001) discard;\n outColor = vec4(gradientColor.rgb * alpha, alpha);\n}`;\n\nexport interface HeatmapWebGLRenderParams {\n width: number;\n height: number;\n positions: Float32Array;\n weights: Float32Array;\n count: number;\n kernelRadiusPx: number;\n blurRadiusPx: number;\n pointAlpha: number;\n gradient: readonly string[];\n opacity: number;\n cutoff?: number;\n gain?: number;\n gamma?: number;\n bias?: number;\n stretch?: number;\n}\n\nexport class HeatmapWebGLRenderer {\n readonly canvas: HTMLCanvasElement;\n\n private readonly gl: WebGL2RenderingContext;\n\n private readonly accumProgram: WebGLProgram;\n\n private readonly colorProgram: WebGLProgram;\n\n private readonly accumVao: WebGLVertexArrayObject;\n\n private readonly colorVao: WebGLVertexArrayObject;\n\n private readonly pointBuffer: WebGLBuffer;\n\n private readonly quadBuffer: WebGLBuffer;\n\n private readonly accumTexture: WebGLTexture;\n\n private readonly gradientTexture: WebGLTexture;\n\n private readonly framebuffer: WebGLFramebuffer;\n\n private readonly accumInternalFormat: number;\n\n private readonly accumTextureFormat: number;\n\n private readonly accumTextureType: number;\n\n private readonly uAccumResolution: WebGLUniformLocation;\n\n private readonly uAccumPointSize: WebGLUniformLocation;\n\n private readonly uAccumCoreRatio: WebGLUniformLocation;\n\n private readonly uAccumPointAlpha: WebGLUniformLocation;\n\n private readonly uColorAccumTexture: WebGLUniformLocation;\n\n private readonly uColorGradientTexture: WebGLUniformLocation;\n\n private readonly uColorOpacity: WebGLUniformLocation;\n\n private readonly uColorCutoff: WebGLUniformLocation;\n\n private readonly uColorGain: WebGLUniformLocation;\n\n private readonly uColorResolution: WebGLUniformLocation;\n\n private readonly uColorGamma: WebGLUniformLocation;\n\n private readonly uColorBias: WebGLUniformLocation;\n\n private readonly uColorStretch: WebGLUniformLocation;\n\n private pointCapacity = 0;\n\n private interleavedCapacity = 0;\n\n private interleavedBuffer: Float32Array | null = null;\n\n private gradientKey = \"\";\n\n constructor() {\n this.canvas = document.createElement(\"canvas\");\n const gl = this.canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: true,\n premultipliedAlpha: true,\n powerPreference: \"high-performance\",\n });\n if (!gl) {\n throw new Error(\"WebGL2 is not available for heatmap rendering.\");\n }\n this.gl = gl;\n\n const colorBufferFloat = gl.getExtension(\"EXT_color_buffer_float\");\n const supportsFloatAccum = Boolean(colorBufferFloat);\n this.accumInternalFormat = supportsFloatAccum ? gl.RGBA16F : gl.RGBA8;\n this.accumTextureFormat = gl.RGBA;\n this.accumTextureType = supportsFloatAccum ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;\n\n this.accumProgram = createProgram(gl, ACCUM_VERTEX_SHADER, ACCUM_FRAGMENT_SHADER);\n this.colorProgram = createProgram(gl, COLOR_VERTEX_SHADER, COLOR_FRAGMENT_SHADER);\n\n const accumVao = gl.createVertexArray();\n const colorVao = gl.createVertexArray();\n const pointBuffer = gl.createBuffer();\n const quadBuffer = gl.createBuffer();\n const accumTexture = gl.createTexture();\n const gradientTexture = gl.createTexture();\n const framebuffer = gl.createFramebuffer();\n if (!accumVao || !colorVao || !pointBuffer || !quadBuffer || !accumTexture || !gradientTexture || !framebuffer) {\n throw new Error(\"Failed to allocate heatmap WebGL resources.\");\n }\n this.accumVao = accumVao;\n this.colorVao = colorVao;\n this.pointBuffer = pointBuffer;\n this.quadBuffer = quadBuffer;\n this.accumTexture = accumTexture;\n this.gradientTexture = gradientTexture;\n this.framebuffer = framebuffer;\n\n const accumResolution = gl.getUniformLocation(this.accumProgram, \"uResolution\");\n const accumPointSize = gl.getUniformLocation(this.accumProgram, \"uPointSize\");\n const accumCoreRatio = gl.getUniformLocation(this.accumProgram, \"uCoreRatio\");\n const accumPointAlpha = gl.getUniformLocation(this.accumProgram, \"uPointAlpha\");\n const colorAccumTexture = gl.getUniformLocation(this.colorProgram, \"uAccumTexture\");\n const colorGradientTexture = gl.getUniformLocation(this.colorProgram, \"uGradientTexture\");\n const colorOpacity = gl.getUniformLocation(this.colorProgram, \"uOpacity\");\n const colorCutoff = gl.getUniformLocation(this.colorProgram, \"uCutoff\");\n const colorGain = gl.getUniformLocation(this.colorProgram, \"uGain\");\n const colorGamma = gl.getUniformLocation(this.colorProgram, \"uGamma\");\n const colorBias = gl.getUniformLocation(this.colorProgram, \"uBias\");\n const colorStretch = gl.getUniformLocation(this.colorProgram, \"uStretch\");\n const colorResolution = gl.getUniformLocation(this.colorProgram, \"uResolution\");\n if (!accumResolution || !accumPointSize || !accumCoreRatio || !accumPointAlpha || !colorAccumTexture || !colorGradientTexture || !colorOpacity || !colorCutoff || !colorGain || !colorGamma || !colorBias || !colorStretch || !colorResolution) {\n throw new Error(\"Failed to resolve heatmap WebGL uniforms.\");\n }\n this.uAccumResolution = accumResolution;\n this.uAccumPointSize = accumPointSize;\n this.uAccumCoreRatio = accumCoreRatio;\n this.uAccumPointAlpha = accumPointAlpha;\n this.uColorAccumTexture = colorAccumTexture;\n this.uColorGradientTexture = colorGradientTexture;\n this.uColorOpacity = colorOpacity;\n this.uColorCutoff = colorCutoff;\n this.uColorGain = colorGain;\n this.uColorGamma = colorGamma;\n this.uColorBias = colorBias;\n this.uColorStretch = colorStretch;\n this.uColorResolution = colorResolution;\n\n gl.bindVertexArray(this.accumVao);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n const centerLocation = gl.getAttribLocation(this.accumProgram, \"aCenter\");\n const weightLocation = gl.getAttribLocation(this.accumProgram, \"aWeight\");\n if (centerLocation < 0 || weightLocation < 0) {\n throw new Error(\"Failed to resolve heatmap WebGL attributes.\");\n }\n gl.enableVertexAttribArray(centerLocation);\n gl.vertexAttribPointer(centerLocation, 2, gl.FLOAT, false, 12, 0);\n gl.enableVertexAttribArray(weightLocation);\n gl.vertexAttribPointer(weightLocation, 1, gl.FLOAT, false, 12, 8);\n gl.bindVertexArray(null);\n\n gl.bindVertexArray(this.colorVao);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n -1, -1,\n 1, -1,\n -1, 1,\n 1, 1,\n ]), gl.STATIC_DRAW);\n const positionLocation = gl.getAttribLocation(this.colorProgram, \"aPosition\");\n if (positionLocation < 0) {\n throw new Error(\"Failed to resolve heatmap color position attribute.\");\n }\n gl.enableVertexAttribArray(positionLocation);\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 8, 0);\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n gl.bindTexture(gl.TEXTURE_2D, this.accumTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.ensureCanvasSize(1, 1);\n }\n\n render(params: HeatmapWebGLRenderParams): boolean {\n if (params.count <= 0 || params.width <= 0 || params.height <= 0) {\n return false;\n }\n\n this.ensureCanvasSize(params.width, params.height);\n this.ensureGradientTexture(params.gradient);\n this.uploadPointData(params.positions, params.weights, params.count);\n\n const gl = this.gl;\n gl.disable(gl.SCISSOR_TEST);\n gl.disable(gl.DEPTH_TEST);\n gl.disable(gl.CULL_FACE);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.viewport(0, 0, params.width, params.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(this.accumProgram);\n gl.bindVertexArray(this.accumVao);\n gl.uniform2f(this.uAccumResolution, params.width, params.height);\n gl.uniform1f(this.uAccumPointSize, Math.max(1, (params.kernelRadiusPx + params.blurRadiusPx) * 2));\n gl.uniform1f(this.uAccumCoreRatio, params.kernelRadiusPx / Math.max(1e-6, params.kernelRadiusPx + params.blurRadiusPx));\n gl.uniform1f(this.uAccumPointAlpha, Math.max(0, params.pointAlpha));\n gl.enable(gl.BLEND);\n gl.blendEquation(gl.FUNC_ADD);\n gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);\n gl.drawArrays(gl.POINTS, 0, params.count);\n gl.disable(gl.BLEND);\n gl.bindVertexArray(null);\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, params.width, params.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n gl.useProgram(this.colorProgram);\n gl.bindVertexArray(this.colorVao);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.accumTexture);\n gl.uniform1i(this.uColorAccumTexture, 0);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture);\n gl.uniform1i(this.uColorGradientTexture, 1);\n gl.uniform1f(this.uColorOpacity, params.opacity);\n gl.uniform1f(this.uColorCutoff, params.cutoff ?? 0.008);\n gl.uniform1f(this.uColorGain, params.gain ?? 2.6);\n gl.uniform1f(this.uColorGamma, params.gamma ?? 1.0);\n gl.uniform1f(this.uColorBias, params.bias ?? 0);\n gl.uniform1f(this.uColorStretch, params.stretch ?? 1);\n gl.uniform2f(this.uColorResolution, params.width, params.height);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n gl.bindVertexArray(null);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.flush();\n\n return true;\n }\n\n destroy(): void {\n const gl = this.gl;\n gl.deleteTexture(this.accumTexture);\n gl.deleteTexture(this.gradientTexture);\n gl.deleteFramebuffer(this.framebuffer);\n gl.deleteBuffer(this.pointBuffer);\n gl.deleteBuffer(this.quadBuffer);\n gl.deleteVertexArray(this.accumVao);\n gl.deleteVertexArray(this.colorVao);\n gl.deleteProgram(this.accumProgram);\n gl.deleteProgram(this.colorProgram);\n this.canvas.width = 0;\n this.canvas.height = 0;\n }\n\n private ensureCanvasSize(width: number, height: number): void {\n const safeWidth = Math.max(1, Math.round(width));\n const safeHeight = Math.max(1, Math.round(height));\n if (this.canvas.width !== safeWidth) {\n this.canvas.width = safeWidth;\n }\n if (this.canvas.height !== safeHeight) {\n this.canvas.height = safeHeight;\n }\n\n const gl = this.gl;\n gl.bindTexture(gl.TEXTURE_2D, this.accumTexture);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n this.accumInternalFormat,\n safeWidth,\n safeHeight,\n 0,\n this.accumTextureFormat,\n this.accumTextureType,\n null,\n );\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.accumTexture, 0);\n const framebufferStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n if (framebufferStatus !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(`Heatmap framebuffer incomplete: ${framebufferStatus}`);\n }\n }\n\n private ensureGradientTexture(colors: readonly string[]): void {\n const nextKey = colors.join(\"|\");\n if (this.gradientKey === nextKey) return;\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = 256;\n canvas.height = 1;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n throw new Error(\"Failed to create heatmap gradient canvas.\");\n }\n\n const gradient = ctx.createLinearGradient(0, 0, 256, 0);\n const stops = colors.length > 1 ? colors : [\"#00000000\", \"#3876FF\", \"#4CDDDD\", \"#FFE75C\", \"#FF8434\", \"#FF3434\"];\n const step = 1 / Math.max(1, stops.length - 1);\n for (let index = 0; index < stops.length; index += 1) {\n gradient.addColorStop(index * step, stops[index]);\n }\n ctx.clearRect(0, 0, 256, 1);\n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, 256, 1);\n\n const pixels = ctx.getImageData(0, 0, 256, 1).data;\n const gl = this.gl;\n gl.bindTexture(gl.TEXTURE_2D, this.gradientTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.gradientKey = nextKey;\n }\n\n private uploadPointData(positions: Float32Array, weights: Float32Array, count: number): void {\n const gl = this.gl;\n const requiredFloats = count * 3;\n const bytes = requiredFloats * 4;\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);\n if (count > this.pointCapacity) {\n gl.bufferData(gl.ARRAY_BUFFER, bytes, gl.DYNAMIC_DRAW);\n this.pointCapacity = count;\n }\n\n if (requiredFloats > this.interleavedCapacity) {\n this.interleavedCapacity = requiredFloats;\n this.interleavedBuffer = new Float32Array(requiredFloats);\n }\n const interleaved = this.interleavedBuffer;\n if (!interleaved) {\n throw new Error(\"Failed to allocate heatmap upload buffer.\");\n }\n for (let index = 0; index < count; index += 1) {\n const sourceOffset = index * 2;\n const targetOffset = index * 3;\n interleaved[targetOffset] = positions[sourceOffset] ?? 0;\n interleaved[targetOffset + 1] = positions[sourceOffset + 1] ?? 0;\n interleaved[targetOffset + 2] = weights[index] ?? 0;\n }\n gl.bufferSubData(gl.ARRAY_BUFFER, 0, interleaved.subarray(0, requiredFloats));\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n }\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport type { PreparedRoiPolygon } from \"../wsi/roi-geometry\";\nimport { pointInAnyPreparedPolygon, prepareRoiPolygons, toRoiGeometry } from \"../wsi/roi-geometry\";\nimport { createSpatialIndex, type SpatialIndex } from \"../wsi/spatial-index\";\nimport type { WsiImageSource, WsiRegion } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\nimport { tracePath } from \"./draw-layer-utils\";\nimport { HeatmapWebGLRenderer } from \"./heatmap-webgl\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport type HeatmapKernelScaleMode = \"screen\" | \"fixed-zoom\";\n\nexport interface HeatmapPointData {\n count: number;\n positions: Float32Array;\n weights?: Float32Array;\n}\n\nexport interface HeatmapLayerStats {\n pointCount: number;\n renderTimeMs: number;\n visiblePointCount: number;\n renderedBinCount: number;\n sampleStride: number;\n maxDensity: number;\n}\n\nexport interface HeatmapLayerProps {\n data: HeatmapPointData | null;\n visible?: boolean;\n opacity?: number;\n radius?: number;\n blur?: number;\n gradient?: readonly string[];\n backgroundColor?: string | null;\n scaleMode?: HeatmapKernelScaleMode;\n fixedZoom?: number;\n zoomThreshold?: number;\n densityContrast?: number;\n clipToRegions?: readonly WsiRegion[];\n zIndex?: number;\n maxRenderedPoints?: number;\n onStats?: (stats: HeatmapLayerStats) => void;\n}\n\ninterface HeatmapCell {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n worldX: number;\n worldY: number;\n renderWorldX: number;\n renderWorldY: number;\n weight: number;\n count: number;\n}\n\ninterface HeatmapLevel {\n cellWorldSize: number;\n bins: HeatmapCell[];\n index: SpatialIndex<number>;\n normalizationUpperWeight: number;\n}\n\ninterface HeatmapSourceData {\n dataRef: HeatmapPointData | null;\n sourceRef: WsiImageSource | null;\n positionsRef: Float32Array;\n weightsRef?: Float32Array;\n inputCount: number;\n clipRef: readonly PreparedRoiPolygon[] | null;\n clipKey: string;\n pointCount: number;\n xs: Float32Array;\n ys: Float32Array;\n ws: Float32Array;\n pointIndex: SpatialIndex<number>;\n cellSizes: number[];\n levels: Array<HeatmapLevel | null>;\n}\n\ninterface HeatmapFixedState {\n dataRef: HeatmapPointData | null;\n positionsRef: Float32Array;\n weightsRef?: Float32Array;\n inputCount: number;\n clipRef: readonly PreparedRoiPolygon[] | null;\n clipKey: string;\n referenceZoom: number;\n referenceRawZoom: number;\n heatmapScale: number;\n kernelWorldRadius: number;\n blurWorldRadius: number;\n sampleProbability: number;\n sampleStride: number;\n pointAlpha: number;\n}\n\ninterface HeatmapRuntime {\n sourceData: HeatmapSourceData | null;\n fixedState: HeatmapFixedState | null;\n screenLevelIndex: number;\n screenSecondaryLevelIndex: number;\n screenSecondaryLevelWeight: number;\n screenPointAlpha: number;\n screenNormalizationMaxWeight: number;\n screenVisibilityStrength: number;\n webgl: HeatmapWebGLRenderer | null | undefined;\n webglWarningIssued: boolean;\n webglPositions: Float32Array | null;\n webglWeights: Float32Array | null;\n webglCapacity: number;\n}\n\ninterface DrawState {\n data: HeatmapPointData | null;\n visible: boolean;\n opacity: number;\n radius: number;\n blur: number;\n gradient: readonly string[];\n backgroundColor: string | null;\n scaleMode: HeatmapKernelScaleMode;\n fixedZoom?: number;\n zoomThreshold: number;\n densityContrast: number;\n clipPolygons: readonly PreparedRoiPolygon[];\n clipKey: string;\n maxRenderedPoints: number;\n onStats?: (stats: HeatmapLayerStats) => void;\n}\n\ninterface ViewportFrame {\n heatmapScale: number;\n rasterWidth: number;\n rasterHeight: number;\n rasterScaleX: number;\n rasterScaleY: number;\n rawZoom: number;\n kernelRadiusPx: number;\n blurRadiusPx: number;\n outerWorldRadius: number;\n desiredCellWorldSize: number;\n}\n\nconst HEATMAP_DRAW_ID = \"__open_plant_heatmap_layer__\";\nconst DEFAULT_GRADIENT = [\"#00000000\", \"#3876FF\", \"#4CDDDD\", \"#FFE75C\", \"#FF8434\", \"#FF3434\"] as const;\nconst DEFAULT_RADIUS = 3;\nconst DEFAULT_BLUR = 2;\nconst DEFAULT_OPACITY = 0.9;\nconst DEFAULT_MAX_RENDERED_POINTS = 52000;\nconst DEFAULT_SCALE_MODE: HeatmapKernelScaleMode = \"screen\";\nconst DEFAULT_DENSITY_CONTRAST = 2.2;\nconst MIN_RASTER_SIZE = 128;\nconst MAX_RASTER_SIZE = 1600;\nconst BASE_RADIUS_UNIT_PX = 1.9;\nconst BASE_BLUR_UNIT_PX = 4.2;\nconst MIN_VISIBLE_BUDGET = 3000;\nconst PYRAMID_SCALE_STEP = Math.SQRT2;\nconst NORMALIZATION_SAMPLE_SIZE = 2048;\nconst NORMALIZATION_PERCENTILE = 0.9;\nconst MAX_DENSITY_CONTRAST = 16;\nconst MAX_ZOOM_THRESHOLD = 8;\n\nfunction resolveContinuousZoom(rawZoom: number, source: WsiImageSource): number {\n return source.maxTierZoom + Math.log2(Math.max(1e-6, rawZoom));\n}\n\nfunction resolveRawZoomFromContinuousZoom(continuousZoom: number, source: WsiImageSource): number {\n return Math.max(1e-6, 2 ** (continuousZoom - source.maxTierZoom));\n}\n\nfunction applyZoomThreshold(rawZoom: number, source: WsiImageSource, zoomThreshold: number): number {\n if (!Number.isFinite(zoomThreshold) || Math.abs(zoomThreshold) < 1e-6) {\n return Math.max(1e-6, rawZoom);\n }\n const shiftedZoom = resolveContinuousZoom(rawZoom, source) - zoomThreshold;\n return resolveRawZoomFromContinuousZoom(shiftedZoom, source);\n}\n\nfunction resolveThresholdLevelBias(zoomThreshold: number): number {\n if (!Number.isFinite(zoomThreshold) || Math.abs(zoomThreshold) < 1e-6) {\n return 0;\n }\n return Math.round((zoomThreshold * 1.5) / Math.max(1e-6, Math.log2(PYRAMID_SCALE_STEP)));\n}\n\nfunction resolveDensityWeightExponent(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n return clamp(0.55 + Math.sqrt(Math.max(0, contrast)) * 0.48, 0.55, 6);\n}\n\nfunction resolveCellSupportFactor(cellCount: number): number {\n const count = Math.max(0, cellCount);\n if (count <= 1) return 0.18;\n if (count <= 2) return 0.3;\n if (count <= 4) return 0.48;\n if (count <= 8) return 0.7;\n if (count <= 16) return 0.86;\n return 1;\n}\n\nfunction resolveDensityCutoff(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n const t = contrast / MAX_DENSITY_CONTRAST;\n return 0.022 - t * 0.015;\n}\n\nfunction resolveDensityGain(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n return 0.18 + Math.pow(Math.max(0, contrast), 0.72) * 0.42 + Math.log2(contrast + 1) * 0.24;\n}\n\nfunction resolveDensityGamma(densityContrast: number): number {\n return resolveDensityWeightExponent(densityContrast);\n}\n\nfunction resolveDensityBias(densityContrast: number): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n const t = contrast / MAX_DENSITY_CONTRAST;\n return clamp(0.46 - t * 0.34, 0.12, 0.46);\n}\n\nfunction resolveDensityStretch(densityContrast: number, rawZoom: number, source: WsiImageSource): number {\n const contrast = clamp(densityContrast, 0, MAX_DENSITY_CONTRAST);\n const contrastT = contrast / MAX_DENSITY_CONTRAST;\n const continuousZoom = resolveContinuousZoom(rawZoom, source);\n const zoomStart = source.maxTierZoom - 3.2;\n const zoomEnd = source.maxTierZoom - 1.15;\n const zoomT = clamp((continuousZoom - zoomStart) / Math.max(1e-6, zoomEnd - zoomStart), 0, 1);\n const baseStretch = 1.12 + Math.pow(contrastT, 0.82) * 1.18;\n const zoomStretch = 1 + zoomT * (0.48 + contrastT * 0.92);\n return baseStretch * zoomStretch;\n}\n\nfunction resolveNormalizedDensityWeight(weight: number, normalizationMaxWeight: number, densityContrast: number): number {\n void densityContrast;\n const safeWeight = Math.max(0, weight);\n const safeMaxWeight = Math.max(1e-6, normalizationMaxWeight);\n const normalized = Math.log1p(safeWeight) / Math.log1p(safeMaxWeight);\n return clamp(normalized, 0, 1);\n}\n\nfunction resolveNormalizationPercentile(densityContrast: number): number {\n void densityContrast;\n return NORMALIZATION_PERCENTILE;\n}\n\nfunction resolveNormalizationUpperWeight(cells: readonly HeatmapCell[], densityContrast: number): number {\n if (cells.length === 0) return 1;\n\n const sampleCount = Math.min(cells.length, NORMALIZATION_SAMPLE_SIZE);\n const sampledWeights = new Array<number>(sampleCount);\n let maxWeight = 1;\n\n for (let sampleIndex = 0; sampleIndex < sampleCount; sampleIndex += 1) {\n const cellIndex = Math.min(\n cells.length - 1,\n Math.floor(((sampleIndex + 0.5) * cells.length) / sampleCount),\n );\n const weight = Math.max(0, cells[cellIndex]?.weight ?? 0);\n sampledWeights[sampleIndex] = weight;\n if (weight > maxWeight) maxWeight = weight;\n }\n\n for (let cellIndex = 0; cellIndex < cells.length; cellIndex += 1) {\n const weight = Math.max(0, cells[cellIndex]?.weight ?? 0);\n if (weight > maxWeight) maxWeight = weight;\n }\n\n sampledWeights.sort((left, right) => left - right);\n const percentile = resolveNormalizationPercentile(densityContrast);\n const percentileIndex = Math.max(0, Math.min(\n sampledWeights.length - 1,\n Math.floor((sampledWeights.length - 1) * percentile),\n ));\n const percentileWeight = sampledWeights[percentileIndex] ?? maxWeight;\n const floorRatio = 0.14;\n const uplift = 1.08;\n return Math.max(1, Math.min(maxWeight, Math.max(percentileWeight * uplift, maxWeight * floorRatio)));\n}\n\nfunction resolveZoomVisibilityStrength(rawZoom: number, source: WsiImageSource, zoomThreshold: number): number {\n void zoomThreshold;\n const continuousZoom = resolveContinuousZoom(rawZoom, source);\n const fadeStart = source.maxTierZoom - 2.45;\n const fadeEnd = source.maxTierZoom - 1.2;\n const baseStrength =\n continuousZoom <= fadeStart ? 1 :\n continuousZoom >= fadeEnd ? 0 :\n (() => {\n const t = clamp((continuousZoom - fadeStart) / Math.max(1e-6, fadeEnd - fadeStart), 0, 1);\n const smooth = t * t * (3 - 2 * t);\n return 1 - smooth;\n })();\n return clamp(baseStrength, 0, 1);\n}\n\nfunction resolveSampleWeightBoost(sampleProbability: number): number {\n if (sampleProbability >= 1) return 1;\n const effectiveStride = 1 / Math.max(sampleProbability, 1e-6);\n return 1 + Math.log2(effectiveStride) * 0.28;\n}\n\nfunction resolveLowResScale(width: number, height: number, totalPointCount: number, rawZoom: number): number {\n const longestSide = Math.max(1, width, height);\n const deviceScale = typeof window === \"undefined\" ? 1 : clamp(window.devicePixelRatio || 1, 1, 2.4);\n const lowZoomBoost =\n rawZoom <= 0.35 ? 1.42 :\n rawZoom <= 0.55 ? 1.26 :\n rawZoom <= 0.8 ? 1.14 :\n 1;\n const targetMaxSize =\n totalPointCount > 160000 ? 896 :\n totalPointCount > 80000 ? 1152 :\n totalPointCount > 30000 ? 1408 :\n MAX_RASTER_SIZE;\n const minScale = MIN_RASTER_SIZE / longestSide;\n const maxScale = MAX_RASTER_SIZE / longestSide;\n return clamp((targetMaxSize * deviceScale * lowZoomBoost) / longestSide, minScale, maxScale);\n}\n\nfunction buildViewportFrame(params: {\n logicalWidth: number;\n logicalHeight: number;\n totalPointCount: number;\n rawZoom: number;\n radius: number;\n blur: number;\n heatmapScale?: number;\n}): ViewportFrame {\n const heatmapScale = params.heatmapScale ?? resolveLowResScale(params.logicalWidth, params.logicalHeight, params.totalPointCount, params.rawZoom);\n const rasterWidth = Math.max(MIN_RASTER_SIZE, Math.min(MAX_RASTER_SIZE, Math.round(params.logicalWidth * heatmapScale)));\n const rasterHeight = Math.max(MIN_RASTER_SIZE, Math.min(MAX_RASTER_SIZE, Math.round(params.logicalHeight * heatmapScale)));\n const rasterScaleX = rasterWidth / Math.max(1, params.logicalWidth);\n const rasterScaleY = rasterHeight / Math.max(1, params.logicalHeight);\n const effectiveScale = Math.min(rasterScaleX, rasterScaleY);\n const rawZoom = Math.max(1e-6, params.rawZoom);\n const kernelRadiusPx = Math.max(0.75, params.radius * BASE_RADIUS_UNIT_PX * effectiveScale);\n const blurRadiusPx = Math.max(0.6, params.blur * BASE_BLUR_UNIT_PX * effectiveScale);\n const outerWorldRadius = (kernelRadiusPx + blurRadiusPx) / Math.max(1e-6, rawZoom * effectiveScale);\n const desiredCellWorldSize = Math.max(\n outerWorldRadius * 0.4,\n 0.62 / Math.max(1e-6, rawZoom * effectiveScale),\n );\n\n return {\n heatmapScale,\n rasterWidth,\n rasterHeight,\n rasterScaleX,\n rasterScaleY,\n rawZoom,\n kernelRadiusPx,\n blurRadiusPx,\n outerWorldRadius,\n desiredCellWorldSize,\n };\n}\n\nfunction resolvePointCount(data: HeatmapPointData | null): number {\n if (!data) return 0;\n const maxByPosition = Math.floor(data.positions.length / 2);\n const maxByWeight = data.weights ? data.weights.length : Number.MAX_SAFE_INTEGER;\n return Math.max(0, Math.min(Math.floor(data.count), maxByPosition, maxByWeight));\n}\n\nfunction hashCoordinate(value: number, seed: number): number {\n const normalized = Number.isFinite(value) ? Math.round(value * 1024) : 0;\n return Math.imul(seed ^ normalized, 0x45d9f3b) >>> 0;\n}\n\nfunction hashIntPair(x: number, y: number, seed = 0x9e3779b9): number {\n let hash = Math.imul(seed ^ (x | 0), 0x85ebca6b) >>> 0;\n hash = Math.imul(hash ^ (y | 0), 0xc2b2ae35) >>> 0;\n hash ^= hash >>> 16;\n return hash >>> 0;\n}\n\nfunction hashToUnitFloat(hash: number): number {\n return (hash >>> 0) / 0xffffffff;\n}\n\nfunction resolveJitteredCoordinate(\n center: number,\n min: number,\n max: number,\n jitterUnit: number,\n paddingFraction: number,\n jitterFraction: number,\n): number {\n const span = Math.max(1e-6, max - min);\n const padding = Math.min(span * clamp(paddingFraction, 0.12, 0.32), span * 0.5 - 1e-6);\n const jitterRange = Math.max(0, span * clamp(jitterFraction, 0.01, 0.22) - padding * 0.15);\n const jitter = (jitterUnit * 2 - 1) * jitterRange;\n return clamp(center + jitter, min + padding, max - padding);\n}\n\nfunction buildClipKey(polygons: readonly PreparedRoiPolygon[]): string {\n let hash = 0x811c9dc5;\n for (let polygonIndex = 0; polygonIndex < polygons.length; polygonIndex += 1) {\n const polygon = polygons[polygonIndex]!;\n hash = Math.imul(hash ^ polygon.outer.length, 0x01000193) >>> 0;\n for (let pointIndex = 0; pointIndex < polygon.outer.length; pointIndex += 1) {\n const point = polygon.outer[pointIndex]!;\n hash = hashCoordinate(point[0], hash);\n hash = hashCoordinate(point[1], hash);\n }\n hash = Math.imul(hash ^ polygon.holes.length, 0x01000193) >>> 0;\n for (let holeIndex = 0; holeIndex < polygon.holes.length; holeIndex += 1) {\n const hole = polygon.holes[holeIndex]!;\n hash = Math.imul(hash ^ hole.length, 0x01000193) >>> 0;\n for (let pointIndex = 0; pointIndex < hole.length; pointIndex += 1) {\n const point = hole[pointIndex]!;\n hash = hashCoordinate(point[0], hash);\n hash = hashCoordinate(point[1], hash);\n }\n }\n }\n return `${polygons.length}:${hash >>> 0}`;\n}\n\nfunction isSameHeatmapInput(\n input: Pick<HeatmapSourceData, \"dataRef\" | \"positionsRef\" | \"weightsRef\" | \"inputCount\" | \"clipKey\"> | Pick<HeatmapFixedState, \"dataRef\" | \"positionsRef\" | \"weightsRef\" | \"inputCount\" | \"clipKey\">,\n data: HeatmapPointData | null,\n clipKey: string,\n): boolean {\n if (input.dataRef === data && input.clipKey === clipKey) {\n return true;\n }\n if (!data) return false;\n return input.clipKey === clipKey &&\n input.inputCount === resolvePointCount(data) &&\n input.positionsRef === data.positions &&\n input.weightsRef === data.weights;\n}\n\nfunction buildSourceData(data: HeatmapPointData | null, clipPolygons: readonly PreparedRoiPolygon[], clipKey: string, source: WsiImageSource | null): HeatmapSourceData | null {\n const pointCount = resolvePointCount(data);\n if (!data || pointCount <= 0) {\n return null;\n }\n\n let xs = new Float32Array(pointCount);\n let ys = new Float32Array(pointCount);\n let ws = new Float32Array(pointCount);\n let acceptedCount = 0;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (let index = 0; index < pointCount; index += 1) {\n const worldX = data.positions[index * 2];\n const worldY = data.positions[index * 2 + 1];\n if (!Number.isFinite(worldX) || !Number.isFinite(worldY)) continue;\n if (clipPolygons.length > 0 && !pointInAnyPreparedPolygon(worldX, worldY, clipPolygons)) continue;\n\n const rawWeight = data.weights?.[index];\n const weight = typeof rawWeight === \"number\" && Number.isFinite(rawWeight) ? Math.max(0, rawWeight) : 1;\n if (weight <= 0) continue;\n\n xs[acceptedCount] = worldX;\n ys[acceptedCount] = worldY;\n ws[acceptedCount] = weight;\n acceptedCount += 1;\n if (worldX < minX) minX = worldX;\n if (worldX > maxX) maxX = worldX;\n if (worldY < minY) minY = worldY;\n if (worldY > maxY) maxY = worldY;\n }\n\n if (acceptedCount === 0 || !Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {\n return null;\n }\n\n if (acceptedCount < pointCount) {\n xs = xs.slice(0, acceptedCount);\n ys = ys.slice(0, acceptedCount);\n ws = ws.slice(0, acceptedCount);\n }\n\n const pointIndexItems: Array<{ minX: number; minY: number; maxX: number; maxY: number; value: number }> = [];\n for (let index = 0; index < acceptedCount; index += 1) {\n const x = xs[index]!;\n const y = ys[index]!;\n pointIndexItems.push({\n minX: x,\n minY: y,\n maxX: x,\n maxY: y,\n value: index,\n });\n }\n const pointIndex = createSpatialIndex<number>(64);\n pointIndex.load(pointIndexItems);\n\n const maxDimension = Math.max(\n source?.width ?? 0,\n source?.height ?? 0,\n maxX - minX,\n maxY - minY,\n 1,\n );\n\n const cellSizes: number[] = [];\n let cellSize = 0.5;\n let guard = 0;\n while (cellSize <= maxDimension && guard < 32) {\n cellSizes.push(cellSize);\n cellSize *= PYRAMID_SCALE_STEP;\n guard += 1;\n }\n if (cellSizes.length === 0) {\n cellSizes.push(1);\n }\n\n return {\n dataRef: data,\n sourceRef: source,\n positionsRef: data.positions,\n weightsRef: data.weights,\n inputCount: pointCount,\n clipRef: clipPolygons,\n clipKey,\n pointCount: acceptedCount,\n xs,\n ys,\n ws,\n pointIndex,\n cellSizes,\n levels: Array.from({ length: cellSizes.length }, () => null),\n };\n}\n\nfunction estimateVisibleBinCount(viewBounds: [number, number, number, number], cellWorldSize: number): number {\n const width = Math.max(1, viewBounds[2] - viewBounds[0]);\n const height = Math.max(1, viewBounds[3] - viewBounds[1]);\n return Math.max(1, Math.round((width * height) / Math.max(1e-6, cellWorldSize * cellWorldSize)));\n}\n\nfunction buildLevel(sourceData: HeatmapSourceData, levelIndex: number): HeatmapLevel | null {\n if (levelIndex < 0 || levelIndex >= sourceData.cellSizes.length) return null;\n const cachedLevel = sourceData.levels[levelIndex];\n if (cachedLevel) return cachedLevel;\n\n const currentCellSize = sourceData.cellSizes[levelIndex];\n const levelT = sourceData.cellSizes.length <= 1 ? 0 : levelIndex / (sourceData.cellSizes.length - 1);\n const adaptivePaddingFraction = 0.24 - levelT * 0.08;\n const adaptiveJitterFraction = 0.035 + levelT * 0.11;\n const cells = new Map<string, {\n cellX: number;\n cellY: number;\n sumX: number;\n sumY: number;\n weight: number;\n count: number;\n }>();\n\n for (let pointIndex = 0; pointIndex < sourceData.pointCount; pointIndex += 1) {\n const worldX = sourceData.xs[pointIndex]!;\n const worldY = sourceData.ys[pointIndex]!;\n const weight = sourceData.ws[pointIndex]!;\n const cellX = Math.floor(worldX / currentCellSize);\n const cellY = Math.floor(worldY / currentCellSize);\n const key = `${cellX}:${cellY}`;\n const existing = cells.get(key);\n if (existing) {\n existing.sumX += worldX * weight;\n existing.sumY += worldY * weight;\n existing.weight += weight;\n existing.count += 1;\n } else {\n cells.set(key, {\n cellX,\n cellY,\n sumX: worldX * weight,\n sumY: worldY * weight,\n weight,\n count: 1,\n });\n }\n }\n\n const bins: HeatmapCell[] = [];\n const items: Array<{ minX: number; minY: number; maxX: number; maxY: number; value: number }> = [];\n cells.forEach(cell => {\n if (cell.weight <= 0) return;\n const cellMinX = cell.cellX * currentCellSize;\n const cellMinY = cell.cellY * currentCellSize;\n const centerX = cell.sumX / cell.weight;\n const centerY = cell.sumY / cell.weight;\n const jitterSeed = hashIntPair(cell.cellX, cell.cellY, Math.round(currentCellSize * 1024));\n const bin: HeatmapCell = {\n minX: cellMinX,\n minY: cellMinY,\n maxX: cellMinX + currentCellSize,\n maxY: cellMinY + currentCellSize,\n worldX: centerX,\n worldY: centerY,\n renderWorldX: resolveJitteredCoordinate(\n centerX,\n cellMinX,\n cellMinX + currentCellSize,\n hashToUnitFloat(jitterSeed),\n adaptivePaddingFraction,\n adaptiveJitterFraction,\n ),\n renderWorldY: resolveJitteredCoordinate(\n centerY,\n cellMinY,\n cellMinY + currentCellSize,\n hashToUnitFloat(hashIntPair(cell.cellY, cell.cellX, jitterSeed ^ 0x68bc21eb)),\n adaptivePaddingFraction,\n adaptiveJitterFraction,\n ),\n weight: cell.weight,\n count: cell.count,\n };\n const value = bins.length;\n bins.push(bin);\n items.push({\n minX: bin.minX,\n minY: bin.minY,\n maxX: bin.maxX,\n maxY: bin.maxY,\n value,\n });\n });\n\n const index = createSpatialIndex<number>(32);\n index.load(items);\n const level = {\n cellWorldSize: currentCellSize,\n bins,\n index,\n normalizationUpperWeight: resolveNormalizationUpperWeight(bins, 1),\n };\n sourceData.levels[levelIndex] = level;\n return level;\n}\n\nfunction findLevelIndex(cellSizes: readonly number[], desiredCellWorldSize: number, previousIndex: number): number {\n if (cellSizes.length === 0) return 0;\n\n if (previousIndex >= 0 && previousIndex < cellSizes.length) {\n const previousCellSize = cellSizes[previousIndex]!;\n if (desiredCellWorldSize >= previousCellSize * 0.52 && desiredCellWorldSize <= previousCellSize * 2.1) {\n return previousIndex;\n }\n }\n\n let bestIndex = 0;\n let bestDistance = Infinity;\n const desiredLog = Math.log2(Math.max(1e-6, desiredCellWorldSize));\n\n for (let index = 0; index < cellSizes.length; index += 1) {\n const distance = Math.abs(Math.log2(cellSizes[index]!) - desiredLog);\n if (distance >= bestDistance) continue;\n bestDistance = distance;\n bestIndex = index;\n }\n return bestIndex;\n}\n\nfunction resolveLevelIndex(params: {\n cellSizes: readonly number[];\n desiredCellWorldSize: number;\n zoomThreshold: number;\n maxRenderedPoints: number;\n viewBounds: [number, number, number, number];\n previousIndex: number;\n}): number {\n const { cellSizes, desiredCellWorldSize, zoomThreshold, maxRenderedPoints, viewBounds, previousIndex } = params;\n let index = findLevelIndex(cellSizes, desiredCellWorldSize, previousIndex);\n const budget = Math.max(MIN_VISIBLE_BUDGET, maxRenderedPoints);\n while (index < cellSizes.length - 1 && estimateVisibleBinCount(viewBounds, cellSizes[index]!) > budget * 1.28) {\n index += 1;\n }\n while (index > 0 && estimateVisibleBinCount(viewBounds, cellSizes[index - 1]!) <= budget * 0.76) {\n index -= 1;\n }\n return Math.max(0, Math.min(cellSizes.length - 1, index + resolveThresholdLevelBias(zoomThreshold)));\n}\n\nfunction resolveScreenLevelBlend(params: {\n cellSizes: readonly number[];\n desiredCellWorldSize: number;\n zoomThreshold: number;\n maxRenderedPoints: number;\n viewBounds: [number, number, number, number];\n}): { lowerIndex: number; upperIndex: number; upperWeight: number } {\n const { cellSizes, desiredCellWorldSize, zoomThreshold, maxRenderedPoints, viewBounds } = params;\n if (cellSizes.length === 0) {\n return { lowerIndex: 0, upperIndex: 0, upperWeight: 0 };\n }\n\n const stepLog = Math.log2(PYRAMID_SCALE_STEP);\n const firstCellLog = Math.log2(Math.max(1e-6, cellSizes[0]!));\n let desiredPosition =\n (Math.log2(Math.max(1e-6, desiredCellWorldSize)) - firstCellLog) / Math.max(1e-6, stepLog) +\n resolveThresholdLevelBias(zoomThreshold);\n\n const budget = Math.max(MIN_VISIBLE_BUDGET, maxRenderedPoints);\n let minimumBudgetIndex = 0;\n while (\n minimumBudgetIndex < cellSizes.length - 1 &&\n estimateVisibleBinCount(viewBounds, cellSizes[minimumBudgetIndex]!) > budget * 1.12\n ) {\n minimumBudgetIndex += 1;\n }\n\n desiredPosition = clamp(desiredPosition, minimumBudgetIndex, cellSizes.length - 1);\n const lowerIndex = Math.floor(desiredPosition);\n const upperIndex = Math.min(cellSizes.length - 1, Math.ceil(desiredPosition));\n const upperWeight = upperIndex === lowerIndex ? 0 : desiredPosition - lowerIndex;\n return { lowerIndex, upperIndex, upperWeight };\n}\n\nfunction collectVisibleCells(level: HeatmapLevel, viewBounds: [number, number, number, number], outerWorldRadius: number): HeatmapCell[] {\n const hits = level.index.search([\n viewBounds[0] - outerWorldRadius,\n viewBounds[1] - outerWorldRadius,\n viewBounds[2] + outerWorldRadius,\n viewBounds[3] + outerWorldRadius,\n ]);\n const visible: HeatmapCell[] = [];\n for (let index = 0; index < hits.length; index += 1) {\n const hit = hits[index];\n if (!hit) continue;\n const cell = level.bins[hit.value];\n if (!cell) continue;\n visible.push(cell);\n }\n return visible;\n}\n\nfunction collectVisiblePointIndices(sourceData: HeatmapSourceData, viewBounds: [number, number, number, number], outerWorldRadius: number): number[] {\n const hits = sourceData.pointIndex.search([\n viewBounds[0] - outerWorldRadius,\n viewBounds[1] - outerWorldRadius,\n viewBounds[2] + outerWorldRadius,\n viewBounds[3] + outerWorldRadius,\n ]);\n const visible = new Array<number>(hits.length);\n let count = 0;\n for (let index = 0; index < hits.length; index += 1) {\n const hit = hits[index];\n if (!hit) continue;\n visible[count] = hit.value;\n count += 1;\n }\n visible.length = count;\n return visible;\n}\n\nfunction resolveSampleProbability(visiblePointCount: number, maxRenderedPoints: number): number {\n const budget = Math.max(MIN_VISIBLE_BUDGET, maxRenderedPoints);\n if (visiblePointCount <= budget) return 1;\n return clamp(budget / Math.max(1, visiblePointCount), 1 / 65536, 1);\n}\n\nfunction resolveSampleStride(sampleProbability: number): number {\n if (sampleProbability >= 1) return 1;\n return Math.max(1, Math.round(1 / Math.max(1e-6, sampleProbability)));\n}\n\nfunction shouldKeepSample(pointIndex: number, sampleProbability: number): boolean {\n if (sampleProbability >= 1) return true;\n const sampleHash = hashIntPair(pointIndex, 0x51ed270b, 0x68bc21eb);\n return hashToUnitFloat(sampleHash) <= clamp(sampleProbability, 0, 1);\n}\n\nfunction resolvePointAlpha(binCount: number, kernelOuterRadiusPx: number, rasterWidth: number, rasterHeight: number): number {\n const rasterArea = Math.max(1, rasterWidth * rasterHeight);\n const kernelArea = Math.PI * kernelOuterRadiusPx * kernelOuterRadiusPx;\n const coverage = (Math.max(1, binCount) * kernelArea) / rasterArea;\n return clamp(0.085 / Math.sqrt(Math.max(1, coverage)), 0.012, 0.075);\n}\n\nfunction smoothHeatmapValue(previousValue: number, nextValue: number, riseFactor: number, fallFactor: number): number {\n if (!Number.isFinite(previousValue) || previousValue <= 0) {\n return nextValue;\n }\n const factor = nextValue >= previousValue ? riseFactor : fallFactor;\n return previousValue + (nextValue - previousValue) * clamp(factor, 0, 1);\n}\n\nfunction shouldFreezeScreenHeatmapAtMinZoom(\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>,\n rawZoom: number,\n): boolean {\n if (!renderer.isViewAnimating()) return false;\n const zoomRange = renderer.getZoomRange();\n const minZoom = Math.max(1e-6, zoomRange.minZoom);\n return rawZoom <= minZoom * 1.075;\n}\n\nfunction getWebglRenderer(runtime: HeatmapRuntime): HeatmapWebGLRenderer | null {\n if (runtime.webgl !== undefined) {\n return runtime.webgl;\n }\n if (typeof document === \"undefined\") {\n runtime.webgl = null;\n return null;\n }\n try {\n runtime.webgl = new HeatmapWebGLRenderer();\n } catch (error) {\n if (!runtime.webglWarningIssued && typeof console !== \"undefined\" && typeof console.warn === \"function\") {\n const reason = error instanceof Error ? error.message : String(error);\n console.warn(`[open-plant] HeatmapLayer disabled because WebGL2 heatmap initialization failed: ${reason}`);\n runtime.webglWarningIssued = true;\n }\n runtime.webgl = null;\n }\n return runtime.webgl;\n}\n\nfunction projectClipRing(renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>, ring: readonly [number, number][]): [number, number][] {\n const out: [number, number][] = [];\n for (let index = 0; index < ring.length; index += 1) {\n const point = ring[index];\n if (!point) continue;\n const projected = renderer.worldToScreen(point[0], point[1]);\n if (!Array.isArray(projected) || projected.length < 2) continue;\n const x = Number(projected[0]);\n const y = Number(projected[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n out.push([x, y]);\n }\n return out;\n}\n\nfunction applyClipPath(ctx: CanvasRenderingContext2D, renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>, polygons: readonly PreparedRoiPolygon[]): void {\n if (polygons.length === 0) return;\n ctx.beginPath();\n for (let index = 0; index < polygons.length; index += 1) {\n const polygon = polygons[index]!;\n const outer = projectClipRing(renderer, polygon.outer);\n if (outer.length >= 3) {\n tracePath(ctx, outer, true);\n }\n for (let holeIndex = 0; holeIndex < polygon.holes.length; holeIndex += 1) {\n const hole = projectClipRing(renderer, polygon.holes[holeIndex]!);\n if (hole.length >= 3) {\n tracePath(ctx, hole, true);\n }\n }\n }\n ctx.clip(\"evenodd\");\n}\n\nfunction ensureSourceData(runtime: HeatmapRuntime, data: HeatmapPointData | null, clipPolygons: readonly PreparedRoiPolygon[], clipKey: string, source: WsiImageSource | null): HeatmapSourceData | null {\n const current = runtime.sourceData;\n if (current && current.sourceRef === source && isSameHeatmapInput(current, data, clipKey)) {\n return current;\n }\n runtime.sourceData = buildSourceData(data, clipPolygons, clipKey, source);\n runtime.fixedState = null;\n runtime.screenLevelIndex = -1;\n return runtime.sourceData;\n}\n\nfunction buildFixedState(params: {\n runtime: HeatmapRuntime;\n sourceData: HeatmapSourceData;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n radius: number;\n blur: number;\n fixedZoom?: number;\n zoomThreshold: number;\n densityContrast: number;\n maxRenderedPoints: number;\n}): HeatmapFixedState | null {\n const { sourceData, renderer, source, logicalWidth, logicalHeight, radius, blur, fixedZoom, maxRenderedPoints } = params;\n\n const currentRawZoom = Math.max(1e-6, renderer.getViewState().zoom);\n const referenceZoom = fixedZoom ?? resolveContinuousZoom(currentRawZoom, source);\n const referenceRawZoom = resolveRawZoomFromContinuousZoom(referenceZoom, source);\n const frame = buildViewportFrame({\n logicalWidth,\n logicalHeight,\n totalPointCount: sourceData.pointCount,\n rawZoom: referenceRawZoom,\n radius,\n blur,\n });\n const viewBounds = renderer.getViewBounds();\n const visiblePointIndices = collectVisiblePointIndices(sourceData, viewBounds, frame.outerWorldRadius);\n const sampleProbability = resolveSampleProbability(visiblePointIndices.length, maxRenderedPoints);\n const sampleStride = resolveSampleStride(sampleProbability);\n const effectiveScale = Math.min(frame.rasterScaleX, frame.rasterScaleY);\n\n return {\n dataRef: sourceData.dataRef,\n positionsRef: sourceData.positionsRef,\n weightsRef: sourceData.weightsRef,\n inputCount: sourceData.inputCount,\n clipRef: sourceData.clipRef,\n clipKey: sourceData.clipKey,\n referenceZoom,\n referenceRawZoom,\n heatmapScale: frame.heatmapScale,\n kernelWorldRadius: frame.kernelRadiusPx / Math.max(1e-6, referenceRawZoom * effectiveScale),\n blurWorldRadius: frame.blurRadiusPx / Math.max(1e-6, referenceRawZoom * effectiveScale),\n sampleProbability,\n sampleStride,\n pointAlpha: resolvePointAlpha(visiblePointIndices.length, frame.kernelRadiusPx + frame.blurRadiusPx, frame.rasterWidth, frame.rasterHeight),\n };\n}\n\nfunction drawHeatmapWebgl(params: {\n ctx: CanvasRenderingContext2D;\n runtime: HeatmapRuntime;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n frame: ViewportFrame;\n cells: readonly HeatmapCell[];\n normalizationMaxWeight: number;\n pointAlpha: number;\n gradient: readonly string[];\n opacity: number;\n densityContrast: number;\n backgroundColor: string | null;\n clipPolygons: readonly PreparedRoiPolygon[];\n}): number {\n const { ctx, runtime, renderer, logicalWidth, logicalHeight, frame, cells, normalizationMaxWeight, pointAlpha, gradient, opacity, densityContrast, backgroundColor, clipPolygons } = params;\n const { source } = params;\n const webgl = getWebglRenderer(runtime);\n if (!webgl || cells.length === 0) {\n return 0;\n }\n\n if (cells.length > runtime.webglCapacity) {\n runtime.webglCapacity = cells.length;\n runtime.webglPositions = new Float32Array(cells.length * 2);\n runtime.webglWeights = new Float32Array(cells.length);\n }\n const positions = runtime.webglPositions;\n const weights = runtime.webglWeights;\n if (!positions || !weights) {\n return 0;\n }\n\n const outerRadiusPx = frame.kernelRadiusPx + frame.blurRadiusPx;\n let drawCount = 0;\n\n for (let index = 0; index < cells.length; index += 1) {\n const cell = cells[index]!;\n const projected = renderer.worldToScreen(cell.renderWorldX, cell.renderWorldY);\n if (!Array.isArray(projected) || projected.length < 2) continue;\n\n const screenX = Number(projected[0]);\n const screenY = Number(projected[1]);\n if (!Number.isFinite(screenX) || !Number.isFinite(screenY)) continue;\n\n const rasterX = screenX * frame.rasterScaleX;\n const rasterY = screenY * frame.rasterScaleY;\n if (\n rasterX < -outerRadiusPx ||\n rasterY < -outerRadiusPx ||\n rasterX > frame.rasterWidth + outerRadiusPx ||\n rasterY > frame.rasterHeight + outerRadiusPx\n ) {\n continue;\n }\n\n const offset = drawCount * 2;\n const supportFactor = resolveCellSupportFactor(cell.count);\n const normalizedWeight = resolveNormalizedDensityWeight(cell.weight, normalizationMaxWeight, densityContrast);\n const effectiveWeight = normalizedWeight * supportFactor;\n if (effectiveWeight <= 0.025) continue;\n\n positions[offset] = rasterX;\n positions[offset + 1] = rasterY;\n weights[drawCount] = effectiveWeight;\n drawCount += 1;\n }\n\n if (drawCount <= 0) {\n return 0;\n }\n\n const rendered = webgl.render({\n width: frame.rasterWidth,\n height: frame.rasterHeight,\n positions,\n weights,\n count: drawCount,\n kernelRadiusPx: frame.kernelRadiusPx,\n blurRadiusPx: frame.blurRadiusPx,\n pointAlpha,\n gradient,\n opacity,\n cutoff: resolveDensityCutoff(densityContrast),\n gain: resolveDensityGain(densityContrast),\n gamma: resolveDensityGamma(densityContrast),\n bias: resolveDensityBias(densityContrast),\n stretch: resolveDensityStretch(densityContrast, frame.rawZoom, source),\n });\n if (!rendered) {\n return 0;\n }\n\n ctx.save();\n if (clipPolygons.length > 0) {\n applyClipPath(ctx, renderer, clipPolygons);\n }\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, logicalWidth, logicalHeight);\n }\n ctx.globalAlpha = 1;\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(webgl.canvas, 0, 0, frame.rasterWidth, frame.rasterHeight, 0, 0, logicalWidth, logicalHeight);\n ctx.restore();\n\n return drawCount;\n}\n\nfunction drawHeatmapWebglPoints(params: {\n ctx: CanvasRenderingContext2D;\n runtime: HeatmapRuntime;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n frame: ViewportFrame;\n sourceData: HeatmapSourceData;\n visiblePointIndices: readonly number[];\n sampleProbability: number;\n sampleStride: number;\n pointAlpha: number;\n gradient: readonly string[];\n opacity: number;\n densityContrast: number;\n backgroundColor: string | null;\n clipPolygons: readonly PreparedRoiPolygon[];\n}): number {\n const {\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n frame,\n sourceData,\n visiblePointIndices,\n sampleProbability,\n sampleStride,\n pointAlpha,\n gradient,\n opacity,\n densityContrast,\n backgroundColor,\n clipPolygons,\n } = params;\n const webgl = getWebglRenderer(runtime);\n if (!webgl || visiblePointIndices.length === 0) {\n return 0;\n }\n\n const targetCapacity = Math.min(\n visiblePointIndices.length,\n Math.max(64, Math.ceil(visiblePointIndices.length * Math.min(1, sampleProbability * 1.15))),\n );\n if (targetCapacity > runtime.webglCapacity) {\n runtime.webglCapacity = targetCapacity;\n runtime.webglPositions = new Float32Array(targetCapacity * 2);\n runtime.webglWeights = new Float32Array(targetCapacity);\n }\n const positions = runtime.webglPositions;\n const weights = runtime.webglWeights;\n if (!positions || !weights) {\n return 0;\n }\n\n const outerRadiusPx = frame.kernelRadiusPx + frame.blurRadiusPx;\n const sampleWeightBoost = resolveSampleWeightBoost(sampleProbability);\n let drawCount = 0;\n\n for (let visibleIndex = 0; visibleIndex < visiblePointIndices.length; visibleIndex += 1) {\n const pointIndex = visiblePointIndices[visibleIndex]!;\n if (!shouldKeepSample(pointIndex, sampleProbability)) continue;\n\n const worldX = sourceData.xs[pointIndex];\n const worldY = sourceData.ys[pointIndex];\n if (!Number.isFinite(worldX) || !Number.isFinite(worldY)) continue;\n\n const projected = renderer.worldToScreen(worldX, worldY);\n if (!Array.isArray(projected) || projected.length < 2) continue;\n\n const screenX = Number(projected[0]);\n const screenY = Number(projected[1]);\n if (!Number.isFinite(screenX) || !Number.isFinite(screenY)) continue;\n\n const rasterX = screenX * frame.rasterScaleX;\n const rasterY = screenY * frame.rasterScaleY;\n if (\n rasterX < -outerRadiusPx ||\n rasterY < -outerRadiusPx ||\n rasterX > frame.rasterWidth + outerRadiusPx ||\n rasterY > frame.rasterHeight + outerRadiusPx\n ) {\n continue;\n }\n\n const offset = drawCount * 2;\n positions[offset] = rasterX;\n positions[offset + 1] = rasterY;\n weights[drawCount] = Math.max(0, (sourceData.ws[pointIndex] ?? 0) * sampleWeightBoost);\n drawCount += 1;\n }\n\n if (drawCount <= 0) {\n return 0;\n }\n\n const rendered = webgl.render({\n width: frame.rasterWidth,\n height: frame.rasterHeight,\n positions,\n weights,\n count: drawCount,\n kernelRadiusPx: frame.kernelRadiusPx,\n blurRadiusPx: frame.blurRadiusPx,\n pointAlpha,\n gradient,\n opacity,\n cutoff: resolveDensityCutoff(densityContrast),\n gain: resolveDensityGain(densityContrast),\n gamma: resolveDensityGamma(densityContrast),\n bias: resolveDensityBias(densityContrast),\n stretch: resolveDensityStretch(densityContrast, frame.rawZoom, source),\n });\n if (!rendered) {\n return 0;\n }\n\n ctx.save();\n if (clipPolygons.length > 0) {\n applyClipPath(ctx, renderer, clipPolygons);\n }\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, logicalWidth, logicalHeight);\n }\n ctx.globalAlpha = 1;\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(webgl.canvas, 0, 0, frame.rasterWidth, frame.rasterHeight, 0, 0, logicalWidth, logicalHeight);\n ctx.restore();\n\n return drawCount;\n}\n\nfunction drawHeatmap(params: {\n ctx: CanvasRenderingContext2D;\n runtime: HeatmapRuntime;\n renderer: NonNullable<ReturnType<typeof useViewerContext>[\"rendererRef\"][\"current\"]>;\n source: WsiImageSource;\n logicalWidth: number;\n logicalHeight: number;\n state: DrawState;\n}): HeatmapLayerStats | null {\n const { ctx, runtime, renderer, source, logicalWidth, logicalHeight, state } = params;\n const sourceData = ensureSourceData(runtime, state.data, state.clipPolygons, state.clipKey, source);\n if (!sourceData || sourceData.cellSizes.length === 0 || sourceData.pointCount <= 0) {\n return null;\n }\n\n const rawZoom = Math.max(1e-6, renderer.getViewState().zoom);\n const zoomVisibilityStrength = resolveZoomVisibilityStrength(rawZoom, source, state.zoomThreshold);\n const viewBounds = renderer.getViewBounds();\n if (zoomVisibilityStrength <= 0.001) {\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: 0,\n renderedBinCount: 0,\n sampleStride: 1,\n maxDensity: 0,\n };\n }\n\n if (state.scaleMode !== \"fixed-zoom\") {\n const frame = buildViewportFrame({\n logicalWidth,\n logicalHeight,\n totalPointCount: sourceData.pointCount,\n rawZoom,\n radius: state.radius,\n blur: state.blur,\n });\n const visiblePointIndices = collectVisiblePointIndices(sourceData, viewBounds, frame.outerWorldRadius);\n if (visiblePointIndices.length === 0) {\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: 0,\n renderedBinCount: 0,\n sampleStride: 1,\n maxDensity: 0,\n };\n }\n\n const sampleProbability = resolveSampleProbability(visiblePointIndices.length, state.maxRenderedPoints);\n const sampleStride = resolveSampleStride(sampleProbability);\n const targetPointAlpha = resolvePointAlpha(\n visiblePointIndices.length,\n frame.kernelRadiusPx + frame.blurRadiusPx,\n frame.rasterWidth,\n frame.rasterHeight,\n );\n runtime.screenLevelIndex = -1;\n runtime.screenSecondaryLevelIndex = -1;\n runtime.screenSecondaryLevelWeight = 0;\n runtime.screenNormalizationMaxWeight = 1;\n runtime.screenPointAlpha = smoothHeatmapValue(runtime.screenPointAlpha, targetPointAlpha, 0.12, 0.08);\n runtime.screenVisibilityStrength = renderer.isViewAnimating()\n ? smoothHeatmapValue(runtime.screenVisibilityStrength, zoomVisibilityStrength, 0.16, 0.12)\n : zoomVisibilityStrength;\n\n const renderedPointCount = drawHeatmapWebglPoints({\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n frame,\n sourceData,\n visiblePointIndices,\n sampleProbability,\n sampleStride,\n pointAlpha: runtime.screenPointAlpha * Math.max(0.08, runtime.screenVisibilityStrength),\n gradient: state.gradient,\n opacity: state.opacity * runtime.screenVisibilityStrength,\n densityContrast: state.densityContrast,\n backgroundColor: state.backgroundColor,\n clipPolygons: state.clipPolygons,\n });\n\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: visiblePointIndices.length,\n renderedBinCount: renderedPointCount,\n sampleStride,\n maxDensity: Math.round(runtime.screenPointAlpha * 255),\n };\n }\n\n const fixedState = runtime.fixedState;\n if (!fixedState) return null;\n\n const frame = buildViewportFrame({\n logicalWidth,\n logicalHeight,\n totalPointCount: sourceData.pointCount,\n rawZoom,\n radius: state.radius,\n blur: state.blur,\n heatmapScale: fixedState.heatmapScale,\n });\n const effectiveScale = Math.min(frame.rasterScaleX, frame.rasterScaleY);\n frame.kernelRadiusPx = Math.max(0.75, fixedState.kernelWorldRadius * rawZoom * effectiveScale);\n frame.blurRadiusPx = Math.max(0.6, fixedState.blurWorldRadius * rawZoom * effectiveScale);\n frame.outerWorldRadius = fixedState.kernelWorldRadius + fixedState.blurWorldRadius;\n\n const visiblePointIndices = collectVisiblePointIndices(sourceData, viewBounds, frame.outerWorldRadius);\n if (visiblePointIndices.length === 0) {\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: 0,\n renderedBinCount: 0,\n sampleStride: 1,\n maxDensity: 0,\n };\n }\n\n runtime.screenPointAlpha = fixedState.pointAlpha;\n runtime.screenVisibilityStrength = zoomVisibilityStrength;\n\n const renderedPointCount = drawHeatmapWebglPoints({\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n frame,\n sourceData,\n visiblePointIndices,\n sampleProbability: fixedState.sampleProbability,\n sampleStride: fixedState.sampleStride,\n pointAlpha: fixedState.pointAlpha * Math.max(0.08, zoomVisibilityStrength),\n gradient: state.gradient,\n opacity: state.opacity * zoomVisibilityStrength,\n densityContrast: state.densityContrast,\n backgroundColor: state.backgroundColor,\n clipPolygons: state.clipPolygons,\n });\n\n return {\n pointCount: sourceData.pointCount,\n renderTimeMs: 0,\n visiblePointCount: visiblePointIndices.length,\n renderedBinCount: renderedPointCount,\n sampleStride: fixedState.sampleStride,\n maxDensity: Math.round(fixedState.pointAlpha * 255),\n };\n}\n\nexport function HeatmapLayer({\n data,\n visible = true,\n opacity = DEFAULT_OPACITY,\n radius = DEFAULT_RADIUS,\n blur = DEFAULT_BLUR,\n gradient = DEFAULT_GRADIENT,\n backgroundColor = null,\n scaleMode = DEFAULT_SCALE_MODE,\n fixedZoom,\n zoomThreshold = 0,\n densityContrast = DEFAULT_DENSITY_CONTRAST,\n clipToRegions,\n zIndex = 5,\n maxRenderedPoints = DEFAULT_MAX_RENDERED_POINTS,\n onStats,\n}: HeatmapLayerProps): null {\n const { rendererRef, source, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw } = useViewerContext();\n\n const clipPolygons = useMemo(() => {\n const geometries = (clipToRegions ?? [])\n .map(region => toRoiGeometry(region?.coordinates))\n .filter((geometry): geometry is NonNullable<typeof geometry> => geometry != null);\n return prepareRoiPolygons(geometries);\n }, [clipToRegions]);\n const clipKey = useMemo(() => buildClipKey(clipPolygons), [clipPolygons]);\n\n const runtimeRef = useRef<HeatmapRuntime>({\n sourceData: null,\n fixedState: null,\n screenLevelIndex: -1,\n screenSecondaryLevelIndex: -1,\n screenSecondaryLevelWeight: 0,\n screenPointAlpha: 0,\n screenNormalizationMaxWeight: 1,\n screenVisibilityStrength: 1,\n webgl: undefined,\n webglWarningIssued: false,\n webglPositions: null,\n webglWeights: null,\n webglCapacity: 0,\n });\n\n const stateRef = useRef<DrawState>({\n data,\n visible,\n opacity,\n radius: clamp(radius, 0.05, 128),\n blur: clamp(blur, 0.05, 128),\n gradient,\n backgroundColor,\n scaleMode,\n fixedZoom,\n zoomThreshold,\n densityContrast: clamp(densityContrast, 0, MAX_DENSITY_CONTRAST),\n clipPolygons,\n clipKey,\n maxRenderedPoints: Math.max(MIN_VISIBLE_BUDGET, Math.floor(maxRenderedPoints)),\n onStats,\n });\n\n stateRef.current = {\n data,\n visible,\n opacity,\n radius: clamp(radius, 0.05, 128),\n blur: clamp(blur, 0.05, 128),\n gradient,\n backgroundColor,\n scaleMode,\n fixedZoom,\n zoomThreshold,\n densityContrast: clamp(densityContrast, 0, MAX_DENSITY_CONTRAST),\n clipPolygons,\n clipKey,\n maxRenderedPoints: Math.max(MIN_VISIBLE_BUDGET, Math.floor(maxRenderedPoints)),\n onStats,\n };\n\n useEffect(() => {\n const draw = (ctx: CanvasRenderingContext2D, logicalWidth: number, logicalHeight: number): void => {\n const state = stateRef.current;\n const runtime = runtimeRef.current;\n const renderer = rendererRef.current;\n if (!state.visible || !state.data || !renderer || !source) return;\n\n const sourceData = ensureSourceData(runtime, state.data, state.clipPolygons, state.clipKey, source);\n if (!sourceData) return;\n\n const needsFixedState =\n state.scaleMode === \"fixed-zoom\" &&\n (!runtime.fixedState ||\n !isSameHeatmapInput(runtime.fixedState, state.data, state.clipKey) ||\n (state.fixedZoom !== undefined && Math.abs(runtime.fixedState.referenceZoom - state.fixedZoom) > 1e-6));\n\n if (needsFixedState) {\n runtime.fixedState = buildFixedState({\n runtime,\n sourceData,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n radius: state.radius,\n blur: state.blur,\n fixedZoom: state.fixedZoom,\n zoomThreshold: state.zoomThreshold,\n densityContrast: state.densityContrast,\n maxRenderedPoints: state.maxRenderedPoints,\n });\n } else if (state.scaleMode !== \"fixed-zoom\") {\n runtime.fixedState = null;\n }\n\n const startedAt = performance.now();\n const stats = drawHeatmap({\n ctx,\n runtime,\n renderer,\n source,\n logicalWidth,\n logicalHeight,\n state,\n });\n if (!stats || !state.onStats) return;\n state.onStats({\n ...stats,\n renderTimeMs: performance.now() - startedAt,\n });\n };\n\n registerDrawCallback(HEATMAP_DRAW_ID, zIndex, draw);\n return () => {\n unregisterDrawCallback(HEATMAP_DRAW_ID);\n runtimeRef.current.sourceData = null;\n runtimeRef.current.fixedState = null;\n runtimeRef.current.screenLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelWeight = 0;\n runtimeRef.current.screenPointAlpha = 0;\n runtimeRef.current.screenNormalizationMaxWeight = 1;\n runtimeRef.current.screenVisibilityStrength = 1;\n runtimeRef.current.webgl?.destroy();\n runtimeRef.current.webgl = undefined;\n runtimeRef.current.webglPositions = null;\n runtimeRef.current.webglWeights = null;\n runtimeRef.current.webglCapacity = 0;\n };\n }, [registerDrawCallback, unregisterDrawCallback, rendererRef, source, zIndex]);\n\n useEffect(() => {\n runtimeRef.current.sourceData = null;\n runtimeRef.current.fixedState = null;\n runtimeRef.current.screenLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelWeight = 0;\n runtimeRef.current.screenPointAlpha = 0;\n runtimeRef.current.screenNormalizationMaxWeight = 1;\n runtimeRef.current.screenVisibilityStrength = 1;\n requestOverlayRedraw();\n }, [data?.positions, data?.weights, data?.count, clipKey, requestOverlayRedraw]);\n\n useEffect(() => {\n runtimeRef.current.fixedState = null;\n runtimeRef.current.screenSecondaryLevelIndex = -1;\n runtimeRef.current.screenSecondaryLevelWeight = 0;\n runtimeRef.current.screenPointAlpha = 0;\n runtimeRef.current.screenNormalizationMaxWeight = 1;\n runtimeRef.current.screenVisibilityStrength = 1;\n requestOverlayRedraw();\n }, [radius, blur, scaleMode, fixedZoom, zoomThreshold, densityContrast, maxRenderedPoints, requestOverlayRedraw]);\n\n useEffect(() => {\n requestOverlayRedraw();\n }, [visible, opacity, gradient, backgroundColor, requestOverlayRedraw]);\n\n return null;\n}\n\nexport const __heatmapLayerInternals = {\n applyZoomThreshold,\n buildClipKey,\n resolveCellSupportFactor,\n resolveContinuousZoom,\n resolveDensityCutoff,\n resolveDensityBias,\n resolveDensityGain,\n resolveDensityGamma,\n resolveDensityStretch,\n resolveNormalizedDensityWeight,\n resolveNormalizationUpperWeight,\n resolveDensityWeightExponent,\n resolveRawZoomFromContinuousZoom,\n resolvePointCount,\n resolveThresholdLevelBias,\n resolveZoomVisibilityStrength,\n isSameHeatmapInput,\n};\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { drawOverlayShapes } from \"./draw-layer-overlay\";\nimport type { DrawCoordinate, DrawOverlayShape } from \"./draw-layer-types\";\nimport { DEFAULT_REGION_STROKE_STYLE } from \"./draw-layer-types\";\nimport { closeRing, toCoord } from \"./draw-layer-utils\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport interface OverlayLayerProps {\n shapes?: DrawOverlayShape[];\n}\n\nconst OVERLAY_DRAW_ID = \"__overlay_layer__\";\n\nexport function OverlayLayer({ shapes }: OverlayLayerProps): React.ReactElement | null {\n const { rendererRef, rendererSerial, source, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw } = useViewerContext();\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = rendererRef.current;\n if (!projector || points.length === 0) return [];\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [],\n );\n\n const drawRef = useRef({ shapes, worldToScreenPoints, source });\n drawRef.current = { shapes, worldToScreenPoints, source };\n\n useEffect(() => {\n const draw = (ctx: CanvasRenderingContext2D) => {\n const { shapes: s, worldToScreenPoints: w2s, source: src } = drawRef.current;\n if (!Array.isArray(s) || s.length === 0 || !src) return;\n\n const imageOuterRing = w2s(\n closeRing([\n [0, 0],\n [src.width, 0],\n [src.width, src.height],\n [0, src.height],\n ]),\n );\n drawOverlayShapes({\n ctx,\n overlayShapes: s,\n imageOuterRing,\n worldToScreenPoints: w2s,\n baseStrokeStyle: DEFAULT_REGION_STROKE_STYLE,\n });\n };\n registerDrawCallback(OVERLAY_DRAW_ID, 30, draw);\n return () => unregisterDrawCallback(OVERLAY_DRAW_ID);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n useEffect(() => { requestOverlayRedraw(); }, [rendererSerial, shapes, source, requestOverlayRedraw]);\n\n return null;\n}\n","import type { WsiClass, WsiImageSource } from \"./types\";\n\nexport interface RawImsInfo {\n width?: number | null;\n height?: number | null;\n tileSize?: number | null;\n zoom?: number | null;\n path?: string | null;\n mpp?: number | null;\n}\n\nexport interface RawWsiClass {\n classId?: string | null;\n className?: string | null;\n classColor?: string | null;\n}\n\nexport interface RawImagePayload {\n _id?: string | null;\n id?: string | null;\n name?: string | null;\n width?: number | null;\n height?: number | null;\n tileSize?: number | null;\n zoom?: number | null;\n path?: string | null;\n mpp?: number | null;\n imsInfo?: RawImsInfo | null;\n classes?: RawWsiClass[] | null;\n tileUrlBuilder?: (tier: number, x: number, y: number, tilePath: string, tileBaseUrl: string) => string;\n}\n\nexport function normalizeImageClasses(raw: Pick<RawImagePayload, \"classes\"> | null | undefined): WsiClass[] {\n return Array.isArray(raw?.classes)\n ? raw.classes.map((item: RawWsiClass) => ({\n classId: String(item?.classId ?? \"\"),\n className: String(item?.className ?? \"\"),\n classColor: String(item?.classColor ?? \"\"),\n }))\n : [];\n}\n\nfunction trimTrailingSlash(value: string): string {\n return String(value ?? \"\").replace(/\\/+$/, \"\");\n}\n\nfunction ensureLeadingSlash(value: string): string {\n const raw = String(value ?? \"\");\n return raw.startsWith(\"/\") ? raw : `/${raw}`;\n}\n\nfunction joinImsTileRoot(tileBaseUrl: string): string {\n const base = trimTrailingSlash(tileBaseUrl);\n if (!base) return \"\";\n\n // Explicit TileGroup path already provided.\n if (/\\/TileGroup\\d+$/i.test(base)) return base;\n\n let parsed: URL | null = null;\n try {\n parsed = new URL(base);\n } catch {\n parsed = null;\n }\n\n if (parsed) {\n const origin = `${parsed.protocol}//${parsed.host}`;\n const path = trimTrailingSlash(parsed.pathname || \"\");\n\n // If caller passes /ims, keep /ims and append image path directly:\n // /ims + /tiles/<hash> + /tier/y_x.webp\n if (/\\/ims$/i.test(path)) return `${origin}${path}`;\n if (/\\/tiles$/i.test(path)) return `${origin}${path}`;\n return `${origin}${path}/tiles`;\n }\n\n // Relative path mode\n if (/\\/ims$/i.test(base)) return `/ims`;\n if (/\\/tiles$/i.test(base)) return `${base}`;\n return `${base}/tiles`;\n}\n\nexport function normalizeImageInfo(raw: RawImagePayload, tileBaseUrl: string): WsiImageSource {\n const ims = raw?.imsInfo ?? {};\n const isIms = !!raw?.imsInfo;\n\n const width = Number(ims.width ?? raw?.width ?? 0);\n const height = Number(ims.height ?? raw?.height ?? 0);\n const tileSize = Number(ims.tileSize ?? raw?.tileSize ?? 0);\n const maxTierZoom = Number(ims.zoom ?? raw?.zoom ?? 0);\n const tilePath = String(ims.path ?? raw?.path ?? \"\");\n const mpp = Number(ims.mpp ?? raw?.mpp ?? 0);\n\n if (!width || !height || !tileSize || !tilePath) {\n throw new Error(\"Incomplete image metadata: width/height/tileSize/path required\");\n }\n\n const normalizedPath = ensureLeadingSlash(tilePath);\n const imsTileRoot = joinImsTileRoot(tileBaseUrl);\n const tileUrlBuilder = raw?.tileUrlBuilder\n ?? (isIms ? (tier: number, x: number, y: number): string => `${imsTileRoot}${normalizedPath}/${tier}/${y}_${x}.webp` : undefined);\n\n return {\n id: raw?._id || raw?.id || \"unknown\",\n name: raw?.name || \"unknown\",\n width,\n height,\n mpp: Number.isFinite(mpp) && mpp > 0 ? mpp : undefined,\n tileSize,\n maxTierZoom: Number.isFinite(maxTierZoom) ? Math.max(0, Math.floor(maxTierZoom)) : 0,\n tilePath,\n tileBaseUrl,\n tileUrlBuilder,\n };\n}\n\nexport function toTileUrl(source: Pick<WsiImageSource, \"tilePath\" | \"tileBaseUrl\" | \"tileUrlBuilder\">, tier: number, x: number, y: number): string {\n if (source.tileUrlBuilder) {\n return source.tileUrlBuilder(tier, x, y, source.tilePath, source.tileBaseUrl);\n }\n const normalizedPath = ensureLeadingSlash(source.tilePath);\n return `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import { type CSSProperties, type MutableRefObject, type ReactNode, type PointerEvent as ReactPointerEvent, type RefObject, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { observeDevicePixelRatioChanges } from \"../wsi/device-pixel-ratio\";\nimport { toTileUrl } from \"../wsi/image-info\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\n\ntype Bounds = [number, number, number, number];\n\ninterface RotatedImageMetrics {\n cos: number;\n sin: number;\n minX: number;\n minY: number;\n width: number;\n height: number;\n translateX: number;\n translateY: number;\n}\n\ninterface OverviewImageLayout {\n contentX: number;\n contentY: number;\n contentWidth: number;\n contentHeight: number;\n metrics: RotatedImageMetrics;\n}\n\nfunction shouldAttachAuthHeaderToOverviewTile(url: string, authToken: string): boolean {\n if (!authToken) return false;\n const host = new URL(url, typeof window !== \"undefined\" ? window.location.href : undefined).hostname.toLowerCase();\n if (host.includes(\"amazonaws.com\") || host.startsWith(\"s3.\") || host.includes(\".s3.\")) return false;\n return true;\n}\n\nexport interface OverviewMapProjector {\n getViewState: () => WsiViewState;\n setViewState: (next: Partial<WsiViewState>) => void;\n setViewCenter?: (worldX: number, worldY: number) => void;\n getViewBounds?: () => number[];\n getViewCorners?: () => Array<[number, number]>;\n getInitialRotationDeg?: () => number;\n}\n\nexport type OverviewMapPosition = \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\n\nexport type ViewportBorderStyle = \"stroke\" | \"dash\";\n\nexport interface OverviewMapOptions {\n width: number;\n height: number;\n margin: number;\n position: OverviewMapPosition;\n borderRadius: number;\n borderWidth: number;\n backgroundColor: string;\n borderColor: string;\n viewportBorderColor: string;\n viewportBorderStyle: ViewportBorderStyle;\n viewportFillColor: string;\n interactive: boolean;\n showThumbnail: boolean;\n maxThumbnailTiles: number;\n onClose?: () => void;\n closeIcon?: ReactNode;\n closeButtonStyle?: CSSProperties;\n}\n\nexport interface OverviewMapProps {\n source: WsiImageSource;\n projectorRef: RefObject<OverviewMapProjector | null>;\n authToken?: string;\n options?: Partial<OverviewMapOptions>;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n width: 200,\n height: 125,\n margin: 16,\n position: \"bottom-right\",\n borderRadius: 6,\n borderWidth: 0,\n backgroundColor: \"rgba(4, 10, 18, 0.88)\",\n borderColor: \"rgba(230, 244, 255, 0.35)\",\n viewportBorderColor: \"rgba(255, 106, 61, 0.95)\",\n viewportBorderStyle: \"dash\",\n viewportFillColor: \"transparent\",\n interactive: true,\n showThumbnail: true,\n maxThumbnailTiles: 16,\n};\n\nfunction strokeSymmetricDashedPolygon(ctx: CanvasRenderingContext2D, points: Array<[number, number]>, dashLen: number, gapLen: number): void {\n const len = points.length;\n if (len < 3) return;\n if (dashLen <= 0 || gapLen <= 0) return;\n\n for (let i = 0; i < len; i += 1) {\n const from = points[i];\n const to = points[(i + 1) % len];\n const sideLen = Math.hypot(to[0] - from[0], to[1] - from[1]);\n if (sideLen < 1e-6) continue;\n\n const n = Math.max(1, Math.round((sideLen + gapLen) / (dashLen + gapLen)));\n const fittedLen = n * dashLen + (n - 1) * gapLen;\n const scale = sideLen / Math.max(1e-6, fittedLen);\n const adjDash = dashLen * scale;\n const adjGap = gapLen * scale;\n\n ctx.beginPath();\n ctx.moveTo(from[0], from[1]);\n ctx.lineTo(to[0], to[1]);\n ctx.setLineDash([adjDash, adjGap]);\n ctx.lineDashOffset = 0;\n ctx.stroke();\n }\n\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n}\n\nfunction isSamePoint(a: readonly [number, number], b: readonly [number, number], epsilon = 1e-4): boolean {\n return Math.abs(a[0] - b[0]) <= epsilon && Math.abs(a[1] - b[1]) <= epsilon;\n}\n\nfunction compactPolygonPoints(points: Array<[number, number]>): Array<[number, number]> {\n const compact: Array<[number, number]> = [];\n for (const point of points) {\n const prev = compact[compact.length - 1];\n if (!prev || !isSamePoint(prev, point)) {\n compact.push(point);\n }\n }\n if (compact.length > 1 && isSamePoint(compact[0], compact[compact.length - 1])) {\n compact.pop();\n }\n return compact;\n}\n\nfunction intersectAtX(from: readonly [number, number], to: readonly [number, number], x: number): [number, number] {\n const dx = to[0] - from[0];\n if (Math.abs(dx) < 1e-6) return [x, from[1]];\n const t = (x - from[0]) / dx;\n return [x, from[1] + (to[1] - from[1]) * t];\n}\n\nfunction intersectAtY(from: readonly [number, number], to: readonly [number, number], y: number): [number, number] {\n const dy = to[1] - from[1];\n if (Math.abs(dy) < 1e-6) return [from[0], y];\n const t = (y - from[1]) / dy;\n return [from[0] + (to[0] - from[0]) * t, y];\n}\n\nfunction clipPolygonToRect(points: Array<[number, number]>, minX: number, minY: number, maxX: number, maxY: number): Array<[number, number]> {\n let output = compactPolygonPoints(points);\n if (output.length < 3) return [];\n\n const edges: Array<{\n inside: (point: readonly [number, number]) => boolean;\n intersect: (from: readonly [number, number], to: readonly [number, number]) => [number, number];\n }> = [\n {\n inside: point => point[0] >= minX,\n intersect: (from, to) => intersectAtX(from, to, minX),\n },\n {\n inside: point => point[0] <= maxX,\n intersect: (from, to) => intersectAtX(from, to, maxX),\n },\n {\n inside: point => point[1] >= minY,\n intersect: (from, to) => intersectAtY(from, to, minY),\n },\n {\n inside: point => point[1] <= maxY,\n intersect: (from, to) => intersectAtY(from, to, maxY),\n },\n ];\n\n for (const edge of edges) {\n if (output.length === 0) return [];\n const input = output;\n output = [];\n let prev = input[input.length - 1];\n let prevInside = edge.inside(prev);\n for (const curr of input) {\n const currInside = edge.inside(curr);\n if (currInside) {\n if (!prevInside) {\n output.push(edge.intersect(prev, curr));\n }\n output.push(curr);\n } else if (prevInside) {\n output.push(edge.intersect(prev, curr));\n }\n prev = curr;\n prevInside = currInside;\n }\n output = compactPolygonPoints(output);\n }\n\n return output.length >= 3 ? output : [];\n}\n\nfunction toPositiveNumber(value: number | undefined, fallback: number, min = 1): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n return Math.max(min, value);\n}\n\nfunction toFiniteRotation(value: number | undefined): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction toRadians(deg: number): number {\n return (deg * Math.PI) / 180;\n}\n\nfunction getRotatedImageMetrics(imageWidth: number, imageHeight: number, rotationDeg: number): RotatedImageMetrics {\n const safeRotation = toFiniteRotation(rotationDeg);\n const rad = toRadians(safeRotation);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const centerX = imageWidth * 0.5;\n const centerY = imageHeight * 0.5;\n const translateX = -cos * centerX - sin * centerY;\n const translateY = sin * centerX - cos * centerY;\n\n const corners: Array<[number, number]> = [\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ].map(([x, y]) => [cos * x + sin * y + translateX, -sin * x + cos * y + translateY]);\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of corners) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n return {\n cos,\n sin,\n minX,\n minY,\n width: Math.max(1e-6, maxX - minX),\n height: Math.max(1e-6, maxY - minY),\n translateX,\n translateY,\n };\n}\n\nfunction getOverviewImageLayout(imageWidth: number, imageHeight: number, boxWidth: number, boxHeight: number, rotationDeg: number): OverviewImageLayout {\n const metrics = getRotatedImageMetrics(imageWidth, imageHeight, rotationDeg);\n const imageAspect = metrics.width / metrics.height;\n const boxAspect = boxWidth / boxHeight;\n\n let contentWidth: number;\n let contentHeight: number;\n if (imageAspect > boxAspect) {\n contentWidth = boxWidth;\n contentHeight = boxWidth / imageAspect;\n } else {\n contentHeight = boxHeight;\n contentWidth = boxHeight * imageAspect;\n }\n\n return {\n contentX: (boxWidth - contentWidth) / 2,\n contentY: (boxHeight - contentHeight) / 2,\n contentWidth,\n contentHeight,\n metrics,\n };\n}\n\nfunction worldToOverviewPoint(worldX: number, worldY: number, layout: OverviewImageLayout): [number, number] {\n const { contentX, contentY, contentWidth, contentHeight, metrics } = layout;\n const rotatedX = metrics.cos * worldX + metrics.sin * worldY + metrics.translateX - metrics.minX;\n const rotatedY = -metrics.sin * worldX + metrics.cos * worldY + metrics.translateY - metrics.minY;\n return [contentX + (rotatedX / metrics.width) * contentWidth, contentY + (rotatedY / metrics.height) * contentHeight];\n}\n\nfunction overviewPointToWorld(pointX: number, pointY: number, layout: OverviewImageLayout, imageWidth: number, imageHeight: number): [number, number] {\n const { metrics } = layout;\n const rotatedX = pointX + metrics.minX - metrics.translateX;\n const rotatedY = pointY + metrics.minY - metrics.translateY;\n const worldX = rotatedX * metrics.cos - rotatedY * metrics.sin;\n const worldY = rotatedX * metrics.sin + rotatedY * metrics.cos;\n return [clamp(worldX, 0, imageWidth), clamp(worldY, 0, imageHeight)];\n}\n\nfunction boundsToCorners(bounds: Bounds): Array<[number, number]> {\n return [\n [bounds[0], bounds[1]],\n [bounds[2], bounds[1]],\n [bounds[2], bounds[3]],\n [bounds[0], bounds[3]],\n ];\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n return Array.isArray(bounds) && bounds.length === 4 && Number.isFinite(bounds[0]) && Number.isFinite(bounds[1]) && Number.isFinite(bounds[2]) && Number.isFinite(bounds[3]);\n}\n\nconst DEFAULT_CLOSE_BUTTON_STYLE: CSSProperties = {\n position: \"absolute\",\n top: 4,\n right: 4,\n zIndex: 1,\n width: 18,\n height: 18,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.4)\",\n background: \"rgba(16, 17, 19, 0.85)\",\n color: \"#fff\",\n fontSize: 12,\n lineHeight: 1,\n cursor: \"pointer\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n};\n\nexport function OverviewMap({ source, projectorRef, authToken = \"\", options, invalidateRef, className, style }: OverviewMapProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n const lastBoundsRef = useRef<Bounds | null>(null);\n const draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n active: false,\n pointerId: null,\n });\n const rafRef = useRef<number | null>(null);\n const drawPendingRef = useRef(false);\n\n const width = toPositiveNumber(options?.width, DEFAULT_OVERVIEW_MAP_OPTIONS.width, 64);\n const height = toPositiveNumber(options?.height, DEFAULT_OVERVIEW_MAP_OPTIONS.height, 48);\n\n const margin = toPositiveNumber(options?.margin, DEFAULT_OVERVIEW_MAP_OPTIONS.margin, 0);\n const borderRadius = toPositiveNumber(options?.borderRadius, DEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius, 0);\n const borderWidth = toPositiveNumber(options?.borderWidth, DEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth, 0);\n const maxThumbnailTiles = Math.max(1, Math.round(toPositiveNumber(options?.maxThumbnailTiles, DEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles, 1)));\n\n const backgroundColor = options?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n const borderColor = options?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n const viewportBorderColor = options?.viewportBorderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.viewportBorderColor;\n const viewportBorderStyle = options?.viewportBorderStyle === \"stroke\" || options?.viewportBorderStyle === \"dash\" ? options.viewportBorderStyle : DEFAULT_OVERVIEW_MAP_OPTIONS.viewportBorderStyle;\n const viewportFillColor = options?.viewportFillColor ?? DEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n const interactive = options?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n const showThumbnail = options?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n const position = options?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n const onClose = options?.onClose;\n const closeIcon = options?.closeIcon;\n const closeButtonStyle = options?.closeButtonStyle;\n\n const mergedStyle = useMemo<CSSProperties>(() => {\n const pos: CSSProperties = {};\n if (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n else pos.right = margin;\n if (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n else pos.bottom = margin;\n\n return {\n position: \"absolute\",\n ...pos,\n width,\n height,\n borderRadius,\n overflow: \"hidden\",\n zIndex: 4,\n pointerEvents: interactive ? \"auto\" : \"none\",\n touchAction: \"none\",\n boxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n ...style,\n };\n }, [margin, position, width, height, borderRadius, interactive, style]);\n\n const draw = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const cssW = width;\n const cssH = height;\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const pixelW = Math.max(1, Math.round(cssW * dpr));\n const pixelH = Math.max(1, Math.round(cssH * dpr));\n if (canvas.width !== pixelW || canvas.height !== pixelH) {\n canvas.width = pixelW;\n canvas.height = pixelH;\n }\n\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, cssW, cssH);\n\n const projector = projectorRef.current;\n const initialRotationDeg = toFiniteRotation(projector?.getInitialRotationDeg?.());\n const layout = getOverviewImageLayout(source.width, source.height, cssW, cssH, initialRotationDeg);\n const { contentX: cx, contentY: cy, contentWidth: cw, contentHeight: ch, metrics } = layout;\n\n const preview = thumbnailRef.current;\n if (preview) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(cx, cy, cw, ch);\n ctx.clip();\n ctx.translate(cx, cy);\n ctx.scale(cw / metrics.width, ch / metrics.height);\n ctx.transform(metrics.cos, -metrics.sin, metrics.sin, metrics.cos, metrics.translateX - metrics.minX, metrics.translateY - metrics.minY);\n ctx.drawImage(preview, 0, 0, source.width, source.height);\n ctx.restore();\n }\n\n ctx.strokeStyle = borderColor;\n ctx.lineWidth = borderWidth;\n ctx.strokeRect(borderWidth * 0.5, borderWidth * 0.5, cssW - borderWidth, cssH - borderWidth);\n\n const bounds = projector?.getViewBounds?.();\n const corners = projector?.getViewCorners?.();\n const safeCorners =\n Array.isArray(corners) && corners.length >= 4 && corners.every(point => Array.isArray(point) && point.length >= 2 && Number.isFinite(point[0]) && Number.isFinite(point[1]))\n ? (corners as Array<[number, number]>)\n : null;\n const safeBounds = isFiniteBounds(bounds) ? bounds : isFiniteBounds(lastBoundsRef.current) ? lastBoundsRef.current : null;\n if (isFiniteBounds(bounds)) {\n lastBoundsRef.current = bounds;\n }\n\n const isDash = viewportBorderStyle === \"dash\";\n\n if (safeCorners) {\n const screenCorners: Array<[number, number]> = safeCorners.map(point => worldToOverviewPoint(point[0], point[1], layout));\n const clippedCorners = clipPolygonToRect(screenCorners, cx, cy, cx + cw, cy + ch);\n\n if (clippedCorners.length >= 3) {\n ctx.beginPath();\n for (let i = 0; i < clippedCorners.length; i += 1) {\n if (i === 0) ctx.moveTo(clippedCorners[i][0], clippedCorners[i][1]);\n else ctx.lineTo(clippedCorners[i][0], clippedCorners[i][1]);\n }\n ctx.closePath();\n ctx.fillStyle = viewportFillColor;\n ctx.fill();\n ctx.strokeStyle = viewportBorderColor;\n ctx.lineWidth = 2.25;\n if (isDash) {\n strokeSymmetricDashedPolygon(ctx, clippedCorners, 4, 3);\n } else {\n ctx.stroke();\n }\n return;\n }\n }\n\n if (!safeBounds) {\n return;\n }\n\n const fallbackCorners = boundsToCorners(safeBounds).map(point => worldToOverviewPoint(point[0], point[1], layout));\n const clippedCorners = clipPolygonToRect(fallbackCorners, cx, cy, cx + cw, cy + ch);\n if (clippedCorners.length < 3) {\n return;\n }\n\n ctx.beginPath();\n for (let i = 0; i < clippedCorners.length; i += 1) {\n if (i === 0) ctx.moveTo(clippedCorners[i][0], clippedCorners[i][1]);\n else ctx.lineTo(clippedCorners[i][0], clippedCorners[i][1]);\n }\n ctx.closePath();\n ctx.fillStyle = viewportFillColor;\n ctx.fill();\n ctx.strokeStyle = viewportBorderColor;\n ctx.lineWidth = 2.25;\n if (isDash) {\n strokeSymmetricDashedPolygon(ctx, clippedCorners, 4, 3);\n } else {\n ctx.stroke();\n }\n }, [width, height, backgroundColor, borderColor, borderWidth, projectorRef, source.width, source.height, viewportFillColor, viewportBorderColor, viewportBorderStyle]);\n\n const requestDraw = useCallback(() => {\n if (drawPendingRef.current) return;\n drawPendingRef.current = true;\n rafRef.current = requestAnimationFrame(() => {\n drawPendingRef.current = false;\n rafRef.current = null;\n draw();\n });\n }, [draw]);\n\n const toWorldFromClient = useCallback(\n (clientX: number, clientY: number): [number, number] | null => {\n const canvas = canvasRef.current;\n if (!canvas) return null;\n\n const rect = canvas.getBoundingClientRect();\n if (!rect.width || !rect.height) return null;\n\n const projector = projectorRef.current;\n const initialRotationDeg = toFiniteRotation(projector?.getInitialRotationDeg?.());\n const layout = getOverviewImageLayout(source.width, source.height, width, height, initialRotationDeg);\n const scaleX = rect.width / width;\n const scaleY = rect.height / height;\n const cxPx = layout.contentX * scaleX;\n const cyPx = layout.contentY * scaleY;\n const cwPx = layout.contentWidth * scaleX;\n const chPx = layout.contentHeight * scaleY;\n\n const nx = clamp((clientX - rect.left - cxPx) / cwPx, 0, 1);\n const ny = clamp((clientY - rect.top - cyPx) / chPx, 0, 1);\n return overviewPointToWorld(nx * layout.metrics.width, ny * layout.metrics.height, layout, source.width, source.height);\n },\n [projectorRef, source.width, source.height, width, height]\n );\n\n const recenterTo = useCallback(\n (worldX: number, worldY: number) => {\n const projector = projectorRef.current;\n if (!projector) return;\n\n if (projector.setViewCenter) {\n projector.setViewCenter(worldX, worldY);\n requestDraw();\n return;\n }\n\n const bounds = projector.getViewBounds?.();\n const safeBounds = isFiniteBounds(bounds) ? bounds : isFiniteBounds(lastBoundsRef.current) ? lastBoundsRef.current : null;\n if (!safeBounds) return;\n\n const visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n const visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n projector.setViewState({\n offsetX: worldX - visibleW * 0.5,\n offsetY: worldY - visibleH * 0.5,\n });\n requestDraw();\n },\n [projectorRef, requestDraw]\n );\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!interactive) return;\n if (event.button !== 0) return;\n\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const world = toWorldFromClient(event.clientX, event.clientY);\n if (!world) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n canvas.setPointerCapture(event.pointerId);\n draggingRef.current = { active: true, pointerId: event.pointerId };\n recenterTo(world[0], world[1]);\n },\n [interactive, toWorldFromClient, recenterTo]\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const drag = draggingRef.current;\n if (!drag.active || drag.pointerId !== event.pointerId) return;\n\n const world = toWorldFromClient(event.clientX, event.clientY);\n if (!world) return;\n\n event.preventDefault();\n event.stopPropagation();\n recenterTo(world[0], world[1]);\n },\n [toWorldFromClient, recenterTo]\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const drag = draggingRef.current;\n if (!drag.active || drag.pointerId !== event.pointerId) return;\n\n const canvas = canvasRef.current;\n if (canvas && canvas.hasPointerCapture(event.pointerId)) {\n try {\n canvas.releasePointerCapture(event.pointerId);\n } catch {\n // noop\n }\n }\n\n draggingRef.current = { active: false, pointerId: null };\n requestDraw();\n },\n [requestDraw]\n );\n\n useEffect(() => {\n let cancelled = false;\n thumbnailRef.current = null;\n requestDraw();\n\n const tier = 0;\n const levelScale = 2 ** (source.maxTierZoom - tier);\n const levelWidth = Math.ceil(source.width / levelScale);\n const levelHeight = Math.ceil(source.height / levelScale);\n const tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n const tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n const tileCount = tilesX * tilesY;\n\n if (!showThumbnail || tileCount > maxThumbnailTiles) {\n return undefined;\n }\n\n const previewScale = Math.min(width / Math.max(1, source.width), height / Math.max(1, source.height));\n const preview = document.createElement(\"canvas\");\n preview.width = Math.max(1, Math.round(source.width * previewScale));\n preview.height = Math.max(1, Math.round(source.height * previewScale));\n const ctx = preview.getContext(\"2d\");\n if (!ctx) {\n return undefined;\n }\n\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, preview.width, preview.height);\n\n const requests: Array<{\n url: string;\n bounds: Bounds;\n }> = [];\n\n for (let y = 0; y < tilesY; y += 1) {\n for (let x = 0; x < tilesX; x += 1) {\n const left = x * source.tileSize * levelScale;\n const top = y * source.tileSize * levelScale;\n const right = Math.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n const bottom = Math.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n requests.push({\n url: toTileUrl(source, tier, x, y),\n bounds: [left, top, right, bottom],\n });\n }\n }\n\n void Promise.allSettled(\n requests.map(async tile => {\n const useAuthHeader = shouldAttachAuthHeaderToOverviewTile(tile.url, authToken);\n const response = await fetch(tile.url, {\n headers: useAuthHeader ? { Authorization: authToken } : undefined,\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const bitmap = await createImageBitmap(await response.blob());\n return { tile, bitmap };\n })\n ).then(results => {\n if (cancelled) {\n for (const result of results) {\n if (result.status === \"fulfilled\") {\n result.value.bitmap.close();\n }\n }\n return;\n }\n\n const sx = preview.width / Math.max(1, source.width);\n const sy = preview.height / Math.max(1, source.height);\n for (const result of results) {\n if (result.status !== \"fulfilled\") continue;\n const {\n tile: { bounds },\n bitmap,\n } = result.value;\n const dx = bounds[0] * sx;\n const dy = bounds[1] * sy;\n const dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n const dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n ctx.drawImage(bitmap, dx, dy, dw, dh);\n bitmap.close();\n }\n\n thumbnailRef.current = preview;\n requestDraw();\n });\n\n return () => {\n cancelled = true;\n };\n }, [source, authToken, backgroundColor, width, height, showThumbnail, maxThumbnailTiles, requestDraw]);\n\n useEffect(() => {\n requestDraw();\n }, [requestDraw]);\n\n useEffect(() => {\n if (projectorRef.current) return undefined;\n let rafId = 0;\n const tick = () => {\n if (projectorRef.current) {\n requestDraw();\n return;\n }\n rafId = requestAnimationFrame(tick);\n };\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, [projectorRef, requestDraw]);\n\n useEffect(() => observeDevicePixelRatioChanges(() => requestDraw()), [requestDraw]);\n\n useEffect(() => {\n if (!invalidateRef) return undefined;\n invalidateRef.current = requestDraw;\n return () => {\n if (invalidateRef.current === requestDraw) {\n invalidateRef.current = null;\n }\n };\n }, [invalidateRef, requestDraw]);\n\n useEffect(\n () => () => {\n draggingRef.current = { active: false, pointerId: null };\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n drawPendingRef.current = false;\n },\n []\n );\n\n return (\n <div className={className} style={mergedStyle}>\n <canvas\n ref={canvasRef}\n style={{\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n borderRadius: \"inherit\",\n }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onContextMenu={event => {\n event.preventDefault();\n }}\n onWheel={event => {\n event.preventDefault();\n event.stopPropagation();\n }}\n />\n {onClose && (\n <button\n type=\"button\"\n aria-label=\"Hide overview map\"\n onClick={event => {\n event.stopPropagation();\n onClose();\n }}\n style={closeButtonStyle ? { ...(closeButtonStyle as CSSProperties) } : { ...(DEFAULT_CLOSE_BUTTON_STYLE as CSSProperties) }}\n >\n {closeIcon ?? \"×\"}\n </button>\n )}\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { WsiRegion } from \"../wsi/types\";\nimport type {\n DrawCoordinate,\n PreparedRenderedRegion,\n RegionStrokeStyle,\n} from \"./draw-layer-types\";\nimport { DEFAULT_PATCH_STROKE_STYLE } from \"./draw-layer-types\";\nimport { drawPath, mergeStrokeStyle, normalizeDrawRegionPolygons, toCoord } from \"./draw-layer-utils\";\nimport { useViewerContext } from \"./viewer-context\";\n\nexport interface PatchLayerProps {\n regions?: WsiRegion[];\n strokeStyle?: Partial<RegionStrokeStyle>;\n}\n\nconst PATCH_DRAW_ID = \"__patch_layer__\";\nconst EMPTY_REGIONS: WsiRegion[] = [];\n\nexport function PatchLayer({ regions, strokeStyle }: PatchLayerProps): React.ReactElement | null {\n const { rendererRef, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw } = useViewerContext();\n\n const safeRegions = regions ?? EMPTY_REGIONS;\n\n const resolvedStrokeStyle = useMemo(() => mergeStrokeStyle(DEFAULT_PATCH_STROKE_STYLE, strokeStyle), [strokeStyle]);\n\n const prepared = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < safeRegions.length; i += 1) {\n const region = safeRegions[i];\n const polys = normalizeDrawRegionPolygons(region.coordinates);\n if (polys.length === 0) continue;\n out.push({ region, regionIndex: i, regionKey: region.id ?? i, polygons: polys });\n }\n return out;\n }, [safeRegions]);\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = rendererRef.current;\n if (!projector || points.length === 0) return [];\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [],\n );\n\n const drawRef = useRef({ prepared, resolvedStrokeStyle, worldToScreenPoints });\n drawRef.current = { prepared, resolvedStrokeStyle, worldToScreenPoints };\n\n useEffect(() => {\n const draw = (ctx: CanvasRenderingContext2D) => {\n const { prepared: prep, resolvedStrokeStyle: style, worldToScreenPoints: w2s } = drawRef.current;\n for (const entry of prep) {\n for (const polygon of entry.polygons) {\n const screenOuter = w2s(polygon.outer);\n if (screenOuter.length >= 4) drawPath(ctx, screenOuter, style, true, false);\n for (const hole of polygon.holes) {\n const screenHole = w2s(hole);\n if (screenHole.length >= 4) drawPath(ctx, screenHole, style, true, false);\n }\n }\n }\n };\n registerDrawCallback(PATCH_DRAW_ID, 20, draw);\n return () => unregisterDrawCallback(PATCH_DRAW_ID);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n useEffect(() => { requestOverlayRedraw(); }, [prepared, resolvedStrokeStyle, requestOverlayRedraw]);\n\n return null;\n}\n","import { pointInAnyPreparedPolygon, prepareRoiPolygons, type RoiCoordinate, type RoiGeometry } from \"./roi-geometry\";\nimport type { WsiPointData } from \"./types\";\nimport { sanitizePointCount } from \"./utils\";\n\nexport type { RoiCoordinate };\nexport type RoiPolygon = RoiGeometry;\n\nexport function filterPointDataByPolygons(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): WsiPointData | null {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const prepared = prepareRoiPolygons(polygons ?? []);\n if (prepared.length === 0) {\n const empty: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointData.fillModes instanceof Uint8Array) {\n empty.fillModes = new Uint8Array(0);\n }\n if (pointData.ids instanceof Uint32Array) {\n empty.ids = new Uint32Array(0);\n }\n return empty;\n }\n\n const count = sanitizePointCount(pointData);\n const positions = pointData.positions;\n const classes = pointData.paletteIndices;\n const fillModes = pointData.fillModes instanceof Uint8Array && pointData.fillModes.length >= count ? pointData.fillModes : null;\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= count ? pointData.ids : null;\n\n const nextPositions = new Float32Array(count * 2);\n const nextClasses = new Uint16Array(count);\n const nextFillModes = fillModes ? new Uint8Array(count) : null;\n const nextIds = pointIds ? new Uint32Array(count) : null;\n let cursor = 0;\n\n for (let i = 0; i < count; i += 1) {\n const x = positions[i * 2];\n const y = positions[i * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextClasses[cursor] = classes[i];\n if (nextFillModes) {\n nextFillModes[cursor] = fillModes![i];\n }\n if (nextIds) {\n nextIds[cursor] = pointIds![i];\n }\n cursor += 1;\n }\n\n const output: WsiPointData = {\n count: cursor,\n positions: nextPositions.subarray(0, cursor * 2),\n paletteIndices: nextClasses.subarray(0, cursor),\n };\n if (nextFillModes) {\n output.fillModes = nextFillModes.subarray(0, cursor);\n }\n if (nextIds) {\n output.ids = nextIds.subarray(0, cursor);\n }\n return output;\n}\n\nexport function filterPointIndicesByPolygons(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Uint32Array {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return new Uint32Array(0);\n }\n\n const prepared = prepareRoiPolygons(polygons ?? []);\n if (prepared.length === 0) {\n return new Uint32Array(0);\n }\n\n const count = sanitizePointCount(pointData);\n if (count === 0) {\n return new Uint32Array(0);\n }\n\n const positions = pointData.positions;\n const out = new Uint32Array(count);\n let cursor = 0;\n\n for (let i = 0; i < count; i += 1) {\n const x = positions[i * 2];\n const y = positions[i * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n out[cursor] = i;\n cursor += 1;\n }\n\n return out.subarray(0, cursor);\n}\n","export interface WebGpuCapabilities {\n\tsupported: boolean;\n\tadapterName?: string;\n\tfeatures: string[];\n\tlimits?: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n}\n\ninterface NavigatorGpuLike {\n\trequestAdapter: () => Promise<GpuAdapterLike | null>;\n}\n\ninterface GpuAdapterLike {\n\tinfo?: {\n\t\tdescription?: string;\n\t\tvendor?: string;\n\t};\n\tfeatures: Iterable<string>;\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n\trequestDevice: () => Promise<GpuDeviceLike>;\n}\n\ninterface GpuBufferLike {\n\tdestroy: () => void;\n\tmapAsync: (mode: number) => Promise<void>;\n\tgetMappedRange: () => ArrayBuffer;\n\tunmap: () => void;\n}\n\ninterface GpuComputePassLike {\n\tsetPipeline: (pipeline: GpuComputePipelineLike) => void;\n\tsetBindGroup: (index: number, bindGroup: unknown) => void;\n\tdispatchWorkgroups: (x: number, y?: number, z?: number) => void;\n\tend: () => void;\n}\n\ninterface GpuCommandEncoderLike {\n\tbeginComputePass: () => GpuComputePassLike;\n\tcopyBufferToBuffer: (\n\t\tsource: GpuBufferLike,\n\t\tsourceOffset: number,\n\t\tdestination: GpuBufferLike,\n\t\tdestinationOffset: number,\n\t\tsize: number,\n\t) => void;\n\tfinish: () => unknown;\n}\n\ninterface GpuQueueLike {\n\twriteBuffer: (\n\t\tbuffer: GpuBufferLike,\n\t\tbufferOffset: number,\n\t\tdata: ArrayBufferView | ArrayBufferLike,\n\t\tdataOffset?: number,\n\t\tsize?: number,\n\t) => void;\n\tsubmit: (commands: unknown[]) => void;\n}\n\ninterface GpuComputePipelineLike {\n\treadonly _brand?: \"GpuComputePipelineLike\";\n}\n\ninterface GpuBindGroupLayoutLike {\n\treadonly _brand?: \"GpuBindGroupLayoutLike\";\n}\n\ninterface GpuDeviceLike {\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t};\n\tqueue: GpuQueueLike;\n\tcreateBindGroupLayout: (descriptor: unknown) => GpuBindGroupLayoutLike;\n\tcreatePipelineLayout: (descriptor: unknown) => unknown;\n\tcreateShaderModule: (descriptor: { code: string }) => unknown;\n\tcreateComputePipeline: (descriptor: unknown) => GpuComputePipelineLike;\n\tcreateBuffer: (descriptor: { size: number; usage: number }) => GpuBufferLike;\n\tcreateBindGroup: (descriptor: unknown) => unknown;\n\tcreateCommandEncoder: () => GpuCommandEncoderLike;\n}\n\ninterface WebGpuContext {\n\tdevice: GpuDeviceLike;\n\tpipeline: GpuComputePipelineLike;\n\tbindGroupLayout: GpuBindGroupLayoutLike;\n}\n\nlet contextPromise: Promise<WebGpuContext | null> | null = null;\n\nconst BBOX_PREFILTER_SHADER = `\nstruct Params {\n pointCount: u32,\n boundsCount: u32,\n _pad0: u32,\n _pad1: u32,\n};\n\n@group(0) @binding(0) var<storage, read> positions: array<vec2<f32>>;\n@group(0) @binding(1) var<storage, read> bounds: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read_write> outputMask: array<u32>;\n@group(0) @binding(3) var<uniform> params: Params;\n\n@compute @workgroup_size(256)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let i = gid.x;\n if (i >= params.pointCount) {\n return;\n }\n\n let p = positions[i];\n var inside: u32 = 0u;\n for (var bi: u32 = 0u; bi < params.boundsCount; bi = bi + 1u) {\n let b = bounds[bi];\n if (p.x >= b.x && p.x <= b.z && p.y >= b.y && p.y <= b.w) {\n inside = 1u;\n break;\n }\n }\n outputMask[i] = inside;\n}\n`;\n\nfunction hasWebGpu(): boolean {\n\tif (typeof navigator === \"undefined\") return false;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\treturn typeof nav.gpu === \"object\" && nav.gpu !== null;\n}\n\nfunction getNavigatorGpu(): NavigatorGpuLike | null {\n\tif (!hasWebGpu()) return null;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\tconst gpu = nav.gpu;\n\tif (!gpu || typeof gpu !== \"object\") return null;\n\tconst candidate = gpu as Partial<NavigatorGpuLike>;\n\tif (typeof candidate.requestAdapter !== \"function\") return null;\n\treturn candidate as NavigatorGpuLike;\n}\n\nconst GPU_SHADER_STAGE_COMPUTE =\n\t(globalThis as { GPUShaderStage?: { COMPUTE?: number } }).GPUShaderStage\n\t\t?.COMPUTE ?? 0x4;\nconst GPU_BUFFER_USAGE_STORAGE =\n\t(globalThis as { GPUBufferUsage?: { STORAGE?: number } }).GPUBufferUsage\n\t\t?.STORAGE ?? 0x80;\nconst GPU_BUFFER_USAGE_COPY_DST =\n\t(globalThis as { GPUBufferUsage?: { COPY_DST?: number } }).GPUBufferUsage\n\t\t?.COPY_DST ?? 0x08;\nconst GPU_BUFFER_USAGE_COPY_SRC =\n\t(globalThis as { GPUBufferUsage?: { COPY_SRC?: number } }).GPUBufferUsage\n\t\t?.COPY_SRC ?? 0x04;\nconst GPU_BUFFER_USAGE_UNIFORM =\n\t(globalThis as { GPUBufferUsage?: { UNIFORM?: number } }).GPUBufferUsage\n\t\t?.UNIFORM ?? 0x40;\nconst GPU_BUFFER_USAGE_MAP_READ =\n\t(globalThis as { GPUBufferUsage?: { MAP_READ?: number } }).GPUBufferUsage\n\t\t?.MAP_READ ?? 0x01;\nconst GPU_MAP_MODE_READ =\n\t(globalThis as { GPUMapMode?: { READ?: number } }).GPUMapMode?.READ ?? 0x01;\n\nexport async function getWebGpuCapabilities(): Promise<WebGpuCapabilities> {\n\tconst navGpu = getNavigatorGpu();\n\tif (!navGpu) {\n\t\treturn { supported: false, features: [] };\n\t}\n\tconst adapter = await navGpu.requestAdapter();\n\tif (!adapter) {\n\t\treturn { supported: false, features: [] };\n\t}\n\n\treturn {\n\t\tsupported: true,\n\t\tadapterName: adapter.info?.description ?? adapter.info?.vendor ?? \"unknown\",\n\t\tfeatures: Array.from(adapter.features),\n\t\tlimits: {\n\t\t\tmaxStorageBufferBindingSize: Number(\n\t\t\t\tadapter.limits.maxStorageBufferBindingSize,\n\t\t\t),\n\t\t\tmaxComputeInvocationsPerWorkgroup: Number(\n\t\t\t\tadapter.limits.maxComputeInvocationsPerWorkgroup,\n\t\t\t),\n\t\t\tmaxComputeWorkgroupSizeX: Number(adapter.limits.maxComputeWorkgroupSizeX),\n\t\t},\n\t};\n}\n\nasync function getContext(): Promise<WebGpuContext | null> {\n\tif (contextPromise) return contextPromise;\n\tcontextPromise = (async () => {\n\t\tconst navGpu = getNavigatorGpu();\n\t\tif (!navGpu) return null;\n\t\tconst adapter = await navGpu.requestAdapter();\n\t\tif (!adapter) return null;\n\t\tconst device = await adapter.requestDevice();\n\n\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: [\n\t\t\t\t{\n\t\t\t\t\tbinding: 0,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 1,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 2,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 3,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"uniform\" },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\n\t\tconst pipeline = device.createComputePipeline({\n\t\t\tlayout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),\n\t\t\tcompute: {\n\t\t\t\tmodule: device.createShaderModule({ code: BBOX_PREFILTER_SHADER }),\n\t\t\t\tentryPoint: \"main\",\n\t\t\t},\n\t\t});\n\n\t\treturn { device, pipeline, bindGroupLayout };\n\t})();\n\n\treturn contextPromise;\n}\n\nfunction align(value: number, step: number): number {\n\treturn Math.ceil(value / step) * step;\n}\n\nexport async function prefilterPointsByBoundsWebGpu(\n\tpositions: Float32Array,\n\tpointCount: number,\n\tbounds: Float32Array,\n): Promise<Uint32Array | null> {\n\tconst ctx = await getContext();\n\tif (!ctx) return null;\n\n\tconst count = Math.max(0, Math.floor(pointCount));\n\tconst boundsCount = Math.max(0, Math.floor(bounds.length / 4));\n\tif (count === 0 || boundsCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst safePointCount = Math.min(count, Math.floor(positions.length / 2));\n\tif (safePointCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positionBytes = safePointCount * 2 * Float32Array.BYTES_PER_ELEMENT;\n\tconst boundsBytes = boundsCount * 4 * Float32Array.BYTES_PER_ELEMENT;\n\tconst outputBytes = safePointCount * Uint32Array.BYTES_PER_ELEMENT;\n\n\tconst limit = Number(ctx.device.limits.maxStorageBufferBindingSize);\n\tif (positionBytes > limit || boundsBytes > limit || outputBytes > limit) {\n\t\treturn null;\n\t}\n\n\tconst positionsBuffer = ctx.device.createBuffer({\n\t\tsize: align(positionBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst boundsBuffer = ctx.device.createBuffer({\n\t\tsize: align(boundsBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst outputBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC,\n\t});\n\tconst uniformBuffer = ctx.device.createBuffer({\n\t\tsize: 16,\n\t\tusage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst readBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_MAP_READ,\n\t});\n\n\tlet readBufferMapped = false;\n\ttry {\n\t\tctx.device.queue.writeBuffer(\n\t\t\tpositionsBuffer,\n\t\t\t0,\n\t\t\tpositions.buffer,\n\t\t\tpositions.byteOffset,\n\t\t\tpositionBytes,\n\t\t);\n\t\tctx.device.queue.writeBuffer(\n\t\t\tboundsBuffer,\n\t\t\t0,\n\t\t\tbounds.buffer,\n\t\t\tbounds.byteOffset,\n\t\t\tboundsBytes,\n\t\t);\n\t\tctx.device.queue.writeBuffer(\n\t\t\tuniformBuffer,\n\t\t\t0,\n\t\t\tnew Uint32Array([safePointCount, boundsCount, 0, 0]),\n\t\t);\n\n\t\tconst bindGroup = ctx.device.createBindGroup({\n\t\t\tlayout: ctx.bindGroupLayout,\n\t\t\tentries: [\n\t\t\t\t{ binding: 0, resource: { buffer: positionsBuffer } },\n\t\t\t\t{ binding: 1, resource: { buffer: boundsBuffer } },\n\t\t\t\t{ binding: 2, resource: { buffer: outputBuffer } },\n\t\t\t\t{ binding: 3, resource: { buffer: uniformBuffer } },\n\t\t\t],\n\t\t});\n\n\t\tconst commandEncoder = ctx.device.createCommandEncoder();\n\t\tconst pass = commandEncoder.beginComputePass();\n\t\tpass.setPipeline(ctx.pipeline);\n\t\tpass.setBindGroup(0, bindGroup);\n\t\tpass.dispatchWorkgroups(Math.ceil(safePointCount / 256));\n\t\tpass.end();\n\n\t\tcommandEncoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, outputBytes);\n\t\tctx.device.queue.submit([commandEncoder.finish()]);\n\n\t\tawait readBuffer.mapAsync(GPU_MAP_MODE_READ);\n\t\treadBufferMapped = true;\n\t\tconst mapped = readBuffer.getMappedRange();\n\t\treturn new Uint32Array(mapped.slice(0));\n\t} finally {\n\t\tif (readBufferMapped) {\n\t\t\ttry {\n\t\t\t\treadBuffer.unmap();\n\t\t\t} catch {\n\t\t\t\t// Already unmapped or map failed after resolving.\n\t\t\t}\n\t\t}\n\t\tpositionsBuffer.destroy();\n\t\tboundsBuffer.destroy();\n\t\toutputBuffer.destroy();\n\t\tuniformBuffer.destroy();\n\t\treadBuffer.destroy();\n\t}\n}\n","import { filterPointDataByPolygons, type RoiPolygon } from \"./point-clip\";\nimport {\n pointInAnyPreparedPolygon,\n prepareRoiPolygons,\n} from \"./roi-geometry\";\nimport type { WsiPointData } from \"./types\";\nimport { nowMs, sanitizePointCount } from \"./utils\";\nimport { prefilterPointsByBoundsWebGpu } from \"./webgpu\";\n\nexport interface HybridPointClipOptions {\n bridgeToDraw?: boolean;\n}\n\nexport interface HybridPointClipResult {\n data: WsiPointData | null;\n meta: {\n mode: \"hybrid-webgpu\";\n durationMs: number;\n usedWebGpu: boolean;\n candidateCount: number;\n bridgedToDraw?: boolean;\n };\n}\n\nexport async function filterPointDataByPolygonsHybrid(\n pointData: WsiPointData | null | undefined,\n polygons: RoiPolygon[] | null | undefined,\n options: HybridPointClipOptions = {}\n): Promise<HybridPointClipResult> {\n const start = nowMs();\n const bridgeToDraw = options.bridgeToDraw === true;\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const prepared = prepareRoiPolygons(polygons ?? []);\n if (prepared.length === 0) {\n const data: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointData.fillModes instanceof Uint8Array) {\n data.fillModes = new Uint8Array(0);\n }\n if (pointData.ids instanceof Uint32Array) {\n data.ids = new Uint32Array(0);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const safeCount = sanitizePointCount(pointData);\n const pointFillModes = pointData.fillModes instanceof Uint8Array && pointData.fillModes.length >= safeCount ? pointData.fillModes : null;\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids : null;\n if (safeCount === 0) {\n const data: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointFillModes) {\n data.fillModes = new Uint8Array(0);\n }\n if (pointIds) {\n data.ids = new Uint32Array(0);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const bboxFlat = new Float32Array(prepared.length * 4);\n for (let i = 0; i < prepared.length; i += 1) {\n const base = i * 4;\n const polygon = prepared[i];\n bboxFlat[base] = polygon.minX;\n bboxFlat[base + 1] = polygon.minY;\n bboxFlat[base + 2] = polygon.maxX;\n bboxFlat[base + 3] = polygon.maxY;\n }\n\n let candidateMask: Uint32Array | null = null;\n let usedWebGpu = false;\n try {\n candidateMask = await prefilterPointsByBoundsWebGpu(pointData.positions, safeCount, bboxFlat);\n usedWebGpu = !!candidateMask;\n } catch {\n candidateMask = null;\n usedWebGpu = false;\n }\n\n if (!candidateMask) {\n const fallback = filterPointDataByPolygons(pointData, polygons);\n return {\n data: fallback,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: safeCount,\n bridgedToDraw: false,\n },\n };\n }\n\n let candidateCount = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] === 1) candidateCount += 1;\n }\n\n const candidateIndices = new Uint32Array(candidateCount);\n if (candidateCount > 0) {\n let candidateCursor = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] !== 1) continue;\n candidateIndices[candidateCursor] = i;\n candidateCursor += 1;\n }\n }\n\n if (candidateCount === 0) {\n if (bridgeToDraw) {\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: new Uint32Array(0),\n };\n if (pointFillModes) {\n data.fillModes = pointFillModes.subarray(0, safeCount);\n }\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: true,\n },\n };\n }\n\n const data: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n };\n if (pointFillModes) {\n data.fillModes = new Uint8Array(0);\n }\n if (pointIds) {\n data.ids = new Uint32Array(0);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n if (bridgeToDraw) {\n const drawIndices = new Uint32Array(candidateCount);\n let visibleCount = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n drawIndices[visibleCount] = pointIndex;\n visibleCount += 1;\n }\n\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: drawIndices.subarray(0, visibleCount),\n };\n if (pointFillModes) {\n data.fillModes = pointFillModes.subarray(0, safeCount);\n }\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: true,\n },\n };\n }\n\n const nextPositions = new Float32Array(candidateCount * 2);\n const nextClasses = new Uint16Array(candidateCount);\n const nextFillModes = pointFillModes ? new Uint8Array(candidateCount) : null;\n const nextIds = pointIds ? new Uint32Array(candidateCount) : null;\n let cursor = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextClasses[cursor] = pointData.paletteIndices[pointIndex];\n if (nextFillModes) {\n nextFillModes[cursor] = pointFillModes![pointIndex];\n }\n if (nextIds) {\n nextIds[cursor] = pointIds![pointIndex];\n }\n cursor += 1;\n }\n\n const compactData: WsiPointData = {\n count: cursor,\n positions: nextPositions.subarray(0, cursor * 2),\n paletteIndices: nextClasses.subarray(0, cursor),\n };\n if (nextFillModes) {\n compactData.fillModes = nextFillModes.subarray(0, cursor);\n }\n if (nextIds) {\n compactData.ids = nextIds.subarray(0, cursor);\n }\n\n return {\n data: compactData,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: false,\n },\n };\n}\n","export interface WorkerClientHandlers<Res extends { id: number }, Pending> {\n onResponse: (message: Res, pending: Pending) => void;\n rejectPending: (pending: Pending, error: Error) => void;\n}\n\nexport class WorkerClient<Res extends { id: number }, Pending> {\n private worker: Worker | null = null;\n private supported = true;\n private requestId = 1;\n private readonly pendingById = new Map<number, Pending>();\n\n private readonly handleMessage = (event: MessageEvent<Res>): void => {\n const message = event.data;\n if (!message) return;\n const pending = this.pendingById.get(message.id);\n if (!pending) return;\n this.pendingById.delete(message.id);\n this.handlers.onResponse(message, pending);\n };\n\n private readonly handleError = (): void => {\n this.supported = false;\n this.teardownWorker(\"worker crashed\");\n };\n\n constructor(\n private readonly createWorker: () => Worker,\n private readonly handlers: WorkerClientHandlers<Res, Pending>,\n ) {}\n\n beginRequest(pending: Pending): { id: number; worker: Worker } | null {\n const worker = this.getOrCreateWorker();\n if (!worker) return null;\n const id = this.requestId++;\n this.pendingById.set(id, pending);\n return { id, worker };\n }\n\n cancelRequest(id: number): Pending | undefined {\n const pending = this.pendingById.get(id);\n if (!pending) return undefined;\n this.pendingById.delete(id);\n return pending;\n }\n\n terminate(reason = \"worker terminated\"): void {\n this.teardownWorker(reason);\n }\n\n private getOrCreateWorker(): Worker | null {\n if (!this.supported) return null;\n if (this.worker) return this.worker;\n\n try {\n const worker = this.createWorker();\n worker.addEventListener(\"message\", this.handleMessage);\n worker.addEventListener(\"error\", this.handleError);\n this.worker = worker;\n return worker;\n } catch {\n this.supported = false;\n return null;\n }\n }\n\n private teardownWorker(reason: string): void {\n if (this.worker) {\n this.worker.removeEventListener(\"message\", this.handleMessage);\n this.worker.removeEventListener(\"error\", this.handleError);\n this.worker.terminate();\n this.worker = null;\n }\n\n const error = new Error(reason);\n for (const [, pending] of this.pendingById) {\n this.handlers.rejectPending(pending, error);\n }\n this.pendingById.clear();\n }\n}\n","import { filterPointDataByPolygons, filterPointIndicesByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { RoiClipWorkerRequest, RoiClipWorkerResponse } from \"./point-clip-worker-protocol\";\nimport type { WsiPointData } from \"./types\";\nimport { nowMs, sanitizePointCount } from \"./utils\";\nimport { WorkerClient } from \"./worker-client\";\n\nexport type PointClipMode = \"sync\" | \"worker\" | \"hybrid-webgpu\";\n\nexport interface PointClipResultMeta {\n mode: PointClipMode;\n durationMs: number;\n}\n\nexport interface PointClipResult {\n data: WsiPointData | null;\n meta: PointClipResultMeta;\n}\n\nexport interface PointClipIndexResult {\n indices: Uint32Array;\n meta: PointClipResultMeta;\n}\n\ninterface PendingDataWorkerRequest {\n kind: \"data\";\n resolve: (result: PointClipResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ninterface PendingIndexWorkerRequest {\n kind: \"index\";\n resolve: (result: PointClipIndexResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ntype PendingWorkerRequest = PendingDataWorkerRequest | PendingIndexWorkerRequest;\n\nconst workerClient = new WorkerClient<RoiClipWorkerResponse, PendingWorkerRequest>(\n () => new Worker(new URL(\"../workers/roi-clip-worker.ts\", import.meta.url), { type: \"module\" }),\n {\n onResponse: (msg, pending) => {\n if (msg.type === \"roi-clip-failure\") {\n pending.reject(new Error(msg.error || \"worker clip failed\"));\n return;\n }\n\n if (msg.type === \"roi-clip-index-success\") {\n if (pending.kind !== \"index\") {\n pending.reject(new Error(\"worker response mismatch: expected point data result\"));\n return;\n }\n const count = Math.max(0, Math.floor(msg.count));\n const indices = new Uint32Array(msg.indices).subarray(0, count);\n pending.resolve({\n indices,\n meta: {\n mode: \"worker\",\n durationMs:\n Number.isFinite(msg.durationMs)\n ? msg.durationMs\n : nowMs() - pending.startMs,\n },\n });\n return;\n }\n\n if (pending.kind !== \"data\") {\n pending.reject(new Error(\"worker response mismatch: expected index result\"));\n return;\n }\n\n const count = Math.max(0, Math.floor(msg.count));\n const positions = new Float32Array(msg.positions);\n const paletteIndices = new Uint16Array(msg.paletteIndices);\n const fillModes = msg.fillModes ? new Uint8Array(msg.fillModes) : null;\n const ids = msg.ids ? new Uint32Array(msg.ids) : null;\n const output: WsiPointData = {\n count,\n positions: positions.subarray(0, count * 2),\n paletteIndices: paletteIndices.subarray(0, count),\n };\n if (fillModes) {\n output.fillModes = fillModes.subarray(0, count);\n }\n if (ids) {\n output.ids = ids.subarray(0, count);\n }\n\n pending.resolve({\n data: output,\n meta: {\n mode: \"worker\",\n durationMs:\n Number.isFinite(msg.durationMs)\n ? msg.durationMs\n : nowMs() - pending.startMs,\n },\n });\n },\n rejectPending: (pending, error) => {\n pending.reject(error);\n },\n },\n);\n\nexport function terminateRoiClipWorker(): void {\n workerClient.terminate(\"worker terminated\");\n}\n\nexport async function filterPointDataByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const safeCount = sanitizePointCount(pointData);\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const classesCopy = pointData.paletteIndices.slice(0, safeCount);\n const fillModesCopy = pointData.fillModes instanceof Uint8Array && pointData.fillModes.length >= safeCount ? pointData.fillModes.slice(0, safeCount) : null;\n const idsCopy = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.slice(0, safeCount) : null;\n\n return new Promise<PointClipResult>((resolve, reject) => {\n const startMs = nowMs();\n const requestTicket = workerClient.beginRequest({\n kind: \"data\",\n resolve,\n reject,\n startMs,\n });\n\n if (!requestTicket) {\n resolve({\n data: filterPointDataByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - startMs },\n });\n return;\n }\n\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-request\",\n id: requestTicket.id,\n count: safeCount,\n positions: positionsCopy.buffer,\n paletteIndices: classesCopy.buffer,\n fillModes: fillModesCopy?.buffer,\n ids: idsCopy?.buffer,\n polygons: polygons ?? [],\n };\n\n const transfer: Transferable[] = [positionsCopy.buffer, classesCopy.buffer];\n if (fillModesCopy) transfer.push(fillModesCopy.buffer);\n if (idsCopy) transfer.push(idsCopy.buffer);\n\n try {\n requestTicket.worker.postMessage(msg, transfer);\n } catch (error) {\n const canceled = workerClient.cancelRequest(requestTicket.id);\n if (canceled) {\n canceled.reject(error);\n } else {\n reject(error);\n }\n }\n });\n}\n\nexport async function filterPointIndicesByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipIndexResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n indices: new Uint32Array(0),\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const safeCount = sanitizePointCount(pointData);\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n\n return new Promise<PointClipIndexResult>((resolve, reject) => {\n const startMs = nowMs();\n const requestTicket = workerClient.beginRequest({\n kind: \"index\",\n resolve,\n reject,\n startMs,\n });\n\n if (!requestTicket) {\n resolve({\n indices: filterPointIndicesByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - startMs },\n });\n return;\n }\n\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-index-request\",\n id: requestTicket.id,\n count: safeCount,\n positions: positionsCopy.buffer,\n polygons: polygons ?? [],\n };\n\n try {\n requestTicket.worker.postMessage(msg, [positionsCopy.buffer]);\n } catch (error) {\n const canceled = workerClient.cancelRequest(requestTicket.id);\n if (canceled) {\n canceled.reject(error);\n } else {\n reject(error);\n }\n }\n });\n}\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { filterPointDataByPolygons, type RoiPolygon } from \"../wsi/point-clip\";\nimport { filterPointDataByPolygonsHybrid } from \"../wsi/point-clip-hybrid\";\nimport { filterPointDataByPolygonsInWorker, type PointClipMode } from \"../wsi/point-clip-worker-client\";\nimport { toRoiGeometry } from \"../wsi/roi-geometry\";\nimport type { WsiPointData, WsiRegion } from \"../wsi/types\";\nimport type { PointClipStatsEvent } from \"./wsi-viewer-canvas-types\";\n\nconst EMPTY_CLIPPED_POINTS: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n};\n\nexport function usePointClipping(\n clipPointsToRois: boolean,\n clipMode: PointClipMode,\n pointData: WsiPointData | null,\n effectiveRoiRegions: WsiRegion[],\n onClipStats?: (event: PointClipStatsEvent) => void,\n): WsiPointData | null {\n const clipRunIdRef = useRef(0);\n const [renderPointData, setRenderPointData] = useState<WsiPointData | null>(pointData);\n\n const clipPolygons = useMemo<RoiPolygon[]>(\n () => effectiveRoiRegions.map(region => toRoiGeometry(region.coordinates)).filter((p): p is RoiPolygon => p != null),\n [effectiveRoiRegions],\n );\n\n useEffect(() => {\n const runId = ++clipRunIdRef.current;\n let cancelled = false;\n\n if (!clipPointsToRois) {\n setRenderPointData(pointData);\n return () => {\n cancelled = true;\n };\n }\n\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n setRenderPointData(null);\n return () => {\n cancelled = true;\n };\n }\n\n if (clipPolygons.length === 0) {\n setRenderPointData(EMPTY_CLIPPED_POINTS);\n onClipStats?.({\n mode: clipMode,\n durationMs: 0,\n inputCount: pointData.count,\n outputCount: 0,\n polygonCount: 0,\n });\n return () => {\n cancelled = true;\n };\n }\n\n const applyResult = (data: WsiPointData | null, stats: Omit<PointClipStatsEvent, \"inputCount\" | \"outputCount\" | \"polygonCount\">) => {\n if (cancelled || runId !== clipRunIdRef.current) return;\n const inputCount = pointData.count;\n const outputCount = data?.drawIndices ? data.drawIndices.length : (data?.count ?? 0);\n setRenderPointData(data);\n onClipStats?.({\n mode: stats.mode,\n durationMs: stats.durationMs,\n inputCount,\n outputCount,\n polygonCount: clipPolygons.length,\n usedWebGpu: stats.usedWebGpu,\n candidateCount: stats.candidateCount,\n bridgedToDraw: stats.bridgedToDraw,\n });\n };\n\n const run = async (): Promise<void> => {\n if (clipMode === \"sync\") {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n return;\n }\n\n if (clipMode === \"hybrid-webgpu\") {\n const result = await filterPointDataByPolygonsHybrid(pointData, clipPolygons, { bridgeToDraw: true });\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n usedWebGpu: result.meta.usedWebGpu,\n candidateCount: result.meta.candidateCount,\n bridgedToDraw: result.meta.bridgedToDraw,\n });\n return;\n }\n\n try {\n const result = await filterPointDataByPolygonsInWorker(pointData, clipPolygons);\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n });\n } catch {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n }\n };\n\n void run();\n return () => {\n cancelled = true;\n };\n }, [clipPointsToRois, clipMode, pointData, clipPolygons, onClipStats]);\n\n return renderPointData;\n}\n","export const MIN_POINT_HIT_GRID_SIZE = 24;\nexport const MAX_POINT_HIT_GRID_SIZE = 1024;\nexport const POINT_HIT_GRID_DENSITY_SCALE = 4;\nexport const HASH_EMPTY = -1;\n\nexport interface PointHitIndexBuildInput {\n count: number;\n positions: Float32Array;\n drawIndices?: Uint32Array | null;\n sourceWidth: number;\n sourceHeight: number;\n}\n\nexport interface PointHitIndexBuildResult {\n cellSize: number;\n safeCount: number;\n cellCount: number;\n hashCapacity: number;\n hashTable: Int32Array;\n cellKeys: Int32Array;\n cellOffsets: Uint32Array;\n cellLengths: Uint32Array;\n pointIndices: Uint32Array;\n}\n\nexport function cellHash(cellX: number, cellY: number, mask: number): number {\n return (((cellX * 73856093) ^ (cellY * 19349663)) >>> 0) & mask;\n}\n\nfunction resolveGridSize(sourceWidth: number, sourceHeight: number, visibleCount: number): number {\n if (sourceWidth <= 0 || sourceHeight <= 0 || visibleCount <= 0) return 256;\n const area = Math.max(1, sourceWidth * sourceHeight);\n const avgSpacing = Math.sqrt(area / Math.max(1, visibleCount));\n const raw = avgSpacing * POINT_HIT_GRID_DENSITY_SCALE;\n return Math.max(MIN_POINT_HIT_GRID_SIZE, Math.min(MAX_POINT_HIT_GRID_SIZE, raw));\n}\n\nfunction sanitizeDrawIndices(raw: Uint32Array | null | undefined, safeCount: number): Uint32Array | null {\n if (!(raw instanceof Uint32Array) || raw.length === 0) {\n return null;\n }\n\n let allValid = true;\n for (let i = 0; i < raw.length; i += 1) {\n if (raw[i] < safeCount) continue;\n allValid = false;\n break;\n }\n if (allValid) {\n return raw;\n }\n\n const filtered = new Uint32Array(raw.length);\n let cursor = 0;\n for (let i = 0; i < raw.length; i += 1) {\n if (raw[i] >= safeCount) continue;\n filtered[cursor] = raw[i];\n cursor += 1;\n }\n return cursor > 0 ? filtered.subarray(0, cursor) : null;\n}\n\nexport function buildPointHitIndex(input: PointHitIndexBuildInput): PointHitIndexBuildResult | null {\n const count = Math.max(0, Math.floor(input.count));\n const maxCountByPositions = Math.floor(input.positions.length / 2);\n const safeCount = Math.max(0, Math.min(count, maxCountByPositions));\n if (safeCount <= 0) {\n return null;\n }\n\n const drawIndices = sanitizeDrawIndices(input.drawIndices ?? null, safeCount);\n const visibleCount = drawIndices ? drawIndices.length : safeCount;\n if (visibleCount === 0) {\n return null;\n }\n\n const cellSize = resolveGridSize(input.sourceWidth, input.sourceHeight, visibleCount);\n const invCellSize = 1.0 / cellSize;\n\n const pointCellX = new Int32Array(visibleCount);\n const pointCellY = new Int32Array(visibleCount);\n let validCount = 0;\n\n if (drawIndices) {\n for (let i = 0; i < visibleCount; i += 1) {\n const pi = drawIndices[i];\n const px = input.positions[pi * 2];\n const py = input.positions[pi * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) continue;\n pointCellX[validCount] = Math.floor(px * invCellSize);\n pointCellY[validCount] = Math.floor(py * invCellSize);\n validCount += 1;\n }\n } else {\n for (let i = 0; i < safeCount; i += 1) {\n const px = input.positions[i * 2];\n const py = input.positions[i * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) continue;\n pointCellX[validCount] = Math.floor(px * invCellSize);\n pointCellY[validCount] = Math.floor(py * invCellSize);\n validCount += 1;\n }\n }\n\n if (validCount === 0) {\n return null;\n }\n\n let estimatedCells = Math.min(validCount, Math.max(64, validCount >>> 3));\n if (!Number.isFinite(estimatedCells) || estimatedCells <= 0) {\n estimatedCells = validCount;\n }\n\n let hashCapacity = 1;\n while (hashCapacity < estimatedCells * 2) hashCapacity <<= 1;\n let hashMask = hashCapacity - 1;\n\n let tempHashKeys = new Int32Array(hashCapacity * 2);\n let tempHashCounts = new Int32Array(hashCapacity);\n tempHashKeys.fill(0x7fffffff);\n let cellCount = 0;\n\n const pointCellSlot = new Int32Array(validCount);\n\n for (let i = 0; i < validCount; i += 1) {\n const cx = pointCellX[i];\n const cy = pointCellY[i];\n let slot = cellHash(cx, cy, hashMask);\n\n while (true) {\n const kx = tempHashKeys[slot * 2];\n if (kx === 0x7fffffff) {\n tempHashKeys[slot * 2] = cx;\n tempHashKeys[slot * 2 + 1] = cy;\n tempHashCounts[slot] = 1;\n pointCellSlot[i] = slot;\n cellCount += 1;\n\n if (cellCount * 4 > hashCapacity * 3) {\n const oldCap = hashCapacity;\n hashCapacity <<= 1;\n hashMask = hashCapacity - 1;\n\n const newKeys = new Int32Array(hashCapacity * 2);\n const newCounts = new Int32Array(hashCapacity);\n newKeys.fill(0x7fffffff);\n\n for (let s = 0; s < oldCap; s += 1) {\n if (tempHashKeys[s * 2] === 0x7fffffff) continue;\n const ocx = tempHashKeys[s * 2];\n const ocy = tempHashKeys[s * 2 + 1];\n let ns = cellHash(ocx, ocy, hashMask);\n while (newKeys[ns * 2] !== 0x7fffffff) ns = (ns + 1) & hashMask;\n newKeys[ns * 2] = ocx;\n newKeys[ns * 2 + 1] = ocy;\n newCounts[ns] = tempHashCounts[s];\n }\n\n tempHashKeys = newKeys;\n tempHashCounts = newCounts;\n\n slot = cellHash(cx, cy, hashMask);\n while (\n tempHashKeys[slot * 2] !== cx ||\n tempHashKeys[slot * 2 + 1] !== cy\n ) {\n slot = (slot + 1) & hashMask;\n }\n pointCellSlot[i] = slot;\n }\n break;\n }\n\n if (kx === cx && tempHashKeys[slot * 2 + 1] === cy) {\n tempHashCounts[slot] += 1;\n pointCellSlot[i] = slot;\n break;\n }\n\n slot = (slot + 1) & hashMask;\n }\n }\n\n const cellKeys = new Int32Array(cellCount * 2);\n const cellOffsets = new Uint32Array(cellCount);\n const cellLengths = new Uint32Array(cellCount);\n const slotToCellIndex = new Int32Array(hashCapacity);\n slotToCellIndex.fill(HASH_EMPTY);\n\n let cellIdx = 0;\n let offset = 0;\n for (let s = 0; s < hashCapacity; s += 1) {\n if (tempHashKeys[s * 2] === 0x7fffffff) continue;\n cellKeys[cellIdx * 2] = tempHashKeys[s * 2];\n cellKeys[cellIdx * 2 + 1] = tempHashKeys[s * 2 + 1];\n cellOffsets[cellIdx] = offset;\n cellLengths[cellIdx] = tempHashCounts[s];\n slotToCellIndex[s] = cellIdx;\n offset += tempHashCounts[s];\n cellIdx += 1;\n }\n\n const pointIndices = new Uint32Array(validCount);\n const fillCursor = new Uint32Array(cellCount);\n fillCursor.set(cellOffsets);\n\n if (drawIndices) {\n for (let i = 0; i < validCount; i += 1) {\n const ci = slotToCellIndex[pointCellSlot[i]];\n pointIndices[fillCursor[ci]] = drawIndices[i];\n fillCursor[ci] += 1;\n }\n } else {\n let srcIdx = 0;\n for (let i = 0; i < safeCount; i += 1) {\n const px = input.positions[i * 2];\n const py = input.positions[i * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) continue;\n const ci = slotToCellIndex[pointCellSlot[srcIdx]];\n pointIndices[fillCursor[ci]] = i;\n fillCursor[ci] += 1;\n srcIdx += 1;\n }\n }\n\n let finalCap = 1;\n while (finalCap < cellCount * 2) finalCap <<= 1;\n const finalMask = finalCap - 1;\n const hashTable = new Int32Array(finalCap);\n hashTable.fill(HASH_EMPTY);\n\n for (let i = 0; i < cellCount; i += 1) {\n const cx = cellKeys[i * 2];\n const cy = cellKeys[i * 2 + 1];\n let slot = cellHash(cx, cy, finalMask);\n while (hashTable[slot] !== HASH_EMPTY) slot = (slot + 1) & finalMask;\n hashTable[slot] = i;\n }\n\n return {\n cellSize,\n safeCount,\n cellCount,\n hashCapacity: finalCap,\n hashTable,\n cellKeys,\n cellOffsets,\n cellLengths,\n pointIndices,\n };\n}\n","import { HASH_EMPTY, buildPointHitIndex, cellHash } from \"./point-hit-index-shared\";\nimport type {\n PointHitIndexWorkerRequest,\n PointHitIndexWorkerResponse,\n PointHitIndexWorkerSuccess,\n} from \"./point-hit-index-worker-protocol\";\nimport type { WsiImageSource, WsiPointData } from \"./types\";\nimport { sanitizePointCount } from \"./utils\";\nimport { WorkerClient } from \"./worker-client\";\n\nexport interface FlatPointSpatialIndex {\n cellSize: number;\n safeCount: number;\n positions: Float32Array;\n ids: Uint32Array | null;\n hashCapacity: number;\n hashMask: number;\n hashTable: Int32Array;\n cellKeys: Int32Array;\n cellOffsets: Uint32Array;\n cellLengths: Uint32Array;\n pointIndices: Uint32Array;\n}\n\nexport function lookupCellIndex(\n index: FlatPointSpatialIndex,\n cellX: number,\n cellY: number,\n): number {\n const { hashTable, cellKeys, hashMask } = index;\n let slot = cellHash(cellX, cellY, hashMask);\n while (true) {\n const ci = hashTable[slot];\n if (ci === HASH_EMPTY) return -1;\n if (cellKeys[ci * 2] === cellX && cellKeys[ci * 2 + 1] === cellY) return ci;\n slot = (slot + 1) & hashMask;\n }\n}\n\ninterface PendingRequest {\n resolve: (result: FlatPointSpatialIndex | null) => void;\n reject: (reason?: unknown) => void;\n pointData: WsiPointData;\n}\n\nfunction buildFromResponse(msg: PointHitIndexWorkerSuccess, pointData: WsiPointData): FlatPointSpatialIndex | null {\n if (msg.safeCount <= 0 || msg.cellCount <= 0) return null;\n\n const safeCount = msg.safeCount;\n return {\n cellSize: msg.cellSize,\n safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n ids:\n pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount\n ? pointData.ids.subarray(0, safeCount)\n : null,\n hashCapacity: msg.hashCapacity,\n hashMask: msg.hashCapacity - 1,\n hashTable: new Int32Array(msg.hashTable),\n cellKeys: new Int32Array(msg.cellKeys),\n cellOffsets: new Uint32Array(msg.cellOffsets),\n cellLengths: new Uint32Array(msg.cellLengths),\n pointIndices: new Uint32Array(msg.pointIndices),\n };\n}\n\nconst workerClient = new WorkerClient<PointHitIndexWorkerResponse, PendingRequest>(\n () =>\n new Worker(new URL(\"../workers/point-hit-index-worker.ts\", import.meta.url), {\n type: \"module\",\n }),\n {\n onResponse: (message, pending) => {\n if (message.type === \"point-hit-index-failure\") {\n pending.reject(new Error(message.error || \"worker index build failed\"));\n return;\n }\n pending.resolve(buildFromResponse(message, pending.pointData));\n },\n rejectPending: (pending, error) => {\n pending.reject(error);\n },\n },\n);\n\nexport function terminatePointHitIndexWorker(): void {\n workerClient.terminate(\"worker terminated\");\n}\n\nfunction buildSyncFallback(\n pointData: WsiPointData,\n source: WsiImageSource | null,\n): FlatPointSpatialIndex | null {\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) return null;\n\n const positions = pointData.positions.subarray(0, safeCount * 2);\n const result = buildPointHitIndex({\n count: safeCount,\n positions,\n drawIndices:\n pointData.drawIndices instanceof Uint32Array ? pointData.drawIndices : null,\n sourceWidth: source?.width ?? 0,\n sourceHeight: source?.height ?? 0,\n });\n if (!result) return null;\n\n return {\n cellSize: result.cellSize,\n safeCount,\n positions,\n ids:\n pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount\n ? pointData.ids.subarray(0, safeCount)\n : null,\n hashCapacity: result.hashCapacity,\n hashMask: result.hashCapacity - 1,\n hashTable: result.hashTable,\n cellKeys: result.cellKeys,\n cellOffsets: result.cellOffsets,\n cellLengths: result.cellLengths,\n pointIndices: result.pointIndices,\n };\n}\n\nexport async function buildPointSpatialIndexAsync(\n pointData: WsiPointData | null | undefined,\n source: WsiImageSource | null,\n): Promise<FlatPointSpatialIndex | null> {\n if (!pointData || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) return null;\n\n return new Promise<FlatPointSpatialIndex | null>((resolve, reject) => {\n const pending: PendingRequest = {\n resolve,\n reject,\n pointData,\n };\n const requestTicket = workerClient.beginRequest(pending);\n if (!requestTicket || !requestTicket.worker) {\n resolve(buildSyncFallback(pointData, source));\n return;\n }\n\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const drawIndicesCopy =\n pointData.drawIndices instanceof Uint32Array &&\n pointData.drawIndices.length > 0\n ? pointData.drawIndices.slice()\n : undefined;\n\n const msg: PointHitIndexWorkerRequest = {\n type: \"point-hit-index-request\",\n id: requestTicket.id,\n count: safeCount,\n positions: positionsCopy.buffer,\n drawIndices: drawIndicesCopy?.buffer,\n sourceWidth: source?.width ?? 0,\n sourceHeight: source?.height ?? 0,\n };\n const transfer: Transferable[] = [positionsCopy.buffer];\n if (drawIndicesCopy) transfer.push(drawIndicesCopy.buffer);\n\n try {\n requestTicket.worker.postMessage(msg, transfer);\n } catch (error) {\n const canceled = workerClient.cancelRequest(requestTicket.id);\n if (canceled) {\n canceled.reject(error);\n } else {\n reject(error);\n }\n }\n });\n}\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport { buildPointSpatialIndexAsync, type FlatPointSpatialIndex, lookupCellIndex } from \"../wsi/point-hit-index-worker-client\";\nimport type { WsiImageSource, WsiPointData } from \"../wsi/types\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate, DrawTool } from \"./draw-layer\";\nimport type { PointClickEvent, PointHitEvent, PointHoverEvent } from \"./wsi-viewer-canvas-types\";\n\nconst POINT_HIT_RADIUS_SCALE = 0.65;\nconst MIN_POINT_HIT_RADIUS_PX = 4;\n\nexport interface UsePointHitTestResult {\n getCellByCoordinates: (coordinate: DrawCoordinate) => PointHitEvent | null;\n emitPointHover: (hit: PointHitEvent | null, coordinate: DrawCoordinate | null) => void;\n emitPointClick: (coordinate: DrawCoordinate, button: number) => void;\n}\n\nexport function usePointHitTest(\n renderPointData: WsiPointData | null,\n source: WsiImageSource | null,\n onPointHover: ((event: PointHoverEvent) => void) | undefined,\n onPointClick: ((event: PointClickEvent) => void) | undefined,\n getCellByCoordinatesRef: MutableRefObject<((coordinate: DrawCoordinate) => PointHitEvent | null) | null> | undefined,\n drawTool: DrawTool,\n rendererRef: MutableRefObject<WsiTileRenderer | null>,\n pointLayerId?: string,\n): UsePointHitTestResult {\n const shouldEnablePointHitTest = Boolean(onPointHover || onPointClick || getCellByCoordinatesRef);\n const [pointSpatialIndex, setPointSpatialIndex] = useState<FlatPointSpatialIndex | null>(null);\n const hoveredPointIndexRef = useRef<number | null>(null);\n const hoveredPointIdRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (!shouldEnablePointHitTest || !renderPointData) {\n setPointSpatialIndex(null);\n return;\n }\n let cancelled = false;\n\n buildPointSpatialIndexAsync(renderPointData, source).then(nextIndex => {\n if (!cancelled) setPointSpatialIndex(nextIndex);\n });\n\n return () => {\n cancelled = true;\n };\n }, [shouldEnablePointHitTest, renderPointData, source]);\n\n const getCellByCoordinates = useCallback(\n (coordinate: DrawCoordinate): PointHitEvent | null => {\n const renderer = rendererRef.current;\n if (!renderer || !pointSpatialIndex) return null;\n\n const x = Number(coordinate[0]);\n const y = Number(coordinate[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\n const zoom = Math.max(1e-6, renderer.getViewState().zoom);\n const pointSizePx = renderer.getPointSize(pointLayerId);\n const hitRadiusPx = Math.max(MIN_POINT_HIT_RADIUS_PX, pointSizePx * POINT_HIT_RADIUS_SCALE);\n const hitRadiusWorld = hitRadiusPx / zoom;\n if (!Number.isFinite(hitRadiusWorld) || hitRadiusWorld <= 0) return null;\n\n const { cellSize, cellOffsets, cellLengths, pointIndices: idxBuf, positions: posBuf, safeCount } = pointSpatialIndex;\n const baseCellX = Math.floor(x / cellSize);\n const baseCellY = Math.floor(y / cellSize);\n const cellRadius = Math.max(1, Math.ceil(hitRadiusWorld / cellSize));\n const maxDist2 = hitRadiusWorld * hitRadiusWorld;\n\n let nearestIndex = -1;\n let nearestDist2 = maxDist2;\n let nearestX = 0;\n let nearestY = 0;\n\n for (let cx = baseCellX - cellRadius; cx <= baseCellX + cellRadius; cx += 1) {\n for (let cy = baseCellY - cellRadius; cy <= baseCellY + cellRadius; cy += 1) {\n const ci = lookupCellIndex(pointSpatialIndex, cx, cy);\n if (ci < 0) continue;\n\n const off = cellOffsets[ci];\n const end = off + cellLengths[ci];\n for (let i = off; i < end; i += 1) {\n const pointIndex = idxBuf[i];\n if (pointIndex >= safeCount) continue;\n\n const px = posBuf[pointIndex * 2];\n const py = posBuf[pointIndex * 2 + 1];\n const dx = px - x;\n const dy = py - y;\n const dist2 = dx * dx + dy * dy;\n if (dist2 > nearestDist2) continue;\n\n nearestDist2 = dist2;\n nearestIndex = pointIndex;\n nearestX = px;\n nearestY = py;\n }\n }\n }\n\n if (nearestIndex < 0) return null;\n const pointId = pointSpatialIndex.ids ? Number(pointSpatialIndex.ids[nearestIndex]) : null;\n return {\n index: nearestIndex,\n id: pointId,\n coordinate: [x, y],\n pointCoordinate: [nearestX, nearestY],\n };\n },\n [pointLayerId, pointSpatialIndex],\n );\n\n const emitPointHover = useCallback(\n (hit: PointHitEvent | null, coordinate: DrawCoordinate | null) => {\n if (!onPointHover) return;\n const nextIndex = hit?.index ?? null;\n const nextId = hit?.id ?? null;\n if (hoveredPointIndexRef.current === nextIndex && hoveredPointIdRef.current === nextId) return;\n hoveredPointIndexRef.current = nextIndex;\n hoveredPointIdRef.current = nextId;\n onPointHover({\n index: nextIndex,\n id: nextId,\n coordinate,\n pointCoordinate: hit?.pointCoordinate ?? null,\n });\n },\n [onPointHover],\n );\n\n const emitPointClick = useCallback(\n (coordinate: DrawCoordinate, button: number) => {\n if (!onPointClick) return;\n const hit = getCellByCoordinates(coordinate);\n if (!hit) return;\n onPointClick({\n ...hit,\n button,\n });\n },\n [onPointClick, getCellByCoordinates],\n );\n\n useEffect(() => {\n if (!getCellByCoordinatesRef) return;\n getCellByCoordinatesRef.current = getCellByCoordinates;\n return () => {\n if (getCellByCoordinatesRef.current === getCellByCoordinates) {\n getCellByCoordinatesRef.current = null;\n }\n };\n }, [getCellByCoordinatesRef, getCellByCoordinates]);\n\n useEffect(() => {\n const hoveredPointIndex = hoveredPointIndexRef.current;\n if (hoveredPointIndex === null) return;\n if (pointSpatialIndex && hoveredPointIndex < pointSpatialIndex.safeCount) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [pointSpatialIndex, onPointHover]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredPointIndexRef.current === null) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [drawTool, onPointHover]);\n\n return { getCellByCoordinates, emitPointHover, emitPointClick };\n}\n","import { forwardRef, useEffect, useImperativeHandle, useRef } from \"react\";\nimport type { PointClipMode } from \"../wsi/point-clip-worker-client\";\nimport type { WsiPointData, WsiRegion } from \"../wsi/types\";\nimport type { PointSizeByMagnification, PointSizeByZoom, PointWeightByMagnification } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate } from \"./draw-layer-types\";\nimport { usePointClipping } from \"./use-point-clipping\";\nimport { usePointHitTest } from \"./use-point-hit-test\";\nimport { useViewerContext } from \"./viewer-context\";\nimport type { PointClickEvent, PointClipStatsEvent, PointHitEvent, PointHoverEvent } from \"./wsi-viewer-canvas-types\";\n\nexport interface PointLayerProps {\n data?: WsiPointData | null;\n palette?: Uint8Array | null;\n sizeByZoom?: PointSizeByZoom;\n sizeByMagnification?: PointSizeByMagnification;\n weightByMagnification?: PointWeightByMagnification;\n opacity?: number;\n strokeScale?: number;\n innerFillOpacity?: number;\n innerFillColor?: string;\n clipEnabled?: boolean;\n clipToRegions?: WsiRegion[];\n clipMode?: PointClipMode;\n onClipStats?: (event: PointClipStatsEvent) => void;\n onHover?: (event: PointHoverEvent) => void;\n onClick?: (event: PointClickEvent) => void;\n dashed?: [number, number];\n}\n\nexport interface PointQueryHandle {\n queryAt: (coordinate: DrawCoordinate) => PointHitEvent | null;\n}\n\nlet nextPointLayerId = 0;\n\nexport const PointLayer = forwardRef<PointQueryHandle, PointLayerProps>(function PointLayer(\n {\n data = null,\n palette = null,\n sizeByZoom,\n sizeByMagnification,\n weightByMagnification,\n opacity,\n strokeScale,\n innerFillOpacity,\n innerFillColor,\n clipEnabled = false,\n clipToRegions,\n clipMode = \"worker\",\n onClipStats,\n onHover,\n onClick,\n dashed,\n },\n ref\n) {\n const { rendererRef, rendererSerial, source } = useViewerContext();\n const getCellByCoordinatesRef = useRef<((coordinate: DrawCoordinate) => PointHitEvent | null) | null>(null);\n const layerIdRef = useRef(`__point_layer__${nextPointLayerId++}`);\n\n const effectiveClipRegions = clipToRegions ?? EMPTY_REGIONS;\n\n const renderPointData = usePointClipping(clipEnabled, clipMode, data, effectiveClipRegions, onClipStats);\n\n const { getCellByCoordinates } = usePointHitTest(renderPointData, source, onHover, onClick, getCellByCoordinatesRef, \"cursor\", rendererRef, layerIdRef.current);\n\n useImperativeHandle(ref, () => ({ queryAt: getCellByCoordinates }), [getCellByCoordinates]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n const layerId = layerIdRef.current;\n renderer.registerPointLayer(layerId);\n return () => {\n renderer.unregisterPointLayer(layerId);\n };\n }, [rendererRef, rendererSerial]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointPalette(palette, layerIdRef.current);\n }, [rendererSerial, palette, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointLineDash(dashed, layerIdRef.current);\n }, [rendererSerial, dashed, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointSizeByZoom(sizeByZoom, layerIdRef.current);\n }, [rendererSerial, sizeByZoom, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointSizeByMagnification(sizeByMagnification, layerIdRef.current);\n }, [rendererSerial, sizeByMagnification, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointWeightByMagnification(weightByMagnification, layerIdRef.current);\n }, [rendererSerial, weightByMagnification, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || opacity === undefined) return;\n renderer.setPointOpacity(opacity, layerIdRef.current);\n }, [rendererSerial, opacity, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || strokeScale === undefined) return;\n renderer.setPointStrokeScale(strokeScale, layerIdRef.current);\n }, [rendererSerial, strokeScale, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || innerFillOpacity === undefined) return;\n renderer.setPointInnerFillOpacity(innerFillOpacity, layerIdRef.current);\n }, [rendererSerial, innerFillOpacity, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointInnerFillColor(innerFillColor, layerIdRef.current);\n }, [rendererSerial, innerFillColor, rendererRef]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointData(renderPointData, layerIdRef.current);\n }, [rendererSerial, renderPointData, rendererRef]);\n\n return null;\n});\n\nconst EMPTY_REGIONS: WsiRegion[] = [];\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport { clamp } from \"../wsi/utils\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport { resolveRegionLabelAutoLiftOffsetPx } from \"./draw-layer\";\n\nconst REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS = 180;\nconst REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX = 20;\n\nfunction smoothstep01(t: number): number {\n const x = clamp(t, 0, 1);\n return x * x * (3 - 2 * x);\n}\n\nexport interface UseRegionLabelAutoLiftResult {\n regionLabelAutoLiftOffsetPx: number;\n syncRegionLabelAutoLiftTarget: (zoom: number | null | undefined) => void;\n cancelRegionLabelAutoLiftAnimation: () => void;\n applyRegionLabelAutoLiftOffset: (next: number) => void;\n}\n\nexport function useRegionLabelAutoLift(\n autoLiftRegionLabelAtMaxZoom: boolean,\n rendererRef: MutableRefObject<WsiTileRenderer | null>,\n drawInvalidateRef: MutableRefObject<(() => void) | null>,\n): UseRegionLabelAutoLiftResult {\n const [regionLabelAutoLiftOffsetPx, setRegionLabelAutoLiftOffsetPx] = useState(0);\n const regionLabelAutoLiftOffsetRef = useRef(0);\n const regionLabelAutoLiftAnimationRef = useRef<{ rafId: number | null; startMs: number; from: number; to: number }>({\n rafId: null,\n startMs: 0,\n from: 0,\n to: 0,\n });\n\n const applyRegionLabelAutoLiftOffset = useCallback((next: number) => {\n const clamped = clamp(next, 0, REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX);\n if (Math.abs(regionLabelAutoLiftOffsetRef.current - clamped) < 1e-4) return;\n regionLabelAutoLiftOffsetRef.current = clamped;\n setRegionLabelAutoLiftOffsetPx(clamped);\n }, []);\n\n const cancelRegionLabelAutoLiftAnimation = useCallback(() => {\n const animation = regionLabelAutoLiftAnimationRef.current;\n if (animation.rafId !== null) {\n cancelAnimationFrame(animation.rafId);\n animation.rafId = null;\n }\n }, []);\n\n const animateRegionLabelAutoLiftTo = useCallback(\n (target: number) => {\n const clampedTarget = clamp(target, 0, REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX);\n const animation = regionLabelAutoLiftAnimationRef.current;\n const from = regionLabelAutoLiftOffsetRef.current;\n if (Math.abs(from - clampedTarget) < 1e-4) {\n cancelRegionLabelAutoLiftAnimation();\n animation.to = clampedTarget;\n applyRegionLabelAutoLiftOffset(clampedTarget);\n return;\n }\n\n cancelRegionLabelAutoLiftAnimation();\n animation.startMs = performance.now();\n animation.from = from;\n animation.to = clampedTarget;\n\n const step = (timestamp: number) => {\n const current = regionLabelAutoLiftAnimationRef.current;\n const elapsed = Math.max(0, timestamp - current.startMs);\n const rawT = REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS <= 0 ? 1 : clamp(elapsed / REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS, 0, 1);\n const eased = smoothstep01(rawT);\n const nextValue = current.from + (current.to - current.from) * eased;\n applyRegionLabelAutoLiftOffset(nextValue);\n drawInvalidateRef.current?.();\n\n if (rawT >= 1) {\n current.rafId = null;\n applyRegionLabelAutoLiftOffset(current.to);\n return;\n }\n current.rafId = requestAnimationFrame(step);\n };\n\n animation.rafId = requestAnimationFrame(step);\n },\n [applyRegionLabelAutoLiftOffset, cancelRegionLabelAutoLiftAnimation],\n );\n\n const syncRegionLabelAutoLiftTarget = useCallback(\n (zoom: number | null | undefined) => {\n const renderer = rendererRef.current;\n if (!renderer || typeof zoom !== \"number\" || !Number.isFinite(zoom)) {\n animateRegionLabelAutoLiftTo(0);\n return;\n }\n const target = resolveRegionLabelAutoLiftOffsetPx(autoLiftRegionLabelAtMaxZoom, zoom, renderer.getZoomRange(), renderer.getRegionLabelAutoLiftCapZoom());\n animateRegionLabelAutoLiftTo(target);\n },\n [autoLiftRegionLabelAtMaxZoom, animateRegionLabelAutoLiftTo],\n );\n\n useEffect(() => {\n return () => {\n cancelRegionLabelAutoLiftAnimation();\n };\n }, [cancelRegionLabelAutoLiftAnimation]);\n\n return {\n regionLabelAutoLiftOffsetPx,\n syncRegionLabelAutoLiftTarget,\n cancelRegionLabelAutoLiftAnimation,\n applyRegionLabelAutoLiftOffset,\n };\n}\n","import { type PreparedRoiPolygon, prepareRoiPolygons, toRoiGeometry } from \"../wsi/roi-geometry\";\nimport type { WsiRegion } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\nimport type { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport { getTopAnchorFromProjectedPolygons, measureLabelTextWidth, mergeRegionLabelStyle } from \"./draw-layer-label\";\nimport type { DrawCoordinate, RegionLabelAnchorMode, RegionLabelStyle, RegionLabelStyleResolver } from \"./draw-layer-types\";\nimport { toDrawCoordinate } from \"./draw-layer-utils\";\n\nconst REGION_CONTOUR_HIT_DISTANCE_PX = 6;\n\nexport interface PreparedRegionHit {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n polygons: PreparedRoiPolygon[];\n label: string;\n}\n\nexport function resolveRegionId(region: WsiRegion, index: number): string | number {\n return region.id ?? index;\n}\n\nfunction pointSegmentDistanceSq(px: number, py: number, ax: number, ay: number, bx: number, by: number): number {\n const abx = bx - ax;\n const aby = by - ay;\n const lengthSq = abx * abx + aby * aby;\n if (lengthSq <= 1e-12) {\n const dx = px - ax;\n const dy = py - ay;\n return dx * dx + dy * dy;\n }\n const t = clamp(((px - ax) * abx + (py - ay) * aby) / lengthSq, 0, 1);\n const nx = ax + abx * t;\n const ny = ay + aby * t;\n const dx = px - nx;\n const dy = py - ny;\n return dx * dx + dy * dy;\n}\n\nfunction isPointNearRing(x: number, y: number, ring: DrawCoordinate[], maxDistanceSq: number): boolean {\n for (let i = 1; i < ring.length; i += 1) {\n const prev = ring[i - 1];\n const next = ring[i];\n if (pointSegmentDistanceSq(x, y, prev[0], prev[1], next[0], next[1]) <= maxDistanceSq) {\n return true;\n }\n }\n return false;\n}\n\nfunction isPointNearPolygonContour(x: number, y: number, polygon: PreparedRoiPolygon, maxDistance: number): boolean {\n if (x < polygon.minX - maxDistance || x > polygon.maxX + maxDistance || y < polygon.minY - maxDistance || y > polygon.maxY + maxDistance) {\n return false;\n }\n const maxDistanceSq = maxDistance * maxDistance;\n if (isPointNearRing(x, y, polygon.outer, maxDistanceSq)) return true;\n for (const hole of polygon.holes) {\n if (isPointNearRing(x, y, hole, maxDistanceSq)) return true;\n }\n return false;\n}\n\nexport function isScreenPointInsideLabel(\n region: PreparedRegionHit,\n screenCoord: DrawCoordinate,\n renderer: WsiTileRenderer,\n regionLabelAnchor: RegionLabelAnchorMode,\n labelStyle: RegionLabelStyle,\n canvasWidth: number,\n canvasHeight: number,\n clampToViewport: boolean\n): boolean {\n if (!region.label) return false;\n\n const anchorScreen = getTopAnchorFromProjectedPolygons(\n region.polygons,\n points => {\n const projected: DrawCoordinate[] = [];\n for (let i = 0; i < points.length; i += 1) {\n const coord = toDrawCoordinate(renderer.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n projected.push(coord);\n }\n return projected;\n },\n regionLabelAnchor\n );\n if (!anchorScreen) return false;\n\n const textWidth = measureLabelTextWidth(region.label, labelStyle);\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const rawX = anchorScreen[0];\n const rawY = anchorScreen[1] - labelStyle.offsetY;\n const x = clampToViewport ? clamp(rawX, boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1) : rawX;\n const y = clampToViewport ? clamp(rawY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1) : rawY;\n const left = x - boxWidth * 0.5;\n const right = x + boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n const bottom = y + boxHeight * 0.5;\n\n return screenCoord[0] >= left && screenCoord[0] <= right && screenCoord[1] >= top && screenCoord[1] <= bottom;\n}\n\nexport function prepareRegionHits(regions: WsiRegion[]): PreparedRegionHit[] {\n const out: PreparedRegionHit[] = [];\n for (let i = 0; i < regions.length; i += 1) {\n const region = regions[i];\n const polygons = prepareRoiPolygons([toRoiGeometry(region?.coordinates)]);\n if (polygons.length === 0) continue;\n const label = typeof region?.label === \"string\" ? region.label.trim() : \"\";\n out.push({\n region,\n regionIndex: i,\n regionId: resolveRegionId(region, i),\n polygons,\n label,\n });\n }\n return out;\n}\n\nexport function pickPreparedRegionAt(\n coord: DrawCoordinate,\n screenCoord: DrawCoordinate,\n regions: PreparedRegionHit[],\n renderer: WsiTileRenderer,\n regionLabelAnchor: RegionLabelAnchorMode,\n labelStyle: RegionLabelStyle,\n labelStyleResolver: RegionLabelStyleResolver | undefined,\n labelAutoLiftOffsetPx: number,\n canvasWidth: number,\n canvasHeight: number,\n clampRegionLabelToViewport = true\n): {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n} | null {\n const x = coord[0];\n const y = coord[1];\n const zoom = Math.max(1e-6, renderer.getViewState().zoom);\n const labelAutoLiftOffset = Math.max(0, labelAutoLiftOffsetPx);\n const contourHitDistance = REGION_CONTOUR_HIT_DISTANCE_PX / zoom;\n for (let i = regions.length - 1; i >= 0; i -= 1) {\n const region = regions[i];\n for (const polygon of region.polygons) {\n if (!isPointNearPolygonContour(x, y, polygon, contourHitDistance)) continue;\n return {\n region: region.region,\n regionIndex: region.regionIndex,\n regionId: region.regionId,\n };\n }\n let dynamicLabelStyle = mergeRegionLabelStyle(\n labelStyle,\n labelStyleResolver?.({\n region: region.region,\n regionId: region.regionId,\n regionIndex: region.regionIndex,\n zoom,\n })\n );\n if (labelAutoLiftOffset > 0) {\n dynamicLabelStyle = {\n ...dynamicLabelStyle,\n offsetY: dynamicLabelStyle.offsetY + labelAutoLiftOffset,\n };\n }\n if (!isScreenPointInsideLabel(region, screenCoord, renderer, regionLabelAnchor, dynamicLabelStyle, canvasWidth, canvasHeight, clampRegionLabelToViewport)) continue;\n return {\n region: region.region,\n regionIndex: region.regionIndex,\n regionId: region.regionId,\n };\n }\n return null;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { WsiRegion } from \"../wsi/types\";\nimport { drawRegionLabel, getTopAnchorFromProjectedPolygons, mergeRegionLabelStyle, resolveRegionLabelAutoLiftOffsetPx, resolveRegionLabelStyle } from \"./draw-layer-label\";\nimport type {\n DrawCoordinate,\n DrawRegionCoordinates,\n PreparedRenderedRegion,\n RegionLabelAnchorMode,\n RegionLabelStyle,\n RegionLabelStyleResolver,\n RegionStrokeStyle,\n RegionStrokeStyleResolver,\n} from \"./draw-layer-types\";\nimport { EMPTY_DASH, REGION_INTERACTION_SHADOW_COLOR, REGION_INTERACTION_SHADOW_WIDTH } from \"./draw-layer-types\";\nimport { drawPath, isSameRegionId, mergeStrokeStyle, normalizeDrawRegionPolygons, resolveStrokeStyle, toCoord } from \"./draw-layer-utils\";\nimport { useRegionLabelAutoLift } from \"./use-region-label-auto-lift\";\nimport { useViewerContext } from \"./viewer-context\";\nimport { pickPreparedRegionAt, prepareRegionHits, resolveRegionId } from \"./wsi-region-hit-utils\";\nimport type { RegionClickEvent, RegionHoverEvent } from \"./wsi-viewer-canvas-types\";\n\nexport interface RegionLayerProps {\n regions?: WsiRegion[];\n polygons?: DrawRegionCoordinates[];\n strokeStyle?: Partial<RegionStrokeStyle>;\n hoverStrokeStyle?: Partial<RegionStrokeStyle>;\n activeStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveStrokeStyle?: RegionStrokeStyleResolver;\n labelStyle?: Partial<RegionLabelStyle> | RegionLabelStyleResolver;\n labelAnchor?: RegionLabelAnchorMode;\n autoLiftLabelAtMaxZoom?: boolean;\n clampLabelToViewport?: boolean;\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n interactive?: boolean;\n onActiveChange?: (regionId: string | number | null) => void;\n onHover?: (event: RegionHoverEvent) => void;\n onClick?: (event: RegionClickEvent) => void;\n}\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawRegionCoordinates[] = [];\nlet nextRegionLayerInstanceId = 0;\n\nfunction resolveRegionInteractionShadow(strokeStyle: RegionStrokeStyle): RegionStrokeStyle {\n return {\n color: REGION_INTERACTION_SHADOW_COLOR,\n width: REGION_INTERACTION_SHADOW_WIDTH,\n lineDash: EMPTY_DASH,\n lineJoin: strokeStyle.lineJoin,\n lineCap: strokeStyle.lineCap,\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n };\n}\n\nexport function RegionLayer({\n regions,\n polygons,\n strokeStyle: strokeStyleProp,\n hoverStrokeStyle: hoverStrokeStyleProp,\n activeStrokeStyle: activeStrokeStyleProp,\n resolveStrokeStyle: resolveStrokeStyleProp,\n labelStyle: labelStyleProp,\n labelAnchor = \"top-center\",\n autoLiftLabelAtMaxZoom = false,\n clampLabelToViewport = true,\n hoveredRegionId: controlledHoveredRegionId,\n activeRegionId: controlledActiveRegionId,\n interactive = true,\n onActiveChange,\n onHover,\n onClick,\n}: RegionLayerProps): React.ReactElement | null {\n const { rendererRef, rendererSerial, canvasRef, containerRef, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw, drawInvalidateRef, registerViewStateListener, screenToWorld, worldToScreen, isInteractionLocked } = useViewerContext();\n\n const safeRegions = regions ?? EMPTY_ROI_REGIONS;\n const safePolygons = polygons ?? EMPTY_ROI_POLYGONS;\n\n const effectiveRegions = useMemo<WsiRegion[]>(() => {\n if (safeRegions.length > 0) return safeRegions;\n if (safePolygons.length === 0) return EMPTY_ROI_REGIONS;\n return safePolygons.map((coordinates, index) => ({ id: index, coordinates }));\n }, [safeRegions, safePolygons]);\n\n const [uncontrolledHoveredRegionId, setUncontrolledHoveredRegionId] = useState<string | number | null>(() => controlledHoveredRegionId ?? null);\n const [uncontrolledActiveRegionId, setUncontrolledActiveRegionId] = useState<string | number | null>(() => controlledActiveRegionId ?? null);\n const isHoverControlled = controlledHoveredRegionId !== undefined;\n const isControlled = controlledActiveRegionId !== undefined;\n const hoveredRegionId = isHoverControlled ? (controlledHoveredRegionId ?? null) : uncontrolledHoveredRegionId;\n const activeRegionId = isControlled ? (controlledActiveRegionId ?? null) : uncontrolledActiveRegionId;\n const hoveredRegionIdRef = useRef<string | number | null>(controlledHoveredRegionId ?? null);\n const drawCallbackIdRef = useRef<string | null>(null);\n const labelDrawCallbackIdRef = useRef<string | null>(null);\n\n if (drawCallbackIdRef.current === null || labelDrawCallbackIdRef.current === null) {\n const instanceId = nextRegionLayerInstanceId++;\n drawCallbackIdRef.current = `__region_layer__${instanceId}`;\n labelDrawCallbackIdRef.current = `__region_label__${instanceId}`;\n }\n\n useEffect(() => {\n if (!isControlled) return;\n setUncontrolledActiveRegionId(controlledActiveRegionId ?? null);\n }, [isControlled, controlledActiveRegionId]);\n\n useEffect(() => {\n if (!isHoverControlled) return;\n const next = controlledHoveredRegionId ?? null;\n hoveredRegionIdRef.current = next;\n setUncontrolledHoveredRegionId(next);\n }, [isHoverControlled, controlledHoveredRegionId]);\n\n const commitActive = useCallback(\n (next: string | number | null) => {\n if (String(activeRegionId) === String(next)) return;\n if (!isControlled) setUncontrolledActiveRegionId(next);\n onActiveChange?.(next);\n },\n [activeRegionId, isControlled, onActiveChange]\n );\n\n const { regionLabelAutoLiftOffsetPx, syncRegionLabelAutoLiftTarget } = useRegionLabelAutoLift(autoLiftLabelAtMaxZoom, rendererRef, drawInvalidateRef);\n\n const resolvedStrokeStyle = useMemo(() => resolveStrokeStyle(strokeStyleProp), [strokeStyleProp]);\n const resolvedHoverStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, hoverStrokeStyleProp), [resolvedStrokeStyle, hoverStrokeStyleProp]);\n const resolvedActiveStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, activeStrokeStyleProp), [resolvedStrokeStyle, activeStrokeStyleProp]);\n\n const { staticLabelStyle, labelStyleResolver } = useMemo(() => {\n if (typeof labelStyleProp === \"function\") {\n return { staticLabelStyle: undefined, labelStyleResolver: labelStyleProp };\n }\n return { staticLabelStyle: labelStyleProp, labelStyleResolver: undefined };\n }, [labelStyleProp]);\n\n const resolvedLabelStyle = useMemo(() => resolveRegionLabelStyle(staticLabelStyle), [staticLabelStyle]);\n\n const preparedRegions = useMemo<PreparedRenderedRegion[]>(() => {\n const out: PreparedRenderedRegion[] = [];\n for (let i = 0; i < effectiveRegions.length; i += 1) {\n const region = effectiveRegions[i];\n const polys = normalizeDrawRegionPolygons(region.coordinates);\n if (polys.length === 0) continue;\n out.push({ region, regionIndex: i, regionKey: region.id ?? i, polygons: polys });\n }\n return out;\n }, [effectiveRegions]);\n\n const preparedRegionHits = useMemo(() => prepareRegionHits(effectiveRegions), [effectiveRegions]);\n\n // sync label auto-lift target when zoom changes (rendererSerial: new renderer instance)\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n syncRegionLabelAutoLiftTarget(renderer.getViewState().zoom);\n return registerViewStateListener(next => {\n syncRegionLabelAutoLiftTarget(next.zoom);\n });\n }, [rendererSerial, registerViewStateListener, syncRegionLabelAutoLiftTarget]);\n\n // clean up stale hover/active on regions change\n useEffect(() => {\n const hasActive = activeRegionId === null ? true : effectiveRegions.some((r, i) => String(resolveRegionId(r, i)) === String(activeRegionId));\n if (!hasActive && activeRegionId !== null) commitActive(null);\n\n const currentHover = hoveredRegionIdRef.current;\n const hasHover = currentHover === null ? true : effectiveRegions.some((r, i) => String(resolveRegionId(r, i)) === String(currentHover));\n if (!hasHover && currentHover !== null) {\n hoveredRegionIdRef.current = null;\n if (!isHoverControlled) setUncontrolledHoveredRegionId(null);\n onHover?.({ region: null, regionId: null, regionIndex: -1, coordinate: null });\n }\n }, [effectiveRegions, activeRegionId, isHoverControlled, onHover, commitActive]);\n\n // worldToScreenPoints helper\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = rendererRef.current;\n if (!projector || points.length === 0) return [];\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n []\n );\n\n // --- register region polygon draw callback ---\n\n const regionDrawRef = useRef({\n preparedRegions,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n resolveStrokeStyleProp,\n worldToScreenPoints,\n });\n regionDrawRef.current = {\n preparedRegions,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n resolveStrokeStyleProp,\n worldToScreenPoints,\n };\n\n useEffect(() => {\n const drawRegions = (_ctx: CanvasRenderingContext2D) => {\n const {\n preparedRegions: prep,\n hoveredRegionId: hovered,\n activeRegionId: active,\n resolvedStrokeStyle: base,\n resolvedHoverStrokeStyle: hover,\n resolvedActiveStrokeStyle: activeS,\n resolveStrokeStyleProp: resolver,\n worldToScreenPoints: w2s,\n } = regionDrawRef.current;\n\n for (const entry of prep) {\n const { region, polygons: polys, regionIndex, regionKey } = entry;\n const state: \"default\" | \"hover\" | \"active\" = isSameRegionId(active, regionKey) ? \"active\" : isSameRegionId(hovered, regionKey) ? \"hover\" : \"default\";\n let style = state === \"active\" ? activeS : state === \"hover\" ? hover : base;\n\n if (resolver) {\n const resolved = resolver({ region, regionId: regionKey, regionIndex, state });\n style = mergeStrokeStyle(style, resolved || undefined);\n }\n const shadow = state === \"default\" ? null : resolveRegionInteractionShadow(style);\n\n for (const polygon of polys) {\n const screenOuter = w2s(polygon.outer);\n if (screenOuter.length >= 4) {\n if (shadow) drawPath(_ctx, screenOuter, shadow, true, false);\n drawPath(_ctx, screenOuter, style, true, false);\n }\n for (const hole of polygon.holes) {\n const screenHole = w2s(hole);\n if (screenHole.length >= 4) {\n if (shadow) drawPath(_ctx, screenHole, shadow, true, false);\n drawPath(_ctx, screenHole, style, true, false);\n }\n }\n }\n }\n };\n\n const drawId = drawCallbackIdRef.current;\n if (!drawId) return;\n registerDrawCallback(drawId, 10, drawRegions);\n return () => unregisterDrawCallback(drawId);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n // --- register region label draw callback ---\n\n const labelDrawRef = useRef({\n preparedRegions,\n resolvedLabelStyle,\n labelStyleResolver,\n labelAnchor,\n autoLiftLabelAtMaxZoom,\n clampLabelToViewport,\n regionLabelAutoLiftOffsetPx,\n rendererRef,\n });\n labelDrawRef.current = {\n preparedRegions,\n resolvedLabelStyle,\n labelStyleResolver,\n labelAnchor,\n autoLiftLabelAtMaxZoom,\n clampLabelToViewport,\n regionLabelAutoLiftOffsetPx,\n rendererRef,\n };\n\n useEffect(() => {\n const drawLabels = (ctx: CanvasRenderingContext2D, canvasWidth: number, canvasHeight: number) => {\n const {\n preparedRegions: prep,\n resolvedLabelStyle: labelS,\n labelStyleResolver: resolver,\n labelAnchor: anchor,\n autoLiftLabelAtMaxZoom: autoLift,\n clampLabelToViewport: clampVp,\n regionLabelAutoLiftOffsetPx: autoLiftPx,\n rendererRef: rRef,\n } = labelDrawRef.current;\n\n if (prep.length === 0) return;\n\n const zoom = Math.max(1e-6, rRef.current?.getViewState?.().zoom ?? 1);\n const labelAutoLiftOffset =\n typeof autoLiftPx === \"number\" && Number.isFinite(autoLiftPx)\n ? Math.max(0, autoLiftPx)\n : resolveRegionLabelAutoLiftOffsetPx(autoLift, zoom, rRef.current?.getZoomRange?.(), rRef.current?.getRegionLabelAutoLiftCapZoom?.());\n\n for (const entry of prep) {\n if (!entry.region.label) continue;\n const anchorScreen = getTopAnchorFromProjectedPolygons(\n entry.polygons,\n points => {\n const projector = rRef.current;\n if (!projector) return [];\n const out: DrawCoordinate[] = [];\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out.push(coord);\n }\n return out;\n },\n anchor\n );\n if (!anchorScreen) continue;\n\n let style = mergeRegionLabelStyle(labelS, resolver?.({ region: entry.region, regionId: entry.regionKey, regionIndex: entry.regionIndex, zoom }));\n if (labelAutoLiftOffset > 0) {\n style = { ...style, offsetY: style.offsetY + labelAutoLiftOffset };\n }\n drawRegionLabel(ctx, entry.region.label, anchorScreen, canvasWidth, canvasHeight, style, clampVp);\n }\n };\n\n const drawId = labelDrawCallbackIdRef.current;\n if (!drawId) return;\n registerDrawCallback(drawId, 50, drawLabels);\n return () => unregisterDrawCallback(drawId);\n }, [registerDrawCallback, unregisterDrawCallback]);\n\n // redraw when deps change\n useEffect(() => {\n requestOverlayRedraw();\n }, [preparedRegions, hoveredRegionId, activeRegionId, resolvedStrokeStyle, resolvedLabelStyle, regionLabelAutoLiftOffsetPx, requestOverlayRedraw]);\n\n // --- pointer event handling for hover / click ---\n\n const pointerHitRef = useRef({\n preparedRegionHits,\n labelAnchor,\n resolvedLabelStyle,\n labelStyleResolver,\n regionLabelAutoLiftOffsetPx,\n clampLabelToViewport,\n onHover,\n onClick,\n commitActive,\n });\n pointerHitRef.current = {\n preparedRegionHits,\n labelAnchor,\n resolvedLabelStyle,\n labelStyleResolver,\n regionLabelAutoLiftOffsetPx,\n clampLabelToViewport,\n onHover,\n onClick,\n commitActive,\n };\n\n useEffect(() => {\n if (!interactive) return;\n const container = containerRef.current;\n if (!container) return;\n\n const handlePointerMove = (e: PointerEvent) => {\n if (isInteractionLocked()) return;\n const renderer = rendererRef.current;\n if (!renderer) return;\n\n const { preparedRegionHits: hits, labelAnchor: currentLabelAnchor, resolvedLabelStyle: labelS, labelStyleResolver: resolver,\n regionLabelAutoLiftOffsetPx: autoLiftPx, clampLabelToViewport: clampVp, onHover: hoverCb } = pointerHitRef.current;\n\n const worldCoord = screenToWorld(e.clientX, e.clientY);\n if (!worldCoord) return;\n\n let nextId: string | number | null = null;\n let hitResult: { region: WsiRegion; regionIndex: number; regionId: string | number } | null = null;\n\n if (hits.length > 0) {\n const screenCoord = worldToScreen(worldCoord[0], worldCoord[1]);\n if (screenCoord) {\n const rect = canvasRef.current?.getBoundingClientRect();\n hitResult = pickPreparedRegionAt(\n worldCoord, screenCoord, hits, renderer, currentLabelAnchor, labelS, resolver,\n typeof autoLiftPx === \"number\" ? autoLiftPx : 0,\n rect?.width ?? 0, rect?.height ?? 0, clampVp,\n );\n nextId = hitResult?.regionId ?? null;\n }\n }\n\n const prevId = hoveredRegionIdRef.current;\n if (String(prevId) === String(nextId)) return;\n\n hoveredRegionIdRef.current = nextId;\n if (!isHoverControlled) setUncontrolledHoveredRegionId(nextId);\n hoverCb?.({\n region: hitResult?.region ?? null,\n regionId: nextId,\n regionIndex: hitResult?.regionIndex ?? -1,\n coordinate: worldCoord,\n });\n requestOverlayRedraw();\n };\n\n const handleClick = (e: MouseEvent) => {\n if (isInteractionLocked()) return;\n const renderer = rendererRef.current;\n if (!renderer) return;\n\n const { preparedRegionHits: hits, labelAnchor: currentLabelAnchor, resolvedLabelStyle: labelS, labelStyleResolver: resolver,\n regionLabelAutoLiftOffsetPx: autoLiftPx, clampLabelToViewport: clampVp,\n onClick: clickCb, commitActive: commit } = pointerHitRef.current;\n\n if (hits.length === 0) return;\n\n const worldCoord = screenToWorld(e.clientX, e.clientY);\n if (!worldCoord) return;\n\n const screenCoord = worldToScreen(worldCoord[0], worldCoord[1]);\n if (!screenCoord) return;\n\n const rect = canvasRef.current?.getBoundingClientRect();\n const hitResult = pickPreparedRegionAt(\n worldCoord, screenCoord, hits, renderer, currentLabelAnchor, labelS, resolver,\n typeof autoLiftPx === \"number\" ? autoLiftPx : 0,\n rect?.width ?? 0, rect?.height ?? 0, clampVp,\n );\n\n const nextId = hitResult?.regionId ?? null;\n commit(nextId);\n\n if (hitResult && clickCb) {\n clickCb({\n region: hitResult.region,\n regionId: hitResult.regionId,\n regionIndex: hitResult.regionIndex,\n coordinate: worldCoord,\n });\n }\n };\n\n const handlePointerLeave = () => {\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n if (!isHoverControlled) setUncontrolledHoveredRegionId(null);\n pointerHitRef.current.onHover?.({ region: null, regionId: null, regionIndex: -1, coordinate: null });\n requestOverlayRedraw();\n };\n\n container.addEventListener(\"pointermove\", handlePointerMove);\n container.addEventListener(\"click\", handleClick);\n container.addEventListener(\"pointerleave\", handlePointerLeave);\n return () => {\n container.removeEventListener(\"pointermove\", handlePointerMove);\n container.removeEventListener(\"click\", handleClick);\n container.removeEventListener(\"pointerleave\", handlePointerLeave);\n };\n }, [containerRef, rendererRef, canvasRef, interactive, isHoverControlled, screenToWorld, worldToScreen, isInteractionLocked, requestOverlayRedraw]);\n\n return null;\n}\n","import { type CSSProperties, useEffect, useMemo, useRef } from \"react\";\nimport { M1TileRenderer } from \"../core/m1-tile-renderer\";\nimport type { ViewState } from \"../core/ortho-camera\";\nimport type { TileDefinition } from \"../core/types\";\n\nexport interface TileViewerCanvasProps {\n\timageWidth: number;\n\timageHeight: number;\n\ttiles: TileDefinition[];\n\tviewState?: Partial<ViewState>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nexport function TileViewerCanvas({\n\timageWidth,\n\timageHeight,\n\ttiles,\n\tviewState,\n\tclassName,\n\tstyle,\n}: TileViewerCanvasProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst rendererRef = useRef<M1TileRenderer | null>(null);\n\tconst mergedStyle = useMemo(\n\t\t() => ({ width: \"100%\", height: \"100%\", display: \"block\", ...style }),\n\t\t[style],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst renderer = new M1TileRenderer({\n\t\t\tcanvas,\n\t\t\timageWidth,\n\t\t\timageHeight,\n\t\t\tinitialViewState: viewState,\n\t\t});\n\n\t\trendererRef.current = renderer;\n\t\tvoid renderer.setTiles(tiles);\n\n\t\treturn () => {\n\t\t\trenderer.destroy();\n\t\t\trendererRef.current = null;\n\t\t};\n\t}, [imageWidth, imageHeight]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid renderer.setTiles(tiles);\n\t}, [tiles]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !viewState) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderer.setViewState(viewState);\n\t}, [viewState]);\n\n\treturn <canvas ref={canvasRef} className={className} style={mergedStyle} />;\n}\n","import { nowMs } from \"./utils\";\n\nexport type TileBounds = [number, number, number, number];\n\nexport interface ScheduledTile {\n\tkey: string;\n\ttier: number;\n\tx: number;\n\ty: number;\n\tbounds: TileBounds;\n\tdistance2: number;\n\turl: string;\n}\n\nexport interface TileSchedulerSnapshot {\n\tinflight: number;\n\tqueued: number;\n\taborted: number;\n\tretries: number;\n\tfailed: number;\n}\n\nexport interface TileSchedulerOptions {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n\tauthToken?: string;\n\tonTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tonTileError?: (\n\t\ttile: ScheduledTile,\n\t\terror: unknown,\n\t\tattemptCount: number,\n\t) => void;\n\tonStateChange?: (snapshot: TileSchedulerSnapshot) => void;\n}\n\ninterface QueueItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\treadyAt: number;\n}\n\ninterface InflightItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\tcontroller: AbortController;\n}\n\nfunction shouldAttachAuthHeader(url: string, authToken: string): boolean {\n\tif (!authToken) return false;\n\ttry {\n\t\tconst parsed = new URL(url, typeof window !== \"undefined\" ? window.location.href : undefined);\n\t\tconst host = parsed.hostname.toLowerCase();\n\t\tconst isAwsS3 =\n\t\t\thost.includes(\"amazonaws.com\") || host.startsWith(\"s3.\") || host.includes(\".s3.\");\n\t\tif (isAwsS3) return false;\n\t} catch {\n\t\t// Fallback to attaching auth if URL parsing fails.\n\t}\n\treturn true;\n}\n\nexport class TileScheduler {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly maxRetries: number;\n\tprivate readonly retryBaseDelayMs: number;\n\tprivate readonly retryMaxDelayMs: number;\n\tprivate readonly onTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tprivate readonly onTileError?:\n\t\t| ((tile: ScheduledTile, error: unknown, attemptCount: number) => void)\n\t\t| undefined;\n\tprivate readonly onStateChange?:\n\t\t| ((snapshot: TileSchedulerSnapshot) => void)\n\t\t| undefined;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate queue: QueueItem[] = [];\n\tprivate queuedByKey = new Map<string, QueueItem>();\n\tprivate inflight = new Map<string, InflightItem>();\n\tprivate visibleKeys = new Set<string>();\n\tprivate timerId: number | null = null;\n\tprivate abortedCount = 0;\n\tprivate retryCount = 0;\n\tprivate failedCount = 0;\n\n\tconstructor(options: TileSchedulerOptions) {\n\t\tthis.maxConcurrency = Math.max(1, Math.floor(options.maxConcurrency ?? 12));\n\t\tthis.maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 2));\n\t\tthis.retryBaseDelayMs = Math.max(\n\t\t\t10,\n\t\t\tMath.floor(options.retryBaseDelayMs ?? 120),\n\t\t);\n\t\tthis.retryMaxDelayMs = Math.max(\n\t\t\tthis.retryBaseDelayMs,\n\t\t\tMath.floor(options.retryMaxDelayMs ?? 1200),\n\t\t);\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.onTileLoad = options.onTileLoad;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onStateChange = options.onStateChange;\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t}\n\n\tschedule(tiles: readonly ScheduledTile[]): void {\n\t\tif (this.destroyed) return;\n\n\t\tconst nextVisibleKeys = new Set<string>();\n\t\tfor (const tile of tiles) {\n\t\t\tnextVisibleKeys.add(tile.key);\n\t\t}\n\t\tthis.visibleKeys = nextVisibleKeys;\n\n\t\tthis.dropInvisibleQueued(nextVisibleKeys);\n\t\tthis.abortInvisibleInflight(nextVisibleKeys);\n\n\t\tfor (const tile of tiles) {\n\t\t\tif (this.inflight.has(tile.key)) {\n\t\t\t\tconst inflight = this.inflight.get(tile.key);\n\t\t\t\tif (inflight) inflight.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst queued = this.queuedByKey.get(tile.key);\n\t\t\tif (queued) {\n\t\t\t\tqueued.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst item: QueueItem = {\n\t\t\t\ttile,\n\t\t\t\tattempt: 0,\n\t\t\t\treadyAt: nowMs(),\n\t\t\t};\n\t\t\tthis.queue.push(item);\n\t\t\tthis.queuedByKey.set(tile.key, item);\n\t\t}\n\n\t\tthis.sortQueue();\n\t\tthis.pump();\n\t\tthis.emitStateChange();\n\t}\n\n\tclear(): void {\n\t\tthis.clearPumpTimer();\n\t\tthis.visibleKeys.clear();\n\t\tthis.queue = [];\n\t\tthis.queuedByKey.clear();\n\n\t\tfor (const [, item] of this.inflight) {\n\t\t\titem.controller.abort();\n\t\t}\n\t\tthis.inflight.clear();\n\t\tthis.emitStateChange();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.clear();\n\t}\n\n\tgetInflightCount(): number {\n\t\treturn this.inflight.size;\n\t}\n\n\tgetSnapshot(): TileSchedulerSnapshot {\n\t\treturn {\n\t\t\tinflight: this.inflight.size,\n\t\t\tqueued: this.queue.length,\n\t\t\taborted: this.abortedCount,\n\t\t\tretries: this.retryCount,\n\t\t\tfailed: this.failedCount,\n\t\t};\n\t}\n\n\tprivate dropInvisibleQueued(visibleKeys: Set<string>): void {\n\t\tif (this.queue.length === 0) return;\n\t\tconst nextQueue: QueueItem[] = [];\n\t\tfor (const item of this.queue) {\n\t\t\tif (!visibleKeys.has(item.tile.key)) {\n\t\t\t\tthis.queuedByKey.delete(item.tile.key);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnextQueue.push(item);\n\t\t}\n\t\tthis.queue = nextQueue;\n\t}\n\n\tprivate abortInvisibleInflight(visibleKeys: Set<string>): void {\n\t\tfor (const [key, item] of this.inflight) {\n\t\t\tif (visibleKeys.has(key)) continue;\n\t\t\tthis.inflight.delete(key);\n\t\t\tthis.abortedCount += 1;\n\t\t\titem.controller.abort();\n\t\t}\n\t}\n\n\tprivate sortQueue(): void {\n\t\tthis.queue.sort((a, b) => {\n\t\t\tif (a.readyAt !== b.readyAt) return a.readyAt - b.readyAt;\n\t\t\tif (a.tile.distance2 !== b.tile.distance2) {\n\t\t\t\treturn a.tile.distance2 - b.tile.distance2;\n\t\t\t}\n\t\t\tif (a.tile.tier !== b.tile.tier) return b.tile.tier - a.tile.tier;\n\t\t\treturn a.tile.key.localeCompare(b.tile.key);\n\t\t});\n\t}\n\n\tprivate pump(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.clearPumpTimer();\n\n\t\twhile (this.inflight.size < this.maxConcurrency) {\n\t\t\tconst next = this.takeNextReadyQueueItem();\n\t\t\tif (!next) break;\n\t\t\tthis.startFetch(next);\n\t\t}\n\n\t\tif (this.inflight.size >= this.maxConcurrency) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.queue.length === 0) return;\n\n\t\tconst earliestReadyAt = this.queue[0]?.readyAt;\n\t\tif (typeof earliestReadyAt !== \"number\") return;\n\t\tconst delay = Math.max(0, earliestReadyAt - nowMs());\n\t\tthis.timerId = globalThis.setTimeout(() => {\n\t\t\tthis.timerId = null;\n\t\t\tthis.pump();\n\t\t}, delay);\n\t}\n\n\tprivate takeNextReadyQueueItem(): QueueItem | null {\n\t\tif (this.queue.length === 0) return null;\n\t\tconst now = nowMs();\n\t\tconst first = this.queue[0];\n\t\tif (!first || first.readyAt > now) return null;\n\n\t\tthis.queue.shift();\n\t\tthis.queuedByKey.delete(first.tile.key);\n\t\treturn first;\n\t}\n\n\tprivate startFetch(item: QueueItem): void {\n\t\tconst controller = new AbortController();\n\t\tconst inflightEntry: InflightItem = {\n\t\t\ttile: item.tile,\n\t\t\tattempt: item.attempt,\n\t\t\tcontroller,\n\t\t};\n\t\tthis.inflight.set(item.tile.key, inflightEntry);\n\t\tthis.emitStateChange();\n\n\t\tconst useAuthHeader = shouldAttachAuthHeader(item.tile.url, this.authToken);\n\t\tfetch(item.tile.url, {\n\t\t\tsignal: controller.signal,\n\t\t\theaders: useAuthHeader ? { Authorization: this.authToken } : undefined,\n\t\t})\n\t\t\t.then((response) => {\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\treturn response.blob();\n\t\t\t})\n\t\t\t.then((blob) => createImageBitmap(blob))\n\t\t\t.then((bitmap) => {\n\t\t\t\tif (this.destroyed || controller.signal.aborted) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!this.visibleKeys.has(item.tile.key)) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.onTileLoad(item.tile, bitmap);\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (controller.signal.aborted || this.destroyed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst shouldRetry =\n\t\t\t\t\titem.attempt < this.maxRetries && this.visibleKeys.has(item.tile.key);\n\t\t\t\tif (shouldRetry) {\n\t\t\t\t\tthis.retryCount += 1;\n\t\t\t\t\tconst nextAttempt = item.attempt + 1;\n\t\t\t\t\tconst retryDelay = this.getRetryDelay(nextAttempt);\n\t\t\t\t\tconst queued: QueueItem = {\n\t\t\t\t\t\ttile: item.tile,\n\t\t\t\t\t\tattempt: nextAttempt,\n\t\t\t\t\t\treadyAt: nowMs() + retryDelay,\n\t\t\t\t\t};\n\t\t\t\t\tconst existing = this.queuedByKey.get(item.tile.key);\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.tile = queued.tile;\n\t\t\t\t\t\texisting.readyAt = Math.min(existing.readyAt, queued.readyAt);\n\t\t\t\t\t\texisting.attempt = Math.max(existing.attempt, queued.attempt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.queue.push(queued);\n\t\t\t\t\t\tthis.queuedByKey.set(queued.tile.key, queued);\n\t\t\t\t\t}\n\t\t\t\t\tthis.sortQueue();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.failedCount += 1;\n\t\t\t\tthis.onTileError?.(item.tile, error, item.attempt + 1);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tthis.inflight.delete(item.tile.key);\n\t\t\t\tthis.pump();\n\t\t\t\tthis.emitStateChange();\n\t\t\t});\n\t}\n\n\tprivate getRetryDelay(attempt: number): number {\n\t\tconst exp = Math.max(0, attempt - 1);\n\t\tconst delay = Math.min(\n\t\t\tthis.retryMaxDelayMs,\n\t\t\tthis.retryBaseDelayMs * 2 ** exp,\n\t\t);\n\t\tconst jitter = 0.85 + Math.random() * 0.3;\n\t\treturn Math.round(delay * jitter);\n\t}\n\n\tprivate clearPumpTimer(): void {\n\t\tif (this.timerId === null) return;\n\t\tglobalThis.clearTimeout(this.timerId);\n\t\tthis.timerId = null;\n\t}\n\n\tprivate emitStateChange(): void {\n\t\tthis.onStateChange?.(this.getSnapshot());\n\t}\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\n\nexport interface RendererCanvasHandlers {\n pointerDown: (event: PointerEvent) => void;\n pointerMove: (event: PointerEvent) => void;\n pointerUp: (event: PointerEvent) => void;\n wheel: (event: WheelEvent) => void;\n doubleClick: (event: MouseEvent) => void;\n contextMenu: (event: MouseEvent) => void;\n contextLost: (event: Event) => void;\n contextRestored: (event: Event) => void;\n}\n\nexport function addRendererCanvasEventListeners(canvas: HTMLCanvasElement, handlers: RendererCanvasHandlers): void {\n canvas.addEventListener(\"pointerdown\", handlers.pointerDown);\n canvas.addEventListener(\"pointermove\", handlers.pointerMove);\n canvas.addEventListener(\"pointerup\", handlers.pointerUp);\n canvas.addEventListener(\"pointercancel\", handlers.pointerUp);\n canvas.addEventListener(\"wheel\", handlers.wheel, { passive: false });\n canvas.addEventListener(\"dblclick\", handlers.doubleClick);\n canvas.addEventListener(\"contextmenu\", handlers.contextMenu);\n canvas.addEventListener(\"webglcontextlost\", handlers.contextLost);\n canvas.addEventListener(\"webglcontextrestored\", handlers.contextRestored);\n}\n\nexport function removeRendererCanvasEventListeners(canvas: HTMLCanvasElement, handlers: RendererCanvasHandlers): void {\n canvas.removeEventListener(\"pointerdown\", handlers.pointerDown);\n canvas.removeEventListener(\"pointermove\", handlers.pointerMove);\n canvas.removeEventListener(\"pointerup\", handlers.pointerUp);\n canvas.removeEventListener(\"pointercancel\", handlers.pointerUp);\n canvas.removeEventListener(\"wheel\", handlers.wheel);\n canvas.removeEventListener(\"dblclick\", handlers.doubleClick);\n canvas.removeEventListener(\"contextmenu\", handlers.contextMenu);\n canvas.removeEventListener(\"webglcontextlost\", handlers.contextLost);\n canvas.removeEventListener(\"webglcontextrestored\", handlers.contextRestored);\n}\n\nexport function resizeCanvasViewport(canvas: HTMLCanvasElement, gl: WebGL2RenderingContext, camera: OrthoCamera): void {\n const rect = canvas.getBoundingClientRect();\n const cssW = Math.max(1, rect.width || canvas.clientWidth || 1);\n const cssH = Math.max(1, rect.height || canvas.clientHeight || 1);\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n\n const pixelW = Math.max(1, Math.round(cssW * dpr));\n const pixelH = Math.max(1, Math.round(cssH * dpr));\n\n if (canvas.width !== pixelW || canvas.height !== pixelH) {\n canvas.width = pixelW;\n canvas.height = pixelH;\n }\n\n camera.setViewport(cssW, cssH);\n gl.viewport(0, 0, pixelW, pixelH);\n}\n","import type { WsiImageColorSettings } from \"./types\";\nimport { clamp, parseHexColorToRgba } from \"./utils\";\nimport type {\n NormalizedImageColorSettings,\n PointSizeByMagnification,\n PointSizeByZoom,\n PointSizeMagnificationStop,\n PointSizeStop,\n PointWeightByMagnification,\n PointWeightMagnificationStop,\n} from \"./wsi-renderer-types\";\n\nexport const DEFAULT_ROTATION_DRAG_SENSITIVITY = 0.35;\nexport const MIN_POINT_SIZE_PX = 0.5;\nexport const MAX_POINT_SIZE_PX = 256;\n\nexport const DEFAULT_POINT_SIZE_STOPS: readonly PointSizeStop[] = [\n { zoom: 1, size: 2.8 },\n { zoom: 2, size: 3.4 },\n { zoom: 3, size: 4.2 },\n { zoom: 4, size: 5.3 },\n { zoom: 5, size: 6.8 },\n { zoom: 6, size: 8.4 },\n { zoom: 7, size: 9.8 },\n { zoom: 8, size: 11.2 },\n { zoom: 9, size: 14.0 },\n { zoom: 10, size: 17.5 },\n { zoom: 11, size: 22.0 },\n { zoom: 12, size: 28.0 },\n];\n\nconst MIN_STROKE_SCALE = 0.1;\nconst MAX_STROKE_SCALE = 5.0;\nconst MIN_POINT_OPACITY = 0;\nconst MAX_POINT_OPACITY = 1;\nconst MIN_POINT_INNER_FILL_OPACITY = 0;\nconst MAX_POINT_INNER_FILL_OPACITY = 1;\nconst MIN_IMAGE_COLOR_INPUT = -100;\nconst MAX_IMAGE_COLOR_INPUT = 100;\nconst MAX_VIEW_TRANSITION_DURATION_MS = 2000;\nexport const DEFAULT_POINT_INNER_FILL_COLOR: readonly [number, number, number] = [255, 255, 255];\n\nexport function toRadians(deg: number): number {\n return (deg * Math.PI) / 180;\n}\n\nexport function isSameArrayView(a: ArrayBufferView | null | undefined, b: ArrayBufferView | null | undefined): boolean {\n if (!a || !b) return a === b;\n return a.buffer === b.buffer && a.byteOffset === b.byteOffset && a.byteLength === b.byteLength;\n}\n\nexport function clonePointSizeStops(stops: readonly PointSizeStop[]): PointSizeStop[] {\n return stops.map(stop => ({ zoom: stop.zoom, size: stop.size }));\n}\n\nexport function clonePointSizeMagnificationStops(stops: readonly PointSizeMagnificationStop[] | null | undefined): PointSizeMagnificationStop[] | null {\n if (!stops || stops.length === 0) return null;\n return stops.map(stop => ({ magnification: stop.magnification, size: stop.size }));\n}\n\nexport function clonePointWeightMagnificationStops(\n stops: readonly PointWeightMagnificationStop[] | null | undefined\n): PointWeightMagnificationStop[] | null {\n if (!stops || stops.length === 0) return null;\n return stops.map(stop => ({ magnification: stop.magnification, weight: stop.weight }));\n}\n\nexport function normalizePointSizeStops(pointSizeByZoom: PointSizeByZoom | null | undefined): PointSizeStop[] {\n if (!pointSizeByZoom) return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\n const parsed = new Map<number, number>();\n for (const [zoomKey, rawSize] of Object.entries(pointSizeByZoom)) {\n const zoom = Number(zoomKey);\n const size = Number(rawSize);\n if (!Number.isFinite(zoom) || !Number.isFinite(size) || size <= 0) continue;\n parsed.set(zoom, size);\n }\n\n if (parsed.size === 0) {\n return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n }\n\n return Array.from(parsed.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([zoom, size]) => ({ zoom, size }));\n}\n\nexport function normalizePointSizeMagnificationStops(pointSizeByMagnification: PointSizeByMagnification | null | undefined): PointSizeMagnificationStop[] | null {\n if (!pointSizeByMagnification) return null;\n\n const parsed = new Map<number, number>();\n for (const [magnificationKey, rawSize] of Object.entries(pointSizeByMagnification)) {\n const magnification = Number(magnificationKey);\n const size = Number(rawSize);\n if (!Number.isFinite(magnification) || magnification <= 0 || !Number.isFinite(size) || size <= 0) continue;\n parsed.set(magnification, size);\n }\n\n if (parsed.size === 0) {\n return null;\n }\n\n return Array.from(parsed.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([magnification, size]) => ({ magnification, size }));\n}\n\nexport function normalizePointWeightMagnificationStops(\n pointWeightByMagnification: PointWeightByMagnification | null | undefined\n): PointWeightMagnificationStop[] | null {\n if (!pointWeightByMagnification) return null;\n\n const parsed = new Map<number, number>();\n for (const [magnificationKey, rawWeight] of Object.entries(pointWeightByMagnification)) {\n const magnification = Number(magnificationKey);\n const weight = normalizeStrokeScale(rawWeight);\n if (!Number.isFinite(magnification) || magnification <= 0) continue;\n parsed.set(magnification, weight);\n }\n\n if (parsed.size === 0) {\n return null;\n }\n\n return Array.from(parsed.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([magnification, weight]) => ({ magnification, weight }));\n}\n\nexport function arePointSizeStopsEqual(a: readonly PointSizeStop[], b: readonly PointSizeStop[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i].zoom !== b[i].zoom || a[i].size !== b[i].size) {\n return false;\n }\n }\n return true;\n}\n\nexport function arePointSizeMagnificationStopsEqual(\n a: readonly PointSizeMagnificationStop[] | null | undefined,\n b: readonly PointSizeMagnificationStop[] | null | undefined\n): boolean {\n if (a === b) return true;\n if (!a || !b) return a === b;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i].magnification !== b[i].magnification || a[i].size !== b[i].size) {\n return false;\n }\n }\n return true;\n}\n\nexport function arePointWeightMagnificationStopsEqual(\n a: readonly PointWeightMagnificationStop[] | null | undefined,\n b: readonly PointWeightMagnificationStop[] | null | undefined\n): boolean {\n if (a === b) return true;\n if (!a || !b) return a === b;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n if (a[i].magnification !== b[i].magnification || a[i].weight !== b[i].weight) {\n return false;\n }\n }\n return true;\n}\n\nexport function resolvePointSizeByZoomStops(continuousZoom: number, stops: readonly PointSizeStop[]): number {\n if (!Number.isFinite(continuousZoom)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n if (stops.length === 0) return MIN_POINT_SIZE_PX;\n if (stops.length === 1) return stops[0].size;\n if (continuousZoom <= stops[0].zoom) return stops[0].size;\n\n for (let i = 1; i < stops.length; i += 1) {\n const prev = stops[i - 1];\n const next = stops[i];\n if (continuousZoom > next.zoom) continue;\n const span = Math.max(1e-6, next.zoom - prev.zoom);\n const t = clamp((continuousZoom - prev.zoom) / span, 0, 1);\n return prev.size + (next.size - prev.size) * t;\n }\n\n const last = stops[stops.length - 1];\n const prev = stops[stops.length - 2];\n const span = Math.max(1e-6, last.zoom - prev.zoom);\n const slope = (last.size - prev.size) / span;\n return last.size + (continuousZoom - last.zoom) * slope;\n}\n\nexport function resolvePointSizeByMagnificationStops(magnification: number, stops: readonly PointSizeMagnificationStop[]): number {\n if (!Number.isFinite(magnification)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n if (stops.length === 0) return MIN_POINT_SIZE_PX;\n if (stops.length === 1) return stops[0].size;\n if (magnification <= stops[0].magnification) return stops[0].size;\n\n for (let i = 1; i < stops.length; i += 1) {\n const prev = stops[i - 1];\n const next = stops[i];\n if (magnification > next.magnification) continue;\n const span = Math.max(1e-6, next.magnification - prev.magnification);\n const t = clamp((magnification - prev.magnification) / span, 0, 1);\n return prev.size + (next.size - prev.size) * t;\n }\n\n const last = stops[stops.length - 1];\n const prev = stops[stops.length - 2];\n const span = Math.max(1e-6, last.magnification - prev.magnification);\n const slope = (last.size - prev.size) / span;\n return last.size + (magnification - last.magnification) * slope;\n}\n\nexport function resolvePointWeightByMagnificationStops(magnification: number, stops: readonly PointWeightMagnificationStop[]): number {\n if (!Number.isFinite(magnification)) return stops[0]?.weight ?? 1.0;\n if (stops.length === 0) return 1.0;\n if (stops.length === 1) return stops[0].weight;\n if (magnification <= stops[0].magnification) return stops[0].weight;\n\n for (let i = 1; i < stops.length; i += 1) {\n const prev = stops[i - 1];\n const next = stops[i];\n if (magnification > next.magnification) continue;\n const span = Math.max(1e-6, next.magnification - prev.magnification);\n const t = clamp((magnification - prev.magnification) / span, 0, 1);\n return prev.weight + (next.weight - prev.weight) * t;\n }\n\n const last = stops[stops.length - 1];\n const prev = stops[stops.length - 2];\n const span = Math.max(1e-6, last.magnification - prev.magnification);\n const slope = (last.weight - prev.weight) / span;\n return last.weight + (magnification - last.magnification) * slope;\n}\n\nexport function normalizeStrokeScale(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 1.0;\n return clamp(value, MIN_STROKE_SCALE, MAX_STROKE_SCALE);\n}\n\nexport function normalizePointOpacity(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 1;\n return clamp(value, MIN_POINT_OPACITY, MAX_POINT_OPACITY);\n}\n\nexport function normalizePointLineDash(dashed: [number, number] | null | undefined): [number, number] {\n if (!dashed) return [1, 0];\n return [clamp(dashed[0], 0, 100), clamp(dashed[1], 0, 100)];\n}\n\nexport function normalizePointInnerFillOpacity(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n return clamp(value, MIN_POINT_INNER_FILL_OPACITY, MAX_POINT_INNER_FILL_OPACITY);\n}\n\nexport function normalizePointInnerFillColor(value: string | null | undefined): [number, number, number] {\n const rgba = parseHexColorToRgba(value, [...DEFAULT_POINT_INNER_FILL_COLOR, 255]);\n return [rgba[0], rgba[1], rgba[2]];\n}\n\nfunction normalizeImageColorInput(value: number | null | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return 0;\n return clamp(value, MIN_IMAGE_COLOR_INPUT, MAX_IMAGE_COLOR_INPUT);\n}\n\nexport function toNormalizedImageColorSettings(settings: WsiImageColorSettings | null | undefined): NormalizedImageColorSettings {\n const brightnessInput = normalizeImageColorInput(settings?.brightness);\n const contrastInput = normalizeImageColorInput(settings?.contrast);\n const saturationInput = normalizeImageColorInput(settings?.saturation);\n return {\n brightness: brightnessInput / 200,\n contrast: contrastInput / 100,\n saturation: saturationInput / 100,\n };\n}\n\nexport function linearEasing(t: number): number {\n return t;\n}\n\nexport function normalizeViewTransitionDuration(duration: number | null | undefined): number {\n if (typeof duration !== \"number\" || !Number.isFinite(duration)) return 0;\n return clamp(duration, 0, MAX_VIEW_TRANSITION_DURATION_MS);\n}\n\nexport function normalizeZoomOverride(value: number | null | undefined): number | null {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) return null;\n return Math.max(1e-6, value);\n}\n\nexport function normalizeTransitionEasing(easing: ((t: number) => number) | null | undefined): (t: number) => number {\n return typeof easing === \"function\" ? easing : linearEasing;\n}\n","import { DEFAULT_ROTATION_DRAG_SENSITIVITY, toRadians } from \"./wsi-normalize\";\nimport type { InteractionConfig, InteractionState, ZoomSnapState } from \"./wsi-renderer-types\";\n\ninterface PointerMoveOptions {\n event: PointerEvent;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n config: InteractionConfig;\n camera: {\n getViewState: () => {\n zoom: number;\n offsetX: number;\n offsetY: number;\n rotationDeg: number;\n };\n setViewState: (next: Partial<{ zoom: number; offsetX: number; offsetY: number; rotationDeg: number }>) => void;\n };\n clampViewState: () => void;\n emitViewState: () => void;\n requestRender: () => void;\n}\n\ninterface PointerDownOptions {\n event: PointerEvent;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n config: InteractionConfig;\n cancelViewAnimation: () => void;\n}\n\ninterface WheelOptions {\n event: WheelEvent;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\ninterface DoubleClickOptions {\n event: MouseEvent;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\nfunction getPointerAngleRad(canvas: HTMLCanvasElement, clientX: number, clientY: number): number {\n const rect = canvas.getBoundingClientRect();\n const x = clientX - rect.left - rect.width * 0.5;\n const y = clientY - rect.top - rect.height * 0.5;\n return Math.atan2(y, x);\n}\n\nexport function cancelDrag(canvas: HTMLCanvasElement, state: InteractionState): void {\n if (state.pointerId !== null && canvas.hasPointerCapture(state.pointerId)) {\n try {\n canvas.releasePointerCapture(state.pointerId);\n } catch {\n // noop\n }\n }\n state.dragging = false;\n state.mode = \"none\";\n state.rotateLastAngleRad = null;\n state.pointerId = null;\n canvas.classList.remove(\"dragging\");\n}\n\nexport function handlePointerDown(options: PointerDownOptions): void {\n const { event, canvas, state, config, cancelViewAnimation } = options;\n const wantsRotate = config.ctrlDragRotate && (event.ctrlKey || event.metaKey);\n const allowButton = event.button === 0 || (wantsRotate && event.button === 2);\n if (!allowButton) return;\n\n cancelViewAnimation();\n if (wantsRotate) {\n event.preventDefault();\n }\n\n state.dragging = true;\n state.mode = wantsRotate ? \"rotate\" : \"pan\";\n state.pointerId = event.pointerId;\n state.lastPointerX = event.clientX;\n state.lastPointerY = event.clientY;\n state.rotateLastAngleRad = state.mode === \"rotate\" ? getPointerAngleRad(canvas, event.clientX, event.clientY) : null;\n\n canvas.classList.add(\"dragging\");\n canvas.setPointerCapture(event.pointerId);\n}\n\nexport function handlePointerMove(options: PointerMoveOptions): void {\n const { event, canvas, state, config, camera, clampViewState, emitViewState, requestRender } = options;\n if (!state.dragging || event.pointerId !== state.pointerId) return;\n\n const dx = event.clientX - state.lastPointerX;\n const dy = event.clientY - state.lastPointerY;\n state.lastPointerX = event.clientX;\n state.lastPointerY = event.clientY;\n\n if (state.mode === \"rotate\") {\n const nextAngle = getPointerAngleRad(canvas, event.clientX, event.clientY);\n const prevAngle = state.rotateLastAngleRad;\n state.rotateLastAngleRad = nextAngle;\n if (prevAngle !== null) {\n const rawDelta = nextAngle - prevAngle;\n const delta = Math.atan2(Math.sin(rawDelta), Math.cos(rawDelta));\n const sensitivityScale = DEFAULT_ROTATION_DRAG_SENSITIVITY > 0 ? config.rotationDragSensitivityDegPerPixel / DEFAULT_ROTATION_DRAG_SENSITIVITY : 1;\n const viewState = camera.getViewState();\n camera.setViewState({\n rotationDeg: viewState.rotationDeg - ((delta * 180) / Math.PI) * sensitivityScale,\n });\n }\n } else {\n const viewState = camera.getViewState();\n const zoom = Math.max(1e-6, viewState.zoom);\n const rad = toRadians(viewState.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const worldDx = (dx * cos - dy * sin) / zoom;\n const worldDy = (dx * sin + dy * cos) / zoom;\n camera.setViewState({\n offsetX: viewState.offsetX - worldDx,\n offsetY: viewState.offsetY - worldDy,\n });\n }\n\n clampViewState();\n emitViewState();\n requestRender();\n}\n\nexport function handlePointerUp(event: PointerEvent, canvas: HTMLCanvasElement, state: InteractionState): void {\n if (event.pointerId !== state.pointerId) return;\n cancelDrag(canvas, state);\n}\n\nexport function handleWheel(options: WheelOptions): void {\n const { event, canvas, onZoomBy } = options;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n applyWheelZoomDelta(event.deltaY, x, y, onZoomBy);\n}\n\ninterface WheelSnapOptions {\n event: WheelEvent;\n canvas: HTMLCanvasElement;\n snapState: ZoomSnapState;\n onSnapZoom: (direction: \"in\" | \"out\", x: number, y: number) => boolean;\n}\n\nconst SNAP_DELTA_THRESHOLD = 4;\n\nexport function applyWheelZoomDelta(deltaY: number, x: number, y: number, onZoomBy: (factor: number, x: number, y: number) => void): void {\n const factor = deltaY < 0 ? 1.12 : 0.89;\n onZoomBy(factor, x, y);\n}\n\nexport function applyWheelSnapDelta(\n deltaY: number,\n x: number,\n y: number,\n snapState: ZoomSnapState,\n onSnapZoom: (direction: \"in\" | \"out\", x: number, y: number) => boolean\n): void {\n const inputDirection: \"in\" | \"out\" | null = deltaY < 0 ? \"in\" : deltaY > 0 ? \"out\" : null;\n if (inputDirection && snapState.blockedDirection) {\n if (inputDirection !== snapState.blockedDirection) {\n snapState.blockedDirection = null;\n snapState.accumulatedDelta = 0;\n } else {\n return;\n }\n }\n\n if (snapState.accumulatedDelta !== 0 && deltaY !== 0 && Math.sign(snapState.accumulatedDelta) !== Math.sign(deltaY)) {\n snapState.accumulatedDelta = 0;\n }\n snapState.accumulatedDelta += deltaY;\n\n if (Math.abs(snapState.accumulatedDelta) < SNAP_DELTA_THRESHOLD) return;\n\n const direction: \"in\" | \"out\" = snapState.accumulatedDelta > 0 ? \"out\" : \"in\";\n\n snapState.accumulatedDelta = 0;\n if (!onSnapZoom(direction, x, y)) {\n snapState.blockedDirection = direction;\n return;\n }\n\n snapState.blockedDirection = null;\n}\n\nexport function handleWheelSnap(options: WheelSnapOptions): void {\n const { event, canvas, snapState, onSnapZoom } = options;\n event.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n applyWheelSnapDelta(event.deltaY, x, y, snapState, onSnapZoom);\n}\n\nexport function handleDoubleClick(options: DoubleClickOptions): void {\n const { event, canvas, onZoomBy } = options;\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n onZoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n}\n\nexport function handleContextMenu(event: MouseEvent, dragging: boolean): void {\n if (dragging || event.ctrlKey || event.metaKey) {\n event.preventDefault();\n }\n}\n","import { toTileUrl } from \"./image-info\";\nimport type { ScheduledTile } from \"./tile-scheduler\";\nimport type { WsiImageSource } from \"./types\";\nimport { clamp } from \"./utils\";\nimport type { Bounds } from \"./wsi-renderer-types\";\n\ninterface CameraViewLike {\n getViewCorners: () => [readonly [number, number], readonly [number, number], readonly [number, number], readonly [number, number]];\n getViewState: () => { zoom: number };\n getCenter: () => [number, number];\n setCenter: (x: number, y: number) => void;\n}\n\nexport function getViewBounds(camera: CameraViewLike): Bounds {\n const corners = camera.getViewCorners();\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of corners) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n return [minX, minY, maxX, maxY];\n}\n\nexport function clampViewState(camera: CameraViewLike, source: WsiImageSource, extentX = 0.2, extentY = 0.2): void {\n const bounds = getViewBounds(camera);\n const visibleW = Math.max(1e-6, bounds[2] - bounds[0]);\n const visibleH = Math.max(1e-6, bounds[3] - bounds[1]);\n const marginX = visibleW * extentX;\n const marginY = visibleH * extentY;\n\n const [centerX, centerY] = camera.getCenter();\n const halfW = visibleW * 0.5;\n const halfH = visibleH * 0.5;\n\n const minCenterX = halfW - marginX;\n const maxCenterX = source.width - halfW + marginX;\n const minCenterY = halfH - marginY;\n const maxCenterY = source.height - halfH + marginY;\n\n const nextCenterX = minCenterX <= maxCenterX ? clamp(centerX, minCenterX, maxCenterX) : source.width * 0.5;\n const nextCenterY = minCenterY <= maxCenterY ? clamp(centerY, minCenterY, maxCenterY) : source.height * 0.5;\n\n camera.setCenter(nextCenterX, nextCenterY);\n}\n\nexport function selectTier(camera: CameraViewLike, source: WsiImageSource): number {\n const zoom = Math.max(1e-6, camera.getViewState().zoom);\n const rawTier = source.maxTierZoom + Math.log2(zoom);\n return clamp(Math.floor(rawTier), 0, source.maxTierZoom);\n}\n\nexport function intersectsBounds(a: Bounds, b: Bounds): boolean {\n return !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n}\n\nexport function getVisibleTilesForTier(camera: CameraViewLike, source: WsiImageSource, tier: number): ScheduledTile[] {\n const viewBounds = getViewBounds(camera);\n\n const levelScale = Math.pow(2, source.maxTierZoom - tier);\n const levelWidth = Math.ceil(source.width / levelScale);\n const levelHeight = Math.ceil(source.height / levelScale);\n\n const tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n const tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\n const viewMinX = viewBounds[0];\n const viewMinY = viewBounds[1];\n const viewMaxX = viewBounds[2];\n const viewMaxY = viewBounds[3];\n\n const minTileX = clamp(Math.floor(viewMinX / levelScale / source.tileSize), 0, tilesX - 1);\n const maxTileX = clamp(Math.floor((viewMaxX - 1) / levelScale / source.tileSize), 0, tilesX - 1);\n const minTileY = clamp(Math.floor(viewMinY / levelScale / source.tileSize), 0, tilesY - 1);\n const maxTileY = clamp(Math.floor((viewMaxY - 1) / levelScale / source.tileSize), 0, tilesY - 1);\n\n if (minTileX > maxTileX || minTileY > maxTileY) {\n return [];\n }\n\n const centerTileX = ((viewMinX + viewMaxX) * 0.5) / levelScale / source.tileSize;\n const centerTileY = ((viewMinY + viewMaxY) * 0.5) / levelScale / source.tileSize;\n\n const visible: ScheduledTile[] = [];\n for (let y = minTileY; y <= maxTileY; y += 1) {\n for (let x = minTileX; x <= maxTileX; x += 1) {\n const left = x * source.tileSize * levelScale;\n const top = y * source.tileSize * levelScale;\n const right = Math.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n const bottom = Math.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\n const dx = x - centerTileX;\n const dy = y - centerTileY;\n visible.push({\n key: `${tier}/${x}/${y}`,\n tier,\n x,\n y,\n bounds: [left, top, right, bottom],\n distance2: dx * dx + dy * dy,\n url: toTileUrl(source, tier, x, y),\n });\n }\n }\n\n visible.sort((a, b) => a.distance2 - b.distance2);\n return visible;\n}\n\nexport function getVisibleTiles(camera: CameraViewLike, source: WsiImageSource): { tier: number; visible: ScheduledTile[] } {\n const tier = selectTier(camera, source);\n return {\n tier,\n visible: getVisibleTilesForTier(camera, source, tier),\n };\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { WsiImageSource } from \"./types\";\nimport type { RendererCanvasHandlers } from \"./wsi-canvas-lifecycle\";\nimport { cancelDrag as cancelInteractionDrag, handleContextMenu, handleDoubleClick, handlePointerDown, handlePointerMove, handlePointerUp, handleWheel, handleWheelSnap } from \"./wsi-interaction\";\nimport type { InteractionState, ZoomSnapState } from \"./wsi-renderer-types\";\nimport { clampViewState } from \"./wsi-tile-visibility\";\n\ninterface BaseInteractionOptions {\n interactionLocked: boolean;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n}\n\ninterface PointerDownWithLockOptions extends BaseInteractionOptions {\n event: PointerEvent;\n ctrlDragRotate: boolean;\n rotationDragSensitivityDegPerPixel: number;\n cancelViewAnimation: () => void;\n}\n\ninterface PointerMoveWithLockOptions extends BaseInteractionOptions {\n event: PointerEvent;\n ctrlDragRotate: boolean;\n rotationDragSensitivityDegPerPixel: number;\n camera: OrthoCamera;\n source: WsiImageSource;\n panExtentX: number;\n panExtentY: number;\n emitViewState: () => void;\n requestRender: () => void;\n}\n\ninterface PointerUpWithLockOptions extends BaseInteractionOptions {\n event: PointerEvent;\n}\n\ninterface WheelWithLockOptions {\n event: WheelEvent;\n interactionLocked: boolean;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\ninterface DoubleClickWithLockOptions {\n event: MouseEvent;\n interactionLocked: boolean;\n canvas: HTMLCanvasElement;\n onZoomBy: (factor: number, x: number, y: number) => void;\n}\n\ninterface ContextMenuWithLockOptions {\n event: MouseEvent;\n canvas: HTMLCanvasElement;\n state: InteractionState;\n}\n\nexport function onPointerDownWithLock(options: PointerDownWithLockOptions): void {\n if (options.interactionLocked) return;\n handlePointerDown({\n event: options.event,\n canvas: options.canvas,\n state: options.state,\n config: {\n ctrlDragRotate: options.ctrlDragRotate,\n rotationDragSensitivityDegPerPixel: options.rotationDragSensitivityDegPerPixel,\n },\n cancelViewAnimation: options.cancelViewAnimation,\n });\n}\n\nexport function onPointerMoveWithLock(options: PointerMoveWithLockOptions): void {\n if (options.interactionLocked) return;\n handlePointerMove({\n event: options.event,\n canvas: options.canvas,\n state: options.state,\n config: {\n ctrlDragRotate: options.ctrlDragRotate,\n rotationDragSensitivityDegPerPixel: options.rotationDragSensitivityDegPerPixel,\n },\n camera: options.camera,\n clampViewState: () => clampViewState(options.camera, options.source, options.panExtentX, options.panExtentY),\n emitViewState: options.emitViewState,\n requestRender: options.requestRender,\n });\n}\n\nexport function onPointerUpWithLock(options: PointerUpWithLockOptions): void {\n if (options.interactionLocked) return;\n handlePointerUp(options.event, options.canvas, options.state);\n}\n\nexport function onWheelWithLock(options: WheelWithLockOptions): void {\n if (options.interactionLocked) {\n options.event.preventDefault();\n return;\n }\n handleWheel({\n event: options.event,\n canvas: options.canvas,\n onZoomBy: options.onZoomBy,\n });\n}\n\nexport function onDoubleClickWithLock(options: DoubleClickWithLockOptions): void {\n if (options.interactionLocked) return;\n handleDoubleClick({\n event: options.event,\n canvas: options.canvas,\n onZoomBy: options.onZoomBy,\n });\n}\n\nexport function onContextMenuWithLock(options: ContextMenuWithLockOptions): void {\n handleContextMenu(options.event, options.state.dragging);\n}\n\nexport function cancelDrag(canvas: HTMLCanvasElement, state: InteractionState): void {\n cancelInteractionDrag(canvas, state);\n}\n\nexport interface CreateRendererInputHandlersOptions {\n canvas: HTMLCanvasElement;\n state: InteractionState;\n getInteractionLocked: () => boolean;\n getCtrlDragRotate: () => boolean;\n getRotationDragSensitivityDegPerPixel: () => number;\n cancelViewAnimation: () => void;\n camera: OrthoCamera;\n source: WsiImageSource;\n emitViewState: () => void;\n requestRender: () => void;\n getPanExtentX: () => number;\n getPanExtentY: () => number;\n zoomBy: (factor: number, x: number, y: number) => void;\n getUseZoomSnaps?: () => boolean;\n onSnapZoom?: (direction: \"in\" | \"out\", x: number, y: number) => boolean;\n zoomSnapState?: ZoomSnapState;\n}\n\nexport function createRendererInputHandlers(\n options: CreateRendererInputHandlersOptions\n): Pick<RendererCanvasHandlers, \"pointerDown\" | \"pointerMove\" | \"pointerUp\" | \"wheel\" | \"doubleClick\" | \"contextMenu\"> {\n return {\n pointerDown: (event: PointerEvent) =>\n onPointerDownWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n state: options.state,\n ctrlDragRotate: options.getCtrlDragRotate(),\n rotationDragSensitivityDegPerPixel: options.getRotationDragSensitivityDegPerPixel(),\n cancelViewAnimation: options.cancelViewAnimation,\n }),\n pointerMove: (event: PointerEvent) =>\n onPointerMoveWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n state: options.state,\n ctrlDragRotate: options.getCtrlDragRotate(),\n rotationDragSensitivityDegPerPixel: options.getRotationDragSensitivityDegPerPixel(),\n camera: options.camera,\n source: options.source,\n panExtentX: options.getPanExtentX(),\n panExtentY: options.getPanExtentY(),\n emitViewState: options.emitViewState,\n requestRender: options.requestRender,\n }),\n pointerUp: (event: PointerEvent) =>\n onPointerUpWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n state: options.state,\n }),\n wheel: (event: WheelEvent) => {\n if (options.getInteractionLocked()) {\n event.preventDefault();\n return;\n }\n if (options.getUseZoomSnaps?.() && options.onSnapZoom && options.zoomSnapState) {\n handleWheelSnap({\n event,\n canvas: options.canvas,\n snapState: options.zoomSnapState,\n onSnapZoom: options.onSnapZoom,\n });\n return;\n }\n handleWheel({\n event,\n canvas: options.canvas,\n onZoomBy: options.zoomBy,\n });\n },\n doubleClick: (event: MouseEvent) =>\n onDoubleClickWithLock({\n event,\n interactionLocked: options.getInteractionLocked(),\n canvas: options.canvas,\n onZoomBy: options.zoomBy,\n }),\n contextMenu: (event: MouseEvent) =>\n onContextMenuWithLock({\n event,\n canvas: options.canvas,\n state: options.state,\n }),\n };\n}\n","import type {\n HandleTileLoadedOptions,\n TileCacheTrimOptions,\n} from \"./wsi-renderer-types\";\n\nexport function trimTileCache(options: TileCacheTrimOptions): void {\n const { gl, cache, maxCacheTiles } = options;\n if (cache.size <= maxCacheTiles) return;\n const targetSize = Math.max(0, Math.floor(maxCacheTiles));\n while (cache.size > targetSize) {\n let oldestKey: string | null = null;\n let oldestValue: { texture: WebGLTexture; lastUsed: number } | null = null;\n for (const [key, value] of cache) {\n if (!oldestValue || value.lastUsed < oldestValue.lastUsed) {\n oldestKey = key;\n oldestValue = value;\n }\n }\n if (!oldestKey || !oldestValue) break;\n gl.deleteTexture(oldestValue.texture);\n cache.delete(oldestKey);\n }\n}\n\nexport function createTextureFromBitmap(gl: WebGL2RenderingContext, bitmap: ImageBitmap): WebGLTexture | null {\n if (gl.isContextLost()) return null;\n\n const texture = gl.createTexture();\n if (!texture) return null;\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return texture;\n}\n\nexport function handleTileLoaded(options: HandleTileLoadedOptions): void {\n const { gl, cache, tile, bitmap, frameSerial, maxCacheTiles, destroyed, contextLost, requestRender } = options;\n\n if (destroyed || contextLost || gl.isContextLost()) {\n bitmap.close();\n return;\n }\n if (cache.has(tile.key)) {\n bitmap.close();\n return;\n }\n\n const texture = createTextureFromBitmap(gl, bitmap);\n bitmap.close();\n if (!texture) return;\n\n cache.set(tile.key, {\n key: tile.key,\n texture,\n bounds: tile.bounds,\n tier: tile.tier,\n lastUsed: frameSerial,\n });\n trimTileCache({ gl, cache, maxCacheTiles });\n requestRender();\n}\n\nexport function deleteCachedTextures(gl: WebGL2RenderingContext, cache: Map<string, { texture: WebGLTexture }>): void {\n for (const [, value] of cache) {\n gl.deleteTexture(value.texture);\n }\n}\n","import type { TileScheduler } from \"./tile-scheduler\";\nimport type { CachedTile, PointProgram, TileVertexProgram } from \"./wsi-renderer-types\";\nimport { deleteCachedTextures } from \"./wsi-tile-cache\";\n\nexport interface ContextLostOptions {\n event: Event;\n destroyed: boolean;\n contextLost: boolean;\n frame: number | null;\n cancelViewAnimation: () => void;\n cancelDrag: () => void;\n tileScheduler: TileScheduler;\n cache: Map<string, CachedTile>;\n onContextLost?: () => void;\n}\n\nexport interface ContextLostResult {\n handled: boolean;\n frame: number | null;\n}\n\nexport function handleContextLost(options: ContextLostOptions): ContextLostResult {\n const { event, destroyed, contextLost, cancelViewAnimation, cancelDrag, tileScheduler, cache, onContextLost } = options;\n event.preventDefault();\n if (destroyed || contextLost) {\n return {\n handled: false,\n frame: options.frame,\n };\n }\n\n let frame = options.frame;\n if (frame !== null) {\n cancelAnimationFrame(frame);\n frame = null;\n }\n cancelViewAnimation();\n\n cancelDrag();\n tileScheduler.clear();\n cache.clear();\n onContextLost?.();\n\n return {\n handled: true,\n frame,\n };\n}\n\nexport interface DestroyRendererOptions {\n destroyed: boolean;\n frame: number | null;\n cancelViewAnimation: () => void;\n resizeObserver: ResizeObserver;\n removeDprListener: () => void;\n removeCanvasEventListeners: () => void;\n cancelDrag: () => void;\n tileScheduler: TileScheduler;\n contextLost: boolean;\n gl: WebGL2RenderingContext;\n cache: Map<string, CachedTile>;\n tileProgram: TileVertexProgram;\n pointPrograms: PointProgram[];\n}\n\nexport interface DestroyRendererResult {\n didDestroy: boolean;\n frame: number | null;\n}\n\nexport function destroyRenderer(options: DestroyRendererOptions): DestroyRendererResult {\n if (options.destroyed) {\n return {\n didDestroy: false,\n frame: options.frame,\n };\n }\n\n let frame = options.frame;\n if (frame !== null) {\n cancelAnimationFrame(frame);\n frame = null;\n }\n options.cancelViewAnimation();\n\n options.resizeObserver.disconnect();\n options.removeDprListener();\n options.removeCanvasEventListeners();\n options.cancelDrag();\n options.tileScheduler.destroy();\n\n if (!options.contextLost && !options.gl.isContextLost()) {\n deleteCachedTextures(options.gl, options.cache);\n options.gl.deleteBuffer(options.tileProgram.vbo);\n options.gl.deleteVertexArray(options.tileProgram.vao);\n options.gl.deleteProgram(options.tileProgram.program);\n\n for (let i = 0; i < options.pointPrograms.length; i += 1) {\n const pointProgram = options.pointPrograms[i];\n options.gl.deleteBuffer(pointProgram.posBuffer);\n options.gl.deleteBuffer(pointProgram.classBuffer);\n options.gl.deleteBuffer(pointProgram.fillModeBuffer);\n options.gl.deleteBuffer(pointProgram.indexBuffer);\n options.gl.deleteTexture(pointProgram.paletteTexture);\n options.gl.deleteVertexArray(pointProgram.vao);\n options.gl.deleteProgram(pointProgram.program);\n }\n }\n options.cache.clear();\n\n return {\n didDestroy: true,\n frame,\n };\n}\n","import type { WsiPointData } from \"./types\";\nimport { isSameArrayView } from \"./wsi-normalize\";\nimport type { PointProgram } from \"./wsi-renderer-types\";\n\nexport interface PointBufferRuntime {\n pointCount: number;\n usePointIndices: boolean;\n pointBuffersDirty: boolean;\n lastPointData: WsiPointData | null;\n zeroFillModes: Uint8Array<ArrayBufferLike>;\n lastPointPalette: Uint8Array<ArrayBufferLike> | null;\n pointPaletteSize: number;\n}\n\nfunction sanitizeDrawIndices(drawIndices: Uint32Array, maxExclusive: number): Uint32Array {\n if (maxExclusive <= 0 || drawIndices.length === 0) {\n return new Uint32Array(0);\n }\n\n let validCount = drawIndices.length;\n for (let i = 0; i < drawIndices.length; i += 1) {\n if (drawIndices[i] < maxExclusive) continue;\n validCount -= 1;\n }\n if (validCount === drawIndices.length) {\n return drawIndices;\n }\n if (validCount <= 0) {\n return new Uint32Array(0);\n }\n\n const filtered = new Uint32Array(validCount);\n let cursor = 0;\n for (let i = 0; i < drawIndices.length; i += 1) {\n const idx = drawIndices[i];\n if (idx >= maxExclusive) continue;\n filtered[cursor] = idx;\n cursor += 1;\n }\n return filtered;\n}\n\nfunction getZeroFillModes(zeroFillModes: Uint8Array<ArrayBufferLike>, count: number): Uint8Array<ArrayBufferLike> {\n if (count <= 0) return new Uint8Array(0);\n if (zeroFillModes.length < count) {\n return new Uint8Array(count);\n }\n return zeroFillModes.subarray(0, count);\n}\n\nexport function setPointPalette(runtime: PointBufferRuntime, gl: WebGL2RenderingContext, pointProgram: PointProgram, contextLost: boolean, colors: Uint8Array | null | undefined): PointBufferRuntime {\n if (!colors || colors.length === 0) {\n return {\n ...runtime,\n lastPointPalette: null,\n };\n }\n\n const nextPalette = new Uint8Array(colors);\n if (contextLost || gl.isContextLost()) {\n return {\n ...runtime,\n lastPointPalette: nextPalette,\n };\n }\n\n const paletteSize = Math.max(1, Math.floor(nextPalette.length / 4));\n gl.bindTexture(gl.TEXTURE_2D, pointProgram.paletteTexture);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, paletteSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, nextPalette);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n ...runtime,\n lastPointPalette: nextPalette,\n pointPaletteSize: paletteSize,\n };\n}\n\nexport function setPointData(runtime: PointBufferRuntime, gl: WebGL2RenderingContext, pointProgram: PointProgram, contextLost: boolean, points: WsiPointData | null | undefined): PointBufferRuntime {\n if (!points || !points.count || !points.positions || !points.paletteIndices) {\n return {\n ...runtime,\n lastPointData: null,\n pointCount: 0,\n usePointIndices: false,\n };\n }\n\n const pointFillModes = points.fillModes instanceof Uint8Array ? points.fillModes : null;\n const hasFillModes = pointFillModes !== null;\n const safeCount = Math.max(0, Math.min(points.count, Math.floor(points.positions.length / 2), points.paletteIndices.length, hasFillModes ? pointFillModes.length : Number.MAX_SAFE_INTEGER));\n const nextPositions = points.positions.subarray(0, safeCount * 2);\n const nextPaletteIndices = points.paletteIndices.subarray(0, safeCount);\n const nextFillModes = hasFillModes ? pointFillModes.subarray(0, safeCount) : undefined;\n const hasDrawIndices = points.drawIndices instanceof Uint32Array;\n const nextDrawIndices = hasDrawIndices ? sanitizeDrawIndices(points.drawIndices as Uint32Array, safeCount) : null;\n\n const prev = runtime.lastPointData;\n const prevHasFillModes = prev?.fillModes instanceof Uint8Array;\n const geometryChanged =\n runtime.pointBuffersDirty ||\n !prev ||\n prev.count !== safeCount ||\n !isSameArrayView(prev.positions, nextPositions) ||\n !isSameArrayView(prev.paletteIndices, nextPaletteIndices) ||\n prevHasFillModes !== hasFillModes ||\n (hasFillModes && (!prev?.fillModes || !isSameArrayView(prev.fillModes, nextFillModes)));\n const drawIndicesChanged = runtime.pointBuffersDirty || (hasDrawIndices && (!prev?.drawIndices || !isSameArrayView(prev.drawIndices, nextDrawIndices))) || (!hasDrawIndices && !!prev?.drawIndices);\n\n const nextRuntime: PointBufferRuntime = {\n ...runtime,\n lastPointData: {\n count: safeCount,\n positions: nextPositions,\n paletteIndices: nextPaletteIndices,\n fillModes: nextFillModes,\n drawIndices: hasDrawIndices ? (nextDrawIndices ?? undefined) : undefined,\n },\n };\n\n if (contextLost || gl.isContextLost()) {\n return nextRuntime;\n }\n\n const currentPointData = nextRuntime.lastPointData;\n if (!currentPointData) {\n return nextRuntime;\n }\n\n if (geometryChanged) {\n gl.bindBuffer(gl.ARRAY_BUFFER, pointProgram.posBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, currentPointData.positions, gl.STATIC_DRAW);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, pointProgram.classBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, currentPointData.paletteIndices, gl.STATIC_DRAW);\n\n const zeroFillModes = getZeroFillModes(nextRuntime.zeroFillModes, safeCount);\n gl.bindBuffer(gl.ARRAY_BUFFER, pointProgram.fillModeBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, currentPointData.fillModes ?? zeroFillModes, gl.STATIC_DRAW);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n nextRuntime.zeroFillModes = zeroFillModes;\n }\n\n if (hasDrawIndices && drawIndicesChanged) {\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, pointProgram.indexBuffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, nextDrawIndices ?? new Uint32Array(0), gl.DYNAMIC_DRAW);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n }\n\n nextRuntime.usePointIndices = hasDrawIndices;\n nextRuntime.pointCount = hasDrawIndices ? (nextDrawIndices?.length ?? 0) : currentPointData.count;\n if (geometryChanged || drawIndicesChanged) {\n nextRuntime.pointBuffersDirty = false;\n }\n\n return nextRuntime;\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { ScheduledTile, TileScheduler } from \"./tile-scheduler\";\nimport type { WsiImageSource } from \"./types\";\nimport type { Bounds, CachedTile, NormalizedImageColorSettings, PointProgram, TileVertexProgram } from \"./wsi-renderer-types\";\n\nexport interface RenderPointLayer {\n pointProgram: PointProgram;\n pointCount: number;\n usePointIndices: boolean;\n pointPaletteSize: number;\n pointLineDash: [number, number];\n pointOpacity: number;\n pointStrokeScale: number;\n pointInnerFillOpacity: number;\n pointInnerFillColor: [number, number, number];\n pointCssSizePx: number;\n pointSizePx: number;\n}\n\nexport interface RenderFrameOptions {\n gl: WebGL2RenderingContext;\n camera: OrthoCamera;\n source: WsiImageSource;\n cache: Map<string, CachedTile>;\n frameSerial: number;\n tileProgram: TileVertexProgram;\n imageColorSettings: NormalizedImageColorSettings;\n pointLayers: readonly RenderPointLayer[];\n tileScheduler: TileScheduler;\n getVisibleTiles: () => { tier: number; visible: ScheduledTile[] };\n getVisibleTilesForTier: (tier: number) => ScheduledTile[];\n getViewBounds: () => Bounds;\n intersectsBounds: (a: Bounds, b: Bounds) => boolean;\n}\n\nexport interface RenderFrameResult {\n tier: number;\n visible: number;\n rendered: number;\n points: number;\n fallback: number;\n cacheHits: number;\n cacheMisses: number;\n drawCalls: number;\n}\n\nexport function renderFrame(options: RenderFrameOptions): RenderFrameResult {\n const {\n gl,\n camera,\n source,\n cache,\n frameSerial,\n tileProgram,\n imageColorSettings,\n pointLayers,\n tileScheduler,\n getVisibleTiles,\n getVisibleTilesForTier,\n getViewBounds,\n intersectsBounds,\n } = options;\n\n gl.clearColor(0.03, 0.06, 0.1, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n const { tier, visible } = getVisibleTiles();\n const viewBounds = getViewBounds();\n const visibleKeys = new Set(visible.map(tile => tile.key));\n\n gl.useProgram(tileProgram.program);\n gl.bindVertexArray(tileProgram.vao);\n gl.uniformMatrix3fv(tileProgram.uCamera, false, camera.getMatrix());\n gl.uniform1i(tileProgram.uTexture, 0);\n gl.uniform1f(tileProgram.uBrightness, imageColorSettings.brightness);\n gl.uniform1f(tileProgram.uContrast, imageColorSettings.contrast);\n gl.uniform1f(tileProgram.uSaturation, imageColorSettings.saturation);\n\n const fallbackTiles: CachedTile[] = [];\n for (const [, cached] of cache) {\n if (visibleKeys.has(cached.key)) continue;\n if (!intersectsBounds(cached.bounds, viewBounds)) continue;\n fallbackTiles.push(cached);\n }\n fallbackTiles.sort((a, b) => a.tier - b.tier);\n\n for (const cached of fallbackTiles) {\n cached.lastUsed = frameSerial;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, cached.texture);\n gl.uniform4f(tileProgram.uBounds, cached.bounds[0], cached.bounds[1], cached.bounds[2], cached.bounds[3]);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n let renderedTiles = 0;\n const missingTiles: ScheduledTile[] = [];\n for (const tile of visible) {\n const cached = cache.get(tile.key);\n if (!cached) {\n missingTiles.push(tile);\n continue;\n }\n cached.lastUsed = frameSerial;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, cached.texture);\n gl.uniform4f(tileProgram.uBounds, cached.bounds[0], cached.bounds[1], cached.bounds[2], cached.bounds[3]);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n renderedTiles += 1;\n }\n\n const tilesToSchedule: ScheduledTile[] = missingTiles.slice();\n const PREFETCH_DISTANCE_PENALTY = 1e6;\n const prefetchTiers: number[] = [];\n if (tier > 0) prefetchTiers.push(tier - 1);\n if (tier < source.maxTierZoom) prefetchTiers.push(tier + 1);\n for (const prefetchTier of prefetchTiers) {\n const prefetchCandidates = getVisibleTilesForTier(prefetchTier);\n for (const tile of prefetchCandidates) {\n if (cache.has(tile.key)) continue;\n tile.distance2 += PREFETCH_DISTANCE_PENALTY;\n tilesToSchedule.push(tile);\n }\n }\n tileScheduler.schedule(tilesToSchedule);\n\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindVertexArray(null);\n\n let renderedPoints = 0;\n let pointDrawCalls = 0;\n if (pointLayers.length > 0) {\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n for (let i = 0; i < pointLayers.length; i += 1) {\n const layer = pointLayers[i];\n if (layer.pointCount <= 0) continue;\n\n gl.useProgram(layer.pointProgram.program);\n gl.bindVertexArray(layer.pointProgram.vao);\n gl.uniformMatrix3fv(layer.pointProgram.uCamera, false, camera.getMatrix());\n gl.uniform1f(layer.pointProgram.uPointSize, layer.pointSizePx);\n gl.uniform1f(layer.pointProgram.uPointCssSize, layer.pointCssSizePx);\n gl.uniform2f(layer.pointProgram.uPointLineDash, layer.pointLineDash[0], layer.pointLineDash[1]);\n gl.uniform1f(layer.pointProgram.uPointOpacity, layer.pointOpacity);\n gl.uniform1f(layer.pointProgram.uPointStrokeScale, layer.pointStrokeScale);\n gl.uniform1f(layer.pointProgram.uPointInnerFillAlpha, layer.pointInnerFillOpacity);\n gl.uniform3f(layer.pointProgram.uPointInnerFillColor, layer.pointInnerFillColor[0], layer.pointInnerFillColor[1], layer.pointInnerFillColor[2]);\n gl.uniform1f(layer.pointProgram.uPaletteSize, layer.pointPaletteSize);\n gl.uniform1i(layer.pointProgram.uPalette, 1);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, layer.pointProgram.paletteTexture);\n if (layer.usePointIndices) {\n gl.drawElements(gl.POINTS, layer.pointCount, gl.UNSIGNED_INT, 0);\n } else {\n gl.drawArrays(gl.POINTS, 0, layer.pointCount);\n }\n renderedPoints += layer.pointCount;\n pointDrawCalls += 1;\n }\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindVertexArray(null);\n }\n\n return {\n tier,\n visible: visible.length,\n rendered: renderedTiles,\n points: renderedPoints,\n fallback: fallbackTiles.length,\n cacheHits: renderedTiles,\n cacheMisses: missingTiles.length,\n drawCalls: fallbackTiles.length + renderedTiles + pointDrawCalls,\n };\n}\n","import { createProgram, requireUniformLocation } from \"../core/gl-utils\";\nimport type { PointProgram, TileVertexProgram } from \"./wsi-renderer-types\";\n\nexport function initTileProgram(gl: WebGL2RenderingContext): TileVertexProgram {\n const vertex = `#version 300 es\n precision highp float;\n in vec2 aUnit;\n in vec2 aUv;\n uniform mat3 uCamera;\n uniform vec4 uBounds;\n out vec2 vUv;\n void main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n }`;\n\n const fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n uniform float uBrightness;\n uniform float uContrast;\n uniform float uSaturation;\n out vec4 outColor;\n void main() {\n vec4 color = texture(uTexture, vUv);\n\n color.rgb = clamp(\n (uContrast + 1.0) * color.rgb - (uContrast / 2.0),\n vec3(0.0),\n vec3(1.0)\n );\n\n float saturation = uSaturation + 1.0;\n float sr = (1.0 - saturation) * 0.2126;\n float sg = (1.0 - saturation) * 0.7152;\n float sb = (1.0 - saturation) * 0.0722;\n mat3 saturationMatrix = mat3(\n sr + saturation, sr, sr,\n sg, sg + saturation, sg,\n sb, sb, sb + saturation\n );\n color.rgb = clamp(saturationMatrix * color.rgb, vec3(0.0), vec3(1.0));\n\n color.rgb = clamp(color.rgb + uBrightness, vec3(0.0), vec3(1.0));\n outColor = color;\n }`;\n\n const program = createProgram(gl, vertex, fragment);\n const uCamera = requireUniformLocation(gl, program, \"uCamera\");\n const uBounds = requireUniformLocation(gl, program, \"uBounds\");\n const uTexture = requireUniformLocation(gl, program, \"uTexture\");\n const uBrightness = requireUniformLocation(gl, program, \"uBrightness\");\n const uContrast = requireUniformLocation(gl, program, \"uContrast\");\n const uSaturation = requireUniformLocation(gl, program, \"uSaturation\");\n\n const vao = gl.createVertexArray();\n const vbo = gl.createBuffer();\n if (!vao || !vbo) {\n throw new Error(\"buffer allocation failed\");\n }\n\n gl.bindVertexArray(vao);\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]), gl.STATIC_DRAW);\n\n const aUnit = gl.getAttribLocation(program, \"aUnit\");\n const aUv = gl.getAttribLocation(program, \"aUv\");\n if (aUnit < 0 || aUv < 0) {\n throw new Error(\"tile attribute lookup failed\");\n }\n gl.enableVertexAttribArray(aUnit);\n gl.enableVertexAttribArray(aUv);\n gl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n return {\n program,\n vao,\n vbo,\n uCamera,\n uBounds,\n uTexture,\n uBrightness,\n uContrast,\n uSaturation,\n };\n}\n\nexport function initPointProgram(gl: WebGL2RenderingContext): PointProgram {\n const pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aClass;\n in uint aFillMode;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vClass;\n flat out uint vFillMode;\n void main() {\n vec3 clip = uCamera * vec3(aPosition, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vClass = aClass;\n vFillMode = aFillMode;\n }`;\n\n const pointFragment = `#version 300 es\n precision highp float;\n const float PI = 3.14159265358979323846;\n flat in uint vClass;\n flat in uint vFillMode;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\n uniform float uPointCssSize;\n uniform float uPointOpacity;\n uniform float uPointStrokeScale;\n uniform float uPointInnerFillAlpha;\n uniform vec3 uPointInnerFillColor;\n uniform vec2 uPointLineDash;\n out vec4 outColor;\n void main() {\n vec2 pc = gl_PointCoord * 2.0 - 1.0;\n float r = length(pc);\n if (r > 1.0) discard;\n\n float idx = clamp(float(vClass), 0.0, max(0.0, uPaletteSize - 1.0));\n vec2 uv = vec2((idx + 0.5) / uPaletteSize, 0.5);\n vec4 color = texture(uPalette, uv);\n if (color.a <= 0.0) discard;\n\n float aa = 1.5 / max(1.0, uPointSize);\n float pointOpacity = clamp(uPointOpacity, 0.0, 1.0);\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n if (vFillMode != 0u) {\n float alpha = outerMask * color.a * pointOpacity;\n if (alpha <= 0.001) discard;\n outColor = vec4(color.rgb * alpha, alpha);\n } else {\n float s = uPointStrokeScale;\n float ringWidth = s * mix(0.18, 0.28, smoothstep(3.0, 12.0, uPointCssSize));\n float innerRadius = 1.0 - ringWidth;\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float dashMask = 1.0;\n if (uPointLineDash.x > 0.0 && uPointLineDash.y > 0.0) {\n float angle01 = (atan(pc.y, pc.x) + PI) / (2.0 * PI);\n float circumferencePx = max(1.0, 2.0 * PI * max(0.5, uPointCssSize * 0.5));\n float dashCycle = uPointLineDash.x + uPointLineDash.y;\n float dashOffset = mod(angle01 * circumferencePx, dashCycle);\n dashMask = dashOffset <= uPointLineDash.x ? 1.0 : 0.0;\n }\n float ringAlpha = outerMask * innerMask * dashMask * color.a;\n float fillAlpha = outerMask * (1.0 - innerMask) * clamp(uPointInnerFillAlpha, 0.0, 1.0);\n float alpha = (ringAlpha + fillAlpha) * pointOpacity;\n if (alpha <= 0.001) discard;\n vec3 fillRgb = (uPointInnerFillColor / 255.0) * fillAlpha * pointOpacity;\n outColor = vec4(color.rgb * ringAlpha * pointOpacity + fillRgb, alpha);\n }\n }`;\n\n const program = createProgram(gl, pointVertex, pointFragment);\n const uCamera = requireUniformLocation(gl, program, \"uCamera\");\n const uPointSize = requireUniformLocation(gl, program, \"uPointSize\");\n const uPointCssSize = requireUniformLocation(gl, program, \"uPointCssSize\");\n const uPointOpacity = requireUniformLocation(gl, program, \"uPointOpacity\");\n const uPointStrokeScale = requireUniformLocation(gl, program, \"uPointStrokeScale\");\n const uPointInnerFillAlpha = requireUniformLocation(gl, program, \"uPointInnerFillAlpha\");\n const uPointInnerFillColor = requireUniformLocation(gl, program, \"uPointInnerFillColor\");\n const uPalette = requireUniformLocation(gl, program, \"uPalette\");\n const uPaletteSize = requireUniformLocation(gl, program, \"uPaletteSize\");\n const uPointLineDash = requireUniformLocation(gl, program, \"uPointLineDash\");\n\n const vao = gl.createVertexArray();\n const posBuffer = gl.createBuffer();\n const classBuffer = gl.createBuffer();\n const fillModeBuffer = gl.createBuffer();\n const indexBuffer = gl.createBuffer();\n const paletteTexture = gl.createTexture();\n if (!vao || !posBuffer || !classBuffer || !fillModeBuffer || !indexBuffer || !paletteTexture) {\n throw new Error(\"point buffer allocation failed\");\n }\n\n gl.bindVertexArray(vao);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const posLoc = gl.getAttribLocation(program, \"aPosition\");\n if (posLoc < 0) {\n throw new Error(\"point position attribute not found\");\n }\n gl.enableVertexAttribArray(posLoc);\n gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, classBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const classLoc = gl.getAttribLocation(program, \"aClass\");\n if (classLoc < 0) {\n throw new Error(\"point class attribute not found\");\n }\n gl.enableVertexAttribArray(classLoc);\n gl.vertexAttribIPointer(classLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, fillModeBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n const fillModeLoc = gl.getAttribLocation(program, \"aFillMode\");\n if (fillModeLoc < 0) {\n throw new Error(\"point fill mode attribute not found\");\n }\n gl.enableVertexAttribArray(fillModeLoc);\n gl.vertexAttribIPointer(fillModeLoc, 1, gl.UNSIGNED_BYTE, 0, 0);\n\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n gl.bindVertexArray(null);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\n gl.bindTexture(gl.TEXTURE_2D, paletteTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([160, 160, 160, 255]));\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n return {\n program,\n vao,\n posBuffer,\n classBuffer,\n fillModeBuffer,\n indexBuffer,\n paletteTexture,\n uCamera,\n uPointSize,\n uPointCssSize,\n uPointOpacity,\n uPointLineDash,\n uPointStrokeScale,\n uPointInnerFillAlpha,\n uPointInnerFillColor,\n uPalette,\n uPaletteSize,\n };\n}\n","import { clamp, nowMs } from \"./utils\";\nimport type { ViewAnimationRuntimeState, ViewAnimationStartOptions } from \"./wsi-renderer-types\";\n\nexport function cancelViewAnimation(state: ViewAnimationRuntimeState): void {\n state.animation = null;\n if (state.frame !== null) {\n cancelAnimationFrame(state.frame);\n state.frame = null;\n }\n}\n\nexport function startViewAnimation(options: ViewAnimationStartOptions): void {\n const { state, camera, target, durationMs, easing, onUpdate } = options;\n const from = camera.getViewState();\n cancelViewAnimation(state);\n state.animation = {\n startMs: nowMs(),\n durationMs: Math.max(0, durationMs),\n from,\n to: target,\n easing,\n };\n\n const step = (): void => {\n const animation = state.animation;\n if (!animation) return;\n\n const elapsed = Math.max(0, nowMs() - animation.startMs);\n const rawT = animation.durationMs <= 0 ? 1 : clamp(elapsed / animation.durationMs, 0, 1);\n let eased = rawT;\n try {\n eased = animation.easing(rawT);\n } catch {\n eased = rawT;\n }\n if (!Number.isFinite(eased)) {\n eased = rawT;\n }\n eased = clamp(eased, 0, 1);\n\n camera.setViewState({\n zoom: animation.from.zoom + (animation.to.zoom - animation.from.zoom) * eased,\n offsetX: animation.from.offsetX + (animation.to.offsetX - animation.from.offsetX) * eased,\n offsetY: animation.from.offsetY + (animation.to.offsetY - animation.from.offsetY) * eased,\n rotationDeg: animation.from.rotationDeg + (animation.to.rotationDeg - animation.from.rotationDeg) * eased,\n });\n onUpdate();\n\n if (rawT >= 1) {\n state.animation = null;\n state.frame = null;\n return;\n }\n\n state.frame = requestAnimationFrame(step);\n };\n\n state.frame = requestAnimationFrame(step);\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { WsiImageSource, WsiViewState } from \"./types\";\nimport { clamp } from \"./utils\";\nimport { toRadians } from \"./wsi-normalize\";\n\nexport function resolveDefaultZoomBounds(fitZoom: number): { minZoom: number; maxZoom: number } {\n const minZoom = Math.max(fitZoom * 0.5, 1e-6);\n const maxZoom = Math.max(1, fitZoom * 8);\n return {\n minZoom,\n maxZoom: Math.max(minZoom, maxZoom),\n };\n}\n\nexport function resolveZoomBounds(fitZoom: number, minZoomOverride: number | null, maxZoomOverride: number | null): { minZoom: number; maxZoom: number } {\n const defaults = resolveDefaultZoomBounds(fitZoom);\n let minZoom = minZoomOverride ?? defaults.minZoom;\n let maxZoom = maxZoomOverride ?? defaults.maxZoom;\n minZoom = Math.max(1e-6, minZoom);\n maxZoom = Math.max(1e-6, maxZoom);\n if (minZoom > maxZoom) {\n minZoom = maxZoom;\n }\n return { minZoom, maxZoom };\n}\n\nexport function resolveTargetViewState(\n camera: OrthoCamera,\n minZoom: number,\n maxZoom: number,\n next: Partial<WsiViewState>,\n clampViewState: () => void,\n): WsiViewState {\n const current = camera.getViewState();\n const candidate: WsiViewState = {\n zoom: typeof next.zoom === \"number\" && Number.isFinite(next.zoom) ? clamp(next.zoom, minZoom, maxZoom) : current.zoom,\n offsetX: typeof next.offsetX === \"number\" && Number.isFinite(next.offsetX) ? next.offsetX : current.offsetX,\n offsetY: typeof next.offsetY === \"number\" && Number.isFinite(next.offsetY) ? next.offsetY : current.offsetY,\n rotationDeg: typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg) ? next.rotationDeg : current.rotationDeg,\n };\n\n camera.setViewState(candidate);\n clampViewState();\n const target = camera.getViewState();\n camera.setViewState(current);\n return target;\n}\n\nexport function computeFitToImageTarget(\n source: WsiImageSource,\n viewportWidth: number,\n viewportHeight: number,\n minZoom: number,\n maxZoom: number,\n rotationDeg = 0,\n): { fitZoom: number; target: WsiViewState } {\n const zoom = Math.min(viewportWidth / source.width, viewportHeight / source.height);\n const safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n const clampedZoom = clamp(safeZoom, minZoom, maxZoom);\n const visibleWorldW = viewportWidth / clampedZoom;\n const visibleWorldH = viewportHeight / clampedZoom;\n\n return {\n fitZoom: safeZoom,\n target: {\n zoom: clampedZoom,\n offsetX: (source.width - visibleWorldW) * 0.5,\n offsetY: (source.height - visibleWorldH) * 0.5,\n rotationDeg,\n },\n };\n}\n\nexport function computeZoomByTarget(\n camera: OrthoCamera,\n minZoom: number,\n maxZoom: number,\n factor: number,\n screenX: number,\n screenY: number,\n): Partial<WsiViewState> | null {\n const state = camera.getViewState();\n const nextZoom = clamp(state.zoom * factor, minZoom, maxZoom);\n if (nextZoom === state.zoom) return null;\n\n const [worldX, worldY] = camera.screenToWorld(screenX, screenY);\n const vp = camera.getViewportSize();\n const dx = screenX - vp.width * 0.5;\n const dy = screenY - vp.height * 0.5;\n const rad = toRadians(state.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n const worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n const nextCenterX = worldX - worldDx;\n const nextCenterY = worldY - worldDy;\n\n return {\n zoom: nextZoom,\n offsetX: nextCenterX - vp.width / (2 * nextZoom),\n offsetY: nextCenterY - vp.height / (2 * nextZoom),\n };\n}\n\nexport function computeZoomToTarget(\n camera: OrthoCamera,\n minZoom: number,\n maxZoom: number,\n targetZoom: number,\n screenX: number,\n screenY: number,\n): Partial<WsiViewState> | null {\n const state = camera.getViewState();\n const nextZoom = clamp(targetZoom, minZoom, maxZoom);\n if (nextZoom === state.zoom) return null;\n\n const [worldX, worldY] = camera.screenToWorld(screenX, screenY);\n const vp = camera.getViewportSize();\n const dx = screenX - vp.width * 0.5;\n const dy = screenY - vp.height * 0.5;\n const rad = toRadians(state.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n const worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n const nextCenterX = worldX - worldDx;\n const nextCenterY = worldY - worldDy;\n\n return {\n zoom: nextZoom,\n offsetX: nextCenterX - vp.width / (2 * nextZoom),\n offsetY: nextCenterY - vp.height / (2 * nextZoom),\n };\n}\n","import type { OrthoCamera } from \"../core/ortho-camera\";\nimport type { WsiViewState } from \"./types\";\nimport { clamp, nowMs } from \"./utils\";\nimport { linearEasing, toRadians } from \"./wsi-normalize\";\nimport type { ViewAnimationRuntimeState } from \"./wsi-renderer-types\";\n\nexport const SNAP_ZOOM_DURATION_MS = 250;\n\nexport function normalizeZoomSnaps(magnifications: number[] | null | undefined, mpp: number | undefined): number[] {\n if (!magnifications || magnifications.length === 0) return [];\n if (!mpp || mpp <= 0) return [];\n const maxMag = 10 / mpp;\n return magnifications\n .map(mag => mag / maxMag)\n .filter(z => Number.isFinite(z) && z > 0)\n .sort((a, b) => a - b);\n}\n\nexport type SnapZoomResult = { type: \"snap\"; zoom: number } | { type: \"fit\" } | null;\n\nexport function resolveSnapTarget(validSnaps: number[], currentZoom: number, direction: \"in\" | \"out\", fitAsMin: boolean): SnapZoomResult {\n if (validSnaps.length === 0) return null;\n\n const epsilon = Math.max(currentZoom * 0.005, 1e-8);\n\n if (direction === \"in\") {\n for (const snap of validSnaps) {\n if (snap > currentZoom + epsilon) {\n return { type: \"snap\", zoom: snap };\n }\n }\n return null;\n }\n\n for (let i = validSnaps.length - 1; i >= 0; i--) {\n if (validSnaps[i] < currentZoom - epsilon) {\n return { type: \"snap\", zoom: validSnaps[i] };\n }\n }\n\n if (fitAsMin && currentZoom <= validSnaps[0] + epsilon) {\n return { type: \"fit\" };\n }\n\n return null;\n}\n\nexport interface ZoomPivotAnimationContext {\n camera: OrthoCamera;\n viewAnimationState: ViewAnimationRuntimeState;\n minZoom: number;\n maxZoom: number;\n cancelViewAnimation: () => void;\n clampViewState: () => void;\n onViewStateChange: (state: WsiViewState) => void;\n requestRender: () => void;\n}\n\nexport function startZoomPivotAnimation(ctx: ZoomPivotAnimationContext, targetZoom: number, pivotScreenX: number, pivotScreenY: number, durationMs: number): void {\n const fromState = ctx.camera.getViewState();\n const [pivotWorldX, pivotWorldY] = ctx.camera.screenToWorld(pivotScreenX, pivotScreenY);\n const vp = ctx.camera.getViewportSize();\n const safeTargetZoom = clamp(targetZoom, ctx.minZoom, ctx.maxZoom);\n if (safeTargetZoom === fromState.zoom) return;\n\n const rad = toRadians(fromState.rotationDeg);\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n const screenDx = pivotScreenX - vp.width * 0.5;\n const screenDy = pivotScreenY - vp.height * 0.5;\n\n ctx.cancelViewAnimation();\n\n const computeOffsetForZoom = (z: number): { offsetX: number; offsetY: number } => {\n const worldDx = (screenDx / z) * cos - (screenDy / z) * sin;\n const worldDy = (screenDx / z) * sin + (screenDy / z) * cos;\n return {\n offsetX: pivotWorldX - worldDx - vp.width / (2 * z),\n offsetY: pivotWorldY - worldDy - vp.height / (2 * z),\n };\n };\n\n const finalOffset = computeOffsetForZoom(safeTargetZoom);\n ctx.viewAnimationState.animation = {\n startMs: nowMs(),\n durationMs: Math.max(0, durationMs),\n from: fromState,\n to: { zoom: safeTargetZoom, offsetX: finalOffset.offsetX, offsetY: finalOffset.offsetY, rotationDeg: fromState.rotationDeg },\n easing: linearEasing,\n };\n\n const step = (): void => {\n const animation = ctx.viewAnimationState.animation;\n if (!animation) return;\n\n const elapsed = Math.max(0, nowMs() - animation.startMs);\n const rawT = durationMs <= 0 ? 1 : clamp(elapsed / durationMs, 0, 1);\n const eased = clamp(rawT * rawT * (3 - 2 * rawT), 0, 1);\n\n const z = fromState.zoom + (safeTargetZoom - fromState.zoom) * eased;\n const { offsetX, offsetY } = computeOffsetForZoom(z);\n\n ctx.camera.setViewState({ zoom: z, offsetX, offsetY, rotationDeg: fromState.rotationDeg });\n\n const isComplete = rawT >= 1;\n if (isComplete) {\n ctx.clampViewState();\n ctx.viewAnimationState.animation = null;\n ctx.viewAnimationState.frame = null;\n }\n\n ctx.onViewStateChange(ctx.camera.getViewState());\n ctx.requestRender();\n\n if (!isComplete) {\n ctx.viewAnimationState.frame = requestAnimationFrame(step);\n }\n };\n\n ctx.viewAnimationState.frame = requestAnimationFrame(step);\n}\n","import { OrthoCamera } from \"../core/ortho-camera\";\nimport { observeDevicePixelRatioChanges } from \"./device-pixel-ratio\";\nimport { TileScheduler } from \"./tile-scheduler\";\nimport type { WsiImageColorSettings, WsiImageSource, WsiPointData, WsiRenderStats, WsiViewState } from \"./types\";\nimport { calcViewingMagnification, clamp, isSameViewState, nowMs } from \"./utils\";\nimport { addRendererCanvasEventListeners, type RendererCanvasHandlers, removeRendererCanvasEventListeners, resizeCanvasViewport } from \"./wsi-canvas-lifecycle\";\nimport { cancelDrag as cancelInputDrag, createRendererInputHandlers } from \"./wsi-input-handlers\";\nimport { applyWheelSnapDelta, applyWheelZoomDelta } from \"./wsi-interaction\";\nimport { destroyRenderer, handleContextLost } from \"./wsi-lifecycle-ops\";\nimport {\n arePointSizeMagnificationStopsEqual,\n arePointSizeStopsEqual,\n arePointWeightMagnificationStopsEqual,\n clonePointSizeMagnificationStops,\n clonePointSizeStops,\n clonePointWeightMagnificationStops,\n DEFAULT_POINT_INNER_FILL_COLOR,\n DEFAULT_POINT_SIZE_STOPS,\n DEFAULT_ROTATION_DRAG_SENSITIVITY,\n linearEasing,\n MAX_POINT_SIZE_PX,\n MIN_POINT_SIZE_PX,\n normalizePointInnerFillColor,\n normalizePointInnerFillOpacity,\n normalizePointLineDash,\n normalizePointOpacity,\n normalizePointSizeMagnificationStops,\n normalizePointSizeStops,\n normalizePointWeightMagnificationStops,\n normalizeStrokeScale,\n normalizeTransitionEasing,\n normalizeViewTransitionDuration,\n normalizeZoomOverride,\n resolvePointSizeByMagnificationStops,\n resolvePointSizeByZoomStops,\n resolvePointWeightByMagnificationStops,\n toNormalizedImageColorSettings,\n} from \"./wsi-normalize\";\nimport type { PointBufferRuntime } from \"./wsi-point-data\";\nimport { setPointData as setManagedPointData, setPointPalette as setManagedPointPalette } from \"./wsi-point-data\";\nimport type { RenderPointLayer } from \"./wsi-render-pass\";\nimport { renderFrame } from \"./wsi-render-pass\";\nimport type {\n Bounds,\n CachedTile,\n InteractionState,\n NormalizedImageColorSettings,\n PointProgram,\n PointSizeByMagnification,\n PointSizeByZoom,\n PointSizeMagnificationStop,\n PointSizeStop,\n PointWeightByMagnification,\n PointWeightMagnificationStop,\n TileVertexProgram,\n ViewAnimationRuntimeState,\n WorldPoint,\n WsiTileErrorEvent,\n WsiTileRendererOptions,\n WsiViewTransitionOptions,\n ZoomSnapState,\n} from \"./wsi-renderer-types\";\nimport { initPointProgram, initTileProgram } from \"./wsi-shaders\";\nimport { handleTileLoaded as cacheTileLoaded } from \"./wsi-tile-cache\";\nimport {\n clampViewState as clampManagedViewState,\n getViewBounds as getManagedViewBounds,\n getVisibleTiles as getManagedVisibleTiles,\n getVisibleTilesForTier as getManagedVisibleTilesForTier,\n intersectsBounds as intersectsManagedBounds,\n} from \"./wsi-tile-visibility\";\nimport { cancelViewAnimation as cancelManagedViewAnimation, startViewAnimation } from \"./wsi-view-animation\";\nimport { computeFitToImageTarget, computeZoomByTarget, computeZoomToTarget, resolveTargetViewState as resolveManagedTargetViewState, resolveZoomBounds } from \"./wsi-view-ops\";\nimport { normalizeZoomSnaps, resolveSnapTarget, SNAP_ZOOM_DURATION_MS, startZoomPivotAnimation, type ZoomPivotAnimationContext } from \"./wsi-zoom-snap\";\n\nexport type {\n PointSizeByMagnification,\n PointSizeByZoom,\n PointWeightByMagnification,\n WsiTileErrorEvent,\n WsiTileRendererOptions,\n WsiTileSchedulerConfig,\n WsiViewTransitionOptions,\n} from \"./wsi-renderer-types\";\n\nconst DEFAULT_POINT_LAYER_ID = \"__default_point_layer__\";\n\ninterface ManagedPointLayerState {\n id: string;\n program: PointProgram;\n runtime: PointBufferRuntime;\n pointSizeZoomStops: PointSizeStop[];\n pointSizeMagnificationStops: PointSizeMagnificationStop[] | null;\n pointWeightMagnificationStops: PointWeightMagnificationStop[] | null;\n pointOpacity: number;\n pointLineDash: [number, number];\n pointStrokeScale: number;\n pointInnerFillOpacity: number;\n pointInnerFillColor: [number, number, number];\n}\n\nexport class WsiTileRenderer {\n private readonly canvas: HTMLCanvasElement;\n private readonly source: WsiImageSource;\n private readonly gl: WebGL2RenderingContext;\n private readonly camera = new OrthoCamera();\n private readonly onViewStateChange?: (next: WsiViewState) => void;\n private readonly onStats?: (stats: WsiRenderStats) => void;\n private readonly onTileError?: (event: WsiTileErrorEvent) => void;\n private readonly onContextLost?: () => void;\n private readonly onContextRestored?: () => void;\n private readonly resizeObserver: ResizeObserver;\n private readonly removeDprListener: () => void;\n private tileProgram: TileVertexProgram;\n private readonly tileScheduler: TileScheduler;\n\n private authToken: string;\n private destroyed = false;\n private contextLost = false;\n private frame: number | null = null;\n private frameSerial = 0;\n private interactionState: InteractionState = {\n dragging: false,\n mode: \"none\",\n rotateLastAngleRad: null,\n pointerId: null,\n lastPointerX: 0,\n lastPointerY: 0,\n };\n private interactionLocked = false;\n private ctrlDragRotate = true;\n private rotationDragSensitivityDegPerPixel = DEFAULT_ROTATION_DRAG_SENSITIVITY;\n private maxCacheTiles: number;\n private fitZoom = 1;\n private initialRotationDeg = 0;\n private minZoom = 1e-6;\n private maxZoom = 1;\n private minZoomOverride: number | null = null;\n private maxZoomOverride: number | null = null;\n private viewTransitionDurationMs = 0;\n private viewTransitionEasing: (t: number) => number = linearEasing;\n private viewAnimationState: ViewAnimationRuntimeState = {\n animation: null,\n frame: null,\n };\n private readonly pointLayers = new Map<string, ManagedPointLayerState>();\n private defaultPointSizeZoomStops: PointSizeStop[] = clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n private defaultPointSizeMagnificationStops: PointSizeMagnificationStop[] | null = null;\n private defaultPointWeightMagnificationStops: PointWeightMagnificationStop[] | null = null;\n private defaultPointOpacity = 1.0;\n private defaultPointLineDash: [number, number] = [1, 0];\n private defaultPointStrokeScale = 1.0;\n private defaultPointInnerFillOpacity = 0;\n private defaultPointInnerFillColor: [number, number, number] = [...DEFAULT_POINT_INNER_FILL_COLOR];\n private imageColorSettings: NormalizedImageColorSettings = {\n brightness: 0,\n contrast: 0,\n saturation: 0,\n };\n private cache = new Map<string, CachedTile>();\n private zoomSnaps: number[] = [];\n private zoomSnapFitAsMin = false;\n private zoomSnapState: ZoomSnapState = { accumulatedDelta: 0, lastSnapTimeMs: 0, blockedDirection: null };\n private panExtentX = 0.2;\n private panExtentY = 0.2;\n\n private readonly boundPointerDown: (event: PointerEvent) => void;\n private readonly boundPointerMove: (event: PointerEvent) => void;\n private readonly boundPointerUp: (event: PointerEvent) => void;\n private readonly boundWheel: (event: WheelEvent) => void;\n private readonly boundDoubleClick: (event: MouseEvent) => void;\n private readonly boundContextMenu: (event: MouseEvent) => void;\n private readonly boundContextLost: (event: Event) => void;\n private readonly boundContextRestored: (event: Event) => void;\n\n private getCanvasHandlers(): RendererCanvasHandlers {\n return {\n pointerDown: this.boundPointerDown,\n pointerMove: this.boundPointerMove,\n pointerUp: this.boundPointerUp,\n wheel: this.boundWheel,\n doubleClick: this.boundDoubleClick,\n contextMenu: this.boundContextMenu,\n contextLost: this.boundContextLost,\n contextRestored: this.boundContextRestored,\n };\n }\n\n constructor(canvas: HTMLCanvasElement, source: WsiImageSource, options: WsiTileRendererOptions = {}) {\n this.canvas = canvas;\n this.source = source;\n this.onViewStateChange = options.onViewStateChange;\n this.onStats = options.onStats;\n this.onTileError = options.onTileError;\n this.onContextLost = options.onContextLost;\n this.onContextRestored = options.onContextRestored;\n this.authToken = options.authToken ?? \"\";\n this.maxCacheTiles = Math.max(32, Math.floor(options.maxCacheTiles ?? 320));\n this.initialRotationDeg = typeof options.initialRotationDeg === \"number\" && Number.isFinite(options.initialRotationDeg) ? options.initialRotationDeg : 0;\n this.ctrlDragRotate = options.ctrlDragRotate ?? true;\n this.rotationDragSensitivityDegPerPixel =\n typeof options.rotationDragSensitivityDegPerPixel === \"number\" && Number.isFinite(options.rotationDragSensitivityDegPerPixel)\n ? Math.max(0, options.rotationDragSensitivityDegPerPixel)\n : DEFAULT_ROTATION_DRAG_SENSITIVITY;\n this.defaultPointSizeZoomStops = normalizePointSizeStops(options.pointSizeByZoom);\n this.defaultPointSizeMagnificationStops = normalizePointSizeMagnificationStops(options.pointSizeByMagnification);\n this.defaultPointWeightMagnificationStops = normalizePointWeightMagnificationStops(options.pointWeightByMagnification);\n this.defaultPointOpacity = normalizePointOpacity(options.pointOpacity);\n this.defaultPointStrokeScale = normalizeStrokeScale(options.pointStrokeScale);\n this.defaultPointInnerFillOpacity = normalizePointInnerFillOpacity(options.pointInnerFillOpacity);\n this.defaultPointInnerFillColor = normalizePointInnerFillColor(options.pointInnerFillColor);\n this.imageColorSettings = toNormalizedImageColorSettings(options.imageColorSettings);\n this.minZoomOverride = normalizeZoomOverride(options.minZoom);\n this.maxZoomOverride = normalizeZoomOverride(options.maxZoom);\n this.viewTransitionDurationMs = normalizeViewTransitionDuration(options.viewTransition?.duration);\n this.viewTransitionEasing = normalizeTransitionEasing(options.viewTransition?.easing);\n this.zoomSnaps = normalizeZoomSnaps(options.zoomSnaps, this.source.mpp);\n this.zoomSnapFitAsMin = Boolean(options.zoomSnapFitAsMin);\n this.applyPanExtent(options.panExtent);\n\n const gl = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n powerPreference: \"high-performance\",\n preserveDrawingBuffer: options.preserveDrawingBuffer ?? false,\n });\n if (!gl) {\n throw new Error(\"WebGL2 not supported\");\n }\n this.gl = gl;\n\n this.tileProgram = initTileProgram(this.gl);\n this.tileScheduler = new TileScheduler({\n authToken: this.authToken,\n maxConcurrency: options.tileScheduler?.maxConcurrency ?? 12,\n maxRetries: options.tileScheduler?.maxRetries ?? 2,\n retryBaseDelayMs: options.tileScheduler?.retryBaseDelayMs ?? 120,\n retryMaxDelayMs: options.tileScheduler?.retryMaxDelayMs ?? 1200,\n onTileLoad: (tile, bitmap) =>\n cacheTileLoaded({\n gl: this.gl,\n cache: this.cache,\n tile,\n bitmap,\n frameSerial: this.frameSerial,\n maxCacheTiles: this.maxCacheTiles,\n destroyed: this.destroyed,\n contextLost: this.contextLost,\n requestRender: () => this.requestRender(),\n }),\n onTileError: (tile, error, attemptCount) => {\n this.onTileError?.({ tile, error, attemptCount });\n console.warn(\"tile load failed\", tile.url, error);\n },\n });\n\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(canvas);\n this.removeDprListener = observeDevicePixelRatioChanges(() => this.resize());\n\n const inputHandlers = createRendererInputHandlers({\n canvas: this.canvas,\n state: this.interactionState,\n getInteractionLocked: () => this.interactionLocked,\n getCtrlDragRotate: () => this.ctrlDragRotate,\n getRotationDragSensitivityDegPerPixel: () => this.rotationDragSensitivityDegPerPixel,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n camera: this.camera,\n source: this.source,\n emitViewState: () => this.onViewStateChange?.(this.camera.getViewState()),\n requestRender: () => this.requestRender(),\n getPanExtentX: () => this.panExtentX,\n getPanExtentY: () => this.panExtentY,\n zoomBy: (factor, x, y) => this.zoomBy(factor, x, y),\n getUseZoomSnaps: () => this.zoomSnaps.length > 0,\n onSnapZoom: (direction, x, y) => this.handleSnapZoom(direction, x, y),\n zoomSnapState: this.zoomSnapState,\n });\n this.boundPointerDown = inputHandlers.pointerDown;\n this.boundPointerMove = inputHandlers.pointerMove;\n this.boundPointerUp = inputHandlers.pointerUp;\n this.boundWheel = inputHandlers.wheel;\n this.boundDoubleClick = inputHandlers.doubleClick;\n this.boundContextMenu = inputHandlers.contextMenu;\n this.boundContextLost = (event: Event) => this.onWebGlContextLost(event);\n this.boundContextRestored = (event: Event) => this.onWebGlContextRestored(event);\n\n addRendererCanvasEventListeners(canvas, this.getCanvasHandlers());\n\n this.fitToImage({ duration: 0 });\n this.resize();\n }\n\n private applyZoomBounds(): void {\n const bounds = resolveZoomBounds(this.fitZoom, this.minZoomOverride, this.maxZoomOverride);\n this.minZoom = bounds.minZoom;\n this.maxZoom = bounds.maxZoom;\n }\n\n private resolveTargetViewState(next: Partial<WsiViewState>): WsiViewState {\n return resolveManagedTargetViewState(this.camera, this.minZoom, this.maxZoom, next, () => clampManagedViewState(this.camera, this.source, this.panExtentX, this.panExtentY));\n }\n\n private cancelViewAnimation(): void {\n cancelManagedViewAnimation(this.viewAnimationState);\n }\n\n private startViewAnimation(target: WsiViewState, durationMs: number, easing: (t: number) => number): void {\n this.resetZoomSnapStateForZoomChange(this.camera.getViewState().zoom, target.zoom);\n startViewAnimation({\n state: this.viewAnimationState,\n camera: this.camera,\n target,\n durationMs,\n easing,\n onUpdate: () => {\n clampManagedViewState(this.camera, this.source, this.panExtentX, this.panExtentY);\n this.onViewStateChange?.(this.camera.getViewState());\n this.requestRender();\n },\n });\n }\n\n private createPointBufferRuntime(): PointBufferRuntime {\n return {\n pointCount: 0,\n usePointIndices: false,\n pointBuffersDirty: true,\n lastPointData: null,\n zeroFillModes: new Uint8Array(0),\n lastPointPalette: null,\n pointPaletteSize: 1,\n };\n }\n\n private createPointLayerState(id: string): ManagedPointLayerState {\n return {\n id,\n program: initPointProgram(this.gl),\n runtime: this.createPointBufferRuntime(),\n pointSizeZoomStops: clonePointSizeStops(this.defaultPointSizeZoomStops),\n pointSizeMagnificationStops: clonePointSizeMagnificationStops(this.defaultPointSizeMagnificationStops),\n pointWeightMagnificationStops: clonePointWeightMagnificationStops(this.defaultPointWeightMagnificationStops),\n pointOpacity: this.defaultPointOpacity,\n pointLineDash: [...this.defaultPointLineDash] as [number, number],\n pointStrokeScale: this.defaultPointStrokeScale,\n pointInnerFillOpacity: this.defaultPointInnerFillOpacity,\n pointInnerFillColor: [...this.defaultPointInnerFillColor],\n };\n }\n\n private ensurePointLayer(layerId: string = DEFAULT_POINT_LAYER_ID): ManagedPointLayerState {\n const nextId = String(layerId || DEFAULT_POINT_LAYER_ID);\n const existing = this.pointLayers.get(nextId);\n if (existing) return existing;\n\n const created = this.createPointLayerState(nextId);\n this.pointLayers.set(nextId, created);\n return created;\n }\n\n private deletePointProgram(program: PointProgram): void {\n if (this.contextLost || this.gl.isContextLost()) return;\n this.gl.deleteBuffer(program.posBuffer);\n this.gl.deleteBuffer(program.classBuffer);\n this.gl.deleteBuffer(program.fillModeBuffer);\n this.gl.deleteBuffer(program.indexBuffer);\n this.gl.deleteTexture(program.paletteTexture);\n this.gl.deleteVertexArray(program.vao);\n this.gl.deleteProgram(program.program);\n }\n\n private getPointRenderLayers(): RenderPointLayer[] {\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const out: RenderPointLayer[] = [];\n for (const layer of this.pointLayers.values()) {\n const pointCssSizePx = this.getPointSize(layer.id);\n out.push({\n pointProgram: layer.program,\n pointCount: layer.runtime.pointCount,\n usePointIndices: layer.runtime.usePointIndices,\n pointPaletteSize: layer.runtime.pointPaletteSize,\n pointLineDash: layer.pointLineDash,\n pointOpacity: layer.pointOpacity,\n pointStrokeScale: this.getPointStrokeScale(layer.id),\n pointInnerFillOpacity: layer.pointInnerFillOpacity,\n pointInnerFillColor: layer.pointInnerFillColor,\n pointCssSizePx,\n pointSizePx: pointCssSizePx * dpr,\n });\n }\n return out;\n }\n\n private resetZoomSnapState(): void {\n this.zoomSnapState.accumulatedDelta = 0;\n this.zoomSnapState.lastSnapTimeMs = 0;\n this.zoomSnapState.blockedDirection = null;\n }\n\n private resetZoomSnapStateForZoomChange(currentZoom: number, targetZoom: number): void {\n if (Math.abs(currentZoom - targetZoom) < 1e-6) return;\n this.resetZoomSnapState();\n }\n\n private applyViewStateAndRender(next: WsiViewState, cancelAnimation = true): void {\n const current = this.camera.getViewState();\n if (cancelAnimation) {\n this.cancelViewAnimation();\n }\n this.resetZoomSnapStateForZoomChange(current.zoom, next.zoom);\n this.camera.setViewState(next);\n this.onViewStateChange?.(this.camera.getViewState());\n this.requestRender();\n }\n\n setAuthToken(token: string): void {\n this.authToken = String(token ?? \"\");\n this.tileScheduler.setAuthToken(this.authToken);\n }\n\n setZoomRange(minZoom: number | null | undefined, maxZoom: number | null | undefined): void {\n const nextMinOverride = normalizeZoomOverride(minZoom);\n const nextMaxOverride = normalizeZoomOverride(maxZoom);\n if (this.minZoomOverride === nextMinOverride && this.maxZoomOverride === nextMaxOverride) {\n return;\n }\n\n this.minZoomOverride = nextMinOverride;\n this.maxZoomOverride = nextMaxOverride;\n this.applyZoomBounds();\n this.resetZoomSnapState();\n\n const target = this.resolveTargetViewState({});\n const current = this.camera.getViewState();\n if (isSameViewState(current, target)) {\n return;\n }\n this.applyViewStateAndRender(target);\n }\n\n setViewTransition(options: WsiViewTransitionOptions | null | undefined): void {\n this.viewTransitionDurationMs = normalizeViewTransitionDuration(options?.duration);\n this.viewTransitionEasing = normalizeTransitionEasing(options?.easing);\n }\n\n setViewState(next: Partial<WsiViewState>, transition?: WsiViewTransitionOptions): void {\n const target = this.resolveTargetViewState(next);\n const current = this.camera.getViewState();\n if (isSameViewState(current, target)) return;\n\n const durationMs = normalizeViewTransitionDuration(transition?.duration ?? this.viewTransitionDurationMs);\n const easing = normalizeTransitionEasing(transition?.easing ?? this.viewTransitionEasing);\n if (durationMs <= 0) {\n this.applyViewStateAndRender(target);\n return;\n }\n\n this.startViewAnimation(target, durationMs, easing);\n }\n\n getViewState(): WsiViewState {\n return this.camera.getViewState();\n }\n\n getZoomRange(): { minZoom: number; maxZoom: number } {\n return { minZoom: this.minZoom, maxZoom: this.maxZoom };\n }\n\n getRegionLabelAutoLiftCapZoom(): number {\n const valid = this.zoomSnaps.filter(z => z >= this.minZoom && z <= this.maxZoom);\n if (valid.length > 0) {\n return valid[valid.length - 1];\n }\n return this.maxZoom;\n }\n\n isViewAnimating(): boolean {\n return this.viewAnimationState.animation !== null;\n }\n\n registerPointLayer(layerId: string): void {\n this.ensurePointLayer(layerId);\n }\n\n unregisterPointLayer(layerId: string): void {\n const nextId = String(layerId || DEFAULT_POINT_LAYER_ID);\n const layer = this.pointLayers.get(nextId);\n if (!layer) return;\n this.pointLayers.delete(nextId);\n this.deletePointProgram(layer.program);\n this.requestRender();\n }\n\n setPointPalette(colors: Uint8Array | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n layer.runtime = setManagedPointPalette(layer.runtime, this.gl, layer.program, this.contextLost, colors);\n if (!colors || colors.length === 0) {\n return;\n }\n this.requestRender();\n }\n\n setPointLineDash(dashed: [number, number] | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointLineDash(dashed);\n if (layer.pointLineDash[0] === next[0] && layer.pointLineDash[1] === next[1]) return;\n layer.pointLineDash = next;\n this.requestRender();\n }\n\n setPointData(points: WsiPointData | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n layer.runtime = setManagedPointData(layer.runtime, this.gl, layer.program, this.contextLost, points);\n this.requestRender();\n }\n\n setInteractionLock(locked: boolean): void {\n const next = Boolean(locked);\n if (this.interactionLocked === next) return;\n this.interactionLocked = next;\n if (next) this.cancelDrag();\n }\n\n setPointSizeByZoom(pointSizeByZoom: PointSizeByZoom | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const nextStops = normalizePointSizeStops(pointSizeByZoom);\n if (arePointSizeStopsEqual(layer.pointSizeZoomStops, nextStops)) return;\n layer.pointSizeZoomStops = nextStops;\n this.requestRender();\n }\n\n setPointSizeByMagnification(pointSizeByMagnification: PointSizeByMagnification | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const nextStops = normalizePointSizeMagnificationStops(pointSizeByMagnification);\n if (arePointSizeMagnificationStopsEqual(layer.pointSizeMagnificationStops, nextStops)) return;\n layer.pointSizeMagnificationStops = nextStops;\n this.requestRender();\n }\n\n setPointWeightByMagnification(pointWeightByMagnification: PointWeightByMagnification | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const nextStops = normalizePointWeightMagnificationStops(pointWeightByMagnification);\n if (arePointWeightMagnificationStopsEqual(layer.pointWeightMagnificationStops, nextStops)) return;\n layer.pointWeightMagnificationStops = nextStops;\n this.requestRender();\n }\n\n setPointOpacity(opacity: number | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointOpacity(opacity);\n if (layer.pointOpacity === next) return;\n layer.pointOpacity = next;\n this.requestRender();\n }\n\n setPointStrokeScale(scale: number | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizeStrokeScale(scale);\n if (layer.pointStrokeScale === next) return;\n layer.pointStrokeScale = next;\n this.requestRender();\n }\n\n setPointInnerFillOpacity(opacity: number | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointInnerFillOpacity(opacity);\n if (layer.pointInnerFillOpacity === next) return;\n layer.pointInnerFillOpacity = next;\n this.requestRender();\n }\n\n setPointInnerFillColor(color: string | null | undefined, layerId: string = DEFAULT_POINT_LAYER_ID): void {\n const layer = this.ensurePointLayer(layerId);\n const next = normalizePointInnerFillColor(color);\n if (layer.pointInnerFillColor[0] === next[0] && layer.pointInnerFillColor[1] === next[1] && layer.pointInnerFillColor[2] === next[2]) {\n return;\n }\n layer.pointInnerFillColor = next;\n this.requestRender();\n }\n\n setImageColorSettings(settings: WsiImageColorSettings | null | undefined): void {\n const next = toNormalizedImageColorSettings(settings);\n const prev = this.imageColorSettings;\n if (prev.brightness === next.brightness && prev.contrast === next.contrast && prev.saturation === next.saturation) {\n return;\n }\n this.imageColorSettings = next;\n this.requestRender();\n }\n\n cancelDrag(): void {\n cancelInputDrag(this.canvas, this.interactionState);\n }\n\n screenToWorld(clientX: number, clientY: number): [number, number] {\n const rect = this.canvas.getBoundingClientRect();\n const sx = clientX - rect.left;\n const sy = clientY - rect.top;\n return this.camera.screenToWorld(sx, sy);\n }\n\n worldToScreen(worldX: number, worldY: number): [number, number] {\n return this.camera.worldToScreen(worldX, worldY);\n }\n\n setViewCenter(worldX: number, worldY: number, transition?: WsiViewTransitionOptions): void {\n if (!Number.isFinite(worldX) || !Number.isFinite(worldY)) return;\n const state = this.camera.getViewState();\n const zoom = Math.max(1e-6, state.zoom);\n const vp = this.camera.getViewportSize();\n this.setViewState(\n {\n offsetX: worldX - vp.width / (2 * zoom),\n offsetY: worldY - vp.height / (2 * zoom),\n },\n transition\n );\n }\n\n getViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n return this.camera.getViewCorners();\n }\n\n getInitialRotationDeg(): number {\n return this.initialRotationDeg;\n }\n\n getViewBounds(): Bounds {\n return getManagedViewBounds(this.camera);\n }\n\n resetRotation(transition?: WsiViewTransitionOptions): void {\n const state = this.camera.getViewState();\n if (Math.abs(state.rotationDeg - this.initialRotationDeg) < 1e-6) return;\n this.setViewState({ rotationDeg: this.initialRotationDeg }, transition);\n }\n\n getPointSize(layerId: string = DEFAULT_POINT_LAYER_ID): number {\n const layer = this.pointLayers.get(String(layerId || DEFAULT_POINT_LAYER_ID));\n const magnificationStops = layer?.pointSizeMagnificationStops ?? this.defaultPointSizeMagnificationStops;\n if (magnificationStops && magnificationStops.length > 0) {\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const magnification = calcViewingMagnification(this.source.mpp ?? 0, zoom);\n if (magnification > 0) {\n const size = resolvePointSizeByMagnificationStops(magnification, magnificationStops);\n return clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n }\n }\n\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n const stops = layer?.pointSizeZoomStops ?? this.defaultPointSizeZoomStops;\n const size = resolvePointSizeByZoomStops(continuousZoom, stops);\n return clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n }\n\n getPointSizeByZoom(layerId: string = DEFAULT_POINT_LAYER_ID): number {\n return this.getPointSize(layerId);\n }\n\n getPointStrokeScale(layerId: string = DEFAULT_POINT_LAYER_ID): number {\n const layer = this.pointLayers.get(String(layerId || DEFAULT_POINT_LAYER_ID));\n const magnificationStops = layer?.pointWeightMagnificationStops ?? this.defaultPointWeightMagnificationStops;\n if (magnificationStops && magnificationStops.length > 0) {\n const zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n const magnification = calcViewingMagnification(this.source.mpp ?? 0, zoom);\n if (magnification > 0) {\n return normalizeStrokeScale(resolvePointWeightByMagnificationStops(magnification, magnificationStops));\n }\n }\n return layer?.pointStrokeScale ?? this.defaultPointStrokeScale;\n }\n\n fitToImage(transition?: WsiViewTransitionOptions): void {\n const rect = this.canvas.getBoundingClientRect();\n const vw = Math.max(1, rect.width || 1);\n const vh = Math.max(1, rect.height || 1);\n const fitTarget = computeFitToImageTarget(this.source, vw, vh, this.minZoom, this.maxZoom, this.initialRotationDeg);\n this.fitZoom = fitTarget.fitZoom;\n this.applyZoomBounds();\n this.setViewState(fitTarget.target, transition);\n }\n\n zoomBy(factor: number, screenX: number, screenY: number, transition?: WsiViewTransitionOptions): void {\n const target = computeZoomByTarget(this.camera, this.minZoom, this.maxZoom, factor, screenX, screenY);\n if (!target) return;\n this.setViewState(target, transition);\n }\n\n handleWheelZoom(deltaY: number, screenX: number, screenY: number): void {\n if (this.zoomSnaps.length > 0) {\n applyWheelSnapDelta(deltaY, screenX, screenY, this.zoomSnapState, (direction, x, y) => this.handleSnapZoom(direction, x, y));\n return;\n }\n applyWheelZoomDelta(deltaY, screenX, screenY, (factor, x, y) => this.zoomBy(factor, x, y));\n }\n\n zoomTo(zoom: number, screenX: number, screenY: number, transition?: WsiViewTransitionOptions): void {\n const target = computeZoomToTarget(this.camera, this.minZoom, this.maxZoom, zoom, screenX, screenY);\n if (!target) return;\n this.setViewState(target, transition);\n }\n\n setZoomSnaps(magnifications: number[] | null | undefined, fitAsMin?: boolean): void {\n this.zoomSnaps = normalizeZoomSnaps(magnifications, this.source.mpp);\n this.zoomSnapFitAsMin = Boolean(fitAsMin);\n this.resetZoomSnapState();\n }\n\n setPanExtent(extent: number | { x: number; y: number } | null | undefined): void {\n this.applyPanExtent(extent);\n }\n\n private applyPanExtent(extent: number | { x: number; y: number } | null | undefined): void {\n if (typeof extent === \"number\" && Number.isFinite(extent)) {\n this.panExtentX = Math.max(0, extent);\n this.panExtentY = Math.max(0, extent);\n } else if (extent != null && typeof extent === \"object\") {\n this.panExtentX = typeof extent.x === \"number\" && Number.isFinite(extent.x) ? Math.max(0, extent.x) : 0.2;\n this.panExtentY = typeof extent.y === \"number\" && Number.isFinite(extent.y) ? Math.max(0, extent.y) : 0.2;\n } else {\n this.panExtentX = 0.2;\n this.panExtentY = 0.2;\n }\n }\n\n private getZoomPivotAnimationContext(): ZoomPivotAnimationContext {\n return {\n camera: this.camera,\n viewAnimationState: this.viewAnimationState,\n minZoom: this.minZoom,\n maxZoom: this.maxZoom,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n clampViewState: () => clampManagedViewState(this.camera, this.source, this.panExtentX, this.panExtentY),\n onViewStateChange: state => this.onViewStateChange?.(state),\n requestRender: () => this.requestRender(),\n };\n }\n\n private handleSnapZoom(direction: \"in\" | \"out\", screenX: number, screenY: number): boolean {\n const ongoing = this.viewAnimationState.animation;\n const baseZoom = ongoing ? ongoing.to.zoom : this.camera.getViewState().zoom;\n const validSnaps = this.zoomSnaps.filter(z => z >= this.minZoom && z <= this.maxZoom);\n const result = resolveSnapTarget(validSnaps, baseZoom, direction, this.zoomSnapFitAsMin);\n if (!result) return false;\n\n let targetZoom: number;\n\n if (result.type === \"fit\") {\n const rect = this.canvas.getBoundingClientRect();\n const vw = Math.max(1, rect.width || 1);\n const vh = Math.max(1, rect.height || 1);\n const fitTarget = computeFitToImageTarget(this.source, vw, vh, this.minZoom, this.maxZoom, this.initialRotationDeg);\n this.fitZoom = fitTarget.fitZoom;\n this.applyZoomBounds();\n targetZoom = fitTarget.target.zoom;\n } else {\n targetZoom = result.zoom;\n }\n\n const epsilon = Math.max(Math.abs(targetZoom) * 0.005, 1e-8);\n\n if (ongoing) {\n const ongoingDirection: \"in\" | \"out\" | null = ongoing.to.zoom > ongoing.from.zoom + epsilon ? \"in\" : ongoing.to.zoom < ongoing.from.zoom - epsilon ? \"out\" : null;\n if (ongoingDirection === direction && Math.abs(ongoing.to.zoom - targetZoom) <= epsilon) {\n return false;\n }\n } else if (Math.abs(baseZoom - targetZoom) <= epsilon) {\n return false;\n }\n\n startZoomPivotAnimation(this.getZoomPivotAnimationContext(), targetZoom, screenX, screenY, SNAP_ZOOM_DURATION_MS);\n return true;\n }\n\n render(): void {\n if (this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n const frameStartMs = this.onStats ? nowMs() : 0;\n this.frameSerial += 1;\n\n const result = renderFrame({\n gl: this.gl,\n camera: this.camera,\n source: this.source,\n cache: this.cache,\n frameSerial: this.frameSerial,\n tileProgram: this.tileProgram,\n imageColorSettings: this.imageColorSettings,\n pointLayers: this.getPointRenderLayers(),\n tileScheduler: this.tileScheduler,\n getVisibleTiles: () => getManagedVisibleTiles(this.camera, this.source),\n getVisibleTilesForTier: tier => getManagedVisibleTilesForTier(this.camera, this.source, tier),\n getViewBounds: () => getManagedViewBounds(this.camera),\n intersectsBounds: intersectsManagedBounds,\n });\n if (this.onStats) {\n const schedulerStats = this.tileScheduler.getSnapshot();\n this.onStats({\n tier: result.tier,\n visible: result.visible,\n rendered: result.rendered,\n points: result.points,\n fallback: result.fallback,\n cache: this.cache.size,\n inflight: schedulerStats.inflight,\n queued: schedulerStats.queued,\n retries: schedulerStats.retries,\n failed: schedulerStats.failed,\n aborted: schedulerStats.aborted,\n cacheHits: result.cacheHits,\n cacheMisses: result.cacheMisses,\n drawCalls: result.drawCalls,\n frameMs: nowMs() - frameStartMs,\n });\n }\n }\n\n requestRender(): void {\n if (this.frame !== null || this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n this.frame = requestAnimationFrame(() => {\n this.frame = null;\n this.render();\n });\n }\n\n resize(): void {\n resizeCanvasViewport(this.canvas, this.gl, this.camera);\n this.requestRender();\n }\n\n private onWebGlContextLost(event: Event): void {\n const result = handleContextLost({\n event,\n destroyed: this.destroyed,\n contextLost: this.contextLost,\n frame: this.frame,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n cancelDrag: () => this.cancelDrag(),\n tileScheduler: this.tileScheduler,\n cache: this.cache,\n onContextLost: this.onContextLost,\n });\n if (!result.handled) return;\n this.frame = result.frame;\n this.contextLost = true;\n for (const layer of this.pointLayers.values()) {\n layer.runtime = {\n ...layer.runtime,\n pointBuffersDirty: true,\n };\n }\n }\n\n private onWebGlContextRestored(_event: Event): void {\n if (this.destroyed) return;\n this.contextLost = false;\n this.cache.clear();\n\n this.tileProgram = initTileProgram(this.gl);\n for (const layer of this.pointLayers.values()) {\n layer.program = initPointProgram(this.gl);\n layer.runtime = {\n ...layer.runtime,\n pointBuffersDirty: true,\n };\n if (layer.runtime.lastPointPalette && layer.runtime.lastPointPalette.length > 0) {\n layer.runtime = setManagedPointPalette(layer.runtime, this.gl, layer.program, this.contextLost, layer.runtime.lastPointPalette);\n }\n if (layer.runtime.lastPointData) {\n layer.runtime = setManagedPointData(layer.runtime, this.gl, layer.program, this.contextLost, layer.runtime.lastPointData);\n }\n }\n\n this.resize();\n this.onContextRestored?.();\n }\n\n destroy(): void {\n const result = destroyRenderer({\n destroyed: this.destroyed,\n frame: this.frame,\n cancelViewAnimation: () => this.cancelViewAnimation(),\n resizeObserver: this.resizeObserver,\n removeDprListener: this.removeDprListener,\n removeCanvasEventListeners: () => removeRendererCanvasEventListeners(this.canvas, this.getCanvasHandlers()),\n cancelDrag: () => this.cancelDrag(),\n tileScheduler: this.tileScheduler,\n contextLost: this.contextLost,\n gl: this.gl,\n cache: this.cache,\n tileProgram: this.tileProgram,\n pointPrograms: Array.from(this.pointLayers.values(), layer => layer.program),\n });\n if (!result.didDestroy) return;\n this.destroyed = true;\n this.frame = result.frame;\n }\n}\n","import { type CSSProperties, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { observeDevicePixelRatioChanges } from \"../wsi/device-pixel-ratio\";\nimport type { WsiImageColorSettings, WsiImageSource, WsiRenderStats, WsiViewState } from \"../wsi/types\";\nimport type { WsiTileErrorEvent, WsiViewTransitionOptions } from \"../wsi/wsi-tile-renderer\";\nimport { WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { DrawCoordinate } from \"./draw-layer-types\";\nimport { toDrawCoordinate } from \"./draw-layer-utils\";\nimport type { OverlayDrawFn, ViewerContextValue } from \"./viewer-context\";\nimport { ViewerContextProvider } from \"./viewer-context\";\nimport type { PointerWorldMoveEvent } from \"./wsi-viewer-canvas-types\";\n\nexport interface WsiViewerProps {\n source: WsiImageSource | null;\n viewState?: Partial<WsiViewState> | null;\n onViewStateChange?: (next: WsiViewState) => void;\n onStats?: (stats: WsiRenderStats) => void;\n onTileError?: (event: WsiTileErrorEvent) => void;\n onContextLost?: () => void;\n onContextRestored?: () => void;\n imageColorSettings?: WsiImageColorSettings | null;\n initialRotate?: number;\n fitNonce?: number;\n rotationResetNonce?: number;\n authToken?: string;\n ctrlDragRotate?: boolean;\n minZoom?: number;\n maxZoom?: number;\n viewTransition?: WsiViewTransitionOptions;\n zoomSnaps?: number[];\n zoomSnapFitAsMin?: boolean;\n panExtent?: number | { x: number; y: number };\n preserveDrawingBuffer?: boolean;\n onPointerWorldMove?: (event: PointerWorldMoveEvent) => void;\n debugOverlay?: boolean;\n debugOverlayStyle?: CSSProperties;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\ninterface DrawCallbackEntry {\n id: string;\n priority: number;\n draw: OverlayDrawFn;\n}\n\nconst EMPTY_DRAW_CALLBACKS: DrawCallbackEntry[] = [];\n\nfunction toFiniteRotation(value: number | undefined): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nexport function WsiViewer({\n source,\n viewState,\n onViewStateChange,\n onStats,\n onTileError,\n onContextLost,\n onContextRestored,\n imageColorSettings = null,\n initialRotate = 0,\n fitNonce = 0,\n rotationResetNonce = 0,\n authToken = \"\",\n ctrlDragRotate = true,\n minZoom,\n maxZoom,\n viewTransition,\n zoomSnaps,\n zoomSnapFitAsMin,\n panExtent,\n preserveDrawingBuffer,\n onPointerWorldMove,\n debugOverlay = false,\n debugOverlayStyle,\n className,\n style,\n children,\n}: WsiViewerProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const overlayCanvasRef = useRef<HTMLCanvasElement | null>(null);\n const rendererRef = useRef<WsiTileRenderer | null>(null);\n const drawInvalidateRef = useRef<(() => void) | null>(null);\n const overviewInvalidateRef = useRef<(() => void) | null>(null);\n const drawCallbacksRef = useRef<DrawCallbackEntry[]>(EMPTY_DRAW_CALLBACKS);\n const overlayPendingRef = useRef(false);\n const interactionLocksRef = useRef<Set<string>>(new Set());\n const viewStateListenersRef = useRef<Set<(state: WsiViewState) => void>>(new Set());\n\n const onViewStateChangeRef = useRef(onViewStateChange);\n const onStatsRef = useRef(onStats);\n const onTileErrorRef = useRef(onTileError);\n const onContextLostRef = useRef(onContextLost);\n const onContextRestoredRef = useRef(onContextRestored);\n\n const [rendererSerial, setRendererSerial] = useState(0);\n const [debugStats, setDebugStats] = useState<WsiRenderStats | null>(null);\n const debugOverlayRef = useRef(debugOverlay);\n\n useEffect(() => {\n onViewStateChangeRef.current = onViewStateChange;\n }, [onViewStateChange]);\n useEffect(() => {\n onStatsRef.current = onStats;\n }, [onStats]);\n useEffect(() => {\n onTileErrorRef.current = onTileError;\n }, [onTileError]);\n useEffect(() => {\n onContextLostRef.current = onContextLost;\n }, [onContextLost]);\n useEffect(() => {\n onContextRestoredRef.current = onContextRestored;\n }, [onContextRestored]);\n useEffect(() => {\n debugOverlayRef.current = debugOverlay;\n if (!debugOverlay) setDebugStats(null);\n }, [debugOverlay]);\n\n const mergedStyle = useMemo<CSSProperties>(() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }), [style]);\n\n const mergedDebugOverlayStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n top: 8,\n left: 8,\n zIndex: 7,\n margin: 0,\n padding: \"8px 10px\",\n maxWidth: \"min(420px, 80%)\",\n pointerEvents: \"none\",\n whiteSpace: \"pre-wrap\",\n lineHeight: 1.35,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 11,\n color: \"#cde6ff\",\n background: \"rgba(6, 12, 20, 0.82)\",\n border: \"1px solid rgba(173, 216, 255, 0.28)\",\n borderRadius: 8,\n boxShadow: \"0 8px 22px rgba(0,0,0,0.35)\",\n ...debugOverlayStyle,\n }),\n [debugOverlayStyle]\n );\n\n const initialRotateValue = toFiniteRotation(initialRotate);\n\n const toExternalViewState = useCallback(\n (state: WsiViewState): WsiViewState => ({\n ...state,\n rotationDeg: state.rotationDeg - initialRotateValue,\n }),\n [initialRotateValue]\n );\n\n const toInternalViewState = useCallback(\n (state: Partial<WsiViewState>): Partial<WsiViewState> => {\n if (typeof state.rotationDeg !== \"number\" || !Number.isFinite(state.rotationDeg)) {\n return state;\n }\n return {\n ...state,\n rotationDeg: state.rotationDeg + initialRotateValue,\n };\n },\n [initialRotateValue]\n );\n\n const handleRendererStats = useCallback((stats: WsiRenderStats): void => {\n onStatsRef.current?.(stats);\n if (debugOverlayRef.current) setDebugStats(stats);\n }, []);\n\n const debugOverlayText = useMemo(() => {\n if (!debugStats) return \"stats: waiting for first frame...\";\n return [\n `tier ${debugStats.tier} | frame ${debugStats.frameMs?.toFixed(2) ?? \"-\"} ms | drawCalls ${debugStats.drawCalls ?? \"-\"}`,\n `tiles visible ${debugStats.visible} | rendered ${debugStats.rendered} | fallback ${debugStats.fallback}`,\n `cache size ${debugStats.cache} | hit ${debugStats.cacheHits ?? \"-\"} | miss ${debugStats.cacheMisses ?? \"-\"}`,\n `queue inflight ${debugStats.inflight} | queued ${debugStats.queued ?? \"-\"} | retries ${debugStats.retries ?? \"-\"} | failed ${debugStats.failed ?? \"-\"} | aborted ${debugStats.aborted ?? \"-\"}`,\n `points ${debugStats.points}`,\n ].join(\"\\n\");\n }, [debugStats]);\n\n // --- overlay draw registry ---\n\n const drawOverlayFrame = useCallback(() => {\n const canvas = overlayCanvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const rect = canvas.getBoundingClientRect();\n const w = Math.max(1, Math.round(rect.width * dpr));\n const h = Math.max(1, Math.round(rect.height * dpr));\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n\n const logicalWidth = rect.width;\n const logicalHeight = rect.height;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n const entries = drawCallbacksRef.current;\n for (let i = 0; i < entries.length; i += 1) {\n ctx.save();\n entries[i].draw(ctx, logicalWidth, logicalHeight);\n ctx.restore();\n }\n }, []);\n\n const requestOverlayRedraw = useCallback(() => {\n if (overlayPendingRef.current) return;\n overlayPendingRef.current = true;\n requestAnimationFrame(() => {\n overlayPendingRef.current = false;\n drawOverlayFrame();\n });\n }, [drawOverlayFrame]);\n\n const registerDrawCallback = useCallback(\n (id: string, priority: number, draw: OverlayDrawFn) => {\n const entries = drawCallbacksRef.current.filter(e => e.id !== id);\n entries.push({ id, priority, draw });\n entries.sort((a, b) => a.priority - b.priority);\n drawCallbacksRef.current = entries;\n requestOverlayRedraw();\n },\n [requestOverlayRedraw]\n );\n\n const unregisterDrawCallback = useCallback(\n (id: string) => {\n drawCallbacksRef.current = drawCallbacksRef.current.filter(e => e.id !== id);\n requestOverlayRedraw();\n },\n [requestOverlayRedraw]\n );\n\n const setInteractionLock = useCallback((id: string, locked: boolean) => {\n if (locked) {\n interactionLocksRef.current.add(id);\n } else {\n interactionLocksRef.current.delete(id);\n }\n rendererRef.current?.setInteractionLock(interactionLocksRef.current.size > 0);\n }, []);\n\n const isInteractionLocked = useCallback(() => interactionLocksRef.current.size > 0, []);\n\n // --- coordinate transforms ---\n\n const worldToScreen = useCallback((worldX: number, worldY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n return toDrawCoordinate(renderer.worldToScreen(worldX, worldY));\n }, []);\n\n const screenToWorld = useCallback((clientX: number, clientY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.screenToWorld(clientX, clientY);\n if (!Array.isArray(raw) || raw.length < 2) return null;\n const x = Number(raw[0]);\n const y = Number(raw[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const registerViewStateListener = useCallback((listener: (state: WsiViewState) => void) => {\n viewStateListenersRef.current.add(listener);\n return () => {\n viewStateListenersRef.current.delete(listener);\n };\n }, []);\n\n // --- viewState change propagation ---\n\n const emitViewStateChange = useCallback(\n (nextInternal: WsiViewState): void => {\n onViewStateChangeRef.current?.(toExternalViewState(nextInternal));\n const listeners = viewStateListenersRef.current;\n if (listeners.size > 0) {\n const snapshot = Array.from(listeners);\n for (let i = 0; i < snapshot.length; i += 1) {\n snapshot[i](nextInternal);\n }\n }\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n requestOverlayRedraw();\n },\n [requestOverlayRedraw, toExternalViewState]\n );\n\n // --- renderer lifecycle ---\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !source) return;\n\n const renderer = new WsiTileRenderer(canvas, source, {\n onViewStateChange: emitViewStateChange,\n onStats: handleRendererStats,\n onTileError: event => {\n onTileErrorRef.current?.(event);\n },\n onContextLost: () => {\n onContextLostRef.current?.();\n },\n onContextRestored: () => {\n onContextRestoredRef.current?.();\n },\n authToken,\n imageColorSettings,\n initialRotationDeg: initialRotate,\n ctrlDragRotate,\n minZoom,\n maxZoom,\n viewTransition,\n zoomSnaps,\n zoomSnapFitAsMin,\n panExtent,\n preserveDrawingBuffer,\n });\n\n rendererRef.current = renderer;\n setRendererSerial(s => s + 1);\n if (viewState) renderer.setViewState(toInternalViewState(viewState));\n renderer.setInteractionLock(interactionLocksRef.current.size > 0);\n\n return () => {\n renderer.destroy();\n rendererRef.current = null;\n };\n }, [source, handleRendererStats, ctrlDragRotate, emitViewStateChange, initialRotateValue, toInternalViewState]);\n\n // --- core renderer sync effects ---\n\n useEffect(() => {\n rendererRef.current?.setAuthToken(authToken);\n }, [authToken]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !viewState) return;\n if (renderer.isViewAnimating()) return;\n renderer.setViewState(toInternalViewState(viewState));\n }, [viewState, toInternalViewState]);\n\n useEffect(() => {\n rendererRef.current?.fitToImage();\n }, [fitNonce]);\n useEffect(() => {\n rendererRef.current?.resetRotation();\n }, [rotationResetNonce]);\n\n useEffect(() => {\n rendererRef.current?.setZoomRange(minZoom, maxZoom);\n }, [minZoom, maxZoom]);\n useEffect(() => {\n rendererRef.current?.setViewTransition(viewTransition);\n }, [viewTransition]);\n useEffect(() => {\n rendererRef.current?.setZoomSnaps(zoomSnaps, zoomSnapFitAsMin);\n }, [zoomSnaps, zoomSnapFitAsMin]);\n useEffect(() => {\n rendererRef.current?.setPanExtent(panExtent);\n }, [panExtent]);\n useEffect(() => {\n rendererRef.current?.setImageColorSettings(imageColorSettings);\n }, [imageColorSettings]);\n\n // --- overlay canvas setup ---\n\n useEffect(() => {\n const canvas = overlayCanvasRef.current;\n if (!canvas) return;\n drawInvalidateRef.current = requestOverlayRedraw;\n requestOverlayRedraw();\n\n const observer = new ResizeObserver(() => requestOverlayRedraw());\n observer.observe(canvas);\n return () => {\n observer.disconnect();\n if (drawInvalidateRef.current === requestOverlayRedraw) {\n drawInvalidateRef.current = null;\n }\n };\n }, [requestOverlayRedraw]);\n\n useEffect(() => observeDevicePixelRatioChanges(() => requestOverlayRedraw()), [requestOverlayRedraw]);\n\n // --- context value ---\n\n const contextValue = useMemo<ViewerContextValue>(\n () => ({\n source,\n rendererRef,\n rendererSerial,\n canvasRef,\n containerRef,\n drawInvalidateRef,\n overviewInvalidateRef,\n worldToScreen,\n screenToWorld,\n registerDrawCallback,\n unregisterDrawCallback,\n requestOverlayRedraw,\n registerViewStateListener,\n setInteractionLock,\n isInteractionLocked,\n }),\n [source, rendererSerial, worldToScreen, screenToWorld, registerDrawCallback, unregisterDrawCallback, requestOverlayRedraw, registerViewStateListener, setInteractionLock, isInteractionLocked]\n );\n\n const onPointerWorldMoveRef = useRef(onPointerWorldMove);\n useEffect(() => {\n onPointerWorldMoveRef.current = onPointerWorldMove;\n }, [onPointerWorldMove]);\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n const cb = onPointerWorldMoveRef.current;\n if (!cb) return;\n const coord = screenToWorld(e.clientX, e.clientY);\n const insideImage = !!coord && coord[0] >= 0 && coord[1] >= 0 && !!source && coord[0] <= source.width && coord[1] <= source.height;\n cb({ coordinate: coord, clientX: e.clientX, clientY: e.clientY, insideImage });\n },\n [screenToWorld, source]\n );\n\n const handlePointerLeave = useCallback(() => {\n onPointerWorldMoveRef.current?.({ coordinate: null, clientX: -1, clientY: -1, insideImage: false });\n }, []);\n\n return (\n <ViewerContextProvider value={contextValue}>\n <div\n ref={containerRef}\n className={className}\n style={mergedStyle}\n onPointerMove={onPointerWorldMove ? handlePointerMove : undefined}\n onPointerLeave={onPointerWorldMove ? handlePointerLeave : undefined}\n >\n <canvas\n ref={canvasRef}\n className=\"wsi-render-canvas\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 1,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n }}\n />\n <canvas\n ref={overlayCanvasRef}\n className=\"wsi-overlay-canvas\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 2,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n pointerEvents: \"none\",\n touchAction: \"none\",\n }}\n />\n {children}\n {debugOverlay && (\n <pre data-open-plant-debug-overlay style={mergedDebugOverlayStyle}>\n {debugOverlayText}\n </pre>\n )}\n </div>\n </ViewerContextProvider>\n );\n}\n","import { type PreparedRoiPolygon, pointInPreparedPolygon, prepareRoiPolygons, toRoiGeometry } from \"./roi-geometry\";\nimport type { WsiPointData, WsiRegion } from \"./types\";\n\nexport interface RoiClassCount {\n classId: string;\n paletteIndex: number;\n count: number;\n}\n\nexport interface RoiPointGroup {\n regionId: string | number;\n regionIndex: number;\n totalCount: number;\n classCounts: RoiClassCount[];\n}\n\nexport interface RoiPointGroupOptions {\n paletteIndexToClassId?: ReadonlyMap<number, string> | readonly string[];\n includeEmptyRegions?: boolean;\n}\n\nexport interface RoiPointGroupStats {\n groups: RoiPointGroup[];\n inputPointCount: number;\n pointsInsideAnyRegion: number;\n unmatchedPointCount: number;\n}\n\ninterface PreparedRegion {\n regionId: string | number;\n regionIndex: number;\n polygons: PreparedRoiPolygon[];\n area: number;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nfunction prepareRegions(regions: readonly WsiRegion[]): PreparedRegion[] {\n const prepared: PreparedRegion[] = [];\n for (let i = 0; i < regions.length; i += 1) {\n const region = regions[i];\n const polygons = prepareRoiPolygons([toRoiGeometry(region?.coordinates)]);\n if (polygons.length === 0) continue;\n\n let area = 0;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const polygon of polygons) {\n area += polygon.area;\n if (polygon.minX < minX) minX = polygon.minX;\n if (polygon.minY < minY) minY = polygon.minY;\n if (polygon.maxX > maxX) maxX = polygon.maxX;\n if (polygon.maxY > maxY) maxY = polygon.maxY;\n }\n if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) continue;\n\n prepared.push({\n regionId: region.id ?? i,\n regionIndex: i,\n polygons,\n area: Math.max(1e-6, area),\n minX,\n minY,\n maxX,\n maxY,\n });\n }\n return prepared;\n}\n\ninterface PreparedRegionGridIndex {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n gridSize: number;\n cellWidth: number;\n cellHeight: number;\n buckets: number[][];\n}\n\nconst MAX_REGION_GRID_SIZE = 128;\nconst EMPTY_CANDIDATE_REGION_INDICES: number[] = [];\n\nfunction toGridCell(value: number, min: number, max: number, cellSize: number, gridSize: number): number {\n if (gridSize <= 1 || max <= min) return 0;\n const ratio = (value - min) / cellSize;\n if (!Number.isFinite(ratio) || ratio <= 0) return 0;\n if (ratio >= gridSize - 1) return gridSize - 1;\n return Math.floor(ratio);\n}\n\nfunction buildPreparedRegionGridIndex(regions: readonly PreparedRegion[]): PreparedRegionGridIndex | null {\n if (regions.length === 0) return null;\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const region of regions) {\n if (region.minX < minX) minX = region.minX;\n if (region.minY < minY) minY = region.minY;\n if (region.maxX > maxX) maxX = region.maxX;\n if (region.maxY > maxY) maxY = region.maxY;\n }\n if (!Number.isFinite(minX) || !Number.isFinite(minY) || !Number.isFinite(maxX) || !Number.isFinite(maxY)) {\n return null;\n }\n\n const estimated = Math.ceil(Math.sqrt(regions.length * 2));\n const gridSize = Math.max(1, Math.min(MAX_REGION_GRID_SIZE, estimated));\n const cellWidth = maxX > minX ? (maxX - minX) / gridSize : 1;\n const cellHeight = maxY > minY ? (maxY - minY) / gridSize : 1;\n const buckets = Array.from({ length: gridSize * gridSize }, () => [] as number[]);\n\n for (let regionArrayIndex = 0; regionArrayIndex < regions.length; regionArrayIndex += 1) {\n const region = regions[regionArrayIndex];\n const minCellX = toGridCell(region.minX, minX, maxX, cellWidth, gridSize);\n const maxCellX = toGridCell(region.maxX, minX, maxX, cellWidth, gridSize);\n const minCellY = toGridCell(region.minY, minY, maxY, cellHeight, gridSize);\n const maxCellY = toGridCell(region.maxY, minY, maxY, cellHeight, gridSize);\n for (let cellY = minCellY; cellY <= maxCellY; cellY += 1) {\n for (let cellX = minCellX; cellX <= maxCellX; cellX += 1) {\n buckets[cellY * gridSize + cellX].push(regionArrayIndex);\n }\n }\n }\n\n return {\n minX,\n minY,\n maxX,\n maxY,\n gridSize,\n cellWidth,\n cellHeight,\n buckets,\n };\n}\n\nfunction getCandidateRegionIndices(index: PreparedRegionGridIndex | null, x: number, y: number): readonly number[] {\n if (!index) return EMPTY_CANDIDATE_REGION_INDICES;\n if (x < index.minX || x > index.maxX || y < index.minY || y > index.maxY) {\n return EMPTY_CANDIDATE_REGION_INDICES;\n }\n const cellX = toGridCell(x, index.minX, index.maxX, index.cellWidth, index.gridSize);\n const cellY = toGridCell(y, index.minY, index.maxY, index.cellHeight, index.gridSize);\n return index.buckets[cellY * index.gridSize + cellX] ?? EMPTY_CANDIDATE_REGION_INDICES;\n}\n\nfunction resolveClassId(paletteIndex: number, paletteIndexToClassId: RoiPointGroupOptions[\"paletteIndexToClassId\"]): string {\n if (Array.isArray(paletteIndexToClassId)) {\n const fromArray = paletteIndexToClassId[paletteIndex];\n if (typeof fromArray === \"string\" && fromArray.length > 0) return fromArray;\n }\n if (paletteIndexToClassId instanceof Map) {\n const fromMap = paletteIndexToClassId.get(paletteIndex);\n if (typeof fromMap === \"string\" && fromMap.length > 0) return fromMap;\n }\n return String(paletteIndex);\n}\n\nexport function computeRoiPointGroups(pointData: WsiPointData | null | undefined, regions: readonly WsiRegion[] | null | undefined, options: RoiPointGroupOptions = {}): RoiPointGroupStats {\n const baseCount = Math.max(\n 0,\n Math.min(\n Math.floor(pointData?.count ?? 0),\n Math.floor((pointData?.positions?.length ?? 0) / 2),\n pointData?.paletteIndices?.length ?? 0,\n pointData?.fillModes instanceof Uint8Array ? pointData.fillModes.length : Number.MAX_SAFE_INTEGER\n )\n );\n\n let drawIndices: Uint32Array | null = null;\n if (pointData?.drawIndices instanceof Uint32Array) {\n const source = pointData.drawIndices;\n let valid = source.length;\n for (let i = 0; i < source.length; i += 1) {\n const idx = source[i];\n if (idx < baseCount) continue;\n valid -= 1;\n }\n if (valid === source.length) {\n drawIndices = source;\n } else if (valid > 0) {\n const filtered = new Uint32Array(valid);\n let cursor = 0;\n for (let i = 0; i < source.length; i += 1) {\n const idx = source[i];\n if (idx >= baseCount) continue;\n filtered[cursor] = idx;\n cursor += 1;\n }\n drawIndices = filtered;\n } else {\n drawIndices = new Uint32Array(0);\n }\n }\n\n const inputCount = drawIndices ? drawIndices.length : baseCount;\n\n const preparedRegions = prepareRegions(regions ?? []);\n if (!pointData || inputCount === 0 || preparedRegions.length === 0) {\n return {\n groups: [],\n inputPointCount: inputCount,\n pointsInsideAnyRegion: 0,\n unmatchedPointCount: inputCount,\n };\n }\n\n const regionClassCounters = new Map<number, Map<number, number>>();\n const regionTotalCounters = new Map<number, number>();\n const preparedRegionIndex = buildPreparedRegionGridIndex(preparedRegions);\n let insideCount = 0;\n\n for (let i = 0; i < inputCount; i += 1) {\n const pointIndex = drawIndices ? drawIndices[i] : i;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n let bestRegion: PreparedRegion | null = null;\n const candidateRegionIndices = getCandidateRegionIndices(preparedRegionIndex, x, y);\n if (candidateRegionIndices.length === 0) continue;\n\n for (const regionArrayIndex of candidateRegionIndices) {\n const region = preparedRegions[regionArrayIndex];\n let inside = false;\n for (const polygon of region.polygons) {\n if (!pointInPreparedPolygon(x, y, polygon)) continue;\n inside = true;\n break;\n }\n if (!inside) continue;\n if (!bestRegion || region.area < bestRegion.area) {\n bestRegion = region;\n }\n }\n\n if (!bestRegion) continue;\n insideCount += 1;\n\n const paletteIndex = pointData.paletteIndices[pointIndex] ?? 0;\n const regionClassMap = regionClassCounters.get(bestRegion.regionIndex) ?? new Map<number, number>();\n regionClassMap.set(paletteIndex, (regionClassMap.get(paletteIndex) ?? 0) + 1);\n regionClassCounters.set(bestRegion.regionIndex, regionClassMap);\n regionTotalCounters.set(bestRegion.regionIndex, (regionTotalCounters.get(bestRegion.regionIndex) ?? 0) + 1);\n }\n\n const includeEmptyRegions = options.includeEmptyRegions ?? false;\n const groups: RoiPointGroup[] = [];\n for (const region of preparedRegions) {\n const totalCount = regionTotalCounters.get(region.regionIndex) ?? 0;\n if (!includeEmptyRegions && totalCount <= 0) continue;\n const classMap = regionClassCounters.get(region.regionIndex) ?? new Map();\n const classCounts: RoiClassCount[] = Array.from(classMap.entries())\n .map(([paletteIndex, count]) => ({\n classId: resolveClassId(paletteIndex, options.paletteIndexToClassId),\n paletteIndex,\n count,\n }))\n .sort((a, b) => b.count - a.count || a.paletteIndex - b.paletteIndex);\n\n groups.push({\n regionId: region.regionId,\n regionIndex: region.regionIndex,\n totalCount,\n classCounts,\n });\n }\n\n return {\n groups,\n inputPointCount: inputCount,\n pointsInsideAnyRegion: insideCount,\n unmatchedPointCount: Math.max(0, inputCount - insideCount),\n };\n}\n","import type { WsiCoordinate, WsiMultiPolygonCoordinates, WsiPolygonCoordinates } from \"./types\";\n\nexport interface ParsedWktPolygon {\n type: \"Polygon\";\n coordinates: WsiPolygonCoordinates;\n}\n\nexport interface ParsedWktMultiPolygon {\n type: \"MultiPolygon\";\n coordinates: WsiMultiPolygonCoordinates;\n}\n\nexport type ParsedWktGeometry = ParsedWktPolygon | ParsedWktMultiPolygon;\n\nfunction stripSridPrefix(value: string): string {\n return value.replace(/^\\s*SRID\\s*=\\s*\\d+\\s*;\\s*/i, \"\");\n}\n\nfunction isWordChar(ch: string): boolean {\n return (ch >= \"A\" && ch <= \"Z\") || (ch >= \"a\" && ch <= \"z\");\n}\n\nfunction isDigitChar(ch: string): boolean {\n return ch >= \"0\" && ch <= \"9\";\n}\n\nfunction isNumberStartChar(ch: string): boolean {\n return ch === \"+\" || ch === \"-\" || ch === \".\" || isDigitChar(ch);\n}\n\nclass WktParser {\n private readonly text: string;\n\n private index = 0;\n\n constructor(rawInput: string) {\n this.text = stripSridPrefix(rawInput.trim());\n }\n\n parse(): ParsedWktGeometry | null {\n if (!this.text) return null;\n\n const geometryType = this.readWord();\n if (!geometryType) return null;\n\n const geometryTypeUpper = geometryType.toUpperCase();\n if (geometryTypeUpper !== \"POLYGON\" && geometryTypeUpper !== \"MULTIPOLYGON\") {\n return null;\n }\n\n this.skipWhitespace();\n const maybeDimension = this.peekWord();\n if (maybeDimension) {\n const dimUpper = maybeDimension.toUpperCase();\n if (dimUpper === \"Z\" || dimUpper === \"M\" || dimUpper === \"ZM\") {\n this.readWord();\n this.skipWhitespace();\n }\n }\n\n if (this.consumeWordIf(\"EMPTY\")) {\n this.skipWhitespace();\n if (!this.isEof()) return null;\n if (geometryTypeUpper === \"POLYGON\") {\n return { type: \"Polygon\", coordinates: [] };\n }\n return { type: \"MultiPolygon\", coordinates: [] };\n }\n\n let nested: unknown;\n try {\n nested = this.parseNestedList();\n } catch {\n return null;\n }\n\n this.skipWhitespace();\n if (!this.isEof()) return null;\n\n if (geometryTypeUpper === \"POLYGON\") {\n const polygon = toPolygonCoordinates(nested);\n if (!polygon) return null;\n return {\n type: \"Polygon\",\n coordinates: polygon,\n };\n }\n\n const multipolygon = toMultiPolygonCoordinates(nested);\n if (!multipolygon) return null;\n return {\n type: \"MultiPolygon\",\n coordinates: multipolygon,\n };\n }\n\n private isEof(): boolean {\n return this.index >= this.text.length;\n }\n\n private currentChar(): string {\n return this.text[this.index] ?? \"\";\n }\n\n private skipWhitespace(): void {\n while (!this.isEof() && /\\s/.test(this.currentChar())) {\n this.index += 1;\n }\n }\n\n private readWord(): string | null {\n this.skipWhitespace();\n if (this.isEof()) return null;\n\n const start = this.index;\n while (!this.isEof() && isWordChar(this.currentChar())) {\n this.index += 1;\n }\n if (this.index === start) return null;\n return this.text.slice(start, this.index);\n }\n\n private peekWord(): string | null {\n const saved = this.index;\n const word = this.readWord();\n this.index = saved;\n return word;\n }\n\n private consumeWordIf(target: string): boolean {\n const saved = this.index;\n const word = this.readWord();\n if (!word || word.toUpperCase() !== target.toUpperCase()) {\n this.index = saved;\n return false;\n }\n return true;\n }\n\n private parseNestedList(): unknown[] {\n this.skipWhitespace();\n if (this.currentChar() !== \"(\") {\n throw new Error(\"Expected '('\");\n }\n this.index += 1;\n\n const values: unknown[] = [];\n while (true) {\n this.skipWhitespace();\n if (this.currentChar() === \"(\") {\n values.push(this.parseNestedList());\n } else {\n values.push(this.parseCoordinateTuple());\n }\n\n this.skipWhitespace();\n const ch = this.currentChar();\n if (ch === \",\") {\n this.index += 1;\n continue;\n }\n if (ch === \")\") {\n this.index += 1;\n break;\n }\n throw new Error(\"Expected ',' or ')'\");\n }\n\n return values;\n }\n\n private parseCoordinateTuple(): WsiCoordinate {\n this.skipWhitespace();\n const values: number[] = [];\n while (true) {\n this.skipWhitespace();\n const ch = this.currentChar();\n if (!ch || !isNumberStartChar(ch)) break;\n const num = this.readNumber();\n if (num === null) break;\n values.push(num);\n this.skipWhitespace();\n const next = this.currentChar();\n if (!next || next === \",\" || next === \")\") break;\n if (!isNumberStartChar(next)) {\n throw new Error(\"Invalid coordinate\");\n }\n }\n\n if (values.length < 2) {\n throw new Error(\"Coordinate requires at least x y\");\n }\n return [values[0], values[1]];\n }\n\n private readNumber(): number | null {\n this.skipWhitespace();\n if (this.isEof()) return null;\n const chunk = this.text.slice(this.index);\n const match = chunk.match(/^[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/);\n if (!match) return null;\n const value = Number(match[0]);\n if (!Number.isFinite(value)) return null;\n this.index += match[0].length;\n return value;\n }\n}\n\nfunction isCoordinate(value: unknown): value is WsiCoordinate {\n return (\n Array.isArray(value) &&\n value.length >= 2 &&\n typeof value[0] === \"number\" &&\n Number.isFinite(value[0]) &&\n typeof value[1] === \"number\" &&\n Number.isFinite(value[1])\n );\n}\n\nfunction toPolygonCoordinates(value: unknown): WsiPolygonCoordinates | null {\n if (!Array.isArray(value)) return null;\n const polygon: WsiPolygonCoordinates = [];\n for (const ringValue of value) {\n if (!Array.isArray(ringValue)) return null;\n const ring: WsiCoordinate[] = [];\n for (const coordValue of ringValue) {\n if (!isCoordinate(coordValue)) return null;\n ring.push([coordValue[0], coordValue[1]]);\n }\n polygon.push(ring);\n }\n return polygon;\n}\n\nfunction toMultiPolygonCoordinates(value: unknown): WsiMultiPolygonCoordinates | null {\n if (!Array.isArray(value)) return null;\n const multipolygon: WsiMultiPolygonCoordinates = [];\n for (const polygonValue of value) {\n const polygon = toPolygonCoordinates(polygonValue);\n if (!polygon) return null;\n multipolygon.push(polygon);\n }\n return multipolygon;\n}\n\nexport function parseWkt(wkt: string): ParsedWktGeometry | null {\n if (typeof wkt !== \"string\") return null;\n return new WktParser(wkt).parse();\n}\n\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","options","context","toRadians","deg","OrthoCamera","__publicField","width","height","next","zoom","centerX","centerY","screenX","screenY","rotationDeg","dx","dy","rad","cos","sin","worldX","worldY","rx","ry","w","h","viewWidth","viewHeight","sx","sy","tx","ty","ax","bx","ay","by","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","f","e","d","n","u","l","i","o","s","c","m","_","z","k","g","a","y","x","p","epsilon","splitter","resulterrbound","sum","elen","flen","Q","Qnew","hh","bvirt","enow","fnow","eindex","findex","hindex","estimate","vec","ccwerrboundA","ccwerrboundB","ccwerrboundC","B","C1","C2","D","orient2dadapt","cx","cy","detsum","acxtail","acytail","bcxtail","bcytail","ahi","alo","bhi","blo","_i","_j","_0","s1","s0","t1","t0","u3","acx","bcx","acy","bcy","det","errbound","C1len","C2len","Dlen","orient2d","detleft","detright","isInBbox","bbox","point","getBboxOverlap","b1","b2","lowerX","upperX","lowerY","upperY","EPSILON_SQ","cmp","b","ab","PtRounder","CoordRounder","SplayTree","coord","node","prevNode","nextNode","rounder","crossProduct","dotProduct","compareVectorAngles","basePt","endPt1","endPt2","res","length","v","sineOfAngle","pShared","pBase","pAngle","vBase","vAngle","cosineOfAngle","horizontalIntersection","pt","verticalIntersection","intersection$1","pt1","v1","pt2","v2","kross","ve","d1","d2","x1","x2","y1","y2","SweepEvent","ptCmp","Segment","aPt","bPt","isLeft","other","otherEvents","iMax","evt","numEvents","evt1","j","evt2","events","baseEvent","cache","fillCache","linkedEvent","nextEvent","asine","acosine","bsine","bcosine","segmentId","alx","blx","arx","brx","aly","bly","ary","bry","aCmpBLeft","bCmpARight","bCmpALeft","aCmpBRight","leftSE","rightSE","rings","windings","ring","leftPt","rightPt","winding","cmpPts","newRightSE","lPt","rPt","yDist","xFromYDist","xDist","yFromXDist","tBbox","oBbox","bboxOverlap","tlp","trp","olp","orp","touchesOtherLSE","touchesThisLSE","touchesOtherRSE","touchesThisRSE","newEvents","alreadyLinked","newLeftSE","oldRightSE","newSeg","tmpEvt","consumer","consumee","tmp","index","seg","beforeState","ringsAfter","windingsAfter","mpsAfter","polysAfter","polysExclude","poly","mp","mpsBefore","operation","noBefores","noAfters","least","most","diff","isJustSubject","mps","RingIn","geomRing","isExterior","firstPoint","prevPoint","sweepEvents","segment","PolyIn","geomPoly","multiPoly","ringSweepEvents","jMax","MultiPolyIn","geom","isSubject","polySweepEvents","RingOut","allSegments","ringsOut","prevEvent","event","startingPoint","intersectionLEs","availableLEs","firstPt","lastPt","indexLE","intersectionLE","ringEvents","comparator","prevPt","points","nextPt","step","iStart","iEnd","orderedPoints","enclosing","leftMostEvt","prevSeg","prevPrevSeg","PolyOut","exteriorRing","ringGeom","MultiPolyOut","polyGeom","polys","enclosingRing","SweepLine","queue","nextSeg","prevMySplitter","prevInter","newEventsFromSplit","nextMySplitter","nextInter","mySplitter","inter","POLYGON_CLIPPING_MAX_QUEUE_SIZE","POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS","Operation","moreGeoms","multipolys","subject","mpA","sweepLine","prevQueueSize","union","_len","_key","intersection","_len2","_key2","xor","_len3","_key3","difference","subjectGeom","_len4","clippingGeoms","_key4","toRoiGeometry","coords","isLinearRing","isPolygonRings","isMultiPolygon","isFiniteNumber","value","isCoordinatePair","polygon","closeRoiRing","coordinates","out","prev","first","last","polygonSignedArea","normalizePolygonRings","normalized","closed","outerIndex","outerArea","area","normalizeRoiGeometry","geometry","second","pointInRing","inside","xi","yi","xj","yj","prepareRoiPolygons","geometries","prepared","multipolygon","outer","minX","minY","maxX","maxY","pointInPreparedPolygon","hole","pointInAnyPreparedPolygon","polygons","DEFAULT_POINT_COLOR","clamp","min","max","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcViewingMagnification","viewZoom","calcScaleLength","unit","nowMs","sanitizePointCount","pointData","fillModesLength","isSameViewState","toBearerToken","trimmed","token","hexToRgba","hex","match","parseHexColorToRgba","fallback","input","hexMatch","ch","resolvePaletteClassKey","item","classId","buildClassPalette","classes","palette","classToPaletteIndex","classKey","colors","ROUND_PRECISIONS","DEFAULT_CIRCLE_SIDES","DEFAULT_SIMPLIFY_FACTOR","DEFAULT_SMOOTHING_PASSES","MAX_SMOOTHING_PASSES","MIN_RADIUS","MIN_TUNNEL_LENGTH_FACTOR","sanitizePath","createCircleRing","center","radius","sides","t","closeRing","createTunnelRing","start","end","minLength","ux","perpX","perpY","r","createBoundsFallback","pad","clampRingToBounds","bounds","round","precision","sanitizeRing","sanitized","sanitizePolygon","tryUnionWithPrecision","current","polygonClipping","unionPolygons","result","toBrushRing","selectLargestOuterRing","multiPolygon","best","bestArea","removeCollinearVertices","curr","cross","pointLineDistanceSquared","abx","aby","len2","simplifyRdp","tolerance","keep","tolerance2","stack","maxDist2","split","dist2","simplifyClosedRing","open","simplified","smoothClosedRingChaikin","iterations","pass","buildBrushStrokePolygon","path","circleSides","minTunnelLength","circle","tunnel","unioned","unionRing","smoothingPasses","optimized","readDevicePixelRatio","raw","observeDevicePixelRatioChanges","onChange","active","lastDpr","mediaQuery","removeMediaQueryListener","unbindMediaQuery","bindMediaQuery","handleMediaQueryChange","emitIfChanged","trigger","nextDpr","previousDpr","handleWindowResize","handleVisualViewportResize","EMPTY_DASH","EMPTY_REGIONS","DEFAULT_REGION_STROKE_STYLE","DEFAULT_PATCH_STROKE_STYLE","REGION_INTERACTION_SHADOW_COLOR","REGION_INTERACTION_SHADOW_WIDTH","DEFAULT_REGION_LABEL_STYLE","DEFAULT_DRAW_AREA_TOOLTIP_STYLE","DEFAULT_DRAW_AREA_TOOLTIP_OFFSET","REGION_LABEL_AUTO_LIFT_MAX_OFFSET_PX","REGION_LABEL_AUTO_LIFT_MAX_EPSILON","DEFAULT_DRAW_PREVIEW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","MICRONS_PER_MM","DEFAULT_STAMP_RECTANGLE_AREA_MM2","DEFAULT_STAMP_CIRCLE_AREA_MM2","DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE","LEGACY_HPF_CIRCLE_AREA_MM2","WHEEL_ZOOM_IN_FACTOR","WHEEL_ZOOM_OUT_FACTOR","DEFAULT_BRUSH_RADIUS","DEFAULT_BRUSH_FILL_COLOR","DEFAULT_BRUSH_FILL_OPACITY","DEFAULT_BRUSH_CURSOR_COLOR","DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR","DEFAULT_BRUSH_CURSOR_LINE_WIDTH","DEFAULT_BRUSH_CURSOR_DASH","DEFAULT_BRUSH_EDGE_DETAIL","MIN_BRUSH_EDGE_DETAIL","MAX_BRUSH_EDGE_DETAIL","DEFAULT_BRUSH_EDGE_SMOOTHING","MIN_BRUSH_EDGE_SMOOTHING","MAX_BRUSH_EDGE_SMOOTHING","BRUSH_SCREEN_STEP","clampWorld","imageWidth","imageHeight","toDrawCoordinate","toCoord","polygonArea","computeBounds","tracePath","ctx","close","drawPath","strokeStyle","fill","fillColor","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","isCoordinateRing","collectOverlayRings","normalizeOverlayRings","sourceRings","clampPositiveOrFallback","clampUnitOpacity","drawRoundedRect","isNestedRingCoordinates","createRectangle","projection","startScreen","endScreen","screenCorners","worldCorners","corner","world","createCircle","normalizeDrawRegionPolygons","normalizedOuter","holes","sanitizeBrushLineDash","resolveBrushEdgeDetail","resolveBrushEdgeSmoothing","resolveBrushOptions","cursorLineWidth","edgeDetail","edgeSmoothing","drawBrushStrokePreview","session","resolvedBrushOptions","screenPoints","radiusPx","drawBrushCursor","projector","cursor","screen","LABEL_MEASURE_FALLBACK_EM","LABEL_MEASURE_CACHE_LIMIT","TOP_ANCHOR_Y_TOLERANCE","sharedLabelMeasureContext","labelTextWidthCache","getLabelMeasureContext","measureLabelTextWidth","label","labelStyle","key","cached","measured","getTopAnchor","anchorMode","getTopAnchorFromProjectedPolygons","project","projectedOuter","anchor","resolveRegionLabelStyle","px","py","fs","bw","oy","br","mergeRegionLabelStyle","resolveRegionLabelAutoLiftOffsetPx","enabled","zoomRange","liftCapZoom","minZoom","maxZoom","cap","tol","resolveDrawAreaTooltipStyle","fontSize","borderRadius","paddingX","paddingY","resolveTooltipCursorOffset","defaultDrawAreaTooltipFormatter","areaMm2","resolveDrawAreaTooltipOptions","format","cursorOffset","drawRegionLabel","text","canvasWidth","canvasHeight","clampToViewport","boxWidth","boxHeight","rawX","rawY","left","top","drawAreaTooltipBox","cursorScreen","drawInvertedFillMask","outerRing","holeRings","drawOverlayShapes","params","overlayShapes","imageOuterRing","worldToScreenPoints","baseStrokeStyle","onInvertedFillDebug","debugOverlay","shape","renderRings","closedRings","isStampTool","tool","resolveStampOptions","mm2ToUm2","createSquareFromCenter","halfLength","screenCenter","screenEdge","screenHL","createCircleFromCenter","buildStampCoords","stampTool","resolvedStampOptions","micronsToWorldPixels","getRectangleProjection","areaUm2","resolveRegionInteractionShadowStyle","resolveDrawPreviewFillColor","isValidPolygon","DrawLayer","stampOptions","brushOptions","projectorRef","onBrushTap","onDrawComplete","onPatchComplete","viewStateSignal","persistedRegions","patchRegions","persistedPolygons","drawFillColor","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","patchStrokeStyle","resolveRegionStrokeStyle","resolveRegionLabelStyleProp","hoveredRegionId","activeRegionId","regionLabelStyle","drawAreaTooltip","autoLiftRegionLabelAtMaxZoom","regionLabelAnchor","clampRegionLabelToViewport","regionLabelAutoLiftOffsetPx","invalidateRef","className","canvasRef","useRef","drawPendingRef","overlayDebugSnapshotRef","lastToolRef","sessionRef","mergedPersistedRegions","useMemo","mergedPatchRegions","preparedPersistedRegions","region","preparedPatchRegions","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedPatchStrokeStyle","resolvedDrawPreviewFillColor","resolvedLabelStyle","resolvedDrawAreaTooltipOptions","mergedStyle","resizeCanvas","useCallback","localScreenToWorld","lengthUm","mppValue","imageZoomValue","viewZoomRaw","continuousZoom","umPerScreenPixel","buildStampCoordsCallback","buildPreviewCoords","drawOverlay","entry","regionIndex","regionKey","state","resolved","interactionShadowStyle","screenOuter","screenHole","info","debugKey","debugSignature","preview","line","labelAutoLiftOffset","anchorScreen","dynamicLabelStyle","areaCoords","areaPx","requestDraw","resetSession","preserveCursor","toWorld","toLocalScreen","finishSession","tapPoint","screenPath","simplifyTolerance","screenPolygon","worldPolygon","handleStampAt","intent","appendBrushPoint","minScreenStep","minScreenStep2","prevScreen","handlePointerDown","handlePointerMove","minWorldStep","minWorldStep2","handlePointerUp","handlePointerLeave","changed","useEffect","observer","onKeyDown","jsx","hasWheelZoom","hasLegacyZoom","ViewerContext","createContext","ViewerContextProvider","useViewerContext","useContext","DrawingLayer","areaTooltip","onComplete","rendererRef","rendererSerial","setInteractionLock","normalizeExtent","intersects","GridSpatialIndex","nodeSize","finite","items","spanX","spanY","bucketCount","minCellX","maxCellX","minCellY","maxCellY","extent","query","serial","bucket","itemIndex","ratio","createSpatialIndex","ACCUM_VERTEX_SHADER","ACCUM_FRAGMENT_SHADER","COLOR_VERTEX_SHADER","COLOR_FRAGMENT_SHADER","HeatmapWebGLRenderer","supportsFloatAccum","accumVao","colorVao","pointBuffer","accumTexture","gradientTexture","framebuffer","accumResolution","accumPointSize","accumCoreRatio","accumPointAlpha","colorAccumTexture","colorGradientTexture","colorOpacity","colorCutoff","colorGain","colorGamma","colorBias","colorStretch","colorResolution","centerLocation","weightLocation","positionLocation","safeWidth","safeHeight","framebufferStatus","nextKey","gradient","stops","pixels","positions","weights","count","requiredFloats","bytes","interleaved","sourceOffset","targetOffset","HEATMAP_DRAW_ID","DEFAULT_GRADIENT","DEFAULT_RADIUS","DEFAULT_BLUR","DEFAULT_OPACITY","DEFAULT_MAX_RENDERED_POINTS","DEFAULT_SCALE_MODE","DEFAULT_DENSITY_CONTRAST","MIN_RASTER_SIZE","MAX_RASTER_SIZE","BASE_RADIUS_UNIT_PX","BASE_BLUR_UNIT_PX","MIN_VISIBLE_BUDGET","PYRAMID_SCALE_STEP","NORMALIZATION_SAMPLE_SIZE","NORMALIZATION_PERCENTILE","MAX_DENSITY_CONTRAST","resolveContinuousZoom","rawZoom","resolveRawZoomFromContinuousZoom","applyZoomThreshold","zoomThreshold","shiftedZoom","resolveThresholdLevelBias","resolveDensityWeightExponent","densityContrast","contrast","resolveCellSupportFactor","cellCount","resolveDensityCutoff","resolveDensityGain","resolveDensityGamma","resolveDensityBias","resolveDensityStretch","contrastT","zoomStart","zoomEnd","zoomT","baseStretch","zoomStretch","resolveNormalizedDensityWeight","weight","normalizationMaxWeight","safeWeight","safeMaxWeight","resolveNormalizationPercentile","resolveNormalizationUpperWeight","cells","sampleCount","sampledWeights","maxWeight","sampleIndex","cellIndex","right","percentile","percentileIndex","percentileWeight","resolveZoomVisibilityStrength","fadeStart","fadeEnd","baseStrength","resolveSampleWeightBoost","sampleProbability","effectiveStride","resolveLowResScale","totalPointCount","longestSide","deviceScale","lowZoomBoost","targetMaxSize","minScale","maxScale","buildViewportFrame","heatmapScale","rasterWidth","rasterHeight","rasterScaleX","rasterScaleY","effectiveScale","kernelRadiusPx","blurRadiusPx","outerWorldRadius","desiredCellWorldSize","resolvePointCount","data","maxByPosition","maxByWeight","hashCoordinate","seed","hashIntPair","hash","hashToUnitFloat","buildClipKey","polygonIndex","pointIndex","holeIndex","isSameHeatmapInput","clipKey","buildSourceData","clipPolygons","pointCount","xs","ys","ws","acceptedCount","rawWeight","pointIndexItems","maxDimension","cellSizes","cellSize","guard","collectVisiblePointIndices","sourceData","viewBounds","hits","visible","hit","resolveSampleProbability","visiblePointCount","maxRenderedPoints","budget","resolveSampleStride","shouldKeepSample","sampleHash","resolvePointAlpha","binCount","kernelOuterRadiusPx","rasterArea","kernelArea","coverage","smoothHeatmapValue","previousValue","nextValue","riseFactor","fallFactor","factor","getWebglRenderer","runtime","reason","projectClipRing","renderer","projected","applyClipPath","ensureSourceData","buildFixedState","logicalWidth","logicalHeight","blur","fixedZoom","currentRawZoom","referenceZoom","referenceRawZoom","frame","visiblePointIndices","sampleStride","drawHeatmapWebglPoints","pointAlpha","opacity","backgroundColor","webgl","targetCapacity","outerRadiusPx","sampleWeightBoost","drawCount","visibleIndex","rasterX","rasterY","offset","drawHeatmap","zoomVisibilityStrength","targetPointAlpha","renderedPointCount","fixedState","HeatmapLayer","scaleMode","clipToRegions","zIndex","onStats","registerDrawCallback","unregisterDrawCallback","requestOverlayRedraw","runtimeRef","stateRef","startedAt","stats","__heatmapLayerInternals","OVERLAY_DRAW_ID","OverlayLayer","shapes","drawRef","w2s","src","normalizeImageClasses","trimTrailingSlash","ensureLeadingSlash","joinImsTileRoot","tileBaseUrl","parsed","origin","normalizeImageInfo","ims","isIms","tileSize","maxTierZoom","tilePath","normalizedPath","imsTileRoot","tileUrlBuilder","tier","toTileUrl","shouldAttachAuthHeaderToOverviewTile","url","authToken","host","DEFAULT_OVERVIEW_MAP_OPTIONS","strokeSymmetricDashedPolygon","dashLen","gapLen","len","from","to","sideLen","fittedLen","scale","adjDash","adjGap","isSamePoint","compactPolygonPoints","compact","intersectAtX","intersectAtY","clipPolygonToRect","output","edges","edge","prevInside","currInside","toPositiveNumber","toFiniteRotation","getRotatedImageMetrics","safeRotation","translateX","translateY","corners","getOverviewImageLayout","metrics","imageAspect","boxAspect","contentWidth","contentHeight","worldToOverviewPoint","layout","contentX","contentY","rotatedX","rotatedY","overviewPointToWorld","pointX","pointY","boundsToCorners","isFiniteBounds","DEFAULT_CLOSE_BUTTON_STYLE","OverviewMap","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderWidth","maxThumbnailTiles","borderColor","viewportBorderColor","viewportBorderStyle","viewportFillColor","interactive","showThumbnail","position","onClose","closeIcon","closeButtonStyle","pos","draw","cssW","cssH","pixelW","pixelH","initialRotationDeg","cw","safeCorners","safeBounds","isDash","clippedCorners","fallbackCorners","toWorldFromClient","clientX","clientY","scaleX","scaleY","cxPx","cyPx","cwPx","chPx","nx","ny","recenterTo","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","previewScale","requests","bottom","useAuthHeader","results","dw","dh","rafId","tick","jsxs","PATCH_DRAW_ID","PatchLayer","regions","safeRegions","prep","filterPointDataByPolygons","empty","fillModes","pointIds","nextPositions","nextClasses","nextFillModes","nextIds","filterPointIndicesByPolygons","contextPromise","BBOX_PREFILTER_SHADER","hasWebGpu","nav","getNavigatorGpu","gpu","candidate","GPU_SHADER_STAGE_COMPUTE","GPU_BUFFER_USAGE_STORAGE","GPU_BUFFER_USAGE_COPY_DST","GPU_BUFFER_USAGE_COPY_SRC","GPU_BUFFER_USAGE_UNIFORM","GPU_BUFFER_USAGE_MAP_READ","GPU_MAP_MODE_READ","getWebGpuCapabilities","navGpu","adapter","getContext","device","bindGroupLayout","pipeline","align","prefilterPointsByBoundsWebGpu","boundsCount","safePointCount","positionBytes","boundsBytes","outputBytes","limit","positionsBuffer","boundsBuffer","outputBuffer","uniformBuffer","readBuffer","readBufferMapped","bindGroup","commandEncoder","mapped","filterPointDataByPolygonsHybrid","bridgeToDraw","safeCount","pointFillModes","bboxFlat","candidateMask","usedWebGpu","candidateCount","candidateIndices","candidateCursor","drawIndices","visibleCount","compactData","WorkerClient","createWorker","handlers","message","pending","worker","id","workerClient","msg","indices","paletteIndices","ids","terminateRoiClipWorker","filterPointDataByPolygonsInWorker","positionsCopy","classesCopy","fillModesCopy","idsCopy","resolve","reject","startMs","requestTicket","transfer","canceled","filterPointIndicesByPolygonsInWorker","EMPTY_CLIPPED_POINTS","usePointClipping","clipPointsToRois","clipMode","effectiveRoiRegions","onClipStats","clipRunIdRef","renderPointData","setRenderPointData","useState","runId","applyResult","inputCount","outputCount","MIN_POINT_HIT_GRID_SIZE","MAX_POINT_HIT_GRID_SIZE","POINT_HIT_GRID_DENSITY_SCALE","HASH_EMPTY","cellHash","cellX","cellY","mask","resolveGridSize","sourceWidth","sourceHeight","sanitizeDrawIndices","allValid","filtered","buildPointHitIndex","maxCountByPositions","invCellSize","pointCellX","pointCellY","validCount","pi","estimatedCells","hashCapacity","hashMask","tempHashKeys","tempHashCounts","pointCellSlot","slot","kx","oldCap","newKeys","newCounts","ocx","ocy","ns","cellKeys","cellOffsets","cellLengths","slotToCellIndex","cellIdx","pointIndices","fillCursor","ci","srcIdx","finalCap","finalMask","hashTable","lookupCellIndex","buildFromResponse","terminatePointHitIndexWorker","buildSyncFallback","buildPointSpatialIndexAsync","drawIndicesCopy","POINT_HIT_RADIUS_SCALE","MIN_POINT_HIT_RADIUS_PX","usePointHitTest","onPointHover","onPointClick","getCellByCoordinatesRef","drawTool","pointLayerId","shouldEnablePointHitTest","pointSpatialIndex","setPointSpatialIndex","hoveredPointIndexRef","hoveredPointIdRef","nextIndex","getCellByCoordinates","coordinate","pointSizePx","hitRadiusWorld","idxBuf","posBuf","baseCellX","baseCellY","cellRadius","nearestIndex","nearestDist2","nearestX","nearestY","off","pointId","emitPointHover","nextId","emitPointClick","button","hoveredPointIndex","nextPointLayerId","PointLayer","forwardRef","sizeByZoom","sizeByMagnification","weightByMagnification","strokeScale","innerFillOpacity","innerFillColor","clipEnabled","onHover","onClick","dashed","ref","layerIdRef","useImperativeHandle","layerId","REGION_LABEL_AUTO_LIFT_ANIMATION_DURATION_MS","smoothstep01","useRegionLabelAutoLift","drawInvalidateRef","setRegionLabelAutoLiftOffsetPx","regionLabelAutoLiftOffsetRef","regionLabelAutoLiftAnimationRef","applyRegionLabelAutoLiftOffset","clamped","cancelRegionLabelAutoLiftAnimation","animation","animateRegionLabelAutoLiftTo","target","clampedTarget","timestamp","elapsed","rawT","eased","syncRegionLabelAutoLiftTarget","REGION_CONTOUR_HIT_DISTANCE_PX","resolveRegionId","pointSegmentDistanceSq","lengthSq","isPointNearRing","maxDistanceSq","isPointNearPolygonContour","maxDistance","isScreenPointInsideLabel","screenCoord","prepareRegionHits","pickPreparedRegionAt","labelStyleResolver","labelAutoLiftOffsetPx","contourHitDistance","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","nextRegionLayerInstanceId","resolveRegionInteractionShadow","RegionLayer","strokeStyleProp","hoverStrokeStyleProp","activeStrokeStyleProp","resolveStrokeStyleProp","labelStyleProp","labelAnchor","autoLiftLabelAtMaxZoom","clampLabelToViewport","controlledHoveredRegionId","controlledActiveRegionId","onActiveChange","containerRef","registerViewStateListener","screenToWorld","worldToScreen","isInteractionLocked","safePolygons","effectiveRegions","uncontrolledHoveredRegionId","setUncontrolledHoveredRegionId","uncontrolledActiveRegionId","setUncontrolledActiveRegionId","isHoverControlled","isControlled","hoveredRegionIdRef","drawCallbackIdRef","labelDrawCallbackIdRef","instanceId","commitActive","staticLabelStyle","preparedRegions","preparedRegionHits","currentHover","regionDrawRef","drawRegions","_ctx","hovered","hover","activeS","resolver","shadow","drawId","labelDrawRef","drawLabels","labelS","autoLift","clampVp","autoLiftPx","rRef","pointerHitRef","container","currentLabelAnchor","hoverCb","worldCoord","hitResult","prevId","handleClick","clickCb","commit","TileViewerCanvas","shouldAttachAuthHeader","TileScheduler","nextVisibleKeys","inflight","queued","visibleKeys","nextQueue","earliestReadyAt","delay","now","controller","inflightEntry","nextAttempt","retryDelay","existing","attempt","exp","jitter","addRendererCanvasEventListeners","removeRendererCanvasEventListeners","resizeCanvasViewport","camera","DEFAULT_ROTATION_DRAG_SENSITIVITY","MIN_POINT_SIZE_PX","MAX_POINT_SIZE_PX","DEFAULT_POINT_SIZE_STOPS","MIN_STROKE_SCALE","MAX_STROKE_SCALE","MIN_POINT_OPACITY","MAX_POINT_OPACITY","MIN_POINT_INNER_FILL_OPACITY","MAX_POINT_INNER_FILL_OPACITY","MIN_IMAGE_COLOR_INPUT","MAX_IMAGE_COLOR_INPUT","MAX_VIEW_TRANSITION_DURATION_MS","DEFAULT_POINT_INNER_FILL_COLOR","isSameArrayView","clonePointSizeStops","stop","clonePointSizeMagnificationStops","clonePointWeightMagnificationStops","normalizePointSizeStops","pointSizeByZoom","zoomKey","rawSize","size","normalizePointSizeMagnificationStops","pointSizeByMagnification","magnificationKey","magnification","normalizePointWeightMagnificationStops","pointWeightByMagnification","normalizeStrokeScale","arePointSizeStopsEqual","arePointSizeMagnificationStopsEqual","arePointWeightMagnificationStopsEqual","resolvePointSizeByZoomStops","span","slope","resolvePointSizeByMagnificationStops","resolvePointWeightByMagnificationStops","normalizePointOpacity","normalizePointLineDash","normalizePointInnerFillOpacity","normalizePointInnerFillColor","rgba","normalizeImageColorInput","toNormalizedImageColorSettings","settings","brightnessInput","contrastInput","saturationInput","linearEasing","normalizeViewTransitionDuration","duration","normalizeZoomOverride","normalizeTransitionEasing","easing","getPointerAngleRad","cancelDrag","config","cancelViewAnimation","wantsRotate","clampViewState","emitViewState","requestRender","nextAngle","prevAngle","rawDelta","delta","sensitivityScale","worldDx","worldDy","handleWheel","onZoomBy","applyWheelZoomDelta","SNAP_DELTA_THRESHOLD","deltaY","applyWheelSnapDelta","snapState","onSnapZoom","inputDirection","direction","handleWheelSnap","handleDoubleClick","handleContextMenu","dragging","getViewBounds","extentX","extentY","marginX","marginY","halfW","halfH","minCenterX","maxCenterX","minCenterY","maxCenterY","nextCenterX","nextCenterY","selectTier","rawTier","intersectsBounds","getVisibleTilesForTier","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","getVisibleTiles","onPointerDownWithLock","onPointerMoveWithLock","onPointerUpWithLock","onDoubleClickWithLock","onContextMenuWithLock","cancelInteractionDrag","createRendererInputHandlers","trimTileCache","maxCacheTiles","targetSize","oldestKey","oldestValue","createTextureFromBitmap","handleTileLoaded","frameSerial","destroyed","contextLost","deleteCachedTextures","handleContextLost","tileScheduler","onContextLost","destroyRenderer","pointProgram","maxExclusive","idx","getZeroFillModes","zeroFillModes","setPointPalette","nextPalette","paletteSize","setPointData","hasFillModes","nextPaletteIndices","hasDrawIndices","nextDrawIndices","prevHasFillModes","geometryChanged","drawIndicesChanged","nextRuntime","currentPointData","renderFrame","tileProgram","imageColorSettings","pointLayers","fallbackTiles","renderedTiles","missingTiles","tilesToSchedule","PREFETCH_DISTANCE_PENALTY","prefetchTiers","prefetchTier","prefetchCandidates","renderedPoints","pointDrawCalls","layer","initTileProgram","uCamera","uBounds","uTexture","uBrightness","uContrast","uSaturation","vbo","aUnit","aUv","initPointProgram","uPointSize","uPointCssSize","uPointOpacity","uPointStrokeScale","uPointInnerFillAlpha","uPointInnerFillColor","uPalette","uPaletteSize","uPointLineDash","posBuffer","classBuffer","fillModeBuffer","indexBuffer","paletteTexture","posLoc","classLoc","fillModeLoc","startViewAnimation","durationMs","onUpdate","resolveDefaultZoomBounds","fitZoom","resolveZoomBounds","minZoomOverride","maxZoomOverride","defaults","resolveTargetViewState","computeFitToImageTarget","viewportWidth","viewportHeight","clampedZoom","visibleWorldW","visibleWorldH","computeZoomByTarget","nextZoom","vp","computeZoomToTarget","targetZoom","SNAP_ZOOM_DURATION_MS","normalizeZoomSnaps","magnifications","maxMag","mag","resolveSnapTarget","validSnaps","fitAsMin","snap","startZoomPivotAnimation","pivotScreenX","pivotScreenY","fromState","pivotWorldX","pivotWorldY","safeTargetZoom","screenDx","screenDy","computeOffsetForZoom","finalOffset","isComplete","DEFAULT_POINT_LAYER_ID","WsiTileRenderer","cacheTileLoaded","attemptCount","inputHandlers","resolveManagedTargetViewState","clampManagedViewState","cancelManagedViewAnimation","created","pointCssSizePx","cancelAnimation","nextMinOverride","nextMaxOverride","transition","valid","setManagedPointPalette","setManagedPointData","locked","nextStops","color","cancelInputDrag","getManagedViewBounds","magnificationStops","vw","vh","fitTarget","ongoing","baseZoom","frameStartMs","getManagedVisibleTiles","getManagedVisibleTilesForTier","intersectsManagedBounds","schedulerStats","_event","EMPTY_DRAW_CALLBACKS","WsiViewer","onViewStateChange","onTileError","onContextRestored","initialRotate","fitNonce","rotationResetNonce","ctrlDragRotate","viewTransition","zoomSnaps","zoomSnapFitAsMin","panExtent","preserveDrawingBuffer","onPointerWorldMove","debugOverlayStyle","children","overlayCanvasRef","overviewInvalidateRef","drawCallbacksRef","overlayPendingRef","interactionLocksRef","viewStateListenersRef","onViewStateChangeRef","onStatsRef","onTileErrorRef","onContextLostRef","onContextRestoredRef","setRendererSerial","debugStats","setDebugStats","debugOverlayRef","mergedDebugOverlayStyle","initialRotateValue","toExternalViewState","toInternalViewState","handleRendererStats","debugOverlayText","drawOverlayFrame","entries","priority","listener","emitViewStateChange","nextInternal","listeners","snapshot","contextValue","onPointerWorldMoveRef","cb","insideImage","prepareRegions","MAX_REGION_GRID_SIZE","EMPTY_CANDIDATE_REGION_INDICES","toGridCell","gridSize","buildPreparedRegionGridIndex","estimated","cellWidth","cellHeight","buckets","regionArrayIndex","getCandidateRegionIndices","resolveClassId","paletteIndex","paletteIndexToClassId","fromArray","fromMap","computeRoiPointGroups","baseCount","regionClassCounters","regionTotalCounters","preparedRegionIndex","insideCount","bestRegion","candidateRegionIndices","regionClassMap","includeEmptyRegions","groups","totalCount","classMap","classCounts","stripSridPrefix","isWordChar","isDigitChar","isNumberStartChar","WktParser","rawInput","geometryType","geometryTypeUpper","maybeDimension","dimUpper","nested","toPolygonCoordinates","toMultiPolygonCoordinates","saved","word","values","num","isCoordinate","ringValue","coordValue","polygonValue","parseWkt","wkt"],"mappings":";;;;;AAAA,SAASA,GAAcC,GAA4BC,GAAcC,GAA6B;AAC5F,QAAMC,IAASH,EAAG,aAAaC,CAAI;AACnC,MAAI,CAACE;AACH,UAAM,IAAI,MAAM,0BAA0B;AAO5C,MAJAH,EAAG,aAAaG,GAAQD,CAAM,GAC9BF,EAAG,cAAcG,CAAM,GAGnB,CADOH,EAAG,mBAAmBG,GAAQH,EAAG,cAAc,GACjD;AACP,UAAMI,IAAMJ,EAAG,iBAAiBG,CAAM,KAAK;AAC3C,UAAAH,EAAG,aAAaG,CAAM,GAChB,IAAI,MAAMC,CAAG;AAAA,EACrB;AAEA,SAAOD;AACT;AAEO,SAASE,GAAcL,GAA4BM,GAAsBC,GAAsC;AACpH,QAAMC,IAAeT,GAAcC,GAAIA,EAAG,eAAeM,CAAY,GAC/DG,IAAiBV,GAAcC,GAAIA,EAAG,iBAAiBO,CAAc,GAErEG,IAAUV,EAAG,cAAA;AACnB,MAAI,CAACU;AACH,UAAAV,EAAG,aAAaQ,CAAY,GAC5BR,EAAG,aAAaS,CAAc,GACxB,IAAI,MAAM,2BAA2B;AAW7C,MARAT,EAAG,aAAaU,GAASF,CAAY,GACrCR,EAAG,aAAaU,GAASD,CAAc,GACvCT,EAAG,YAAYU,CAAO,GAEtBV,EAAG,aAAaQ,CAAY,GAC5BR,EAAG,aAAaS,CAAc,GAG1B,CADOT,EAAG,oBAAoBU,GAASV,EAAG,WAAW,GAChD;AACP,UAAMI,IAAMJ,EAAG,kBAAkBU,CAAO,KAAK;AAC7C,UAAAV,EAAG,cAAcU,CAAO,GAClB,IAAI,MAAMN,CAAG;AAAA,EACrB;AAEA,SAAOM;AACT;AAEO,SAASC,GAAuBX,GAA4BU,GAAuBE,GAA2C;AACnI,QAAMC,IAAWb,EAAG,mBAAmBU,GAASE,CAAW;AAC3D,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,mCAAmCD,CAAW,EAAE;AAElE,SAAOC;AACT;AAEO,SAASC,GAAcC,GAA2BC,GAAuE;AAC9H,QAAMC,IAAUF,EAAO,WAAW,UAAU;AAAA,IAC1C,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,uBAAuBC,GAAS,yBAAyB;AAAA,IACzD,iBAAiB;AAAA,EAAA,CAClB;AAED,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,0BAA0B;AAG5C,SAAOA;AACT;AC7DA,SAASC,GAAUC,GAAqB;AACtC,SAAQA,IAAM,KAAK,KAAM;AAC3B;AAEO,MAAMC,GAAY;AAAA,EAAlB;AACG,IAAAC,EAAA,uBAAgB;AAChB,IAAAA,EAAA,wBAAiB;AAEjB,IAAAA,EAAA,mBAAuB;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA;AAAA,EAGf,YAAYC,GAAeC,GAAsB;AAC/C,SAAK,gBAAgB,KAAK,IAAI,GAAGD,CAAK,GACtC,KAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EAC1C;AAAA,EAEA,kBAAqD;AACnD,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IAAA;AAAA,EAEjB;AAAA,EAEA,aAAaC,GAAgC;AAC3C,IAAIA,EAAK,YAAY,WACnB,KAAK,UAAU,UAAUA,EAAK,UAG5BA,EAAK,YAAY,WACnB,KAAK,UAAU,UAAUA,EAAK,UAG5BA,EAAK,SAAS,WAChB,KAAK,UAAU,OAAO,KAAK,IAAI,MAAQA,EAAK,IAAI,IAG9C,OAAOA,EAAK,eAAgB,YAAY,OAAO,SAASA,EAAK,WAAW,MAC1E,KAAK,UAAU,cAAcA,EAAK;AAAA,EAEtC;AAAA,EAEA,eAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EACnB;AAAA,EAEA,YAAwB;AACtB,UAAMC,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI;AAC/C,WAAO;AAAA,MACL,KAAK,UAAU,UAAU,KAAK,iBAAiB,IAAIA;AAAA,MACnD,KAAK,UAAU,UAAU,KAAK,kBAAkB,IAAIA;AAAA,IAAA;AAAA,EAExD;AAAA,EAEA,UAAUC,GAAiBC,GAAuB;AAChD,UAAMF,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI;AAC/C,SAAK,UAAU,UAAUC,IAAU,KAAK,iBAAiB,IAAID,IAC7D,KAAK,UAAU,UAAUE,IAAU,KAAK,kBAAkB,IAAIF;AAAA,EAChE;AAAA,EAEA,cAAcG,GAAiBC,GAA6B;AAC1D,UAAMJ,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,GACzC,CAACC,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1BG,IAAc,KAAK,UAAU,eAAe,GAC5CC,KAAMH,IAAU,KAAK,gBAAgB,OAAOH,GAC5CO,KAAMH,IAAU,KAAK,iBAAiB,OAAOJ,GAC7CQ,IAAMf,GAAUY,CAAW,GAC3BI,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG;AACxB,WAAO,CAACP,IAAUK,IAAKG,IAAMF,IAAKG,GAAKR,IAAUI,IAAKI,IAAMH,IAAKE,CAAG;AAAA,EACtE;AAAA,EAEA,cAAcE,GAAgBC,GAA4B;AACxD,UAAMZ,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,GACzC,CAACC,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1BG,IAAc,KAAK,UAAU,eAAe,GAC5CC,IAAKK,IAASV,GACdM,IAAKK,IAASV,GACdM,IAAMf,GAAUY,CAAW,GAC3BI,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBK,IAAKP,IAAKG,IAAMF,IAAKG,GACrBI,IAAK,CAACR,IAAKI,IAAMH,IAAKE;AAC5B,WAAO;AAAA,MACL,KAAK,gBAAgB,MAAMI,IAAKb;AAAA,MAChC,KAAK,iBAAiB,MAAMc,IAAKd;AAAA,IAAA;AAAA,EAErC;AAAA,EAEA,iBAAmE;AACjE,UAAMe,IAAI,KAAK,eACTC,IAAI,KAAK;AACf,WAAO;AAAA,MACL,KAAK,cAAc,GAAG,CAAC;AAAA,MACvB,KAAK,cAAcD,GAAG,CAAC;AAAA,MACvB,KAAK,cAAcA,GAAGC,CAAC;AAAA,MACvB,KAAK,cAAc,GAAGA,CAAC;AAAA,IAAA;AAAA,EAE3B;AAAA,EAEA,YAA0B;AACxB,UAAMhB,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,GACzCK,IAAc,KAAK,UAAU,eAAe;AAElD,QAAIA,MAAgB,GAAG;AACrB,YAAMY,IAAY,KAAK,gBAAgBjB,GACjCkB,IAAa,KAAK,iBAAiBlB,GACnCmB,IAAK,IAAIF,GACTG,IAAK,KAAKF,GACVG,IAAK,KAAK,KAAK,UAAU,UAAUF,GACnCG,IAAK,IAAI,KAAK,UAAU,UAAUF;AACxC,aAAO,IAAI,aAAa,CAACD,GAAI,GAAG,GAAG,GAAGC,GAAI,GAAGC,GAAIC,GAAI,CAAC,CAAC;AAAA,IACzD;AAEA,UAAM,CAACrB,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1BM,IAAMf,GAAUY,CAAW,GAC3BI,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBe,IAAM,IAAIvB,IAAOS,IAAO,KAAK,eAC7Be,IAAM,IAAIxB,IAAOU,IAAO,KAAK,eAC7Be,IAAM,IAAIzB,IAAOU,IAAO,KAAK,gBAC7BgB,IAAM,KAAK1B,IAAOS,IAAO,KAAK,gBAC9BY,IAAK,EAAEE,IAAKtB,IAAUuB,IAAKtB,IAC3BoB,IAAK,EAAEG,IAAKxB,IAAUyB,IAAKxB;AACjC,WAAO,IAAI,aAAa,CAACqB,GAAIE,GAAI,GAAGD,GAAIE,GAAI,GAAGL,GAAIC,GAAI,CAAC,CAAC;AAAA,EAC3D;AACF;ACvHA,MAAMK,KAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAsBhBC,KAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAajB,MAAMC,GAAe;AAAA,EAsB1B,YAAYtC,GAAgC;AArB3B,IAAAK,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAID,GAAA;AACb,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAET,IAAAA,EAAA,eAAsB,CAAA;AACtB,IAAAA,EAAA,iBAAyB;AACzB,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,gBAAS;AACT,IAAAA,EAAA,6BAAsB;AAG5B,SAAK,SAASL,EAAQ,QACtB,KAAK,aAAa,KAAK,IAAI,GAAGA,EAAQ,UAAU,GAChD,KAAK,cAAc,KAAK,IAAI,GAAGA,EAAQ,WAAW,GAClD,KAAK,aAAaA,EAAQ,cAAc,CAAC,MAAM,MAAM,MAAM,CAAC,GAE5D,KAAK,KAAKF,GAAc,KAAK,QAAQ,EAAE,uBAAuBE,EAAQ,uBAAuB,GAC7F,KAAK,UAAUX,GAAc,KAAK,IAAI+C,IAAeC,EAAe;AAEpE,UAAME,IAAM,KAAK,GAAG,kBAAA,GACdC,IAAa,KAAK,GAAG,aAAA;AAC3B,QAAI,CAACD,KAAO,CAACC;AACX,YAAM,IAAI,MAAM,iCAAiC;AAGnD,SAAK,MAAMD,GACX,KAAK,aAAaC,GAElB,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,KAAK,UAAU;AAExD,UAAMC,IAAe,IAAI,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAEtF,SAAK,GAAG,WAAW,KAAK,GAAG,cAAcA,GAAc,KAAK,GAAG,WAAW;AAE1E,UAAMC,IAAe,KAAK,GAAG,kBAAkB,KAAK,SAAS,OAAO,GAC9DC,IAAa,KAAK,GAAG,kBAAkB,KAAK,SAAS,KAAK;AAChE,QAAID,IAAe,KAAKC,IAAa;AACnC,YAAM,IAAI,MAAM,oCAAoC;AAGtD,UAAMC,IAAS,IAAI,aAAa;AAChC,SAAK,GAAG,wBAAwBF,CAAY,GAC5C,KAAK,GAAG,oBAAoBA,GAAc,GAAG,KAAK,GAAG,OAAO,IAAOE,GAAQ,CAAC,GAC5E,KAAK,GAAG,wBAAwBD,CAAU,GAC1C,KAAK,GAAG,oBAAoBA,GAAY,GAAG,KAAK,GAAG,OAAO,IAAOC,GAAQ,IAAI,aAAa,iBAAiB,GAE3G,KAAK,GAAG,gBAAgB,IAAI,GAC5B,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,IAAI,GAE7C,KAAK,kBAAkBjD,GAAuB,KAAK,IAAI,KAAK,SAAS,SAAS,GAC9E,KAAK,kBAAkBA,GAAuB,KAAK,IAAI,KAAK,SAAS,SAAS,GAC9E,KAAK,mBAAmBA,GAAuB,KAAK,IAAI,KAAK,SAAS,UAAU,GAE5EK,EAAQ,qBACV,KAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,EAAQ,gBAAgB,IAGnD,KAAK,iBAAiB,IAAI,eAAe,MAAM;AAC7C,WAAK,OAAA;AAAA,IACP,CAAC,GAED,KAAK,eAAe,QAAQ,KAAK,MAAM,GACvC,KAAK,OAAA;AAAA,EACP;AAAA,EAEA,MAAM,SAAS6C,GAAwC;AACrD,QAAI,KAAK;AACP;AAGF,UAAMC,IAAU,EAAE,KAAK,aAEjBC,IAAS,MAAM,QAAQ;AAAA,MAC3BF,EAAM,IAAI,OAAMG,MACK,MAAM,KAAK,SAASA,GAAMF,CAAO,CAErD;AAAA,IAAA;AAGH,QAAI,KAAK,aAAaA,MAAY,KAAK,aAAa;AAClD,iBAAWE,KAAQD;AACjB,QAAIC,KACF,KAAK,GAAG,cAAcA,EAAK,OAAO;AAGtC;AAAA,IACF;AAEA,SAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQD,EAAO,OAAO,CAACC,MAA6BA,MAAS,IAAI,GACtE,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,aAAaC,GAAqC;AAChD,SAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,CAAS,GAClC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,eAA0B;AACxB,WAAO,KAAK,OAAO,aAAA;AAAA,EACrB;AAAA,EAEA,UAAgB;AACd,IAAI,KAAK,cAIT,KAAK,YAAY,IACjB,KAAK,eAAe,GAEhB,KAAK,YAAY,SACnB,qBAAqB,KAAK,OAAO,GACjC,KAAK,UAAU,OAGjB,KAAK,eAAe,WAAA,GACpB,KAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQ,CAAA,GAEb,KAAK,GAAG,aAAa,KAAK,UAAU,GACpC,KAAK,GAAG,kBAAkB,KAAK,GAAG,GAClC,KAAK,GAAG,cAAc,KAAK,OAAO;AAAA,EACpC;AAAA,EAEA,MAAc,SAASD,GAAsBF,GAA6C;AACxF,QAAI;AACF,YAAMI,IAAW,MAAM,MAAMF,EAAK,GAAG;AACrC,UAAI,CAACE,EAAS;AACZ,cAAM,IAAI,MAAM,sBAAsBA,EAAS,MAAM,IAAIA,EAAS,UAAU,EAAE;AAGhF,YAAMC,IAAO,MAAMD,EAAS,KAAA,GACtBE,IAAS,MAAM,kBAAkBD,CAAI;AAE3C,UAAI,KAAK,aAAaL,MAAY,KAAK;AACrC,eAAAM,EAAO,MAAA,GACA;AAGT,YAAMC,IAAU,KAAK,GAAG,cAAA;AACxB,UAAI,CAACA;AACH,cAAAD,EAAO,MAAA,GACD,IAAI,MAAM,gCAAgC;AAGlD,kBAAK,GAAG,YAAY,KAAK,GAAG,YAAYC,CAAO,GAC/C,KAAK,GAAG,YAAY,KAAK,GAAG,qBAAqB,CAAC,GAClD,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,gBAAgB,KAAK,GAAG,aAAa,GACvF,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,gBAAgB,KAAK,GAAG,aAAa,GACvF,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAoB,KAAK,GAAG,MAAM,GACpF,KAAK,GAAG,cAAc,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAoB,KAAK,GAAG,MAAM,GACpF,KAAK,GAAG,WAAW,KAAK,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,KAAK,GAAG,MAAM,KAAK,GAAG,eAAeD,CAAM,GACnG,KAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5CA,EAAO,MAAA,GAEA;AAAA,QACL,IAAIJ,EAAK;AAAA,QACT,QAAQA,EAAK;AAAA,QACb,SAAAK;AAAA,MAAA;AAAA,IAEJ,SAASC,GAAO;AACd,qBAAQ,MAAM,sCAAsCN,EAAK,EAAE,IAAIM,CAAK,GAC7D;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,SAAe;AACrB,QAAI,KAAK;AACP;AAGF,UAAMC,IAAO,KAAK,OAAO,sBAAA,GACnBC,IAAW,KAAK,IAAI,GAAGD,EAAK,SAAS,KAAK,OAAO,eAAe,CAAC,GACjEE,IAAY,KAAK,IAAI,GAAGF,EAAK,UAAU,KAAK,OAAO,gBAAgB,CAAC,GACpEG,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9CC,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMH,IAAWE,CAAG,CAAC,GACpDE,IAAe,KAAK,IAAI,GAAG,KAAK,MAAMH,IAAYC,CAAG,CAAC;AAE5D,KAAI,KAAK,OAAO,UAAUC,KAAe,KAAK,OAAO,WAAWC,OAC9D,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGvB,KAAK,OAAO,YAAYJ,GAAUC,CAAS,GAC3C,KAAK,GAAG,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,GAExD,CAAC,KAAK,UAAU,CAAC,KAAK,wBACxB,KAAK,WAAA,GACL,KAAK,SAAS,KAGhB,KAAK,cAAA;AAAA,EACP;AAAA,EAEQ,aAAmB;AACzB,UAAMI,IAAW,KAAK,OAAO,gBAAA,GAEvBpD,IAAO,KAAK,IAAIoD,EAAS,QAAQ,KAAK,YAAYA,EAAS,SAAS,KAAK,WAAW,GACpFC,IAAW,OAAO,SAASrD,CAAI,KAAKA,IAAO,IAAIA,IAAO,GAEtDsD,IAAoBF,EAAS,QAAQC,GACrCE,IAAqBH,EAAS,SAASC,GAEvCG,KAAW,KAAK,aAAaF,KAAqB,KAClDG,KAAW,KAAK,cAAcF,KAAsB;AAE1D,SAAK,OAAO,aAAa;AAAA,MACvB,MAAMF;AAAA,MACN,SAAAG;AAAA,MACA,SAAAC;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEQ,gBAAsB;AAC5B,IAAI,KAAK,YAAY,QAAQ,KAAK,cAIlC,KAAK,UAAU,sBAAsB,MAAM;AACzC,WAAK,UAAU,MACf,KAAK,OAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,QAAI,MAAK,WAIT;AAAA,WAAK,GAAG,WAAW,KAAK,WAAW,CAAC,GAAG,KAAK,WAAW,CAAC,GAAG,KAAK,WAAW,CAAC,GAAG,KAAK,WAAW,CAAC,CAAC,GACjG,KAAK,GAAG,MAAM,KAAK,GAAG,gBAAgB,GAEtC,KAAK,GAAG,WAAW,KAAK,OAAO,GAC/B,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG,iBAAiB,KAAK,iBAAiB,IAAO,KAAK,OAAO,WAAW,GAC7E,KAAK,GAAG,UAAU,KAAK,kBAAkB,CAAC;AAE1C,iBAAWlB,KAAQ,KAAK;AACtB,aAAK,GAAG,cAAc,KAAK,GAAG,QAAQ,GACtC,KAAK,GAAG,YAAY,KAAK,GAAG,YAAYA,EAAK,OAAO,GACpD,KAAK,GAAG,UAAU,KAAK,iBAAiBA,EAAK,OAAO,CAAC,GAAGA,EAAK,OAAO,CAAC,GAAGA,EAAK,OAAO,CAAC,GAAGA,EAAK,OAAO,CAAC,CAAC,GACtG,KAAK,GAAG,WAAW,KAAK,GAAG,gBAAgB,GAAG,CAAC;AAGjD,WAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5C,KAAK,GAAG,gBAAgB,IAAI;AAAA;AAAA,EAC9B;AAAA,EAEQ,aAAaH,GAA2B;AAC9C,eAAWG,KAAQH;AACjB,WAAK,GAAG,cAAcG,EAAK,OAAO;AAAA,EAEtC;AACF;ACnUA,MAAMmB,GAAE;AAAA,EACN,YAAY,GAAGC,GAAG;AAChB,SAAK,OAAO,MAAM,KAAK,MAAM,GAAG,KAAK,OAAOA,GAAG,KAAK,OAAO,MAAM,KAAK,QAAQ;AAAA,EAChF;AACF;AACA,SAASC,GAAEC,GAAG,GAAG;AACf,SAAOA,IAAI,IAAI,IAAIA,IAAI,IAAI,KAAK;AAClC;AACA,SAASC,GAAED,GAAG,GAAGF,GAAG;AAClB,QAAM,IAAI,IAAID,GAAE,MAAM,IAAI;AAC1B,MAAIK,IAAI,GAAGC,IAAI;AACf,aAAW;AACT,UAAMC,IAAIN,EAAEE,GAAG,EAAE,GAAG;AACpB,QAAII,IAAI,GAAG;AACT,UAAI,EAAE,SAAS,KAAM;AACrB,UAAIN,EAAEE,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG;AACxB,cAAMK,IAAI,EAAE;AACZ,YAAI,EAAE,OAAOA,EAAE,OAAOA,EAAE,QAAQ,GAAG,IAAIA,GAAG,EAAE,SAAS,KAAM;AAAA,MAC7D;AACA,MAAAF,EAAE,OAAO,GAAGA,IAAI,GAAG,IAAI,EAAE;AAAA,IAC3B,WAAWC,IAAI,GAAG;AAChB,UAAI,EAAE,UAAU,KAAM;AACtB,UAAIN,EAAEE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG;AACzB,cAAMK,IAAI,EAAE;AACZ,YAAI,EAAE,QAAQA,EAAE,MAAMA,EAAE,OAAO,GAAG,IAAIA,GAAG,EAAE,UAAU,KAAM;AAAA,MAC7D;AACA,MAAAH,EAAE,QAAQ,GAAGA,IAAI,GAAG,IAAI,EAAE;AAAA,IAC5B,MAAO;AAAA,EACT;AACA,SAAOA,EAAE,QAAQ,EAAE,MAAMC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM;AACjF;AACA,SAASG,GAAEN,GAAG,GAAGF,GAAG,GAAG;AACrB,QAAMI,IAAI,IAAIL,GAAEG,GAAG,CAAC;AACpB,MAAIF,MAAM;AACR,WAAOI,EAAE,OAAOA,EAAE,QAAQ,MAAMA;AAClC,EAAAJ,IAAIG,GAAED,GAAGF,GAAG,CAAC;AACb,QAAMK,IAAI,EAAEH,GAAGF,EAAE,GAAG;AACpB,SAAOK,IAAI,KAAKD,EAAE,OAAOJ,EAAE,MAAMI,EAAE,QAAQJ,GAAGA,EAAE,OAAO,QAAQK,KAAK,MAAMD,EAAE,QAAQJ,EAAE,OAAOI,EAAE,OAAOJ,GAAGA,EAAE,QAAQ,OAAOI;AAC5H;AACA,SAASK,GAAEP,GAAG,GAAGF,GAAG;AAClB,MAAI,IAAI,MAAMI,IAAI;AAClB,MAAI,GAAG;AACL,QAAID,GAAED,GAAG,GAAGF,CAAC;AACb,UAAMK,IAAIL,EAAE,EAAE,KAAKE,CAAC;AACpB,IAAAG,MAAM,KAAK,IAAI,EAAE,MAAMD,IAAI,EAAE,SAASC,IAAI,KAAKD,IAAI,EAAE,OAAO,EAAE,QAAQ,MAAM,IAAI,MAAM,IAAI,EAAE,MAAM,EAAE,OAAO,MAAMA,IAAI;AAAA,EACvH;AACA,SAAO,EAAE,MAAM,GAAG,OAAOA,EAAC;AAC5B;AACA,SAAShD,GAAE8C,GAAG,GAAGF,GAAG;AAClB,SAAO,MAAM,OAAOE,KAAKA,MAAM,SAAS,IAAIC,GAAED,EAAE,KAAK,GAAGF,CAAC,GAAG,EAAE,OAAOE,IAAI;AAC3E;AACA,SAASQ,GAAER,GAAG,GAAGF,GAAG,GAAGI,GAAG;AACxB,MAAIF,GAAG;AACL,MAAE,GAAG,CAAC,GAAGF,IAAI,SAAS,MAAM,GAAGI,EAAEF,CAAC,CAAC;AAAA,CACtC;AACG,UAAMG,IAAI,KAAKL,IAAI,SAAS;AAC5B,IAAAE,EAAE,QAAQQ,GAAER,EAAE,MAAMG,GAAG,IAAI,GAAGD,CAAC,GAAGF,EAAE,SAASQ,GAAER,EAAE,OAAOG,GAAG,IAAI,GAAGD,CAAC;AAAA,EACrE;AACF;AACA,MAAMO,GAAE;AAAA,EACN,YAAY,IAAIV,IAAG;AACjB,SAAK,QAAQ,MAAM,KAAK,QAAQ,GAAG,KAAK,cAAc;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAIA,OAAO,GAAGD,GAAG;AACX,WAAO,KAAK,SAAS,KAAK,QAAQQ,GAAE,GAAGR,GAAG,KAAK,OAAO,KAAK,WAAW;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAIA,IAAI,GAAGA,GAAG;AACR,UAAM,IAAI,IAAID,GAAE,GAAGC,CAAC;AACpB,SAAK,UAAU,SAAS,EAAE,OAAO,EAAE,QAAQ,MAAM,KAAK,SAAS,KAAK,QAAQ;AAC5E,UAAMI,IAAI,KAAK,aAAaC,IAAIF,GAAE,GAAG,KAAK,OAAOC,CAAC,GAAGE,IAAIF,EAAE,GAAGC,EAAE,GAAG;AACnE,WAAOC,MAAM,IAAI,KAAK,QAAQD,KAAKC,IAAI,KAAK,EAAE,OAAOD,EAAE,MAAM,EAAE,QAAQA,GAAGA,EAAE,OAAO,QAAQC,IAAI,MAAM,EAAE,QAAQD,EAAE,OAAO,EAAE,OAAOA,GAAGA,EAAE,QAAQ,OAAO,KAAK,SAAS,KAAK,QAAQ,IAAI,KAAK;AAAA,EAC3L;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,GAAG;AACR,SAAK,QAAQ,KAAK,QAAQ,GAAG,KAAK,OAAO,KAAK,WAAW;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAIA,QAAQ,GAAGL,GAAG,GAAG;AACf,QAAII;AACJ,WAAOJ,MAAM,OAAO,QAAQA,IAAIG,GAAE,GAAGH,GAAG,CAAC,GAAG,EAAE,GAAGA,EAAE,GAAG,MAAM,KAAKA,EAAE,SAAS,OAAOI,IAAIJ,EAAE,SAASI,IAAID,GAAE,GAAGH,EAAE,MAAM,CAAC,GAAGI,EAAE,QAAQJ,EAAE,QAAQ,KAAK,SAASI,KAAKJ;AAAA,EAChK;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM;AACJ,QAAI,IAAI,KAAK;AACb,QAAI,GAAG;AACL,aAAO,EAAE,OAAQ,KAAI,EAAE;AACvB,aAAO,KAAK,QAAQG,GAAE,EAAE,KAAK,KAAK,OAAO,KAAK,WAAW,GAAG,KAAK,QAAQ,KAAK,QAAQ,EAAE,KAAK,KAAK,OAAO,KAAK,WAAW,GAAG,EAAE,KAAK,EAAE,KAAK,MAAM,EAAE,KAAI;AAAA,IACxJ;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAIA,WAAW,GAAG;AACZ,QAAIH,IAAI,KAAK;AACb,UAAM,IAAI,KAAK;AACf,WAAOA,KAAK;AACV,YAAMI,IAAI,EAAE,GAAGJ,EAAE,GAAG;AACpB,UAAII,MAAM,EAAG,QAAOJ;AACpB,MAAAI,IAAI,IAAIJ,IAAIA,EAAE,OAAOA,IAAIA,EAAE;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA,EACA,KAAK,GAAG;AACN,WAAO,KAAK,UAAU,KAAK,QAAQG,GAAE,GAAG,KAAK,OAAO,KAAK,WAAW,GAAG,KAAK,YAAY,GAAG,KAAK,MAAM,GAAG,MAAM,KAAK,OAAO,KAAK;AAAA,EAClI;AAAA,EACA,SAAS,GAAG;AACV,QAAIH,IAAI,KAAK;AACb,UAAM,IAAI,KAAK;AACf,WAAOA,KAAK;AACV,YAAMI,IAAI,EAAE,GAAGJ,EAAE,GAAG;AACpB,UAAII,MAAM,EAAG,QAAO;AACpB,MAAAA,IAAI,IAAIJ,IAAIA,EAAE,OAAOA,IAAIA,EAAE;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQ,GAAGA,GAAG;AACZ,QAAI,IAAI,KAAK;AACb,UAAMI,IAAI,CAAA;AACV,QAAIC,IAAI;AACR,WAAO,CAACA;AACN,YAAM,QAAQD,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,QAAQA,EAAE,WAAW,KAAK,IAAIA,EAAE,IAAG,GAAI,EAAE,KAAKJ,GAAG,CAAC,GAAG,IAAI,EAAE,SAASK,IAAI;AACzG,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAIA,MAAM,GAAGL,GAAG,GAAGI,GAAG;AAChB,UAAMC,IAAI,CAAA,GAAIC,IAAI,KAAK;AACvB,QAAIC,IAAI,KAAK,OAAOlD;AACpB,WAAOgD,EAAE,WAAW,KAAKE;AACvB,UAAIA;AACF,QAAAF,EAAE,KAAKE,CAAC,GAAGA,IAAIA,EAAE;AAAA,WACd;AACH,YAAIA,IAAIF,EAAE,IAAG,GAAIhD,IAAIiD,EAAEC,EAAE,KAAKP,CAAC,GAAG3C,IAAI;AACpC;AACF,YAAIiD,EAAEC,EAAE,KAAK,CAAC,KAAK,KAAK,EAAE,KAAKH,GAAGG,CAAC;AACjC,iBAAO;AACT,QAAAA,IAAIA,EAAE;AAAA,MACR;AACF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAIA,OAAO;AACL,UAAM,IAAI,CAAA;AACV,WAAO,KAAK,QAAQ,CAAC,EAAE,KAAKP,EAAC,MAAO;AAClC,QAAE,KAAKA,CAAC;AAAA,IACV,CAAC,GAAG;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAIA,SAAS;AACP,UAAM,IAAI,CAAA;AACV,WAAO,KAAK,QAAQ,CAAC,EAAE,MAAMA,EAAC,MAAO;AACnC,QAAE,KAAKA,CAAC;AAAA,IACV,CAAC,GAAG;AAAA,EACN;AAAA,EACA,MAAM;AACJ,WAAO,KAAK,QAAQ,KAAK,QAAQ,KAAK,KAAK,EAAE,MAAM;AAAA,EACrD;AAAA,EACA,MAAM;AACJ,WAAO,KAAK,QAAQ,KAAK,QAAQ,KAAK,KAAK,EAAE,MAAM;AAAA,EACrD;AAAA,EACA,QAAQ,IAAI,KAAK,OAAO;AACtB,QAAI,EAAG,QAAO,EAAE,OAAQ,KAAI,EAAE;AAC9B,WAAO;AAAA,EACT;AAAA,EACA,QAAQ,IAAI,KAAK,OAAO;AACtB,QAAI,EAAG,QAAO,EAAE,QAAS,KAAI,EAAE;AAC/B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAIA,GAAG,GAAG;AACJ,QAAIA,IAAI,KAAK,OAAO,IAAI,IAAII,IAAI;AAChC,UAAMC,IAAI,CAAA;AACV,WAAO,CAAC;AACN,UAAIL;AACF,QAAAK,EAAE,KAAKL,CAAC,GAAGA,IAAIA,EAAE;AAAA,eACVK,EAAE,SAAS,GAAG;AACrB,YAAIL,IAAIK,EAAE,IAAG,GAAID,MAAM,EAAG,QAAOJ;AACjC,QAAAI,KAAKJ,IAAIA,EAAE;AAAA,MACb,MAAO,KAAI;AACb,WAAO;AAAA,EACT;AAAA,EACA,KAAK,GAAG;AACN,QAAIA,IAAI,KAAK,OAAO,IAAI;AACxB,QAAI,EAAE,OAAO;AACX,WAAK,IAAI,EAAE,OAAO,EAAE,OAAQ,KAAI,EAAE;AAClC,aAAO;AAAA,IACT;AACA,UAAMI,IAAI,KAAK;AACf,WAAOJ,KAAK;AACV,YAAMK,IAAID,EAAE,EAAE,KAAKJ,EAAE,GAAG;AACxB,UAAIK,MAAM,EAAG;AACb,MAAAA,IAAI,KAAK,IAAIL,GAAGA,IAAIA,EAAE,QAAQA,IAAIA,EAAE;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA,EACA,KAAK,GAAG;AACN,QAAIA,IAAI,KAAK,OAAO,IAAI;AACxB,QAAI,EAAE,SAAS,MAAM;AACnB,WAAK,IAAI,EAAE,MAAM,EAAE,QAAS,KAAI,EAAE;AAClC,aAAO;AAAA,IACT;AACA,UAAMI,IAAI,KAAK;AACf,WAAOJ,KAAK;AACV,YAAMK,IAAID,EAAE,EAAE,KAAKJ,EAAE,GAAG;AACxB,UAAIK,MAAM,EAAG;AACb,MAAAA,IAAI,IAAIL,IAAIA,EAAE,QAAQ,IAAIA,GAAGA,IAAIA,EAAE;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQ;AACN,WAAO,KAAK,QAAQ,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC5C;AAAA,EACA,SAAS;AACP,WAAOY,GAAE,KAAK,KAAK;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAIA,KAAK,GAAGZ,IAAI,CAAA,GAAI,IAAI,IAAI;AACtB,QAAII,IAAI,EAAE;AACV,UAAMC,IAAI,KAAK;AACf,QAAI,KAAKQ,GAAE,GAAGb,GAAG,GAAGI,IAAI,GAAGC,CAAC,GAAG,KAAK,UAAU;AAC5C,WAAK,QAAQS,GAAE,GAAGd,GAAG,GAAGI,CAAC,GAAG,KAAK,QAAQA;AAAA,SACtC;AACH,YAAME,IAAIS;AAAA,QACR,KAAK,OAAM;AAAA,QACXC,GAAE,GAAGhB,CAAC;AAAA,QACNK;AAAA,MACR;AACM,MAAAD,IAAI,KAAK,QAAQA,GAAG,KAAK,QAAQa,GAAE,EAAE,MAAMX,KAAK,GAAGF,CAAC;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAAA,EACA,UAAU;AACR,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EACA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EACA,SAAS,IAAI,CAACJ,MAAM,OAAOA,EAAE,GAAG,GAAG;AACjC,UAAMA,IAAI,CAAA;AACV,WAAOU,GAAE,KAAK,OAAO,IAAI,IAAI,CAAC,MAAMV,EAAE,KAAK,CAAC,GAAG,CAAC,GAAGA,EAAE,KAAK,EAAE;AAAA,EAC9D;AAAA,EACA,OAAO,GAAGA,GAAG,GAAG;AACd,UAAMI,IAAI,KAAK;AACf,QAAI,EAAE,MAAMC,GAAG,OAAOC,EAAC,IAAKG,GAAE,GAAG,KAAK,OAAOL,CAAC;AAC9C,IAAAA,EAAE,GAAGJ,CAAC,IAAI,IAAIM,IAAIE,GAAER,GAAG,GAAGM,GAAGF,CAAC,IAAIC,IAAIG,GAAER,GAAG,GAAGK,GAAGD,CAAC,GAAG,KAAK,QAAQhD,GAAEiD,GAAGC,GAAGF,CAAC;AAAA,EAC7E;AAAA,EACA,MAAM,GAAG;AACP,WAAOK,GAAE,GAAG,KAAK,OAAO,KAAK,WAAW;AAAA,EAC1C;AAAA,EACA,EAAE,OAAO,QAAQ,IAAI;AACnB,QAAI,IAAI,KAAK;AACb,UAAMT,IAAI,CAAA;AACV,QAAI,IAAI;AACR,WAAO,CAAC;AACN,YAAM,QAAQA,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,QAAQA,EAAE,WAAW,KAAK,IAAIA,EAAE,OAAO,MAAM,GAAG,IAAI,EAAE,SAAS,IAAI;AAAA,EACtG;AACF;AACA,SAASc,GAAEZ,GAAG,GAAGF,GAAG,GAAG;AACrB,QAAMI,IAAI,IAAIJ;AACd,MAAII,IAAI,GAAG;AACT,UAAMC,IAAIL,IAAI,KAAK,MAAMI,IAAI,CAAC,GAAGE,IAAIJ,EAAEG,CAAC,GAAGE,IAAI,EAAEF,CAAC,GAAGhD,IAAI,IAAI0C,GAAEO,GAAGC,CAAC;AACnE,WAAOlD,EAAE,OAAOyD,GAAEZ,GAAG,GAAGF,GAAGK,CAAC,GAAGhD,EAAE,QAAQyD,GAAEZ,GAAG,GAAGG,IAAI,GAAG,CAAC,GAAGhD;AAAA,EAC9D;AACA,SAAO;AACT;AACA,SAAS2D,GAAEd,GAAG,GAAG;AACf,QAAMF,IAAI,IAAID,GAAE,MAAM,IAAI;AAC1B,MAAI,IAAIC;AACR,WAASI,IAAI,GAAGA,IAAIF,EAAE,QAAQE;AAC5B,QAAI,EAAE,OAAO,IAAIL,GAAEG,EAAEE,CAAC,GAAG,EAAEA,CAAC,CAAC;AAC/B,SAAO,EAAE,OAAO,MAAMJ,EAAE;AAC1B;AACA,SAASY,GAAEV,GAAG;AACZ,MAAI,IAAIA;AACR,QAAMF,IAAI,CAAA;AACV,MAAI,IAAI;AACR,QAAMI,IAAI,IAAIL,GAAE,MAAM,IAAI;AAC1B,MAAIM,IAAID;AACR,SAAO,CAAC;AACN,SAAKJ,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,QAAQA,EAAE,SAAS,KAAK,IAAIK,IAAIA,EAAE,OAAOL,EAAE,OAAO,IAAI,EAAE,SAAS,IAAI;AAC7F,SAAOK,EAAE,OAAO,MAAMD,EAAE;AAC1B;AACA,SAASa,GAAEf,GAAG,GAAGF,GAAG;AAClB,QAAM,IAAIA,IAAI;AACd,MAAI,IAAI,GAAG;AACT,UAAMI,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,GAAGC,IAAIY,GAAEf,GAAG,GAAGE,CAAC,GAAGE,IAAIJ,EAAE;AACvD,WAAOI,EAAE,OAAOD,GAAGH,EAAE,OAAOA,EAAE,KAAK,MAAMI,EAAE,QAAQW,GAAEf,GAAGE,IAAI,GAAGJ,CAAC,GAAGM;AAAA,EACrE;AACA,SAAO;AACT;AACA,SAASS,GAAEb,GAAG,GAAGF,GAAG;AAClB,QAAM,IAAI,IAAID,GAAE,MAAM,IAAI;AAC1B,MAAIK,IAAI,GAAGC,IAAIH,GAAGI,IAAI;AACtB,SAAOD,MAAM,QAAQC,MAAM;AACzB,IAAAN,EAAEK,EAAE,KAAKC,EAAE,GAAG,IAAI,KAAKF,EAAE,OAAOC,GAAGA,IAAIA,EAAE,SAASD,EAAE,OAAOE,GAAGA,IAAIA,EAAE,OAAOF,IAAIA,EAAE;AACnF,SAAOC,MAAM,OAAOD,EAAE,OAAOC,IAAIC,MAAM,SAASF,EAAE,OAAOE,IAAI,EAAE;AACjE;AACA,SAASO,GAAEX,GAAG,GAAGF,GAAG,GAAGI,GAAG;AACxB,MAAIJ,KAAK,EAAG;AACZ,QAAMK,IAAIH,EAAEF,IAAI,KAAK,CAAC;AACtB,MAAIM,IAAIN,IAAI,GAAGO,IAAI,IAAI;AACvB,aAAW;AACT;AACE,MAAAD;AAAA,WACKF,EAAEF,EAAEI,CAAC,GAAGD,CAAC,IAAI;AACpB;AACE,MAAAE;AAAA,WACKH,EAAEF,EAAEK,CAAC,GAAGF,CAAC,IAAI;AACpB,QAAIC,KAAKC,EAAG;AACZ,QAAIlD,IAAI6C,EAAEI,CAAC;AACX,IAAAJ,EAAEI,CAAC,IAAIJ,EAAEK,CAAC,GAAGL,EAAEK,CAAC,IAAIlD,GAAGA,IAAI,EAAEiD,CAAC,GAAG,EAAEA,CAAC,IAAI,EAAEC,CAAC,GAAG,EAAEA,CAAC,IAAIlD;AAAA,EACvD;AACA,EAAAwD,GAAEX,GAAG,GAAGF,GAAGO,GAAGH,CAAC,GAAGS,GAAEX,GAAG,GAAGK,IAAI,GAAG,GAAGH,CAAC;AACvC;ACnVO,MAAMc,KAAU,uBACVC,KAAW,WACXC,MAAkB,IAAI,IAAIF,MAAWA;AAG3C,SAASG,GAAIC,GAAMtB,GAAGuB,GAAMxB,GAAG1C,GAAG;AACrC,MAAImE,GAAGC,GAAMC,GAAIC,GACbC,IAAO5B,EAAE,CAAC,GACV6B,IAAO9B,EAAE,CAAC,GACV+B,IAAS,GACTC,IAAS;AACb,EAAKF,IAAOD,KAAWC,IAAO,CAACD,KAC3BJ,IAAII,GACJA,IAAO5B,EAAE,EAAE8B,CAAM,MAEjBN,IAAIK,GACJA,IAAO9B,EAAE,EAAEgC,CAAM;AAErB,MAAIC,IAAS;AACb,MAAIF,IAASR,KAAQS,IAASR;AAc1B,SAbKM,IAAOD,KAAWC,IAAO,CAACD,KAC3BH,IAAOG,IAAOJ,GACdE,IAAKF,KAAKC,IAAOG,IACjBA,IAAO5B,EAAE,EAAE8B,CAAM,MAEjBL,IAAOI,IAAOL,GACdE,IAAKF,KAAKC,IAAOI,IACjBA,IAAO9B,EAAE,EAAEgC,CAAM,IAErBP,IAAIC,GACAC,MAAO,MACPrE,EAAE2E,GAAQ,IAAIN,IAEXI,IAASR,KAAQS,IAASR;AAC7B,MAAKM,IAAOD,KAAWC,IAAO,CAACD,KAC3BH,IAAOD,IAAII,GACXD,IAAQF,IAAOD,GACfE,IAAKF,KAAKC,IAAOE,MAAUC,IAAOD,IAClCC,IAAO5B,EAAE,EAAE8B,CAAM,MAEjBL,IAAOD,IAAIK,GACXF,IAAQF,IAAOD,GACfE,IAAKF,KAAKC,IAAOE,MAAUE,IAAOF,IAClCE,IAAO9B,EAAE,EAAEgC,CAAM,IAErBP,IAAIC,GACAC,MAAO,MACPrE,EAAE2E,GAAQ,IAAIN;AAI1B,SAAOI,IAASR;AACZ,IAAAG,IAAOD,IAAII,GACXD,IAAQF,IAAOD,GACfE,IAAKF,KAAKC,IAAOE,MAAUC,IAAOD,IAClCC,IAAO5B,EAAE,EAAE8B,CAAM,GACjBN,IAAIC,GACAC,MAAO,MACPrE,EAAE2E,GAAQ,IAAIN;AAGtB,SAAOK,IAASR;AACZ,IAAAE,IAAOD,IAAIK,GACXF,IAAQF,IAAOD,GACfE,IAAKF,KAAKC,IAAOE,MAAUE,IAAOF,IAClCE,IAAO9B,EAAE,EAAEgC,CAAM,GACjBP,IAAIC,GACAC,MAAO,MACPrE,EAAE2E,GAAQ,IAAIN;AAGtB,UAAIF,MAAM,KAAKQ,MAAW,OACtB3E,EAAE2E,GAAQ,IAAIR,IAEXQ;AACX;AAsDO,SAASC,GAASX,GAAMtB,GAAG;AAC9B,MAAIwB,IAAIxB,EAAE,CAAC;AACX,WAASK,IAAI,GAAGA,IAAIiB,GAAMjB,IAAK,CAAAmB,KAAKxB,EAAEK,CAAC;AACvC,SAAOmB;AACX;AAEO,SAASU,GAAIhC,GAAG;AACnB,SAAO,IAAI,aAAaA,CAAC;AAC7B;ACvIA,MAAMiC,MAAgB,IAAI,KAAKjB,MAAWA,IACpCkB,MAAgB,IAAI,KAAKlB,MAAWA,IACpCmB,MAAgB,IAAI,KAAKnB,MAAWA,KAAUA,IAE9CoB,KAAIJ,GAAI,CAAC,GACTK,KAAKL,GAAI,CAAC,GACVM,KAAKN,GAAI,EAAE,GACXO,KAAIP,GAAI,EAAE,GACV/B,KAAI+B,GAAI,CAAC;AAEf,SAASQ,GAAc9E,GAAIE,GAAID,GAAIE,GAAI4E,GAAIC,GAAIC,GAAQ;AACnD,MAAIC,GAASC,GAASC,GAASC,GAC3BtB,GAAOnB,GAAG0C,GAAKC,GAAKC,GAAKC,GAAKC,GAAIC,GAAIC,GAAIC,GAAIC,GAAIC,GAAIC,GAAIC;AAE9D,QAAMC,IAAMlG,IAAK+E,GACXoB,IAAMlG,IAAK8E,GACXqB,IAAMlG,IAAK8E,GACXqB,IAAMlG,IAAK6E;AAEjB,EAAAa,IAAKK,IAAMG,GACXzD,IAAIW,KAAW2C,GACfZ,IAAM1C,KAAKA,IAAIsD,IACfX,IAAMW,IAAMZ,GACZ1C,IAAIW,KAAW8C,GACfb,IAAM5C,KAAKA,IAAIyD,IACfZ,IAAMY,IAAMb,GACZM,IAAKP,IAAME,KAAOI,IAAKP,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDM,IAAKK,IAAMD,GACXvD,IAAIW,KAAW6C,GACfd,IAAM1C,KAAKA,IAAIwD,IACfb,IAAMa,IAAMd,GACZ1C,IAAIW,KAAW4C,GACfX,IAAM5C,KAAKA,IAAIuD,IACfV,IAAMU,IAAMX,GACZQ,IAAKT,IAAME,KAAOM,IAAKT,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDC,IAAKI,IAAKE,GACVjC,IAAQ+B,IAAKJ,GACbhB,GAAE,CAAC,IAAIoB,KAAMJ,IAAK3B,MAAUA,IAAQiC,IACpCL,IAAKE,IAAKH,GACV3B,IAAQ4B,IAAKE,GACbD,IAAKC,KAAMF,IAAK5B,MAAU2B,IAAK3B,IAC/B2B,IAAKE,IAAKG,GACVhC,IAAQ6B,IAAKF,GACbhB,GAAE,CAAC,IAAIkB,KAAMF,IAAK3B,MAAUA,IAAQgC,IACpCE,IAAKN,IAAKD,GACV3B,IAAQkC,IAAKN,GACbjB,GAAE,CAAC,IAAIiB,KAAMM,IAAKlC,MAAU2B,IAAK3B,IACjCW,GAAE,CAAC,IAAIuB;AAEP,MAAIK,IAAMjC,GAAS,GAAGK,EAAC,GACnB6B,IAAW/B,KAAeS;AAoB9B,MAnBIqB,KAAOC,KAAY,CAACD,KAAOC,MAI/BxC,IAAQ/D,IAAKkG,GACbhB,IAAUlF,KAAMkG,IAAMnC,MAAUA,IAAQgB,IACxChB,IAAQ9D,IAAKkG,GACbf,IAAUnF,KAAMkG,IAAMpC,MAAUA,IAAQgB,IACxChB,IAAQ7D,IAAKkG,GACbjB,IAAUjF,KAAMkG,IAAMrC,MAAUA,IAAQiB,IACxCjB,IAAQ5D,IAAKkG,GACbhB,IAAUlF,KAAMkG,IAAMtC,MAAUA,IAAQiB,IAEpCE,MAAY,KAAKC,MAAY,KAAKC,MAAY,KAAKC,MAAY,OAInEkB,IAAW9B,KAAeQ,IAASzB,KAAiB,KAAK,IAAI8C,CAAG,GAChEA,KAAQJ,IAAMb,IAAUgB,IAAMnB,KAAYkB,IAAMhB,IAAUe,IAAMhB,IAC5DmB,KAAOC,KAAY,CAACD,KAAOC,GAAU,QAAOD;AAEhD,EAAAT,IAAKX,IAAUmB,GACfzD,IAAIW,KAAW2B,GACfI,IAAM1C,KAAKA,IAAIsC,IACfK,IAAML,IAAUI,GAChB1C,IAAIW,KAAW8C,GACfb,IAAM5C,KAAKA,IAAIyD,IACfZ,IAAMY,IAAMb,GACZM,IAAKP,IAAME,KAAOI,IAAKP,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDM,IAAKZ,IAAUgB,GACfvD,IAAIW,KAAW4B,GACfG,IAAM1C,KAAKA,IAAIuC,IACfI,IAAMJ,IAAUG,GAChB1C,IAAIW,KAAW4C,GACfX,IAAM5C,KAAKA,IAAIuD,IACfV,IAAMU,IAAMX,GACZQ,IAAKT,IAAME,KAAOM,IAAKT,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDC,IAAKI,IAAKE,GACVjC,IAAQ+B,IAAKJ,GACbnD,GAAE,CAAC,IAAIuD,KAAMJ,IAAK3B,MAAUA,IAAQiC,IACpCL,IAAKE,IAAKH,GACV3B,IAAQ4B,IAAKE,GACbD,IAAKC,KAAMF,IAAK5B,MAAU2B,IAAK3B,IAC/B2B,IAAKE,IAAKG,GACVhC,IAAQ6B,IAAKF,GACbnD,GAAE,CAAC,IAAIqD,KAAMF,IAAK3B,MAAUA,IAAQgC,IACpCE,IAAKN,IAAKD,GACV3B,IAAQkC,IAAKN,GACbpD,GAAE,CAAC,IAAIoD,KAAMM,IAAKlC,MAAU2B,IAAK3B,IACjCxB,GAAE,CAAC,IAAI0D;AACP,QAAMO,IAAQ/C,GAAI,GAAGiB,IAAG,GAAGnC,IAAGoC,EAAE;AAEhC,EAAAkB,IAAKK,IAAMb,GACXzC,IAAIW,KAAW2C,GACfZ,IAAM1C,KAAKA,IAAIsD,IACfX,IAAMW,IAAMZ,GACZ1C,IAAIW,KAAW8B,GACfG,IAAM5C,KAAKA,IAAIyC,IACfI,IAAMJ,IAAUG,GAChBM,IAAKP,IAAME,KAAOI,IAAKP,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDM,IAAKK,IAAMhB,GACXxC,IAAIW,KAAW6C,GACfd,IAAM1C,KAAKA,IAAIwD,IACfb,IAAMa,IAAMd,GACZ1C,IAAIW,KAAW6B,GACfI,IAAM5C,KAAKA,IAAIwC,IACfK,IAAML,IAAUI,GAChBQ,IAAKT,IAAME,KAAOM,IAAKT,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDC,IAAKI,IAAKE,GACVjC,IAAQ+B,IAAKJ,GACbnD,GAAE,CAAC,IAAIuD,KAAMJ,IAAK3B,MAAUA,IAAQiC,IACpCL,IAAKE,IAAKH,GACV3B,IAAQ4B,IAAKE,GACbD,IAAKC,KAAMF,IAAK5B,MAAU2B,IAAK3B,IAC/B2B,IAAKE,IAAKG,GACVhC,IAAQ6B,IAAKF,GACbnD,GAAE,CAAC,IAAIqD,KAAMF,IAAK3B,MAAUA,IAAQgC,IACpCE,IAAKN,IAAKD,GACV3B,IAAQkC,IAAKN,GACbpD,GAAE,CAAC,IAAIoD,KAAMM,IAAKlC,MAAU2B,IAAK3B,IACjCxB,GAAE,CAAC,IAAI0D;AACP,QAAMQ,IAAQhD,GAAI+C,GAAO7B,IAAI,GAAGpC,IAAGqC,EAAE;AAErC,EAAAiB,IAAKX,IAAUG,GACfzC,IAAIW,KAAW2B,GACfI,IAAM1C,KAAKA,IAAIsC,IACfK,IAAML,IAAUI,GAChB1C,IAAIW,KAAW8B,GACfG,IAAM5C,KAAKA,IAAIyC,IACfI,IAAMJ,IAAUG,GAChBM,IAAKP,IAAME,KAAOI,IAAKP,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDM,IAAKZ,IAAUC,GACfxC,IAAIW,KAAW4B,GACfG,IAAM1C,KAAKA,IAAIuC,IACfI,IAAMJ,IAAUG,GAChB1C,IAAIW,KAAW6B,GACfI,IAAM5C,KAAKA,IAAIwC,IACfK,IAAML,IAAUI,GAChBQ,IAAKT,IAAME,KAAOM,IAAKT,IAAME,IAAMD,IAAMC,IAAMF,IAAMG,IACrDC,IAAKI,IAAKE,GACVjC,IAAQ+B,IAAKJ,GACbnD,GAAE,CAAC,IAAIuD,KAAMJ,IAAK3B,MAAUA,IAAQiC,IACpCL,IAAKE,IAAKH,GACV3B,IAAQ4B,IAAKE,GACbD,IAAKC,KAAMF,IAAK5B,MAAU2B,IAAK3B,IAC/B2B,IAAKE,IAAKG,GACVhC,IAAQ6B,IAAKF,GACbnD,GAAE,CAAC,IAAIqD,KAAMF,IAAK3B,MAAUA,IAAQgC,IACpCE,IAAKN,IAAKD,GACV3B,IAAQkC,IAAKN,GACbpD,GAAE,CAAC,IAAIoD,KAAMM,IAAKlC,MAAU2B,IAAK3B,IACjCxB,GAAE,CAAC,IAAI0D;AACP,QAAMS,KAAOjD,GAAIgD,GAAO7B,IAAI,GAAGrC,IAAGsC,EAAC;AAEnC,SAAOA,GAAE6B,KAAO,CAAC;AACrB;AAEO,SAASC,GAAS3G,GAAIE,GAAID,GAAIE,GAAI4E,GAAIC,GAAI;AAC7C,QAAM4B,KAAW1G,IAAK8E,MAAO/E,IAAK8E,IAC5B8B,KAAY7G,IAAK+E,MAAO5E,IAAK6E,IAC7BsB,IAAMM,IAAUC,GAEhB5B,IAAS,KAAK,IAAI2B,IAAUC,CAAQ;AAC1C,SAAI,KAAK,IAAIP,CAAG,KAAK/B,KAAeU,IAAeqB,IAE5C,CAACxB,GAAc9E,GAAIE,GAAID,GAAIE,GAAI4E,GAAIC,GAAIC,CAAM;AACxD;ACzKA,MAAM6B,KAAW,CAACC,GAAMC,MACfD,EAAK,GAAG,KAAKC,EAAM,KAAKA,EAAM,KAAKD,EAAK,GAAG,KAAKA,EAAK,GAAG,KAAKC,EAAM,KAAKA,EAAM,KAAKD,EAAK,GAAG,GAM9FE,KAAiB,CAACC,GAAIC,MAAO;AAEjC,MAAIA,EAAG,GAAG,IAAID,EAAG,GAAG,KAAKA,EAAG,GAAG,IAAIC,EAAG,GAAG,KAAKA,EAAG,GAAG,IAAID,EAAG,GAAG,KAAKA,EAAG,GAAG,IAAIC,EAAG,GAAG,EAAG,QAAO;AAG7F,QAAMC,IAASF,EAAG,GAAG,IAAIC,EAAG,GAAG,IAAIA,EAAG,GAAG,IAAID,EAAG,GAAG,GAC7CG,IAASH,EAAG,GAAG,IAAIC,EAAG,GAAG,IAAID,EAAG,GAAG,IAAIC,EAAG,GAAG,GAG7CG,IAASJ,EAAG,GAAG,IAAIC,EAAG,GAAG,IAAIA,EAAG,GAAG,IAAID,EAAG,GAAG,GAC7CK,IAASL,EAAG,GAAG,IAAIC,EAAG,GAAG,IAAID,EAAG,GAAG,IAAIC,EAAG,GAAG;AAGnD,SAAO;AAAA,IACL,IAAI;AAAA,MACF,GAAGC;AAAA,MACH,GAAGE;AAAA,IACT;AAAA,IACI,IAAI;AAAA,MACF,GAAGD;AAAA,MACH,GAAGE;AAAA,IACT;AAAA,EACA;AACA;AAQA,IAAIjE,KAAU,OAAO;AAGjBA,OAAY,WAAWA,KAAU,KAAK,IAAI,GAAG,GAAG;AACpD,MAAMkE,KAAalE,KAAUA,IAGvBmE,KAAM,CAACvE,GAAGwE,MAAM;AAEpB,MAAI,CAACpE,KAAUJ,KAAKA,IAAII,MAClB,CAACA,KAAUoE,KAAKA,IAAIpE;AACtB,WAAO;AAKX,QAAMqE,IAAKzE,IAAIwE;AACf,SAAIC,IAAKA,IAAKH,KAAatE,IAAIwE,IACtB,IAIFxE,IAAIwE,IAAI,KAAK;AACtB;AAeA,MAAME,GAAU;AAAA,EACd,cAAc;AACZ,SAAK,MAAK;AAAA,EACZ;AAAA,EACA,QAAQ;AACN,SAAK,WAAW,IAAIC,GAAY,GAChC,KAAK,WAAW,IAAIA,GAAY;AAAA,EAClC;AAAA,EACA,MAAMzE,GAAGD,GAAG;AACV,WAAO;AAAA,MACL,GAAG,KAAK,SAAS,MAAMC,CAAC;AAAA,MACxB,GAAG,KAAK,SAAS,MAAMD,CAAC;AAAA,IAC9B;AAAA,EACE;AACF;AACA,MAAM0E,GAAa;AAAA,EACjB,cAAc;AACZ,SAAK,OAAO,IAAIC,GAAS,GAEzB,KAAK,MAAM,CAAC;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAMC,GAAO;AACX,UAAMC,IAAO,KAAK,KAAK,IAAID,CAAK,GAC1BE,IAAW,KAAK,KAAK,KAAKD,CAAI;AACpC,QAAIC,MAAa,QAAQR,GAAIO,EAAK,KAAKC,EAAS,GAAG,MAAM;AACvD,kBAAK,KAAK,OAAOF,CAAK,GACfE,EAAS;AAElB,UAAMC,IAAW,KAAK,KAAK,KAAKF,CAAI;AACpC,WAAIE,MAAa,QAAQT,GAAIO,EAAK,KAAKE,EAAS,GAAG,MAAM,KACvD,KAAK,KAAK,OAAOH,CAAK,GACfG,EAAS,OAEXH;AAAA,EACT;AACF;AAGA,MAAMI,KAAU,IAAIP,GAAS,GAGvBQ,KAAe,CAAClF,GAAGwE,MAAMxE,EAAE,IAAIwE,EAAE,IAAIxE,EAAE,IAAIwE,EAAE,GAG7CW,KAAa,CAACnF,GAAGwE,MAAMxE,EAAE,IAAIwE,EAAE,IAAIxE,EAAE,IAAIwE,EAAE,GAG3CY,KAAsB,CAACC,GAAQC,GAAQC,MAAW;AACtD,QAAMC,IAAM/B,GAAS4B,EAAO,GAAGA,EAAO,GAAGC,EAAO,GAAGA,EAAO,GAAGC,EAAO,GAAGA,EAAO,CAAC;AAC/E,SAAIC,IAAM,IAAU,KAChBA,IAAM,IAAU,IACb;AACT,GACMC,KAAS,CAAAC,MAAK,KAAK,KAAKP,GAAWO,GAAGA,CAAC,CAAC,GAGxCC,KAAc,CAACC,GAASC,GAAOC,MAAW;AAC9C,QAAMC,IAAQ;AAAA,IACZ,GAAGF,EAAM,IAAID,EAAQ;AAAA,IACrB,GAAGC,EAAM,IAAID,EAAQ;AAAA,EACzB,GACQI,IAAS;AAAA,IACb,GAAGF,EAAO,IAAIF,EAAQ;AAAA,IACtB,GAAGE,EAAO,IAAIF,EAAQ;AAAA,EAC1B;AACE,SAAOV,GAAac,GAAQD,CAAK,IAAIN,GAAOO,CAAM,IAAIP,GAAOM,CAAK;AACpE,GAGME,KAAgB,CAACL,GAASC,GAAOC,MAAW;AAChD,QAAMC,IAAQ;AAAA,IACZ,GAAGF,EAAM,IAAID,EAAQ;AAAA,IACrB,GAAGC,EAAM,IAAID,EAAQ;AAAA,EACzB,GACQI,IAAS;AAAA,IACb,GAAGF,EAAO,IAAIF,EAAQ;AAAA,IACtB,GAAGE,EAAO,IAAIF,EAAQ;AAAA,EAC1B;AACE,SAAOT,GAAWa,GAAQD,CAAK,IAAIN,GAAOO,CAAM,IAAIP,GAAOM,CAAK;AAClE,GAKMG,KAAyB,CAACC,GAAIT,GAAGzF,MACjCyF,EAAE,MAAM,IAAU,OACf;AAAA,EACL,GAAGS,EAAG,IAAIT,EAAE,IAAIA,EAAE,KAAKzF,IAAIkG,EAAG;AAAA,EAC9B,GAAGlG;AACP,GAMMmG,KAAuB,CAACD,GAAIT,GAAGxF,MAC/BwF,EAAE,MAAM,IAAU,OACf;AAAA,EACL,GAAGxF;AAAA,EACH,GAAGiG,EAAG,IAAIT,EAAE,IAAIA,EAAE,KAAKxF,IAAIiG,EAAG;AAClC,GAKME,KAAiB,CAACC,GAAKC,GAAIC,GAAKC,MAAO;AAI3C,MAAIF,EAAG,MAAM,EAAG,QAAOH,GAAqBI,GAAKC,GAAIH,EAAI,CAAC;AAC1D,MAAIG,EAAG,MAAM,EAAG,QAAOL,GAAqBE,GAAKC,GAAIC,EAAI,CAAC;AAC1D,MAAID,EAAG,MAAM,EAAG,QAAOL,GAAuBM,GAAKC,GAAIH,EAAI,CAAC;AAC5D,MAAIG,EAAG,MAAM,EAAG,QAAOP,GAAuBI,GAAKC,GAAIC,EAAI,CAAC;AAM5D,QAAME,IAAQxB,GAAaqB,GAAIE,CAAE;AACjC,MAAIC,KAAS,EAAG,QAAO;AACvB,QAAMC,IAAK;AAAA,IACT,GAAGH,EAAI,IAAIF,EAAI;AAAA,IACf,GAAGE,EAAI,IAAIF,EAAI;AAAA,EACnB,GACQM,IAAK1B,GAAayB,GAAIJ,CAAE,IAAIG,GAC5BG,IAAK3B,GAAayB,GAAIF,CAAE,IAAIC,GAG5BI,IAAKR,EAAI,IAAIO,IAAKN,EAAG,GACzBQ,IAAKP,EAAI,IAAII,IAAKH,EAAG,GACjBO,IAAKV,EAAI,IAAIO,IAAKN,EAAG,GACzBU,IAAKT,EAAI,IAAII,IAAKH,EAAG,GACjBvG,KAAK4G,IAAKC,KAAM,GAChB9G,KAAK+G,IAAKC,KAAM;AACtB,SAAO;AAAA,IACL,GAAG/G;AAAA,IACH,GAAGD;AAAA,EACP;AACA;AAEA,MAAMiH,GAAW;AAAA;AAAA,EAEf,OAAO,QAAQlH,GAAGwE,GAAG;AAEnB,UAAM2C,IAAQD,GAAW,cAAclH,EAAE,OAAOwE,EAAE,KAAK;AACvD,WAAI2C,MAAU,IAAUA,KAGpBnH,EAAE,UAAUwE,EAAE,SAAOxE,EAAE,KAAKwE,CAAC,GAG7BxE,EAAE,WAAWwE,EAAE,SAAexE,EAAE,SAAS,IAAI,KAI1CoH,GAAQ,QAAQpH,EAAE,SAASwE,EAAE,OAAO;AAAA,EAC7C;AAAA;AAAA,EAGA,OAAO,cAAc6C,GAAKC,GAAK;AAC7B,WAAID,EAAI,IAAIC,EAAI,IAAU,KACtBD,EAAI,IAAIC,EAAI,IAAU,IACtBD,EAAI,IAAIC,EAAI,IAAU,KACtBD,EAAI,IAAIC,EAAI,IAAU,IACnB;AAAA,EACT;AAAA;AAAA,EAGA,YAAYxD,GAAOyD,GAAQ;AACzB,IAAIzD,EAAM,WAAW,SAAWA,EAAM,SAAS,CAAC,IAAI,IAAOA,EAAM,OAAO,KAAK,IAAI,GACjF,KAAK,QAAQA,GACb,KAAK,SAASyD;AAAA,EAEhB;AAAA,EACA,KAAKC,GAAO;AACV,QAAIA,EAAM,UAAU,KAAK;AACvB,YAAM,IAAI,MAAM,qCAAqC;AAEvD,UAAMC,IAAcD,EAAM,MAAM;AAChC,aAASjI,IAAI,GAAGmI,IAAOD,EAAY,QAAQlI,IAAImI,GAAMnI,KAAK;AACxD,YAAMoI,IAAMF,EAAYlI,CAAC;AACzB,WAAK,MAAM,OAAO,KAAKoI,CAAG,GAC1BA,EAAI,QAAQ,KAAK;AAAA,IACnB;AACA,SAAK,kBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA,EAIA,oBAAoB;AAOlB,UAAMC,IAAY,KAAK,MAAM,OAAO;AACpC,aAASrI,IAAI,GAAGA,IAAIqI,GAAWrI,KAAK;AAClC,YAAMsI,IAAO,KAAK,MAAM,OAAOtI,CAAC;AAChC,UAAIsI,EAAK,QAAQ,eAAe;AAChC,iBAASC,IAAIvI,IAAI,GAAGuI,IAAIF,GAAWE,KAAK;AACtC,gBAAMC,IAAO,KAAK,MAAM,OAAOD,CAAC;AAChC,UAAIC,EAAK,eAAe,UACpBF,EAAK,QAAQ,MAAM,WAAWE,EAAK,QAAQ,MAAM,UACrDF,EAAK,QAAQ,QAAQE,EAAK,OAAO;AAAA,QACnC;AAAA,IACF;AAAA,EACF;AAAA,EACA,2BAA2B;AAEzB,UAAMC,IAAS,CAAA;AACf,aAASzI,IAAI,GAAGmI,IAAO,KAAK,MAAM,OAAO,QAAQnI,IAAImI,GAAMnI,KAAK;AAC9D,YAAMoI,IAAM,KAAK,MAAM,OAAOpI,CAAC;AAC/B,MAAIoI,MAAQ,QAAQ,CAACA,EAAI,QAAQ,WAAWA,EAAI,QAAQ,gBACtDK,EAAO,KAAKL,CAAG;AAAA,IAEnB;AACA,WAAOK;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,sBAAsBC,GAAW;AAC/B,UAAMC,IAAQ,oBAAI,IAAG,GACfC,IAAY,CAAAC,MAAe;AAC/B,YAAMC,IAAYD,EAAY;AAC9B,MAAAF,EAAM,IAAIE,GAAa;AAAA,QACrB,MAAMzC,GAAY,KAAK,OAAOsC,EAAU,OAAOI,EAAU,KAAK;AAAA,QAC9D,QAAQpC,GAAc,KAAK,OAAOgC,EAAU,OAAOI,EAAU,KAAK;AAAA,MAC1E,CAAO;AAAA,IACH;AACA,WAAO,CAACrI,GAAGwE,MAAM;AACf,MAAK0D,EAAM,IAAIlI,CAAC,KAAGmI,EAAUnI,CAAC,GACzBkI,EAAM,IAAI1D,CAAC,KAAG2D,EAAU3D,CAAC;AAC9B,YAAM;AAAA,QACJ,MAAM8D;AAAA,QACN,QAAQC;AAAA,MAChB,IAAUL,EAAM,IAAIlI,CAAC,GACT;AAAA,QACJ,MAAMwI;AAAA,QACN,QAAQC;AAAA,MAChB,IAAUP,EAAM,IAAI1D,CAAC;AAGf,aAAI8D,KAAS,KAAKE,KAAS,IACrBD,IAAUE,IAAgB,IAC1BF,IAAUE,IAAgB,KACvB,IAILH,IAAQ,KAAKE,IAAQ,IACnBD,IAAUE,IAAgB,KAC1BF,IAAUE,IAAgB,IACvB,IAILD,IAAQF,IAAc,KACtBE,IAAQF,IAAc,IACnB;AAAA,IACT;AAAA,EACF;AACF;AAIA,IAAII,KAAY;AAChB,MAAMtB,GAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcZ,OAAO,QAAQpH,GAAGwE,GAAG;AACnB,UAAMmE,IAAM3I,EAAE,OAAO,MAAM,GACrB4I,IAAMpE,EAAE,OAAO,MAAM,GACrBqE,IAAM7I,EAAE,QAAQ,MAAM,GACtB8I,IAAMtE,EAAE,QAAQ,MAAM;AAG5B,QAAIsE,IAAMH,EAAK,QAAO;AACtB,QAAIE,IAAMD,EAAK,QAAO;AACtB,UAAMG,IAAM/I,EAAE,OAAO,MAAM,GACrBgJ,IAAMxE,EAAE,OAAO,MAAM,GACrByE,IAAMjJ,EAAE,QAAQ,MAAM,GACtBkJ,IAAM1E,EAAE,QAAQ,MAAM;AAG5B,QAAImE,IAAMC,GAAK;AAEb,UAAII,IAAMD,KAAOC,IAAMC,EAAK,QAAO;AACnC,UAAID,IAAMD,KAAOC,IAAMC,EAAK,QAAO;AAGnC,YAAME,IAAYnJ,EAAE,aAAawE,EAAE,OAAO,KAAK;AAC/C,UAAI2E,IAAY,EAAG,QAAO;AAC1B,UAAIA,IAAY,EAAG,QAAO;AAG1B,YAAMC,IAAa5E,EAAE,aAAaxE,EAAE,QAAQ,KAAK;AACjD,aAAIoJ,MAAe,IAAUA,IAItB;AAAA,IACT;AAGA,QAAIT,IAAMC,GAAK;AACb,UAAIG,IAAMC,KAAOD,IAAMG,EAAK,QAAO;AACnC,UAAIH,IAAMC,KAAOD,IAAMG,EAAK,QAAO;AAGnC,YAAMG,IAAY7E,EAAE,aAAaxE,EAAE,OAAO,KAAK;AAC/C,UAAIqJ,MAAc,EAAG,QAAOA;AAG5B,YAAMC,IAAatJ,EAAE,aAAawE,EAAE,QAAQ,KAAK;AACjD,aAAI8E,IAAa,IAAU,IACvBA,IAAa,IAAU,KAIpB;AAAA,IACT;AAMA,QAAIP,IAAMC,EAAK,QAAO;AACtB,QAAID,IAAMC,EAAK,QAAO;AAMtB,QAAIH,IAAMC,GAAK;AACb,YAAMM,IAAa5E,EAAE,aAAaxE,EAAE,QAAQ,KAAK;AACjD,UAAIoJ,MAAe,EAAG,QAAOA;AAAA,IAC/B;AAGA,QAAIP,IAAMC,GAAK;AACb,YAAMQ,IAAatJ,EAAE,aAAawE,EAAE,QAAQ,KAAK;AACjD,UAAI8E,IAAa,EAAG,QAAO;AAC3B,UAAIA,IAAa,EAAG,QAAO;AAAA,IAC7B;AACA,QAAIT,MAAQC,GAAK;AAGf,YAAM9L,IAAKiM,IAAMF,GACXjM,IAAK+L,IAAMF,GACX1L,IAAKiM,IAAMF,GACXjM,IAAK+L,IAAMF;AACjB,UAAI5L,IAAKF,KAAMG,IAAKF,EAAI,QAAO;AAC/B,UAAIC,IAAKF,KAAMG,IAAKF,EAAI,QAAO;AAAA,IACjC;AAIA,WAAI8L,IAAMC,IAAY,IAClBD,IAAMC,KAMNG,IAAMC,IAAY,KAClBD,IAAMC,IAAY,IAIlBlJ,EAAE,KAAKwE,EAAE,KAAW,KACpBxE,EAAE,KAAKwE,EAAE,KAAW,IAGjB;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,YAAY+E,GAAQC,GAASC,GAAOC,GAAU;AAC5C,SAAK,KAAK,EAAEhB,IACZ,KAAK,SAASa,GACdA,EAAO,UAAU,MACjBA,EAAO,UAAUC,GACjB,KAAK,UAAUA,GACfA,EAAQ,UAAU,MAClBA,EAAQ,UAAUD,GAClB,KAAK,QAAQE,GACb,KAAK,WAAWC;AAAA,EAGlB;AAAA,EACA,OAAO,SAASpD,GAAKE,GAAKmD,GAAM;AAC9B,QAAIC,GAAQC,GAASC;AAGrB,UAAMC,IAAS7C,GAAW,cAAcZ,GAAKE,CAAG;AAChD,QAAIuD,IAAS;AACX,MAAAH,IAAStD,GACTuD,IAAUrD,GACVsD,IAAU;AAAA,aACDC,IAAS;AAClB,MAAAH,IAASpD,GACTqD,IAAUvD,GACVwD,IAAU;AAAA,QACL,OAAM,IAAI,MAAM,0CAA0CxD,EAAI,CAAC,KAAKA,EAAI,CAAC,GAAG;AACnF,UAAMiD,IAAS,IAAIrC,GAAW0C,GAAQ,EAAI,GACpCJ,IAAU,IAAItC,GAAW2C,GAAS,EAAK;AAC7C,WAAO,IAAIzC,GAAQmC,GAAQC,GAAS,CAACG,CAAI,GAAG,CAACG,CAAO,CAAC;AAAA,EACvD;AAAA;AAAA,EAGA,eAAeE,GAAY;AACzB,SAAK,UAAUA,GACf,KAAK,QAAQ,UAAU,MACvB,KAAK,QAAQ,UAAU,KAAK,QAC5B,KAAK,OAAO,UAAU,KAAK;AAAA,EAC7B;AAAA,EACA,OAAO;AACL,UAAMhD,IAAK,KAAK,OAAO,MAAM,GACvBC,IAAK,KAAK,QAAQ,MAAM;AAC9B,WAAO;AAAA,MACL,IAAI;AAAA,QACF,GAAG,KAAK,OAAO,MAAM;AAAA,QACrB,GAAGD,IAAKC,IAAKD,IAAKC;AAAA,MAC1B;AAAA,MACM,IAAI;AAAA,QACF,GAAG,KAAK,QAAQ,MAAM;AAAA,QACtB,GAAGD,IAAKC,IAAKD,IAAKC;AAAA,MAC1B;AAAA,IACA;AAAA,EACE;AAAA;AAAA,EAGA,SAAS;AACP,WAAO;AAAA,MACL,GAAG,KAAK,QAAQ,MAAM,IAAI,KAAK,OAAO,MAAM;AAAA,MAC5C,GAAG,KAAK,QAAQ,MAAM,IAAI,KAAK,OAAO,MAAM;AAAA,IAClD;AAAA,EACE;AAAA,EACA,aAAad,GAAI;AACf,WAAOA,EAAG,MAAM,KAAK,OAAO,MAAM,KAAKA,EAAG,MAAM,KAAK,OAAO,MAAM,KAAKA,EAAG,MAAM,KAAK,QAAQ,MAAM,KAAKA,EAAG,MAAM,KAAK,QAAQ,MAAM;AAAA,EACtI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,aAAarC,GAAO;AAClB,QAAI,KAAK,aAAaA,CAAK,EAAG,QAAO;AACrC,UAAMmG,IAAM,KAAK,OAAO,OAClBC,IAAM,KAAK,QAAQ,OACnBxE,IAAI,KAAK,OAAM;AAGrB,QAAIuE,EAAI,MAAMC,EAAI;AAChB,aAAIpG,EAAM,MAAMmG,EAAI,IAAU,IACvBnG,EAAM,IAAImG,EAAI,IAAI,IAAI;AAK/B,UAAME,KAASrG,EAAM,IAAImG,EAAI,KAAKvE,EAAE,GAC9B0E,IAAaH,EAAI,IAAIE,IAAQzE,EAAE;AACrC,QAAI5B,EAAM,MAAMsG,EAAY,QAAO;AAInC,UAAMC,KAASvG,EAAM,IAAImG,EAAI,KAAKvE,EAAE,GAC9B4E,IAAaL,EAAI,IAAII,IAAQ3E,EAAE;AACrC,WAAI5B,EAAM,MAAMwG,IAAmB,IAC5BxG,EAAM,IAAIwG,IAAa,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,gBAAgB9C,GAAO;AAErB,UAAM+C,IAAQ,KAAK,KAAI,GACjBC,IAAQhD,EAAM,KAAI,GAClBiD,IAAc1G,GAAewG,GAAOC,CAAK;AAC/C,QAAIC,MAAgB,KAAM,QAAO;AAMjC,UAAMC,IAAM,KAAK,OAAO,OAClBC,IAAM,KAAK,QAAQ,OACnBC,IAAMpD,EAAM,OAAO,OACnBqD,IAAMrD,EAAM,QAAQ,OAKpBsD,IAAkBlH,GAAS2G,GAAOK,CAAG,KAAK,KAAK,aAAaA,CAAG,MAAM,GACrEG,IAAiBnH,GAAS4G,GAAOE,CAAG,KAAKlD,EAAM,aAAakD,CAAG,MAAM,GACrEM,IAAkBpH,GAAS2G,GAAOM,CAAG,KAAK,KAAK,aAAaA,CAAG,MAAM,GACrEI,IAAiBrH,GAAS4G,GAAOG,CAAG,KAAKnD,EAAM,aAAamD,CAAG,MAAM;AAG3E,QAAII,KAAkBD;AAGpB,aAAIG,KAAkB,CAACD,IAAwBL,IAC3C,CAACM,KAAkBD,IAAwBH,IAGxC;AAIT,QAAIE;AAEF,aAAIC,KACEN,EAAI,MAAMG,EAAI,KAAKH,EAAI,MAAMG,EAAI,IAAU,OAG1CH;AAIT,QAAII;AAEF,aAAIG,KACEN,EAAI,MAAMC,EAAI,KAAKD,EAAI,MAAMC,EAAI,IAAU,OAG1CA;AAIT,QAAIK,KAAkBD,EAAiB,QAAO;AAG9C,QAAIC,EAAgB,QAAON;AAC3B,QAAIK,EAAiB,QAAOH;AAI5B,UAAM1E,IAAKE,GAAeqE,GAAK,KAAK,OAAM,GAAIE,GAAKpD,EAAM,QAAQ;AAOjE,WAHIrB,MAAO,QAGP,CAACvC,GAAS6G,GAAatE,CAAE,IAAU,OAGhClB,GAAQ,MAAMkB,EAAG,GAAGA,EAAG,CAAC;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAMrC,GAAO;AACX,UAAMoH,IAAY,CAAA,GACZC,IAAgBrH,EAAM,WAAW,QACjCsH,IAAY,IAAIlE,GAAWpD,GAAO,EAAI,GACtCkG,IAAa,IAAI9C,GAAWpD,GAAO,EAAK,GACxCuH,IAAa,KAAK;AACxB,SAAK,eAAerB,CAAU,GAC9BkB,EAAU,KAAKlB,CAAU,GACzBkB,EAAU,KAAKE,CAAS;AACxB,UAAME,IAAS,IAAIlE,GAAQgE,GAAWC,GAAY,KAAK,MAAM,MAAK,GAAI,KAAK,SAAS,MAAK,CAAE;AAK3F,WAAInE,GAAW,cAAcoE,EAAO,OAAO,OAAOA,EAAO,QAAQ,KAAK,IAAI,KACxEA,EAAO,WAAU,GAEfpE,GAAW,cAAc,KAAK,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI,KACpE,KAAK,WAAU,GAMbiE,MACFC,EAAU,kBAAiB,GAC3BpB,EAAW,kBAAiB,IAEvBkB;AAAA,EACT;AAAA;AAAA,EAGA,aAAa;AACX,UAAMK,IAAS,KAAK;AACpB,SAAK,UAAU,KAAK,QACpB,KAAK,SAASA,GACd,KAAK,OAAO,SAAS,IACrB,KAAK,QAAQ,SAAS;AACtB,aAAShM,IAAI,GAAGmI,IAAO,KAAK,SAAS,QAAQnI,IAAImI,GAAMnI;AACrD,WAAK,SAASA,CAAC,KAAK;AAAA,EAExB;AAAA;AAAA;AAAA,EAIA,QAAQiI,GAAO;AACb,QAAIgE,IAAW,MACXC,IAAWjE;AACf,WAAOgE,EAAS,aAAY,CAAAA,IAAWA,EAAS;AAChD,WAAOC,EAAS,aAAY,CAAAA,IAAWA,EAAS;AAChD,UAAMlH,IAAM6C,GAAQ,QAAQoE,GAAUC,CAAQ;AAC9C,QAAIlH,MAAQ,GAGZ;AAAA,UAAIA,IAAM,GAAG;AACX,cAAMmH,IAAMF;AACZ,QAAAA,IAAWC,GACXA,IAAWC;AAAA,MACb;AAGA,UAAIF,EAAS,SAASC,GAAU;AAC9B,cAAMC,IAAMF;AACZ,QAAAA,IAAWC,GACXA,IAAWC;AAAA,MACb;AACA,eAASnM,IAAI,GAAGmI,IAAO+D,EAAS,MAAM,QAAQlM,IAAImI,GAAMnI,KAAK;AAC3D,cAAMoK,IAAO8B,EAAS,MAAMlM,CAAC,GACvBuK,IAAU2B,EAAS,SAASlM,CAAC,GAC7BoM,IAAQH,EAAS,MAAM,QAAQ7B,CAAI;AACzC,QAAIgC,MAAU,MACZH,EAAS,MAAM,KAAK7B,CAAI,GACxB6B,EAAS,SAAS,KAAK1B,CAAO,KACzB0B,EAAS,SAASG,CAAK,KAAK7B;AAAA,MACrC;AACA,MAAA2B,EAAS,QAAQ,MACjBA,EAAS,WAAW,MACpBA,EAAS,aAAaD,GAGtBC,EAAS,OAAO,aAAaD,EAAS,QACtCC,EAAS,QAAQ,aAAaD,EAAS;AAAA;AAAA,EACzC;AAAA;AAAA,EAGA,eAAe;AACb,WAAI,KAAK,kBAAkB,SAAkB,KAAK,iBAC7C,KAAK,OAAyC,KAAK,KAAK,WAAU,IAAI,KAAK,gBAAgB,KAAK,OAAU,KAAK,gBAAgB,KAAK,KAAK,aAAY,IAA1I,KAAK,gBAAgB,MAC9B,KAAK;AAAA,EACd;AAAA,EACA,cAAc;AACZ,QAAI,KAAK,iBAAiB,OAAW,QAAO,KAAK;AACjD,QAAI,CAAC,KAAK,KAAM,MAAK,eAAe;AAAA,MAClC,OAAO,CAAA;AAAA,MACP,UAAU,CAAA;AAAA,MACV,YAAY,CAAA;AAAA,IAClB;AAAA,SAAW;AACL,YAAMI,IAAM,KAAK,KAAK,cAAc,KAAK;AACzC,WAAK,eAAeA,EAAI,WAAU;AAAA,IACpC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EACA,aAAa;AACX,QAAI,KAAK,gBAAgB,OAAW,QAAO,KAAK;AAChD,UAAMC,IAAc,KAAK,YAAW;AACpC,SAAK,cAAc;AAAA,MACjB,OAAOA,EAAY,MAAM,MAAM,CAAC;AAAA,MAChC,UAAUA,EAAY,SAAS,MAAM,CAAC;AAAA,MACtC,YAAY,CAAA;AAAA,IAClB;AACI,UAAMC,IAAa,KAAK,YAAY,OAC9BC,IAAgB,KAAK,YAAY,UACjCC,IAAW,KAAK,YAAY;AAGlC,aAASzM,IAAI,GAAGmI,IAAO,KAAK,MAAM,QAAQnI,IAAImI,GAAMnI,KAAK;AACvD,YAAMoK,IAAO,KAAK,MAAMpK,CAAC,GACnBuK,IAAU,KAAK,SAASvK,CAAC,GACzBoM,IAAQG,EAAW,QAAQnC,CAAI;AACrC,MAAIgC,MAAU,MACZG,EAAW,KAAKnC,CAAI,GACpBoC,EAAc,KAAKjC,CAAO,KACrBiC,EAAcJ,CAAK,KAAK7B;AAAA,IACjC;AAGA,UAAMmC,IAAa,CAAA,GACbC,IAAe,CAAA;AACrB,aAAS3M,IAAI,GAAGmI,IAAOoE,EAAW,QAAQvM,IAAImI,GAAMnI,KAAK;AACvD,UAAIwM,EAAcxM,CAAC,MAAM,EAAG;AAC5B,YAAMoK,IAAOmC,EAAWvM,CAAC,GACnB4M,IAAOxC,EAAK;AAClB,UAAIuC,EAAa,QAAQC,CAAI,MAAM;AACnC,YAAIxC,EAAK,WAAY,CAAAsC,EAAW,KAAKE,CAAI;AAAA,aAAO;AAC9C,UAAID,EAAa,QAAQC,CAAI,MAAM,MAAID,EAAa,KAAKC,CAAI;AAC7D,gBAAMR,IAAQM,EAAW,QAAQtC,EAAK,IAAI;AAC1C,UAAIgC,MAAU,MAAIM,EAAW,OAAON,GAAO,CAAC;AAAA,QAC9C;AAAA,IACF;AAGA,aAASpM,IAAI,GAAGmI,IAAOuE,EAAW,QAAQ1M,IAAImI,GAAMnI,KAAK;AACvD,YAAM6M,IAAKH,EAAW1M,CAAC,EAAE;AACzB,MAAIyM,EAAS,QAAQI,CAAE,MAAM,MAAIJ,EAAS,KAAKI,CAAE;AAAA,IACnD;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,aAAa;AAEX,QAAI,KAAK,WAAY,QAAO;AAC5B,QAAI,KAAK,gBAAgB,OAAW,QAAO,KAAK;AAChD,UAAMC,IAAY,KAAK,YAAW,EAAG,YAC/BL,IAAW,KAAK,WAAU,EAAG;AACnC,YAAQM,GAAU,MAAI;AAAA,MACpB,KAAK,SACH;AAIE,cAAMC,IAAYF,EAAU,WAAW,GACjCG,IAAWR,EAAS,WAAW;AACrC,aAAK,cAAcO,MAAcC;AACjC;AAAA,MACF;AAAA,MACF,KAAK,gBACH;AAKE,YAAIC,GACAC;AACJ,QAAIL,EAAU,SAASL,EAAS,UAC9BS,IAAQJ,EAAU,QAClBK,IAAOV,EAAS,WAEhBS,IAAQT,EAAS,QACjBU,IAAOL,EAAU,SAEnB,KAAK,cAAcK,MAASJ,GAAU,iBAAiBG,IAAQC;AAC/D;AAAA,MACF;AAAA,MACF,KAAK,OACH;AAIE,cAAMC,IAAO,KAAK,IAAIN,EAAU,SAASL,EAAS,MAAM;AACxD,aAAK,cAAcW,IAAO,MAAM;AAChC;AAAA,MACF;AAAA,MACF,KAAK,cACH;AAGE,cAAMC,IAAgB,CAAAC,MAAOA,EAAI,WAAW,KAAKA,EAAI,CAAC,EAAE;AACxD,aAAK,cAAcD,EAAcP,CAAS,MAAMO,EAAcZ,CAAQ;AACtE;AAAA,MACF;AAAA,MACF;AACE,cAAM,IAAI,MAAM,qCAAqCM,GAAU,IAAI,EAAE;AAAA,IAC7E;AACI,WAAO,KAAK;AAAA,EACd;AACF;AAEA,MAAMQ,GAAO;AAAA,EACX,YAAYC,GAAUZ,GAAMa,GAAY;AACtC,QAAI,CAAC,MAAM,QAAQD,CAAQ,KAAKA,EAAS,WAAW;AAClD,YAAM,IAAI,MAAM,uDAAuD;AAKzE,QAHA,KAAK,OAAOZ,GACZ,KAAK,aAAaa,GAClB,KAAK,WAAW,CAAA,GACZ,OAAOD,EAAS,CAAC,EAAE,CAAC,KAAM,YAAY,OAAOA,EAAS,CAAC,EAAE,CAAC,KAAM;AAClE,YAAM,IAAI,MAAM,uDAAuD;AAEzE,UAAME,IAAahI,GAAQ,MAAM8H,EAAS,CAAC,EAAE,CAAC,GAAGA,EAAS,CAAC,EAAE,CAAC,CAAC;AAC/D,SAAK,OAAO;AAAA,MACV,IAAI;AAAA,QACF,GAAGE,EAAW;AAAA,QACd,GAAGA,EAAW;AAAA,MACtB;AAAA,MACM,IAAI;AAAA,QACF,GAAGA,EAAW;AAAA,QACd,GAAGA,EAAW;AAAA,MACtB;AAAA,IACA;AACI,QAAIC,IAAYD;AAChB,aAAS1N,IAAI,GAAGmI,IAAOqF,EAAS,QAAQxN,IAAImI,GAAMnI,KAAK;AACrD,UAAI,OAAOwN,EAASxN,CAAC,EAAE,CAAC,KAAM,YAAY,OAAOwN,EAASxN,CAAC,EAAE,CAAC,KAAM;AAClE,cAAM,IAAI,MAAM,uDAAuD;AAEzE,UAAIuE,IAAQmB,GAAQ,MAAM8H,EAASxN,CAAC,EAAE,CAAC,GAAGwN,EAASxN,CAAC,EAAE,CAAC,CAAC;AAExD,MAAIuE,EAAM,MAAMoJ,EAAU,KAAKpJ,EAAM,MAAMoJ,EAAU,MACrD,KAAK,SAAS,KAAK9F,GAAQ,SAAS8F,GAAWpJ,GAAO,IAAI,CAAC,GACvDA,EAAM,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAM,IACjDA,EAAM,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAM,IACjDA,EAAM,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAM,IACjDA,EAAM,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAM,IACrDoJ,IAAYpJ;AAAA,IACd;AAEA,KAAImJ,EAAW,MAAMC,EAAU,KAAKD,EAAW,MAAMC,EAAU,MAC7D,KAAK,SAAS,KAAK9F,GAAQ,SAAS8F,GAAWD,GAAY,IAAI,CAAC;AAAA,EAEpE;AAAA,EACA,iBAAiB;AACf,UAAME,IAAc,CAAA;AACpB,aAAS5N,IAAI,GAAGmI,IAAO,KAAK,SAAS,QAAQnI,IAAImI,GAAMnI,KAAK;AAC1D,YAAM6N,IAAU,KAAK,SAAS7N,CAAC;AAC/B,MAAA4N,EAAY,KAAKC,EAAQ,MAAM,GAC/BD,EAAY,KAAKC,EAAQ,OAAO;AAAA,IAClC;AACA,WAAOD;AAAA,EACT;AACF;AACA,MAAME,GAAO;AAAA,EACX,YAAYC,GAAUC,GAAW;AAC/B,QAAI,CAAC,MAAM,QAAQD,CAAQ;AACzB,YAAM,IAAI,MAAM,uDAAuD;AAEzE,SAAK,eAAe,IAAIR,GAAOQ,EAAS,CAAC,GAAG,MAAM,EAAI,GAEtD,KAAK,OAAO;AAAA,MACV,IAAI;AAAA,QACF,GAAG,KAAK,aAAa,KAAK,GAAG;AAAA,QAC7B,GAAG,KAAK,aAAa,KAAK,GAAG;AAAA,MACrC;AAAA,MACM,IAAI;AAAA,QACF,GAAG,KAAK,aAAa,KAAK,GAAG;AAAA,QAC7B,GAAG,KAAK,aAAa,KAAK,GAAG;AAAA,MACrC;AAAA,IACA,GACI,KAAK,gBAAgB,CAAA;AACrB,aAAS/N,IAAI,GAAGmI,IAAO4F,EAAS,QAAQ/N,IAAImI,GAAMnI,KAAK;AACrD,YAAMoK,IAAO,IAAImD,GAAOQ,EAAS/N,CAAC,GAAG,MAAM,EAAK;AAChD,MAAIoK,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IAC/DA,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IAC/DA,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IAC/DA,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IACnE,KAAK,cAAc,KAAKA,CAAI;AAAA,IAC9B;AACA,SAAK,YAAY4D;AAAA,EACnB;AAAA,EACA,iBAAiB;AACf,UAAMJ,IAAc,KAAK,aAAa,eAAc;AACpD,aAAS5N,IAAI,GAAGmI,IAAO,KAAK,cAAc,QAAQnI,IAAImI,GAAMnI,KAAK;AAC/D,YAAMiO,IAAkB,KAAK,cAAcjO,CAAC,EAAE,eAAc;AAC5D,eAASuI,IAAI,GAAG2F,IAAOD,EAAgB,QAAQ1F,IAAI2F,GAAM3F;AACvD,QAAAqF,EAAY,KAAKK,EAAgB1F,CAAC,CAAC;AAAA,IAEvC;AACA,WAAOqF;AAAA,EACT;AACF;AACA,MAAMO,GAAY;AAAA,EAChB,YAAYC,GAAMC,GAAW;AAC3B,QAAI,CAAC,MAAM,QAAQD,CAAI;AACrB,YAAM,IAAI,MAAM,uDAAuD;AAEzE,QAAI;AAEF,MAAI,OAAOA,EAAK,CAAC,EAAE,CAAC,EAAE,CAAC,KAAM,aAAUA,IAAO,CAACA,CAAI;AAAA,IACrD,QAAa;AAAA,IAGb;AACA,SAAK,QAAQ,CAAA,GACb,KAAK,OAAO;AAAA,MACV,IAAI;AAAA,QACF,GAAG,OAAO;AAAA,QACV,GAAG,OAAO;AAAA,MAClB;AAAA,MACM,IAAI;AAAA,QACF,GAAG,OAAO;AAAA,QACV,GAAG,OAAO;AAAA,MAClB;AAAA,IACA;AACI,aAASpO,IAAI,GAAGmI,IAAOiG,EAAK,QAAQpO,IAAImI,GAAMnI,KAAK;AACjD,YAAM4M,IAAO,IAAIkB,GAAOM,EAAKpO,CAAC,GAAG,IAAI;AACrC,MAAI4M,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IAC/DA,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IAC/DA,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IAC/DA,EAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,MAAG,KAAK,KAAK,GAAG,IAAIA,EAAK,KAAK,GAAG,IACnE,KAAK,MAAM,KAAKA,CAAI;AAAA,IACtB;AACA,SAAK,YAAYyB;AAAA,EACnB;AAAA,EACA,iBAAiB;AACf,UAAMT,IAAc,CAAA;AACpB,aAAS5N,IAAI,GAAGmI,IAAO,KAAK,MAAM,QAAQnI,IAAImI,GAAMnI,KAAK;AACvD,YAAMsO,IAAkB,KAAK,MAAMtO,CAAC,EAAE,eAAc;AACpD,eAASuI,IAAI,GAAG2F,IAAOI,EAAgB,QAAQ/F,IAAI2F,GAAM3F;AACvD,QAAAqF,EAAY,KAAKU,EAAgB/F,CAAC,CAAC;AAAA,IAEvC;AACA,WAAOqF;AAAA,EACT;AACF;AAEA,MAAMW,GAAQ;AAAA;AAAA;AAAA,EAGZ,OAAO,QAAQC,GAAa;AAC1B,UAAMC,IAAW,CAAA;AACjB,aAASzO,IAAI,GAAGmI,IAAOqG,EAAY,QAAQxO,IAAImI,GAAMnI,KAAK;AACxD,YAAM6N,IAAUW,EAAYxO,CAAC;AAC7B,UAAI,CAAC6N,EAAQ,gBAAgBA,EAAQ,QAAS;AAC9C,UAAIa,IAAY,MACZC,IAAQd,EAAQ,QAChB/E,IAAY+E,EAAQ;AACxB,YAAMpF,IAAS,CAACkG,CAAK,GACfC,IAAgBD,EAAM,OACtBE,IAAkB,CAAA;AAGxB,aACEH,IAAYC,GACZA,IAAQ7F,GACRL,EAAO,KAAKkG,CAAK,GAGbA,EAAM,UAAUC;AACpB,mBAAa;AACX,gBAAME,IAAeH,EAAM,yBAAwB;AAInD,cAAIG,EAAa,WAAW,GAAG;AAC7B,kBAAMC,IAAUtG,EAAO,CAAC,EAAE,OACpBuG,IAASvG,EAAOA,EAAO,SAAS,CAAC,EAAE;AACzC,kBAAM,IAAI,MAAM,+CAA+CsG,EAAQ,CAAC,KAAUA,EAAQ,CAAC,2CAAgDC,EAAO,CAAC,KAAKA,EAAO,CAAC,IAAI;AAAA,UACtK;AAGA,cAAIF,EAAa,WAAW,GAAG;AAC7B,YAAAhG,IAAYgG,EAAa,CAAC,EAAE;AAC5B;AAAA,UACF;AAGA,cAAIG,IAAU;AACd,mBAAS1G,IAAI,GAAG2F,IAAOW,EAAgB,QAAQtG,IAAI2F,GAAM3F;AACvD,gBAAIsG,EAAgBtG,CAAC,EAAE,UAAUoG,EAAM,OAAO;AAC5C,cAAAM,IAAU1G;AACV;AAAA,YACF;AAGF,cAAI0G,MAAY,MAAM;AACpB,kBAAMC,IAAiBL,EAAgB,OAAOI,CAAO,EAAE,CAAC,GAClDE,IAAa1G,EAAO,OAAOyG,EAAe,KAAK;AACrD,YAAAC,EAAW,QAAQA,EAAW,CAAC,EAAE,OAAO,GACxCV,EAAS,KAAK,IAAIF,GAAQY,EAAW,QAAO,CAAE,CAAC;AAC/C;AAAA,UACF;AAEA,UAAAN,EAAgB,KAAK;AAAA,YACnB,OAAOpG,EAAO;AAAA,YACd,OAAOkG,EAAM;AAAA,UACzB,CAAW;AAED,gBAAMS,IAAaT,EAAM,sBAAsBD,CAAS;AACxD,UAAA5F,IAAYgG,EAAa,KAAKM,CAAU,EAAE,CAAC,EAAE;AAC7C;AAAA,QACF;AAEF,MAAAX,EAAS,KAAK,IAAIF,GAAQ9F,CAAM,CAAC;AAAA,IACnC;AACA,WAAOgG;AAAA,EACT;AAAA,EACA,YAAYhG,GAAQ;AAClB,SAAK,SAASA;AACd,aAASzI,IAAI,GAAGmI,IAAOM,EAAO,QAAQzI,IAAImI,GAAMnI;AAC9C,MAAAyI,EAAOzI,CAAC,EAAE,QAAQ,UAAU;AAE9B,SAAK,OAAO;AAAA,EACd;AAAA,EACA,UAAU;AAER,QAAIqP,IAAS,KAAK,OAAO,CAAC,EAAE;AAC5B,UAAMC,IAAS,CAACD,CAAM;AACtB,aAASrP,IAAI,GAAGmI,IAAO,KAAK,OAAO,SAAS,GAAGnI,IAAImI,GAAMnI,KAAK;AAC5D,YAAM4G,IAAK,KAAK,OAAO5G,CAAC,EAAE,OACpBuP,IAAS,KAAK,OAAOvP,IAAI,CAAC,EAAE;AAClC,MAAI6F,GAAoBe,GAAIyI,GAAQE,CAAM,MAAM,MAChDD,EAAO,KAAK1I,CAAE,GACdyI,IAASzI;AAAA,IACX;AAGA,QAAI0I,EAAO,WAAW,EAAG,QAAO;AAGhC,UAAM1I,IAAK0I,EAAO,CAAC,GACbC,IAASD,EAAO,CAAC;AACvB,IAAIzJ,GAAoBe,GAAIyI,GAAQE,CAAM,MAAM,KAAGD,EAAO,MAAK,GAC/DA,EAAO,KAAKA,EAAO,CAAC,CAAC;AACrB,UAAME,IAAO,KAAK,eAAc,IAAK,IAAI,IACnCC,IAAS,KAAK,eAAc,IAAK,IAAIH,EAAO,SAAS,GACrDI,IAAO,KAAK,eAAc,IAAKJ,EAAO,SAAS,IAC/CK,IAAgB,CAAA;AACtB,aAAS3P,IAAIyP,GAAQzP,KAAK0P,GAAM1P,KAAKwP,EAAM,CAAAG,EAAc,KAAK,CAACL,EAAOtP,CAAC,EAAE,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC;AACxF,WAAO2P;AAAA,EACT;AAAA,EACA,iBAAiB;AACf,QAAI,KAAK,oBAAoB,QAAW;AACtC,YAAMC,IAAY,KAAK,cAAa;AACpC,WAAK,kBAAkBA,IAAY,CAACA,EAAU,eAAc,IAAK;AAAA,IACnE;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EACA,gBAAgB;AACd,WAAI,KAAK,mBAAmB,WAC1B,KAAK,iBAAiB,KAAK,mBAAkB,IAExC,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,qBAAqB;AAGnB,QAAIC,IAAc,KAAK,OAAO,CAAC;AAC/B,aAAS,IAAI,GAAG1H,IAAO,KAAK,OAAO,QAAQ,IAAIA,GAAM,KAAK;AACxD,YAAMC,IAAM,KAAK,OAAO,CAAC;AACzB,MAAIT,GAAW,QAAQkI,GAAazH,CAAG,IAAI,MAAGyH,IAAczH;AAAA,IAC9D;AACA,QAAI0H,IAAUD,EAAY,QAAQ,aAAY,GAC1CE,IAAcD,IAAUA,EAAQ,aAAY,IAAK;AACrD,eAAa;AAEX,UAAI,CAACA,EAAS,QAAO;AAIrB,UAAI,CAACC,EAAa,QAAOD,EAAQ;AAKjC,UAAIC,EAAY,YAAYD,EAAQ;AAClC,eAAIC,EAAY,QAAQ,cAAa,MAAOD,EAAQ,UAC3CA,EAAQ,UACHA,EAAQ,QAAQ,cAAa;AAK7C,MAAAA,IAAUC,EAAY,aAAY,GAClCA,IAAcD,IAAUA,EAAQ,aAAY,IAAK;AAAA,IACnD;AAAA,EACF;AACF;AACA,MAAME,GAAQ;AAAA,EACZ,YAAYC,GAAc;AACxB,SAAK,eAAeA,GACpBA,EAAa,OAAO,MACpB,KAAK,gBAAgB,CAAA;AAAA,EACvB;AAAA,EACA,YAAY7F,GAAM;AAChB,SAAK,cAAc,KAAKA,CAAI,GAC5BA,EAAK,OAAO;AAAA,EACd;AAAA,EACA,UAAU;AACR,UAAMgE,IAAO,CAAC,KAAK,aAAa,QAAO,CAAE;AAEzC,QAAIA,EAAK,CAAC,MAAM,KAAM,QAAO;AAC7B,aAASpO,IAAI,GAAGmI,IAAO,KAAK,cAAc,QAAQnI,IAAImI,GAAMnI,KAAK;AAC/D,YAAMkQ,IAAW,KAAK,cAAclQ,CAAC,EAAE,QAAO;AAE9C,MAAIkQ,MAAa,QACjB9B,EAAK,KAAK8B,CAAQ;AAAA,IACpB;AACA,WAAO9B;AAAA,EACT;AACF;AACA,MAAM+B,GAAa;AAAA,EACjB,YAAYjG,GAAO;AACjB,SAAK,QAAQA,GACb,KAAK,QAAQ,KAAK,cAAcA,CAAK;AAAA,EACvC;AAAA,EACA,UAAU;AACR,UAAMkE,IAAO,CAAA;AACb,aAASpO,IAAI,GAAGmI,IAAO,KAAK,MAAM,QAAQnI,IAAImI,GAAMnI,KAAK;AACvD,YAAMoQ,IAAW,KAAK,MAAMpQ,CAAC,EAAE,QAAO;AAEtC,MAAIoQ,MAAa,QACjBhC,EAAK,KAAKgC,CAAQ;AAAA,IACpB;AACA,WAAOhC;AAAA,EACT;AAAA,EACA,cAAclE,GAAO;AACnB,UAAMmG,IAAQ,CAAA;AACd,aAASrQ,IAAI,GAAGmI,IAAO+B,EAAM,QAAQlK,IAAImI,GAAMnI,KAAK;AAClD,YAAMoK,IAAOF,EAAMlK,CAAC;AACpB,UAAI,CAAAoK,EAAK;AACT,YAAIA,EAAK,eAAc,EAAI,CAAAiG,EAAM,KAAK,IAAIL,GAAQ5F,CAAI,CAAC;AAAA,aAAO;AAC5D,gBAAMkG,IAAgBlG,EAAK,cAAa;AACxC,UAAKkG,EAAc,QAAMD,EAAM,KAAK,IAAIL,GAAQM,CAAa,CAAC,GAC9DA,EAAc,KAAK,YAAYlG,CAAI;AAAA,QACrC;AAAA,IACF;AACA,WAAOiG;AAAA,EACT;AACF;AAaA,MAAME,GAAU;AAAA,EACd,YAAYC,GAAO;AACjB,QAAIpB,IAAa,UAAU,SAAS,KAAK,UAAU,CAAC,MAAM,SAAY,UAAU,CAAC,IAAIvH,GAAQ;AAC7F,SAAK,QAAQ2I,GACb,KAAK,OAAO,IAAInL,GAAU+J,CAAU,GACpC,KAAK,WAAW,CAAA;AAAA,EAClB;AAAA,EACA,QAAQT,GAAO;AACb,UAAMd,IAAUc,EAAM,SAChBhD,IAAY,CAAA;AAIlB,QAAIgD,EAAM;AACR,aAAIA,EAAM,SAAQ,KAAK,MAAM,OAAOA,EAAM,OAAO,IAAO,KAAK,KAAK,OAAOd,CAAO,GACzElC;AAET,UAAMpG,IAAOoJ,EAAM,SAAS,KAAK,KAAK,IAAId,CAAO,IAAI,KAAK,KAAK,KAAKA,CAAO;AAC3E,QAAI,CAACtI,EAAM,OAAM,IAAI,MAAM,2BAA2BsI,EAAQ,EAAE,KAAUA,EAAQ,OAAO,MAAM,CAAC,KAAKA,EAAQ,OAAO,MAAM,CAAC,SAAcA,EAAQ,QAAQ,MAAM,CAAC,KAAKA,EAAQ,QAAQ,MAAM,CAAC,sBAA2B;AACvN,QAAIrI,IAAWD,GACXE,IAAWF,GACXuK,GACAW;AAGJ,WAAOX,MAAY;AACjB,MAAAtK,IAAW,KAAK,KAAK,KAAKA,CAAQ,GAC9BA,MAAa,OAAMsK,IAAU,OAActK,EAAS,IAAI,eAAe,WAAWsK,IAAUtK,EAAS;AAI3G,WAAOiL,MAAY;AACjB,MAAAhL,IAAW,KAAK,KAAK,KAAKA,CAAQ,GAC9BA,MAAa,OAAMgL,IAAU,OAAchL,EAAS,IAAI,eAAe,WAAWgL,IAAUhL,EAAS;AAE3G,QAAIkJ,EAAM,QAAQ;AAEhB,UAAI+B,IAAiB;AACrB,UAAIZ,GAAS;AACX,cAAMa,IAAYb,EAAQ,gBAAgBjC,CAAO;AACjD,YAAI8C,MAAc,SACX9C,EAAQ,aAAa8C,CAAS,MAAGD,IAAiBC,IACnD,CAACb,EAAQ,aAAaa,CAAS,IAAG;AACpC,gBAAMC,IAAqB,KAAK,aAAad,GAASa,CAAS;AAC/D,mBAAS3Q,IAAI,GAAGmI,IAAOyI,EAAmB,QAAQ5Q,IAAImI,GAAMnI;AAC1D,YAAA2L,EAAU,KAAKiF,EAAmB5Q,CAAC,CAAC;AAAA,QAExC;AAAA,MAEJ;AAGA,UAAI6Q,IAAiB;AACrB,UAAIJ,GAAS;AACX,cAAMK,IAAYL,EAAQ,gBAAgB5C,CAAO;AACjD,YAAIiD,MAAc,SACXjD,EAAQ,aAAaiD,CAAS,MAAGD,IAAiBC,IACnD,CAACL,EAAQ,aAAaK,CAAS,IAAG;AACpC,gBAAMF,IAAqB,KAAK,aAAaH,GAASK,CAAS;AAC/D,mBAAS9Q,IAAI,GAAGmI,IAAOyI,EAAmB,QAAQ5Q,IAAImI,GAAMnI;AAC1D,YAAA2L,EAAU,KAAKiF,EAAmB5Q,CAAC,CAAC;AAAA,QAExC;AAAA,MAEJ;AAKA,UAAI0Q,MAAmB,QAAQG,MAAmB,MAAM;AACtD,YAAIE,IAAa;AACjB,QAAIL,MAAmB,OAAMK,IAAaF,IAAwBA,MAAmB,OAAME,IAAaL,IAEtGK,IADqBpJ,GAAW,cAAc+I,GAAgBG,CAAc,KAC/C,IAAIH,IAAiBG,GAKpD,KAAK,MAAM,OAAOhD,EAAQ,OAAO,GACjClC,EAAU,KAAKkC,EAAQ,OAAO;AAC9B,cAAM+C,IAAqB/C,EAAQ,MAAMkD,CAAU;AACnD,iBAAS/Q,IAAI,GAAGmI,IAAOyI,EAAmB,QAAQ5Q,IAAImI,GAAMnI;AAC1D,UAAA2L,EAAU,KAAKiF,EAAmB5Q,CAAC,CAAC;AAAA,MAExC;AACA,MAAI2L,EAAU,SAAS,KAIrB,KAAK,KAAK,OAAOkC,CAAO,GACxBlC,EAAU,KAAKgD,CAAK,MAGpB,KAAK,SAAS,KAAKd,CAAO,GAC1BA,EAAQ,OAAOiC;AAAA,IAEnB,OAAO;AAKL,UAAIA,KAAWW,GAAS;AACtB,cAAMO,IAAQlB,EAAQ,gBAAgBW,CAAO;AAC7C,YAAIO,MAAU,MAAM;AAClB,cAAI,CAAClB,EAAQ,aAAakB,CAAK,GAAG;AAChC,kBAAMJ,IAAqB,KAAK,aAAad,GAASkB,CAAK;AAC3D,qBAAShR,IAAI,GAAGmI,IAAOyI,EAAmB,QAAQ5Q,IAAImI,GAAMnI;AAC1D,cAAA2L,EAAU,KAAKiF,EAAmB5Q,CAAC,CAAC;AAAA,UAExC;AACA,cAAI,CAACyQ,EAAQ,aAAaO,CAAK,GAAG;AAChC,kBAAMJ,IAAqB,KAAK,aAAaH,GAASO,CAAK;AAC3D,qBAAShR,IAAI,GAAGmI,IAAOyI,EAAmB,QAAQ5Q,IAAImI,GAAMnI;AAC1D,cAAA2L,EAAU,KAAKiF,EAAmB5Q,CAAC,CAAC;AAAA,UAExC;AAAA,QACF;AAAA,MACF;AACA,WAAK,KAAK,OAAO6N,CAAO;AAAA,IAC1B;AACA,WAAOlC;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,aAAaU,GAAKzF,GAAI;AAKpB,SAAK,KAAK,OAAOyF,CAAG;AACpB,UAAMpC,IAAUoC,EAAI;AACpB,SAAK,MAAM,OAAOpC,CAAO;AACzB,UAAM0B,IAAYU,EAAI,MAAMzF,CAAE;AAC9B,WAAA+E,EAAU,KAAK1B,CAAO,GAElBoC,EAAI,eAAe,UAAW,KAAK,KAAK,IAAIA,CAAG,GAC5CV;AAAA,EACT;AACF;AAGA,MAAMsF,KAAkC,OAAO,UAAY,OAAe,QAAQ,IAAI,mCAAmC,KACnHC,KAA0C,OAAO,UAAY,OAAe,QAAQ,IAAI,2CAA2C;AACzI,MAAMC,GAAU;AAAA,EACd,IAAI3W,GAAM4T,GAAMgD,GAAW;AACzB,IAAArE,GAAU,OAAOvS,GACjBkL,GAAQ,MAAK;AAGb,UAAM2L,IAAa,CAAC,IAAIlD,GAAYC,GAAM,EAAI,CAAC;AAC/C,aAASpO,IAAI,GAAGmI,IAAOiJ,EAAU,QAAQpR,IAAImI,GAAMnI;AACjD,MAAAqR,EAAW,KAAK,IAAIlD,GAAYiD,EAAUpR,CAAC,GAAG,EAAK,CAAC;AAQtD,QANA+M,GAAU,gBAAgBsE,EAAW,QAMjCtE,GAAU,SAAS,cAAc;AAEnC,YAAMuE,IAAUD,EAAW,CAAC;AAC5B,UAAIrR,IAAI;AACR,aAAOA,IAAIqR,EAAW;AACpB,QAAI7M,GAAe6M,EAAWrR,CAAC,EAAE,MAAMsR,EAAQ,IAAI,MAAM,OAAMtR,MAASqR,EAAW,OAAOrR,GAAG,CAAC;AAAA,IAElG;AAKA,QAAI+M,GAAU,SAAS;AAGrB,eAAS/M,IAAI,GAAGmI,IAAOkJ,EAAW,QAAQrR,IAAImI,GAAMnI,KAAK;AACvD,cAAMuR,IAAMF,EAAWrR,CAAC;AACxB,iBAASuI,IAAIvI,IAAI,GAAGkO,IAAOmD,EAAW,QAAQ9I,IAAI2F,GAAM3F;AACtD,cAAI/D,GAAe+M,EAAI,MAAMF,EAAW9I,CAAC,EAAE,IAAI,MAAM,KAAM,QAAO,CAAA;AAAA,MAEtE;AAIF,UAAMiI,IAAQ,IAAInL,GAAUsC,GAAW,OAAO;AAC9C,aAAS3H,IAAI,GAAGmI,IAAOkJ,EAAW,QAAQrR,IAAImI,GAAMnI,KAAK;AACvD,YAAM4N,IAAcyD,EAAWrR,CAAC,EAAE,eAAc;AAChD,eAASuI,IAAI,GAAG2F,IAAON,EAAY,QAAQrF,IAAI2F,GAAM3F;AAEnD,YADAiI,EAAM,OAAO5C,EAAYrF,CAAC,CAAC,GACvBiI,EAAM,OAAOS;AAEf,gBAAM,IAAI,MAAM,wFAA6F;AAAA,IAGnH;AAGA,UAAMO,IAAY,IAAIjB,GAAUC,CAAK;AACrC,QAAIiB,IAAgBjB,EAAM,MACtBjL,IAAOiL,EAAM,IAAG;AACpB,WAAOjL,KAAM;AACX,YAAM6C,IAAM7C,EAAK;AACjB,UAAIiL,EAAM,SAASiB,GAAe;AAEhC,cAAMpF,IAAMjE,EAAI;AAChB,cAAM,IAAI,MAAM,mBAAmBA,EAAI,SAAS,SAAS,OAAO,gBAAqBA,EAAI,MAAM,CAAC,KAAKA,EAAI,MAAM,CAAC,mBAAmBiE,EAAI,EAAE,KAAUA,EAAI,OAAO,MAAM,CAAC,KAAKA,EAAI,OAAO,MAAM,CAAC,SAAcA,EAAI,QAAQ,MAAM,CAAC,KAAKA,EAAI,QAAQ,MAAM,CAAC,eAAe;AAAA,MACtQ;AACA,UAAImE,EAAM,OAAOS;AAEf,cAAM,IAAI,MAAM,4EAAiF;AAEnG,UAAIO,EAAU,SAAS,SAASN;AAE9B,cAAM,IAAI,MAAM,sFAA2F;AAE7G,YAAMvF,IAAY6F,EAAU,QAAQpJ,CAAG;AACvC,eAASpI,IAAI,GAAGmI,IAAOwD,EAAU,QAAQ3L,IAAImI,GAAMnI,KAAK;AACtD,cAAMoI,IAAMuD,EAAU3L,CAAC;AACvB,QAAIoI,EAAI,eAAe,UAAWoI,EAAM,OAAOpI,CAAG;AAAA,MACpD;AACA,MAAAqJ,IAAgBjB,EAAM,MACtBjL,IAAOiL,EAAM,IAAG;AAAA,IAClB;AAGA,IAAA9K,GAAQ,MAAK;AAGb,UAAM+I,IAAWF,GAAQ,QAAQiD,EAAU,QAAQ;AAEnD,WADe,IAAIrB,GAAa1B,CAAQ,EAC1B,QAAO;AAAA,EACvB;AACF;AAGA,MAAM1B,KAAY,IAAIoE,GAAS,GAEzBO,KAAQ,SAAUtD,GAAM;AAC5B,WAASuD,IAAO,UAAU,QAAQP,IAAY,IAAI,MAAMO,IAAO,IAAIA,IAAO,IAAI,CAAC,GAAGC,IAAO,GAAGA,IAAOD,GAAMC;AACvG,IAAAR,EAAUQ,IAAO,CAAC,IAAI,UAAUA,CAAI;AAEtC,SAAO7E,GAAU,IAAI,SAASqB,GAAMgD,CAAS;AAC/C,GACMS,KAAe,SAAUzD,GAAM;AACnC,WAAS0D,IAAQ,UAAU,QAAQV,IAAY,IAAI,MAAMU,IAAQ,IAAIA,IAAQ,IAAI,CAAC,GAAGC,IAAQ,GAAGA,IAAQD,GAAOC;AAC7G,IAAAX,EAAUW,IAAQ,CAAC,IAAI,UAAUA,CAAK;AAExC,SAAOhF,GAAU,IAAI,gBAAgBqB,GAAMgD,CAAS;AACtD,GACMY,KAAM,SAAU5D,GAAM;AAC1B,WAAS6D,IAAQ,UAAU,QAAQb,IAAY,IAAI,MAAMa,IAAQ,IAAIA,IAAQ,IAAI,CAAC,GAAGC,IAAQ,GAAGA,IAAQD,GAAOC;AAC7G,IAAAd,EAAUc,IAAQ,CAAC,IAAI,UAAUA,CAAK;AAExC,SAAOnF,GAAU,IAAI,OAAOqB,GAAMgD,CAAS;AAC7C,GACMe,KAAa,SAAUC,GAAa;AACxC,WAASC,IAAQ,UAAU,QAAQC,IAAgB,IAAI,MAAMD,IAAQ,IAAIA,IAAQ,IAAI,CAAC,GAAGE,IAAQ,GAAGA,IAAQF,GAAOE;AACjH,IAAAD,EAAcC,IAAQ,CAAC,IAAI,UAAUA,CAAK;AAE5C,SAAOxF,GAAU,IAAI,cAAcqF,GAAaE,CAAa;AAC/D;AACA,IAAIlG,KAAQ;AAAA,EACV,OAAOsF;AAAA,EACP,cAAcG;AAAA,EACd,KAAKG;AAAA,EACL,YAAYG;AACd;AC/+CO,SAASK,GAAcC,GAAiD;AAC9E,SAAIA,KAAU,OAAa,OACvBC,GAAaD,CAAM,KAAKE,GAAeF,CAAM,KAAKG,GAAeH,CAAM,IACnEA,IAED;AACR;AAYA,SAASI,GAAeC,GAAiC;AACxD,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK;AAC1D;AAEA,SAASC,GAAiBD,GAAwC;AACjE,SACC,MAAM,QAAQA,CAAK,KACnBA,EAAM,UAAU,KAChBD,GAAeC,EAAM,CAAC,CAAC,KACvBD,GAAeC,EAAM,CAAC,CAAC;AAEzB;AAEA,SAASJ,GAAaI,GAAwC;AAC7D,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,KAAKA,EAAM,MAAM,CAAAvO,MAASwO,GAAiBxO,CAAK,CAAC;AAChG;AAEA,SAASoO,GAAeG,GAA0C;AACjE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,KAAKA,EAAM,MAAM,CAAA1I,MAAQsI,GAAatI,CAAI,CAAC;AAC1F;AAEA,SAASwI,GAAeE,GAA0C;AACjE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,KAAKA,EAAM,MAAM,CAAAE,MAAWL,GAAeK,CAAO,CAAC;AAClG;AAEO,SAASC,GAAaC,GAAsD;AAClF,MAAI,CAAC,MAAM,QAAQA,CAAW,KAAKA,EAAY,SAAS,EAAG,QAAO,CAAA;AAClE,QAAMC,IAAqB,CAAA;AAC3B,aAAW5O,KAAS2O,GAAa;AAChC,QAAI,CAAC,MAAM,QAAQ3O,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAM5D,IAAI,OAAO4D,EAAM,CAAC,CAAC,GACnB7D,IAAI,OAAO6D,EAAM,CAAC,CAAC;AACzB,QAAI,CAAC,OAAO,SAAS5D,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,EAAG;AAChD,UAAM0S,IAAOD,EAAIA,EAAI,SAAS,CAAC;AAC/B,IAAIC,KAAQA,EAAK,CAAC,MAAMzS,KAAKyS,EAAK,CAAC,MAAM1S,KACzCyS,EAAI,KAAK,CAACxS,GAAGD,CAAC,CAAC;AAAA,EAChB;AACA,MAAIyS,EAAI,SAAS,EAAG,QAAO,CAAA;AAC3B,QAAME,IAAQF,EAAI,CAAC,GACbG,IAAOH,EAAIA,EAAI,SAAS,CAAC;AAC/B,UAAIE,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CH,EAAI,KAAK,CAACE,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBF,EAAI,UAAU,IAAIA,IAAM,CAAA;AAChC;AAEO,SAASI,GAAkBnJ,GAA6B;AAC9D,MAAI,CAAC,MAAM,QAAQA,CAAI,KAAKA,EAAK,SAAS,EAAG,QAAO;AACpD,MAAIpJ,IAAM;AACV,WAAShB,IAAI,GAAGA,IAAIoK,EAAK,SAAS,GAAGpK,KAAK,GAAG;AAC5C,UAAMS,IAAI2J,EAAKpK,CAAC,GACViF,IAAImF,EAAKpK,IAAI,CAAC;AACpB,IAAAgB,KAAOP,EAAE,CAAC,IAAIwE,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAIxE,EAAE,CAAC;AAAA,EAChC;AACA,SAAOO,IAAM;AACd;AAEA,SAASwS,GAAsBtJ,GAAyC;AACvE,MAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,WAAW,EAAG,QAAO,CAAA;AACxD,QAAMuJ,IAA8B,CAAA;AACpC,aAAWrJ,KAAQF,GAAO;AACzB,UAAMwJ,IAAST,GAAa7I,CAAI;AAChC,IAAIsJ,EAAO,UAAU,KAAGD,EAAW,KAAKC,CAAM;AAAA,EAC/C;AACA,MAAID,EAAW,WAAW,EAAG,QAAO,CAAA;AACpC,MAAIA,EAAW,WAAW,UAAU,CAACA,EAAW,CAAC,CAAC;AAElD,MAAIE,IAAa,GACbC,IAAY;AAChB,WAAS5T,IAAI,GAAGA,IAAIyT,EAAW,QAAQzT,KAAK,GAAG;AAC9C,UAAM6T,IAAO,KAAK,IAAIN,GAAkBE,EAAWzT,CAAC,CAAC,CAAC;AACtD,IAAI6T,KAAQD,MACZA,IAAYC,GACZF,IAAa3T;AAAA,EACd;AAEA,QAAMmT,IAAuB,CAACM,EAAWE,CAAU,CAAC;AACpD,WAAS3T,IAAI,GAAGA,IAAIyT,EAAW,QAAQzT,KAAK;AAC3C,IAAIA,MAAM2T,KACVR,EAAI,KAAKM,EAAWzT,CAAC,CAAC;AAEvB,SAAOmT;AACR;AAEO,SAASW,GAAqBC,GAA2D;AAC/F,MAAI,CAAC,MAAM,QAAQA,CAAQ,KAAKA,EAAS,WAAW,EAAG,QAAO,CAAA;AAE9D,QAAMV,IAAQU,EAAS,CAAC;AACxB,MAAIhB,GAAiBM,CAAK,GAAG;AAC5B,UAAML,IAAUQ,GAAsB,CAACO,CAAyB,CAAC;AACjE,WAAOf,EAAQ,SAAS,IAAI,CAACA,CAAO,IAAI,CAAA;AAAA,EACzC;AAEA,MAAI,CAAC,MAAM,QAAQK,CAAK,KAAKA,EAAM,WAAW,EAAG,QAAO,CAAA;AACxD,QAAMW,IAASX,EAAM,CAAC;AACtB,MAAIN,GAAiBiB,CAAM,GAAG;AAC7B,UAAMhB,IAAUQ,GAAsBO,CAA2B;AACjE,WAAOf,EAAQ,SAAS,IAAI,CAACA,CAAO,IAAI,CAAA;AAAA,EACzC;AAEA,MAAI,CAAC,MAAM,QAAQgB,CAAM,KAAKA,EAAO,WAAW,KAAK,CAACjB,GAAiBiB,EAAO,CAAC,CAAC;AAC/E,WAAO,CAAA;AAGR,QAAMb,IAAuB,CAAA;AAC7B,aAAWH,KAAWe,GAA6B;AAClD,UAAMN,IAAaD,GAAsBR,CAAO;AAChD,IAAIS,EAAW,SAAS,KAAGN,EAAI,KAAKM,CAAU;AAAA,EAC/C;AACA,SAAON;AACR;AAEO,SAASc,GAAYtT,GAAWD,GAAW0J,GAA8B;AAC/E,MAAI8J,IAAS;AACb,WAAS,IAAI,GAAG3L,IAAI6B,EAAK,SAAS,GAAG,IAAIA,EAAK,QAAQ7B,IAAI,GAAG,KAAK,GAAG;AACpE,UAAM4L,IAAK/J,EAAK,CAAC,EAAE,CAAC,GACdgK,IAAKhK,EAAK,CAAC,EAAE,CAAC,GACdiK,IAAKjK,EAAK7B,CAAC,EAAE,CAAC,GACd+L,IAAKlK,EAAK7B,CAAC,EAAE,CAAC;AAEpB,QADI6L,MAAOE,KACNF,IAAK1T,KAAQ4T,IAAK5T,EAAI;AAE3B,IADkBC,KAAM0T,IAAKF,MAAOzT,IAAI0T,MAAQE,IAAKF,KAAMD,UACnC,CAACD;AAAA,EAC1B;AACA,SAAOA;AACR;AAmBO,SAASK,GACfC,GACuB;AACvB,QAAMC,IAAiC,CAAA;AACvC,aAAWV,KAAYS,KAAc,IAAI;AACxC,UAAME,IAAeZ,GAAqBC,CAAQ;AAClD,eAAWf,KAAW0B,GAAc;AACnC,YAAMC,IAAQ3B,EAAQ,CAAC;AACvB,UAAI,CAAC2B,KAASA,EAAM,SAAS,EAAG;AAChC,UAAIC,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,iBAAW,CAACpU,GAAGD,CAAC,KAAKiU;AACpB,QAAIhU,IAAIiU,MAAMA,IAAOjU,IACjBA,IAAImU,MAAMA,IAAOnU,IACjBD,IAAImU,MAAMA,IAAOnU,IACjBA,IAAIqU,MAAMA,IAAOrU;AAEtB,UACC,CAAC,OAAO,SAASkU,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI;AAErB;AAED,UAAIlB,IAAO,KAAK,IAAIN,GAAkBoB,CAAK,CAAC;AAC5C,eAAS3U,IAAI,GAAGA,IAAIgT,EAAQ,QAAQhT,KAAK;AACxC,QAAA6T,KAAQ,KAAK,IAAIN,GAAkBP,EAAQhT,CAAC,CAAC,CAAC;AAE/C,MAAAyU,EAAS,KAAK;AAAA,QACb,OAAAE;AAAA,QACA,OAAO3B,EAAQ,MAAM,CAAC;AAAA,QACtB,MAAA4B;AAAA,QACA,MAAAC;AAAA,QACA,MAAAC;AAAA,QACA,MAAAC;AAAA,QACA,MAAM,KAAK,IAAI,MAAMlB,CAAI;AAAA,MAAA,CACzB;AAAA,IACF;AAAA,EACD;AACA,SAAOY;AACR;AAEO,SAASO,GACfrU,GACAD,GACAsS,GACU;AAIV,MAHIrS,IAAIqS,EAAQ,QAAQrS,IAAIqS,EAAQ,QAAQtS,IAAIsS,EAAQ,QAAQtS,IAAIsS,EAAQ,QAGxE,CAACiB,GAAYtT,GAAGD,GAAGsS,EAAQ,KAAK,EAAG,QAAO;AAC9C,aAAWiC,KAAQjC,EAAQ;AAC1B,QAAIiB,GAAYtT,GAAGD,GAAGuU,CAAI,EAAG,QAAO;AAErC,SAAO;AACR;AAEO,SAASC,GACfvU,GACAD,GACAyU,GACU;AACV,aAAWnC,KAAWmC;AACrB,QAAKH,GAAuBrU,GAAGD,GAAGsS,CAAO;AACzC,aAAO;AAER,SAAO;AACR;AClPO,MAAMoC,KAAwD;AAAA,EACpE;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAChB;ACCO,SAASC,EAAMvC,GAAewC,GAAaC,GAAqB;AACtE,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKzC,CAAK,CAAC;AAC1C;AAEO,SAAS0C,GACfC,GACAC,GACAC,GACS;AACT,QAAMC,IAAM,OAAOH,CAAQ,GACrBI,IAAK,OAAOH,CAAS,GACrBI,IAAK,OAAOH,CAAW;AAC7B,SAAI,CAAC,OAAO,SAASC,CAAG,KAAKA,KAAO,IAAU,IAC1C,CAAC,OAAO,SAASC,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,IAAUF,IAClD,KAAK,IAAI,GAAGC,IAAKC,CAAE,IAAIF;AAC/B;AAEO,SAASG,GACfN,GACAO,GACS;AACT,QAAMJ,IAAM,OAAOH,CAAQ,GACrBzZ,IAAO,OAAOga,CAAQ;AAE5B,SADI,CAAC,OAAO,SAASJ,CAAG,KAAKA,KAAO,KAChC,CAAC,OAAO,SAAS5Z,CAAI,KAAKA,KAAQ,IAAU,IACzCA,KAAQ,KAAK4Z;AACrB;AAEO,SAASK,GACfR,GACAC,GACAC,GACS;AAET,MAAIzP,IAAS,MADMsP,GAAoBC,GAAUC,GAAWC,CAAW;AAEvE,MAAI,OAAOF,CAAQ,GAAG;AACrB,QAAIS,IAAO;AACX,WAAIhQ,IAAS,QACZA,KAAU,KACVgQ,IAAO,OAED,GAAGhQ,EAAO,YAAY,CAAC,CAAC,IAAIgQ,CAAI;AAAA,EACxC;AACA,SAAO,GAAG,KAAK,MAAMhQ,IAAS,GAAI,IAAI,GAAI;AAC3C;AAEO,SAASiQ,KAAgB;AAC/B,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC7D,YAAY,IAAA,IAEb,KAAK,IAAA;AACb;AAEO,SAASC,GAAmBC,GAAiC;AACnE,QAAMC,IACLD,EAAU,qBAAqB,aAC5BA,EAAU,UAAU,SACpB,OAAO;AACX,SAAO,KAAK;AAAA,IACX;AAAA,IACA,KAAK;AAAA,MACJ,KAAK,MAAMA,EAAU,SAAS,CAAC;AAAA,MAC/B,KAAK,OAAOA,EAAU,WAAW,UAAU,KAAK,CAAC;AAAA,MACjDA,EAAU,gBAAgB,UAAU;AAAA,MACpCC;AAAA,IAAA;AAAA,EACD;AAEF;AAEO,SAASC,GACf9V,GACAwE,GACU;AACV,SAAI,CAACxE,KAAK,CAACwE,IAAU,KACjB,CAACxE,KAAK,CAACwE,IAAU,KAEpB,KAAK,KAAKxE,EAAE,QAAQ,MAAMwE,EAAE,QAAQ,EAAE,IAAI,QAC1C,KAAK,KAAKxE,EAAE,WAAW,MAAMwE,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKxE,EAAE,WAAW,MAAMwE,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKxE,EAAE,eAAe,MAAMwE,EAAE,eAAe,EAAE,IAAI;AAE1D;AAEO,SAASuR,GAAc1D,GAA0C;AACvE,QAAM2D,IAAU,OAAO3D,KAAS,EAAE,EAAE,KAAA;AACpC,MAAI,CAAC2D,EAAS,QAAO;AACrB,MAAI,cAAc,KAAKA,CAAO,GAAG;AAChC,UAAMC,IAAQD,EAAQ,QAAQ,eAAe,EAAE,EAAE,KAAA;AACjD,WAAOC,IAAQ,UAAUA,CAAK,KAAK;AAAA,EACpC;AACA,SAAO,UAAUD,CAAO;AACzB;AAEO,SAASE,GACfC,GACmC;AAEnC,QAAMC,IADQ,OAAOD,KAAO,EAAE,EAAE,KAAA,EACZ,MAAM,sBAAsB;AAChD,MAAI,CAACC,EAAO,QAAO,CAAC,GAAGzB,EAAmB;AAE1C,QAAMvV,IAAI,OAAO,SAASgX,EAAM,CAAC,GAAG,EAAE;AACtC,SAAO,CAAEhX,KAAK,KAAM,KAAMA,KAAK,IAAK,KAAKA,IAAI,KAAK,GAAG;AACtD;AAEO,SAASiX,GACfhE,GACAiE,GACmC;AACnC,QAAMC,IAAQ,OAAOlE,KAAS,EAAE,EAAE,KAAA;AAClC,MAAI,CAACkE,EAAO,QAAO,CAAC,GAAGD,CAAQ;AAE/B,QAAME,IAAWD,EAAM,MAAM,qCAAqC;AAClE,MAAIC,GAAU;AACb,UAAML,IAAMK,EAAS,CAAC,EAAE,WAAW,IAAIA,EAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,OAAMC,IAAKA,CAAE,EAAE,KAAK,EAAE,IAAID,EAAS,CAAC,GAC/FpX,IAAI,OAAO,SAAS+W,GAAK,EAAE;AACjC,WAAO,CAAE/W,KAAK,KAAM,KAAMA,KAAK,IAAK,KAAKA,IAAI,KAAK,GAAG;AAAA,EACtD;AAEA,SAAO,CAAC,GAAGkX,CAAQ;AACpB;AAEA,SAASI,GACRC,GAIS;AACT,QAAMC,IAAU,OAAOD,GAAM,WAAW,EAAE,EAAE,KAAA;AAC5C,SAAIC,KACG,OAAOD,GAAM,aAAa,EAAE,EAAE,KAAA;AACtC;AAEO,SAASE,GACfC,GAIe;AACf,QAAMC,IAAmD;AAAA,IACxD,CAAC,GAAGpC,EAAmB;AAAA,EAAA,GAElBqC,wBAA0B,IAAA;AAEhC,aAAWL,KAAQG,KAAW,IAAI;AACjC,UAAMG,IAAWP,GAAuBC,CAAI;AAC5C,IAAI,CAACM,KAAYD,EAAoB,IAAIC,CAAQ,MAEjDD,EAAoB,IAAIC,GAAUF,EAAQ,MAAM,GAChDA,EAAQ,KAAKb,GAAUS,GAAM,UAAU,CAAC;AAAA,EACzC;AAEA,QAAMO,IAAS,IAAI,WAAWH,EAAQ,SAAS,CAAC;AAChD,WAAS,IAAI,GAAG,IAAIA,EAAQ,QAAQ,KAAK;AACxC,IAAAG,EAAO,IAAI,CAAC,IAAIH,EAAQ,CAAC,EAAE,CAAC,GAC5BG,EAAO,IAAI,IAAI,CAAC,IAAIH,EAAQ,CAAC,EAAE,CAAC,GAChCG,EAAO,IAAI,IAAI,CAAC,IAAIH,EAAQ,CAAC,EAAE,CAAC,GAChCG,EAAO,IAAI,IAAI,CAAC,IAAIH,EAAQ,CAAC,EAAE,CAAC;AAGjC,SAAO,EAAE,QAAAG,GAAQ,qBAAAF,EAAA;AAClB;ACjJA,MAAMG,KAAmB,CAAC,GAAG,GAAG,CAAC,GAC3BC,KAAuB,IACvBC,KAA0B,MAC1BC,KAA2B,GAC3BC,KAAuB,GACvBC,KAAa,MACbC,KAA2B;AAEjC,SAASC,GAAa7I,GAA0D;AAC/E,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAA;AAC1D,QAAM6D,IAA+B,CAAA;AACrC,aAAW5O,KAAS+K,GAAQ;AAC3B,QAAI,CAAC,MAAM,QAAQ/K,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAM5D,IAAI,OAAO4D,EAAM,CAAC,CAAC,GACnB7D,IAAI,OAAO6D,EAAM,CAAC,CAAC;AACzB,QAAI,CAAC,OAAO,SAAS5D,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,EAAG;AAChD,UAAM0S,IAAOD,EAAIA,EAAI,SAAS,CAAC;AAC/B,IAAIC,KAAQ,KAAK,IAAIA,EAAK,CAAC,IAAIzS,CAAC,IAAI,QAAQ,KAAK,IAAIyS,EAAK,CAAC,IAAI1S,CAAC,IAAI,QAGpEyS,EAAI,KAAK,CAACxS,GAAGD,CAAC,CAAC;AAAA,EAChB;AACA,SAAOyS;AACR;AAEA,SAASiF,GAAiBC,GAA+BC,GAAgBC,GAAwC;AAChH,MAAID,KAAUL,MAAcM,IAAQ,UAAU,CAAA;AAC9C,QAAMnO,IAAgC,CAAA;AACtC,WAAS,IAAI,GAAG,KAAKmO,GAAO,KAAK,GAAG;AACnC,UAAMC,IAAK,IAAID,IAAS,KAAK,KAAK;AAClC,IAAAnO,EAAK,KAAK,CAACiO,EAAO,CAAC,IAAI,KAAK,IAAIG,CAAC,IAAIF,GAAQD,EAAO,CAAC,IAAI,KAAK,IAAIG,CAAC,IAAIF,CAAM,CAAC;AAAA,EAC/E;AACA,SAAOG,GAAUrO,CAAI;AACtB;AAEA,SAASsO,GACRC,GACAC,GACAN,GACAO,GAC0B;AAC1B,QAAMvc,IAAKsc,EAAI,CAAC,IAAID,EAAM,CAAC,GACrBpc,IAAKqc,EAAI,CAAC,IAAID,EAAM,CAAC,GACrBzS,IAAS,KAAK,KAAK5J,IAAKA,IAAKC,IAAKA,CAAE;AAC1C,MAAI,CAAC,OAAO,SAAS2J,CAAM,KAAKA,KAAU2S,UAAkB,CAAA;AAE5D,QAAMC,IAAKxc,IAAK4J,GAEV6S,IAAQ,EADHxc,IAAK2J,IAEV8S,IAAQF,GACRG,IAAI,KAAK,IAAIhB,IAAYK,CAAM;AACrC,SAAOG,GAAU;AAAA,IAChB,CAACE,EAAM,CAAC,IAAII,IAAQE,GAAGN,EAAM,CAAC,IAAIK,IAAQC,CAAC;AAAA,IAC3C,CAACL,EAAI,CAAC,IAAIG,IAAQE,GAAGL,EAAI,CAAC,IAAII,IAAQC,CAAC;AAAA,IACvC,CAACL,EAAI,CAAC,IAAIG,IAAQE,GAAGL,EAAI,CAAC,IAAII,IAAQC,CAAC;AAAA,IACvC,CAACN,EAAM,CAAC,IAAII,IAAQE,GAAGN,EAAM,CAAC,IAAIK,IAAQC,CAAC;AAAA,EAAA,CAC3C;AACF;AAEA,SAASC,GAAqB5J,GAAiCgJ,GAAyC;AACvG,MAAI,CAAChJ,EAAO,OAAQ,QAAO,CAAA;AAC3B,MAAIsF,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAW,CAACpU,GAAGD,CAAC,KAAK4O;AACpB,IAAI3O,IAAIiU,MAAMA,IAAOjU,IACjBA,IAAImU,MAAMA,IAAOnU,IACjBD,IAAImU,MAAMA,IAAOnU,IACjBA,IAAIqU,MAAMA,IAAOrU;AAEtB,MAAI,CAAC,OAAO,SAASkU,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,EAAG,QAAO,CAAA;AAC7D,QAAMsE,IAAM,KAAK,IAAIb,GAAQ,CAAC;AAC9B,SAAOG,GAAU;AAAA,IAChB,CAAC7D,IAAOuE,GAAKtE,IAAOsE,CAAG;AAAA,IACvB,CAACrE,IAAOqE,GAAKtE,IAAOsE,CAAG;AAAA,IACvB,CAACrE,IAAOqE,GAAKpE,IAAOoE,CAAG;AAAA,IACvB,CAACvE,IAAOuE,GAAKpE,IAAOoE,CAAG;AAAA,EAAA,CACvB;AACF;AAEA,SAASC,GACRhP,GACAiP,GAC0B;AAC1B,SACOZ;AAAAA,IADFY,IAEJjP,EAAK,IAAI,CAAC,CAACzJ,GAAGD,CAAC,MAAM;AAAA,MACpB2U,EAAM1U,GAAG0Y,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,MAC7BhE,EAAM3U,GAAG2Y,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IAAA,CACJ,IALGjP;AAAA,EAKH;AAE5B;AAEA,SAASkP,GAAMxG,GAAeyG,GAA2B;AACxD,SAAK,OAAO,SAASzG,CAAK,IACnB,OAAOA,EAAM,QAAQyG,CAAS,CAAC,IADFzG;AAErC;AAEA,SAAS0G,GAAapP,GAA4BmP,GAAyC;AAC1F,MAAI,CAAC,MAAM,QAAQnP,CAAI,KAAKA,EAAK,WAAW,EAAG,QAAO,CAAA;AACtD,QAAMqP,IAAkC,CAAA;AACxC,aAAWlV,KAAS6F,GAAM;AACzB,QAAI,CAAC,MAAM,QAAQ7F,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAM5D,IAAI2Y,GAAM,OAAO/U,EAAM,CAAC,CAAC,GAAGgV,CAAS,GACrC7Y,IAAI4Y,GAAM,OAAO/U,EAAM,CAAC,CAAC,GAAGgV,CAAS;AAC3C,QAAI,CAAC,OAAO,SAAS5Y,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,EAAG;AAChD,UAAM0S,IAAOqG,EAAUA,EAAU,SAAS,CAAC;AAC3C,KAAI,CAACrG,KAAQA,EAAK,CAAC,MAAMzS,KAAKyS,EAAK,CAAC,MAAM1S,MACzC+Y,EAAU,KAAK,CAAC9Y,GAAGD,CAAC,CAAC;AAAA,EAEvB;AAEA,MAAI+Y,EAAU,UAAU,GAAG;AAC1B,UAAMpG,IAAQoG,EAAU,CAAC,GACnBnG,IAAOmG,EAAUA,EAAU,SAAS,CAAC;AAC3C,QAAI,CAACpG,KAAS,CAACC,UAAa,CAAA;AAC5B,KAAID,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CmG,EAAU,KAAK,CAACpG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC;AAAA,EAErC;AAEA,SAAOoG,EAAU,UAAU,IAAIA,IAAY,CAAA;AAC5C;AAEA,SAASC,GAAgB1G,GAAkCuG,GAA4C;AACtG,MAAI,CAAC,MAAM,QAAQvG,CAAO,KAAKA,EAAQ,WAAW,EAAG,QAAO,CAAA;AAC5D,QAAM9I,IAAQ8I,EACZ,IAAI,CAAA5I,MAAQoP,GAAapP,GAAMmP,CAAS,CAAC,EACzC,OAAO,CAAAnP,MAAQA,EAAK,UAAU,CAAC;AACjC,SAAOF,EAAM,SAAS,IAAIA,IAAQ,CAAA;AACnC;AAEA,SAASyP,GACRxE,GACAoE,GACsC;AACtC,QAAME,IAAYtE,EAChB,IAAI,CAAAnC,MAAW0G,GAAgB1G,GAASuG,CAAS,CAAC,EAClD,OAAO,CAAAvG,MAAWA,EAAQ,SAAS,CAAC;AACtC,MAAIyG,EAAU,WAAW,EAAG,QAAO;AAEnC,MAAIG,IAAwC,CAACH,EAAU,CAAC,CAAC;AACzD,MAAI;AACH,aAAS,IAAI,GAAG,IAAIA,EAAU,QAAQ,KAAK;AAE1C,UADAG,IAAUC,GAAgB,MAAMD,GAAS,CAACH,EAAU,CAAC,CAAC,CAAC,GACnD,CAAC,MAAM,QAAQG,CAAO,KAAKA,EAAQ,WAAW;AACjD,eAAO;AAAA,EAGV,SAAS/a,GAAO;AAEf,mBAAQ,MAAM,wCAAwC0a,GAAW1a,CAAK,GAC/D;AAAA,EACR;AAEA,SAAO+a,EAAQ,SAAS,IAAIA,IAAU;AACvC;AAEA,SAASE,GAAc3E,GAA0E;AAChG,MAAIA,EAAS,WAAW,EAAG,QAAO;AAClC,aAAWoE,KAAa3B,IAAkB;AACzC,UAAMmC,IAASJ,GAAsBxE,GAAUoE,CAAS;AACxD,QAAIQ,EAAQ,QAAOA;AAAA,EACpB;AACA,SAAO;AACR;AAEA,SAASC,GAAY5P,GAAqD;AACzE,MAAI,CAAC,MAAM,QAAQA,CAAI,KAAKA,EAAK,WAAW,EAAG,QAAO,CAAA;AACtD,QAAM+I,IAA+B,CAAA;AACrC,aAAW5O,KAAS6F,GAAM;AACzB,QAAI,CAAC,MAAM,QAAQ7F,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAM5D,IAAI,OAAO4D,EAAM,CAAC,CAAC,GACnB7D,IAAI,OAAO6D,EAAM,CAAC,CAAC;AACzB,IAAI,CAAC,OAAO,SAAS5D,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,KAC7CyS,EAAI,KAAK,CAACxS,GAAGD,CAAC,CAAC;AAAA,EAChB;AACA,SAAO+X,GAAUtF,CAAG;AACrB;AAEA,SAAS8G,GAAuBC,GAAqE;AACpG,MAAIC,IAAgC,CAAA,GAChCC,IAAW;AACf,aAAWpH,KAAWkH,GAAc;AACnC,QAAI,CAAC,MAAM,QAAQlH,CAAO,KAAKA,EAAQ,WAAW,EAAG;AACrD,UAAM2B,IAAQqF,GAAYhH,EAAQ,CAAC,KAAK,CAAA,CAAE;AAC1C,QAAI2B,EAAM,SAAS,EAAG;AACtB,UAAMd,IAAO,KAAK,IAAIN,GAAkBoB,CAAK,CAAC;AAC9C,IAAId,KAAQuG,MACZA,IAAWvG,GACXsG,IAAOxF;AAAA,EACR;AACA,SAAOwF;AACR;AAEA,SAASE,GACRjQ,GACAvJ,IAAU,MACgB;AAC1B,QAAM6S,IAAS+E,GAAUrO,CAAI;AAC7B,MAAIsJ,EAAO,SAAS,EAAG,QAAOA;AAC9B,QAAMP,IAA+B,CAACO,EAAO,CAAC,CAAC;AAC/C,WAAS,IAAI,GAAG,IAAIA,EAAO,SAAS,GAAG,KAAK,GAAG;AAC9C,UAAMN,IAAOD,EAAIA,EAAI,SAAS,CAAC,GACzBmH,IAAO5G,EAAO,CAAC,GACf3X,IAAO2X,EAAO,IAAI,CAAC,GACnB6G,KACJD,EAAK,CAAC,IAAIlH,EAAK,CAAC,MAAMrX,EAAK,CAAC,IAAIue,EAAK,CAAC,MACtCA,EAAK,CAAC,IAAIlH,EAAK,CAAC,MAAMrX,EAAK,CAAC,IAAIue,EAAK,CAAC;AACxC,IAAI,KAAK,IAAIC,CAAK,KAAK1Z,KACvBsS,EAAI,KAAKmH,CAAI;AAAA,EACd;AACA,SAAAnH,EAAI,KAAKA,EAAI,CAAC,CAAC,GACRsF,GAAUtF,CAAG;AACrB;AAEA,SAASqH,GACR5Z,GACAH,GACAwE,GACS;AACT,QAAMwV,IAAMxV,EAAE,CAAC,IAAIxE,EAAE,CAAC,GAChBia,IAAMzV,EAAE,CAAC,IAAIxE,EAAE,CAAC,GAChBka,IAAOF,IAAMA,IAAMC,IAAMA;AAC/B,MAAIC,KAAQ,OAAO;AAClB,UAAMre,IAAKsE,EAAE,CAAC,IAAIH,EAAE,CAAC,GACflE,IAAKqE,EAAE,CAAC,IAAIH,EAAE,CAAC;AACrB,WAAOnE,IAAKA,IAAKC,IAAKA;AAAAA,EACvB;AACA,QAAMic,IAAInD;AAAA,MACPzU,EAAE,CAAC,IAAIH,EAAE,CAAC,KAAKga,KAAO7Z,EAAE,CAAC,IAAIH,EAAE,CAAC,KAAKia,KAAOC;AAAA,IAC9C;AAAA,IACA;AAAA,EAAA,GAEKha,IAAIF,EAAE,CAAC,IAAIga,IAAMjC,GACjB9X,IAAID,EAAE,CAAC,IAAIia,IAAMlC,GACjBlc,IAAKsE,EAAE,CAAC,IAAID,GACZpE,IAAKqE,EAAE,CAAC,IAAIF;AAClB,SAAOpE,IAAKA,IAAKC,IAAKA;AACvB;AAEA,SAASqe,GAAYtL,GAAiCuL,GAA4C;AACjG,MAAIvL,EAAO,UAAU,KAAKuL,KAAa,EAAG,QAAOvL,EAAO,MAAA;AAExD,QAAMwL,IAAO,IAAI,WAAWxL,EAAO,MAAM;AACzC,EAAAwL,EAAK,CAAC,IAAI,GACVA,EAAKxL,EAAO,SAAS,CAAC,IAAI;AAC1B,QAAMyL,IAAaF,IAAYA,GACzBG,IAAiC,CAAC,CAAC,GAAG1L,EAAO,SAAS,CAAC,CAAC;AAE9D,SAAO0L,EAAM,SAAS,KAAG;AACxB,UAAMjf,IAAOif,EAAM,IAAA;AACnB,QAAI,CAACjf,EAAM;AACX,UAAM,CAAC4c,GAAOC,CAAG,IAAI7c;AACrB,QAAI6c,IAAMD,KAAS,EAAG;AAEtB,QAAIsC,IAAW,GACXC,IAAQ;AACZ,aAASlb,IAAI2Y,IAAQ,GAAG3Y,IAAI4Y,GAAK5Y,KAAK,GAAG;AACxC,YAAMmb,IAAQX,GAAyBlL,EAAOtP,CAAC,GAAGsP,EAAOqJ,CAAK,GAAGrJ,EAAOsJ,CAAG,CAAC;AAC5E,MAAIuC,IAAQF,MACXA,IAAWE,GACXD,IAAQlb;AAAA,IAEV;AAEA,IAAIkb,KAAS,KAAKD,IAAWF,MAC5BD,EAAKI,CAAK,IAAI,GACdF,EAAM,KAAK,CAACrC,GAAOuC,CAAK,GAAG,CAACA,GAAOtC,CAAG,CAAC;AAAA,EAEzC;AAEA,QAAMzF,IAA+B,CAAA;AACrC,WAASnT,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK;AACvC,IAAI8a,EAAK9a,CAAC,OAAO,KAAKsP,EAAOtP,CAAC,CAAC;AAEhC,SAAOmT;AACR;AAEA,SAASiI,GAAmBhR,GAA+ByQ,GAA4C;AACtG,QAAMnH,IAAS+E,GAAUrO,CAAI;AAC7B,MAAIsJ,EAAO,SAAS,KAAKmH,KAAa,EAAG,QAAOnH;AAChD,QAAM2H,IAAO3H,EAAO,MAAM,GAAG,EAAE,GACzB4H,IAAaV,GAAYS,GAAMR,CAAS;AAC9C,SAAIS,EAAW,SAAS,IAAU5H,IAC3B+E,GAAU6C,CAAU;AAC5B;AAEA,SAASC,GACRnR,GACAoR,GAC0B;AAC1B,MAAIrI,IAAMsF,GAAUrO,CAAI;AACxB,MAAIoR,KAAc,KAAKrI,EAAI,SAAS,EAAG,QAAOA;AAE9C,WAASsI,IAAO,GAAGA,IAAOD,GAAYC,KAAQ,GAAG;AAChD,UAAMJ,IAAOlI,EAAI,MAAM,GAAG,EAAE;AAC5B,QAAIkI,EAAK,SAAS,EAAG;AACrB,UAAMtf,IAAgC,CAAA;AACtC,aAASiE,IAAI,GAAGA,IAAIqb,EAAK,QAAQrb,KAAK,GAAG;AACxC,YAAM,IAAIqb,EAAKrb,CAAC,GACViF,IAAIoW,GAAMrb,IAAI,KAAKqb,EAAK,MAAM;AACpC,MAAAtf,EAAK;AAAA,QACJ,CAAC,EAAE,CAAC,IAAI,OAAOkJ,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,IAAI,OAAOA,EAAE,CAAC,IAAI,IAAI;AAAA,QACrD,CAAC,EAAE,CAAC,IAAI,OAAOA,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,IAAI,OAAOA,EAAE,CAAC,IAAI,IAAI;AAAA,MAAA;AAAA,IAEvD;AACA,IAAAkO,IAAMsF,GAAU1c,CAAI;AAAA,EACrB;AACA,SAAOoX;AACR;AAEO,SAASuI,GACfC,GACApgB,GAC0B;AAC1B,QAAM+T,IAAS6I,GAAawD,CAAI,GAC1BrD,IAAS,KAAK,IAAIL,IAAY,OAAO1c,EAAQ,MAAM,KAAK,CAAC;AAC/D,MAAI+T,EAAO,WAAW,KAAK,CAAC,OAAO,SAASgJ,CAAM,EAAG,QAAO,CAAA;AAE5D,QAAMsD,IAAc,KAAK,IAAI,IAAI,KAAK,MAAMrgB,EAAQ,eAAesc,EAAoB,CAAC;AACxF,MAAIvI,EAAO,WAAW;AACrB,WAAO8J,GAAkBhB,GAAiB9I,EAAO,CAAC,GAAGgJ,GAAQsD,CAAW,GAAGrgB,EAAQ,UAAU;AAG9F,QAAM4Z,IAAsC,CAAA,GACtC0G,IAAkB,KAAK,IAAI5D,IAAYK,IAASJ,EAAwB;AAC9E,WAASlY,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK,GAAG;AAC1C,UAAMqY,IAAS/I,EAAOtP,CAAC,GACjB8b,IAAS1D,GAAiBC,GAAQC,GAAQsD,CAAW;AAI3D,QAHIE,EAAO,UAAU,KACpB3G,EAAS,KAAK,CAAC2G,CAAM,CAAC,GAEnB9b,MAAM,EAAG;AACb,UAAM+b,IAASrD,GAAiBpJ,EAAOtP,IAAI,CAAC,GAAGqY,GAAQC,GAAQuD,CAAe;AAC9E,IAAIE,EAAO,UAAU,KACpB5G,EAAS,KAAK,CAAC4G,CAAM,CAAC;AAAA,EAExB;AAEA,QAAMC,IAAUlC,GAAc3E,CAAQ,GAChC8G,IAAYD,IAAU/B,GAAuB+B,CAAO,IAAI,CAAA;AAC9D,MAAI,CAACC,EAAU;AACd,WAAO7C,GAAkBF,GAAqB5J,GAAQgJ,CAAM,GAAG/c,EAAQ,UAAU;AAGlF,QAAMsf,IACL,OAAOtf,EAAQ,qBAAsB,YAAY,OAAO,SAASA,EAAQ,iBAAiB,IACvF,KAAK,IAAI,GAAGA,EAAQ,iBAAiB,IACrC,KAAK,IAAI,MAAM+c,IAASR,EAAuB,GAC7CoE,IACL,OAAO3gB,EAAQ,mBAAoB,YAAY,OAAO,SAASA,EAAQ,eAAe,IACnF,KAAK,MAAM8Z,EAAM9Z,EAAQ,iBAAiB,GAAGyc,EAAoB,CAAC,IAClED,IAEEoE,IAAYf;AAAA,IACjBG;AAAA,MACClB,GAAwB4B,GAAW,IAAI;AAAA,MACvCC;AAAA,IAAA;AAAA,IAEDrB;AAAA,EAAA;AAGD,SAAIsB,EAAU,SAAS,IACf/C,GAAkBF,GAAqB5J,GAAQgJ,CAAM,GAAG/c,EAAQ,UAAU,IAE3E6d,GAAkB+C,GAAW5gB,EAAQ,UAAU;AACvD;AClYA,SAAS6gB,KAA+B;AACtC,MAAI,OAAO,SAAW,IAAa,QAAO;AAC1C,QAAMC,IAAM,OAAO,oBAAoB;AACvC,SAAO,OAAO,SAASA,CAAG,KAAKA,IAAM,IAAIA,IAAM;AACjD;AAQO,SAASC,GAA+BC,GAAoE;AACjH,MAAI,OAAO,SAAW;AACpB,WAAO,MAAM;AAAA,IAEb;AAGF,MAAIC,IAAS,IACTC,IAAUL,GAAA,GACVM,IAAoC,MACpCC,IAAgD;AAEpD,QAAMC,IAAmB,MAAM;AAC7B,IAAAD,IAAA,GACAA,IAA2B,MAC3BD,IAAa;AAAA,EACf,GAEMG,IAAiB,MAAM;AAC3B,IAAAD,EAAA,GACAF,IAAa,OAAO,WAAW,gBAAgBD,CAAO,OAAO;AAC7D,UAAMK,IAAyB,MAAM;AACnC,MAAAC,EAAc,aAAa;AAAA,IAC7B;AACA,QAAI,OAAOL,EAAW,oBAAqB,YAAY;AACrD,MAAAA,EAAW,iBAAiB,UAAUI,CAAsB,GAC5DH,IAA2B,MAAMD,GAAY,oBAAoB,UAAUI,CAAsB;AACjG;AAAA,IACF;AACA,IAAAJ,EAAW,YAAYI,CAAsB,GAC7CH,IAA2B,MAAMD,GAAY,eAAeI,CAAsB;AAAA,EACpF,GAEMC,IAAgB,CAACC,MAAoD;AACzE,QAAI,CAACR,EAAQ;AACb,UAAMS,IAAUb,GAAA;AAChB,QAAI,KAAK,IAAIa,IAAUR,CAAO,KAAK,KAAM;AACzC,UAAMS,IAAcT;AACpB,IAAAA,IAAUQ,GACVJ,EAAA,GACAN,EAAS,EAAE,aAAAW,GAAa,SAAAD,GAAS,SAAAD,EAAA,CAAS;AAAA,EAC5C,GAEMG,IAAqB,MAAMJ,EAAc,eAAe,GACxDK,IAA6B,MAAML,EAAc,wBAAwB;AAE/E,SAAAF,EAAA,GACA,OAAO,iBAAiB,UAAUM,CAAkB,GACpD,OAAO,gBAAgB,iBAAiB,UAAUC,CAA0B,GAErE,MAAM;AACX,IAAAZ,IAAS,IACTI,EAAA,GACA,OAAO,oBAAoB,UAAUO,CAAkB,GACvD,OAAO,gBAAgB,oBAAoB,UAAUC,CAA0B;AAAA,EACjF;AACF;ACwLO,MAAMC,KAAuB,CAAA,GACvBC,KAA8B,CAAA,GAE9BC,KAAiD;AAAA,EAC5D,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAUF;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AACjB,GAEaG,KAAgD;AAAA,EAC3D,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU,CAAC,IAAI,CAAC;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AACjB,GAEaC,KAAkC,yBAClCC,KAAkC,GAElCC,KAA+C;AAAA,EAC1D,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc;AAChB,GAEaC,KAAwD;AAAA,EACnE,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,UAAU;AAAA,EACV,UAAU;AACZ,GAEaC,KAAmC;AAAA,EAC9C,GAAG;AAAA,EACH,GAAG;AACL,GAEaC,KAAuC,IACvCC,KAAqC,MAGrCC,KAA4B,eAC5BC,KAAsB,GACtBC,KAAuB,GACvBC,KAAe,IACfC,KAAc,GACdC,KAAiB,KACjBC,KAAmC,GACnCC,KAAgC,GAChCC,KAAqC,MACrCC,KAA6B,KAC7BC,KAAuB,MACvBC,KAAwB,MACxBC,KAAuB,IACvBC,KAA2B,WAC3BC,KAA6B,KAC7BC,KAA6B,WAC7BC,KAAoC,WACpCC,KAAkC,KAClCC,KAA4B,CAAC,GAAG,CAAC,GACjCC,KAA4B,GAC5BC,KAAwB,MACxBC,KAAwB,GACxBC,KAA+B,GAC/BC,KAA2B,GAC3BC,KAA2B,GAG3BC,KAAoB;AChV1B,SAASC,GAAWpa,GAAuBqa,GAAoBC,GAAqC;AACzG,SAAO,CAACvK,EAAM/P,EAAM,CAAC,GAAG,GAAGqa,CAAU,GAAGtK,EAAM/P,EAAM,CAAC,GAAG,GAAGsa,CAAW,CAAC;AACzE;AAEO,SAASC,GAAiB/M,GAAuC;AACtE,MAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,EAAG,QAAO;AACtD,QAAMnS,IAAI,OAAOmS,EAAM,CAAC,CAAC,GACnBpS,IAAI,OAAOoS,EAAM,CAAC,CAAC;AACzB,SAAI,CAAC,OAAO,SAASnS,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,IAAU,OAChD,CAACC,GAAGD,CAAC;AACd;AAEO,MAAMof,KAAUD;AAEhB,SAASpH,GAAUhG,GAA4C;AACpE,SAAOQ,GAAaR,CAAM;AAC5B;AAEO,SAASsN,GAAYtN,GAAkC;AAC5D,SAAO,KAAK,IAAIc,GAAkBkF,GAAUhG,CAAM,CAAC,CAAC;AACtD;AAEO,SAASuN,GAAcvN,GAAsC;AAClE,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAErE,MAAImC,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AAEX,aAAW,CAACpU,GAAGD,CAAC,KAAK+R;AACnB,IAAI9R,IAAIiU,MAAMA,IAAOjU,IACjBA,IAAImU,MAAMA,IAAOnU,IACjBD,IAAImU,MAAMA,IAAOnU,IACjBA,IAAIqU,MAAMA,IAAOrU;AAGvB,SAAO,CAACkU,GAAMC,GAAMC,GAAMC,CAAI;AAChC;AAEO,SAASkL,GAAUC,GAA+B5Q,GAA0B6Q,IAAQ,IAAa;AACtG,MAAI7Q,EAAO,WAAW,GAEtB;AAAA,IAAA4Q,EAAI,OAAO5Q,EAAO,CAAC,EAAE,CAAC,GAAGA,EAAO,CAAC,EAAE,CAAC,CAAC;AACrC,aAAStP,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK;AACtC,MAAAkgB,EAAI,OAAO5Q,EAAOtP,CAAC,EAAE,CAAC,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC;AAGvC,IAAImgB,KACFD,EAAI,UAAA;AAAA;AAER;AAEO,SAASE,GAASF,GAA+B5Q,GAA0B+Q,GAAgCF,IAAQ,IAAOG,IAAO,IAAOC,IAAY,2BAAiC;AAC1L,EAAIjR,EAAO,WAAW,MAEtB4Q,EAAI,UAAA,GACJD,GAAUC,GAAK5Q,GAAQ6Q,CAAK,GACxBG,KAAQH,MACVD,EAAI,YAAYK,GAChBL,EAAI,KAAA,IAGNA,EAAI,cAAcG,EAAY,OAC9BH,EAAI,YAAYG,EAAY,OAC5BH,EAAI,WAAWG,EAAY,UAC3BH,EAAI,UAAUG,EAAY,SAC1BH,EAAI,cAAcG,EAAY,aAC9BH,EAAI,aAAaG,EAAY,YAC7BH,EAAI,gBAAgBG,EAAY,eAChCH,EAAI,gBAAgBG,EAAY,eAChCH,EAAI,YAAYG,EAAY,QAAQ,GACpCH,EAAI,OAAA,GACJA,EAAI,YAAY7C,EAAU,GAC1B6C,EAAI,cAAc,oBAClBA,EAAI,aAAa,GACjBA,EAAI,gBAAgB,GACpBA,EAAI,gBAAgB;AACtB;AAEO,SAASM,GAAmBC,GAAkE;AACnG,QAAMC,IAAO,MAAM,QAAQD,GAAO,QAAQ,IAAIA,EAAM,SAAS,OAAO,CAAA3N,MAAS,OAAO,SAASA,CAAK,KAAKA,KAAS,CAAC,IAAIuK,IAC/GxhB,IAAQ,OAAO4kB,GAAO,SAAU,YAAY,OAAO,SAASA,EAAM,KAAK,IAAI,KAAK,IAAI,GAAGA,EAAM,KAAK,IAAIlD,GAA4B,OAClIoD,IAAa,OAAOF,GAAO,cAAe,YAAY,OAAO,SAASA,EAAM,UAAU,IAAI,KAAK,IAAI,GAAGA,EAAM,UAAU,IAAIlD,GAA4B,YACtJqD,IAAgB,OAAOH,GAAO,iBAAkB,YAAY,OAAO,SAASA,EAAM,aAAa,IAAIA,EAAM,gBAAgBlD,GAA4B,eACrJsD,IAAgB,OAAOJ,GAAO,iBAAkB,YAAY,OAAO,SAASA,EAAM,aAAa,IAAIA,EAAM,gBAAgBlD,GAA4B;AAC3J,SAAO;AAAA,IACL,OAAOkD,GAAO,SAASlD,GAA4B;AAAA,IACnD,OAAA1hB;AAAA,IACA,UAAU6kB,EAAK,SAASA,IAAOrD;AAAA,IAC/B,UAAUoD,GAAO,YAAYlD,GAA4B;AAAA,IACzD,SAASkD,GAAO,WAAWlD,GAA4B;AAAA,IACvD,aAAakD,GAAO,eAAelD,GAA4B;AAAA,IAC/D,YAAAoD;AAAA,IACA,eAAAC;AAAA,IACA,eAAAC;AAAA,EAAA;AAEJ;AAEO,SAASC,GAAiBC,GAAyBC,GAAqE;AAC7H,SAAKA,IACER,GAAmB;AAAA,IACxB,OAAOQ,EAAS,SAASD,EAAK;AAAA,IAC9B,OAAOC,EAAS,SAASD,EAAK;AAAA,IAC9B,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,SAASC,EAAS,WAAWD,EAAK;AAAA,IAClC,aAAaC,EAAS,eAAeD,EAAK;AAAA,IAC1C,YAAYC,EAAS,cAAcD,EAAK;AAAA,IACxC,eAAeC,EAAS,iBAAiBD,EAAK;AAAA,IAC9C,eAAeC,EAAS,iBAAiBD,EAAK;AAAA,EAAA,CAC/C,IAXqBA;AAYxB;AAEO,SAASE,GAAexgB,GAAuCwE,GAAgD;AACpH,SAAIxE,KAAM,QAA2BwE,MAAM,QAAQA,MAAM,SAChD,KAEF,OAAOxE,CAAC,MAAM,OAAOwE,CAAC;AAC/B;AAEO,SAAS4N,GAAeC,GAAiC;AAC9D,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK;AAC3D;AAEO,SAASC,GAAiBD,GAA2C;AAC1E,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAKD,GAAeC,EAAM,CAAC,CAAC,KAAKD,GAAeC,EAAM,CAAC,CAAC;AACzG;AAEO,SAASoO,GAAiBpO,GAA2C;AAC1E,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAKA,EAAM,MAAM,CAAAvO,MAASwO,GAAiBxO,CAAK,CAAC;AAClG;AAEA,SAAS4c,GAAoBrO,GAAgBK,GAA+B;AAC1E,MAAI,GAAC,MAAM,QAAQL,CAAK,KAAKA,EAAM,WAAW,IAC9C;AAAA,QAAIoO,GAAiBpO,CAAK,GAAG;AAC3B,MAAAK,EAAI,KAAKL,EAAM,IAAI,CAAC,CAACnS,GAAGD,CAAC,MAAM,CAACC,GAAGD,CAAC,CAAmB,CAAC;AACxD;AAAA,IACF;AACA,eAAW0W,KAAQtE;AACjB,MAAAqO,GAAoB/J,GAAMjE,CAAG;AAAA;AAEjC;AAEO,SAASiO,GAAsBlO,GAAqCiN,GAAoC;AAC7G,QAAMkB,IAAkC,CAAA;AACxC,EAAAF,GAAoBjO,GAAamO,CAAW;AAC5C,QAAMlO,IAA0B,CAAA;AAChC,aAAW/I,KAAQiX,GAAa;AAC9B,QAAIjX,EAAK,SAAS,EAAG;AACrB,UAAMqJ,IAAa0M,IAAQ1H,GAAUrO,CAAI,IAAIA;AAC7C,IAAIqJ,EAAW,WAAW0M,IAAQ,IAAI,MACpChN,EAAI,KAAKM,CAAU;AAAA,EAEvB;AACA,SAAON;AACT;AAEO,SAASmO,GAAwBxO,GAA2BiE,GAA0B;AAC3F,SAAI,OAAOjE,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,KAAKA,KAAS,IAC5DiE,IAEFjE;AACT;AAEO,SAASyO,GAAiBzO,GAA2BiE,GAA0B;AACpF,SAAI,OAAOjE,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUiE,IAC1D1B,EAAMvC,GAAO,GAAG,CAAC;AAC1B;AAEO,SAAS0O,GAAgBtB,GAA+Bvf,GAAWD,GAAW7E,GAAeC,GAAgBwc,GAAsB;AACxI,QAAMW,IAAI,KAAK,IAAI,GAAG,KAAK,IAAIX,GAAQzc,IAAQ,KAAKC,IAAS,GAAG,CAAC;AACjE,EAAAokB,EAAI,UAAA,GACJA,EAAI,OAAOvf,IAAIsY,GAAGvY,CAAC,GACnBwf,EAAI,OAAOvf,IAAI9E,IAAQod,GAAGvY,CAAC,GAC3Bwf,EAAI,iBAAiBvf,IAAI9E,GAAO6E,GAAGC,IAAI9E,GAAO6E,IAAIuY,CAAC,GACnDiH,EAAI,OAAOvf,IAAI9E,GAAO6E,IAAI5E,IAASmd,CAAC,GACpCiH,EAAI,iBAAiBvf,IAAI9E,GAAO6E,IAAI5E,GAAQ6E,IAAI9E,IAAQod,GAAGvY,IAAI5E,CAAM,GACrEokB,EAAI,OAAOvf,IAAIsY,GAAGvY,IAAI5E,CAAM,GAC5BokB,EAAI,iBAAiBvf,GAAGD,IAAI5E,GAAQ6E,GAAGD,IAAI5E,IAASmd,CAAC,GACrDiH,EAAI,OAAOvf,GAAGD,IAAIuY,CAAC,GACnBiH,EAAI,iBAAiBvf,GAAGD,GAAGC,IAAIsY,GAAGvY,CAAC,GACnCwf,EAAI,UAAA;AACN;AAEO,SAASuB,GAAwBvO,GAA8C;AACpF,QAAMG,IAAQH,EAAY,CAAC;AAC3B,SAAO,MAAM,QAAQG,CAAK,KAAK,MAAM,QAAQA,EAAM,CAAC,CAAC;AACvD;AAEO,SAASqO,GACd/I,GACAC,GACA+I,GAIkB;AAClB,MAAI,CAAChJ,KAAS,CAACC,UAAY,CAAA;AAE3B,MAAI+I,GAAY;AACd,UAAMC,IAAcD,EAAW,cAAchJ,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,GACzDkJ,IAAYF,EAAW,cAAc/I,EAAI,CAAC,GAAGA,EAAI,CAAC,CAAC;AAEzD,QAAIgJ,KAAeC,GAAW;AAC5B,YAAMC,IAAkC;AAAA,QACtC,CAACF,EAAY,CAAC,GAAGA,EAAY,CAAC,CAAC;AAAA,QAC/B,CAACC,EAAU,CAAC,GAAGD,EAAY,CAAC,CAAC;AAAA,QAC7B,CAACC,EAAU,CAAC,GAAGA,EAAU,CAAC,CAAC;AAAA,QAC3B,CAACD,EAAY,CAAC,GAAGC,EAAU,CAAC,CAAC;AAAA,MAAA,GAEzBE,IAAiC,CAAA;AACvC,iBAAWC,KAAUF,GAAe;AAClC,cAAMG,IAAQN,EAAW,cAAcK,CAAM;AAC7C,YAAI,CAACC,EAAO,QAAOP,GAAgB/I,GAAOC,CAAG;AAC7C,QAAAmJ,EAAa,KAAKE,CAAK;AAAA,MACzB;AACA,aAAOxJ,GAAUsJ,CAAY;AAAA,IAC/B;AAAA,EACF;AAEA,SAAOtJ,GAAU;AAAA,IACf,CAACE,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IACnB,CAACC,EAAI,CAAC,GAAGD,EAAM,CAAC,CAAC;AAAA,IACjB,CAACC,EAAI,CAAC,GAAGA,EAAI,CAAC,CAAC;AAAA,IACf,CAACD,EAAM,CAAC,GAAGC,EAAI,CAAC,CAAC;AAAA,EAAA,CAClB;AACH;AAEO,SAASsJ,GAAavJ,GAA8BC,GAA4BL,IAAQ4F,IAAgC;AAC7H,MAAI,CAACxF,KAAS,CAACC,UAAY,CAAA;AAE3B,QAAM3c,KAAW0c,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChC1c,KAAWyc,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChCN,IAAS,KAAK,MAAMM,EAAI,CAAC,IAAID,EAAM,CAAC,GAAGC,EAAI,CAAC,IAAID,EAAM,CAAC,CAAC,IAAI;AAClE,MAAIL,IAAS,EAAG,QAAO,CAAA;AAEvB,QAAM7F,IAA2B,CAAA;AACjC,WAASzS,IAAI,GAAGA,KAAKuY,GAAOvY,KAAK,GAAG;AAClC,UAAMwY,IAAKxY,IAAIuY,IAAS,KAAK,KAAK;AAClC,IAAA9F,EAAO,KAAK,CAACxW,IAAU,KAAK,IAAIuc,CAAC,IAAIF,GAAQpc,IAAU,KAAK,IAAIsc,CAAC,IAAIF,CAAM,CAAC;AAAA,EAC9E;AAEA,SAAOG,GAAUhG,CAAM;AACzB;AAEO,SAAS0P,GAA4BjP,GAAmE;AAC7G,QAAMwB,IAAeZ,GAAqBtB,GAAcU,CAAW,CAAC;AACpE,MAAIwB,EAAa,WAAW,EAAG,QAAO,CAAA;AAEtC,QAAMvB,IAAqC,CAAA;AAC3C,aAAWH,KAAW0B,GAAc;AAClC,UAAMC,IAAQ3B,EAAQ,CAAC;AACvB,QAAI,CAAC2B,KAASA,EAAM,SAAS,EAAG;AAChC,UAAMyN,IAAkBzN,EAAM,IAAI,CAAC,CAAChU,GAAGD,CAAC,MAAM,CAACC,GAAGD,CAAC,CAAmB,GAChE2hB,IAA4B,CAAA;AAClC,aAASriB,IAAI,GAAGA,IAAIgT,EAAQ,QAAQhT,KAAK,GAAG;AAC1C,YAAMiV,IAAOjC,EAAQhT,CAAC;AACtB,MAAI,CAACiV,KAAQA,EAAK,SAAS,KAC3BoN,EAAM,KAAKpN,EAAK,IAAI,CAAC,CAACtU,GAAGD,CAAC,MAAM,CAACC,GAAGD,CAAC,CAAmB,CAAC;AAAA,IAC3D;AACA,IAAAyS,EAAI,KAAK;AAAA,MACP,OAAOiP;AAAA,MACP,OAAAC;AAAA,IAAA,CACD;AAAA,EACH;AACA,SAAOlP;AACT;AC7PO,SAASmP,GAAsBxP,GAAuC;AAC3E,MAAI,CAAC,MAAM,QAAQA,CAAK,EAAG,QAAOoM;AAClC,QAAM/L,IAAML,EAAM,OAAO,CAAAsE,MAAQ,OAAO,SAASA,CAAI,KAAKA,KAAQ,CAAC;AACnE,SAAOjE,EAAI,SAAS,IAAIA,IAAM+L;AAChC;AAEO,SAASqD,GAAuBzP,GAAmC;AACxE,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUqM,KAC1D9J,EAAMvC,GAAOsM,IAAuBC,EAAqB;AAClE;AAEO,SAASmD,GAA0B1P,GAAmC;AAC3E,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUwM,KAC1D,KAAK,MAAMjK,EAAMvC,GAAOyM,IAA0BC,EAAwB,CAAC;AACpF;AAEO,SAASiD,GAAoBlnB,GAAyD;AAC3F,QAAM+c,IAASgJ,GAAwB/lB,GAAS,QAAQqjB,EAAoB,GACtE8D,IAAkBpB,GAAwB/lB,GAAS,iBAAiB0jB,EAA+B,GACnG0D,IAAaJ,GAAuBhnB,GAAS,UAAU,GACvDqnB,IAAgBJ,GAA0BjnB,GAAS,aAAa;AACtE,SAAO;AAAA,IACL,QAAA+c;AAAA,IACA,YAAAqK;AAAA,IACA,eAAAC;AAAA,IACA,gBAAgBrnB,GAAS,mBAAmB;AAAA,IAC5C,WAAWA,GAAS,aAAasjB;AAAA,IACjC,aAAa0C,GAAiBhmB,GAAS,aAAaujB,EAA0B;AAAA,IAC9E,aAAavjB,GAAS,eAAewjB;AAAA,IACrC,mBAAmBxjB,GAAS,qBAAqByjB;AAAA,IACjD,iBAAA0D;AAAA,IACA,gBAAgBJ,GAAsB/mB,GAAS,cAAc;AAAA,EAAA;AAEjE;AAEO,SAASsnB,GAAuB3C,GAA+B4C,GAAsBC,GAAkD;AAC5I,MAAI,CAACD,EAAQ,aAAaA,EAAQ,aAAa,WAAW,EAAG;AAC7D,QAAME,IAAeF,EAAQ;AAC7B,MAAIE,EAAa,WAAW,EAAG;AAC/B,QAAMC,IAAWF,EAAqB;AACtC,MAAI,GAAC,OAAO,SAASE,CAAQ,KAAKA,KAAY,IAS9C;AAAA,QAPA/C,EAAI,KAAA,GACJA,EAAI,cAAc6C,EAAqB,aACvC7C,EAAI,YAAY6C,EAAqB,WACrC7C,EAAI,cAAc6C,EAAqB,WACvC7C,EAAI,UAAU,SACdA,EAAI,WAAW,SACfA,EAAI,YAAY+C,IAAW,GACvBD,EAAa,WAAW;AAC1B,MAAA9C,EAAI,UAAA,GACJA,EAAI,IAAI8C,EAAa,CAAC,EAAE,CAAC,GAAGA,EAAa,CAAC,EAAE,CAAC,GAAGC,GAAU,GAAG,KAAK,KAAK,CAAC,GACxE/C,EAAI,KAAA;AAAA,SACC;AACL,MAAAA,EAAI,UAAA,GACJA,EAAI,OAAO8C,EAAa,CAAC,EAAE,CAAC,GAAGA,EAAa,CAAC,EAAE,CAAC,CAAC;AACjD,eAAShjB,IAAI,GAAGA,IAAIgjB,EAAa,QAAQhjB,KAAK;AAC5C,QAAAkgB,EAAI,OAAO8C,EAAahjB,CAAC,EAAE,CAAC,GAAGgjB,EAAahjB,CAAC,EAAE,CAAC,CAAC;AAEnD,MAAAkgB,EAAI,OAAA;AAAA,IACN;AACA,IAAAA,EAAI,QAAA;AAAA;AACN;AAEO,SAASgD,GAAgBhD,GAA+B4C,GAAsBK,GAAiCJ,GAAkD;AACtK,QAAMK,IAASN,EAAQ;AACvB,MAAI,CAACM,EAAQ;AACb,QAAMC,IAASP,EAAQ,gBAAgBhD,GAAQqD,GAAW,cAAcC,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,KAAK,CAAA,CAAE;AACnG,MAAI,CAACC,EAAQ;AACb,QAAMJ,IAAWF,EAAqB;AACtC,EAAI,CAAC,OAAO,SAASE,CAAQ,KAAKA,KAAY,MAE9C/C,EAAI,KAAA,GACJA,EAAI,UAAA,GACJA,EAAI,IAAImD,EAAO,CAAC,GAAGA,EAAO,CAAC,GAAGJ,GAAU,GAAG,KAAK,KAAK,CAAC,GACtD/C,EAAI,cAAc4C,EAAQ,YAAYC,EAAqB,oBAAoBA,EAAqB,aACpG7C,EAAI,YAAY6C,EAAqB,iBACrC7C,EAAI,YAAY6C,EAAqB,cAAc,GACnD7C,EAAI,OAAA,GACJA,EAAI,YAAY7C,EAAU,GAC1B6C,EAAI,QAAA;AACN;AC5FA,MAAMoD,KAA4B,MAC5BC,KAA4B,MAC5BC,KAAyB;AAE/B,IAAIC,KAA6D;AACjE,MAAMC,yBAA0B,IAAA;AAEhC,SAASC,KAA0D;AACjE,MAAIF,GAA2B,QAAOA;AACtC,MAAI,OAAO,WAAa,IAAa,QAAO;AAE5C,QAAMvD,IADS,SAAS,cAAc,QAAQ,EAC3B,WAAW,IAAI;AAClC,SAAKA,KACLuD,KAA4BvD,GACrBuD,MAFU;AAGnB;AAEO,SAASG,GAAsBC,GAAeC,GAA2F;AAC9I,QAAMC,IAAM,GAAGD,EAAW,UAAU,IAAIA,EAAW,QAAQ,IAAIA,EAAW,UAAU,IAAID,CAAK,IACvFG,IAASN,GAAoB,IAAIK,CAAG;AAC1C,MAAIC,MAAW,OAAW,QAAOA;AAEjC,QAAMjN,IAAW8M,EAAM,SAASC,EAAW,WAAWR,IAChDpD,IAAMyD,GAAA;AACZ,MAAI9nB,IAAQkb;AACZ,MAAImJ,GAAK;AACP,IAAAA,EAAI,OAAO,GAAG4D,EAAW,UAAU,IAAIA,EAAW,QAAQ,MAAMA,EAAW,UAAU;AACrF,UAAMG,IAAW/D,EAAI,YAAY2D,CAAK,EAAE;AACxC,IAAI,OAAO,SAASI,CAAQ,KAAKA,KAAY,MAC3CpoB,IAAQooB;AAAA,EAEZ;AAEA,SAAIP,GAAoB,OAAOH,MAC7BG,GAAoB,MAAA,GAEtBA,GAAoB,IAAIK,GAAKloB,CAAK,GAC3BA;AACT;AAEO,SAASqoB,GAAazR,GAA0B0R,IAAoC,cAAqC;AAC9H,MAAI,CAAC1R,EAAO,OAAQ,QAAO;AAE3B,MAAIoC,IAAO;AACX,aAAWtQ,KAASkO;AAClB,IAAIlO,EAAM,CAAC,IAAIsQ,MAAMA,IAAOtQ,EAAM,CAAC;AAErC,MAAI,CAAC,OAAO,SAASsQ,CAAI,EAAG,QAAO;AAEnC,MAAID,IAAO,OACPE,IAAO;AACX,aAAWvQ,KAASkO;AAClB,IAAI,KAAK,IAAIlO,EAAM,CAAC,IAAIsQ,CAAI,IAAI2O,OAC5Bjf,EAAM,CAAC,IAAIqQ,MAAMA,IAAOrQ,EAAM,CAAC,IAC/BA,EAAM,CAAC,IAAIuQ,MAAMA,IAAOvQ,EAAM,CAAC;AAGrC,SAAI,CAAC,OAAO,SAASqQ,CAAI,KAAK,CAAC,OAAO,SAASE,CAAI,IAAU,OACzDqP,MAAe,eACV,EAAEvP,IAAOE,KAAQ,KAAKD,CAAI,IAE5B,CAACD,GAAMC,CAAI;AACpB;AAcO,SAASuP,GACdjP,GACAkP,GACAF,IAAoC,cACb;AACvB,MAAIhK,IAA8B;AAClC,aAAWnH,KAAWmC,GAAU;AAC9B,UAAMmP,IAAiBD,EAAQrR,EAAQ,KAAK;AAC5C,QAAIsR,EAAe,WAAW,EAAG;AACjC,UAAMC,IAASL,GAAaI,GAAgBH,CAAU;AACtD,IAAKI,MACD,CAACpK,KAAQoK,EAAO,CAAC,IAAIpK,EAAK,CAAC,KAAMoK,EAAO,CAAC,MAAMpK,EAAK,CAAC,KAAKoK,EAAO,CAAC,IAAIpK,EAAK,CAAC,OAC9EA,IAAOoK;AAAA,EAEX;AACA,SAAOpK;AACT;AAEO,SAASqK,GAAwB/D,GAAgE;AACtG,QAAMgE,IAAK,OAAOhE,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAI9C,GAA2B,UACvI+G,IAAK,OAAOjE,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAI9C,GAA2B,UACvIgH,IAAK,OAAOlE,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAI9C,GAA2B,UACvIiH,IAAK,OAAOnE,GAAO,eAAgB,YAAY,OAAO,SAASA,EAAM,WAAW,IAAI,KAAK,IAAI,GAAGA,EAAM,WAAW,IAAI9C,GAA2B,aAChJkH,IAAK,OAAOpE,GAAO,WAAY,YAAY,OAAO,SAASA,EAAM,OAAO,IAAIA,EAAM,UAAU9C,GAA2B,SACvHmH,IAAK,OAAOrE,GAAO,gBAAiB,YAAY,OAAO,SAASA,EAAM,YAAY,IAAI,KAAK,IAAI,GAAGA,EAAM,YAAY,IAAI9C,GAA2B;AACzJ,SAAO;AAAA,IACL,YAAY8C,GAAO,cAAc9C,GAA2B;AAAA,IAC5D,UAAUgH;AAAA,IACV,YAAYlE,GAAO,cAAc9C,GAA2B;AAAA,IAC5D,WAAW8C,GAAO,aAAa9C,GAA2B;AAAA,IAC1D,iBAAiB8C,GAAO,mBAAmB9C,GAA2B;AAAA,IACtE,aAAa8C,GAAO,eAAe9C,GAA2B;AAAA,IAC9D,aAAaiH;AAAA,IACb,UAAUH;AAAA,IACV,UAAUC;AAAA,IACV,SAASG;AAAA,IACT,cAAcC;AAAA,EAAA;AAElB;AAEO,SAASC,GAAsBhE,GAAwBC,GAA0E;AACtI,SAAKA,IACEwD,GAAwB;AAAA,IAC7B,YAAYxD,EAAS,cAAcD,EAAK;AAAA,IACxC,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,YAAYC,EAAS,cAAcD,EAAK;AAAA,IACxC,WAAWC,EAAS,aAAaD,EAAK;AAAA,IACtC,iBAAiBC,EAAS,mBAAmBD,EAAK;AAAA,IAClD,aAAaC,EAAS,eAAeD,EAAK;AAAA,IAC1C,aAAaC,EAAS,eAAeD,EAAK;AAAA,IAC1C,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,SAASC,EAAS,WAAWD,EAAK;AAAA,IAClC,cAAcC,EAAS,gBAAgBD,EAAK;AAAA,EAAA,CAC7C,IAbqBA;AAcxB;AAEO,SAASiE,GACdC,GACAjpB,GACAkpB,GACAC,GACQ;AAER,MADI,CAACF,KACD,CAACC,EAAW,QAAO;AAEvB,QAAME,IAAU,OAAOF,EAAU,OAAO,GAClCG,IAAU,OAAOH,EAAU,OAAO;AAIxC,MAHI,CAAC,OAAO,SAASE,CAAO,KAAK,CAAC,OAAO,SAASC,CAAO,KAErDA,IAAUD,KAAWrH,MACrB,CAAC,OAAO,SAAS/hB,CAAI,EAAG,QAAO;AAEnC,MAAIspB,IAAMD;AACV,EAAIF,KAAe,QAAQ,OAAO,SAASA,CAAW,MACpDG,IAAMjQ,EAAM8P,GAAaC,GAASC,CAAO;AAE3C,QAAME,IAAM,KAAK,IAAIxH,IAAoC,KAAK,IAAIuH,CAAG,IAAI,IAAI;AAC7E,SAAOtpB,KAAQspB,IAAMC,IAAMzH,KAAuC;AACpE;AAEA,SAAS0H,GAA4B/E,GAAwE;AAC3G,QAAMgF,IAAW,OAAOhF,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAI7C,GAAgC,UAClJ8H,IAAe,OAAOjF,GAAO,gBAAiB,YAAY,OAAO,SAASA,EAAM,YAAY,IAAI,KAAK,IAAI,GAAGA,EAAM,YAAY,IAAI7C,GAAgC,cAClK+H,IAAW,OAAOlF,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAI7C,GAAgC,UAClJgI,IAAW,OAAOnF,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAI7C,GAAgC;AACxJ,SAAO;AAAA,IACL,YAAY6C,GAAO,cAAc7C,GAAgC;AAAA,IACjE,UAAA6H;AAAA,IACA,YAAYhF,GAAO,cAAc7C,GAAgC;AAAA,IACjE,WAAW6C,GAAO,aAAa7C,GAAgC;AAAA,IAC/D,iBAAiB6C,GAAO,mBAAmB7C,GAAgC;AAAA,IAC3E,cAAA8H;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,EAAA;AAEJ;AAEA,SAASC,GAA2B/S,GAAyE;AAC3G,QAAMnS,IAAI,OAAOmS,GAAO,KAAM,YAAY,OAAO,SAASA,EAAM,CAAC,IAAIA,EAAM,IAAI+K,GAAiC,GAC1Gnd,IAAI,OAAOoS,GAAO,KAAM,YAAY,OAAO,SAASA,EAAM,CAAC,IAAIA,EAAM,IAAI+K,GAAiC;AAChH,SAAO,EAAE,GAAAld,GAAG,GAAAD,EAAA;AACd;AAEO,SAASolB,GAAgCC,GAAyB;AACvE,SAAK,OAAO,SAASA,CAAO,IACrB,GAAG,KAAK,IAAI,GAAGA,CAAO,EAAE,QAAQ,CAAC,CAAC,SADH;AAExC;AAEO,SAASC,GAA8BzqB,GAA6E;AACzH,QAAM0qB,IAAS,OAAO1qB,GAAS,UAAW,aAAaA,EAAQ,SAASuqB,IAClEI,IAAeL,GAA2BtqB,GAAS,YAAY;AACrE,SAAO;AAAA,IACL,SAASA,GAAS,YAAY;AAAA,IAC9B,QAAA0qB;AAAA,IACA,OAAOT,GAA4BjqB,GAAS,KAAK;AAAA,IACjD,eAAe2qB,EAAa;AAAA,IAC5B,eAAeA,EAAa;AAAA,EAAA;AAEhC;AAEO,SAASC,GACdjG,GACAkG,GACA7B,GACA8B,GACAC,GACAxC,GACAyC,IAAkB,IACZ;AACN,QAAM1C,IAAQuC,EAAK,KAAA;AACnB,MAAI,CAACvC,EAAO;AAEZ,EAAA3D,EAAI,KAAA,GACJA,EAAI,OAAO,GAAG4D,EAAW,UAAU,IAAIA,EAAW,QAAQ,MAAMA,EAAW,UAAU,IACrF5D,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,QAAMsG,IADY5C,GAAsBC,GAAOC,CAAU,IAC5BA,EAAW,WAAW,GAC7C2C,IAAY3C,EAAW,WAAWA,EAAW,WAAW,GAExD4C,IAAOnC,EAAO,CAAC,GACfoC,IAAOpC,EAAO,CAAC,IAAIT,EAAW,SAC9BnjB,IAAI4lB,IAAkBlR,EAAMqR,GAAMF,IAAW,MAAM,GAAGH,IAAcG,IAAW,MAAM,CAAC,IAAIE,GAC1FhmB,IAAI6lB,IAAkBlR,EAAMsR,GAAMF,IAAY,MAAM,GAAGH,IAAeG,IAAY,MAAM,CAAC,IAAIE,GAC7FC,IAAOjmB,IAAI6lB,IAAW,KACtBK,IAAMnmB,IAAI+lB,IAAY;AAE5B,EAAAvG,EAAI,YAAY4D,EAAW,iBAC3B5D,EAAI,cAAc4D,EAAW,aAC7B5D,EAAI,YAAY4D,EAAW,aAC3BtC,GAAgBtB,GAAK0G,GAAMC,GAAKL,GAAUC,GAAW3C,EAAW,YAAY,GAC5E5D,EAAI,KAAA,GACA4D,EAAW,cAAc,KAC3B5D,EAAI,OAAA,GAGNA,EAAI,YAAY4D,EAAW,WAC3B5D,EAAI,SAAS2D,GAAOljB,GAAGD,IAAI,GAAG,GAC9Bwf,EAAI,QAAA;AACN;AAEO,SAAS4G,GACd5G,GACAkG,GACAW,GACAV,GACAC,GACA7F,GACAjhB,GACAC,GACM;AACN,QAAMokB,IAAQuC,EAAK,KAAA;AACnB,MAAI,CAACvC,EAAO;AAEZ,EAAA3D,EAAI,KAAA,GACJA,EAAI,OAAO,GAAGO,EAAM,UAAU,IAAIA,EAAM,QAAQ,MAAMA,EAAM,UAAU,IACtEP,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,QAAMsG,IADY5C,GAAsBC,GAAOpD,CAAK,IACvBA,EAAM,WAAW,GACxCgG,IAAYhG,EAAM,WAAWA,EAAM,WAAW,GAE9C9f,IAAI0U,EAAM0R,EAAa,CAAC,IAAIvnB,GAASgnB,IAAW,MAAM,GAAGH,IAAcG,IAAW,MAAM,CAAC,GACzF9lB,IAAI2U,EAAM0R,EAAa,CAAC,IAAItnB,GAASgnB,IAAY,MAAM,GAAGH,IAAeG,IAAY,MAAM,CAAC,GAC5FG,IAAOjmB,IAAI6lB,IAAW,KACtBK,IAAMnmB,IAAI+lB,IAAY;AAE5B,EAAAvG,EAAI,YAAYO,EAAM,iBACtBe,GAAgBtB,GAAK0G,GAAMC,GAAKL,GAAUC,GAAWhG,EAAM,YAAY,GACvEP,EAAI,KAAA,GAEJA,EAAI,YAAYO,EAAM,WACtBP,EAAI,SAAS2D,GAAOljB,GAAGD,IAAI,GAAG,GAC9Bwf,EAAI,QAAA;AACN;ACxRO,SAAS8G,GAAqB9G,GAA+B+G,GAA6BC,GAA+B3G,GAAyB;AACvJ,MAAI,EAAA0G,EAAU,SAAS,KAAKC,EAAU,WAAW,IACjD;AAAA,IAAAhH,EAAI,KAAA,GACJA,EAAI,UAAA,GACJD,GAAUC,GAAK+G,GAAW,EAAI;AAC9B,eAAW7c,KAAQ8c;AACjB,MAAI9c,EAAK,SAAS,KAClB6V,GAAUC,GAAK9V,GAAM,EAAI;AAE3B,IAAA8V,EAAI,YAAYK,GAChBL,EAAI,KAAK,SAAS,GAClBA,EAAI,QAAA;AAAA;AACN;AAWO,SAASiH,GAAkBC,GAAuC;AACvE,QAAM,EAAE,KAAAlH,GAAK,eAAAmH,GAAe,gBAAAC,GAAgB,qBAAAC,GAAqB,iBAAAC,GAAiB,qBAAAC,MAAwBL,GAEpGM,IAAe,EAAS,WAA0D;AAExF,WAAS1nB,IAAI,GAAGA,IAAIqnB,EAAc,QAAQrnB,KAAK,GAAG;AAChD,UAAM2nB,IAAQN,EAAcrnB,CAAC;AAC7B,QAAI,CAAC2nB,GAAO,aAAa,UAAUA,EAAM,YAAY,GAAO;AAE5D,UAAMjU,IAASiU,EAAM,UAAUlG,GAAwBkG,EAAM,WAAW,GAClEC,IAAcxG,GAAsBuG,EAAM,aAAajU,CAAM;AAEnE,QAAIiU,EAAM,cAAc,WAAW;AACjC,YAAMT,IAAgC,CAAA,GAChCW,IAAczG,GAAsBuG,EAAM,aAAa,EAAI;AACjE,iBAAWvd,KAAQyd,GAAa;AAC9B,cAAMxE,IAASkE,EAAoBnd,CAAI;AACvC,QAAIiZ,EAAO,UAAU,KACnB6D,EAAU,KAAK7D,CAAM;AAAA,MAEzB;AACA,MAAIqE,KAAgBD,KAClBA,EAAoB;AAAA,QAClB,IAAIE,EAAM,MAAM3nB;AAAA,QAChB,iBAAiBsnB,EAAe;AAAA,QAChC,iBAAiBO,EAAY;AAAA,QAC7B,eAAeX,EAAU;AAAA,QACzB,WAAWS,EAAM,aAAa;AAAA,MAAA,CAC/B,GAEHX,GAAqB9G,GAAKoH,GAAgBJ,GAAWS,EAAM,aAAa,SAAS;AAAA,IACnF;AAEA,QAAIC,EAAY,WAAW,EAAG;AAC9B,UAAMvH,IAAcS,GAAiB0G,GAAiBG,EAAM,UAAUA,EAAM,WAAW;AACvF,eAAWvd,KAAQwd,GAAa;AAC9B,YAAMvE,IAASkE,EAAoBnd,CAAI;AACvC,MAAIiZ,EAAO,SAAS,KACpBjD,GAASF,GAAKmD,GAAQhD,GAAa3M,GAAQiU,EAAM,QAAQ,EAAK;AAAA,IAChE;AAAA,EACF;AACF;AC7DO,SAASG,GAAYC,GAAuC;AACjE,SACE,OAAOA,KAAS,aACdA,MAAS,qBAAqBA,MAAS,kBAAkBA,MAAS,4BAA4BA,MAAS,0BAA0BA,MAAS,uBAAuBA,MAAS;AAGhL;AAcO,SAASC,GAAoBzsB,GAA2D;AAC7F,SAAO;AAAA,IACL,kBAAkB+lB,GAAwB/lB,GAAS,kBAAkB+iB,EAAgC;AAAA,IACrG,eAAegD,GAAwB/lB,GAAS,eAAegjB,EAA6B;AAAA,IAC5F,oBAAoB+C,GAAwB/lB,GAAS,oBAAoBijB,EAAkC;AAAA,EAAA;AAE/G;AAEA,MAAMH,KAAiB;AAEhB,SAAS4J,GAASlC,GAAyB;AAChD,SAAOA,IAAU1H,KAAiBA;AACpC;AAEO,SAAS6J,GACd7P,GACA8P,GACAxG,GAIkB;AAClB,MAAI,CAACtJ,KAAU,CAAC,OAAO,SAAS8P,CAAU,KAAKA,KAAc,EAAG,QAAO,CAAA;AAEvE,MAAIxG,GAAY;AACd,UAAMyG,IAAezG,EAAW,cAActJ,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,GAC5DgQ,IAAa1G,EAAW,cAActJ,EAAO,CAAC,IAAI8P,GAAY9P,EAAO,CAAC,CAAC;AAC7E,QAAI+P,KAAgBC,GAAY;AAC9B,YAAMC,IAAW,KAAK,MAAMD,EAAW,CAAC,IAAID,EAAa,CAAC,GAAGC,EAAW,CAAC,IAAID,EAAa,CAAC,CAAC,GACtFtG,IAAkC;AAAA,QACtC,CAACsG,EAAa,CAAC,IAAIE,GAAUF,EAAa,CAAC,IAAIE,CAAQ;AAAA,QACvD,CAACF,EAAa,CAAC,IAAIE,GAAUF,EAAa,CAAC,IAAIE,CAAQ;AAAA,QACvD,CAACF,EAAa,CAAC,IAAIE,GAAUF,EAAa,CAAC,IAAIE,CAAQ;AAAA,QACvD,CAACF,EAAa,CAAC,IAAIE,GAAUF,EAAa,CAAC,IAAIE,CAAQ;AAAA,MAAA,GAEnDvG,IAAiC,CAAA;AACvC,iBAAWC,KAAUF,GAAe;AAClC,cAAMG,IAAQN,EAAW,cAAcK,CAAM;AAC7C,YAAI,CAACC,EAAO,OAAM,IAAI,MAAM,4BAA4B;AACxD,QAAAF,EAAa,KAAKE,CAAK;AAAA,MACzB;AACA,aAAOxJ,GAAUsJ,CAAY;AAAA,IAC/B;AAAA,EACF;AAEA,SAAOtJ,GAAU;AAAA,IACf,CAACJ,EAAO,CAAC,IAAI8P,GAAY9P,EAAO,CAAC,IAAI8P,CAAU;AAAA,IAC/C,CAAC9P,EAAO,CAAC,IAAI8P,GAAY9P,EAAO,CAAC,IAAI8P,CAAU;AAAA,IAC/C,CAAC9P,EAAO,CAAC,IAAI8P,GAAY9P,EAAO,CAAC,IAAI8P,CAAU;AAAA,IAC/C,CAAC9P,EAAO,CAAC,IAAI8P,GAAY9P,EAAO,CAAC,IAAI8P,CAAU;AAAA,EAAA,CAChD;AACH;AAEO,SAASI,GAAuBlQ,GAA+BC,GAAgBC,IAAQ4F,IAAgC;AAC5H,MAAI,CAAC9F,KAAU,CAAC,OAAO,SAASC,CAAM,KAAKA,KAAU,EAAG,QAAO,CAAA;AAE/D,QAAM7F,IAA2B,CAAA;AACjC,WAAS,IAAI,GAAG,KAAK8F,GAAO,KAAK,GAAG;AAClC,UAAMC,IAAK,IAAID,IAAS,KAAK,KAAK;AAClC,IAAA9F,EAAO,KAAK,CAAC4F,EAAO,CAAC,IAAI,KAAK,IAAIG,CAAC,IAAIF,GAAQD,EAAO,CAAC,IAAI,KAAK,IAAIG,CAAC,IAAIF,CAAM,CAAC;AAAA,EAClF;AAEA,SAAOG,GAAUhG,CAAM;AACzB;AAiBO,SAAS+V,GAAiBpB,GAAkD;AACjF,QAAM,EAAE,WAAAqB,GAAW,QAAApQ,GAAQ,sBAAAqQ,GAAsB,YAAA/I,GAAY,aAAAC,GAAa,sBAAA+I,GAAsB,wBAAAC,MAA2BxB;AAE3H,MAAI,CAAC/O,EAAQ,QAAO,CAAA;AAEpB,MAAIoQ,MAAc,0BAA0B;AAC1C,UAAMN,IAAaO,EAAqB,qBAAqB;AAC7D,WAAOR,GAAuB7P,GAAQ8P,GAAYS,EAAA,CAAwB,EAAE,IAAI,CAAArkB,MAASmb,GAAWnb,GAAOob,GAAYC,CAAW,CAAC;AAAA,EACrI;AAEA,MAAImG,IAAU;AAMd,MALI0C,MAAc,qBAAqBA,MAAc,yBACnD1C,IAAU0C,MAAc,yBAAyBnK,KAAmCoK,EAAqB,oBAChGD,MAAc,kBAAkBA,MAAc,uBAAuBA,MAAc,+BAC5F1C,IAAU0C,MAAc,4BAA4BhK,KAA6BgK,MAAc,sBAAsBlK,KAAgCmK,EAAqB,gBAExK,CAAC,OAAO,SAAS3C,CAAO,KAAKA,KAAW,UAAU,CAAA;AAEtD,QAAM8C,IAAUZ,GAASlC,CAAO;AAChC,MAAItT,IAA2B,CAAA;AAC/B,MAAIgW,MAAc,qBAAqBA,MAAc,wBAAwB;AAC3E,UAAMN,IAAaQ,EAAqB,KAAK,KAAKE,CAAO,IAAI,GAAG;AAChE,IAAApW,IAASyV,GAAuB7P,GAAQ8P,GAAYS,EAAA,CAAwB;AAAA,EAC9E,WAAWH,MAAc,kBAAkBA,MAAc,uBAAuBA,MAAc,2BAA2B;AACvH,UAAMnQ,IAASqQ,EAAqB,KAAK,KAAKE,IAAU,KAAK,EAAE,CAAC;AAChE,IAAApW,IAAS8V,GAAuBlQ,GAAQC,CAAM;AAAA,EAChD;AAEA,SAAK7F,EAAO,SACLA,EAAO,IAAI,CAAAlO,MAASmb,GAAWnb,GAAOob,GAAYC,CAAW,CAAC,IAD1C,CAAA;AAE7B;ACpDA,SAASkJ,GAAoCzI,GAA6G;AACxJ,SAAO;AAAA,IACL,OAAO5C;AAAA,IACP,OAAOC;AAAA,IACP,UAAUL;AAAA,IACV,UAAUgD,EAAY;AAAA,IACtB,SAASA,EAAY;AAAA,IACrB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,eAAe;AAAA,EAAA;AAEnB;AAEA,SAAS0I,GAA4BjW,GAAmC;AACtE,MAAI,OAAOA,KAAU,SAAU,QAAOkL;AACtC,QAAMjiB,IAAO+W,EAAM,KAAA;AACnB,SAAO/W,EAAK,SAAS,IAAIA,IAAOiiB;AAClC;AAEA,SAASgL,GAAevW,GAAgE;AACtF,SAAO,MAAM,QAAQA,CAAM,KAAKA,EAAO,UAAU,KAAKsN,GAAYtN,CAAM,IAAI2L;AAC9E;AAEO,SAAS6K,GAAU;AAAA,EACxB,MAAAlB;AAAA,EACA,YAAApI;AAAA,EACA,aAAAC;AAAA,EACA,UAAAnK;AAAA,EACA,WAAAC;AAAA,EACA,cAAAwT;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,SAAAtE;AAAA,EACA,iBAAAuE;AAAA,EACA,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,0BAAAC;AAAA,EACA,yBAAyBC;AAAA,EACzB,eAAA7C;AAAA,EACA,iBAAA8C,IAAkB;AAAA,EAClB,gBAAAC,IAAiB;AAAA,EACjB,kBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,8BAAAC,IAA+B;AAAA,EAC/B,mBAAAC,IAAoB;AAAA,EACpB,4BAAAC,IAA6B;AAAA,EAC7B,6BAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAnK;AACF,GAAuC;AACrC,QAAMoK,KAAYC,EAAiC,IAAI,GACjDC,KAAiBD,EAAO,EAAK,GAC7BE,KAA0BF,EAA4B,oBAAI,KAAK,GAC/DG,IAAcH,EAAiB/C,CAAI,GACnCmD,IAAaJ,EAAoB;AAAA,IACrC,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,QAAQ,CAAA;AAAA,IACR,cAAc,CAAA;AAAA,IACd,aAAa;AAAA,EAAA,CACd,GAEKtO,IAASyI,KAAW8C,MAAS,UAC7BoD,KAAyBC,GAAsB,MAC/C3B,KAAoBA,EAAiB,SAAS,IACzCA,IAEL,CAACE,KAAqBA,EAAkB,WAAW,IAC9CrM,KAEFqM,EAAkB,IAAI,CAACzW,GAAa9G,OAAW;AAAA,IACpD,IAAIA;AAAA,IACJ,aAAA8G;AAAA,EAAA,EACA,GACD,CAACuW,GAAkBE,CAAiB,CAAC,GAClC0B,KAAqBD,GAAsB,MAAM1B,KAAgBpM,IAAe,CAACoM,CAAY,CAAC,GAC9F4B,IAA2BF,GAAkC,MAAM;AACvE,UAAMjY,IAAgC,CAAA;AACtC,aAASnT,IAAI,GAAGA,IAAImrB,GAAuB,QAAQnrB,KAAK,GAAG;AACzD,YAAMurB,IAASJ,GAAuBnrB,CAAC,GACjCmV,IAAWgN,GAA4BoJ,EAAO,WAAW;AAC/D,MAAIpW,EAAS,WAAW,KACxBhC,EAAI,KAAK;AAAA,QACP,QAAAoY;AAAA,QACA,aAAavrB;AAAA,QACb,WAAWurB,EAAO,MAAMvrB;AAAA,QACxB,UAAAmV;AAAA,MAAA,CACD;AAAA,IACH;AACA,WAAOhC;AAAA,EACT,GAAG,CAACgY,EAAsB,CAAC,GACrBK,KAAuBJ,GAAkC,MAAM;AACnE,UAAMjY,IAAgC,CAAA;AACtC,aAASnT,IAAI,GAAGA,IAAIqrB,GAAmB,QAAQrrB,KAAK,GAAG;AACrD,YAAMurB,IAASF,GAAmBrrB,CAAC,GAC7BmV,IAAWgN,GAA4BoJ,EAAO,WAAW;AAC/D,MAAIpW,EAAS,WAAW,KACxBhC,EAAI,KAAK;AAAA,QACP,QAAAoY;AAAA,QACA,aAAavrB;AAAA,QACb,WAAWurB,EAAO,MAAMvrB;AAAA,QACxB,UAAAmV;AAAA,MAAA,CACD;AAAA,IACH;AACA,WAAOhC;AAAA,EACT,GAAG,CAACkY,EAAkB,CAAC,GAEjBI,KAAsBL,GAAQ,MAAM5K,GAAmBqJ,CAAiB,GAAG,CAACA,CAAiB,CAAC,GAC9F6B,KAA2BN,GAAQ,MAAMtK,GAAiB2K,IAAqB3B,CAAsB,GAAG,CAAC2B,IAAqB3B,CAAsB,CAAC,GACrJ6B,KAA4BP,GAAQ,MAAMtK,GAAiB2K,IAAqB1B,CAAuB,GAAG,CAAC0B,IAAqB1B,CAAuB,CAAC,GACxJ6B,KAA2BR,GAAQ,MAAMtK,GAAiBtD,IAA4BwM,CAAgB,GAAG,CAACA,CAAgB,CAAC,GAC3H6B,KAA+BT,GAAQ,MAAMrC,GAA4Ba,CAAa,GAAG,CAACA,CAAa,CAAC,GAExGkC,KAAqBV,GAAQ,MAAM5G,GAAwB6F,CAAgB,GAAG,CAACA,CAAgB,CAAC,GAChG0B,KAAiCX,GAAQ,MAAMpF,GAA8BsE,CAAe,GAAG,CAACA,CAAe,CAAC,GAChH5B,KAAuB0C,GAAQ,MAAMpD,GAAoBkB,CAAY,GAAG,CAACA,CAAY,CAAC,GACtFnG,KAAuBqI,GAAQ,MAAM3I,GAAoB0G,CAAY,GAAG,CAACA,CAAY,CAAC,GAEtF6C,KAAcZ;AAAA,IAClB,OAAO;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,aAAa;AAAA,MACb,eAAe5O,IAAS,SAAS;AAAA,MACjC,QAAQA,IAAUuL,MAAS,UAAU,SAAS,cAAe;AAAA,MAC7D,GAAGtH;AAAA,IAAA;AAAA,IAEL,CAACjE,GAAQuL,GAAMtH,EAAK;AAAA,EAAA,GAGhBwL,KAAeC,EAAY,MAAM;AACrC,UAAM5wB,IAASuvB,GAAU;AACzB,QAAI,CAACvvB,EAAQ;AAEb,UAAMwD,IAAOxD,EAAO,sBAAA,GACd2D,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9ClC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM+B,EAAK,QAAQG,CAAG,CAAC,GAC5CjC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM8B,EAAK,SAASG,CAAG,CAAC;AAEnD,KAAI3D,EAAO,UAAUyB,KAAKzB,EAAO,WAAW0B,OAC1C1B,EAAO,QAAQyB,GACfzB,EAAO,SAAS0B;AAAA,EAEpB,GAAG,CAACwf,GAAQuL,CAAI,CAAC,GAEXR,KAAsB2E;AAAA,IAC1B,CAAC5c,MAAyG;AACxG,YAAM6T,IAAYiG,EAAa;AAC/B,UAAI,CAACjG,KAAa7T,EAAO,WAAW,UAAU,CAAA;AAE9C,YAAM6D,IAAM,IAAI,MAAmD7D,EAAO,MAAM;AAChF,eAAStP,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK,GAAG;AACzC,cAAMsF,IAAQwa,GAAQqD,EAAU,cAAc7T,EAAOtP,CAAC,EAAE,CAAC,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,YAAI,CAACsF,EAAO,QAAO,CAAA;AACnB,QAAA6N,EAAInT,CAAC,IAAIsF;AAAA,MACX;AACA,aAAO6N;AAAA,IACT;AAAA,IACA,CAACiW,CAAY;AAAA,EAAA,GAGT+C,IAAqBD;AAAA,IACzB,CAAC7I,MAA4G;AAC3G,YAAMF,IAAYiG,EAAa,SACzB9tB,IAASuvB,GAAU;AACzB,UAAI,CAAC1H,KAAa,CAAC7nB,EAAQ,QAAO;AAClC,YAAMwD,IAAOxD,EAAO,sBAAA,GACd+gB,IAAMyD,GAAQqD,EAAU,cAAcrkB,EAAK,OAAOukB,EAAO,CAAC,GAAGvkB,EAAK,MAAMukB,EAAO,CAAC,CAAC,CAAC;AACxF,aAAKhH,IACEqD,GAAWrD,GAAKsD,GAAYC,CAAW,IAD7B;AAAA,IAEnB;AAAA,IACA,CAACwJ,GAAczJ,GAAYC,CAAW;AAAA,EAAA,GAGlCgJ,IAAyBsD,EAAY,MAAM;AAC/C,UAAM/I,IAAYiG,EAAa,SACzB/sB,IAAc8mB,GAAW,eAAA,EAAiB,eAAe;AAC/D,QAAI,OAAK,IAAI9mB,IAAc,GAAG,IAAI,QAAQ,CAAC8mB;AAE3C,aAAO;AAAA,QACL,eAAe,CAACxiB,GAAWD,MAAkEof,GAAQqD,EAAU,cAAcxiB,GAAGD,CAAC,CAAC;AAAA,QAClI,eAAeyrB;AAAA,MAAA;AAAA,EAEnB,GAAG,CAAC/C,GAAc+C,CAAkB,CAAC,GAE/BxD,KAAuBuD;AAAA,IAC3B,CAACE,MAA6B;AAC5B,UAAI,CAAC,OAAO,SAASA,CAAQ,KAAKA,KAAY,EAAG,QAAO;AAExD,YAAMC,IAAW,OAAO5W,KAAa,YAAY,OAAO,SAASA,CAAQ,KAAKA,IAAW,IAAIA,IAAW,GAClG6W,IAAiB,OAAO5W,KAAc,YAAY,OAAO,SAASA,CAAS,IAAIA,IAAY,GAC3F6W,IAAcnD,EAAa,SAAS,eAAA,EAAiB,MACrDpT,IAAW,OAAOuW,KAAgB,YAAY,OAAO,SAASA,CAAW,KAAKA,IAAc,IAAIA,IAAc,GAC9GC,KAAiBF,IAAiB,KAAK,KAAKtW,CAAQ,GACpDyW,KAAmB,KAAK,IAAI,MAAMjX,GAAoB6W,GAAUC,GAAgBE,EAAc,CAAC;AAErG,aADqBJ,IAAWK,KACVzW;AAAA,IACxB;AAAA,IACA,CAACP,GAAUC,GAAW0T,CAAY;AAAA,EAAA,GAG9BsD,KAA2BR;AAAA,IAC/B,CAACzD,GAA0BpQ,MAClBmQ,GAAiB;AAAA,MACtB,WAAAC;AAAA,MACA,QAAApQ;AAAA,MACA,sBAAAqQ;AAAA,MACA,YAAA/I;AAAA,MACA,aAAAC;AAAA,MACA,sBAAA+I;AAAA,MACA,wBAAAC;AAAA,IAAA,CACD;AAAA,IAEH,CAACD,IAAsBhJ,GAAYC,GAAa8I,IAAsBE,CAAsB;AAAA,EAAA,GAGxF+D,IAAqBT,EAAY,MAAqD;AAC1F,UAAMpJ,IAAUoI,EAAW;AAC3B,WAAIpD,GAAYC,CAAI,IACX2E,GAAyB3E,GAAMjF,EAAQ,WAAW,IAEvDiF,MAAS,UACJ,CAAA,IAEJjF,EAAQ,YAETiF,MAAS,aACJjF,EAAQ,SAEbiF,MAAS,cACJrG,GAAgBoB,EAAQ,OAAOA,EAAQ,SAAS8F,GAAwB,IAE7Eb,MAAS,aACJ7F,GAAaY,EAAQ,OAAOA,EAAQ,OAAO,IAG7C,CAAA,IAZwB,CAAA;AAAA,EAajC,GAAG,CAACiF,GAAM2E,IAA0B9D,CAAsB,CAAC,GAErDgE,KAAcV,EAAY,MAAM;AACpC,IAAAD,GAAA;AAEA,UAAM3wB,IAASuvB,GAAU;AACzB,QAAI,CAACvvB,EAAQ;AAEb,UAAM4kB,IAAM5kB,EAAO,WAAW,IAAI;AAClC,QAAI,CAAC4kB,EAAK;AAEV,UAAMjhB,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9ConB,IAAc/qB,EAAO,QAAQ2D,GAC7BqnB,IAAehrB,EAAO,SAAS2D;AAKrC,QAJAihB,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAG5kB,EAAO,OAAOA,EAAO,MAAM,GAC/C4kB,EAAI,aAAajhB,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAEjCqsB,EAAyB,SAAS;AACpC,iBAAWuB,MAASvB,GAA0B;AAC5C,cAAM,EAAE,QAAAC,IAAQ,UAAApW,IAAU,aAAA2X,IAAa,WAAAC,OAAcF,IAC/CG,KAAwC/L,GAAemJ,GAAgB2C,EAAS,IAAI,WAAW9L,GAAekJ,GAAiB4C,EAAS,IAAI,UAAU;AAC5J,YAAI1M,KAAc2M,OAAU,WAAWrB,KAA4BqB,OAAU,UAAUtB,KAA2BD;AAElH,YAAIxB,GAA0B;AAC5B,gBAAMgD,KAAWhD,EAAyB;AAAA,YACxC,QAAAsB;AAAA,YACA,UAAUwB;AAAA,YACV,aAAAD;AAAA,YACA,OAAAE;AAAA,UAAA,CACD;AACD,UAAA3M,KAAcS,GAAiBT,IAAa4M,MAAY,MAAS;AAAA,QACnE;AACA,cAAMC,KAAyBF,OAAU,YAAY,OAAOlE,GAAoCzI,EAAW;AAE3G,mBAAWrN,MAAWmC,IAAU;AAC9B,gBAAMgY,KAAc5F,GAAoBvU,GAAQ,KAAK;AACrD,UAAIma,GAAY,UAAU,MACpBD,MACF9M,GAASF,GAAKiN,IAAaD,IAAwB,IAAM,EAAK,GAEhE9M,GAASF,GAAKiN,IAAa9M,IAAa,IAAM,EAAK;AAErD,qBAAWpL,MAAQjC,GAAQ,OAAO;AAChC,kBAAMoa,KAAa7F,GAAoBtS,EAAI;AAC3C,YAAImY,GAAW,UAAU,MACnBF,MACF9M,GAASF,GAAKkN,IAAYF,IAAwB,IAAM,EAAK,GAE/D9M,GAASF,GAAKkN,IAAY/M,IAAa,IAAM,EAAK;AAAA,UAEtD;AAAA,QACF;AAAA,MACF;AAGF,QAAImL,GAAqB,SAAS;AAChC,iBAAWqB,MAASrB;AAClB,mBAAWxY,MAAW6Z,GAAM,UAAU;AACpC,gBAAMM,KAAc5F,GAAoBvU,GAAQ,KAAK;AACrD,UAAIma,GAAY,UAAU,KACxB/M,GAASF,GAAKiN,IAAavB,IAA0B,IAAM,EAAK;AAElE,qBAAW3W,MAAQjC,GAAQ,OAAO;AAChC,kBAAMoa,KAAa7F,GAAoBtS,EAAI;AAC3C,YAAImY,GAAW,UAAU,KACvBhN,GAASF,GAAKkN,IAAYxB,IAA0B,IAAM,EAAK;AAAA,UAEnE;AAAA,QACF;AAIJ,QAAI,MAAM,QAAQvE,CAAa,KAAKA,EAAc,SAAS,GAAG;AAC5D,YAAMC,KAAiBC;AAAA,QACrB9O,GAAU;AAAA,UACR,CAAC,GAAG,CAAC;AAAA,UACL,CAACkH,GAAY,CAAC;AAAA,UACd,CAACA,GAAYC,CAAW;AAAA,UACxB,CAAC,GAAGA,CAAW;AAAA,QAAA,CAChB;AAAA,MAAA;AAEH,MAAAuH,GAAkB;AAAA,QAChB,KAAAjH;AAAA,QACA,eAAAmH;AAAA,QACA,gBAAAC;AAAA,QACA,qBAAAC;AAAA,QACA,iBAAiBkE;AAAA,QACjB,qBAAsB,WAA0D,+BAC5E,CAAA4B,OAAQ;AACN,gBAAMC,KAAW,OAAOD,GAAK,EAAE,GACzBE,KAAiB,GAAGF,GAAK,eAAe,IAAIA,GAAK,eAAe,IAAIA,GAAK,aAAa,IAAIA,GAAK,SAAS;AAC9G,UAAIrC,GAAwB,QAAQ,IAAIsC,EAAQ,MAAMC,OACpDvC,GAAwB,QAAQ,IAAIsC,IAAUC,EAAc,GAC5D,QAAQ,MAAM,6BAA6BF,EAAI;AAAA,QAEnD,IACA;AAAA,MAAA,CACL;AAAA,IACH;AAEA,UAAMG,KAAUb,EAAA;AAEhB,QAAInQ;AACF,UAAIuL,MAAS;AACX,QAAAlF,GAAuB3C,GAAKgL,EAAW,SAASnI,EAAoB,GACpEG,GAAgBhD,GAAKgL,EAAW,SAAS9B,EAAa,SAASrG,EAAoB;AAAA,eAC1EyK,GAAQ,SAAS;AAC1B,YAAIzF,MAAS,YAAY;AACvB,gBAAM0F,KAAOlG,GAAoBiG,EAAO;AACxC,UAAIC,GAAK,UAAU,KACjBrN,GAASF,GAAKuN,IAAMhC,IAAqB,IAAO,EAAK,GAEnDgC,GAAK,UAAU,KACjBrN,GAASF,GAAKqH,GAAoB9O,GAAU+U,EAAO,CAAC,GAAG/B,IAAqB,IAAM,IAAMI,EAA4B;AAAA,QAExH,OAAO;AACL,gBAAM7Y,KAAUuU,GAAoBiG,EAAO;AAC3C,UAAIxa,GAAQ,UAAU,KACpBoN,GAASF,GAAKlN,IAASyY,IAAqB,IAAM,IAAMI,EAA4B;AAAA,QAExF;AAAA;AAIJ,QAAIP,EAAyB,SAAS,GAAG;AACvC,YAAMtvB,KAAO,KAAK,IAAI,MAAMotB,EAAa,SAAS,eAAA,EAAiB,QAAQ,CAAC,GACtEsE,KACJ,OAAOhD,KAAgC,YAAY,OAAO,SAASA,CAA2B,IAC1F,KAAK,IAAI,GAAGA,CAA2B,IACvC1F;AAAA,QACEuF;AAAA,QACAvuB;AAAA,QACAotB,EAAa,SAAS,eAAA;AAAA,QACtBA,EAAa,SAAS,gCAAA;AAAA,MAAgC;AAE9D,iBAAWyD,MAASvB,GAA0B;AAC5C,YAAI,CAACuB,GAAM,OAAO,MAAO;AACzB,cAAMc,KAAevJ,GAAkCyI,GAAM,UAAUtF,IAAqBiD,CAAiB;AAC7G,YAAI,CAACmD,GAAc;AACnB,YAAIC,KAAoB7I;AAAA,UACtB+G;AAAA,UACA5B,IAA8B;AAAA,YAC5B,QAAQ2C,GAAM;AAAA,YACd,UAAUA,GAAM;AAAA,YAChB,aAAaA,GAAM;AAAA,YACnB,MAAA7wB;AAAA,UAAA,CACD;AAAA,QAAA;AAEH,QAAI0xB,KAAsB,MACxBE,KAAoB;AAAA,UAClB,GAAGA;AAAA,UACH,SAASA,GAAkB,UAAUF;AAAA,QAAA,IAGzCvH,GAAgBjG,GAAK2M,GAAM,OAAO,OAAOc,IAActH,GAAaC,GAAcsH,IAAmBnD,CAA0B;AAAA,MACjI;AAAA,IACF;AAEA,QAAIsB,GAA+B,WAAWvP,MAAWuL,MAAS,cAAcA,MAAS,eAAeA,MAAS,aAAa;AAC5H,YAAMjF,KAAUoI,EAAW;AAC3B,UAAIpI,GAAQ,WAAW;AACrB,cAAM+K,KAAa9F,MAAS,aAAatP,GAAU+U,EAAO,IAAIA;AAC9D,YAAIK,GAAW,UAAU,GAAG;AAC1B,gBAAMC,KAAS/N,GAAY8N,EAAU,GAC/BjY,KAAM,OAAOH,KAAa,YAAY,OAAO,SAASA,CAAQ,KAAKA,IAAW,IAAIA,IAAW,GAC7FsQ,KAAUnQ,KAAM,IAAKkY,KAASlY,KAAMA,MAAQyI,KAAiBA,MAAkB,GAC/E+H,KAAO2F,GAA+B,OAAOhG,EAAO,GAEpD3C,KAASN,GAAQ,iBAAiBA,GAAQ,UAAUhD,GAAQsJ,EAAa,SAAS,cAActG,GAAQ,QAAQ,CAAC,GAAGA,GAAQ,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI;AACvJ,UAAIM,MACF0D;AAAA,YACE5G;AAAA,YACAkG;AAAA,YACAhD;AAAA,YACAiD;AAAA,YACAC;AAAA,YACAyF,GAA+B;AAAA,YAC/BA,GAA+B;AAAA,YAC/BA,GAA+B;AAAA,UAAA;AAAA,QAGrC;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG;AAAA,IACDvP;AAAA,IACAuL;AAAA,IACA4E;AAAA,IACAV;AAAA,IACA1E;AAAA,IACA5H;AAAA,IACAC;AAAA,IACAwJ;AAAA,IACAkC;AAAA,IACAjE;AAAA,IACA8C;AAAA,IACAC;AAAA,IACAqB;AAAA,IACAC;AAAA,IACAC;AAAA,IACAE;AAAA,IACAL;AAAA,IACAI;AAAA,IACA3B;AAAA,IACAC;AAAA,IACA4B;AAAA,IACAC;AAAA,IACAxB;AAAA,IACAC;AAAA,IACAC;AAAA,IACAC;AAAA,IACAjV;AAAA,IACAsN;AAAA,EAAA,CACD,GAEKgL,IAAc7B,EAAY,MAAM;AACpC,IAAInB,GAAe,YACnBA,GAAe,UAAU,IACzB,sBAAsB,MAAM;AAC1B,MAAAA,GAAe,UAAU,IACzB6B,GAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACA,EAAW,CAAC,GAEVoB,KAAe9B,EAAY,CAAC+B,IAAiB,OAAU;AAC3D,UAAMnL,IAAUoI,EAAW,SACrB5vB,IAASuvB,GAAU;AAEzB,IAAIvvB,KAAUwnB,EAAQ,cAAc,QAAQxnB,EAAO,kBAAkBwnB,EAAQ,SAAS,KACpFxnB,EAAO,sBAAsBwnB,EAAQ,SAAS,GAGhDA,EAAQ,YAAY,IACpBA,EAAQ,YAAY,MACpBA,EAAQ,QAAQ,MAChBA,EAAQ,UAAU,MAClBA,EAAQ,SAAS,CAAA,GACjBA,EAAQ,eAAe,CAAA,GACvBA,EAAQ,cAAc,MACjBmL,MACHnL,EAAQ,SAAS,MACjBA,EAAQ,eAAe;AAAA,EAE3B,GAAG,CAAA,CAAE,GAECoL,KAAUhC;AAAA,IACd,CAACvd,MAAoG;AACnG,YAAMwU,IAAYiG,EAAa;AAC/B,UAAI,CAACjG,KAAaxD,KAAc,KAAKC,KAAe,EAAG,QAAO;AAE9D,YAAMvD,IAAMyD,GAAQqD,EAAU,cAAcxU,EAAM,SAASA,EAAM,OAAO,CAAC;AACzE,aAAK0N,IACEqD,GAAWrD,GAAKsD,GAAYC,CAAW,IAD7B;AAAA,IAEnB;AAAA,IACA,CAACwJ,GAAczJ,GAAYC,CAAW;AAAA,EAAA,GAGlCuO,KAAgBjC,EAAY,CAACvd,MAAoG;AACrI,UAAMrT,IAASuvB,GAAU;AACzB,QAAI,CAACvvB,EAAQ,QAAO;AACpB,UAAMwD,IAAOxD,EAAO,sBAAA,GACdqF,IAAI0U,EAAM1G,EAAM,UAAU7P,EAAK,MAAM,GAAGA,EAAK,KAAK,GAClD4B,IAAI2U,EAAM1G,EAAM,UAAU7P,EAAK,KAAK,GAAGA,EAAK,MAAM;AACxD,WAAI,CAAC,OAAO,SAAS6B,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,IAAU,OAChD,CAACC,GAAGD,CAAC;AAAA,EACd,GAAG,CAAA,CAAE,GAEC0tB,IAAgBlC,EAAY,MAAM;AACtC,UAAMpJ,IAAUoI,EAAW;AAC3B,QAAI,CAACpI,EAAQ,WAAW;AACtB,MAAAkL,GAAa,EAAI,GACjBD,EAAA;AACA;AAAA,IACF;AAEA,QAAI7a,IAA6D,CAAA;AACjE,QAAI6U,MAAS;AACX,MAAIjF,EAAQ,OAAO,UAAU7E,OAC3B/K,IAAcuF,GAAUqK,EAAQ,MAAM;AAAA,aAE/BiF,MAAS;AAClB,MAAA7U,IAAcwO,GAAgBoB,EAAQ,OAAOA,EAAQ,SAAS8F,GAAwB;AAAA,aAC7Eb,MAAS;AAClB,MAAA7U,IAAcgP,GAAaY,EAAQ,OAAOA,EAAQ,OAAO;AAAA,aAChDiF,MAAS,SAAS;AAC3B,YAAMsG,IAAWvL,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,KAAKA,EAAQ,WAAWA,EAAQ;AACzF,UAAIC,GAAqB,kBAAkBsL,KAAYvL,EAAQ,OAAO,UAAU,KAAKuG,IAAagF,CAAQ,GAAG;AAC3G,QAAAL,GAAa,EAAI,GACjBD,EAAA;AACA;AAAA,MACF;AACA,YAAMpL,IAAa,KAAK,IAAI,MAAMI,GAAqB,UAAU,GAC3DuL,IAAaxL,EAAQ,aAAa,SAAS,IAAIA,EAAQ,eAAeyE,GAAoBzE,EAAQ,MAAM,GACxGyL,KAAoB,KAAK,IAAI,KAAMxL,GAAqB,SAAS,OAAQJ,CAAU,GACnF6L,KAAgB9S,GAAwB4S,GAAY;AAAA,QACxD,QAAQvL,GAAqB;AAAA,QAC7B,aAAa,KAAK,IAAI,IAAI,KAAK,MAAM,KAAKJ,CAAU,CAAC;AAAA,QACrD,mBAAA4L;AAAA,QACA,iBAAiBxL,GAAqB;AAAA,MAAA,CACvC,GACK0L,KAA8D,CAAA;AACpE,iBAAWlqB,MAASiqB,IAAe;AACjC,cAAMvM,KAAQkK,EAAmB5nB,EAAK;AACtC,QAAK0d,MACLwM,GAAa,KAAKxM,EAAK;AAAA,MACzB;AACA,MAAA/O,IAAcuF,GAAUgW,EAAY;AAAA,IACtC;AAEA,KAAK1G,MAAS,cAAcA,MAAS,eAAeA,MAAS,cAAcA,MAAS,YAAYiB,GAAe9V,CAAW,KAAKoW,KAE7HA,EAAe;AAAA,MACb,MAAAvB;AAAA,MACA,QAHsDA,MAAS,UAAU,UAAU;AAAA,MAInF,aAAA7U;AAAA,MACA,MAAM8M,GAAc9M,CAAW;AAAA,MAC/B,QAAQ6M,GAAY7M,CAAW;AAAA,IAAA,CAChC,GAGH8a,GAAa,EAAI,GACjBD,EAAA;AAAA,EACF,GAAG;AAAA,IACDhG;AAAA,IACAuB;AAAA,IACA0E;AAAA,IACAD;AAAA,IACAxG;AAAA,IACA4E;AAAA,IACAvD;AAAA,IACA7F,GAAqB;AAAA,IACrBA,GAAqB;AAAA,IACrBA,GAAqB;AAAA,IACrBA,GAAqB;AAAA,IACrBsG;AAAA,EAAA,CACD,GAEKqF,IAAgBxC;AAAA,IACpB,CAACzD,GAA0BpQ,MAA8D;AACvF,YAAMnF,IAAcwZ,GAAyBjE,GAAWpQ,CAAM;AAC9D,UAAI,CAAC2Q,GAAe9V,CAAW,EAAG;AAClC,YAAMyb,IAAkDlG,MAAc,2BAA2B,UAAU,OACrG1O,IAAkD;AAAA,QACtD,MAAM0O;AAAA,QACN,QAAAkG;AAAA,QACA,aAAAzb;AAAA,QACA,MAAM8M,GAAc9M,CAAW;AAAA,QAC/B,QAAQ6M,GAAY7M,CAAW;AAAA,MAAA;AAEjC,MAAAoW,IAAiBvP,CAAM,GACnB4U,MAAW,WAAWpF,KACxBA,EAAgBxP,CAAsD;AAAA,IAE1E;AAAA,IACA,CAAC2S,IAA0BpD,GAAgBC,CAAe;AAAA,EAAA,GAGtDqF,IAAmB1C;AAAA,IACvB,CAACpJ,GAAsBb,GAAoDoB,MAA8D;AACvI,YAAMwL,IAAgB,KAAK,IAAIpP,IAAmBsD,GAAqB,SAAS,GAAG,GAC7E+L,IAAiBD,IAAgBA,GACjCE,KAAajM,EAAQ,aAAaA,EAAQ,aAAa,SAAS,CAAC;AACvE,UAAI,CAACiM,IAAY;AACf,QAAAjM,EAAQ,OAAO,KAAKb,CAAK,GACzBa,EAAQ,aAAa,KAAKO,CAAM,GAChCP,EAAQ,UAAUb;AAClB;AAAA,MACF;AACA,YAAM3lB,KAAK+mB,EAAO,CAAC,IAAI0L,GAAW,CAAC,GAC7BxyB,KAAK8mB,EAAO,CAAC,IAAI0L,GAAW,CAAC;AACnC,MAAIzyB,KAAKA,KAAKC,KAAKA,MAAMuyB,KACvBhM,EAAQ,OAAO,KAAKb,CAAK,GACzBa,EAAQ,aAAa,KAAKO,CAAM,MAEhCP,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,IAAIb,GAC5Ca,EAAQ,aAAaA,EAAQ,aAAa,SAAS,CAAC,IAAIO,IAE1DP,EAAQ,UAAUb;AAAA,IACpB;AAAA,IACA,CAACc,GAAqB,MAAM;AAAA,EAAA,GAGxBiM,KAAoB9C;AAAA,IACxB,CAACvd,MAAgD;AAG/C,UAFI,CAAC6N,KACDuL,MAAS,YACTpZ,EAAM,WAAW,EAAG;AAExB,YAAMsT,IAAQiM,GAAQvf,CAAK;AAC3B,UAAI,CAACsT,EAAO;AACZ,YAAMoB,IAAS8K,GAAcxf,CAAK;AAClC,UAAI,CAAC0U,EAAQ;AAKb,UAHA1U,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEFmZ,GAAYC,CAAI,GAAG;AACrB,cAAMjF,KAAUoI,EAAW;AAC3BpI,QAAAA,GAAQ,cAAcb,GACtByM,EAAc3G,GAAM9F,CAAK,GACzB8L,EAAA;AACA;AAAA,MACF;AAEA,YAAMzyB,IAASuvB,GAAU;AACzB,MAAIvvB,KACFA,EAAO,kBAAkBqT,EAAM,SAAS;AAG1C,YAAMmU,IAAUoI,EAAW;AAC3B,MAAApI,EAAQ,YAAY,IACpBA,EAAQ,YAAYnU,EAAM,WAC1BmU,EAAQ,QAAQb,GAChBa,EAAQ,UAAUb,GAClBa,EAAQ,SAASb,GACjBa,EAAQ,eAAeO,GACvBP,EAAQ,SAASiF,MAAS,cAAcA,MAAS,UAAU,CAAC9F,CAAK,IAAI,CAAA,GACrEa,EAAQ,eAAeiF,MAAS,UAAU,CAAC1E,CAAM,IAAI,CAAA,GACrD0K,EAAA;AAAA,IACF;AAAA,IACA,CAACvR,GAAQuL,GAAMmG,IAASC,IAAeO,GAAeX,CAAW;AAAA,EAAA,GAG7DkB,KAAoB/C;AAAA,IACxB,CAACvd,MAAgD;AAE/C,UADI,CAAC6N,KACDuL,MAAS,SAAU;AAEvB,YAAM9F,IAAQiM,GAAQvf,CAAK;AAC3B,UAAI,CAACsT,EAAO;AACZ,YAAMoB,IAAS8K,GAAcxf,CAAK;AAClC,UAAI,CAAC0U,EAAQ;AAEb,YAAMP,IAAUoI,EAAW;AAI3B,UAHApI,EAAQ,SAASb,GACjBa,EAAQ,eAAeO,GAEnByE,GAAYC,CAAI,GAAG;AACrB,QAAAjF,EAAQ,cAAcb,GACtBtT,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNof,EAAA;AACA;AAAA,MACF;AAEA,UAAIhG,MAAS,SAAS;AACpB,YAAI,CAACjF,EAAQ,aAAaA,EAAQ,cAAcnU,EAAM,WAAW;AAC/D,UAAAof,EAAA;AACA;AAAA,QACF;AACA,QAAApf,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNigB,EAAiB9L,GAASb,GAAOoB,CAAM,GACvC0K,EAAA;AACA;AAAA,MACF;AAEA,UAAI,GAACjL,EAAQ,aAAaA,EAAQ,cAAcnU,EAAM,YAMtD;AAAA,YAHAA,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEFoZ,MAAS,YAAY;AACvB,gBAAM5E,IAAYiG,EAAa,SACzBptB,KAAO,KAAK,IAAI,MAAMmnB,GAAW,eAAA,EAAiB,QAAQ,CAAC,GAC3D+L,KAAehR,KAAuBliB,IACtCmzB,KAAgBD,KAAeA,IAC/B9b,KAAO0P,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC;AAErD,cAAI,CAAC1P;AACH,YAAA0P,EAAQ,OAAO,KAAKb,CAAK;AAAA,eACpB;AACL,kBAAM3lB,KAAK2lB,EAAM,CAAC,IAAI7O,GAAK,CAAC,GACtB7W,KAAK0lB,EAAM,CAAC,IAAI7O,GAAK,CAAC;AAC5B,YAAI9W,KAAKA,KAAKC,KAAKA,MAAM4yB,MACvBrM,EAAQ,OAAO,KAAKb,CAAK;AAAA,UAE7B;AAAA,QACF;AACE,UAAAa,EAAQ,UAAUb;AAGpB,QAAA8L,EAAA;AAAA;AAAA,IACF;AAAA,IACA,CAACvR,GAAQuL,GAAMmG,IAASC,IAAeJ,GAAa3E,GAAcwF,CAAgB;AAAA,EAAA,GAG9EQ,KAAkBlD;AAAA,IACtB,CAACvd,MAAgD;AAC/C,YAAMmU,IAAUoI,EAAW;AAC3B,UAAI,CAACpI,EAAQ,aAAaA,EAAQ,cAAcnU,EAAM,UAAW;AAEjE,MAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,YAAMsT,IAAQiM,GAAQvf,CAAK,GACrB0U,IAAS8K,GAAcxf,CAAK;AAClC,MAAIsT,MACFa,EAAQ,SAASb,GACboB,MACFP,EAAQ,eAAeO,IAErB0E,MAAS,UACP1E,KACFuL,EAAiB9L,GAASb,GAAOoB,CAAM,IAGzCP,EAAQ,UAAUb;AAGtB,YAAM3mB,IAASuvB,GAAU;AACzB,MAAIvvB,KAAUA,EAAO,kBAAkBqT,EAAM,SAAS,KACpDrT,EAAO,sBAAsBqT,EAAM,SAAS,GAG9Cyf,EAAA;AAAA,IACF;AAAA,IACA,CAACA,GAAeF,IAASC,IAAepG,GAAM6G,CAAgB;AAAA,EAAA,GAG1DS,KAAqBnD,EAAY,MAAM;AAC3C,UAAMpJ,IAAUoI,EAAW;AAC3B,QAAIoE,IAAU;AACd,IAAIvH,MAAS,WAAW,CAACjF,EAAQ,aAAaA,EAAQ,WACpDA,EAAQ,SAAS,MACjBA,EAAQ,eAAe,MACvBwM,IAAU,KAERxH,GAAYC,CAAI,KAAKjF,EAAQ,gBAC/BA,EAAQ,cAAc,MACtBwM,IAAU,KAERA,KACFvB,EAAA;AAAA,EAEJ,GAAG,CAAChG,GAAMgG,CAAW,CAAC;AAEtB,SAAAwB,EAAU,MAAM;AACd,IAAAtD,GAAA,GACA8B,EAAA;AAEA,UAAMzyB,IAASuvB,GAAU;AACzB,QAAI,CAACvvB,EAAQ;AAEb,UAAMk0B,IAAW,IAAI,eAAe,MAAM;AACxC,MAAAvD,GAAA,GACA8B,EAAA;AAAA,IACF,CAAC;AACD,WAAAyB,EAAS,QAAQl0B,CAAM,GAEhB,MAAM;AACX,MAAAk0B,EAAS,WAAA;AAAA,IACX;AAAA,EACF,GAAG,CAACvD,IAAc8B,CAAW,CAAC,GAE9BwB,EAAU,MAAMjT,GAA+B,MAAM;AACnD,IAAA2P,GAAA,GACA8B,EAAA;AAAA,EACF,CAAC,GAAG,CAAC9B,IAAc8B,CAAW,CAAC,GAE/BwB,EAAU,MAAM;AACd,IAAK/S,KACHwR,GAAA,GAEFD,EAAA;AAAA,EACF,GAAG,CAACvR,GAAQuR,GAAaC,EAAY,CAAC,GAEtCuB,EAAU,MAAM;AACd,IAAItE,EAAY,YAAYlD,MAG5BkD,EAAY,UAAUlD,GACtBiG,GAAA,GACAD,EAAA;AAAA,EACF,GAAG,CAAChG,GAAMiG,IAAcD,CAAW,CAAC,GAEpCwB,EAAU,MAAM;AACd,IAAAxB,EAAA;AAAA,EACF,GAAG,CAACvE,GAAiB2B,IAAwB9D,GAAe0G,CAAW,CAAC,GAExEwB,EAAU,MAAM;AACd,QAAK5E;AACL,aAAAA,EAAc,UAAUoD,GACjB,MAAM;AACX,QAAIpD,EAAc,YAAYoD,MAC5BpD,EAAc,UAAU;AAAA,MAE5B;AAAA,EACF,GAAG,CAACA,GAAeoD,CAAW,CAAC,GAE/BwB,EAAU,MAAM;AACd,QAAI,CAAC/S,EAAQ;AAEb,UAAMiT,IAAY,CAAC9gB,MAA+B;AAChD,MAAIA,EAAM,QAAQ,aAClBqf,GAAA,GACAD,EAAA;AAAA,IACF;AAEA,kBAAO,iBAAiB,WAAW0B,CAAS,GACrC,MAAM;AACX,aAAO,oBAAoB,WAAWA,CAAS;AAAA,IACjD;AAAA,EACF,GAAG,CAACjT,GAAQwR,IAAcD,CAAW,CAAC,GAGpC,gBAAA2B;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK7E;AAAA,MACL,WAAAD;AAAA,MACA,OAAOoB;AAAA,MACP,eAAegD;AAAA,MACf,eAAeC;AAAA,MACf,aAAaG;AAAA,MACb,iBAAiBA;AAAA,MACjB,gBAAgBC;AAAA,MAChB,eAAe,CAAA1gB,MAAS;AACtB,QAAI6N,OAAc,eAAA;AAAA,MACpB;AAAA,MACA,SAAS,CAAA7N,MAAS;AAChB,YAAI,CAAC6N,EAAQ;AACb,cAAMlhB,IAASuvB,GAAU,SACnB1H,IAAYiG,EAAa,SACzBuG,IAAe,OAAOxM,GAAW,mBAAoB,YACrDyM,IAAgB,OAAOzM,GAAW,UAAW;AACnD,YAAI,CAAC7nB,KAAW,CAACq0B,KAAgB,CAACC,EAAgB;AAClD,QAAAjhB,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,cAAM7P,KAAOxD,EAAO,sBAAA,GACda,KAAUwS,EAAM,UAAU7P,GAAK,MAC/B1C,KAAUuS,EAAM,UAAU7P,GAAK;AACrC,QAAI6wB,IACFxM,EAAU,kBAAkBxU,EAAM,QAAQxS,IAASC,EAAO,IAE1D+mB,EAAU,SAASxU,EAAM,SAAS,IAAI+P,KAAuBC,IAAuBxiB,IAASC,EAAO,GAEtG2xB,EAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAGN;ACv7BA,MAAM8B,KAAgBC,GAAyC,IAAI,GAEtDC,KAAwBF,GAAc;AAE5C,SAASG,KAAuC;AACrD,QAAM9P,IAAM+P,GAAWJ,EAAa;AACpC,MAAI,CAAC3P;AACH,UAAM,IAAI,MAAM,oDAAoD;AAEtE,SAAOA;AACT;ACvBO,SAASgQ,GAAa,EAAE,MAAAnI,IAAO,UAAU,cAAAmB,GAAc,cAAAC,GAAc,WAAA5I,GAAW,aAAA4P,GAAa,YAAAC,GAAY,iBAAA7G,GAAiB,YAAAF,EAAA,GAA4D;AAC3L,QAAM,EAAE,QAAA5uB,GAAQ,aAAA41B,GAAa,gBAAAC,GAAgB,oBAAAC,EAAA,IAAuBP,GAAA,GAE9DxT,IAASuL,MAAS;AAExB,EAAAwH,EAAU,OACRgB,EAAmB,iBAAiB/T,CAAM,GACnC,MAAM+T,EAAmB,iBAAiB,EAAK,IACrD,CAAC/T,GAAQ+T,CAAkB,CAAC;AAE/B,QAAM/G,IAAkB4B,GAAQ,MAAMiF,EAAY,SAAS,aAAA,GAAgB,CAACC,CAAc,CAAC;AAE3F,SAAK71B,IAGH,gBAAAi1B;AAAA,IAACzG;AAAA,IAAA;AAAA,MACC,MAAAlB;AAAA,MACA,SAASvL;AAAA,MACT,YAAY/hB,EAAO;AAAA,MACnB,aAAaA,EAAO;AAAA,MACpB,UAAUA,EAAO;AAAA,MACjB,WAAWA,EAAO;AAAA,MAClB,cAAAyuB;AAAA,MACA,cAAAC;AAAA,MACA,eAAe5I;AAAA,MACf,cAAc8P;AAAA,MACd,YAAAhH;AAAA,MACA,iBAAAG;AAAA,MACA,iBAAiB2G;AAAA,MACjB,gBAAgBC;AAAA,MAChB,iBAAA7G;AAAA,IAAA;AAAA,EAAA,IAlBgB;AAqBtB;AClCA,SAASiH,GAAgB5b,GAAcC,GAAcC,GAAcC,GAA6B;AAC9F,SAAO,CAAC,KAAK,IAAIH,GAAME,CAAI,GAAG,KAAK,IAAID,GAAME,CAAI,GAAG,KAAK,IAAIH,GAAME,CAAI,GAAG,KAAK,IAAID,GAAME,CAAI,CAAC;AAChG;AAEA,SAAS0b,GAAWhwB,GAAkBwE,GAA2B;AAC/D,SAAO,EAAExE,EAAE,CAAC,IAAIwE,EAAE,CAAC,KAAKxE,EAAE,CAAC,IAAIwE,EAAE,CAAC,KAAKxE,EAAE,CAAC,IAAIwE,EAAE,CAAC,KAAKxE,EAAE,CAAC,IAAIwE,EAAE,CAAC;AAClE;AAEA,MAAMyrB,GAA+C;AAAA,EAmBnD,YAAYC,IAAW,IAAI;AAlBV,IAAA/0B,EAAA;AAET,IAAAA,EAAA,eAA+B,CAAA;AAE/B,IAAAA,EAAA,sBAA8B,CAAC,GAAG,GAAG,GAAG,CAAC;AAEzC,IAAAA,EAAA,kBAAW;AAEX,IAAAA,EAAA,mBAAY;AAEZ,IAAAA,EAAA,oBAAa;AAEb,IAAAA,EAAA,iBAAsB,CAAA;AAEtB,IAAAA,EAAA,iBAAU,IAAI,YAAY,CAAC;AAE3B,IAAAA,EAAA,qBAAc;AAGpB,UAAMg1B,IAAS,OAAO,SAASD,CAAQ,IAAI,KAAK,MAAMA,CAAQ,IAAI;AAClE,SAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EAC1C;AAAA,EAEA,KAAKC,GAAoC;AACvC,QAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,WAAW,GAAG;AAC/C,WAAK,QAAQ,CAAA,GACb,KAAK,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC,GAC/B,KAAK,WAAW,GAChB,KAAK,YAAY,GACjB,KAAK,aAAa,GAClB,KAAK,UAAU,CAAA,GACf,KAAK,UAAU,IAAI,YAAY,CAAC,GAChC,KAAK,cAAc;AACnB;AAAA,IACF;AAEA,UAAMpd,IAAoC,CAAA;AAC1C,QAAImB,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAWqC,KAAQyZ,GAAO;AAExB,UADI,CAACzZ,KACD,CAAC,OAAO,SAASA,EAAK,IAAI,KAAK,CAAC,OAAO,SAASA,EAAK,IAAI,KAAK,CAAC,OAAO,SAASA,EAAK,IAAI,KAAK,CAAC,OAAO,SAASA,EAAK,IAAI;AACzH;AAEF,YAAMiC,IAASmX,GAAgBpZ,EAAK,MAAMA,EAAK,MAAMA,EAAK,MAAMA,EAAK,IAAI;AACzE,MAAAxC,IAAO,KAAK,IAAIA,GAAMyE,EAAO,CAAC,CAAC,GAC/BxE,IAAO,KAAK,IAAIA,GAAMwE,EAAO,CAAC,CAAC,GAC/BvE,IAAO,KAAK,IAAIA,GAAMuE,EAAO,CAAC,CAAC,GAC/BtE,IAAO,KAAK,IAAIA,GAAMsE,EAAO,CAAC,CAAC,GAC/B5F,EAAW,KAAK;AAAA,QACd,MAAM4F,EAAO,CAAC;AAAA,QACd,MAAMA,EAAO,CAAC;AAAA,QACd,MAAMA,EAAO,CAAC;AAAA,QACd,MAAMA,EAAO,CAAC;AAAA,QACd,OAAOjC,EAAK;AAAA,MAAA,CACb;AAAA,IACH;AAMA,QAJA,KAAK,QAAQ3D,GACb,KAAK,UAAU,IAAI,YAAYA,EAAW,MAAM,GAChD,KAAK,cAAc,GAEfA,EAAW,WAAW,KAAK,CAAC,OAAO,SAASmB,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,GAAG;AACnI,WAAK,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC,GAC/B,KAAK,WAAW,GAChB,KAAK,YAAY,GACjB,KAAK,aAAa,GAClB,KAAK,UAAU,CAAA;AACf;AAAA,IACF;AAEA,SAAK,eAAe,CAACH,GAAMC,GAAMC,GAAMC,CAAI,GAC3C,KAAK,WAAW,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,KAAKtB,EAAW,SAAS,KAAK,cAAc,CAAC,CAAC;AAEzF,UAAMqd,IAAQ,KAAK,IAAI,GAAGhc,IAAOF,CAAI,GAC/Bmc,IAAQ,KAAK,IAAI,GAAGhc,IAAOF,CAAI;AACrC,SAAK,YAAYic,IAAQ,IAAIA,IAAQ,KAAK,WAAW,GACrD,KAAK,aAAaC,IAAQ,IAAIA,IAAQ,KAAK,WAAW;AAEtD,UAAMC,IAAc,KAAK,WAAW,KAAK;AACzC,SAAK,UAAU,MAAM,KAAK,EAAE,QAAQA,EAAA,GAAe,MAAM,EAAE;AAE3D,aAAS5kB,IAAQ,GAAGA,IAAQqH,EAAW,QAAQrH,KAAS,GAAG;AACzD,YAAMgL,IAAO3D,EAAWrH,CAAK,GACvB6kB,IAAW,KAAK,QAAQ7Z,EAAK,IAAI,GACjC8Z,IAAW,KAAK,QAAQ9Z,EAAK,IAAI,GACjC+Z,IAAW,KAAK,QAAQ/Z,EAAK,IAAI,GACjCga,IAAW,KAAK,QAAQha,EAAK,IAAI;AACvC,eAAS,IAAI+Z,GAAU,KAAKC,GAAU,KAAK;AACzC,iBAASzwB,IAAIswB,GAAUtwB,KAAKuwB,GAAUvwB,KAAK;AACzC,eAAK,QAAQ,IAAI,KAAK,WAAWA,CAAC,EAAE,KAAKyL,CAAK;AAAA,IAGpD;AAAA,EACF;AAAA,EAEA,OAAOilB,GAA8C;AACnD,QAAI,KAAK,MAAM,WAAW,UAAU,CAAA;AACpC,QAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AAExD,UAAMC,IAAQd,GAAgBa,EAAO,CAAC,GAAGA,EAAO,CAAC,GAAGA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AACxE,QAAI,CAACZ,GAAWa,GAAO,KAAK,YAAY,UAAU,CAAA;AAElD,UAAML,IAAW,KAAK,QAAQK,EAAM,CAAC,CAAC,GAChCJ,IAAW,KAAK,QAAQI,EAAM,CAAC,CAAC,GAChCH,IAAW,KAAK,QAAQG,EAAM,CAAC,CAAC,GAChCF,IAAW,KAAK,QAAQE,EAAM,CAAC,CAAC,GAEhCC,IAAS,KAAK,WAAA,GACdpe,IAA6B,CAAA;AAEnC,aAASzS,IAAIywB,GAAUzwB,KAAK0wB,GAAU1wB,KAAK;AACzC,eAASC,IAAIswB,GAAUtwB,KAAKuwB,GAAUvwB,KAAK,GAAG;AAC5C,cAAM6wB,IAAS,KAAK,QAAQ9wB,IAAI,KAAK,WAAWC,CAAC;AACjD,YAAI,GAAC6wB,KAAUA,EAAO,WAAW;AACjC,qBAAWC,KAAaD,GAAQ;AAC9B,gBAAI,KAAK,QAAQC,CAAS,MAAMF,EAAQ;AACxC,iBAAK,QAAQE,CAAS,IAAIF;AAC1B,kBAAMna,IAAO,KAAK,MAAMqa,CAAS;AACjC,YAAKhB,GAAWa,GAAO,CAACla,EAAK,MAAMA,EAAK,MAAMA,EAAK,MAAMA,EAAK,IAAI,CAAC,KACnEjE,EAAI,KAAKiE,CAAI;AAAA,UACf;AAAA,MACF;AAGF,WAAOjE;AAAA,EACT;AAAA,EAEQ,aAAqB;AAC3B,gBAAK,eAAe,GAChB,KAAK,gBAAgB,eACvB,KAAK,QAAQ,KAAK,CAAC,GACnB,KAAK,cAAc,IAEd,KAAK;AAAA,EACd;AAAA,EAEQ,QAAQxS,GAAmB;AACjC,UAAMiU,IAAO,KAAK,aAAa,CAAC,GAC1BE,IAAO,KAAK,aAAa,CAAC;AAChC,QAAI,KAAK,YAAY,KAAKA,KAAQF,EAAM,QAAO;AAC/C,UAAM8c,KAAS/wB,IAAIiU,KAAQ,KAAK;AAEhC,WADI,CAAC,OAAO,SAAS8c,CAAK,KACtBA,KAAS,IAAU,IACnBA,KAAS,KAAK,WAAW,IAAU,KAAK,WAAW,IAChD,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,WAAW,GAAG,KAAK,MAAMA,CAAK,CAAC,CAAC;AAAA,EACnE;AAAA,EAEQ,QAAQhxB,GAAmB;AACjC,UAAMmU,IAAO,KAAK,aAAa,CAAC,GAC1BE,IAAO,KAAK,aAAa,CAAC;AAChC,QAAI,KAAK,YAAY,KAAKA,KAAQF,EAAM,QAAO;AAC/C,UAAM6c,KAAShxB,IAAImU,KAAQ,KAAK;AAEhC,WADI,CAAC,OAAO,SAAS6c,CAAK,KACtBA,KAAS,IAAU,IACnBA,KAAS,KAAK,WAAW,IAAU,KAAK,WAAW,IAChD,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,WAAW,GAAG,KAAK,MAAMA,CAAK,CAAC,CAAC;AAAA,EACnE;AACF;AAEO,SAASC,GAAsBhB,GAAoC;AACxE,SAAO,IAAID,GAAoBC,CAAQ;AACzC;AC1LA,MAAMiB,KAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAetBC,KAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkBxBC,KAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,IAOtBC,KAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwDvB,MAAMC,GAAqB;AAAA,EA+DhC,cAAc;AA9DL,IAAAp2B,EAAA;AAEQ,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAEA,IAAAA,EAAA;AAET,IAAAA,EAAA,uBAAgB;AAEhB,IAAAA,EAAA,6BAAsB;AAEtB,IAAAA,EAAA,2BAAyC;AAEzC,IAAAA,EAAA,qBAAc;AAGpB,SAAK,SAAS,SAAS,cAAc,QAAQ;AAC7C,UAAMrB,IAAK,KAAK,OAAO,WAAW,UAAU;AAAA,MAC1C,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,uBAAuB;AAAA,MACvB,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,IAAA,CAClB;AACD,QAAI,CAACA;AACH,YAAM,IAAI,MAAM,gDAAgD;AAElE,SAAK,KAAKA;AAGV,UAAM03B,IAAqB,EADF13B,EAAG,aAAa,wBAAwB;AAEjE,SAAK,sBAAsB03B,IAAqB13B,EAAG,UAAUA,EAAG,OAChE,KAAK,qBAAqBA,EAAG,MAC7B,KAAK,mBAAmB03B,IAAqB13B,EAAG,aAAaA,EAAG,eAEhE,KAAK,eAAeK,GAAcL,GAAIq3B,IAAqBC,EAAqB,GAChF,KAAK,eAAej3B,GAAcL,GAAIu3B,IAAqBC,EAAqB;AAEhF,UAAMG,IAAW33B,EAAG,kBAAA,GACd43B,IAAW53B,EAAG,kBAAA,GACd63B,IAAc73B,EAAG,aAAA,GACjBwD,IAAaxD,EAAG,aAAA,GAChB83B,IAAe93B,EAAG,cAAA,GAClB+3B,IAAkB/3B,EAAG,cAAA,GACrBg4B,IAAch4B,EAAG,kBAAA;AACvB,QAAI,CAAC23B,KAAY,CAACC,KAAY,CAACC,KAAe,CAACr0B,KAAc,CAACs0B,KAAgB,CAACC,KAAmB,CAACC;AACjG,YAAM,IAAI,MAAM,6CAA6C;AAE/D,SAAK,WAAWL,GAChB,KAAK,WAAWC,GAChB,KAAK,cAAcC,GACnB,KAAK,aAAar0B,GAClB,KAAK,eAAes0B,GACpB,KAAK,kBAAkBC,GACvB,KAAK,cAAcC;AAEnB,UAAMC,IAAkBj4B,EAAG,mBAAmB,KAAK,cAAc,aAAa,GACxEk4B,IAAiBl4B,EAAG,mBAAmB,KAAK,cAAc,YAAY,GACtEm4B,IAAiBn4B,EAAG,mBAAmB,KAAK,cAAc,YAAY,GACtEo4B,IAAkBp4B,EAAG,mBAAmB,KAAK,cAAc,aAAa,GACxEq4B,IAAoBr4B,EAAG,mBAAmB,KAAK,cAAc,eAAe,GAC5Es4B,IAAuBt4B,EAAG,mBAAmB,KAAK,cAAc,kBAAkB,GAClFu4B,IAAev4B,EAAG,mBAAmB,KAAK,cAAc,UAAU,GAClEw4B,IAAcx4B,EAAG,mBAAmB,KAAK,cAAc,SAAS,GAChEy4B,IAAYz4B,EAAG,mBAAmB,KAAK,cAAc,OAAO,GAC5D04B,IAAa14B,EAAG,mBAAmB,KAAK,cAAc,QAAQ,GAC9D24B,IAAY34B,EAAG,mBAAmB,KAAK,cAAc,OAAO,GAC5D44B,IAAe54B,EAAG,mBAAmB,KAAK,cAAc,UAAU,GAClE64B,IAAkB74B,EAAG,mBAAmB,KAAK,cAAc,aAAa;AAC9E,QAAI,CAACi4B,KAAmB,CAACC,KAAkB,CAACC,KAAkB,CAACC,KAAmB,CAACC,KAAqB,CAACC,KAAwB,CAACC,KAAgB,CAACC,KAAe,CAACC,KAAa,CAACC,KAAc,CAACC,KAAa,CAACC,KAAgB,CAACC;AAC7N,YAAM,IAAI,MAAM,2CAA2C;AAE7D,SAAK,mBAAmBZ,GACxB,KAAK,kBAAkBC,GACvB,KAAK,kBAAkBC,GACvB,KAAK,mBAAmBC,GACxB,KAAK,qBAAqBC,GAC1B,KAAK,wBAAwBC,GAC7B,KAAK,gBAAgBC,GACrB,KAAK,eAAeC,GACpB,KAAK,aAAaC,GAClB,KAAK,cAAcC,GACnB,KAAK,aAAaC,GAClB,KAAK,gBAAgBC,GACrB,KAAK,mBAAmBC,GAExB74B,EAAG,gBAAgB,KAAK,QAAQ,GAChCA,EAAG,WAAWA,EAAG,cAAc,KAAK,WAAW,GAC/CA,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AAEjD,UAAM84B,IAAiB94B,EAAG,kBAAkB,KAAK,cAAc,SAAS,GAClE+4B,IAAiB/4B,EAAG,kBAAkB,KAAK,cAAc,SAAS;AACxE,QAAI84B,IAAiB,KAAKC,IAAiB;AACzC,YAAM,IAAI,MAAM,6CAA6C;AAE/D,IAAA/4B,EAAG,wBAAwB84B,CAAc,GACzC94B,EAAG,oBAAoB84B,GAAgB,GAAG94B,EAAG,OAAO,IAAO,IAAI,CAAC,GAChEA,EAAG,wBAAwB+4B,CAAc,GACzC/4B,EAAG,oBAAoB+4B,GAAgB,GAAG/4B,EAAG,OAAO,IAAO,IAAI,CAAC,GAChEA,EAAG,gBAAgB,IAAI,GAEvBA,EAAG,gBAAgB,KAAK,QAAQ,GAChCA,EAAG,WAAWA,EAAG,cAAc,KAAK,UAAU,GAC9CA,EAAG,WAAWA,EAAG,cAAc,IAAI,aAAa;AAAA,MAC9C;AAAA,MAAI;AAAA,MACJ;AAAA,MAAG;AAAA,MACH;AAAA,MAAI;AAAA,MACJ;AAAA,MAAG;AAAA,IAAA,CACJ,GAAGA,EAAG,WAAW;AAClB,UAAMg5B,IAAmBh5B,EAAG,kBAAkB,KAAK,cAAc,WAAW;AAC5E,QAAIg5B,IAAmB;AACrB,YAAM,IAAI,MAAM,qDAAqD;AAEvE,IAAAh5B,EAAG,wBAAwBg5B,CAAgB,GAC3Ch5B,EAAG,oBAAoBg5B,GAAkB,GAAGh5B,EAAG,OAAO,IAAO,GAAG,CAAC,GACjEA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GAEnCA,EAAG,YAAYA,EAAG,YAAY,KAAK,YAAY,GAC/CA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAElCA,EAAG,YAAYA,EAAG,YAAY,KAAK,eAAe,GAClDA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAElC,KAAK,iBAAiB,GAAG,CAAC;AAAA,EAC5B;AAAA,EAEA,OAAO6sB,GAA2C;AAChD,QAAIA,EAAO,SAAS,KAAKA,EAAO,SAAS,KAAKA,EAAO,UAAU;AAC7D,aAAO;AAGT,SAAK,iBAAiBA,EAAO,OAAOA,EAAO,MAAM,GACjD,KAAK,sBAAsBA,EAAO,QAAQ,GAC1C,KAAK,gBAAgBA,EAAO,WAAWA,EAAO,SAASA,EAAO,KAAK;AAEnE,UAAM7sB,IAAK,KAAK;AAChB,WAAAA,EAAG,QAAQA,EAAG,YAAY,GAC1BA,EAAG,QAAQA,EAAG,UAAU,GACxBA,EAAG,QAAQA,EAAG,SAAS,GAEvBA,EAAG,gBAAgBA,EAAG,aAAa,KAAK,WAAW,GACnDA,EAAG,SAAS,GAAG,GAAG6sB,EAAO,OAAOA,EAAO,MAAM,GAC7C7sB,EAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GACxBA,EAAG,MAAMA,EAAG,gBAAgB,GAE5BA,EAAG,WAAW,KAAK,YAAY,GAC/BA,EAAG,gBAAgB,KAAK,QAAQ,GAChCA,EAAG,UAAU,KAAK,kBAAkB6sB,EAAO,OAAOA,EAAO,MAAM,GAC/D7sB,EAAG,UAAU,KAAK,iBAAiB,KAAK,IAAI,IAAI6sB,EAAO,iBAAiBA,EAAO,gBAAgB,CAAC,CAAC,GACjG7sB,EAAG,UAAU,KAAK,iBAAiB6sB,EAAO,iBAAiB,KAAK,IAAI,MAAMA,EAAO,iBAAiBA,EAAO,YAAY,CAAC,GACtH7sB,EAAG,UAAU,KAAK,kBAAkB,KAAK,IAAI,GAAG6sB,EAAO,UAAU,CAAC,GAClE7sB,EAAG,OAAOA,EAAG,KAAK,GAClBA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,kBAAkBA,EAAG,KAAKA,EAAG,KAAKA,EAAG,KAAKA,EAAG,GAAG,GACnDA,EAAG,WAAWA,EAAG,QAAQ,GAAG6sB,EAAO,KAAK,GACxC7sB,EAAG,QAAQA,EAAG,KAAK,GACnBA,EAAG,gBAAgB,IAAI,GAEvBA,EAAG,gBAAgBA,EAAG,aAAa,IAAI,GACvCA,EAAG,SAAS,GAAG,GAAG6sB,EAAO,OAAOA,EAAO,MAAM,GAC7C7sB,EAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GACxBA,EAAG,MAAMA,EAAG,gBAAgB,GAE5BA,EAAG,WAAW,KAAK,YAAY,GAC/BA,EAAG,gBAAgB,KAAK,QAAQ,GAChCA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,YAAY,GAC/CA,EAAG,UAAU,KAAK,oBAAoB,CAAC,GACvCA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,eAAe,GAClDA,EAAG,UAAU,KAAK,uBAAuB,CAAC,GAC1CA,EAAG,UAAU,KAAK,eAAe6sB,EAAO,OAAO,GAC/C7sB,EAAG,UAAU,KAAK,cAAc6sB,EAAO,UAAU,IAAK,GACtD7sB,EAAG,UAAU,KAAK,YAAY6sB,EAAO,QAAQ,GAAG,GAChD7sB,EAAG,UAAU,KAAK,aAAa6sB,EAAO,SAAS,CAAG,GAClD7sB,EAAG,UAAU,KAAK,YAAY6sB,EAAO,QAAQ,CAAC,GAC9C7sB,EAAG,UAAU,KAAK,eAAe6sB,EAAO,WAAW,CAAC,GACpD7sB,EAAG,UAAU,KAAK,kBAAkB6sB,EAAO,OAAOA,EAAO,MAAM,GAC/D7sB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC,GACrCA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,MAAA,GAEI;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,UAAMA,IAAK,KAAK;AAChB,IAAAA,EAAG,cAAc,KAAK,YAAY,GAClCA,EAAG,cAAc,KAAK,eAAe,GACrCA,EAAG,kBAAkB,KAAK,WAAW,GACrCA,EAAG,aAAa,KAAK,WAAW,GAChCA,EAAG,aAAa,KAAK,UAAU,GAC/BA,EAAG,kBAAkB,KAAK,QAAQ,GAClCA,EAAG,kBAAkB,KAAK,QAAQ,GAClCA,EAAG,cAAc,KAAK,YAAY,GAClCA,EAAG,cAAc,KAAK,YAAY,GAClC,KAAK,OAAO,QAAQ,GACpB,KAAK,OAAO,SAAS;AAAA,EACvB;AAAA,EAEQ,iBAAiBsB,GAAeC,GAAsB;AAC5D,UAAM03B,IAAY,KAAK,IAAI,GAAG,KAAK,MAAM33B,CAAK,CAAC,GACzC43B,IAAa,KAAK,IAAI,GAAG,KAAK,MAAM33B,CAAM,CAAC;AACjD,IAAI,KAAK,OAAO,UAAU03B,MACxB,KAAK,OAAO,QAAQA,IAElB,KAAK,OAAO,WAAWC,MACzB,KAAK,OAAO,SAASA;AAGvB,UAAMl5B,IAAK,KAAK;AAChB,IAAAA,EAAG,YAAYA,EAAG,YAAY,KAAK,YAAY,GAC/CA,EAAG;AAAA,MACDA,EAAG;AAAA,MACH;AAAA,MACA,KAAK;AAAA,MACLi5B;AAAA,MACAC;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAEFl5B,EAAG,gBAAgBA,EAAG,aAAa,KAAK,WAAW,GACnDA,EAAG,qBAAqBA,EAAG,aAAaA,EAAG,mBAAmBA,EAAG,YAAY,KAAK,cAAc,CAAC;AACjG,UAAMm5B,IAAoBn5B,EAAG,uBAAuBA,EAAG,WAAW;AAElE,QADAA,EAAG,gBAAgBA,EAAG,aAAa,IAAI,GACnCm5B,MAAsBn5B,EAAG;AAC3B,YAAM,IAAI,MAAM,mCAAmCm5B,CAAiB,EAAE;AAAA,EAE1E;AAAA,EAEQ,sBAAsB/b,GAAiC;AAC7D,UAAMgc,IAAUhc,EAAO,KAAK,GAAG;AAC/B,QAAI,KAAK,gBAAgBgc,EAAS;AAElC,UAAMr4B,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAAA,EAAO,QAAQ,KACfA,EAAO,SAAS;AAChB,UAAM4kB,IAAM5kB,EAAO,WAAW,IAAI;AAClC,QAAI,CAAC4kB;AACH,YAAM,IAAI,MAAM,2CAA2C;AAG7D,UAAM0T,IAAW1T,EAAI,qBAAqB,GAAG,GAAG,KAAK,CAAC,GAChD2T,IAAQlc,EAAO,SAAS,IAAIA,IAAS,CAAC,aAAa,WAAW,WAAW,WAAW,WAAW,SAAS,GACxGnI,IAAO,IAAI,KAAK,IAAI,GAAGqkB,EAAM,SAAS,CAAC;AAC7C,aAASznB,IAAQ,GAAGA,IAAQynB,EAAM,QAAQznB,KAAS;AACjD,MAAAwnB,EAAS,aAAaxnB,IAAQoD,GAAMqkB,EAAMznB,CAAK,CAAC;AAElD,IAAA8T,EAAI,UAAU,GAAG,GAAG,KAAK,CAAC,GAC1BA,EAAI,YAAY0T,GAChB1T,EAAI,SAAS,GAAG,GAAG,KAAK,CAAC;AAEzB,UAAM4T,IAAS5T,EAAI,aAAa,GAAG,GAAG,KAAK,CAAC,EAAE,MACxC3lB,IAAK,KAAK;AAChB,IAAAA,EAAG,YAAYA,EAAG,YAAY,KAAK,eAAe,GAClDA,EAAG,WAAWA,EAAG,YAAY,GAAGA,EAAG,MAAM,KAAK,GAAG,GAAGA,EAAG,MAAMA,EAAG,eAAeu5B,CAAM,GACrFv5B,EAAG,YAAYA,EAAG,YAAY,IAAI,GAElC,KAAK,cAAco5B;AAAA,EACrB;AAAA,EAEQ,gBAAgBI,GAAyBC,GAAuBC,GAAqB;AAC3F,UAAM15B,IAAK,KAAK,IACV25B,IAAiBD,IAAQ,GACzBE,IAAQD,IAAiB;AAE/B,IAAA35B,EAAG,WAAWA,EAAG,cAAc,KAAK,WAAW,GAC3C05B,IAAQ,KAAK,kBACf15B,EAAG,WAAWA,EAAG,cAAc45B,GAAO55B,EAAG,YAAY,GACrD,KAAK,gBAAgB05B,IAGnBC,IAAiB,KAAK,wBACxB,KAAK,sBAAsBA,GAC3B,KAAK,oBAAoB,IAAI,aAAaA,CAAc;AAE1D,UAAME,IAAc,KAAK;AACzB,QAAI,CAACA;AACH,YAAM,IAAI,MAAM,2CAA2C;AAE7D,aAAShoB,IAAQ,GAAGA,IAAQ6nB,GAAO7nB,KAAS,GAAG;AAC7C,YAAMioB,IAAejoB,IAAQ,GACvBkoB,IAAeloB,IAAQ;AAC7B,MAAAgoB,EAAYE,CAAY,IAAIP,EAAUM,CAAY,KAAK,GACvDD,EAAYE,IAAe,CAAC,IAAIP,EAAUM,IAAe,CAAC,KAAK,GAC/DD,EAAYE,IAAe,CAAC,IAAIN,EAAQ5nB,CAAK,KAAK;AAAA,IACpD;AACA,IAAA7R,EAAG,cAAcA,EAAG,cAAc,GAAG65B,EAAY,SAAS,GAAGF,CAAc,CAAC,GAC5E35B,EAAG,WAAWA,EAAG,cAAc,IAAI;AAAA,EACrC;AACF;AChTA,MAAMg6B,KAAkB,gCAClBC,KAAmB,CAAC,aAAa,WAAW,WAAW,WAAW,WAAW,SAAS,GACtFC,KAAiB,GACjBC,KAAe,GACfC,KAAkB,KAClBC,KAA8B,MAC9BC,KAA6C,UAC7CC,KAA2B,KAC3BC,KAAkB,KAClBC,KAAkB,MAClBC,KAAsB,KACtBC,KAAoB,KACpBC,KAAqB,KACrBC,KAAqB,KAAK,OAC1BC,KAA4B,MAC5BC,KAA2B,KAC3BC,KAAuB;AAG7B,SAASC,GAAsBC,GAAiBh7B,GAAgC;AAC9E,SAAOA,EAAO,cAAc,KAAK,KAAK,KAAK,IAAI,MAAMg7B,CAAO,CAAC;AAC/D;AAEA,SAASC,GAAiClJ,GAAwB/xB,GAAgC;AAChG,SAAO,KAAK,IAAI,MAAM,MAAM+xB,IAAiB/xB,EAAO,YAAY;AAClE;AAEA,SAASk7B,GAAmBF,GAAiBh7B,GAAwBm7B,GAA+B;AAClG,MAAI,CAAC,OAAO,SAASA,CAAa,KAAK,KAAK,IAAIA,CAAa,IAAI;AAC/D,WAAO,KAAK,IAAI,MAAMH,CAAO;AAE/B,QAAMI,IAAcL,GAAsBC,GAASh7B,CAAM,IAAIm7B;AAC7D,SAAOF,GAAiCG,GAAap7B,CAAM;AAC7D;AAEA,SAASq7B,GAA0BF,GAA+B;AAChE,SAAI,CAAC,OAAO,SAASA,CAAa,KAAK,KAAK,IAAIA,CAAa,IAAI,OACxD,IAEF,KAAK,MAAOA,IAAgB,MAAO,KAAK,IAAI,MAAM,KAAK,KAAKR,EAAkB,CAAC,CAAC;AACzF;AAEA,SAASW,GAA6BC,GAAiC;AACrE,QAAMC,IAAW5gB,EAAM2gB,GAAiB,GAAGT,EAAoB;AAC/D,SAAOlgB,EAAM,OAAO,KAAK,KAAK,KAAK,IAAI,GAAG4gB,CAAQ,CAAC,IAAI,MAAM,MAAM,CAAC;AACtE;AAEA,SAASC,GAAyBC,GAA2B;AAC3D,QAAMlC,IAAQ,KAAK,IAAI,GAAGkC,CAAS;AACnC,SAAIlC,KAAS,IAAU,OACnBA,KAAS,IAAU,MACnBA,KAAS,IAAU,OACnBA,KAAS,IAAU,MACnBA,KAAS,KAAW,OACjB;AACT;AAEA,SAASmC,GAAqBJ,GAAiC;AAG7D,SAAO,QAFU3gB,EAAM2gB,GAAiB,GAAGT,EAAoB,IAC1CA,KACF;AACrB;AAEA,SAASc,GAAmBL,GAAiC;AAC3D,QAAMC,IAAW5gB,EAAM2gB,GAAiB,GAAGT,EAAoB;AAC/D,SAAO,OAAO,KAAK,IAAI,KAAK,IAAI,GAAGU,CAAQ,GAAG,IAAI,IAAI,OAAO,KAAK,KAAKA,IAAW,CAAC,IAAI;AACzF;AAEA,SAASK,GAAoBN,GAAiC;AAC5D,SAAOD,GAA6BC,CAAe;AACrD;AAEA,SAASO,GAAmBP,GAAiC;AAE3D,QAAMxd,IADWnD,EAAM2gB,GAAiB,GAAGT,EAAoB,IAC1CA;AACrB,SAAOlgB,EAAM,OAAOmD,IAAI,MAAM,MAAM,IAAI;AAC1C;AAEA,SAASge,GAAsBR,GAAyBP,GAAiBh7B,GAAgC;AAEvG,QAAMg8B,IADWphB,EAAM2gB,GAAiB,GAAGT,EAAoB,IAClCA,IACvB/I,IAAiBgJ,GAAsBC,GAASh7B,CAAM,GACtDi8B,IAAYj8B,EAAO,cAAc,KACjCk8B,IAAUl8B,EAAO,cAAc,MAC/Bm8B,IAAQvhB,GAAOmX,IAAiBkK,KAAa,KAAK,IAAI,MAAMC,IAAUD,CAAS,GAAG,GAAG,CAAC,GACtFG,IAAc,OAAO,KAAK,IAAIJ,GAAW,IAAI,IAAI,MACjDK,IAAc,IAAIF,KAAS,OAAOH,IAAY;AACpD,SAAOI,IAAcC;AACvB;AAEA,SAASC,GAA+BC,GAAgBC,GAAgCjB,GAAiC;AAEvH,QAAMkB,IAAa,KAAK,IAAI,GAAGF,CAAM,GAC/BG,IAAgB,KAAK,IAAI,MAAMF,CAAsB,GACrDxjB,IAAa,KAAK,MAAMyjB,CAAU,IAAI,KAAK,MAAMC,CAAa;AACpE,SAAO9hB,EAAM5B,GAAY,GAAG,CAAC;AAC/B;AAEA,SAAS2jB,GAA+BpB,GAAiC;AAEvE,SAAOV;AACT;AAEA,SAAS+B,GAAgCC,GAA+BtB,GAAiC;AACvG,MAAIsB,EAAM,WAAW,EAAG,QAAO;AAE/B,QAAMC,IAAc,KAAK,IAAID,EAAM,QAAQjC,EAAyB,GAC9DmC,IAAiB,IAAI,MAAcD,CAAW;AACpD,MAAIE,IAAY;AAEhB,WAASC,IAAc,GAAGA,IAAcH,GAAaG,KAAe,GAAG;AACrE,UAAMC,IAAY,KAAK;AAAA,MACrBL,EAAM,SAAS;AAAA,MACf,KAAK,OAAQI,IAAc,OAAOJ,EAAM,SAAUC,CAAW;AAAA,IAAA,GAEzDP,IAAS,KAAK,IAAI,GAAGM,EAAMK,CAAS,GAAG,UAAU,CAAC;AACxD,IAAAH,EAAeE,CAAW,IAAIV,GAC1BA,IAASS,MAAWA,IAAYT;AAAA,EACtC;AAEA,WAASW,IAAY,GAAGA,IAAYL,EAAM,QAAQK,KAAa,GAAG;AAChE,UAAMX,IAAS,KAAK,IAAI,GAAGM,EAAMK,CAAS,GAAG,UAAU,CAAC;AACxD,IAAIX,IAASS,MAAWA,IAAYT;AAAA,EACtC;AAEA,EAAAQ,EAAe,KAAK,CAAC5Q,GAAMgR,MAAUhR,IAAOgR,CAAK;AACjD,QAAMC,IAAaT,GAA8C,GAC3DU,IAAkB,KAAK,IAAI,GAAG,KAAK;AAAA,IACvCN,EAAe,SAAS;AAAA,IACxB,KAAK,OAAOA,EAAe,SAAS,KAAKK,CAAU;AAAA,EAAA,CACpD,GACKE,IAAmBP,EAAeM,CAAe,KAAKL;AAG5D,SAAO,KAAK,IAAI,GAAG,KAAK,IAAIA,GAAW,KAAK,IAAIM,IADjC,MAC4DN,IAFxD,IAE8E,CAAC,CAAC;AACrG;AAEA,SAASO,GAA8BvC,GAAiBh7B,GAAwBm7B,GAA+B;AAE7G,QAAMpJ,IAAiBgJ,GAAsBC,GAASh7B,CAAM,GACtDw9B,IAAYx9B,EAAO,cAAc,MACjCy9B,IAAUz9B,EAAO,cAAc,KAC/B09B,IACJ3L,KAAkByL,IAAY,IAC9BzL,KAAkB0L,IAAU,KAC3B,MAAM;AACL,UAAM1f,IAAInD,GAAOmX,IAAiByL,KAAa,KAAK,IAAI,MAAMC,IAAUD,CAAS,GAAG,GAAG,CAAC;AAExF,WAAO,IADQzf,IAAIA,KAAK,IAAI,IAAIA;AAAA,EAElC,GAAA;AACF,SAAOnD,EAAM8iB,GAAc,GAAG,CAAC;AACjC;AAEA,SAASC,GAAyBC,GAAmC;AACnE,MAAIA,KAAqB,EAAG,QAAO;AACnC,QAAMC,IAAkB,IAAI,KAAK,IAAID,GAAmB,IAAI;AAC5D,SAAO,IAAI,KAAK,KAAKC,CAAe,IAAI;AAC1C;AAEA,SAASC,GAAmB18B,GAAeC,GAAgB08B,GAAyB/C,GAAyB;AAC3G,QAAMgD,IAAc,KAAK,IAAI,GAAG58B,GAAOC,CAAM,GACvC48B,IAAc,OAAO,SAAW,MAAc,IAAIrjB,EAAM,OAAO,oBAAoB,GAAG,GAAG,GAAG,GAC5FsjB,IACJlD,KAAW,OAAO,OAClBA,KAAW,OAAO,OAClBA,KAAW,MAAM,OACjB,GACImD,IACJJ,IAAkB,OAAS,MAC3BA,IAAkB,MAAQ,OAC1BA,IAAkB,MAAQ,OAC1BxD,IACI6D,IAAW9D,KAAkB0D,GAC7BK,IAAW9D,KAAkByD;AACnC,SAAOpjB,EAAOujB,IAAgBF,IAAcC,IAAgBF,GAAaI,GAAUC,CAAQ;AAC7F;AAEA,SAASC,GAAmB3R,GAQV;AAChB,QAAM4R,IAAe5R,EAAO,gBAAgBmR,GAAmBnR,EAAO,cAAcA,EAAO,eAAeA,EAAO,iBAAiBA,EAAO,OAAO,GAC1I6R,IAAc,KAAK,IAAIlE,IAAiB,KAAK,IAAIC,IAAiB,KAAK,MAAM5N,EAAO,eAAe4R,CAAY,CAAC,CAAC,GACjHE,IAAe,KAAK,IAAInE,IAAiB,KAAK,IAAIC,IAAiB,KAAK,MAAM5N,EAAO,gBAAgB4R,CAAY,CAAC,CAAC,GACnHG,IAAeF,IAAc,KAAK,IAAI,GAAG7R,EAAO,YAAY,GAC5DgS,IAAeF,IAAe,KAAK,IAAI,GAAG9R,EAAO,aAAa,GAC9DiS,IAAiB,KAAK,IAAIF,GAAcC,CAAY,GACpD3D,IAAU,KAAK,IAAI,MAAMrO,EAAO,OAAO,GACvCkS,IAAiB,KAAK,IAAI,MAAMlS,EAAO,SAAS6N,KAAsBoE,CAAc,GACpFE,IAAe,KAAK,IAAI,KAAKnS,EAAO,OAAO8N,KAAoBmE,CAAc,GAC7EG,KAAoBF,IAAiBC,KAAgB,KAAK,IAAI,MAAM9D,IAAU4D,CAAc,GAC5FI,IAAuB,KAAK;AAAA,IAChCD,IAAmB;AAAA,IACnB,OAAO,KAAK,IAAI,MAAM/D,IAAU4D,CAAc;AAAA,EAAA;AAGhD,SAAO;AAAA,IACL,cAAAL;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC;AAAA,IACA,cAAAC;AAAA,IACA,cAAAC;AAAA,IACA,SAAA3D;AAAA,IACA,gBAAA6D;AAAA,IACA,cAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,sBAAAC;AAAA,EAAA;AAEJ;AAEA,SAASC,GAAkBC,GAAuC;AAChE,MAAI,CAACA,EAAM,QAAO;AAClB,QAAMC,IAAgB,KAAK,MAAMD,EAAK,UAAU,SAAS,CAAC,GACpDE,IAAcF,EAAK,UAAUA,EAAK,QAAQ,SAAS,OAAO;AAChE,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAMA,EAAK,KAAK,GAAGC,GAAeC,CAAW,CAAC;AACjF;AAEA,SAASC,GAAehnB,GAAeinB,GAAsB;AAC3D,QAAMtmB,IAAa,OAAO,SAASX,CAAK,IAAI,KAAK,MAAMA,IAAQ,IAAI,IAAI;AACvE,SAAO,KAAK,KAAKinB,IAAOtmB,GAAY,QAAS,MAAM;AACrD;AAEA,SAASumB,GAAYr5B,GAAWD,GAAWq5B,IAAO,YAAoB;AACpE,MAAIE,IAAO,KAAK,KAAKF,KAAQp5B,IAAI,IAAI,UAAU,MAAM;AACrD,SAAAs5B,IAAO,KAAK,KAAKA,KAAQv5B,IAAI,IAAI,UAAU,MAAM,GACjDu5B,KAAQA,MAAS,IACVA,MAAS;AAClB;AAEA,SAASC,GAAgBD,GAAsB;AAC7C,UAAQA,MAAS,KAAK;AACxB;AAiBA,SAASE,GAAahlB,GAAiD;AACrE,MAAI8kB,IAAO;AACX,WAASG,IAAe,GAAGA,IAAejlB,EAAS,QAAQilB,KAAgB,GAAG;AAC5E,UAAMpnB,IAAUmC,EAASilB,CAAY;AACrC,IAAAH,IAAO,KAAK,KAAKA,IAAOjnB,EAAQ,MAAM,QAAQ,QAAU,MAAM;AAC9D,aAASqnB,IAAa,GAAGA,IAAarnB,EAAQ,MAAM,QAAQqnB,KAAc,GAAG;AAC3E,YAAM91B,IAAQyO,EAAQ,MAAMqnB,CAAU;AACtC,MAAAJ,IAAOH,GAAev1B,EAAM,CAAC,GAAG01B,CAAI,GACpCA,IAAOH,GAAev1B,EAAM,CAAC,GAAG01B,CAAI;AAAA,IACtC;AACA,IAAAA,IAAO,KAAK,KAAKA,IAAOjnB,EAAQ,MAAM,QAAQ,QAAU,MAAM;AAC9D,aAASsnB,IAAY,GAAGA,IAAYtnB,EAAQ,MAAM,QAAQsnB,KAAa,GAAG;AACxE,YAAMrlB,IAAOjC,EAAQ,MAAMsnB,CAAS;AACpC,MAAAL,IAAO,KAAK,KAAKA,IAAOhlB,EAAK,QAAQ,QAAU,MAAM;AACrD,eAASolB,IAAa,GAAGA,IAAaplB,EAAK,QAAQolB,KAAc,GAAG;AAClE,cAAM91B,IAAQ0Q,EAAKolB,CAAU;AAC7B,QAAAJ,IAAOH,GAAev1B,EAAM,CAAC,GAAG01B,CAAI,GACpCA,IAAOH,GAAev1B,EAAM,CAAC,GAAG01B,CAAI;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,GAAG9kB,EAAS,MAAM,IAAI8kB,MAAS,CAAC;AACzC;AAEA,SAASM,GACPvjB,GACA2iB,GACAa,GACS;AACT,SAAIxjB,EAAM,YAAY2iB,KAAQ3iB,EAAM,YAAYwjB,IACvC,KAEJb,IACE3iB,EAAM,YAAYwjB,KACvBxjB,EAAM,eAAe0iB,GAAkBC,CAAI,KAC3C3iB,EAAM,iBAAiB2iB,EAAK,aAC5B3iB,EAAM,eAAe2iB,EAAK,UAJV;AAKpB;AAEA,SAASc,GAAgBd,GAA+Be,GAA6CF,GAAiB//B,GAAyD;AAC7K,QAAMkgC,IAAajB,GAAkBC,CAAI;AACzC,MAAI,CAACA,KAAQgB,KAAc;AACzB,WAAO;AAGT,MAAIC,IAAK,IAAI,aAAaD,CAAU,GAChCE,IAAK,IAAI,aAAaF,CAAU,GAChCG,IAAK,IAAI,aAAaH,CAAU,GAChCI,IAAgB,GAChBnmB,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AAEX,WAAS3I,IAAQ,GAAGA,IAAQuuB,GAAYvuB,KAAS,GAAG;AAClD,UAAMzP,IAASg9B,EAAK,UAAUvtB,IAAQ,CAAC,GACjCxP,IAAS+8B,EAAK,UAAUvtB,IAAQ,IAAI,CAAC;AAE3C,QADI,CAAC,OAAO,SAASzP,CAAM,KAAK,CAAC,OAAO,SAASC,CAAM,KACnD89B,EAAa,SAAS,KAAK,CAACxlB,GAA0BvY,GAAQC,GAAQ89B,CAAY,EAAG;AAEzF,UAAMM,IAAYrB,EAAK,UAAUvtB,CAAK,GAChC4qB,IAAS,OAAOgE,KAAc,YAAY,OAAO,SAASA,CAAS,IAAI,KAAK,IAAI,GAAGA,CAAS,IAAI;AACtG,IAAIhE,KAAU,MAEd4D,EAAGG,CAAa,IAAIp+B,GACpBk+B,EAAGE,CAAa,IAAIn+B,GACpBk+B,EAAGC,CAAa,IAAI/D,GACpB+D,KAAiB,GACbp+B,IAASiY,MAAMA,IAAOjY,IACtBA,IAASmY,MAAMA,IAAOnY,IACtBC,IAASiY,MAAMA,IAAOjY,IACtBA,IAASmY,MAAMA,IAAOnY;AAAA,EAC5B;AAEA,MAAIm+B,MAAkB,KAAK,CAAC,OAAO,SAASnmB,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI;AAC5H,WAAO;AAGT,EAAIgmB,IAAgBJ,MAClBC,IAAKA,EAAG,MAAM,GAAGG,CAAa,GAC9BF,IAAKA,EAAG,MAAM,GAAGE,CAAa,GAC9BD,IAAKA,EAAG,MAAM,GAAGC,CAAa;AAGhC,QAAME,IAAoG,CAAA;AAC1G,WAAS7uB,IAAQ,GAAGA,IAAQ2uB,GAAe3uB,KAAS,GAAG;AACrD,UAAMzL,IAAIi6B,EAAGxuB,CAAK,GACZ1L,IAAIm6B,EAAGzuB,CAAK;AAClB,IAAA6uB,EAAgB,KAAK;AAAA,MACnB,MAAMt6B;AAAA,MACN,MAAMD;AAAA,MACN,MAAMC;AAAA,MACN,MAAMD;AAAA,MACN,OAAO0L;AAAA,IAAA,CACR;AAAA,EACH;AACA,QAAMiuB,IAAa1I,GAA2B,EAAE;AAChD,EAAA0I,EAAW,KAAKY,CAAe;AAE/B,QAAMC,IAAe,KAAK;AAAA,IACxBzgC,GAAQ,SAAS;AAAA,IACjBA,GAAQ,UAAU;AAAA,IAClBqa,IAAOF;AAAA,IACPG,IAAOF;AAAA,IACP;AAAA,EAAA,GAGIsmB,IAAsB,CAAA;AAC5B,MAAIC,IAAW,KACXC,IAAQ;AACZ,SAAOD,KAAYF,KAAgBG,IAAQ;AACzC,IAAAF,EAAU,KAAKC,CAAQ,GACvBA,KAAYhG,IACZiG,KAAS;AAEX,SAAIF,EAAU,WAAW,KACvBA,EAAU,KAAK,CAAC,GAGX;AAAA,IACL,SAASxB;AAAA,IACT,WAAWl/B;AAAA,IACX,cAAck/B,EAAK;AAAA,IACnB,YAAYA,EAAK;AAAA,IACjB,YAAYgB;AAAA,IACZ,SAASD;AAAA,IACT,SAAAF;AAAA,IACA,YAAYO;AAAA,IACZ,IAAAH;AAAA,IACA,IAAAC;AAAA,IACA,IAAAC;AAAA,IACA,YAAAT;AAAA,IACA,WAAAc;AAAA,IACA,QAAQ,MAAM,KAAK,EAAE,QAAQA,EAAU,OAAA,GAAU,MAAM,IAAI;AAAA,EAAA;AAE/D;AA4MA,SAASG,GAA2BC,GAA+BC,GAA8ChC,GAAoC;AACnJ,QAAMiC,IAAOF,EAAW,WAAW,OAAO;AAAA,IACxCC,EAAW,CAAC,IAAIhC;AAAA,IAChBgC,EAAW,CAAC,IAAIhC;AAAA,IAChBgC,EAAW,CAAC,IAAIhC;AAAA,IAChBgC,EAAW,CAAC,IAAIhC;AAAA,EAAA,CACjB,GACKkC,IAAU,IAAI,MAAcD,EAAK,MAAM;AAC7C,MAAIxH,IAAQ;AACZ,WAAS7nB,IAAQ,GAAGA,IAAQqvB,EAAK,QAAQrvB,KAAS,GAAG;AACnD,UAAMuvB,IAAMF,EAAKrvB,CAAK;AACtB,IAAKuvB,MACLD,EAAQzH,CAAK,IAAI0H,EAAI,OACrB1H,KAAS;AAAA,EACX;AACA,SAAAyH,EAAQ,SAASzH,GACVyH;AACT;AAEA,SAASE,GAAyBC,GAA2BC,GAAmC;AAC9F,QAAMC,IAAS,KAAK,IAAI5G,IAAoB2G,CAAiB;AAC7D,SAAID,KAAqBE,IAAe,IACjC1mB,EAAM0mB,IAAS,KAAK,IAAI,GAAGF,CAAiB,GAAG,IAAI,OAAO,CAAC;AACpE;AAEA,SAASG,GAAoB3D,GAAmC;AAC9D,SAAIA,KAAqB,IAAU,IAC5B,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,KAAK,IAAI,MAAMA,CAAiB,CAAC,CAAC;AACtE;AAEA,SAAS4D,GAAiB5B,GAAoBhC,GAAoC;AAChF,MAAIA,KAAqB,EAAG,QAAO;AACnC,QAAM6D,IAAalC,GAAYK,GAAY,YAAY,UAAU;AACjE,SAAOH,GAAgBgC,CAAU,KAAK7mB,EAAMgjB,GAAmB,GAAG,CAAC;AACrE;AAEA,SAAS8D,GAAkBC,GAAkBC,GAA6BpD,GAAqBC,GAA8B;AAC3H,QAAMoD,IAAa,KAAK,IAAI,GAAGrD,IAAcC,CAAY,GACnDqD,IAAa,KAAK,KAAKF,IAAsBA,GAC7CG,IAAY,KAAK,IAAI,GAAGJ,CAAQ,IAAIG,IAAcD;AACxD,SAAOjnB,EAAM,QAAQ,KAAK,KAAK,KAAK,IAAI,GAAGmnB,CAAQ,CAAC,GAAG,OAAO,KAAK;AACrE;AAEA,SAASC,GAAmBC,GAAuBC,GAAmBC,GAAoBC,GAA4B;AACpH,MAAI,CAAC,OAAO,SAASH,CAAa,KAAKA,KAAiB;AACtD,WAAOC;AAET,QAAMG,IAASH,KAAaD,IAAgBE,IAAaC;AACzD,SAAOH,KAAiBC,IAAYD,KAAiBrnB,EAAMynB,GAAQ,GAAG,CAAC;AACzE;AAYA,SAASC,GAAiBC,GAAsD;AAC9E,MAAIA,EAAQ,UAAU;AACpB,WAAOA,EAAQ;AAEjB,MAAI,OAAO,WAAa;AACtB,WAAAA,EAAQ,QAAQ,MACT;AAET,MAAI;AACF,IAAAA,EAAQ,QAAQ,IAAIhL,GAAA;AAAA,EACtB,SAASnzB,GAAO;AACd,QAAI,CAACm+B,EAAQ,sBAAsB,OAAO,UAAY,OAAe,OAAO,QAAQ,QAAS,YAAY;AACvG,YAAMC,IAASp+B,aAAiB,QAAQA,EAAM,UAAU,OAAOA,CAAK;AACpE,cAAQ,KAAK,oFAAoFo+B,CAAM,EAAE,GACzGD,EAAQ,qBAAqB;AAAA,IAC/B;AACA,IAAAA,EAAQ,QAAQ;AAAA,EAClB;AACA,SAAOA,EAAQ;AACjB;AAEA,SAASE,GAAgBC,GAAsF/yB,GAAuD;AACpK,QAAM+I,IAA0B,CAAA;AAChC,WAAS/G,IAAQ,GAAGA,IAAQhC,EAAK,QAAQgC,KAAS,GAAG;AACnD,UAAM7H,IAAQ6F,EAAKgC,CAAK;AACxB,QAAI,CAAC7H,EAAO;AACZ,UAAM64B,IAAYD,EAAS,cAAc54B,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAC3D,QAAI,CAAC,MAAM,QAAQ64B,CAAS,KAAKA,EAAU,SAAS,EAAG;AACvD,UAAMz8B,IAAI,OAAOy8B,EAAU,CAAC,CAAC,GACvB18B,IAAI,OAAO08B,EAAU,CAAC,CAAC;AAC7B,IAAI,CAAC,OAAO,SAASz8B,CAAC,KAAK,CAAC,OAAO,SAASD,CAAC,KAC7CyS,EAAI,KAAK,CAACxS,GAAGD,CAAC,CAAC;AAAA,EACjB;AACA,SAAOyS;AACT;AAEA,SAASkqB,GAAcnd,GAA+Bid,GAAsFhoB,GAA+C;AACzL,MAAIA,EAAS,WAAW,GACxB;AAAA,IAAA+K,EAAI,UAAA;AACJ,aAAS9T,IAAQ,GAAGA,IAAQ+I,EAAS,QAAQ/I,KAAS,GAAG;AACvD,YAAM4G,IAAUmC,EAAS/I,CAAK,GACxBuI,IAAQuoB,GAAgBC,GAAUnqB,EAAQ,KAAK;AACrD,MAAI2B,EAAM,UAAU,KAClBsL,GAAUC,GAAKvL,GAAO,EAAI;AAE5B,eAAS2lB,IAAY,GAAGA,IAAYtnB,EAAQ,MAAM,QAAQsnB,KAAa,GAAG;AACxE,cAAMrlB,IAAOioB,GAAgBC,GAAUnqB,EAAQ,MAAMsnB,CAAS,CAAE;AAChE,QAAIrlB,EAAK,UAAU,KACjBgL,GAAUC,GAAKjL,GAAM,EAAI;AAAA,MAE7B;AAAA,IACF;AACA,IAAAiL,EAAI,KAAK,SAAS;AAAA;AACpB;AAEA,SAASod,GAAiBN,GAAyBrD,GAA+Be,GAA6CF,GAAiB//B,GAAyD;AACvM,QAAMmf,IAAUojB,EAAQ;AACxB,SAAIpjB,KAAWA,EAAQ,cAAcnf,KAAU8/B,GAAmB3gB,GAAS+f,GAAMa,CAAO,IAC/E5gB,KAETojB,EAAQ,aAAavC,GAAgBd,GAAMe,GAAcF,GAAS//B,CAAM,GACxEuiC,EAAQ,aAAa,MACrBA,EAAQ,mBAAmB,IACpBA,EAAQ;AACjB;AAEA,SAASO,GAAgBnW,GAaI;AAC3B,QAAM,EAAE,YAAAmU,GAAY,UAAA4B,GAAU,QAAA1iC,GAAQ,cAAA+iC,GAAc,eAAAC,GAAe,QAAAnlB,GAAQ,MAAAolB,GAAM,WAAAC,GAAW,mBAAA7B,EAAA,IAAsB1U,GAE5GwW,IAAiB,KAAK,IAAI,MAAMT,EAAS,aAAA,EAAe,IAAI,GAC5DU,IAAgBF,KAAanI,GAAsBoI,GAAgBnjC,CAAM,GACzEqjC,IAAmBpI,GAAiCmI,GAAepjC,CAAM,GACzEsjC,IAAQhF,GAAmB;AAAA,IAC/B,cAAAyE;AAAA,IACA,eAAAC;AAAA,IACA,iBAAiBlC,EAAW;AAAA,IAC5B,SAASuC;AAAA,IACT,QAAAxlB;AAAA,IACA,MAAAolB;AAAA,EAAA,CACD,GACKlC,IAAa2B,EAAS,cAAA,GACtBa,IAAsB1C,GAA2BC,GAAYC,GAAYuC,EAAM,gBAAgB,GAC/F1F,IAAoBuD,GAAyBoC,EAAoB,QAAQlC,CAAiB,GAC1FmC,IAAejC,GAAoB3D,CAAiB,GACpDgB,IAAiB,KAAK,IAAI0E,EAAM,cAAcA,EAAM,YAAY;AAEtE,SAAO;AAAA,IACL,SAASxC,EAAW;AAAA,IACpB,cAAcA,EAAW;AAAA,IACzB,YAAYA,EAAW;AAAA,IACvB,YAAYA,EAAW;AAAA,IACvB,SAASA,EAAW;AAAA,IACpB,SAASA,EAAW;AAAA,IACpB,eAAAsC;AAAA,IACA,kBAAAC;AAAA,IACA,cAAcC,EAAM;AAAA,IACpB,mBAAmBA,EAAM,iBAAiB,KAAK,IAAI,MAAMD,IAAmBzE,CAAc;AAAA,IAC1F,iBAAiB0E,EAAM,eAAe,KAAK,IAAI,MAAMD,IAAmBzE,CAAc;AAAA,IACtF,mBAAAhB;AAAA,IACA,cAAA4F;AAAA,IACA,YAAY9B,GAAkB6B,EAAoB,QAAQD,EAAM,iBAAiBA,EAAM,cAAcA,EAAM,aAAaA,EAAM,YAAY;AAAA,EAAA;AAE9I;AAiHA,SAASG,GAAuB9W,GAkBrB;AACT,QAAM;AAAA,IACJ,KAAAlH;AAAA,IACA,SAAA8c;AAAA,IACA,UAAAG;AAAA,IACA,QAAA1iC;AAAA,IACA,cAAA+iC;AAAA,IACA,eAAAC;AAAA,IACA,OAAAM;AAAA,IACA,YAAAxC;AAAA,IACA,qBAAAyC;AAAA,IACA,mBAAA3F;AAAA,IACA,cAAA4F;AAAA,IACA,YAAAE;AAAA,IACA,UAAAvK;AAAA,IACA,SAAAwK;AAAA,IACA,iBAAApI;AAAA,IACA,iBAAAqI;AAAA,IACA,cAAA3D;AAAA,EAAA,IACEtT,GACEkX,IAAQvB,GAAiBC,CAAO;AACtC,MAAI,CAACsB,KAASN,EAAoB,WAAW;AAC3C,WAAO;AAGT,QAAMO,IAAiB,KAAK;AAAA,IAC1BP,EAAoB;AAAA,IACpB,KAAK,IAAI,IAAI,KAAK,KAAKA,EAAoB,SAAS,KAAK,IAAI,GAAG3F,IAAoB,IAAI,CAAC,CAAC;AAAA,EAAA;AAE5F,EAAIkG,IAAiBvB,EAAQ,kBAC3BA,EAAQ,gBAAgBuB,GACxBvB,EAAQ,iBAAiB,IAAI,aAAauB,IAAiB,CAAC,GAC5DvB,EAAQ,eAAe,IAAI,aAAauB,CAAc;AAExD,QAAMxK,IAAYiJ,EAAQ,gBACpBhJ,IAAUgJ,EAAQ;AACxB,MAAI,CAACjJ,KAAa,CAACC;AACjB,WAAO;AAGT,QAAMwK,IAAgBT,EAAM,iBAAiBA,EAAM,cAC7CU,IAAoBrG,GAAyBC,CAAiB;AACpE,MAAIqG,IAAY;AAEhB,WAASC,IAAe,GAAGA,IAAeX,EAAoB,QAAQW,KAAgB,GAAG;AACvF,UAAMtE,IAAa2D,EAAoBW,CAAY;AACnD,QAAI,CAAC1C,GAAiB5B,GAAYhC,CAAiB,EAAG;AAEtD,UAAM17B,IAAS4+B,EAAW,GAAGlB,CAAU,GACjCz9B,IAAS2+B,EAAW,GAAGlB,CAAU;AACvC,QAAI,CAAC,OAAO,SAAS19B,CAAM,KAAK,CAAC,OAAO,SAASC,CAAM,EAAG;AAE1D,UAAMwgC,IAAYD,EAAS,cAAcxgC,GAAQC,CAAM;AACvD,QAAI,CAAC,MAAM,QAAQwgC,CAAS,KAAKA,EAAU,SAAS,EAAG;AAEvD,UAAMjhC,IAAU,OAAOihC,EAAU,CAAC,CAAC,GAC7BhhC,IAAU,OAAOghC,EAAU,CAAC,CAAC;AACnC,QAAI,CAAC,OAAO,SAASjhC,CAAO,KAAK,CAAC,OAAO,SAASC,CAAO,EAAG;AAE5D,UAAMwiC,KAAUziC,IAAU4hC,EAAM,cAC1Bc,KAAUziC,IAAU2hC,EAAM;AAChC,QACEa,KAAU,CAACJ,KACXK,KAAU,CAACL,KACXI,KAAUb,EAAM,cAAcS,KAC9BK,KAAUd,EAAM,eAAeS;AAE/B;AAGF,UAAMM,KAASJ,IAAY;AAC3B,IAAA3K,EAAU+K,EAAM,IAAIF,IACpB7K,EAAU+K,KAAS,CAAC,IAAID,IACxB7K,EAAQ0K,CAAS,IAAI,KAAK,IAAI,IAAInD,EAAW,GAAGlB,CAAU,KAAK,KAAKoE,CAAiB,GACrFC,KAAa;AAAA,EACf;AAuBA,SArBIA,KAAa,KAqBb,CAjBaJ,EAAM,OAAO;AAAA,IAC5B,OAAOP,EAAM;AAAA,IACb,QAAQA,EAAM;AAAA,IACd,WAAAhK;AAAA,IACA,SAAAC;AAAA,IACA,OAAO0K;AAAA,IACP,gBAAgBX,EAAM;AAAA,IACtB,cAAcA,EAAM;AAAA,IACpB,YAAAI;AAAA,IACA,UAAAvK;AAAA,IACA,SAAAwK;AAAA,IACA,QAAQhI,GAAqBJ,CAAe;AAAA,IAC5C,MAAMK,GAAmBL,CAAe;AAAA,IACxC,OAAOM,GAAoBN,CAAe;AAAA,IAC1C,MAAMO,GAAmBP,CAAe;AAAA,IACxC,SAASQ,GAAsBR,GAAiB+H,EAAM,SAAStjC,CAAM;AAAA,EAAA,CACtE,IAEQ,KAGTylB,EAAI,KAAA,GACAwa,EAAa,SAAS,KACxB2C,GAAcnd,GAAKid,GAAUzC,CAAY,GAEvC2D,MACFne,EAAI,YAAYme,GAChBne,EAAI,SAAS,GAAG,GAAGsd,GAAcC,CAAa,IAEhDvd,EAAI,cAAc,GAClBA,EAAI,wBAAwB,IAC5BA,EAAI,UAAUoe,EAAM,QAAQ,GAAG,GAAGP,EAAM,aAAaA,EAAM,cAAc,GAAG,GAAGP,GAAcC,CAAa,GAC1Gvd,EAAI,QAAA,GAEGwe;AACT;AAEA,SAASK,GAAY3X,GAQQ;AAC3B,QAAM,EAAE,KAAAlH,GAAK,SAAA8c,GAAS,UAAAG,GAAU,QAAA1iC,GAAQ,cAAA+iC,GAAc,eAAAC,GAAe,OAAAzQ,MAAU5F,GACzEmU,IAAa+B,GAAiBN,GAAShQ,EAAM,MAAMA,EAAM,cAAcA,EAAM,SAASvyB,CAAM;AAClG,MAAI,CAAC8gC,KAAcA,EAAW,UAAU,WAAW,KAAKA,EAAW,cAAc;AAC/E,WAAO;AAGT,QAAM9F,IAAU,KAAK,IAAI,MAAM0H,EAAS,aAAA,EAAe,IAAI,GACrD6B,IAAyBhH,GAA8BvC,GAASh7B,GAAQuyB,EAAM,aAAa,GAC3FwO,IAAa2B,EAAS,cAAA;AAC5B,MAAI6B,KAA0B;AAC5B,WAAO;AAAA,MACL,YAAYzD,EAAW;AAAA,MACvB,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,YAAY;AAAA,IAAA;AAIhB,MAAIvO,EAAM,cAAc,cAAc;AACpC,UAAM+Q,IAAQhF,GAAmB;AAAA,MAC/B,cAAAyE;AAAA,MACA,eAAAC;AAAA,MACA,iBAAiBlC,EAAW;AAAA,MAC5B,SAAA9F;AAAA,MACA,QAAQzI,EAAM;AAAA,MACd,MAAMA,EAAM;AAAA,IAAA,CACb,GACKgR,IAAsB1C,GAA2BC,GAAYC,GAAYuC,EAAM,gBAAgB;AACrG,QAAIC,EAAoB,WAAW;AACjC,aAAO;AAAA,QACL,YAAYzC,EAAW;AAAA,QACvB,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,YAAY;AAAA,MAAA;AAIhB,UAAMlD,IAAoBuD,GAAyBoC,EAAoB,QAAQhR,EAAM,iBAAiB,GAChGiR,IAAejC,GAAoB3D,CAAiB,GACpD4G,IAAmB9C;AAAA,MACvB6B,EAAoB;AAAA,MACpBD,EAAM,iBAAiBA,EAAM;AAAA,MAC7BA,EAAM;AAAA,MACNA,EAAM;AAAA,IAAA;AAER,IAAAf,EAAQ,mBAAmB,IAC3BA,EAAQ,4BAA4B,IACpCA,EAAQ,6BAA6B,GACrCA,EAAQ,+BAA+B,GACvCA,EAAQ,mBAAmBP,GAAmBO,EAAQ,kBAAkBiC,GAAkB,MAAM,IAAI,GACpGjC,EAAQ,2BAA2BG,EAAS,gBAAA,IACxCV,GAAmBO,EAAQ,0BAA0BgC,GAAwB,MAAM,IAAI,IACvFA;AAEJ,UAAME,IAAqBhB,GAAuB;AAAA,MAChD,KAAAhe;AAAA,MACA,SAAA8c;AAAA,MACA,UAAAG;AAAA,MACA,QAAA1iC;AAAA,MACA,cAAA+iC;AAAA,MACA,eAAAC;AAAA,MACA,OAAAM;AAAAA,MACA,YAAAxC;AAAA,MACA,qBAAAyC;AAAAA,MACA,mBAAA3F;AAAA,MACA,cAAA4F;AAAA,MACA,YAAYjB,EAAQ,mBAAmB,KAAK,IAAI,MAAMA,EAAQ,wBAAwB;AAAA,MACtF,UAAUhQ,EAAM;AAAA,MAChB,SAASA,EAAM,UAAUgQ,EAAQ;AAAA,MACjC,iBAAiBhQ,EAAM;AAAA,MACvB,iBAAiBA,EAAM;AAAA,MACvB,cAAcA,EAAM;AAAA,IAAA,CACrB;AAED,WAAO;AAAA,MACL,YAAYuO,EAAW;AAAA,MACvB,cAAc;AAAA,MACd,mBAAmByC,EAAoB;AAAA,MACvC,kBAAkBkB;AAAAA,MAClB,cAAAjB;AAAA,MACA,YAAY,KAAK,MAAMjB,EAAQ,mBAAmB,GAAG;AAAA,IAAA;AAAA,EAEzD;AAEA,QAAMmC,IAAanC,EAAQ;AAC3B,MAAI,CAACmC,EAAY,QAAO;AAExB,QAAMpB,IAAQhF,GAAmB;AAAA,IAC/B,cAAAyE;AAAA,IACA,eAAAC;AAAA,IACA,iBAAiBlC,EAAW;AAAA,IAC5B,SAAA9F;AAAA,IACA,QAAQzI,EAAM;AAAA,IACd,MAAMA,EAAM;AAAA,IACZ,cAAcmS,EAAW;AAAA,EAAA,CAC1B,GACK9F,IAAiB,KAAK,IAAI0E,EAAM,cAAcA,EAAM,YAAY;AACtE,EAAAA,EAAM,iBAAiB,KAAK,IAAI,MAAMoB,EAAW,oBAAoB1J,IAAU4D,CAAc,GAC7F0E,EAAM,eAAe,KAAK,IAAI,KAAKoB,EAAW,kBAAkB1J,IAAU4D,CAAc,GACxF0E,EAAM,mBAAmBoB,EAAW,oBAAoBA,EAAW;AAEnE,QAAMnB,IAAsB1C,GAA2BC,GAAYC,GAAYuC,EAAM,gBAAgB;AACrG,MAAIC,EAAoB,WAAW;AACjC,WAAO;AAAA,MACL,YAAYzC,EAAW;AAAA,MACvB,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,YAAY;AAAA,IAAA;AAIhB,EAAAyB,EAAQ,mBAAmBmC,EAAW,YACtCnC,EAAQ,2BAA2BgC;AAEnC,QAAME,IAAqBhB,GAAuB;AAAA,IAChD,KAAAhe;AAAA,IACA,SAAA8c;AAAA,IACA,UAAAG;AAAA,IACA,QAAA1iC;AAAA,IACA,cAAA+iC;AAAA,IACA,eAAAC;AAAA,IACA,OAAAM;AAAA,IACA,YAAAxC;AAAA,IACA,qBAAAyC;AAAA,IACA,mBAAmBmB,EAAW;AAAA,IAC9B,cAAcA,EAAW;AAAA,IACzB,YAAYA,EAAW,aAAa,KAAK,IAAI,MAAMH,CAAsB;AAAA,IACzE,UAAUhS,EAAM;AAAA,IAChB,SAASA,EAAM,UAAUgS;AAAA,IACzB,iBAAiBhS,EAAM;AAAA,IACvB,iBAAiBA,EAAM;AAAA,IACvB,cAAcA,EAAM;AAAA,EAAA,CACrB;AAED,SAAO;AAAA,IACL,YAAYuO,EAAW;AAAA,IACvB,cAAc;AAAA,IACd,mBAAmByC,EAAoB;AAAA,IACvC,kBAAkBkB;AAAA,IAClB,cAAcC,EAAW;AAAA,IACzB,YAAY,KAAK,MAAMA,EAAW,aAAa,GAAG;AAAA,EAAA;AAEtD;AAEO,SAASC,GAAa;AAAA,EAC3B,MAAAzF;AAAA,EACA,SAAA+B,IAAU;AAAA,EACV,SAAA0C,IAAUzJ;AAAA,EACV,QAAArc,IAASmc;AAAA,EACT,MAAAiJ,IAAOhJ;AAAA,EACP,UAAAd,IAAWY;AAAA,EACX,iBAAA6J,IAAkB;AAAA,EAClB,WAAAgB,IAAYxK;AAAA,EACZ,WAAA8I;AAAA,EACA,eAAA/H,IAAgB;AAAA,EAChB,iBAAAI,IAAkBlB;AAAA,EAClB,eAAAwK;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,mBAAAzD,IAAoBlH;AAAA,EACpB,SAAA4K;AACF,GAA4B;AAC1B,QAAM,EAAE,aAAAnP,GAAa,QAAA51B,GAAQ,sBAAAglC,GAAsB,wBAAAC,GAAwB,sBAAAC,EAAA,IAAyB3P,GAAA,GAE9F0K,IAAetP,GAAQ,MAAM;AACjC,UAAM5W,KAAc8qB,KAAiB,CAAA,GAClC,IAAI,CAAA/T,MAAU/Y,GAAc+Y,GAAQ,WAAW,CAAC,EAChD,OAAO,CAACxX,MAAuDA,KAAY,IAAI;AAClF,WAAOQ,GAAmBC,CAAU;AAAA,EACtC,GAAG,CAAC8qB,CAAa,CAAC,GACZ9E,IAAUpP,GAAQ,MAAM+O,GAAaO,CAAY,GAAG,CAACA,CAAY,CAAC,GAElEkF,IAAa9U,EAAuB;AAAA,IACxC,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,2BAA2B;AAAA,IAC3B,4BAA4B;AAAA,IAC5B,kBAAkB;AAAA,IAClB,8BAA8B;AAAA,IAC9B,0BAA0B;AAAA,IAC1B,OAAO;AAAA,IACP,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,eAAe;AAAA,EAAA,CAChB,GAEK+U,IAAW/U,EAAkB;AAAA,IACjC,MAAA6O;AAAA,IACA,SAAA+B;AAAA,IACA,SAAA0C;AAAA,IACA,QAAQ/oB,EAAMiD,GAAQ,MAAM,GAAG;AAAA,IAC/B,MAAMjD,EAAMqoB,GAAM,MAAM,GAAG;AAAA,IAC3B,UAAA9J;AAAA,IACA,iBAAAyK;AAAA,IACA,WAAAgB;AAAA,IACA,WAAA1B;AAAA,IACA,eAAA/H;AAAA,IACA,iBAAiBvgB,EAAM2gB,GAAiB,GAAGT,EAAoB;AAAA,IAC/D,cAAAmF;AAAA,IACA,SAAAF;AAAA,IACA,mBAAmB,KAAK,IAAIrF,IAAoB,KAAK,MAAM2G,CAAiB,CAAC;AAAA,IAC7E,SAAA0D;AAAA,EAAA,CACD;AAED,SAAAK,EAAS,UAAU;AAAA,IACjB,MAAAlG;AAAA,IACA,SAAA+B;AAAA,IACA,SAAA0C;AAAA,IACA,QAAQ/oB,EAAMiD,GAAQ,MAAM,GAAG;AAAA,IAC/B,MAAMjD,EAAMqoB,GAAM,MAAM,GAAG;AAAA,IAC3B,UAAA9J;AAAA,IACA,iBAAAyK;AAAA,IACA,WAAAgB;AAAA,IACA,WAAA1B;AAAA,IACA,eAAA/H;AAAA,IACA,iBAAiBvgB,EAAM2gB,GAAiB,GAAGT,EAAoB;AAAA,IAC/D,cAAAmF;AAAA,IACA,SAAAF;AAAA,IACA,mBAAmB,KAAK,IAAIrF,IAAoB,KAAK,MAAM2G,CAAiB,CAAC;AAAA,IAC7E,SAAA0D;AAAA,EAAA,GAGFjQ,EAAU,OAoDRkQ,EAAqBlL,IAAiBgL,GAnDzB,CAACrf,GAA+Bsd,GAAsBC,MAAgC;AACjG,UAAMzQ,IAAQ6S,EAAS,SACjB7C,IAAU4C,EAAW,SACrBzC,IAAW9M,EAAY;AAC7B,QAAI,CAACrD,EAAM,WAAW,CAACA,EAAM,QAAQ,CAACmQ,KAAY,CAAC1iC,EAAQ;AAE3D,UAAM8gC,IAAa+B,GAAiBN,GAAShQ,EAAM,MAAMA,EAAM,cAAcA,EAAM,SAASvyB,CAAM;AAClG,QAAI,CAAC8gC,EAAY;AAQjB,IALEvO,EAAM,cAAc,iBACnB,CAACgQ,EAAQ,cACR,CAACzC,GAAmByC,EAAQ,YAAYhQ,EAAM,MAAMA,EAAM,OAAO,KAChEA,EAAM,cAAc,UAAa,KAAK,IAAIgQ,EAAQ,WAAW,gBAAgBhQ,EAAM,SAAS,IAAI,QAGnGgQ,EAAQ,aAAaO,GAAgB;AAAA,MAEnC,YAAAhC;AAAA,MACA,UAAA4B;AAAA,MACA,QAAA1iC;AAAA,MACA,cAAA+iC;AAAA,MACA,eAAAC;AAAA,MACA,QAAQzQ,EAAM;AAAA,MACd,MAAMA,EAAM;AAAA,MACZ,WAAWA,EAAM;AAAA,MACjB,eAAeA,EAAM;AAAA,MACrB,iBAAiBA,EAAM;AAAA,MACvB,mBAAmBA,EAAM;AAAA,IAAA,CAC1B,IACQA,EAAM,cAAc,iBAC7BgQ,EAAQ,aAAa;AAGvB,UAAM8C,KAAY,YAAY,IAAA,GACxBC,KAAQhB,GAAY;AAAA,MACxB,KAAA7e;AAAA,MACA,SAAA8c;AAAA,MACA,UAAAG;AAAA,MACA,QAAA1iC;AAAA,MACA,cAAA+iC;AAAA,MACA,eAAAC;AAAA,MACA,OAAAzQ;AAAA,IAAA,CACD;AACD,IAAI,CAAC+S,MAAS,CAAC/S,EAAM,WACrBA,EAAM,QAAQ;AAAA,MACZ,GAAG+S;AAAA,MACH,cAAc,YAAY,QAAQD;AAAA,IAAA,CACnC;AAAA,EACH,CAEkD,GAC3C,MAAM;AACX,IAAAJ,EAAuBnL,EAAe,GACtCqL,EAAW,QAAQ,aAAa,MAChCA,EAAW,QAAQ,aAAa,MAChCA,EAAW,QAAQ,mBAAmB,IACtCA,EAAW,QAAQ,4BAA4B,IAC/CA,EAAW,QAAQ,6BAA6B,GAChDA,EAAW,QAAQ,mBAAmB,GACtCA,EAAW,QAAQ,+BAA+B,GAClDA,EAAW,QAAQ,2BAA2B,GAC9CA,EAAW,QAAQ,OAAO,QAAA,GAC1BA,EAAW,QAAQ,QAAQ,QAC3BA,EAAW,QAAQ,iBAAiB,MACpCA,EAAW,QAAQ,eAAe,MAClCA,EAAW,QAAQ,gBAAgB;AAAA,EACrC,IACC,CAACH,GAAsBC,GAAwBrP,GAAa51B,GAAQ8kC,CAAM,CAAC,GAE9EhQ,EAAU,MAAM;AACd,IAAAqQ,EAAW,QAAQ,aAAa,MAChCA,EAAW,QAAQ,aAAa,MAChCA,EAAW,QAAQ,mBAAmB,IACtCA,EAAW,QAAQ,4BAA4B,IAC/CA,EAAW,QAAQ,6BAA6B,GAChDA,EAAW,QAAQ,mBAAmB,GACtCA,EAAW,QAAQ,+BAA+B,GAClDA,EAAW,QAAQ,2BAA2B,GAC9CD,EAAA;AAAA,EACF,GAAG,CAAChG,GAAM,WAAWA,GAAM,SAASA,GAAM,OAAOa,GAASmF,CAAoB,CAAC,GAE/EpQ,EAAU,MAAM;AACd,IAAAqQ,EAAW,QAAQ,aAAa,MAChCA,EAAW,QAAQ,4BAA4B,IAC/CA,EAAW,QAAQ,6BAA6B,GAChDA,EAAW,QAAQ,mBAAmB,GACtCA,EAAW,QAAQ,+BAA+B,GAClDA,EAAW,QAAQ,2BAA2B,GAC9CD,EAAA;AAAA,EACF,GAAG,CAACrnB,GAAQolB,GAAM2B,GAAW1B,GAAW/H,GAAeI,GAAiB8F,GAAmB6D,CAAoB,CAAC,GAEhHpQ,EAAU,MAAM;AACd,IAAAoQ,EAAA;AAAA,EACF,GAAG,CAACjE,GAAS0C,GAASxK,GAAUyK,GAAiBsB,CAAoB,CAAC,GAE/D;AACT;AAEO,MAAMK,KAA0B;AAAA,EACrC,oBAAArK;AAAA,EACA,cAAAwE;AAAA,EACA,0BAAAjE;AAAA,EACA,uBAAAV;AAAA,EACA,sBAAAY;AAAA,EACA,oBAAAG;AAAA,EACA,oBAAAF;AAAA,EACA,qBAAAC;AAAA,EACA,uBAAAE;AAAA,EACA,gCAAAO;AAAA,EACA,iCAAAM;AAAA,EACA,8BAAAtB;AAAA,EACA,kCAAAL;AAAA,EACA,mBAAAgE;AAAA,EACA,2BAAA5D;AAAA,EACA,+BAAAkC;AAAA,EACA,oBAAAuC;AACF,GCp+CM0F,KAAkB;AAEjB,SAASC,GAAa,EAAE,QAAAC,KAAwD;AACrF,QAAM,EAAE,aAAA9P,GAAa,gBAAAC,GAAgB,QAAA71B,GAAQ,sBAAAglC,GAAsB,wBAAAC,GAAwB,sBAAAC,EAAA,IAAyB3P,GAAA,GAE9GzI,IAAsB2E;AAAA,IAC1B,CAAC5c,MAA+C;AAC9C,YAAM6T,IAAYkN,EAAY;AAC9B,UAAI,CAAClN,KAAa7T,EAAO,WAAW,UAAU,CAAA;AAC9C,YAAM6D,IAAM,IAAI,MAAsB7D,EAAO,MAAM;AACnD,eAAStP,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK,GAAG;AACzC,cAAMsF,IAAQwa,GAAQqD,EAAU,cAAc7T,EAAOtP,CAAC,EAAE,CAAC,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,YAAI,CAACsF,EAAO,QAAO,CAAA;AACnB,QAAA6N,EAAInT,CAAC,IAAIsF;AAAA,MACX;AACA,aAAO6N;AAAA,IACT;AAAA,IACA,CAAA;AAAA,EAAC,GAGGitB,IAAUtV,EAAO,EAAE,QAAAqV,GAAQ,qBAAA5Y,GAAqB,QAAA9sB,GAAQ;AAC9D,SAAA2lC,EAAQ,UAAU,EAAE,QAAAD,GAAQ,qBAAA5Y,GAAqB,QAAA9sB,EAAA,GAEjD80B,EAAU,OAqBRkQ,EAAqBQ,IAAiB,IApBzB,CAAC/f,MAAkC;AAC9C,UAAM,EAAE,QAAQhgB,GAAG,qBAAqBmgC,GAAK,QAAQC,MAAQF,EAAQ;AACrE,QAAI,CAAC,MAAM,QAAQlgC,CAAC,KAAKA,EAAE,WAAW,KAAK,CAACogC,EAAK;AAEjD,UAAMhZ,IAAiB+Y;AAAA,MACrB5nB,GAAU;AAAA,QACR,CAAC,GAAG,CAAC;AAAA,QACL,CAAC6nB,EAAI,OAAO,CAAC;AAAA,QACb,CAACA,EAAI,OAAOA,EAAI,MAAM;AAAA,QACtB,CAAC,GAAGA,EAAI,MAAM;AAAA,MAAA,CACf;AAAA,IAAA;AAEH,IAAAnZ,GAAkB;AAAA,MAChB,KAAAjH;AAAA,MACA,eAAehgB;AAAA,MACf,gBAAAonB;AAAA,MACA,qBAAqB+Y;AAAA,MACrB,iBAAiB9iB;AAAA,IAAA,CAClB;AAAA,EACH,CAC8C,GACvC,MAAMmiB,EAAuBO,EAAe,IAClD,CAACR,GAAsBC,CAAsB,CAAC,GAEjDnQ,EAAU,MAAM;AAAE,IAAAoQ,EAAA;AAAA,EAAwB,GAAG,CAACrP,GAAgB6P,GAAQ1lC,GAAQklC,CAAoB,CAAC,GAE5F;AACT;AC9BO,SAASY,GAAsBlkB,GAAsE;AAC1G,SAAO,MAAM,QAAQA,GAAK,OAAO,IAC7BA,EAAI,QAAQ,IAAI,CAACjF,OAAuB;AAAA,IACtC,SAAS,OAAOA,GAAM,WAAW,EAAE;AAAA,IACnC,WAAW,OAAOA,GAAM,aAAa,EAAE;AAAA,IACvC,YAAY,OAAOA,GAAM,cAAc,EAAE;AAAA,EAAA,EACzC,IACF,CAAA;AACN;AAEA,SAASopB,GAAkB1tB,GAAuB;AAChD,SAAO,OAAOA,KAAS,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC/C;AAEA,SAAS2tB,GAAmB3tB,GAAuB;AACjD,QAAMuJ,IAAM,OAAOvJ,KAAS,EAAE;AAC9B,SAAOuJ,EAAI,WAAW,GAAG,IAAIA,IAAM,IAAIA,CAAG;AAC5C;AAEA,SAASqkB,GAAgBC,GAA6B;AACpD,QAAM5f,IAAOyf,GAAkBG,CAAW;AAC1C,MAAI,CAAC5f,EAAM,QAAO;AAGlB,MAAI,mBAAmB,KAAKA,CAAI,EAAG,QAAOA;AAE1C,MAAI6f,IAAqB;AACzB,MAAI;AACF,IAAAA,IAAS,IAAI,IAAI7f,CAAI;AAAA,EACvB,QAAQ;AACN,IAAA6f,IAAS;AAAA,EACX;AAEA,MAAIA,GAAQ;AACV,UAAMC,IAAS,GAAGD,EAAO,QAAQ,KAAKA,EAAO,IAAI,IAC3CjlB,IAAO6kB,GAAkBI,EAAO,YAAY,EAAE;AAIpD,WAAI,UAAU,KAAKjlB,CAAI,IAAU,GAAGklB,CAAM,GAAGllB,CAAI,KAC7C,YAAY,KAAKA,CAAI,IAAU,GAAGklB,CAAM,GAAGllB,CAAI,KAC5C,GAAGklB,CAAM,GAAGllB,CAAI;AAAA,EACzB;AAGA,SAAI,UAAU,KAAKoF,CAAI,IAAU,SAC7B,YAAY,KAAKA,CAAI,IAAU,GAAGA,CAAI,KACnC,GAAGA,CAAI;AAChB;AAEO,SAAS+f,GAAmBzkB,GAAsBskB,GAAqC;AAC5F,QAAMI,IAAM1kB,GAAK,WAAW,CAAA,GACtB2kB,IAAQ,CAAC,CAAC3kB,GAAK,SAEfxgB,IAAQ,OAAOklC,EAAI,SAAS1kB,GAAK,SAAS,CAAC,GAC3CvgB,IAAS,OAAOilC,EAAI,UAAU1kB,GAAK,UAAU,CAAC,GAC9C4kB,IAAW,OAAOF,EAAI,YAAY1kB,GAAK,YAAY,CAAC,GACpD6kB,IAAc,OAAOH,EAAI,QAAQ1kB,GAAK,QAAQ,CAAC,GAC/C8kB,IAAW,OAAOJ,EAAI,QAAQ1kB,GAAK,QAAQ,EAAE,GAC7CzG,IAAM,OAAOmrB,EAAI,OAAO1kB,GAAK,OAAO,CAAC;AAE3C,MAAI,CAACxgB,KAAS,CAACC,KAAU,CAACmlC,KAAY,CAACE;AACrC,UAAM,IAAI,MAAM,gEAAgE;AAGlF,QAAMC,IAAiBX,GAAmBU,CAAQ,GAC5CE,IAAcX,GAAgBC,CAAW,GACzCW,IAAiBjlB,GAAK,mBACtB2kB,IAAQ,CAACO,GAAc5gC,GAAWD,MAAsB,GAAG2gC,CAAW,GAAGD,CAAc,IAAIG,CAAI,IAAI7gC,CAAC,IAAIC,CAAC,UAAU;AAEzH,SAAO;AAAA,IACL,IAAI0b,GAAK,OAAOA,GAAK,MAAM;AAAA,IAC3B,MAAMA,GAAK,QAAQ;AAAA,IACnB,OAAAxgB;AAAA,IACA,QAAAC;AAAA,IACA,KAAK,OAAO,SAAS8Z,CAAG,KAAKA,IAAM,IAAIA,IAAM;AAAA,IAC7C,UAAAqrB;AAAA,IACA,aAAa,OAAO,SAASC,CAAW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMA,CAAW,CAAC,IAAI;AAAA,IACnF,UAAAC;AAAA,IACA,aAAAR;AAAA,IACA,gBAAAW;AAAA,EAAA;AAEJ;AAEO,SAASE,GAAU/mC,GAA6E8mC,GAAc5gC,GAAWD,GAAmB;AACjJ,MAAIjG,EAAO;AACT,WAAOA,EAAO,eAAe8mC,GAAM5gC,GAAGD,GAAGjG,EAAO,UAAUA,EAAO,WAAW;AAE9E,QAAM2mC,IAAiBX,GAAmBhmC,EAAO,QAAQ;AACzD,SAAO,GAAGA,EAAO,WAAW,GAAG2mC,CAAc,IAAIG,CAAI,IAAI7gC,CAAC,IAAIC,CAAC;AACjE;AC/FA,SAAS8gC,GAAqCC,GAAaC,GAA4B;AACrF,MAAI,CAACA,EAAW,QAAO;AACvB,QAAMC,IAAO,IAAI,IAAIF,GAAK,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,MAAS,EAAE,SAAS,YAAA;AACrG,SAAI,EAAAE,EAAK,SAAS,eAAe,KAAKA,EAAK,WAAW,KAAK,KAAKA,EAAK,SAAS,MAAM;AAEtF;AA6CA,MAAMC,KAAmD;AAAA,EACvD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AACrB;AAEA,SAASC,GAA6B5hB,GAA+B5Q,GAAiCyyB,GAAiBC,GAAsB;AAC3I,QAAMC,IAAM3yB,EAAO;AACnB,MAAI,EAAA2yB,IAAM,IAGV;AAAA,aAASjiC,IAAI,GAAGA,IAAIiiC,GAAKjiC,KAAK,GAAG;AAC/B,YAAMkiC,IAAO5yB,EAAOtP,CAAC,GACfmiC,IAAK7yB,GAAQtP,IAAI,KAAKiiC,CAAG,GACzBG,IAAU,KAAK,MAAMD,EAAG,CAAC,IAAID,EAAK,CAAC,GAAGC,EAAG,CAAC,IAAID,EAAK,CAAC,CAAC;AAC3D,UAAIE,IAAU,KAAM;AAEpB,YAAMviC,IAAI,KAAK,IAAI,GAAG,KAAK,OAAOuiC,IAAUJ,MAAWD,IAAUC,EAAO,CAAC,GACnEK,IAAYxiC,IAAIkiC,KAAWliC,IAAI,KAAKmiC,GACpCM,IAAQF,IAAU,KAAK,IAAI,MAAMC,CAAS,GAC1CE,IAAUR,IAAUO,GACpBE,IAASR,IAASM;AAExB,MAAApiB,EAAI,UAAA,GACJA,EAAI,OAAOgiB,EAAK,CAAC,GAAGA,EAAK,CAAC,CAAC,GAC3BhiB,EAAI,OAAOiiB,EAAG,CAAC,GAAGA,EAAG,CAAC,CAAC,GACvBjiB,EAAI,YAAY,CAACqiB,GAASC,CAAM,CAAC,GACjCtiB,EAAI,iBAAiB,GACrBA,EAAI,OAAA;AAAA,IACN;AAEA,IAAAA,EAAI,YAAY,EAAE,GAClBA,EAAI,iBAAiB;AAAA;AACvB;AAEA,SAASuiB,GAAYhiC,GAA8BwE,GAA8BpE,IAAU,MAAe;AACxG,SAAO,KAAK,IAAIJ,EAAE,CAAC,IAAIwE,EAAE,CAAC,CAAC,KAAKpE,KAAW,KAAK,IAAIJ,EAAE,CAAC,IAAIwE,EAAE,CAAC,CAAC,KAAKpE;AACtE;AAEA,SAAS6hC,GAAqBpzB,GAA0D;AACtF,QAAMqzB,IAAmC,CAAA;AACzC,aAAWp+B,KAAS+K,GAAQ;AAC1B,UAAM8D,IAAOuvB,EAAQA,EAAQ,SAAS,CAAC;AACvC,KAAI,CAACvvB,KAAQ,CAACqvB,GAAYrvB,GAAM7O,CAAK,MACnCo+B,EAAQ,KAAKp+B,CAAK;AAAA,EAEtB;AACA,SAAIo+B,EAAQ,SAAS,KAAKF,GAAYE,EAAQ,CAAC,GAAGA,EAAQA,EAAQ,SAAS,CAAC,CAAC,KAC3EA,EAAQ,IAAA,GAEHA;AACT;AAEA,SAASC,GAAaV,GAAiCC,GAA+BxhC,GAA6B;AACjH,QAAMrE,IAAK6lC,EAAG,CAAC,IAAID,EAAK,CAAC;AACzB,MAAI,KAAK,IAAI5lC,CAAE,IAAI,aAAa,CAACqE,GAAGuhC,EAAK,CAAC,CAAC;AAC3C,QAAM1pB,KAAK7X,IAAIuhC,EAAK,CAAC,KAAK5lC;AAC1B,SAAO,CAACqE,GAAGuhC,EAAK,CAAC,KAAKC,EAAG,CAAC,IAAID,EAAK,CAAC,KAAK1pB,CAAC;AAC5C;AAEA,SAASqqB,GAAaX,GAAiCC,GAA+BzhC,GAA6B;AACjH,QAAMnE,IAAK4lC,EAAG,CAAC,IAAID,EAAK,CAAC;AACzB,MAAI,KAAK,IAAI3lC,CAAE,IAAI,aAAa,CAAC2lC,EAAK,CAAC,GAAGxhC,CAAC;AAC3C,QAAM8X,KAAK9X,IAAIwhC,EAAK,CAAC,KAAK3lC;AAC1B,SAAO,CAAC2lC,EAAK,CAAC,KAAKC,EAAG,CAAC,IAAID,EAAK,CAAC,KAAK1pB,GAAG9X,CAAC;AAC5C;AAEA,SAASoiC,GAAkBxzB,GAAiCsF,GAAcC,GAAcC,GAAcC,GAAuC;AAC3I,MAAIguB,IAASL,GAAqBpzB,CAAM;AACxC,MAAIyzB,EAAO,SAAS,EAAG,QAAO,CAAA;AAE9B,QAAMC,IAGD;AAAA,IACH;AAAA,MACE,QAAQ,CAAAz+B,MAASA,EAAM,CAAC,KAAKqQ;AAAA,MAC7B,WAAW,CAACstB,GAAMC,MAAOS,GAAaV,GAAMC,GAAIvtB,CAAI;AAAA,IAAA;AAAA,IAEtD;AAAA,MACE,QAAQ,CAAArQ,MAASA,EAAM,CAAC,KAAKuQ;AAAA,MAC7B,WAAW,CAACotB,GAAMC,MAAOS,GAAaV,GAAMC,GAAIrtB,CAAI;AAAA,IAAA;AAAA,IAEtD;AAAA,MACE,QAAQ,CAAAvQ,MAASA,EAAM,CAAC,KAAKsQ;AAAA,MAC7B,WAAW,CAACqtB,GAAMC,MAAOU,GAAaX,GAAMC,GAAIttB,CAAI;AAAA,IAAA;AAAA,IAEtD;AAAA,MACE,QAAQ,CAAAtQ,MAASA,EAAM,CAAC,KAAKwQ;AAAA,MAC7B,WAAW,CAACmtB,GAAMC,MAAOU,GAAaX,GAAMC,GAAIptB,CAAI;AAAA,IAAA;AAAA,EACtD;AAGF,aAAWkuB,KAAQD,GAAO;AACxB,QAAID,EAAO,WAAW,EAAG,QAAO,CAAA;AAChC,UAAM/rB,IAAQ+rB;AACd,IAAAA,IAAS,CAAA;AACT,QAAI3vB,IAAO4D,EAAMA,EAAM,SAAS,CAAC,GAC7BksB,IAAaD,EAAK,OAAO7vB,CAAI;AACjC,eAAWkH,KAAQtD,GAAO;AACxB,YAAMmsB,IAAaF,EAAK,OAAO3oB,CAAI;AACnC,MAAI6oB,KACGD,KACHH,EAAO,KAAKE,EAAK,UAAU7vB,GAAMkH,CAAI,CAAC,GAExCyoB,EAAO,KAAKzoB,CAAI,KACP4oB,KACTH,EAAO,KAAKE,EAAK,UAAU7vB,GAAMkH,CAAI,CAAC,GAExClH,IAAOkH,GACP4oB,IAAaC;AAAA,IACf;AACA,IAAAJ,IAASL,GAAqBK,CAAM;AAAA,EACtC;AAEA,SAAOA,EAAO,UAAU,IAAIA,IAAS,CAAA;AACvC;AAEA,SAASK,GAAiBtwB,GAA2BiE,GAAkBzB,IAAM,GAAW;AACtF,SAAI,OAAOxC,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUiE,IAC1D,KAAK,IAAIzB,GAAKxC,CAAK;AAC5B;AAEA,SAASuwB,GAAiBvwB,GAAmC;AAC3D,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK,IAAIA,IAAQ;AACvE;AAEA,SAASrX,GAAUC,GAAqB;AACtC,SAAQA,IAAM,KAAK,KAAM;AAC3B;AAEA,SAAS4nC,GAAuB3jB,GAAoBC,GAAqBvjB,GAA0C;AACjH,QAAMknC,IAAeF,GAAiBhnC,CAAW,GAC3CG,IAAMf,GAAU8nC,CAAY,GAC5B9mC,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBP,IAAU0jB,IAAa,KACvBzjB,IAAU0jB,IAAc,KACxB4jB,IAAa,CAAC/mC,IAAMR,IAAUS,IAAMR,GACpCunC,IAAa/mC,IAAMT,IAAUQ,IAAMP,GAEnCwnC,IAAmC;AAAA,IACvC,CAAC,GAAG,CAAC;AAAA,IACL,CAAC/jB,GAAY,CAAC;AAAA,IACd,CAACA,GAAYC,CAAW;AAAA,IACxB,CAAC,GAAGA,CAAW;AAAA,EAAA,EACf,IAAI,CAAC,CAACjf,GAAGD,CAAC,MAAM,CAACjE,IAAMkE,IAAIjE,IAAMgE,IAAI8iC,GAAY,CAAC9mC,IAAMiE,IAAIlE,IAAMiE,IAAI+iC,CAAU,CAAC;AAEnF,MAAI7uB,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AAEX,aAAW,CAACpU,GAAGD,CAAC,KAAKgjC;AACnB,IAAI/iC,IAAIiU,MAAMA,IAAOjU,IACjBA,IAAImU,MAAMA,IAAOnU,IACjBD,IAAImU,MAAMA,IAAOnU,IACjBA,IAAIqU,MAAMA,IAAOrU;AAGvB,SAAO;AAAA,IACL,KAAAjE;AAAA,IACA,KAAAC;AAAA,IACA,MAAAkY;AAAA,IACA,MAAAC;AAAA,IACA,OAAO,KAAK,IAAI,MAAMC,IAAOF,CAAI;AAAA,IACjC,QAAQ,KAAK,IAAI,MAAMG,IAAOF,CAAI;AAAA,IAClC,YAAA2uB;AAAA,IACA,YAAAC;AAAA,EAAA;AAEJ;AAEA,SAASE,GAAuBhkB,GAAoBC,GAAqB4G,GAAkBC,GAAmBpqB,GAA0C;AACtJ,QAAMunC,IAAUN,GAAuB3jB,GAAYC,GAAavjB,CAAW,GACrEwnC,IAAcD,EAAQ,QAAQA,EAAQ,QACtCE,IAAYtd,IAAWC;AAE7B,MAAIsd,GACAC;AACJ,SAAIH,IAAcC,KAChBC,IAAevd,GACfwd,IAAgBxd,IAAWqd,MAE3BG,IAAgBvd,GAChBsd,IAAetd,IAAYod,IAGtB;AAAA,IACL,WAAWrd,IAAWud,KAAgB;AAAA,IACtC,WAAWtd,IAAYud,KAAiB;AAAA,IACxC,cAAAD;AAAA,IACA,eAAAC;AAAA,IACA,SAAAJ;AAAA,EAAA;AAEJ;AAEA,SAASK,GAAqBtnC,GAAgBC,GAAgBsnC,GAA+C;AAC3G,QAAM,EAAE,UAAAC,GAAU,UAAAC,GAAU,cAAAL,GAAc,eAAAC,GAAe,SAAAJ,MAAYM,GAC/DG,IAAWT,EAAQ,MAAMjnC,IAASinC,EAAQ,MAAMhnC,IAASgnC,EAAQ,aAAaA,EAAQ,MACtFU,IAAW,CAACV,EAAQ,MAAMjnC,IAASinC,EAAQ,MAAMhnC,IAASgnC,EAAQ,aAAaA,EAAQ;AAC7F,SAAO,CAACO,IAAYE,IAAWT,EAAQ,QAASG,GAAcK,IAAYE,IAAWV,EAAQ,SAAUI,CAAa;AACtH;AAEA,SAASO,GAAqBC,GAAgBC,GAAgBP,GAA6BvkB,GAAoBC,GAAuC;AACpJ,QAAM,EAAE,SAAAgkB,MAAYM,GACdG,IAAWG,IAASZ,EAAQ,OAAOA,EAAQ,YAC3CU,IAAWG,IAASb,EAAQ,OAAOA,EAAQ,YAC3CjnC,IAAS0nC,IAAWT,EAAQ,MAAMU,IAAWV,EAAQ,KACrDhnC,IAASynC,IAAWT,EAAQ,MAAMU,IAAWV,EAAQ;AAC3D,SAAO,CAACvuB,EAAM1Y,GAAQ,GAAGgjB,CAAU,GAAGtK,EAAMzY,GAAQ,GAAGgjB,CAAW,CAAC;AACrE;AAEA,SAAS8kB,GAAgBrrB,GAAyC;AAChE,SAAO;AAAA,IACL,CAACA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IACrB,CAACA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IACrB,CAACA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IACrB,CAACA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,EAAA;AAEzB;AAEA,SAASsrB,GAAetrB,GAAuD;AAC7E,SAAO,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,KAAK,OAAO,SAASA,EAAO,CAAC,CAAC,KAAK,OAAO,SAASA,EAAO,CAAC,CAAC,KAAK,OAAO,SAASA,EAAO,CAAC,CAAC,KAAK,OAAO,SAASA,EAAO,CAAC,CAAC;AAC5K;AAEA,MAAMurB,KAA4C;AAAA,EAChD,UAAU;AAAA,EACV,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,gBAAgB;AAClB;AAEO,SAASC,GAAY,EAAE,QAAApqC,GAAQ,cAAA2uB,GAAc,WAAAuY,IAAY,IAAI,SAAApmC,GAAS,eAAAovB,GAAe,WAAAC,GAAW,OAAAnK,KAA+C;AACpJ,QAAMoK,IAAYC,EAAiC,IAAI,GACjDga,IAAeha,EAAiC,IAAI,GACpDia,IAAgBja,EAAsB,IAAI,GAC1Cka,IAAcla,EAAsD;AAAA,IACxE,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA,CACZ,GACKma,IAASna,EAAsB,IAAI,GACnCC,IAAiBD,EAAO,EAAK,GAE7BjvB,IAAQunC,GAAiB7nC,GAAS,OAAOsmC,GAA6B,OAAO,EAAE,GAC/E/lC,IAASsnC,GAAiB7nC,GAAS,QAAQsmC,GAA6B,QAAQ,EAAE,GAElFqD,IAAS9B,GAAiB7nC,GAAS,QAAQsmC,GAA6B,QAAQ,CAAC,GACjFnc,IAAe0d,GAAiB7nC,GAAS,cAAcsmC,GAA6B,cAAc,CAAC,GACnGsD,IAAc/B,GAAiB7nC,GAAS,aAAasmC,GAA6B,aAAa,CAAC,GAChGuD,IAAoB,KAAK,IAAI,GAAG,KAAK,MAAMhC,GAAiB7nC,GAAS,mBAAmBsmC,GAA6B,mBAAmB,CAAC,CAAC,CAAC,GAE3IxD,IAAkB9iC,GAAS,mBAAmBsmC,GAA6B,iBAC3EwD,IAAc9pC,GAAS,eAAesmC,GAA6B,aACnEyD,IAAsB/pC,GAAS,uBAAuBsmC,GAA6B,qBACnF0D,IAAsBhqC,GAAS,wBAAwB,YAAYA,GAAS,wBAAwB,SAASA,EAAQ,sBAAsBsmC,GAA6B,qBACxK2D,IAAoBjqC,GAAS,qBAAqBsmC,GAA6B,mBAC/E4D,IAAclqC,GAAS,eAAesmC,GAA6B,aACnE6D,IAAgBnqC,GAAS,iBAAiBsmC,GAA6B,eACvE8D,IAAWpqC,GAAS,YAAYsmC,GAA6B,UAC7D+D,IAAUrqC,GAAS,SACnBsqC,IAAYtqC,GAAS,WACrBuqC,IAAmBvqC,GAAS,kBAE5BywB,IAAcZ,GAAuB,MAAM;AAC/C,UAAM2a,IAAqB,CAAA;AAC3B,WAAIJ,MAAa,cAAcA,MAAa,kBAAmB,OAAOT,MAC7D,QAAQA,GACbS,MAAa,cAAcA,MAAa,gBAAiB,MAAMT,MAC1D,SAASA,GAEX;AAAA,MACL,UAAU;AAAA,MACV,GAAGa;AAAA,MACH,OAAAlqC;AAAA,MACA,QAAAC;AAAA,MACA,cAAA4pB;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAe+f,IAAc,SAAS;AAAA,MACtC,aAAa;AAAA,MACb,WAAW;AAAA,MACX,GAAGhlB;AAAA,IAAA;AAAA,EAEP,GAAG,CAACykB,GAAQS,GAAU9pC,GAAOC,GAAQ4pB,GAAc+f,GAAahlB,CAAK,CAAC,GAEhEulB,IAAO9Z,EAAY,MAAM;AAC7B,UAAM5wB,IAASuvB,EAAU;AACzB,QAAI,CAACvvB,EAAQ;AAEb,UAAM4kB,IAAM5kB,EAAO,WAAW,IAAI;AAClC,QAAI,CAAC4kB,EAAK;AAEV,UAAM+lB,IAAOpqC,GACPqqC,KAAOpqC,GACPmD,KAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9CknC,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAOhnC,EAAG,CAAC,GAC3CmnC,KAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,KAAOjnC,EAAG,CAAC;AACjD,KAAI3D,EAAO,UAAU6qC,KAAU7qC,EAAO,WAAW8qC,QAC/C9qC,EAAO,QAAQ6qC,GACf7qC,EAAO,SAAS8qC,KAGlBlmB,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAG5kB,EAAO,OAAOA,EAAO,MAAM,GAC/C4kB,EAAI,aAAajhB,IAAK,GAAG,GAAGA,IAAK,GAAG,CAAC,GAErCihB,EAAI,YAAYme,GAChBne,EAAI,SAAS,GAAG,GAAG+lB,GAAMC,EAAI;AAE7B,UAAM/iB,KAAYiG,EAAa,SACzBid,KAAqBhD,GAAiBlgB,IAAW,wBAAA,CAAyB,GAC1E+gB,KAASP,GAAuBlpC,EAAO,OAAOA,EAAO,QAAQwrC,GAAMC,IAAMG,EAAkB,GAC3F,EAAE,UAAU/jC,IAAI,UAAUC,IAAI,cAAc+jC,IAAI,eAAepvB,IAAI,SAAA0sB,GAAA,IAAYM,IAE/E1W,KAAUsX,EAAa;AAC7B,IAAItX,OACFtN,EAAI,KAAA,GACJA,EAAI,UAAA,GACJA,EAAI,KAAK5d,IAAIC,IAAI+jC,IAAIpvB,EAAE,GACvBgJ,EAAI,KAAA,GACJA,EAAI,UAAU5d,IAAIC,EAAE,GACpB2d,EAAI,MAAMomB,KAAK1C,GAAQ,OAAO1sB,KAAK0sB,GAAQ,MAAM,GACjD1jB,EAAI,UAAU0jB,GAAQ,KAAK,CAACA,GAAQ,KAAKA,GAAQ,KAAKA,GAAQ,KAAKA,GAAQ,aAAaA,GAAQ,MAAMA,GAAQ,aAAaA,GAAQ,IAAI,GACvI1jB,EAAI,UAAUsN,IAAS,GAAG,GAAG/yB,EAAO,OAAOA,EAAO,MAAM,GACxDylB,EAAI,QAAA,IAGNA,EAAI,cAAcmlB,GAClBnlB,EAAI,YAAYilB,GAChBjlB,EAAI,WAAWilB,IAAc,KAAKA,IAAc,KAAKc,IAAOd,GAAae,KAAOf,CAAW;AAE3F,UAAM9rB,KAAS8J,IAAW,gBAAA,GACpBugB,KAAUvgB,IAAW,iBAAA,GACrBojB,KACJ,MAAM,QAAQ7C,EAAO,KAAKA,GAAQ,UAAU,KAAKA,GAAQ,MAAM,CAAAn/B,MAAS,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAK,OAAO,SAASA,EAAM,CAAC,CAAC,KAAK,OAAO,SAASA,EAAM,CAAC,CAAC,CAAC,IACtKm/B,KACD,MACA8C,IAAa7B,GAAetrB,EAAM,IAAIA,KAASsrB,GAAeI,EAAc,OAAO,IAAIA,EAAc,UAAU;AACrH,IAAIJ,GAAetrB,EAAM,MACvB0rB,EAAc,UAAU1rB;AAG1B,UAAMotB,IAASlB,MAAwB;AAEvC,QAAIgB,IAAa;AACf,YAAMzkB,IAAyCykB,GAAY,IAAI,CAAAhiC,MAAS0/B,GAAqB1/B,EAAM,CAAC,GAAGA,EAAM,CAAC,GAAG2/B,EAAM,CAAC,GAClHwC,KAAiB5D,GAAkBhhB,GAAexf,IAAIC,IAAID,KAAKgkC,IAAI/jC,KAAK2U,EAAE;AAEhF,UAAIwvB,GAAe,UAAU,GAAG;AAC9B,QAAAxmB,EAAI,UAAA;AACJ,iBAASlgB,IAAI,GAAGA,IAAI0mC,GAAe,QAAQ1mC,KAAK;AAC9C,UAAIA,MAAM,IAAGkgB,EAAI,OAAOwmB,GAAe1mC,CAAC,EAAE,CAAC,GAAG0mC,GAAe1mC,CAAC,EAAE,CAAC,CAAC,IAC7DkgB,EAAI,OAAOwmB,GAAe1mC,CAAC,EAAE,CAAC,GAAG0mC,GAAe1mC,CAAC,EAAE,CAAC,CAAC;AAE5D,QAAAkgB,EAAI,UAAA,GACJA,EAAI,YAAYslB,GAChBtlB,EAAI,KAAA,GACJA,EAAI,cAAcolB,GAClBplB,EAAI,YAAY,MACZumB,IACF3E,GAA6B5hB,GAAKwmB,IAAgB,GAAG,CAAC,IAEtDxmB,EAAI,OAAA;AAEN;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAACsmB;AACH;AAGF,UAAMG,KAAkBjC,GAAgB8B,CAAU,EAAE,IAAI,CAAAjiC,MAAS0/B,GAAqB1/B,EAAM,CAAC,GAAGA,EAAM,CAAC,GAAG2/B,EAAM,CAAC,GAC3GwC,KAAiB5D,GAAkB6D,IAAiBrkC,IAAIC,IAAID,KAAKgkC,IAAI/jC,KAAK2U,EAAE;AAClF,QAAI,EAAAwvB,GAAe,SAAS,IAI5B;AAAA,MAAAxmB,EAAI,UAAA;AACJ,eAASlgB,IAAI,GAAGA,IAAI0mC,GAAe,QAAQ1mC,KAAK;AAC9C,QAAIA,MAAM,IAAGkgB,EAAI,OAAOwmB,GAAe1mC,CAAC,EAAE,CAAC,GAAG0mC,GAAe1mC,CAAC,EAAE,CAAC,CAAC,IAC7DkgB,EAAI,OAAOwmB,GAAe1mC,CAAC,EAAE,CAAC,GAAG0mC,GAAe1mC,CAAC,EAAE,CAAC,CAAC;AAE5D,MAAAkgB,EAAI,UAAA,GACJA,EAAI,YAAYslB,GAChBtlB,EAAI,KAAA,GACJA,EAAI,cAAcolB,GAClBplB,EAAI,YAAY,MACZumB,IACF3E,GAA6B5hB,GAAKwmB,IAAgB,GAAG,CAAC,IAEtDxmB,EAAI,OAAA;AAAA;AAAA,EAER,GAAG,CAACrkB,GAAOC,GAAQuiC,GAAiBgH,GAAaF,GAAa/b,GAAc3uB,EAAO,OAAOA,EAAO,QAAQ+qC,GAAmBF,GAAqBC,CAAmB,CAAC,GAE/JxX,IAAc7B,EAAY,MAAM;AACpC,IAAInB,EAAe,YACnBA,EAAe,UAAU,IACzBka,EAAO,UAAU,sBAAsB,MAAM;AAC3C,MAAAla,EAAe,UAAU,IACzBka,EAAO,UAAU,MACjBe,EAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACA,CAAI,CAAC,GAEHY,KAAoB1a;AAAA,IACxB,CAAC2a,GAAiBC,MAA6C;AAC7D,YAAMxrC,IAASuvB,EAAU;AACzB,UAAI,CAACvvB,EAAQ,QAAO;AAEpB,YAAMwD,KAAOxD,EAAO,sBAAA;AACpB,UAAI,CAACwD,GAAK,SAAS,CAACA,GAAK,OAAQ,QAAO;AAExC,YAAMqkB,KAAYiG,EAAa,SACzBid,IAAqBhD,GAAiBlgB,IAAW,wBAAA,CAAyB,GAC1E+gB,KAASP,GAAuBlpC,EAAO,OAAOA,EAAO,QAAQoB,GAAOC,GAAQuqC,CAAkB,GAC9FU,KAASjoC,GAAK,QAAQjD,GACtBmrC,KAASloC,GAAK,SAAShD,GACvBmrC,KAAO/C,GAAO,WAAW6C,IACzBG,KAAOhD,GAAO,WAAW8C,IACzBG,KAAOjD,GAAO,eAAe6C,IAC7BK,KAAOlD,GAAO,gBAAgB8C,IAE9BK,KAAKhyB,GAAOwxB,IAAU/nC,GAAK,OAAOmoC,MAAQE,IAAM,GAAG,CAAC,GACpDG,KAAKjyB,GAAOyxB,IAAUhoC,GAAK,MAAMooC,MAAQE,IAAM,GAAG,CAAC;AACzD,aAAO7C,GAAqB8C,KAAKnD,GAAO,QAAQ,OAAOoD,KAAKpD,GAAO,QAAQ,QAAQA,IAAQzpC,EAAO,OAAOA,EAAO,MAAM;AAAA,IACxH;AAAA,IACA,CAAC2uB,GAAc3uB,EAAO,OAAOA,EAAO,QAAQoB,GAAOC,CAAM;AAAA,EAAA,GAGrDyrC,KAAarb;AAAA,IACjB,CAACvvB,GAAgBC,MAAmB;AAClC,YAAMumB,IAAYiG,EAAa;AAC/B,UAAI,CAACjG,EAAW;AAEhB,UAAIA,EAAU,eAAe;AAC3B,QAAAA,EAAU,cAAcxmB,GAAQC,CAAM,GACtCmxB,EAAA;AACA;AAAA,MACF;AAEA,YAAM1U,KAAS8J,EAAU,gBAAA,GACnBqjB,KAAa7B,GAAetrB,EAAM,IAAIA,KAASsrB,GAAeI,EAAc,OAAO,IAAIA,EAAc,UAAU;AACrH,UAAI,CAACyB,GAAY;AAEjB,YAAMgB,IAAW,KAAK,IAAI,MAAMhB,GAAW,CAAC,IAAIA,GAAW,CAAC,CAAC,GACvDiB,KAAW,KAAK,IAAI,MAAMjB,GAAW,CAAC,IAAIA,GAAW,CAAC,CAAC;AAE7D,MAAArjB,EAAU,aAAa;AAAA,QACrB,SAASxmB,IAAS6qC,IAAW;AAAA,QAC7B,SAAS5qC,IAAS6qC,KAAW;AAAA,MAAA,CAC9B,GACD1Z,EAAA;AAAA,IACF;AAAA,IACA,CAAC3E,GAAc2E,CAAW;AAAA,EAAA,GAGtBiB,KAAoB9C;AAAA,IACxB,CAACvd,MAAgD;AAE/C,UADI,CAAC82B,KACD92B,EAAM,WAAW,EAAG;AAExB,YAAMrT,IAASuvB,EAAU;AACzB,UAAI,CAACvvB,EAAQ;AAEb,YAAM2mB,IAAQ2kB,GAAkBj4B,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKsT,MAELtT,EAAM,eAAA,GACNA,EAAM,gBAAA,GAENrT,EAAO,kBAAkBqT,EAAM,SAAS,GACxCq2B,EAAY,UAAU,EAAE,QAAQ,IAAM,WAAWr2B,EAAM,UAAA,GACvD44B,GAAWtlB,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC/B;AAAA,IACA,CAACwjB,GAAamB,IAAmBW,EAAU;AAAA,EAAA,GAGvCtY,KAAoB/C;AAAA,IACxB,CAACvd,MAAgD;AAC/C,YAAM+4B,IAAO1C,EAAY;AACzB,UAAI,CAAC0C,EAAK,UAAUA,EAAK,cAAc/4B,EAAM,UAAW;AAExD,YAAMsT,IAAQ2kB,GAAkBj4B,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKsT,MAELtT,EAAM,eAAA,GACNA,EAAM,gBAAA,GACN44B,GAAWtlB,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC/B;AAAA,IACA,CAAC2kB,IAAmBW,EAAU;AAAA,EAAA,GAG1BnY,KAAkBlD;AAAA,IACtB,CAACvd,MAAgD;AAC/C,YAAM+4B,IAAO1C,EAAY;AACzB,UAAI,CAAC0C,EAAK,UAAUA,EAAK,cAAc/4B,EAAM,UAAW;AAExD,YAAMrT,IAASuvB,EAAU;AACzB,UAAIvvB,KAAUA,EAAO,kBAAkBqT,EAAM,SAAS;AACpD,YAAI;AACF,UAAArT,EAAO,sBAAsBqT,EAAM,SAAS;AAAA,QAC9C,QAAQ;AAAA,QAER;AAGF,MAAAq2B,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAClDjX,EAAA;AAAA,IACF;AAAA,IACA,CAACA,CAAW;AAAA,EAAA;AAGd,SAAAwB,EAAU,MAAM;AACd,QAAIoY,IAAY;AAChB,IAAA7C,EAAa,UAAU,MACvB/W,EAAA;AAEA,UAAMwT,IAAO,GACPqG,IAAa,MAAMntC,EAAO,cAAc8mC,IACxCsG,KAAa,KAAK,KAAKptC,EAAO,QAAQmtC,CAAU,GAChDE,KAAc,KAAK,KAAKrtC,EAAO,SAASmtC,CAAU,GAClDG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,KAAaptC,EAAO,QAAQ,CAAC,GAC5DutC,KAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,KAAcrtC,EAAO,QAAQ,CAAC,GAC7DwtC,KAAYF,IAASC;AAE3B,QAAI,CAACtC,KAAiBuC,KAAY7C;AAChC;AAGF,UAAM8C,KAAe,KAAK,IAAIrsC,IAAQ,KAAK,IAAI,GAAGpB,EAAO,KAAK,GAAGqB,IAAS,KAAK,IAAI,GAAGrB,EAAO,MAAM,CAAC,GAC9F+yB,KAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,GAAQ,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM/yB,EAAO,QAAQytC,EAAY,CAAC,GACnE1a,GAAQ,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM/yB,EAAO,SAASytC,EAAY,CAAC;AACrE,UAAMhoB,KAAMsN,GAAQ,WAAW,IAAI;AACnC,QAAI,CAACtN;AACH;AAGF,IAAAA,GAAI,YAAYme,GAChBne,GAAI,SAAS,GAAG,GAAGsN,GAAQ,OAAOA,GAAQ,MAAM;AAEhD,UAAM2a,KAGD,CAAA;AAEL,aAASznC,KAAI,GAAGA,KAAIsnC,IAAQtnC,MAAK;AAC/B,eAASC,KAAI,GAAGA,KAAIonC,GAAQpnC,MAAK,GAAG;AAClC,cAAMimB,KAAOjmB,KAAIlG,EAAO,WAAWmtC,GAC7B/gB,KAAMnmB,KAAIjG,EAAO,WAAWmtC,GAC5BhQ,KAAQ,KAAK,KAAKj3B,KAAI,KAAKlG,EAAO,UAAUotC,EAAU,IAAID,GAC1DQ,KAAS,KAAK,KAAK1nC,KAAI,KAAKjG,EAAO,UAAUqtC,EAAW,IAAIF;AAClE,QAAAO,GAAS,KAAK;AAAA,UACZ,KAAK3G,GAAU/mC,GAAQ8mC,GAAM5gC,IAAGD,EAAC;AAAA,UACjC,QAAQ,CAACkmB,IAAMC,IAAK+Q,IAAOwQ,EAAM;AAAA,QAAA,CAClC;AAAA,MACH;AAGF,WAAK,QAAQ;AAAA,MACXD,GAAS,IAAI,OAAM5pC,OAAQ;AACzB,cAAM8pC,KAAgB5G,GAAqCljC,GAAK,KAAKojC,CAAS,GACxEljC,KAAW,MAAM,MAAMF,GAAK,KAAK;AAAA,UACrC,SAAS8pC,KAAgB,EAAE,eAAe1G,MAAc;AAAA,QAAA,CACzD;AACD,YAAI,CAACljC,GAAS;AACZ,gBAAM,IAAI,MAAM,QAAQA,GAAS,MAAM,EAAE;AAE3C,cAAME,KAAS,MAAM,kBAAkB,MAAMF,GAAS,MAAM;AAC5D,eAAO,EAAE,MAAAF,IAAM,QAAAI,GAAA;AAAA,MACjB,CAAC;AAAA,IAAA,EACD,KAAK,CAAA2pC,OAAW;AAChB,UAAIX,GAAW;AACb,mBAAW5tB,MAAUuuB;AACnB,UAAIvuB,GAAO,WAAW,eACpBA,GAAO,MAAM,OAAO,MAAA;AAGxB;AAAA,MACF;AAEA,YAAM5c,KAAKqwB,GAAQ,QAAQ,KAAK,IAAI,GAAG/yB,EAAO,KAAK,GAC7C2C,KAAKowB,GAAQ,SAAS,KAAK,IAAI,GAAG/yB,EAAO,MAAM;AACrD,iBAAWsf,MAAUuuB,IAAS;AAC5B,YAAIvuB,GAAO,WAAW,YAAa;AACnC,cAAM;AAAA,UACJ,MAAM,EAAE,QAAAV,GAAA;AAAA,UACR,QAAA1a;AAAA,QAAA,IACEob,GAAO,OACLzd,KAAK+c,GAAO,CAAC,IAAIlc,IACjBZ,IAAK8c,GAAO,CAAC,IAAIjc,IACjBmrC,IAAK,KAAK,IAAI,IAAIlvB,GAAO,CAAC,IAAIA,GAAO,CAAC,KAAKlc,EAAE,GAC7CqrC,KAAK,KAAK,IAAI,IAAInvB,GAAO,CAAC,IAAIA,GAAO,CAAC,KAAKjc,EAAE;AACnD,QAAA8iB,GAAI,UAAUvhB,IAAQrC,IAAIC,GAAIgsC,GAAIC,EAAE,GACpC7pC,GAAO,MAAA;AAAA,MACT;AAEA,MAAAmmC,EAAa,UAAUtX,IACvBO,EAAA;AAAA,IACF,CAAC,GAEM,MAAM;AACX,MAAA4Z,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACltC,GAAQknC,GAAWtD,GAAiBxiC,GAAOC,GAAQ4pC,GAAeN,GAAmBrX,CAAW,CAAC,GAErGwB,EAAU,MAAM;AACd,IAAAxB,EAAA;AAAA,EACF,GAAG,CAACA,CAAW,CAAC,GAEhBwB,EAAU,MAAM;AACd,QAAInG,EAAa,QAAS;AAC1B,QAAIqf,IAAQ;AACZ,UAAMC,IAAO,MAAM;AACjB,UAAItf,EAAa,SAAS;AACxB,QAAA2E,EAAA;AACA;AAAA,MACF;AACA,MAAA0a,IAAQ,sBAAsBC,CAAI;AAAA,IACpC;AACA,WAAAD,IAAQ,sBAAsBC,CAAI,GAC3B,MAAM,qBAAqBD,CAAK;AAAA,EACzC,GAAG,CAACrf,GAAc2E,CAAW,CAAC,GAE9BwB,EAAU,MAAMjT,GAA+B,MAAMyR,EAAA,CAAa,GAAG,CAACA,CAAW,CAAC,GAElFwB,EAAU,MAAM;AACd,QAAK5E;AACL,aAAAA,EAAc,UAAUoD,GACjB,MAAM;AACX,QAAIpD,EAAc,YAAYoD,MAC5BpD,EAAc,UAAU;AAAA,MAE5B;AAAA,EACF,GAAG,CAACA,GAAeoD,CAAW,CAAC,GAE/BwB;AAAA,IACE,MAAM,MAAM;AACV,MAAAyV,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAC9CC,EAAO,YAAY,SACrB,qBAAqBA,EAAO,OAAO,GACnCA,EAAO,UAAU,OAEnBla,EAAe,UAAU;AAAA,IAC3B;AAAA,IACA,CAAA;AAAA,EAAC,GAID,gBAAA4d,GAAC,OAAA,EAAI,WAAA/d,GAAsB,OAAOoB,GAChC,UAAA;AAAA,IAAA,gBAAA0D;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK7E;AAAA,QACL,OAAO;AAAA,UACL,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,cAAc;AAAA,QAAA;AAAA,QAEhB,eAAemE;AAAA,QACf,eAAeC;AAAA,QACf,aAAaG;AAAA,QACb,iBAAiBA;AAAA,QACjB,eAAe,CAAAzgB,MAAS;AACtB,UAAAA,EAAM,eAAA;AAAA,QACR;AAAA,QACA,SAAS,CAAAA,MAAS;AAChB,UAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AAAA,QACR;AAAA,MAAA;AAAA,IAAA;AAAA,IAEDi3B,KACC,gBAAAlW;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,CAAA/gB,MAAS;AAChB,UAAAA,EAAM,gBAAA,GACNi3B,EAAA;AAAA,QACF;AAAA,QACA,OAAOE,IAAmB,EAAE,GAAIA,MAAuC,EAAE,GAAIlB,GAAA;AAAA,QAE5E,UAAAiB,KAAa;AAAA,MAAA;AAAA,IAAA;AAAA,EAChB,GAEJ;AAEJ;ACpwBA,MAAM+C,KAAgB,mBAChBtrB,KAA6B,CAAA;AAE5B,SAASurB,GAAW,EAAE,SAAAC,GAAS,aAAAzoB,KAA2D;AAC/F,QAAM,EAAE,aAAAgQ,GAAa,sBAAAoP,GAAsB,wBAAAC,GAAwB,sBAAAC,EAAA,IAAyB3P,GAAA,GAEtF+Y,IAAcD,KAAWxrB,IAEzBmO,IAAsBL,GAAQ,MAAMtK,GAAiBtD,IAA4B6C,CAAW,GAAG,CAACA,CAAW,CAAC,GAE5G5L,IAAW2W,GAAkC,MAAM;AACvD,UAAMjY,IAAgC,CAAA;AACtC,aAASnT,IAAI,GAAGA,IAAI+oC,EAAY,QAAQ/oC,KAAK,GAAG;AAC9C,YAAMurB,IAASwd,EAAY/oC,CAAC,GACtBqQ,IAAQ8R,GAA4BoJ,EAAO,WAAW;AAC5D,MAAIlb,EAAM,WAAW,KACrB8C,EAAI,KAAK,EAAE,QAAAoY,GAAQ,aAAavrB,GAAG,WAAWurB,EAAO,MAAMvrB,GAAG,UAAUqQ,EAAA,CAAO;AAAA,IACjF;AACA,WAAO8C;AAAA,EACT,GAAG,CAAC41B,CAAW,CAAC,GAEVxhB,IAAsB2E;AAAA,IAC1B,CAAC5c,MAA+C;AAC9C,YAAM6T,IAAYkN,EAAY;AAC9B,UAAI,CAAClN,KAAa7T,EAAO,WAAW,UAAU,CAAA;AAC9C,YAAM6D,IAAM,IAAI,MAAsB7D,EAAO,MAAM;AACnD,eAAStP,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK,GAAG;AACzC,cAAMsF,IAAQwa,GAAQqD,EAAU,cAAc7T,EAAOtP,CAAC,EAAE,CAAC,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,YAAI,CAACsF,EAAO,QAAO,CAAA;AACnB,QAAA6N,EAAInT,CAAC,IAAIsF;AAAA,MACX;AACA,aAAO6N;AAAA,IACT;AAAA,IACA,CAAA;AAAA,EAAC,GAGGitB,IAAUtV,EAAO,EAAE,UAAArW,GAAU,qBAAAgX,GAAqB,qBAAAlE,GAAqB;AAC7E,SAAA6Y,EAAQ,UAAU,EAAE,UAAA3rB,GAAU,qBAAAgX,GAAqB,qBAAAlE,EAAA,GAEnDgI,EAAU,OAcRkQ,EAAqBmJ,IAAe,IAbvB,CAAC1oB,MAAkC;AAC9C,UAAM,EAAE,UAAU8oB,GAAM,qBAAqBvoB,GAAO,qBAAqB4f,MAAQD,EAAQ;AACzF,eAAWvT,KAASmc;AAClB,iBAAWh2B,KAAW6Z,EAAM,UAAU;AACpC,cAAMM,IAAckT,EAAIrtB,EAAQ,KAAK;AACrC,QAAIma,EAAY,UAAU,KAAG/M,GAASF,GAAKiN,GAAa1M,GAAO,IAAM,EAAK;AAC1E,mBAAWxL,KAAQjC,EAAQ,OAAO;AAChC,gBAAMoa,IAAaiT,EAAIprB,CAAI;AAC3B,UAAImY,EAAW,UAAU,KAAGhN,GAASF,GAAKkN,GAAY3M,GAAO,IAAM,EAAK;AAAA,QAC1E;AAAA,MACF;AAAA,EAEJ,CAC4C,GACrC,MAAMif,EAAuBkJ,EAAa,IAChD,CAACnJ,GAAsBC,CAAsB,CAAC,GAEjDnQ,EAAU,MAAM;AAAE,IAAAoQ,EAAA;AAAA,EAAwB,GAAG,CAAClrB,GAAUgX,GAAqBkU,CAAoB,CAAC,GAE3F;AACT;ACrEO,SAASsJ,GAA0B5yB,GAA4ClB,GAAgE;AACpJ,MAAI,CAACkB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAGT,QAAM5B,IAAWF,GAAmBY,KAAY,EAAE;AAClD,MAAIV,EAAS,WAAW,GAAG;AACzB,UAAMy0B,IAAsB;AAAA,MAC1B,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAEnC,WAAI7yB,EAAU,qBAAqB,eACjC6yB,EAAM,YAAY,IAAI,WAAW,CAAC,IAEhC7yB,EAAU,eAAe,gBAC3B6yB,EAAM,MAAM,IAAI,YAAY,CAAC,IAExBA;AAAA,EACT;AAEA,QAAMjV,IAAQ7d,GAAmBC,CAAS,GACpC0d,IAAY1d,EAAU,WACtBkB,IAAUlB,EAAU,gBACpB8yB,IAAY9yB,EAAU,qBAAqB,cAAcA,EAAU,UAAU,UAAU4d,IAAQ5d,EAAU,YAAY,MACrH+yB,IAAW/yB,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU4d,IAAQ5d,EAAU,MAAM,MAEnGgzB,IAAgB,IAAI,aAAapV,IAAQ,CAAC,GAC1CqV,IAAc,IAAI,YAAYrV,CAAK,GACnCsV,IAAgBJ,IAAY,IAAI,WAAWlV,CAAK,IAAI,MACpDuV,IAAUJ,IAAW,IAAI,YAAYnV,CAAK,IAAI;AACpD,MAAI7Q,IAAS;AAEb,WAASpjB,IAAI,GAAGA,IAAIi0B,GAAOj0B,KAAK,GAAG;AACjC,UAAMW,IAAIozB,EAAU/zB,IAAI,CAAC,GACnB,IAAI+zB,EAAU/zB,IAAI,IAAI,CAAC;AAC7B,IAAKkV,GAA0BvU,GAAG,GAAG8T,CAAQ,MAC7C40B,EAAcjmB,IAAS,CAAC,IAAIziB,GAC5B0oC,EAAcjmB,IAAS,IAAI,CAAC,IAAI,GAChCkmB,EAAYlmB,CAAM,IAAI7L,EAAQvX,CAAC,GAC3BupC,MACFA,EAAcnmB,CAAM,IAAI+lB,EAAWnpC,CAAC,IAElCwpC,MACFA,EAAQpmB,CAAM,IAAIgmB,EAAUppC,CAAC,IAE/BojB,KAAU;AAAA,EACZ;AAEA,QAAM2f,IAAuB;AAAA,IAC3B,OAAO3f;AAAA,IACP,WAAWimB,EAAc,SAAS,GAAGjmB,IAAS,CAAC;AAAA,IAC/C,gBAAgBkmB,EAAY,SAAS,GAAGlmB,CAAM;AAAA,EAAA;AAEhD,SAAImmB,MACFxG,EAAO,YAAYwG,EAAc,SAAS,GAAGnmB,CAAM,IAEjDomB,MACFzG,EAAO,MAAMyG,EAAQ,SAAS,GAAGpmB,CAAM,IAElC2f;AACT;AAEO,SAAS0G,GAA6BpzB,GAA4ClB,GAAwD;AAC/I,MAAI,CAACkB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO,IAAI,YAAY,CAAC;AAG1B,QAAM5B,IAAWF,GAAmBY,KAAY,EAAE;AAClD,MAAIV,EAAS,WAAW;AACtB,WAAO,IAAI,YAAY,CAAC;AAG1B,QAAMwf,IAAQ7d,GAAmBC,CAAS;AAC1C,MAAI4d,MAAU;AACZ,WAAO,IAAI,YAAY,CAAC;AAG1B,QAAMF,IAAY1d,EAAU,WACtBlD,IAAM,IAAI,YAAY8gB,CAAK;AACjC,MAAI7Q,IAAS;AAEb,WAASpjB,IAAI,GAAGA,IAAIi0B,GAAOj0B,KAAK,GAAG;AACjC,UAAMW,IAAIozB,EAAU/zB,IAAI,CAAC,GACnBU,IAAIqzB,EAAU/zB,IAAI,IAAI,CAAC;AAC7B,IAAKkV,GAA0BvU,GAAGD,GAAG+T,CAAQ,MAC7CtB,EAAIiQ,CAAM,IAAIpjB,GACdojB,KAAU;AAAA,EACZ;AAEA,SAAOjQ,EAAI,SAAS,GAAGiQ,CAAM;AAC/B;ACJA,IAAIsmB,KAAuD;AAE3D,MAAMC,KAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiC9B,SAASC,KAAqB;AAC7B,MAAI,OAAO,YAAc,IAAa,QAAO;AAC7C,QAAMC,IAAM;AACZ,SAAO,OAAOA,EAAI,OAAQ,YAAYA,EAAI,QAAQ;AACnD;AAEA,SAASC,KAA2C;AACnD,MAAI,CAACF,GAAA,EAAa,QAAO;AAEzB,QAAMG,IADM,UACI;AAChB,MAAI,CAACA,KAAO,OAAOA,KAAQ,SAAU,QAAO;AAC5C,QAAMC,IAAYD;AAClB,SAAI,OAAOC,EAAU,kBAAmB,aAAmB,OACpDA;AACR;AAEA,MAAMC,KACJ,WAAyD,gBACvD,WAAW,GACTC,KACJ,WAAyD,gBACvD,WAAW,KACTC,KACJ,WAA0D,gBACxD,YAAY,GACVC,KACJ,WAA0D,gBACxD,YAAY,GACVC,KACJ,WAAyD,gBACvD,WAAW,IACTC,KACJ,WAA0D,gBACxD,YAAY,GACVC,KACJ,WAAkD,YAAY,QAAQ;AAExE,eAAsBC,KAAqD;AAC1E,QAAMC,IAASX,GAAA;AACf,MAAI,CAACW;AACJ,WAAO,EAAE,WAAW,IAAO,UAAU,CAAA,EAAC;AAEvC,QAAMC,IAAU,MAAMD,EAAO,eAAA;AAC7B,SAAKC,IAIE;AAAA,IACN,WAAW;AAAA,IACX,aAAaA,EAAQ,MAAM,eAAeA,EAAQ,MAAM,UAAU;AAAA,IAClE,UAAU,MAAM,KAAKA,EAAQ,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACP,6BAA6B;AAAA,QAC5BA,EAAQ,OAAO;AAAA,MAAA;AAAA,MAEhB,mCAAmC;AAAA,QAClCA,EAAQ,OAAO;AAAA,MAAA;AAAA,MAEhB,0BAA0B,OAAOA,EAAQ,OAAO,wBAAwB;AAAA,IAAA;AAAA,EACzE,IAfO,EAAE,WAAW,IAAO,UAAU,CAAA,EAAC;AAiBxC;AAEA,eAAeC,KAA4C;AAC1D,SAAIjB,OACJA,MAAkB,YAAY;AAC7B,UAAMe,IAASX,GAAA;AACf,QAAI,CAACW,EAAQ,QAAO;AACpB,UAAMC,IAAU,MAAMD,EAAO,eAAA;AAC7B,QAAI,CAACC,EAAS,QAAO;AACrB,UAAME,IAAS,MAAMF,EAAQ,cAAA,GAEvBG,IAAkBD,EAAO,sBAAsB;AAAA,MACpD,SAAS;AAAA,QACR;AAAA,UACC,SAAS;AAAA,UACT,YAAYX;AAAA,UACZ,QAAQ,EAAE,MAAM,oBAAA;AAAA,QAAoB;AAAA,QAErC;AAAA,UACC,SAAS;AAAA,UACT,YAAYA;AAAA,UACZ,QAAQ,EAAE,MAAM,oBAAA;AAAA,QAAoB;AAAA,QAErC;AAAA,UACC,SAAS;AAAA,UACT,YAAYA;AAAA,UACZ,QAAQ,EAAE,MAAM,UAAA;AAAA,QAAU;AAAA,QAE3B;AAAA,UACC,SAAS;AAAA,UACT,YAAYA;AAAA,UACZ,QAAQ,EAAE,MAAM,UAAA;AAAA,QAAU;AAAA,MAC3B;AAAA,IACD,CACA,GAEKa,IAAWF,EAAO,sBAAsB;AAAA,MAC7C,QAAQA,EAAO,qBAAqB,EAAE,kBAAkB,CAACC,CAAe,GAAG;AAAA,MAC3E,SAAS;AAAA,QACR,QAAQD,EAAO,mBAAmB,EAAE,MAAMjB,IAAuB;AAAA,QACjE,YAAY;AAAA,MAAA;AAAA,IACb,CACA;AAED,WAAO,EAAE,QAAAiB,GAAQ,UAAAE,GAAU,iBAAAD,EAAA;AAAA,EAC5B,GAAA,GAEOnB;AACR;AAEA,SAASqB,GAAMj4B,GAAetD,GAAsB;AACnD,SAAO,KAAK,KAAKsD,IAAQtD,CAAI,IAAIA;AAClC;AAEA,eAAsBw7B,GACrBjX,GACA4G,GACAthB,GAC8B;AAC9B,QAAM6G,IAAM,MAAMyqB,GAAA;AAClB,MAAI,CAACzqB,EAAK,QAAO;AAEjB,QAAM+T,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAM0G,CAAU,CAAC,GAC1CsQ,IAAc,KAAK,IAAI,GAAG,KAAK,MAAM5xB,EAAO,SAAS,CAAC,CAAC;AAC7D,MAAI4a,MAAU,KAAKgX,MAAgB;AAClC,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAiB,KAAK,IAAIjX,GAAO,KAAK,MAAMF,EAAU,SAAS,CAAC,CAAC;AACvE,MAAImX,MAAmB;AACtB,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAgBD,IAAiB,IAAI,aAAa,mBAClDE,IAAcH,IAAc,IAAI,aAAa,mBAC7CI,IAAcH,IAAiB,YAAY,mBAE3CI,IAAQ,OAAOprB,EAAI,OAAO,OAAO,2BAA2B;AAClE,MAAIirB,IAAgBG,KAASF,IAAcE,KAASD,IAAcC;AACjE,WAAO;AAGR,QAAMC,IAAkBrrB,EAAI,OAAO,aAAa;AAAA,IAC/C,MAAM6qB,GAAMI,GAAe,CAAC;AAAA,IAC5B,OAAOjB,KAA2BC;AAAA,EAAA,CAClC,GACKqB,IAAetrB,EAAI,OAAO,aAAa;AAAA,IAC5C,MAAM6qB,GAAMK,GAAa,CAAC;AAAA,IAC1B,OAAOlB,KAA2BC;AAAA,EAAA,CAClC,GACKsB,IAAevrB,EAAI,OAAO,aAAa;AAAA,IAC5C,MAAM6qB,GAAMM,GAAa,CAAC;AAAA,IAC1B,OAAOnB,KAA2BE;AAAA,EAAA,CAClC,GACKsB,IAAgBxrB,EAAI,OAAO,aAAa;AAAA,IAC7C,MAAM;AAAA,IACN,OAAOmqB,KAA2BF;AAAA,EAAA,CAClC,GACKwB,IAAazrB,EAAI,OAAO,aAAa;AAAA,IAC1C,MAAM6qB,GAAMM,GAAa,CAAC;AAAA,IAC1B,OAAOlB,KAA4BG;AAAA,EAAA,CACnC;AAED,MAAIsB,IAAmB;AACvB,MAAI;AACH,IAAA1rB,EAAI,OAAO,MAAM;AAAA,MAChBqrB;AAAA,MACA;AAAA,MACAxX,EAAU;AAAA,MACVA,EAAU;AAAA,MACVoX;AAAA,IAAA,GAEDjrB,EAAI,OAAO,MAAM;AAAA,MAChBsrB;AAAA,MACA;AAAA,MACAnyB,EAAO;AAAA,MACPA,EAAO;AAAA,MACP+xB;AAAA,IAAA,GAEDlrB,EAAI,OAAO,MAAM;AAAA,MAChBwrB;AAAA,MACA;AAAA,MACA,IAAI,YAAY,CAACR,GAAgBD,GAAa,GAAG,CAAC,CAAC;AAAA,IAAA;AAGpD,UAAMY,IAAY3rB,EAAI,OAAO,gBAAgB;AAAA,MAC5C,QAAQA,EAAI;AAAA,MACZ,SAAS;AAAA,QACR,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQqrB,IAAgB;AAAA,QAClD,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAa;AAAA,QAC/C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAa;AAAA,QAC/C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAc;AAAA,MAAE;AAAA,IACnD,CACA,GAEKI,IAAiB5rB,EAAI,OAAO,qBAAA,GAC5BzE,IAAOqwB,EAAe,iBAAA;AAC5B,IAAArwB,EAAK,YAAYyE,EAAI,QAAQ,GAC7BzE,EAAK,aAAa,GAAGowB,CAAS,GAC9BpwB,EAAK,mBAAmB,KAAK,KAAKyvB,IAAiB,GAAG,CAAC,GACvDzvB,EAAK,IAAA,GAELqwB,EAAe,mBAAmBL,GAAc,GAAGE,GAAY,GAAGN,CAAW,GAC7EnrB,EAAI,OAAO,MAAM,OAAO,CAAC4rB,EAAe,OAAA,CAAQ,CAAC,GAEjD,MAAMH,EAAW,SAASpB,EAAiB,GAC3CqB,IAAmB;AACnB,UAAMG,IAASJ,EAAW,eAAA;AAC1B,WAAO,IAAI,YAAYI,EAAO,MAAM,CAAC,CAAC;AAAA,EACvC,UAAA;AACC,QAAIH;AACH,UAAI;AACH,QAAAD,EAAW,MAAA;AAAA,MACZ,QAAQ;AAAA,MAER;AAED,IAAAJ,EAAgB,QAAA,GAChBC,EAAa,QAAA,GACbC,EAAa,QAAA,GACbC,EAAc,QAAA,GACdC,EAAW,QAAA;AAAA,EACZ;AACD;ACzUA,eAAsBK,GACpB31B,GACAlB,GACA5Z,IAAkC,CAAA,GACF;AAChC,QAAMod,IAAQxC,GAAA,GACR81B,IAAe1wC,EAAQ,iBAAiB;AAC9C,MAAI,CAAC8a,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYF,OAAUwC;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAMlE,IAAWF,GAAmBY,KAAY,EAAE;AAClD,MAAIV,EAAS,WAAW,GAAG;AACzB,UAAMklB,IAAqB;AAAA,MACzB,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAEnC,WAAItjB,EAAU,qBAAqB,eACjCsjB,EAAK,YAAY,IAAI,WAAW,CAAC,IAE/BtjB,EAAU,eAAe,gBAC3BsjB,EAAK,MAAM,IAAI,YAAY,CAAC,IAEvB;AAAA,MACL,MAAAA;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYxjB,OAAUwC;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,QAAMuzB,IAAY91B,GAAmBC,CAAS,GACxC81B,IAAiB91B,EAAU,qBAAqB,cAAcA,EAAU,UAAU,UAAU61B,IAAY71B,EAAU,YAAY,MAC9H+yB,IAAW/yB,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU61B,IAAY71B,EAAU,MAAM;AAC7G,MAAI61B,MAAc,GAAG;AACnB,UAAMvS,IAAqB;AAAA,MACzB,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAEnC,WAAIwS,MACFxS,EAAK,YAAY,IAAI,WAAW,CAAC,IAE/ByP,MACFzP,EAAK,MAAM,IAAI,YAAY,CAAC,IAEvB;AAAA,MACL,MAAAA;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYxjB,OAAUwC;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,QAAMyzB,IAAW,IAAI,aAAa33B,EAAS,SAAS,CAAC;AACrD,WAASzU,IAAI,GAAGA,IAAIyU,EAAS,QAAQzU,KAAK,GAAG;AAC3C,UAAM+gB,IAAO/gB,IAAI,GACXgT,IAAUyB,EAASzU,CAAC;AAC1B,IAAAosC,EAASrrB,CAAI,IAAI/N,EAAQ,MACzBo5B,EAASrrB,IAAO,CAAC,IAAI/N,EAAQ,MAC7Bo5B,EAASrrB,IAAO,CAAC,IAAI/N,EAAQ,MAC7Bo5B,EAASrrB,IAAO,CAAC,IAAI/N,EAAQ;AAAA,EAC/B;AAEA,MAAIq5B,IAAoC,MACpCC,IAAa;AACjB,MAAI;AACF,IAAAD,IAAgB,MAAMrB,GAA8B30B,EAAU,WAAW61B,GAAWE,CAAQ,GAC5FE,IAAa,CAAC,CAACD;AAAA,EACjB,QAAQ;AACN,IAAAA,IAAgB,MAChBC,IAAa;AAAA,EACf;AAEA,MAAI,CAACD;AAEH,WAAO;AAAA,MACL,MAFepD,GAA0B5yB,GAAWlB,CAAQ;AAAA,MAG5D,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYgB,OAAUwC;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgBuzB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,MAAIK,IAAiB;AACrB,WAASvsC,IAAI,GAAGA,IAAIksC,GAAWlsC,KAAK;AAClC,IAAIqsC,EAAcrsC,CAAC,MAAM,MAAGusC,KAAkB;AAGhD,QAAMC,IAAmB,IAAI,YAAYD,CAAc;AACvD,MAAIA,IAAiB,GAAG;AACtB,QAAIE,IAAkB;AACtB,aAASzsC,IAAI,GAAGA,IAAIksC,GAAWlsC,KAAK;AAClC,MAAIqsC,EAAcrsC,CAAC,MAAM,MACzBwsC,EAAiBC,CAAe,IAAIzsC,GACpCysC,KAAmB;AAAA,EAEvB;AAEA,MAAIF,MAAmB,GAAG;AACxB,QAAIN,GAAc;AAChB,YAAMtS,IAAqB;AAAA,QACzB,OAAOuS;AAAA,QACP,WAAW71B,EAAU,UAAU,SAAS,GAAG61B,IAAY,CAAC;AAAA,QACxD,gBAAgB71B,EAAU,eAAe,SAAS,GAAG61B,CAAS;AAAA,QAC9D,aAAa,IAAI,YAAY,CAAC;AAAA,MAAA;AAEhC,aAAIC,MACFxS,EAAK,YAAYwS,EAAe,SAAS,GAAGD,CAAS,IAEnD9C,MACFzP,EAAK,MAAMyP,EAAS,SAAS,GAAG8C,CAAS,IAEpC;AAAA,QACL,MAAAvS;AAAAA,QACA,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,YAAYxjB,OAAUwC;AAAA,UACtB,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,eAAe;AAAA,QAAA;AAAA,MACjB;AAAA,IAEJ;AAEA,UAAMghB,IAAqB;AAAA,MACzB,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAEnC,WAAIwS,MACFxS,EAAK,YAAY,IAAI,WAAW,CAAC,IAE/ByP,MACFzP,EAAK,MAAM,IAAI,YAAY,CAAC,IAEvB;AAAA,MACL,MAAAA;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYxjB,OAAUwC;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,MAAIszB,GAAc;AAChB,UAAMS,IAAc,IAAI,YAAYH,CAAc;AAClD,QAAII,IAAe;AAEnB,aAAS3sC,IAAI,GAAGA,IAAIusC,GAAgBvsC,KAAK,GAAG;AAC1C,YAAMq6B,IAAamS,EAAiBxsC,CAAC,KAAK,GACpCW,IAAI0V,EAAU,UAAUgkB,IAAa,CAAC,GACtC35B,IAAI2V,EAAU,UAAUgkB,IAAa,IAAI,CAAC;AAChD,MAAKnlB,GAA0BvU,GAAGD,GAAG+T,CAAQ,MAC7Ci4B,EAAYC,CAAY,IAAItS,GAC5BsS,KAAgB;AAAA,IAClB;AAEA,UAAMhT,IAAqB;AAAA,MACzB,OAAOuS;AAAA,MACP,WAAW71B,EAAU,UAAU,SAAS,GAAG61B,IAAY,CAAC;AAAA,MACxD,gBAAgB71B,EAAU,eAAe,SAAS,GAAG61B,CAAS;AAAA,MAC9D,aAAaQ,EAAY,SAAS,GAAGC,CAAY;AAAA,IAAA;AAEnD,WAAIR,MACFxS,EAAK,YAAYwS,EAAe,SAAS,GAAGD,CAAS,IAEnD9C,MACFzP,EAAK,MAAMyP,EAAS,SAAS,GAAG8C,CAAS,IAGpC;AAAA,MACL,MAAAvS;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYxjB,OAAUwC;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAA4zB;AAAA,QACA,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,QAAMlD,IAAgB,IAAI,aAAakD,IAAiB,CAAC,GACnDjD,IAAc,IAAI,YAAYiD,CAAc,GAC5ChD,IAAgB4C,IAAiB,IAAI,WAAWI,CAAc,IAAI,MAClE/C,IAAUJ,IAAW,IAAI,YAAYmD,CAAc,IAAI;AAC7D,MAAInpB,IAAS;AAEb,WAASpjB,IAAI,GAAGA,IAAIusC,GAAgBvsC,KAAK,GAAG;AAC1C,UAAMq6B,IAAamS,EAAiBxsC,CAAC,KAAK,GACpCW,IAAI0V,EAAU,UAAUgkB,IAAa,CAAC,GACtC35B,IAAI2V,EAAU,UAAUgkB,IAAa,IAAI,CAAC;AAChD,IAAKnlB,GAA0BvU,GAAGD,GAAG+T,CAAQ,MAC7C40B,EAAcjmB,IAAS,CAAC,IAAIziB,GAC5B0oC,EAAcjmB,IAAS,IAAI,CAAC,IAAI1iB,GAChC4oC,EAAYlmB,CAAM,IAAI/M,EAAU,eAAegkB,CAAU,GACrDkP,MACFA,EAAcnmB,CAAM,IAAI+oB,EAAgB9R,CAAU,IAEhDmP,MACFA,EAAQpmB,CAAM,IAAIgmB,EAAU/O,CAAU,IAExCjX,KAAU;AAAA,EACZ;AAEA,QAAMwpB,IAA4B;AAAA,IAChC,OAAOxpB;AAAA,IACP,WAAWimB,EAAc,SAAS,GAAGjmB,IAAS,CAAC;AAAA,IAC/C,gBAAgBkmB,EAAY,SAAS,GAAGlmB,CAAM;AAAA,EAAA;AAEhD,SAAImmB,MACFqD,EAAY,YAAYrD,EAAc,SAAS,GAAGnmB,CAAM,IAEtDomB,MACFoD,EAAY,MAAMpD,EAAQ,SAAS,GAAGpmB,CAAM,IAGvC;AAAA,IACL,MAAMwpB;AAAA,IACN,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,YAAYz2B,OAAUwC;AAAA,MACtB,YAAY;AAAA,MACZ,gBAAA4zB;AAAA,MACA,eAAe;AAAA,IAAA;AAAA,EACjB;AAEJ;AChRO,MAAMM,GAAkD;AAAA,EAoB7D,YACmBC,GACAC,GACjB;AAtBM,IAAAnxC,EAAA,gBAAwB;AACxB,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,mBAAY;AACH,IAAAA,EAAA,yCAAkB,IAAA;AAElB,IAAAA,EAAA,uBAAgB,CAAC+S,MAAmC;AACnE,YAAMq+B,IAAUr+B,EAAM;AACtB,UAAI,CAACq+B,EAAS;AACd,YAAMC,IAAU,KAAK,YAAY,IAAID,EAAQ,EAAE;AAC/C,MAAKC,MACL,KAAK,YAAY,OAAOD,EAAQ,EAAE,GAClC,KAAK,SAAS,WAAWA,GAASC,CAAO;AAAA,IAC3C;AAEiB,IAAArxC,EAAA,qBAAc,MAAY;AACzC,WAAK,YAAY,IACjB,KAAK,eAAe,gBAAgB;AAAA,IACtC;AAGmB,SAAA,eAAAkxC,GACA,KAAA,WAAAC;AAAA,EAChB;AAAA,EAEH,aAAaE,GAAyD;AACpE,UAAMC,IAAS,KAAK,kBAAA;AACpB,QAAI,CAACA,EAAQ,QAAO;AACpB,UAAMC,IAAK,KAAK;AAChB,gBAAK,YAAY,IAAIA,GAAIF,CAAO,GACzB,EAAE,IAAAE,GAAI,QAAAD,EAAA;AAAA,EACf;AAAA,EAEA,cAAcC,GAAiC;AAC7C,UAAMF,IAAU,KAAK,YAAY,IAAIE,CAAE;AACvC,QAAKF;AACL,kBAAK,YAAY,OAAOE,CAAE,GACnBF;AAAA,EACT;AAAA,EAEA,UAAUhQ,IAAS,qBAA2B;AAC5C,SAAK,eAAeA,CAAM;AAAA,EAC5B;AAAA,EAEQ,oBAAmC;AACzC,QAAI,CAAC,KAAK,UAAW,QAAO;AAC5B,QAAI,KAAK,OAAQ,QAAO,KAAK;AAE7B,QAAI;AACF,YAAMiQ,IAAS,KAAK,aAAA;AACpB,aAAAA,EAAO,iBAAiB,WAAW,KAAK,aAAa,GACrDA,EAAO,iBAAiB,SAAS,KAAK,WAAW,GACjD,KAAK,SAASA,GACPA;AAAA,IACT,QAAQ;AACN,kBAAK,YAAY,IACV;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,eAAejQ,GAAsB;AAC3C,IAAI,KAAK,WACP,KAAK,OAAO,oBAAoB,WAAW,KAAK,aAAa,GAC7D,KAAK,OAAO,oBAAoB,SAAS,KAAK,WAAW,GACzD,KAAK,OAAO,UAAA,GACZ,KAAK,SAAS;AAGhB,UAAMp+B,IAAQ,IAAI,MAAMo+B,CAAM;AAC9B,eAAW,CAAA,EAAGgQ,CAAO,KAAK,KAAK;AAC7B,WAAK,SAAS,cAAcA,GAASpuC,CAAK;AAE5C,SAAK,YAAY,MAAA;AAAA,EACnB;AACF;ACxCA,MAAMuuC,KAAe,IAAIP;AAAA,EACvB,MAAM,IAAI,OAAO,IAAA;AAAA;AAAA,IAAA;IAAA,YAAA;AAAA,EAAA,GAA2D,EAAE,MAAM,SAAA,CAAU;AAAA,EAC9F;AAAA,IACE,YAAY,CAACQ,GAAKJ,MAAY;AAC5B,UAAII,EAAI,SAAS,oBAAoB;AACnC,QAAAJ,EAAQ,OAAO,IAAI,MAAMI,EAAI,SAAS,oBAAoB,CAAC;AAC3D;AAAA,MACF;AAEA,UAAIA,EAAI,SAAS,0BAA0B;AACzC,YAAIJ,EAAQ,SAAS,SAAS;AAC5B,UAAAA,EAAQ,OAAO,IAAI,MAAM,sDAAsD,CAAC;AAChF;AAAA,QACF;AACA,cAAMhZ,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMoZ,EAAI,KAAK,CAAC,GACzCC,IAAU,IAAI,YAAYD,EAAI,OAAO,EAAE,SAAS,GAAGpZ,CAAK;AAC9D,QAAAgZ,EAAQ,QAAQ;AAAA,UACd,SAAAK;AAAA,UACA,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,YACE,OAAO,SAASD,EAAI,UAAU,IAC1BA,EAAI,aACJl3B,GAAA,IAAU82B,EAAQ;AAAA,UAAA;AAAA,QAC1B,CACD;AACD;AAAA,MACF;AAEA,UAAIA,EAAQ,SAAS,QAAQ;AAC3B,QAAAA,EAAQ,OAAO,IAAI,MAAM,iDAAiD,CAAC;AAC3E;AAAA,MACF;AAEA,YAAMhZ,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMoZ,EAAI,KAAK,CAAC,GACzCtZ,IAAY,IAAI,aAAasZ,EAAI,SAAS,GAC1CE,IAAiB,IAAI,YAAYF,EAAI,cAAc,GACnDlE,IAAYkE,EAAI,YAAY,IAAI,WAAWA,EAAI,SAAS,IAAI,MAC5DG,IAAMH,EAAI,MAAM,IAAI,YAAYA,EAAI,GAAG,IAAI,MAC3CtK,IAAuB;AAAA,QAC3B,OAAA9O;AAAA,QACA,WAAWF,EAAU,SAAS,GAAGE,IAAQ,CAAC;AAAA,QAC1C,gBAAgBsZ,EAAe,SAAS,GAAGtZ,CAAK;AAAA,MAAA;AAElD,MAAIkV,MACFpG,EAAO,YAAYoG,EAAU,SAAS,GAAGlV,CAAK,IAE5CuZ,MACFzK,EAAO,MAAMyK,EAAI,SAAS,GAAGvZ,CAAK,IAGpCgZ,EAAQ,QAAQ;AAAA,QACd,MAAMlK;AAAA,QACN,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,YACE,OAAO,SAASsK,EAAI,UAAU,IAC1BA,EAAI,aACJl3B,GAAA,IAAU82B,EAAQ;AAAA,QAAA;AAAA,MAC1B,CACD;AAAA,IACH;AAAA,IACA,eAAe,CAACA,GAASpuC,MAAU;AACjC,MAAAouC,EAAQ,OAAOpuC,CAAK;AAAA,IACtB;AAAA,EAAA;AAEJ;AAEO,SAAS4uC,KAA+B;AAC7CL,EAAAA,GAAa,UAAU,mBAAmB;AAC5C;AAEA,eAAsBM,GAAkCr3B,GAA4ClB,GAAqE;AACvK,MAAI,CAACkB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,EAAE,MAAM,UAAU,YAAY,EAAA;AAAA,IAAE;AAI1C,QAAM61B,IAAY91B,GAAmBC,CAAS,GACxCs3B,IAAgBt3B,EAAU,UAAU,MAAM,GAAG61B,IAAY,CAAC,GAC1D0B,IAAcv3B,EAAU,eAAe,MAAM,GAAG61B,CAAS,GACzD2B,IAAgBx3B,EAAU,qBAAqB,cAAcA,EAAU,UAAU,UAAU61B,IAAY71B,EAAU,UAAU,MAAM,GAAG61B,CAAS,IAAI,MACjJ4B,IAAUz3B,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU61B,IAAY71B,EAAU,IAAI,MAAM,GAAG61B,CAAS,IAAI;AAEhI,SAAO,IAAI,QAAyB,CAAC6B,GAASC,MAAW;AACvD,UAAMC,IAAU93B,GAAA,GACV+3B,IAAgBd,GAAa,aAAa;AAAA,MAC9C,MAAM;AAAA,MACN,SAAAW;AAAA,MACA,QAAAC;AAAA,MACA,SAAAC;AAAA,IAAA,CACD;AAED,QAAI,CAACC,GAAe;AAClB,MAAAH,EAAQ;AAAA,QACN,MAAM9E,GAA0B5yB,GAAWlB,CAAQ;AAAA,QACnD,MAAM,EAAE,MAAM,QAAQ,YAAYgB,GAAA,IAAU83B,EAAA;AAAA,MAAQ,CACrD;AACD;AAAA,IACF;AAEA,UAAMZ,IAA4B;AAAA,MAChC,MAAM;AAAA,MACN,IAAIa,EAAc;AAAA,MAClB,OAAOhC;AAAA,MACP,WAAWyB,EAAc;AAAA,MACzB,gBAAgBC,EAAY;AAAA,MAC5B,WAAWC,GAAe;AAAA,MAC1B,KAAKC,GAAS;AAAA,MACd,UAAU34B,KAAY,CAAA;AAAA,IAAC,GAGnBg5B,IAA2B,CAACR,EAAc,QAAQC,EAAY,MAAM;AAC1E,IAAIC,KAAeM,EAAS,KAAKN,EAAc,MAAM,GACjDC,KAASK,EAAS,KAAKL,EAAQ,MAAM;AAEzC,QAAI;AACF,MAAAI,EAAc,OAAO,YAAYb,GAAKc,CAAQ;AAAA,IAChD,SAAStvC,GAAO;AACd,YAAMuvC,IAAWhB,GAAa,cAAcc,EAAc,EAAE;AAC5D,MAAIE,IACFA,EAAS,OAAOvvC,CAAK,IAErBmvC,EAAOnvC,CAAK;AAAA,IAEhB;AAAA,EACF,CAAC;AACH;AAEA,eAAsBwvC,GAAqCh4B,GAA4ClB,GAA0E;AAC/K,MAAI,CAACkB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,SAAS,IAAI,YAAY,CAAC;AAAA,MAC1B,MAAM,EAAE,MAAM,UAAU,YAAY,EAAA;AAAA,IAAE;AAI1C,QAAM61B,IAAY91B,GAAmBC,CAAS,GACxCs3B,IAAgBt3B,EAAU,UAAU,MAAM,GAAG61B,IAAY,CAAC;AAEhE,SAAO,IAAI,QAA8B,CAAC6B,GAASC,MAAW;AAC5D,UAAMC,IAAU93B,GAAA,GACV+3B,IAAgBd,GAAa,aAAa;AAAA,MAC9C,MAAM;AAAA,MACN,SAAAW;AAAA,MACA,QAAAC;AAAA,MACA,SAAAC;AAAA,IAAA,CACD;AAED,QAAI,CAACC,GAAe;AAClB,MAAAH,EAAQ;AAAA,QACN,SAAStE,GAA6BpzB,GAAWlB,CAAQ;AAAA,QACzD,MAAM,EAAE,MAAM,QAAQ,YAAYgB,GAAA,IAAU83B,EAAA;AAAA,MAAQ,CACrD;AACD;AAAA,IACF;AAEA,UAAMZ,IAA4B;AAAA,MAChC,MAAM;AAAA,MACN,IAAIa,EAAc;AAAA,MAClB,OAAOhC;AAAA,MACP,WAAWyB,EAAc;AAAA,MACzB,UAAUx4B,KAAY,CAAA;AAAA,IAAC;AAGzB,QAAI;AACF,MAAA+4B,EAAc,OAAO,YAAYb,GAAK,CAACM,EAAc,MAAM,CAAC;AAAA,IAC9D,SAAS9uC,GAAO;AACd,YAAMuvC,IAAWhB,GAAa,cAAcc,EAAc,EAAE;AAC5D,MAAIE,IACFA,EAAS,OAAOvvC,CAAK,IAErBmvC,EAAOnvC,CAAK;AAAA,IAEhB;AAAA,EACF,CAAC;AACH;ACjNA,MAAMyvC,KAAqC;AAAA,EACzC,OAAO;AAAA,EACP,WAAW,IAAI,aAAa,CAAC;AAAA,EAC7B,gBAAgB,IAAI,YAAY,CAAC;AACnC;AAEO,SAASC,GACdC,GACAC,GACAp4B,GACAq4B,GACAC,GACqB;AACrB,QAAMC,IAAe9jB,EAAO,CAAC,GACvB,CAAC+jB,GAAiBC,CAAkB,IAAIC,GAA8B14B,CAAS,GAE/EqkB,IAAetP;AAAA,IACnB,MAAMsjB,EAAoB,IAAI,CAAAnjB,MAAU/Y,GAAc+Y,EAAO,WAAW,CAAC,EAAE,OAAO,CAAC3qB,MAAuBA,KAAK,IAAI;AAAA,IACnH,CAAC8tC,CAAmB;AAAA,EAAA;AAGtB,SAAAnf,EAAU,MAAM;AACd,UAAMyf,IAAQ,EAAEJ,EAAa;AAC7B,QAAIjH,IAAY;AAEhB,QAAI,CAAC6G;AACH,aAAAM,EAAmBz4B,CAAS,GACrB,MAAM;AACX,QAAAsxB,IAAY;AAAA,MACd;AAGF,QAAI,CAACtxB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,aAAAy4B,EAAmB,IAAI,GAChB,MAAM;AACX,QAAAnH,IAAY;AAAA,MACd;AAGF,QAAIjN,EAAa,WAAW;AAC1B,aAAAoU,EAAmBR,EAAoB,GACvCK,IAAc;AAAA,QACZ,MAAMF;AAAA,QACN,YAAY;AAAA,QACZ,YAAYp4B,EAAU;AAAA,QACtB,aAAa;AAAA,QACb,cAAc;AAAA,MAAA,CACf,GACM,MAAM;AACX,QAAAsxB,IAAY;AAAA,MACd;AAGF,UAAMsH,IAAc,CAACtV,GAA2BoG,MAAoF;AAClI,UAAI4H,KAAaqH,MAAUJ,EAAa,QAAS;AACjD,YAAMM,IAAa74B,EAAU,OACvB84B,IAAcxV,GAAM,cAAcA,EAAK,YAAY,SAAUA,GAAM,SAAS;AAClF,MAAAmV,EAAmBnV,CAAI,GACvBgV,IAAc;AAAA,QACZ,MAAM5O,EAAM;AAAA,QACZ,YAAYA,EAAM;AAAA,QAClB,YAAAmP;AAAA,QACA,aAAAC;AAAA,QACA,cAAczU,EAAa;AAAA,QAC3B,YAAYqF,EAAM;AAAA,QAClB,gBAAgBA,EAAM;AAAA,QACtB,eAAeA,EAAM;AAAA,MAAA,CACtB;AAAA,IACH;AAyCA,YAvCY,YAA2B;AACrC,UAAI0O,MAAa,QAAQ;AACvB,cAAM91B,IAAQ,YAAY,IAAA,GACpBghB,IAAOsP,GAA0B5yB,GAAWqkB,CAAY;AAC9D,QAAAuU,EAAYtV,GAAM;AAAA,UAChB,MAAM;AAAA,UACN,YAAY,YAAY,QAAQhhB;AAAA,QAAA,CACjC;AACD;AAAA,MACF;AAEA,UAAI81B,MAAa,iBAAiB;AAChC,cAAM10B,IAAS,MAAMiyB,GAAgC31B,GAAWqkB,GAAc,EAAE,cAAc,IAAM;AACpG,QAAAuU,EAAYl1B,EAAO,MAAM;AAAA,UACvB,MAAMA,EAAO,KAAK;AAAA,UAClB,YAAYA,EAAO,KAAK;AAAA,UACxB,YAAYA,EAAO,KAAK;AAAA,UACxB,gBAAgBA,EAAO,KAAK;AAAA,UAC5B,eAAeA,EAAO,KAAK;AAAA,QAAA,CAC5B;AACD;AAAA,MACF;AAEA,UAAI;AACF,cAAMA,IAAS,MAAM2zB,GAAkCr3B,GAAWqkB,CAAY;AAC9E,QAAAuU,EAAYl1B,EAAO,MAAM;AAAA,UACvB,MAAMA,EAAO,KAAK;AAAA,UAClB,YAAYA,EAAO,KAAK;AAAA,QAAA,CACzB;AAAA,MACH,QAAQ;AACN,cAAMpB,IAAQ,YAAY,IAAA,GACpBghB,IAAOsP,GAA0B5yB,GAAWqkB,CAAY;AAC9D,QAAAuU,EAAYtV,GAAM;AAAA,UAChB,MAAM;AAAA,UACN,YAAY,YAAY,QAAQhhB;AAAA,QAAA,CACjC;AAAA,MACH;AAAA,IACF,GAEK,GACE,MAAM;AACX,MAAAgvB,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC6G,GAAkBC,GAAUp4B,GAAWqkB,GAAciU,CAAW,CAAC,GAE9DE;AACT;AC5HO,MAAMO,KAA0B,IAC1BC,KAA0B,MAC1BC,KAA+B,GAC/BC,KAAa;AAsBnB,SAASC,GAASC,GAAeC,GAAeC,GAAsB;AAC3E,UAAUF,IAAQ,WAAaC,IAAQ,cAAe,IAAKC;AAC7D;AAEA,SAASC,GAAgBC,GAAqBC,GAAsBnD,GAA8B;AAChG,MAAIkD,KAAe,KAAKC,KAAgB,KAAKnD,KAAgB,EAAG,QAAO;AACvE,QAAM94B,IAAO,KAAK,IAAI,GAAGg8B,IAAcC,CAAY,GAE7CzzB,IADa,KAAK,KAAKxI,IAAO,KAAK,IAAI,GAAG84B,CAAY,CAAC,IACpC2C;AACzB,SAAO,KAAK,IAAIF,IAAyB,KAAK,IAAIC,IAAyBhzB,CAAG,CAAC;AACjF;AAEA,SAAS0zB,GAAoB1zB,GAAqC6vB,GAAuC;AACvG,MAAI,EAAE7vB,aAAe,gBAAgBA,EAAI,WAAW;AAClD,WAAO;AAGT,MAAI2zB,IAAW;AACf,WAAShwC,IAAI,GAAGA,IAAIqc,EAAI,QAAQrc,KAAK;AACnC,QAAI,EAAAqc,EAAIrc,CAAC,IAAIksC,IACb;AAAA,MAAA8D,IAAW;AACX;AAAA;AAEF,MAAIA;AACF,WAAO3zB;AAGT,QAAM4zB,IAAW,IAAI,YAAY5zB,EAAI,MAAM;AAC3C,MAAI+G,IAAS;AACb,WAASpjB,IAAI,GAAGA,IAAIqc,EAAI,QAAQrc,KAAK;AACnC,IAAIqc,EAAIrc,CAAC,KAAKksC,MACd+D,EAAS7sB,CAAM,IAAI/G,EAAIrc,CAAC,GACxBojB,KAAU;AAEZ,SAAOA,IAAS,IAAI6sB,EAAS,SAAS,GAAG7sB,CAAM,IAAI;AACrD;AAEO,SAAS8sB,GAAmBl5B,GAAiE;AAClG,QAAMid,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMjd,EAAM,KAAK,CAAC,GAC3Cm5B,IAAsB,KAAK,MAAMn5B,EAAM,UAAU,SAAS,CAAC,GAC3Dk1B,IAAY,KAAK,IAAI,GAAG,KAAK,IAAIjY,GAAOkc,CAAmB,CAAC;AAClE,MAAIjE,KAAa;AACf,WAAO;AAGT,QAAMQ,IAAcqD,GAAoB/4B,EAAM,eAAe,MAAMk1B,CAAS,GACtES,IAAeD,IAAcA,EAAY,SAASR;AACxD,MAAIS,MAAiB;AACnB,WAAO;AAGT,QAAMvR,IAAWwU,GAAgB54B,EAAM,aAAaA,EAAM,cAAc21B,CAAY,GAC9EyD,IAAc,IAAMhV,GAEpBiV,IAAa,IAAI,WAAW1D,CAAY,GACxC2D,IAAa,IAAI,WAAW3D,CAAY;AAC9C,MAAI4D,IAAa;AAEjB,MAAI7D;AACF,aAAS1sC,IAAI,GAAGA,IAAI2sC,GAAc3sC,KAAK,GAAG;AACxC,YAAMwwC,IAAK9D,EAAY1sC,CAAC,GAClBykB,IAAKzN,EAAM,UAAUw5B,IAAK,CAAC,GAC3B9rB,IAAK1N,EAAM,UAAUw5B,IAAK,IAAI,CAAC;AACrC,MAAI,CAAC,OAAO,SAAS/rB,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,MAC/C2rB,EAAWE,CAAU,IAAI,KAAK,MAAM9rB,IAAK2rB,CAAW,GACpDE,EAAWC,CAAU,IAAI,KAAK,MAAM7rB,IAAK0rB,CAAW,GACpDG,KAAc;AAAA,IAChB;AAAA;AAEA,aAASvwC,IAAI,GAAGA,IAAIksC,GAAWlsC,KAAK,GAAG;AACrC,YAAMykB,IAAKzN,EAAM,UAAUhX,IAAI,CAAC,GAC1B0kB,IAAK1N,EAAM,UAAUhX,IAAI,IAAI,CAAC;AACpC,MAAI,CAAC,OAAO,SAASykB,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,MAC/C2rB,EAAWE,CAAU,IAAI,KAAK,MAAM9rB,IAAK2rB,CAAW,GACpDE,EAAWC,CAAU,IAAI,KAAK,MAAM7rB,IAAK0rB,CAAW,GACpDG,KAAc;AAAA,IAChB;AAGF,MAAIA,MAAe;AACjB,WAAO;AAGT,MAAIE,IAAiB,KAAK,IAAIF,GAAY,KAAK,IAAI,IAAIA,MAAe,CAAC,CAAC;AACxE,GAAI,CAAC,OAAO,SAASE,CAAc,KAAKA,KAAkB,OACxDA,IAAiBF;AAGnB,MAAIG,IAAe;AACnB,SAAOA,IAAeD,IAAiB,IAAG,CAAAC,MAAiB;AAC3D,MAAIC,IAAWD,IAAe,GAE1BE,IAAe,IAAI,WAAWF,IAAe,CAAC,GAC9CG,IAAiB,IAAI,WAAWH,CAAY;AAChD,EAAAE,EAAa,KAAK,UAAU;AAC5B,MAAIza,IAAY;AAEhB,QAAM2a,IAAgB,IAAI,WAAWP,CAAU;AAE/C,WAASvwC,IAAI,GAAGA,IAAIuwC,GAAYvwC,KAAK,GAAG;AACtC,UAAMsC,IAAK+tC,EAAWrwC,CAAC,GACjBuC,IAAK+tC,EAAWtwC,CAAC;AACvB,QAAI+wC,IAAOvB,GAASltC,GAAIC,GAAIouC,CAAQ;AAEpC,eAAa;AACX,YAAMK,KAAKJ,EAAaG,IAAO,CAAC;AAChC,UAAIC,OAAO,YAAY;AAOrB,YANAJ,EAAaG,IAAO,CAAC,IAAIzuC,GACzBsuC,EAAaG,IAAO,IAAI,CAAC,IAAIxuC,GAC7BsuC,EAAeE,CAAI,IAAI,GACvBD,EAAc9wC,CAAC,IAAI+wC,GACnB5a,KAAa,GAETA,IAAY,IAAIua,IAAe,GAAG;AACpC,gBAAMO,KAASP;AACf,UAAAA,MAAiB,GACjBC,IAAWD,IAAe;AAE1B,gBAAMQ,KAAU,IAAI,WAAWR,IAAe,CAAC,GACzCS,KAAY,IAAI,WAAWT,CAAY;AAC7C,UAAAQ,GAAQ,KAAK,UAAU;AAEvB,mBAAShxC,KAAI,GAAGA,KAAI+wC,IAAQ/wC,MAAK,GAAG;AAClC,gBAAI0wC,EAAa1wC,KAAI,CAAC,MAAM,WAAY;AACxC,kBAAMkxC,IAAMR,EAAa1wC,KAAI,CAAC,GACxBmxC,IAAMT,EAAa1wC,KAAI,IAAI,CAAC;AAClC,gBAAIoxC,IAAK9B,GAAS4B,GAAKC,GAAKV,CAAQ;AACpC,mBAAOO,GAAQI,IAAK,CAAC,MAAM,aAAY,CAAAA,IAAMA,IAAK,IAAKX;AACvD,YAAAO,GAAQI,IAAK,CAAC,IAAIF,GAClBF,GAAQI,IAAK,IAAI,CAAC,IAAID,GACtBF,GAAUG,CAAE,IAAIT,EAAe3wC,EAAC;AAAA,UAClC;AAMA,eAJA0wC,IAAeM,IACfL,IAAiBM,IAEjBJ,IAAOvB,GAASltC,GAAIC,GAAIouC,CAAQ,GAE9BC,EAAaG,IAAO,CAAC,MAAMzuC,KAC3BsuC,EAAaG,IAAO,IAAI,CAAC,MAAMxuC;AAE/B,YAAAwuC,IAAQA,IAAO,IAAKJ;AAEtB,UAAAG,EAAc9wC,CAAC,IAAI+wC;AAAA,QACrB;AACA;AAAA,MACF;AAEA,UAAIC,OAAO1uC,KAAMsuC,EAAaG,IAAO,IAAI,CAAC,MAAMxuC,GAAI;AAClD,QAAAsuC,EAAeE,CAAI,KAAK,GACxBD,EAAc9wC,CAAC,IAAI+wC;AACnB;AAAA,MACF;AAEA,MAAAA,IAAQA,IAAO,IAAKJ;AAAA,IACtB;AAAA,EACF;AAEA,QAAMY,IAAW,IAAI,WAAWpb,IAAY,CAAC,GACvCqb,IAAc,IAAI,YAAYrb,CAAS,GACvCsb,IAAc,IAAI,YAAYtb,CAAS,GACvCub,IAAkB,IAAI,WAAWhB,CAAY;AACnD,EAAAgB,EAAgB,KAAKnC,EAAU;AAE/B,MAAIoC,IAAU,GACV7S,IAAS;AACb,WAAS5+B,IAAI,GAAGA,IAAIwwC,GAAcxwC,KAAK;AACrC,IAAI0wC,EAAa1wC,IAAI,CAAC,MAAM,eAC5BqxC,EAASI,IAAU,CAAC,IAAIf,EAAa1wC,IAAI,CAAC,GAC1CqxC,EAASI,IAAU,IAAI,CAAC,IAAIf,EAAa1wC,IAAI,IAAI,CAAC,GAClDsxC,EAAYG,CAAO,IAAI7S,GACvB2S,EAAYE,CAAO,IAAId,EAAe3wC,CAAC,GACvCwxC,EAAgBxxC,CAAC,IAAIyxC,GACrB7S,KAAU+R,EAAe3wC,CAAC,GAC1ByxC,KAAW;AAGb,QAAMC,IAAe,IAAI,YAAYrB,CAAU,GACzCsB,IAAa,IAAI,YAAY1b,CAAS;AAG5C,MAFA0b,EAAW,IAAIL,CAAW,GAEtB9E;AACF,aAAS1sC,IAAI,GAAGA,IAAIuwC,GAAYvwC,KAAK,GAAG;AACtC,YAAM8xC,IAAKJ,EAAgBZ,EAAc9wC,CAAC,CAAC;AAC3C,MAAA4xC,EAAaC,EAAWC,CAAE,CAAC,IAAIpF,EAAY1sC,CAAC,GAC5C6xC,EAAWC,CAAE,KAAK;AAAA,IACpB;AAAA,OACK;AACL,QAAIC,IAAS;AACb,aAAS/xC,IAAI,GAAGA,IAAIksC,GAAWlsC,KAAK,GAAG;AACrC,YAAMykB,IAAKzN,EAAM,UAAUhX,IAAI,CAAC,GAC1B0kB,IAAK1N,EAAM,UAAUhX,IAAI,IAAI,CAAC;AACpC,UAAI,CAAC,OAAO,SAASykB,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,EAAG;AAClD,YAAMotB,KAAKJ,EAAgBZ,EAAciB,CAAM,CAAC;AAChD,MAAAH,EAAaC,EAAWC,EAAE,CAAC,IAAI9xC,GAC/B6xC,EAAWC,EAAE,KAAK,GAClBC,KAAU;AAAA,IACZ;AAAA,EACF;AAEA,MAAIC,IAAW;AACf,SAAOA,IAAW7b,IAAY,IAAG,CAAA6b,MAAa;AAC9C,QAAMC,IAAYD,IAAW,GACvBE,IAAY,IAAI,WAAWF,CAAQ;AACzC,EAAAE,EAAU,KAAK3C,EAAU;AAEzB,WAASvvC,IAAI,GAAGA,IAAIm2B,GAAWn2B,KAAK,GAAG;AACrC,UAAMsC,IAAKivC,EAASvxC,IAAI,CAAC,GACnBuC,IAAKgvC,EAASvxC,IAAI,IAAI,CAAC;AAC7B,QAAI+wC,IAAOvB,GAASltC,GAAIC,GAAI0vC,CAAS;AACrC,WAAOC,EAAUnB,CAAI,MAAMxB,KAAY,CAAAwB,IAAQA,IAAO,IAAKkB;AAC3D,IAAAC,EAAUnB,CAAI,IAAI/wC;AAAA,EACpB;AAEA,SAAO;AAAA,IACL,UAAAo7B;AAAA,IACA,WAAA8Q;AAAA,IACA,WAAA/V;AAAA,IACA,cAAc6b;AAAA,IACd,WAAAE;AAAA,IACA,UAAAX;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAG;AAAA,EAAA;AAEJ;AClOO,SAASO,GACd/lC,GACAqjC,GACAC,GACQ;AACR,QAAM,EAAE,WAAAwC,GAAW,UAAAX,GAAU,UAAAZ,EAAA,IAAavkC;AAC1C,MAAI2kC,IAAOvB,GAASC,GAAOC,GAAOiB,CAAQ;AAC1C,aAAa;AACX,UAAMmB,IAAKI,EAAUnB,CAAI;AACzB,QAAIe,MAAOvC,GAAY,QAAO;AAC9B,QAAIgC,EAASO,IAAK,CAAC,MAAMrC,KAAS8B,EAASO,IAAK,IAAI,CAAC,MAAMpC,EAAO,QAAOoC;AACzE,IAAAf,IAAQA,IAAO,IAAKJ;AAAA,EACtB;AACF;AAQA,SAASyB,GAAkB/E,GAAiCh3B,GAAuD;AACjH,MAAIg3B,EAAI,aAAa,KAAKA,EAAI,aAAa,EAAG,QAAO;AAErD,QAAMnB,IAAYmB,EAAI;AACtB,SAAO;AAAA,IACL,UAAUA,EAAI;AAAA,IACd,WAAAnB;AAAA,IACA,WAAW71B,EAAU,UAAU,SAAS,GAAG61B,IAAY,CAAC;AAAA,IACxD,KACE71B,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU61B,IAC5D71B,EAAU,IAAI,SAAS,GAAG61B,CAAS,IACnC;AAAA,IACN,cAAcmB,EAAI;AAAA,IAClB,UAAUA,EAAI,eAAe;AAAA,IAC7B,WAAW,IAAI,WAAWA,EAAI,SAAS;AAAA,IACvC,UAAU,IAAI,WAAWA,EAAI,QAAQ;AAAA,IACrC,aAAa,IAAI,YAAYA,EAAI,WAAW;AAAA,IAC5C,aAAa,IAAI,YAAYA,EAAI,WAAW;AAAA,IAC5C,cAAc,IAAI,YAAYA,EAAI,YAAY;AAAA,EAAA;AAElD;AAEA,MAAMD,KAAe,IAAIP;AAAA,EACvB,MACE,IAAI,OAAO,IAAA;AAAA;AAAA,IAAA;IAAA,YAAA;AAAA,EAAA,GAAkE;AAAA,IAC3E,MAAM;AAAA,EAAA,CACP;AAAA,EACH;AAAA,IACE,YAAY,CAACG,GAASC,MAAY;AAChC,UAAID,EAAQ,SAAS,2BAA2B;AAC9C,QAAAC,EAAQ,OAAO,IAAI,MAAMD,EAAQ,SAAS,2BAA2B,CAAC;AACtE;AAAA,MACF;AACA,MAAAC,EAAQ,QAAQmF,GAAkBpF,GAASC,EAAQ,SAAS,CAAC;AAAA,IAC/D;AAAA,IACA,eAAe,CAACA,GAASpuC,MAAU;AACjC,MAAAouC,EAAQ,OAAOpuC,CAAK;AAAA,IACtB;AAAA,EAAA;AAEJ;AAEO,SAASwzC,KAAqC;AACnD,EAAAjF,GAAa,UAAU,mBAAmB;AAC5C;AAEA,SAASkF,GACPj8B,GACA5b,GAC8B;AAC9B,QAAMyxC,IAAY91B,GAAmBC,CAAS;AAC9C,MAAI61B,KAAa,EAAG,QAAO;AAE3B,QAAMnY,IAAY1d,EAAU,UAAU,SAAS,GAAG61B,IAAY,CAAC,GACzDnyB,IAASm2B,GAAmB;AAAA,IAChC,OAAOhE;AAAA,IACP,WAAAnY;AAAA,IACA,aACE1d,EAAU,uBAAuB,cAAcA,EAAU,cAAc;AAAA,IACzE,aAAa5b,GAAQ,SAAS;AAAA,IAC9B,cAAcA,GAAQ,UAAU;AAAA,EAAA,CACjC;AACD,SAAKsf,IAEE;AAAA,IACL,UAAUA,EAAO;AAAA,IACjB,WAAAmyB;AAAA,IACA,WAAAnY;AAAA,IACA,KACE1d,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU61B,IAC5D71B,EAAU,IAAI,SAAS,GAAG61B,CAAS,IACnC;AAAA,IACN,cAAcnyB,EAAO;AAAA,IACrB,UAAUA,EAAO,eAAe;AAAA,IAChC,WAAWA,EAAO;AAAA,IAClB,UAAUA,EAAO;AAAA,IACjB,aAAaA,EAAO;AAAA,IACpB,aAAaA,EAAO;AAAA,IACpB,cAAcA,EAAO;AAAA,EAAA,IAhBH;AAkBtB;AAEA,eAAsBw4B,GACpBl8B,GACA5b,GACuC;AACvC,MAAI,CAAC4b,KAAa,CAACA,EAAU,aAAa,CAACA,EAAU;AACnD,WAAO;AAGT,QAAM61B,IAAY91B,GAAmBC,CAAS;AAC9C,SAAI61B,KAAa,IAAU,OAEpB,IAAI,QAAsC,CAAC6B,GAASC,MAAW;AACpE,UAAMf,IAA0B;AAAA,MAC9B,SAAAc;AAAA,MACA,QAAAC;AAAA,MACA,WAAA33B;AAAA,IAAA,GAEI63B,IAAgBd,GAAa,aAAaH,CAAO;AACvD,QAAI,CAACiB,KAAiB,CAACA,EAAc,QAAQ;AAC3C,MAAAH,EAAQuE,GAAkBj8B,GAAW5b,CAAM,CAAC;AAC5C;AAAA,IACF;AAEA,UAAMkzC,IAAgBt3B,EAAU,UAAU,MAAM,GAAG61B,IAAY,CAAC,GAC1DsG,IACJn8B,EAAU,uBAAuB,eACjCA,EAAU,YAAY,SAAS,IAC3BA,EAAU,YAAY,MAAA,IACtB,QAEAg3B,IAAkC;AAAA,MACtC,MAAM;AAAA,MACN,IAAIa,EAAc;AAAA,MAClB,OAAOhC;AAAA,MACP,WAAWyB,EAAc;AAAA,MACzB,aAAa6E,GAAiB;AAAA,MAC9B,aAAa/3C,GAAQ,SAAS;AAAA,MAC9B,cAAcA,GAAQ,UAAU;AAAA,IAAA,GAE5B0zC,IAA2B,CAACR,EAAc,MAAM;AACtD,IAAI6E,KAAiBrE,EAAS,KAAKqE,EAAgB,MAAM;AAEzD,QAAI;AACF,MAAAtE,EAAc,OAAO,YAAYb,GAAKc,CAAQ;AAAA,IAChD,SAAStvC,GAAO;AACd,YAAMuvC,IAAWhB,GAAa,cAAcc,EAAc,EAAE;AAC5D,MAAIE,IACFA,EAAS,OAAOvvC,CAAK,IAErBmvC,EAAOnvC,CAAK;AAAA,IAEhB;AAAA,EACF,CAAC;AACH;AC5KA,MAAM4zC,KAAyB,MACzBC,KAA0B;AAQzB,SAASC,GACd9D,GACAp0C,GACAm4C,GACAC,GACAC,GACAC,GACA1iB,GACA2iB,GACuB;AACvB,QAAMC,IAA2B,GAAQL,KAAgBC,KAAgBC,IACnE,CAACI,GAAmBC,CAAoB,IAAIpE,GAAuC,IAAI,GACvFqE,IAAuBtoB,EAAsB,IAAI,GACjDuoB,IAAoBvoB,EAAsB,IAAI;AAEpD,EAAAyE,EAAU,MAAM;AACd,QAAI,CAAC0jB,KAA4B,CAACpE,GAAiB;AACjD,MAAAsE,EAAqB,IAAI;AACzB;AAAA,IACF;AACA,QAAIxL,IAAY;AAEhB,WAAA4K,GAA4B1D,GAAiBp0C,CAAM,EAAE,KAAK,CAAA64C,MAAa;AACrE,MAAK3L,KAAWwL,EAAqBG,CAAS;AAAA,IAChD,CAAC,GAEM,MAAM;AACX,MAAA3L,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACsL,GAA0BpE,GAAiBp0C,CAAM,CAAC;AAEtD,QAAM84C,IAAuBrnB;AAAA,IAC3B,CAACsnB,MAAqD;AACpD,YAAMrW,IAAW9M,EAAY;AAC7B,UAAI,CAAC8M,KAAY,CAAC+V,EAAmB,QAAO;AAE5C,YAAM,IAAI,OAAOM,EAAW,CAAC,CAAC,GACxB9yC,IAAI,OAAO8yC,EAAW,CAAC,CAAC;AAC9B,UAAI,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS9yC,CAAC,EAAG,QAAO;AAEvD,YAAM1E,IAAO,KAAK,IAAI,MAAMmhC,EAAS,aAAA,EAAe,IAAI,GAClDsW,IAActW,EAAS,aAAa6V,CAAY,GAEhDU,IADc,KAAK,IAAIhB,IAAyBe,IAAchB,EAAsB,IACrDz2C;AACrC,UAAI,CAAC,OAAO,SAAS03C,CAAc,KAAKA,KAAkB,EAAG,QAAO;AAEpE,YAAM,EAAE,UAAAtY,GAAU,aAAAoW,GAAa,aAAAC,GAAa,cAAckC,GAAQ,WAAWC,GAAQ,WAAA1H,EAAA,IAAcgH,GAC7FW,IAAY,KAAK,MAAM,IAAIzY,CAAQ,GACnC0Y,IAAY,KAAK,MAAMpzC,IAAI06B,CAAQ,GACnC2Y,IAAa,KAAK,IAAI,GAAG,KAAK,KAAKL,IAAiBtY,CAAQ,CAAC,GAC7DngB,KAAWy4B,IAAiBA;AAElC,UAAIM,KAAe,IACfC,KAAeh5B,IACfi5B,KAAW,GACXC,KAAW;AAEf,eAAS7xC,IAAKuxC,IAAYE,GAAYzxC,KAAMuxC,IAAYE,GAAYzxC,KAAM;AACxE,iBAASC,IAAKuxC,IAAYC,GAAYxxC,KAAMuxC,IAAYC,GAAYxxC,KAAM,GAAG;AAC3E,gBAAMuvC,KAAKK,GAAgBe,GAAmB5wC,GAAIC,CAAE;AACpD,cAAIuvC,KAAK,EAAG;AAEZ,gBAAMsC,KAAM5C,EAAYM,EAAE,GACpBl5B,IAAMw7B,KAAM3C,EAAYK,EAAE;AAChC,mBAAS9xC,KAAIo0C,IAAKp0C,KAAI4Y,GAAK5Y,MAAK,GAAG;AACjC,kBAAMq6B,KAAasZ,EAAO3zC,EAAC;AAC3B,gBAAIq6B,MAAc6R,EAAW;AAE7B,kBAAMznB,KAAKmvB,EAAOvZ,KAAa,CAAC,GAC1B3V,KAAKkvB,EAAOvZ,KAAa,IAAI,CAAC,GAC9B/9B,KAAKmoB,KAAK,GACVloB,KAAKmoB,KAAKhkB,GACVya,KAAQ7e,KAAKA,KAAKC,KAAKA;AAC7B,YAAI4e,KAAQ84B,OAEZA,KAAe94B,IACf64B,KAAe3Z,IACf6Z,KAAWzvB,IACX0vB,KAAWzvB;AAAA,UACb;AAAA,QACF;AAGF,UAAIsvB,KAAe,EAAG,QAAO;AAC7B,YAAMK,IAAUnB,EAAkB,MAAM,OAAOA,EAAkB,IAAIc,EAAY,CAAC,IAAI;AACtF,aAAO;AAAA,QACL,OAAOA;AAAA,QACP,IAAIK;AAAA,QACJ,YAAY,CAAC,GAAG3zC,CAAC;AAAA,QACjB,iBAAiB,CAACwzC,IAAUC,EAAQ;AAAA,MAAA;AAAA,IAExC;AAAA,IACA,CAACnB,GAAcE,CAAiB;AAAA,EAAA,GAG5BoB,IAAiBpoB;AAAA,IACrB,CAACyP,GAA2B6X,MAAsC;AAChE,UAAI,CAACZ,EAAc;AACnB,YAAMU,IAAY3X,GAAK,SAAS,MAC1B4Y,IAAS5Y,GAAK,MAAM;AAC1B,MAAIyX,EAAqB,YAAYE,KAAaD,EAAkB,YAAYkB,MAChFnB,EAAqB,UAAUE,GAC/BD,EAAkB,UAAUkB,GAC5B3B,EAAa;AAAA,QACX,OAAOU;AAAA,QACP,IAAIiB;AAAA,QACJ,YAAAf;AAAA,QACA,iBAAiB7X,GAAK,mBAAmB;AAAA,MAAA,CAC1C;AAAA,IACH;AAAA,IACA,CAACiX,CAAY;AAAA,EAAA,GAGT4B,IAAiBtoB;AAAA,IACrB,CAACsnB,GAA4BiB,MAAmB;AAC9C,UAAI,CAAC5B,EAAc;AACnB,YAAMlX,IAAM4X,EAAqBC,CAAU;AAC3C,MAAK7X,KACLkX,EAAa;AAAA,QACX,GAAGlX;AAAA,QACH,QAAA8Y;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC5B,GAAcU,CAAoB;AAAA,EAAA;AAGrC,SAAAhkB,EAAU,MAAM;AACd,QAAKujB;AACL,aAAAA,EAAwB,UAAUS,GAC3B,MAAM;AACX,QAAIT,EAAwB,YAAYS,MACtCT,EAAwB,UAAU;AAAA,MAEtC;AAAA,EACF,GAAG,CAACA,GAAyBS,CAAoB,CAAC,GAElDhkB,EAAU,MAAM;AACd,UAAMmlB,IAAoBtB,EAAqB;AAC/C,IAAIsB,MAAsB,SACtBxB,KAAqBwB,IAAoBxB,EAAkB,cAC/DE,EAAqB,UAAU,MAC/BC,EAAkB,UAAU,MAC5BT,IAAe;AAAA,MACb,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,iBAAiB;AAAA,IAAA,CAClB;AAAA,EACH,GAAG,CAACM,GAAmBN,CAAY,CAAC,GAEpCrjB,EAAU,MAAM;AAAA,EAWhB,GAAG,CAACwjB,GAAUH,CAAY,CAAC,GAEpB,EAAE,sBAAAW,GAAsB,gBAAAe,GAAgB,gBAAAE,EAAA;AACjD;ACnJA,IAAIG,KAAmB;AAEhB,MAAMC,KAAaC,GAA8C,SACtE;AAAA,EACE,MAAAlb,IAAO;AAAA,EACP,SAAAniB,IAAU;AAAA,EACV,YAAAs9B;AAAA,EACA,qBAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,SAAA5W;AAAA,EACA,aAAA6W;AAAA,EACA,kBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,eAAA9V;AAAA,EACA,UAAAmP,IAAW;AAAA,EACX,aAAAE;AAAA,EACA,SAAA0G;AAAA,EACA,SAAAC;AAAA,EACA,QAAAC;AACF,GACAC,GACA;AACA,QAAM,EAAE,aAAAnlB,GAAa,gBAAAC,GAAgB,QAAA71B,EAAA,IAAWu1B,GAAA,GAC1C8iB,IAA0BhoB,EAAsE,IAAI,GACpG2qB,IAAa3qB,EAAO,kBAAkB6pB,IAAkB,EAAE,GAI1D9F,IAAkBN,GAAiB6G,GAAa3G,GAAU9U,GAFnC2F,KAAiBhiB,IAE8CqxB,CAAW,GAEjG,EAAE,sBAAA4E,EAAA,IAAyBZ,GAAgB9D,GAAiBp0C,GAAQ46C,GAASC,GAASxC,GAAyB,UAAUziB,GAAaolB,EAAW,OAAO;AAE9J,SAAAC,GAAoBF,GAAK,OAAO,EAAE,SAASjC,MAAyB,CAACA,CAAoB,CAAC,GAE1FhkB,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,QAAI,CAAC8M,EAAU;AACf,UAAMwY,IAAUF,EAAW;AAC3B,WAAAtY,EAAS,mBAAmBwY,CAAO,GAC5B,MAAM;AACX,MAAAxY,EAAS,qBAAqBwY,CAAO;AAAA,IACvC;AAAA,EACF,GAAG,CAACtlB,GAAaC,CAAc,CAAC,GAEhCf,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,gBAAgB3lB,GAASi+B,EAAW,OAAO;AAAA,EACtD,GAAG,CAACnlB,GAAgB9Y,GAAS6Y,CAAW,CAAC,GAEzCd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,iBAAiBoY,GAAQE,EAAW,OAAO;AAAA,EACtD,GAAG,CAACnlB,GAAgBilB,GAAQllB,CAAW,CAAC,GAExCd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,mBAAmB2X,GAAYW,EAAW,OAAO;AAAA,EAC5D,GAAG,CAACnlB,GAAgBwkB,GAAYzkB,CAAW,CAAC,GAE5Cd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,4BAA4B4X,GAAqBU,EAAW,OAAO;AAAA,EAC9E,GAAG,CAACnlB,GAAgBykB,GAAqB1kB,CAAW,CAAC,GAErDd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,8BAA8B6X,GAAuBS,EAAW,OAAO;AAAA,EAClF,GAAG,CAACnlB,GAAgB0kB,GAAuB3kB,CAAW,CAAC,GAEvDd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAI,CAAC8M,KAAYiB,MAAY,UAC7BjB,EAAS,gBAAgBiB,GAASqX,EAAW,OAAO;AAAA,EACtD,GAAG,CAACnlB,GAAgB8N,GAAS/N,CAAW,CAAC,GAEzCd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAI,CAAC8M,KAAY8X,MAAgB,UACjC9X,EAAS,oBAAoB8X,GAAaQ,EAAW,OAAO;AAAA,EAC9D,GAAG,CAACnlB,GAAgB2kB,GAAa5kB,CAAW,CAAC,GAE7Cd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAI,CAAC8M,KAAY+X,MAAqB,UACtC/X,EAAS,yBAAyB+X,GAAkBO,EAAW,OAAO;AAAA,EACxE,GAAG,CAACnlB,GAAgB4kB,GAAkB7kB,CAAW,CAAC,GAElDd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,uBAAuBgY,GAAgBM,EAAW,OAAO;AAAA,EACpE,GAAG,CAACnlB,GAAgB6kB,GAAgB9kB,CAAW,CAAC,GAEhDd,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KACLA,EAAS,aAAa0R,GAAiB4G,EAAW,OAAO;AAAA,EAC3D,GAAG,CAACnlB,GAAgBue,GAAiBxe,CAAW,CAAC,GAE1C;AACT,CAAC,GAEK/S,KAA6B,CAAA,GCxI7Bs4B,KAA+C,KAC/C93B,KAAuC;AAE7C,SAAS+3B,GAAar9B,GAAmB;AACvC,QAAM7X,IAAI0U,EAAMmD,GAAG,GAAG,CAAC;AACvB,SAAO7X,IAAIA,KAAK,IAAI,IAAIA;AAC1B;AASO,SAASm1C,GACdvrB,GACA8F,GACA0lB,GAC8B;AAC9B,QAAM,CAACrrB,GAA6BsrB,CAA8B,IAAIjH,GAAS,CAAC,GAC1EkH,IAA+BnrB,EAAO,CAAC,GACvCorB,IAAkCprB,EAA4E;AAAA,IAClH,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,IAAI;AAAA,EAAA,CACL,GAEKqrB,IAAiCjqB,EAAY,CAACnwB,MAAiB;AACnE,UAAMq6C,IAAU/gC,EAAMtZ,GAAM,GAAG+hB,EAAoC;AACnE,IAAI,KAAK,IAAIm4B,EAA6B,UAAUG,CAAO,IAAI,SAC/DH,EAA6B,UAAUG,GACvCJ,EAA+BI,CAAO;AAAA,EACxC,GAAG,CAAA,CAAE,GAECC,IAAqCnqB,EAAY,MAAM;AAC3D,UAAMoqB,IAAYJ,EAAgC;AAClD,IAAII,EAAU,UAAU,SACtB,qBAAqBA,EAAU,KAAK,GACpCA,EAAU,QAAQ;AAAA,EAEtB,GAAG,CAAA,CAAE,GAECC,IAA+BrqB;AAAA,IACnC,CAACsqB,MAAmB;AAClB,YAAMC,IAAgBphC,EAAMmhC,GAAQ,GAAG14B,EAAoC,GACrEw4B,IAAYJ,EAAgC,SAC5ChU,IAAO+T,EAA6B;AAC1C,UAAI,KAAK,IAAI/T,IAAOuU,CAAa,IAAI,MAAM;AACzC,QAAAJ,EAAA,GACAC,EAAU,KAAKG,GACfN,EAA+BM,CAAa;AAC5C;AAAA,MACF;AAEA,MAAAJ,EAAA,GACAC,EAAU,UAAU,YAAY,IAAA,GAChCA,EAAU,OAAOpU,GACjBoU,EAAU,KAAKG;AAEf,YAAMjnC,IAAO,CAACknC,MAAsB;AAClC,cAAM98B,IAAUs8B,EAAgC,SAC1CS,IAAU,KAAK,IAAI,GAAGD,IAAY98B,EAAQ,OAAO,GACjDg9B,IAA+DvhC,EAAMshC,IAAUf,IAA8C,GAAG,CAAC,GACjIiB,IAAQhB,GAAae,CAAI,GACzBja,IAAY/iB,EAAQ,QAAQA,EAAQ,KAAKA,EAAQ,QAAQi9B;AAI/D,YAHAV,EAA+BxZ,CAAS,GACxCoZ,EAAkB,UAAA,GAEda,KAAQ,GAAG;AACb,UAAAh9B,EAAQ,QAAQ,MAChBu8B,EAA+Bv8B,EAAQ,EAAE;AACzC;AAAA,QACF;AACA,QAAAA,EAAQ,QAAQ,sBAAsBpK,CAAI;AAAA,MAC5C;AAEA,MAAA8mC,EAAU,QAAQ,sBAAsB9mC,CAAI;AAAA,IAC9C;AAAA,IACA,CAAC2mC,GAAgCE,CAAkC;AAAA,EAAA,GAG/DS,IAAgC5qB;AAAA,IACpC,CAAClwB,MAAoC;AACnC,YAAMmhC,IAAW9M,EAAY;AAC7B,UAAI,CAAC8M,KAAY,OAAOnhC,KAAS,YAAY,CAAC,OAAO,SAASA,CAAI,GAAG;AACnE,QAAAu6C,EAA6B,CAAC;AAC9B;AAAA,MACF;AACA,YAAMC,IAASxxB,GAAmCuF,GAA8BvuB,GAAMmhC,EAAS,aAAA,GAAgBA,EAAS,+BAA+B;AACvJ,MAAAoZ,EAA6BC,CAAM;AAAA,IACrC;AAAA,IACA,CAACjsB,GAA8BgsB,CAA4B;AAAA,EAAA;AAG7D,SAAAhnB,EAAU,MACD,MAAM;AACX,IAAA8mB,EAAA;AAAA,EACF,GACC,CAACA,CAAkC,CAAC,GAEhC;AAAA,IACL,6BAAA3rB;AAAA,IACA,+BAAAosB;AAAA,IACA,oCAAAT;AAAA,IACA,gCAAAF;AAAA,EAAA;AAEJ;ACzGA,MAAMY,KAAiC;AAUhC,SAASC,GAAgBzrB,GAAmBnf,GAAgC;AACjF,SAAOmf,EAAO,MAAMnf;AACtB;AAEA,SAAS6qC,GAAuBxyB,GAAYC,GAAYnnB,GAAYE,GAAYD,GAAYE,GAAoB;AAC9G,QAAM+c,IAAMjd,IAAKD,GACXmd,IAAMhd,IAAKD,GACXy5C,IAAWz8B,IAAMA,IAAMC,IAAMA;AACnC,MAAIw8B,KAAY,OAAO;AACrB,UAAM56C,IAAKmoB,IAAKlnB,GACVhB,IAAKmoB,IAAKjnB;AAChB,WAAOnB,IAAKA,IAAKC,IAAKA;AAAAA,EACxB;AACA,QAAMic,IAAInD,IAAQoP,IAAKlnB,KAAMkd,KAAOiK,IAAKjnB,KAAMid,KAAOw8B,GAAU,GAAG,CAAC,GAC9D7P,IAAK9pC,IAAKkd,IAAMjC,GAChB8uB,IAAK7pC,IAAKid,IAAMlC,GAChBlc,IAAKmoB,IAAK4iB,GACV9qC,IAAKmoB,IAAK4iB;AAChB,SAAOhrC,IAAKA,IAAKC,IAAKA;AACxB;AAEA,SAAS46C,GAAgBx2C,GAAWD,GAAW0J,GAAwBgtC,GAAgC;AACrG,WAAS,IAAI,GAAG,IAAIhtC,EAAK,QAAQ,KAAK,GAAG;AACvC,UAAMgJ,IAAOhJ,EAAK,IAAI,CAAC,GACjBrO,IAAOqO,EAAK,CAAC;AACnB,QAAI6sC,GAAuBt2C,GAAGD,GAAG0S,EAAK,CAAC,GAAGA,EAAK,CAAC,GAAGrX,EAAK,CAAC,GAAGA,EAAK,CAAC,CAAC,KAAKq7C;AACtE,aAAO;AAAA,EAEX;AACA,SAAO;AACT;AAEA,SAASC,GAA0B12C,GAAWD,GAAWsS,GAA6BskC,GAA8B;AAClH,MAAI32C,IAAIqS,EAAQ,OAAOskC,KAAe32C,IAAIqS,EAAQ,OAAOskC,KAAe52C,IAAIsS,EAAQ,OAAOskC,KAAe52C,IAAIsS,EAAQ,OAAOskC;AAC3H,WAAO;AAET,QAAMF,IAAgBE,IAAcA;AACpC,MAAIH,GAAgBx2C,GAAGD,GAAGsS,EAAQ,OAAOokC,CAAa,EAAG,QAAO;AAChE,aAAWniC,KAAQjC,EAAQ;AACzB,QAAImkC,GAAgBx2C,GAAGD,GAAGuU,GAAMmiC,CAAa,EAAG,QAAO;AAEzD,SAAO;AACT;AAEO,SAASG,GACdhsB,GACAisB,GACAra,GACA3S,GACA1G,GACAuC,GACAC,GACAC,GACS;AACT,MAAI,CAACgF,EAAO,MAAO,QAAO;AAE1B,QAAMoC,IAAevJ;AAAA,IACnBmH,EAAO;AAAA,IACP,CAAAjc,MAAU;AACR,YAAM8tB,IAA8B,CAAA;AACpC,eAASp9B,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK,GAAG;AACzC,cAAMsF,IAAQua,GAAiBsd,EAAS,cAAc7tB,EAAOtP,CAAC,EAAE,CAAC,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC,CAAC;AACjF,YAAI,CAACsF,EAAO,QAAO,CAAA;AACnB,QAAA83B,EAAU,KAAK93B,CAAK;AAAA,MACtB;AACA,aAAO83B;AAAA,IACT;AAAA,IACA5S;AAAA,EAAA;AAEF,MAAI,CAACmD,EAAc,QAAO;AAG1B,QAAMnH,IADY5C,GAAsB2H,EAAO,OAAOzH,CAAU,IACnCA,EAAW,WAAW,GAC7C2C,IAAY3C,EAAW,WAAWA,EAAW,WAAW,GAExD4C,IAAOiH,EAAa,CAAC,GACrBhH,IAAOgH,EAAa,CAAC,IAAI7J,EAAW,SACpCnjB,IAAI4lB,IAAkBlR,EAAMqR,GAAMF,IAAW,MAAM,GAAGH,IAAcG,IAAW,MAAM,CAAC,IAAIE,GAC1FhmB,IAAI6lB,IAAkBlR,EAAMsR,GAAMF,IAAY,MAAM,GAAGH,IAAeG,IAAY,MAAM,CAAC,IAAIE,GAC7FC,IAAOjmB,IAAI6lB,IAAW,KACtBoR,IAAQj3B,IAAI6lB,IAAW,KACvBK,IAAMnmB,IAAI+lB,IAAY,KACtB2hB,IAAS1nC,IAAI+lB,IAAY;AAE/B,SAAO+wB,EAAY,CAAC,KAAK5wB,KAAQ4wB,EAAY,CAAC,KAAK5f,KAAS4f,EAAY,CAAC,KAAK3wB,KAAO2wB,EAAY,CAAC,KAAKpP;AACzG;AAEO,SAASqP,GAAkB3O,GAA2C;AAC3E,QAAM31B,IAA2B,CAAA;AACjC,WAASnT,IAAI,GAAGA,IAAI8oC,EAAQ,QAAQ9oC,KAAK,GAAG;AAC1C,UAAMurB,IAASud,EAAQ9oC,CAAC,GAClBmV,IAAWZ,GAAmB,CAAC/B,GAAc+Y,GAAQ,WAAW,CAAC,CAAC;AACxE,QAAIpW,EAAS,WAAW,EAAG;AAC3B,UAAM0O,IAAQ,OAAO0H,GAAQ,SAAU,WAAWA,EAAO,MAAM,SAAS;AACxE,IAAApY,EAAI,KAAK;AAAA,MACP,QAAAoY;AAAA,MACA,aAAavrB;AAAA,MACb,UAAUg3C,GAAgBzrB,GAAQvrB,CAAC;AAAA,MACnC,UAAAmV;AAAA,MACA,OAAA0O;AAAA,IAAA,CACD;AAAA,EACH;AACA,SAAO1Q;AACT;AAEO,SAASukC,GACdpyC,GACAkyC,GACA1O,GACA3L,GACA3S,GACA1G,GACA6zB,GACAC,GACAvxB,GACAC,GACAmE,IAA6B,IAKtB;AACP,QAAM9pB,IAAI2E,EAAM,CAAC,GACX5E,IAAI4E,EAAM,CAAC,GACXtJ,IAAO,KAAK,IAAI,MAAMmhC,EAAS,aAAA,EAAe,IAAI,GAClDzP,IAAsB,KAAK,IAAI,GAAGkqB,CAAqB,GACvDC,IAAqBd,KAAiC/6C;AAC5D,WAASgE,IAAI8oC,EAAQ,SAAS,GAAG9oC,KAAK,GAAGA,KAAK,GAAG;AAC/C,UAAMurB,IAASud,EAAQ9oC,CAAC;AACxB,eAAWgT,KAAWuY,EAAO;AAC3B,UAAK8rB,GAA0B12C,GAAGD,GAAGsS,GAAS6kC,CAAkB;AAChE,eAAO;AAAA,UACL,QAAQtsB,EAAO;AAAA,UACf,aAAaA,EAAO;AAAA,UACpB,UAAUA,EAAO;AAAA,QAAA;AAGrB,QAAIqC,IAAoB7I;AAAA,MACtBjB;AAAA,MACA6zB,IAAqB;AAAA,QACnB,QAAQpsB,EAAO;AAAA,QACf,UAAUA,EAAO;AAAA,QACjB,aAAaA,EAAO;AAAA,QACpB,MAAAvvB;AAAA,MAAA,CACD;AAAA,IAAA;AAQH,QANI0xB,IAAsB,MACxBE,IAAoB;AAAA,MAClB,GAAGA;AAAA,MACH,SAASA,EAAkB,UAAUF;AAAA,IAAA,IAGrC,EAAC6pB,GAAyBhsB,GAAQisB,GAAara,GAAU3S,GAAmBoD,GAAmBvH,GAAaC,GAAcmE,CAA0B;AACxJ,aAAO;AAAA,QACL,QAAQc,EAAO;AAAA,QACf,aAAaA,EAAO;AAAA,QACpB,UAAUA,EAAO;AAAA,MAAA;AAAA,EAErB;AACA,SAAO;AACT;AC3IA,MAAMusB,KAAiC,CAAA,GACjCC,KAA8C,CAAA;AACpD,IAAIC,KAA4B;AAEhC,SAASC,GAA+B53B,GAAmD;AACzF,SAAO;AAAA,IACL,OAAO5C;AAAA,IACP,OAAOC;AAAA,IACP,UAAUL;AAAA,IACV,UAAUgD,EAAY;AAAA,IACtB,SAASA,EAAY;AAAA,IACrB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,eAAe;AAAA,EAAA;AAEnB;AAEO,SAAS63B,GAAY;AAAA,EAC1B,SAAApP;AAAA,EACA,UAAA3zB;AAAA,EACA,aAAagjC;AAAA,EACb,kBAAkBC;AAAA,EAClB,mBAAmBC;AAAA,EACnB,oBAAoBC;AAAA,EACpB,YAAYC;AAAA,EACZ,aAAAC,IAAc;AAAA,EACd,wBAAAC,IAAyB;AAAA,EACzB,sBAAAC,IAAuB;AAAA,EACvB,iBAAiBC;AAAA,EACjB,gBAAgBC;AAAA,EAChB,aAAAnT,IAAc;AAAA,EACd,gBAAAoT;AAAA,EACA,SAAAxD;AAAA,EACA,SAAAC;AACF,GAAgD;AAC9C,QAAM,EAAE,aAAAjlB,GAAa,gBAAAC,GAAgB,WAAAzF,GAAW,cAAAiuB,GAAc,sBAAArZ,GAAsB,wBAAAC,GAAwB,sBAAAC,GAAsB,mBAAAoW,GAAmB,2BAAAgD,GAA2B,eAAAC,GAAe,eAAAC,GAAe,qBAAAC,EAAA,IAAwBlpB,GAAA,GAEhO+Y,IAAcD,KAAWgP,IACzBqB,IAAehkC,KAAY4iC,IAE3BqB,IAAmBhuB,GAAqB,MACxC2d,EAAY,SAAS,IAAUA,IAC/BoQ,EAAa,WAAW,IAAUrB,KAC/BqB,EAAa,IAAI,CAACjmC,GAAa9G,OAAW,EAAE,IAAIA,GAAO,aAAA8G,EAAA,EAAc,GAC3E,CAAC61B,GAAaoQ,CAAY,CAAC,GAExB,CAACE,GAA6BC,CAA8B,IAAIvK,GAAiC,MAAM4J,KAA6B,IAAI,GACxI,CAACY,IAA4BC,EAA6B,IAAIzK,GAAiC,MAAM6J,KAA4B,IAAI,GACrIa,KAAoBd,MAA8B,QAClDe,KAAed,MAA6B,QAC5CzuB,KAAkBsvB,KAAqBd,KAA6B,OAAQU,GAC5EjvB,IAAiBsvB,KAAgBd,KAA4B,OAAQW,IACrEI,IAAqB7uB,EAA+B6tB,KAA6B,IAAI,GACrFiB,IAAoB9uB,EAAsB,IAAI,GAC9C+uB,KAAyB/uB,EAAsB,IAAI;AAEzD,MAAI8uB,EAAkB,YAAY,QAAQC,GAAuB,YAAY,MAAM;AACjF,UAAMC,IAAa9B;AACnB,IAAA4B,EAAkB,UAAU,mBAAmBE,CAAU,IACzDD,GAAuB,UAAU,mBAAmBC,CAAU;AAAA,EAChE;AAEA,EAAAvqB,EAAU,MAAM;AACd,IAAKmqB,MACLF,GAA8BZ,KAA4B,IAAI;AAAA,EAChE,GAAG,CAACc,IAAcd,CAAwB,CAAC,GAE3CrpB,EAAU,MAAM;AACd,QAAI,CAACkqB,GAAmB;AACxB,UAAM19C,IAAO48C,KAA6B;AAC1C,IAAAgB,EAAmB,UAAU59C,GAC7Bu9C,EAA+Bv9C,CAAI;AAAA,EACrC,GAAG,CAAC09C,IAAmBd,CAAyB,CAAC;AAEjD,QAAMoB,KAAe7tB;AAAA,IACnB,CAACnwB,MAAiC;AAChC,MAAI,OAAOquB,CAAc,MAAM,OAAOruB,CAAI,MACrC29C,MAAcF,GAA8Bz9C,CAAI,GACrD88C,IAAiB98C,CAAI;AAAA,IACvB;AAAA,IACA,CAACquB,GAAgBsvB,IAAcb,CAAc;AAAA,EAAA,GAGzC,EAAE,6BAAAnuB,GAA6B,+BAAAosB,GAAA,IAAkChB,GAAuB2C,GAAwBpoB,GAAa0lB,CAAiB,GAE9ItqB,KAAsBL,GAAQ,MAAM5K,GAAmB23B,CAAe,GAAG,CAACA,CAAe,CAAC,GAC1FzsB,KAA2BN,GAAQ,MAAMtK,GAAiB2K,IAAqB2sB,CAAoB,GAAG,CAAC3sB,IAAqB2sB,CAAoB,CAAC,GACjJzsB,KAA4BP,GAAQ,MAAMtK,GAAiB2K,IAAqB4sB,CAAqB,GAAG,CAAC5sB,IAAqB4sB,CAAqB,CAAC,GAEpJ,EAAE,kBAAA2B,IAAkB,oBAAArC,GAAA,IAAuBvsB,GAAQ,MACnD,OAAOmtB,KAAmB,aACrB,EAAE,kBAAkB,QAAW,oBAAoBA,EAAA,IAErD,EAAE,kBAAkBA,GAAgB,oBAAoB,OAAA,GAC9D,CAACA,CAAc,CAAC,GAEbzsB,KAAqBV,GAAQ,MAAM5G,GAAwBw1B,EAAgB,GAAG,CAACA,EAAgB,CAAC,GAEhGC,KAAkB7uB,GAAkC,MAAM;AAC9D,UAAMjY,IAAgC,CAAA;AACtC,aAASnT,IAAI,GAAGA,IAAIo5C,EAAiB,QAAQp5C,KAAK,GAAG;AACnD,YAAMurB,KAAS6tB,EAAiBp5C,CAAC,GAC3BqQ,KAAQ8R,GAA4BoJ,GAAO,WAAW;AAC5D,MAAIlb,GAAM,WAAW,KACrB8C,EAAI,KAAK,EAAE,QAAAoY,IAAQ,aAAavrB,GAAG,WAAWurB,GAAO,MAAMvrB,GAAG,UAAUqQ,GAAA,CAAO;AAAA,IACjF;AACA,WAAO8C;AAAA,EACT,GAAG,CAACimC,CAAgB,CAAC,GAEfc,KAAqB9uB,GAAQ,MAAMqsB,GAAkB2B,CAAgB,GAAG,CAACA,CAAgB,CAAC;AAGhG,EAAA7pB,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,QAAK8M;AACL,aAAA2Z,GAA8B3Z,EAAS,aAAA,EAAe,IAAI,GACnD4b,EAA0B,CAAAh9C,MAAQ;AACvC,QAAA+6C,GAA8B/6C,EAAK,IAAI;AAAA,MACzC,CAAC;AAAA,EACH,GAAG,CAACu0B,GAAgByoB,GAA2BjC,EAA6B,CAAC,GAG7EvnB,EAAU,MAAM;AAEd,IAAI,EADcnF,MAAmB,OAAO,KAAOgvB,EAAiB,KAAK,CAACngC,IAAGjZ,MAAM,OAAOg3C,GAAgB/9B,IAAGjZ,CAAC,CAAC,MAAM,OAAOoqB,CAAc,CAAC,MACzHA,MAAmB,WAAmB,IAAI;AAE5D,UAAM+vB,IAAeR,EAAmB;AAExC,IAAI,EADaQ,MAAiB,OAAO,KAAOf,EAAiB,KAAK,CAACngC,IAAGjZ,MAAM,OAAOg3C,GAAgB/9B,IAAGjZ,CAAC,CAAC,MAAM,OAAOm6C,CAAY,CAAC,MACrHA,MAAiB,SAChCR,EAAmB,UAAU,MACxBF,MAAmBH,EAA+B,IAAI,GAC3DjE,IAAU,EAAE,QAAQ,MAAM,UAAU,MAAM,aAAa,IAAI,YAAY,MAAM;AAAA,EAEjF,GAAG,CAAC+D,GAAkBhvB,GAAgBqvB,IAAmBpE,GAAS0E,EAAY,CAAC;AAG/E,QAAMxyB,KAAsB2E;AAAA,IAC1B,CAAC5c,MAA+C;AAC9C,YAAM6T,IAAYkN,EAAY;AAC9B,UAAI,CAAClN,KAAa7T,EAAO,WAAW,UAAU,CAAA;AAC9C,YAAM6D,KAAM,IAAI,MAAsB7D,EAAO,MAAM;AACnD,eAAStP,KAAI,GAAGA,KAAIsP,EAAO,QAAQtP,MAAK,GAAG;AACzC,cAAMsF,IAAQwa,GAAQqD,EAAU,cAAc7T,EAAOtP,EAAC,EAAE,CAAC,GAAGsP,EAAOtP,EAAC,EAAE,CAAC,CAAC,CAAC;AACzE,YAAI,CAACsF,EAAO,QAAO,CAAA;AACnB,QAAA6N,GAAInT,EAAC,IAAIsF;AAAA,MACX;AACA,aAAO6N;AAAA,IACT;AAAA,IACA,CAAA;AAAA,EAAC,GAKGinC,KAAgBtvB,EAAO;AAAA,IAC3B,iBAAAmvB;AAAA,IACA,iBAAA9vB;AAAA,IACA,gBAAAC;AAAA,IACA,qBAAAqB;AAAA,IACA,0BAAAC;AAAA,IACA,2BAAAC;AAAA,IACA,wBAAA2sB;AAAA,IACA,qBAAA/wB;AAAA,EAAA,CACD;AACD,EAAA6yB,GAAc,UAAU;AAAA,IACtB,iBAAAH;AAAA,IACA,iBAAA9vB;AAAA,IACA,gBAAAC;AAAA,IACA,qBAAAqB;AAAA,IACA,0BAAAC;AAAA,IACA,2BAAAC;AAAA,IACA,wBAAA2sB;AAAA,IACA,qBAAA/wB;AAAA,EAAA,GAGFgI,EAAU,MAAM;AACd,UAAM8qB,IAAc,CAACC,OAAmC;AACtD,YAAM;AAAA,QACJ,iBAAiBtR;AAAA,QACjB,iBAAiBuR;AAAA,QACjB,gBAAgB/9B;AAAA,QAChB,qBAAqBuE;AAAA,QACrB,0BAA0By5B;AAAA,QAC1B,2BAA2BC;AAAA,QAC3B,wBAAwBC;AAAA,QACxB,qBAAqBra;AAAA,MAAA,IACnB+Z,GAAc;AAElB,iBAAWvtB,KAASmc,IAAM;AACxB,cAAM,EAAE,QAAAzd,GAAQ,UAAUlb,IAAO,aAAAyc,IAAa,WAAAC,OAAcF,GACtDG,KAAwC/L,GAAezE,IAAQuQ,EAAS,IAAI,WAAW9L,GAAes5B,GAASxtB,EAAS,IAAI,UAAU;AAC5I,YAAItM,IAAQuM,OAAU,WAAWytB,KAAUztB,OAAU,UAAUwtB,KAAQz5B;AAEvE,YAAI25B,IAAU;AACZ,gBAAMztB,IAAWytB,GAAS,EAAE,QAAAnvB,GAAQ,UAAUwB,IAAW,aAAAD,IAAa,OAAAE,IAAO;AAC7E,UAAAvM,IAAQK,GAAiBL,GAAOwM,KAAY,MAAS;AAAA,QACvD;AACA,cAAM0tB,IAAS3tB,OAAU,YAAY,OAAOirB,GAA+Bx3B,CAAK;AAEhF,mBAAWzN,KAAW3C,IAAO;AAC3B,gBAAM8c,IAAckT,EAAIrtB,EAAQ,KAAK;AACrC,UAAIma,EAAY,UAAU,MACpBwtB,KAAQv6B,GAASk6B,IAAMntB,GAAawtB,GAAQ,IAAM,EAAK,GAC3Dv6B,GAASk6B,IAAMntB,GAAa1M,GAAO,IAAM,EAAK;AAEhD,qBAAWxL,KAAQjC,EAAQ,OAAO;AAChC,kBAAMoa,KAAaiT,EAAIprB,CAAI;AAC3B,YAAImY,GAAW,UAAU,MACnButB,KAAQv6B,GAASk6B,IAAMltB,IAAYutB,GAAQ,IAAM,EAAK,GAC1Dv6B,GAASk6B,IAAMltB,IAAY3M,GAAO,IAAM,EAAK;AAAA,UAEjD;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAEMm6B,IAAShB,EAAkB;AACjC,QAAKgB;AACL,aAAAnb,EAAqBmb,GAAQ,IAAIP,CAAW,GACrC,MAAM3a,EAAuBkb,CAAM;AAAA,EAC5C,GAAG,CAACnb,GAAsBC,CAAsB,CAAC;AAIjD,QAAMmb,KAAe/vB,EAAO;AAAA,IAC1B,iBAAAmvB;AAAA,IACA,oBAAAnuB;AAAA,IACA,oBAAA6rB;AAAA,IACA,aAAAa;AAAA,IACA,wBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,6BAAAhuB;AAAA,IACA,aAAA2F;AAAA,EAAA,CACD;AACD,EAAAwqB,GAAa,UAAU;AAAA,IACrB,iBAAAZ;AAAA,IACA,oBAAAnuB;AAAA,IACA,oBAAA6rB;AAAA,IACA,aAAAa;AAAA,IACA,wBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,6BAAAhuB;AAAA,IACA,aAAA2F;AAAA,EAAA,GAGFd,EAAU,MAAM;AACd,UAAMurB,IAAa,CAAC56B,IAA+BmG,IAAqBC,MAAyB;AAC/F,YAAM;AAAA,QACJ,iBAAiB0iB;AAAA,QACjB,oBAAoB+R;AAAA,QACpB,oBAAoBL;AAAA,QACpB,aAAan2B;AAAA,QACb,wBAAwBy2B;AAAA,QACxB,sBAAsBC;AAAA,QACtB,6BAA6BC;AAAA,QAC7B,aAAaC;AAAA,MAAA,IACXN,GAAa;AAEjB,UAAI7R,GAAK,WAAW,EAAG;AAEvB,YAAMhtC,KAAO,KAAK,IAAI,MAAMm/C,EAAK,SAAS,eAAA,EAAiB,QAAQ,CAAC,GAC9DztB,KACJ,OAAOwtB,KAAe,YAAY,OAAO,SAASA,CAAU,IACxD,KAAK,IAAI,GAAGA,CAAU,IACtBl2B,GAAmCg2B,IAAUh/C,IAAMm/C,EAAK,SAAS,kBAAkBA,EAAK,SAAS,iCAAiC;AAExI,iBAAWtuB,MAASmc,IAAM;AACxB,YAAI,CAACnc,GAAM,OAAO,MAAO;AACzB,cAAMc,KAAevJ;AAAA,UACnByI,GAAM;AAAA,UACN,CAAAvd,MAAU;AACR,kBAAM6T,IAAYg4B,EAAK;AACvB,gBAAI,CAACh4B,EAAW,QAAO,CAAA;AACvB,kBAAMhQ,IAAwB,CAAA;AAC9B,qBAASnT,IAAI,GAAGA,IAAIsP,EAAO,QAAQtP,KAAK,GAAG;AACzC,oBAAMsF,KAAQwa,GAAQqD,EAAU,cAAc7T,EAAOtP,CAAC,EAAE,CAAC,GAAGsP,EAAOtP,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,kBAAI,CAACsF,GAAO,QAAO,CAAA;AACnB,cAAA6N,EAAI,KAAK7N,EAAK;AAAA,YAChB;AACA,mBAAO6N;AAAA,UACT;AAAA,UACAoR;AAAA,QAAA;AAEF,YAAI,CAACoJ,GAAc;AAEnB,YAAIlN,IAAQsE,GAAsBg2B,GAAQL,KAAW,EAAE,QAAQ7tB,GAAM,QAAQ,UAAUA,GAAM,WAAW,aAAaA,GAAM,aAAa,MAAA7wB,GAAA,CAAM,CAAC;AAC/I,QAAI0xB,KAAsB,MACxBjN,IAAQ,EAAE,GAAGA,GAAO,SAASA,EAAM,UAAUiN,GAAA,IAE/CvH,GAAgBjG,IAAK2M,GAAM,OAAO,OAAOc,IAActH,IAAaC,GAAc7F,GAAOw6B,CAAO;AAAA,MAClG;AAAA,IACF,GAEML,IAASf,GAAuB;AACtC,QAAKe;AACL,aAAAnb,EAAqBmb,GAAQ,IAAIE,CAAU,GACpC,MAAMpb,EAAuBkb,CAAM;AAAA,EAC5C,GAAG,CAACnb,GAAsBC,CAAsB,CAAC,GAGjDnQ,EAAU,MAAM;AACd,IAAAoQ,EAAA;AAAA,EACF,GAAG,CAACsa,IAAiB9vB,IAAiBC,GAAgBqB,IAAqBK,IAAoBpB,GAA6BiV,CAAoB,CAAC;AAIjJ,QAAMyb,KAAgBtwB,EAAO;AAAA,IAC3B,oBAAAovB;AAAA,IACA,aAAA1B;AAAA,IACA,oBAAA1sB;AAAA,IACA,oBAAA6rB;AAAA,IACA,6BAAAjtB;AAAA,IACA,sBAAAguB;AAAA,IACA,SAAArD;AAAA,IACA,SAAAC;AAAA,IACA,cAAAyE;AAAA,EAAA,CACD;AACD,SAAAqB,GAAc,UAAU;AAAA,IACtB,oBAAAlB;AAAA,IACA,aAAA1B;AAAA,IACA,oBAAA1sB;AAAA,IACA,oBAAA6rB;AAAA,IACA,6BAAAjtB;AAAA,IACA,sBAAAguB;AAAA,IACA,SAAArD;AAAA,IACA,SAAAC;AAAA,IACA,cAAAyE;AAAA,EAAA,GAGFxqB,EAAU,MAAM;AACd,QAAI,CAACkW,EAAa;AAClB,UAAM4V,IAAYvC,EAAa;AAC/B,QAAI,CAACuC,EAAW;AAEhB,UAAMpsB,IAAoB,CAACtvB,MAAoB;AAC7C,UAAIu5C,IAAuB;AAC3B,YAAM/b,KAAW9M,EAAY;AAC7B,UAAI,CAAC8M,GAAU;AAEf,YAAM;AAAA,QAAE,oBAAoB1B;AAAA,QAAM,aAAa6f;AAAA,QAAoB,oBAAoBP;AAAA,QAAQ,oBAAoBL;AAAA,QACjH,6BAA6BQ;AAAA,QAAY,sBAAsBD;AAAA,QAAS,SAASM;AAAA,MAAA,IAAYH,GAAc,SAEvGI,KAAaxC,EAAcr5C,EAAE,SAASA,EAAE,OAAO;AACrD,UAAI,CAAC67C,GAAY;AAEjB,UAAIjH,KAAiC,MACjCkH,KAA0F;AAE9F,UAAIhgB,EAAK,SAAS,GAAG;AACnB,cAAM+b,IAAcyB,EAAcuC,GAAW,CAAC,GAAGA,GAAW,CAAC,CAAC;AAC9D,YAAIhE,GAAa;AACf,gBAAM14C,IAAO+rB,EAAU,SAAS,sBAAA;AAChC,UAAA4wB,KAAY/D;AAAA,YACV8D;AAAA,YAAYhE;AAAA,YAAa/b;AAAA,YAAM0B;AAAA,YAAUme;AAAA,YAAoBP;AAAA,YAAQL;AAAA,YACrE,OAAOQ,KAAe,WAAWA,IAAa;AAAA,YAC9Cp8C,GAAM,SAAS;AAAA,YAAGA,GAAM,UAAU;AAAA,YAAGm8C;AAAA,UAAA,GAEvC1G,KAASkH,IAAW,YAAY;AAAA,QAClC;AAAA,MACF;AAEA,YAAMC,KAAS/B,EAAmB;AAClC,MAAI,OAAO+B,EAAM,MAAM,OAAOnH,EAAM,MAEpCoF,EAAmB,UAAUpF,IACxBkF,MAAmBH,EAA+B/E,EAAM,GAC7DgH,IAAU;AAAA,QACR,QAAQE,IAAW,UAAU;AAAA,QAC7B,UAAUlH;AAAA,QACV,aAAakH,IAAW,eAAe;AAAA,QACvC,YAAYD;AAAA,MAAA,CACb,GACD7b,EAAA;AAAA,IACF,GAEMgc,KAAc,CAACh8C,MAAkB;AACrC,UAAIu5C,IAAuB;AAC3B,YAAM/b,KAAW9M,EAAY;AAC7B,UAAI,CAAC8M,GAAU;AAEf,YAAM;AAAA,QAAE,oBAAoB1B;AAAA,QAAM,aAAa6f;AAAA,QAAoB,oBAAoBP;AAAA,QAAQ,oBAAoBL;AAAA,QACjH,6BAA6BQ;AAAA,QAAY,sBAAsBD;AAAA,QAC/D,SAASW;AAAA,QAAS,cAAcC;AAAA,MAAA,IAAWT,GAAc;AAE3D,UAAI3f,EAAK,WAAW,EAAG;AAEvB,YAAM+f,KAAaxC,EAAcr5C,EAAE,SAASA,EAAE,OAAO;AACrD,UAAI,CAAC67C,GAAY;AAEjB,YAAMhE,KAAcyB,EAAcuC,GAAW,CAAC,GAAGA,GAAW,CAAC,CAAC;AAC9D,UAAI,CAAChE,GAAa;AAElB,YAAM14C,KAAO+rB,EAAU,SAAS,sBAAA,GAC1B4wB,IAAY/D;AAAA,QAChB8D;AAAA,QAAYhE;AAAA,QAAa/b;AAAA,QAAM0B;AAAA,QAAUme;AAAA,QAAoBP;AAAA,QAAQL;AAAA,QACrE,OAAOQ,KAAe,WAAWA,IAAa;AAAA,QAC9Cp8C,IAAM,SAAS;AAAA,QAAGA,IAAM,UAAU;AAAA,QAAGm8C;AAAA,MAAA,GAGjC1G,IAASkH,GAAW,YAAY;AACtC,MAAAI,GAAOtH,CAAM,GAETkH,KAAaG,KACfA,EAAQ;AAAA,QACN,QAAQH,EAAU;AAAA,QAClB,UAAUA,EAAU;AAAA,QACpB,aAAaA,EAAU;AAAA,QACvB,YAAYD;AAAA,MAAA,CACb;AAAA,IAEL,GAEMnsB,KAAqB,MAAM;AAC/B,MAAIsqB,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MACxBF,MAAmBH,EAA+B,IAAI,GAC3D8B,GAAc,QAAQ,UAAU,EAAE,QAAQ,MAAM,UAAU,MAAM,aAAa,IAAI,YAAY,KAAA,CAAM,GACnGzb,EAAA;AAAA,IACF;AAEA,WAAA0b,EAAU,iBAAiB,eAAepsB,CAAiB,GAC3DosB,EAAU,iBAAiB,SAASM,EAAW,GAC/CN,EAAU,iBAAiB,gBAAgBhsB,EAAkB,GACtD,MAAM;AACX,MAAAgsB,EAAU,oBAAoB,eAAepsB,CAAiB,GAC9DosB,EAAU,oBAAoB,SAASM,EAAW,GAClDN,EAAU,oBAAoB,gBAAgBhsB,EAAkB;AAAA,IAClE;AAAA,EACF,GAAG,CAACypB,GAAczoB,GAAaxF,GAAW4a,GAAagU,IAAmBT,GAAeC,GAAeC,GAAqBvZ,CAAoB,CAAC,GAE3I;AACT;ACxcO,SAASmc,GAAiB;AAAA,EAChC,YAAAn8B;AAAA,EACA,aAAAC;AAAA,EACA,OAAAxhB;AAAA,EACA,WAAAI;AAAA,EACA,WAAAosB;AAAA,EACA,OAAAnK;AACD,GAA8C;AAC7C,QAAMoK,IAAYC,EAAiC,IAAI,GACjDuF,IAAcvF,EAA8B,IAAI,GAChDkB,IAAcZ;AAAA,IACnB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,SAAS,SAAS,GAAG3K;IAC7D,CAACA,CAAK;AAAA,EAAA;AAGP,SAAA8O,EAAU,MAAM;AACf,UAAMj0B,IAASuvB,EAAU;AACzB,QAAI,CAACvvB;AACJ;AAGD,UAAM6hC,IAAW,IAAIt/B,GAAe;AAAA,MACnC,QAAAvC;AAAA,MACA,YAAAqkB;AAAA,MACA,aAAAC;AAAA,MACA,kBAAkBphB;AAAA,IAAA,CAClB;AAED,WAAA6xB,EAAY,UAAU8M,GACjBA,EAAS,SAAS/+B,CAAK,GAErB,MAAM;AACZ,MAAA++B,EAAS,QAAA,GACT9M,EAAY,UAAU;AAAA,IACvB;AAAA,EACD,GAAG,CAAC1Q,GAAYC,CAAW,CAAC,GAE5B2P,EAAU,MAAM;AACf,UAAM4N,IAAW9M,EAAY;AAC7B,IAAK8M,KAIAA,EAAS,SAAS/+B,CAAK;AAAA,EAC7B,GAAG,CAACA,CAAK,CAAC,GAEVmxB,EAAU,MAAM;AACf,UAAM4N,IAAW9M,EAAY;AAC7B,IAAI,CAAC8M,KAAY,CAAC3+B,KAIlB2+B,EAAS,aAAa3+B,CAAS;AAAA,EAChC,GAAG,CAACA,CAAS,CAAC,sBAEN,UAAA,EAAO,KAAKqsB,GAAW,WAAAD,GAAsB,OAAOoB,GAAa;AAC1E;ACrBA,SAAS+vB,GAAuBra,GAAaC,GAA4B;AACxE,MAAI,CAACA,EAAW,QAAO;AACvB,MAAI;AAEH,UAAMC,IADS,IAAI,IAAIF,GAAK,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,MAAS,EACxE,SAAS,YAAA;AAG7B,QADCE,EAAK,SAAS,eAAe,KAAKA,EAAK,WAAW,KAAK,KAAKA,EAAK,SAAS,MAAM,EACpE,QAAO;AAAA,EACrB,QAAQ;AAAA,EAER;AACA,SAAO;AACR;AAEO,MAAMoa,GAAc;AAAA,EAwB1B,YAAYzgD,GAA+B;AAvB1B,IAAAK,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAGA,IAAAA,EAAA;AAIT,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,eAAqB,CAAA;AACrB,IAAAA,EAAA,yCAAkB,IAAA;AAClB,IAAAA,EAAA,sCAAe,IAAA;AACf,IAAAA,EAAA,yCAAkB,IAAA;AAClB,IAAAA,EAAA,iBAAyB;AACzB,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,qBAAc;AAGrB,SAAK,iBAAiB,KAAK,IAAI,GAAG,KAAK,MAAML,EAAQ,kBAAkB,EAAE,CAAC,GAC1E,KAAK,aAAa,KAAK,IAAI,GAAG,KAAK,MAAMA,EAAQ,cAAc,CAAC,CAAC,GACjE,KAAK,mBAAmB,KAAK;AAAA,MAC5B;AAAA,MACA,KAAK,MAAMA,EAAQ,oBAAoB,GAAG;AAAA,IAAA,GAE3C,KAAK,kBAAkB,KAAK;AAAA,MAC3B,KAAK;AAAA,MACL,KAAK,MAAMA,EAAQ,mBAAmB,IAAI;AAAA,IAAA,GAE3C,KAAK,YAAYA,EAAQ,aAAa,IACtC,KAAK,aAAaA,EAAQ,YAC1B,KAAK,cAAcA,EAAQ,aAC3B,KAAK,gBAAgBA,EAAQ;AAAA,EAC9B;AAAA,EAEA,aAAamb,GAAqB;AACjC,SAAK,YAAY,OAAOA,KAAS,EAAE;AAAA,EACpC;AAAA,EAEA,SAAStY,GAAuC;AAC/C,QAAI,KAAK,UAAW;AAEpB,UAAM69C,wBAAsB,IAAA;AAC5B,eAAW19C,KAAQH;AAClB,MAAA69C,EAAgB,IAAI19C,EAAK,GAAG;AAE7B,SAAK,cAAc09C,GAEnB,KAAK,oBAAoBA,CAAe,GACxC,KAAK,uBAAuBA,CAAe;AAE3C,eAAW19C,KAAQH,GAAO;AACzB,UAAI,KAAK,SAAS,IAAIG,EAAK,GAAG,GAAG;AAChC,cAAM29C,IAAW,KAAK,SAAS,IAAI39C,EAAK,GAAG;AAC3C,QAAI29C,QAAmB,OAAO39C;AAC9B;AAAA,MACD;AAEA,YAAM49C,IAAS,KAAK,YAAY,IAAI59C,EAAK,GAAG;AAC5C,UAAI49C,GAAQ;AACX,QAAAA,EAAO,OAAO59C;AACd;AAAA,MACD;AAEA,YAAM6Y,IAAkB;AAAA,QACvB,MAAA7Y;AAAA,QACA,SAAS;AAAA,QACT,SAAS4X,GAAA;AAAA,MAAM;AAEhB,WAAK,MAAM,KAAKiB,CAAI,GACpB,KAAK,YAAY,IAAI7Y,EAAK,KAAK6Y,CAAI;AAAA,IACpC;AAEA,SAAK,UAAA,GACL,KAAK,KAAA,GACL,KAAK,gBAAA;AAAA,EACN;AAAA,EAEA,QAAc;AACb,SAAK,eAAA,GACL,KAAK,YAAY,MAAA,GACjB,KAAK,QAAQ,CAAA,GACb,KAAK,YAAY,MAAA;AAEjB,eAAW,CAAA,EAAGA,CAAI,KAAK,KAAK;AAC3B,MAAAA,EAAK,WAAW,MAAA;AAEjB,SAAK,SAAS,MAAA,GACd,KAAK,gBAAA;AAAA,EACN;AAAA,EAEA,UAAgB;AACf,IAAI,KAAK,cACT,KAAK,YAAY,IACjB,KAAK,MAAA;AAAA,EACN;AAAA,EAEA,mBAA2B;AAC1B,WAAO,KAAK,SAAS;AAAA,EACtB;AAAA,EAEA,cAAqC;AACpC,WAAO;AAAA,MACN,UAAU,KAAK,SAAS;AAAA,MACxB,QAAQ,KAAK,MAAM;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,IAAA;AAAA,EAEf;AAAA,EAEQ,oBAAoBglC,GAAgC;AAC3D,QAAI,KAAK,MAAM,WAAW,EAAG;AAC7B,UAAMC,IAAyB,CAAA;AAC/B,eAAWjlC,KAAQ,KAAK,OAAO;AAC9B,UAAI,CAACglC,EAAY,IAAIhlC,EAAK,KAAK,GAAG,GAAG;AACpC,aAAK,YAAY,OAAOA,EAAK,KAAK,GAAG;AACrC;AAAA,MACD;AACA,MAAAilC,EAAU,KAAKjlC,CAAI;AAAA,IACpB;AACA,SAAK,QAAQilC;AAAA,EACd;AAAA,EAEQ,uBAAuBD,GAAgC;AAC9D,eAAW,CAACr4B,GAAK3M,CAAI,KAAK,KAAK;AAC9B,MAAIglC,EAAY,IAAIr4B,CAAG,MACvB,KAAK,SAAS,OAAOA,CAAG,GACxB,KAAK,gBAAgB,GACrB3M,EAAK,WAAW,MAAA;AAAA,EAElB;AAAA,EAEQ,YAAkB;AACzB,SAAK,MAAM,KAAK,CAAC3W,GAAGwE,MACfxE,EAAE,YAAYwE,EAAE,UAAgBxE,EAAE,UAAUwE,EAAE,UAC9CxE,EAAE,KAAK,cAAcwE,EAAE,KAAK,YACxBxE,EAAE,KAAK,YAAYwE,EAAE,KAAK,YAE9BxE,EAAE,KAAK,SAASwE,EAAE,KAAK,OAAaA,EAAE,KAAK,OAAOxE,EAAE,KAAK,OACtDA,EAAE,KAAK,IAAI,cAAcwE,EAAE,KAAK,GAAG,CAC1C;AAAA,EACF;AAAA,EAEQ,OAAa;AACpB,QAAI,KAAK,UAAW;AAGpB,SAFA,KAAK,eAAA,GAEE,KAAK,SAAS,OAAO,KAAK,kBAAgB;AAChD,YAAMlJ,IAAO,KAAK,uBAAA;AAClB,UAAI,CAACA,EAAM;AACX,WAAK,WAAWA,CAAI;AAAA,IACrB;AAMA,QAJI,KAAK,SAAS,QAAQ,KAAK,kBAI3B,KAAK,MAAM,WAAW,EAAG;AAE7B,UAAMugD,IAAkB,KAAK,MAAM,CAAC,GAAG;AACvC,QAAI,OAAOA,KAAoB,SAAU;AACzC,UAAMC,IAAQ,KAAK,IAAI,GAAGD,IAAkBnmC,IAAO;AACnD,SAAK,UAAU,WAAW,WAAW,MAAM;AAC1C,WAAK,UAAU,MACf,KAAK,KAAA;AAAA,IACN,GAAGomC,CAAK;AAAA,EACT;AAAA,EAEQ,yBAA2C;AAClD,QAAI,KAAK,MAAM,WAAW,EAAG,QAAO;AACpC,UAAMC,IAAMrmC,GAAA,GACN9C,IAAQ,KAAK,MAAM,CAAC;AAC1B,WAAI,CAACA,KAASA,EAAM,UAAUmpC,IAAY,QAE1C,KAAK,MAAM,MAAA,GACX,KAAK,YAAY,OAAOnpC,EAAM,KAAK,GAAG,GAC/BA;AAAA,EACR;AAAA,EAEQ,WAAW+D,GAAuB;AACzC,UAAMqlC,IAAa,IAAI,gBAAA,GACjBC,IAA8B;AAAA,MACnC,MAAMtlC,EAAK;AAAA,MACX,SAASA,EAAK;AAAA,MACd,YAAAqlC;AAAA,IAAA;AAED,SAAK,SAAS,IAAIrlC,EAAK,KAAK,KAAKslC,CAAa,GAC9C,KAAK,gBAAA;AAEL,UAAMrU,IAAgB0T,GAAuB3kC,EAAK,KAAK,KAAK,KAAK,SAAS;AAC1E,UAAMA,EAAK,KAAK,KAAK;AAAA,MACpB,QAAQqlC,EAAW;AAAA,MACnB,SAASpU,IAAgB,EAAE,eAAe,KAAK,cAAc;AAAA,IAAA,CAC7D,EACC,KAAK,CAAC5pC,MAAa;AACnB,UAAI,CAACA,EAAS;AACb,cAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,EAAE;AAE1C,aAAOA,EAAS,KAAA;AAAA,IACjB,CAAC,EACA,KAAK,CAACC,MAAS,kBAAkBA,CAAI,CAAC,EACtC,KAAK,CAACC,MAAW;AACjB,UAAI,KAAK,aAAa89C,EAAW,OAAO,SAAS;AAChD,QAAA99C,EAAO,MAAA;AACP;AAAA,MACD;AACA,UAAI,CAAC,KAAK,YAAY,IAAIyY,EAAK,KAAK,GAAG,GAAG;AACzC,QAAAzY,EAAO,MAAA;AACP;AAAA,MACD;AACA,WAAK,WAAWyY,EAAK,MAAMzY,CAAM;AAAA,IAClC,CAAC,EACA,MAAM,CAACE,MAAmB;AAC1B,UAAI49C,EAAW,OAAO,WAAW,KAAK;AACrC;AAKD,UADCrlC,EAAK,UAAU,KAAK,cAAc,KAAK,YAAY,IAAIA,EAAK,KAAK,GAAG,GACpD;AAChB,aAAK,cAAc;AACnB,cAAMulC,IAAcvlC,EAAK,UAAU,GAC7BwlC,IAAa,KAAK,cAAcD,CAAW,GAC3CR,IAAoB;AAAA,UACzB,MAAM/kC,EAAK;AAAA,UACX,SAASulC;AAAA,UACT,SAASxmC,OAAUymC;AAAA,QAAA,GAEdC,IAAW,KAAK,YAAY,IAAIzlC,EAAK,KAAK,GAAG;AACnD,QAAIylC,KACHA,EAAS,OAAOV,EAAO,MACvBU,EAAS,UAAU,KAAK,IAAIA,EAAS,SAASV,EAAO,OAAO,GAC5DU,EAAS,UAAU,KAAK,IAAIA,EAAS,SAASV,EAAO,OAAO,MAE5D,KAAK,MAAM,KAAKA,CAAM,GACtB,KAAK,YAAY,IAAIA,EAAO,KAAK,KAAKA,CAAM,IAE7C,KAAK,UAAA;AACL;AAAA,MACD;AAEA,WAAK,eAAe,GACpB,KAAK,cAAc/kC,EAAK,MAAMvY,GAAOuY,EAAK,UAAU,CAAC;AAAA,IACtD,CAAC,EACA,QAAQ,MAAM;AACd,WAAK,SAAS,OAAOA,EAAK,KAAK,GAAG,GAClC,KAAK,KAAA,GACL,KAAK,gBAAA;AAAA,IACN,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc0lC,GAAyB;AAC9C,UAAMC,IAAM,KAAK,IAAI,GAAGD,IAAU,CAAC,GAC7BP,IAAQ,KAAK;AAAA,MAClB,KAAK;AAAA,MACL,KAAK,mBAAmB,KAAKQ;AAAA,IAAA,GAExBC,IAAS,OAAO,KAAK,OAAA,IAAW;AACtC,WAAO,KAAK,MAAMT,IAAQS,CAAM;AAAA,EACjC;AAAA,EAEQ,iBAAuB;AAC9B,IAAI,KAAK,YAAY,SACrB,WAAW,aAAa,KAAK,OAAO,GACpC,KAAK,UAAU;AAAA,EAChB;AAAA,EAEQ,kBAAwB;AAC/B,SAAK,gBAAgB,KAAK,aAAa;AAAA,EACxC;AACD;ACvUO,SAASC,GAAgC3hD,GAA2ByxC,GAAwC;AACjH,EAAAzxC,EAAO,iBAAiB,eAAeyxC,EAAS,WAAW,GAC3DzxC,EAAO,iBAAiB,eAAeyxC,EAAS,WAAW,GAC3DzxC,EAAO,iBAAiB,aAAayxC,EAAS,SAAS,GACvDzxC,EAAO,iBAAiB,iBAAiByxC,EAAS,SAAS,GAC3DzxC,EAAO,iBAAiB,SAASyxC,EAAS,OAAO,EAAE,SAAS,IAAO,GACnEzxC,EAAO,iBAAiB,YAAYyxC,EAAS,WAAW,GACxDzxC,EAAO,iBAAiB,eAAeyxC,EAAS,WAAW,GAC3DzxC,EAAO,iBAAiB,oBAAoByxC,EAAS,WAAW,GAChEzxC,EAAO,iBAAiB,wBAAwByxC,EAAS,eAAe;AAC1E;AAEO,SAASmQ,GAAmC5hD,GAA2ByxC,GAAwC;AACpH,EAAAzxC,EAAO,oBAAoB,eAAeyxC,EAAS,WAAW,GAC9DzxC,EAAO,oBAAoB,eAAeyxC,EAAS,WAAW,GAC9DzxC,EAAO,oBAAoB,aAAayxC,EAAS,SAAS,GAC1DzxC,EAAO,oBAAoB,iBAAiByxC,EAAS,SAAS,GAC9DzxC,EAAO,oBAAoB,SAASyxC,EAAS,KAAK,GAClDzxC,EAAO,oBAAoB,YAAYyxC,EAAS,WAAW,GAC3DzxC,EAAO,oBAAoB,eAAeyxC,EAAS,WAAW,GAC9DzxC,EAAO,oBAAoB,oBAAoByxC,EAAS,WAAW,GACnEzxC,EAAO,oBAAoB,wBAAwByxC,EAAS,eAAe;AAC7E;AAEO,SAASoQ,GAAqB7hD,GAA2Bf,GAA4B6iD,GAA2B;AACrH,QAAMt+C,IAAOxD,EAAO,sBAAA,GACd2qC,IAAO,KAAK,IAAI,GAAGnnC,EAAK,SAASxD,EAAO,eAAe,CAAC,GACxD4qC,IAAO,KAAK,IAAI,GAAGpnC,EAAK,UAAUxD,EAAO,gBAAgB,CAAC,GAC1D2D,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9CknC,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAOhnC,CAAG,CAAC,GAC3CmnC,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAOjnC,CAAG,CAAC;AAEjD,GAAI3D,EAAO,UAAU6qC,KAAU7qC,EAAO,WAAW8qC,OAC/C9qC,EAAO,QAAQ6qC,GACf7qC,EAAO,SAAS8qC,IAGlBgX,EAAO,YAAYnX,GAAMC,CAAI,GAC7B3rC,EAAG,SAAS,GAAG,GAAG4rC,GAAQC,CAAM;AAClC;ACzCO,MAAMiX,KAAoC,MACpCC,KAAoB,KACpBC,KAAoB,KAEpBC,KAAqD;AAAA,EAChE,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,KAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,GAAA;AAAA,EACjB,EAAE,MAAM,IAAI,MAAM,KAAA;AAAA,EAClB,EAAE,MAAM,IAAI,MAAM,GAAA;AAAA,EAClB,EAAE,MAAM,IAAI,MAAM,GAAA;AACpB,GAEMC,KAAmB,KACnBC,KAAmB,GACnBC,KAAoB,GACpBC,KAAoB,GACpBC,KAA+B,GAC/BC,KAA+B,GAC/BC,KAAwB,MACxBC,KAAwB,KACxBC,KAAkC,KAC3BC,KAAoE,CAAC,KAAK,KAAK,GAAG;AAExF,SAASziD,GAAUC,GAAqB;AAC7C,SAAQA,IAAM,KAAK,KAAM;AAC3B;AAEO,SAASyiD,GAAgB19C,GAAuCwE,GAAgD;AACrH,SAAI,CAACxE,KAAK,CAACwE,IAAUxE,MAAMwE,IACpBxE,EAAE,WAAWwE,EAAE,UAAUxE,EAAE,eAAewE,EAAE,cAAcxE,EAAE,eAAewE,EAAE;AACtF;AAEO,SAASm5C,GAAoBvqB,GAAkD;AACpF,SAAOA,EAAM,IAAI,CAAAwqB,OAAS,EAAE,MAAMA,EAAK,MAAM,MAAMA,EAAK,KAAA,EAAO;AACjE;AAEO,SAASC,GAAiCzqB,GAAsG;AACrJ,SAAI,CAACA,KAASA,EAAM,WAAW,IAAU,OAClCA,EAAM,IAAI,CAAAwqB,OAAS,EAAE,eAAeA,EAAK,eAAe,MAAMA,EAAK,KAAA,EAAO;AACnF;AAEO,SAASE,GACd1qB,GACuC;AACvC,SAAI,CAACA,KAASA,EAAM,WAAW,IAAU,OAClCA,EAAM,IAAI,CAAAwqB,OAAS,EAAE,eAAeA,EAAK,eAAe,QAAQA,EAAK,OAAA,EAAS;AACvF;AAEO,SAASG,GAAwBC,GAAsE;AAC5G,MAAI,CAACA,EAAiB,QAAOL,GAAoBZ,EAAwB;AAEzE,QAAM5c,wBAAa,IAAA;AACnB,aAAW,CAAC8d,GAASC,CAAO,KAAK,OAAO,QAAQF,CAAe,GAAG;AAChE,UAAMziD,IAAO,OAAO0iD,CAAO,GACrBE,IAAO,OAAOD,CAAO;AAC3B,IAAI,CAAC,OAAO,SAAS3iD,CAAI,KAAK,CAAC,OAAO,SAAS4iD,CAAI,KAAKA,KAAQ,KAChEhe,EAAO,IAAI5kC,GAAM4iD,CAAI;AAAA,EACvB;AAEA,SAAIhe,EAAO,SAAS,IACXwd,GAAoBZ,EAAwB,IAG9C,MAAM,KAAK5c,EAAO,QAAA,CAAS,EAC/B,KAAK,CAACngC,GAAGwE,MAAMxE,EAAE,CAAC,IAAIwE,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAACjJ,GAAM4iD,CAAI,OAAO,EAAE,MAAA5iD,GAAM,MAAA4iD,EAAA,EAAO;AAC3C;AAEO,SAASC,GAAqCC,GAA4G;AAC/J,MAAI,CAACA,EAA0B,QAAO;AAEtC,QAAMle,wBAAa,IAAA;AACnB,aAAW,CAACme,GAAkBJ,CAAO,KAAK,OAAO,QAAQG,CAAwB,GAAG;AAClF,UAAME,IAAgB,OAAOD,CAAgB,GACvCH,IAAO,OAAOD,CAAO;AAC3B,IAAI,CAAC,OAAO,SAASK,CAAa,KAAKA,KAAiB,KAAK,CAAC,OAAO,SAASJ,CAAI,KAAKA,KAAQ,KAC/Fhe,EAAO,IAAIoe,GAAeJ,CAAI;AAAA,EAChC;AAEA,SAAIhe,EAAO,SAAS,IACX,OAGF,MAAM,KAAKA,EAAO,QAAA,CAAS,EAC/B,KAAK,CAACngC,GAAGwE,MAAMxE,EAAE,CAAC,IAAIwE,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAAC+5C,GAAeJ,CAAI,OAAO,EAAE,eAAAI,GAAe,MAAAJ,EAAA,EAAO;AAC7D;AAEO,SAASK,GACdC,GACuC;AACvC,MAAI,CAACA,EAA4B,QAAO;AAExC,QAAMte,wBAAa,IAAA;AACnB,aAAW,CAACme,GAAkB/jB,CAAS,KAAK,OAAO,QAAQkkB,CAA0B,GAAG;AACtF,UAAMF,IAAgB,OAAOD,CAAgB,GACvC/nB,IAASmoB,GAAqBnkB,CAAS;AAC7C,IAAI,CAAC,OAAO,SAASgkB,CAAa,KAAKA,KAAiB,KACxDpe,EAAO,IAAIoe,GAAehoB,CAAM;AAAA,EAClC;AAEA,SAAI4J,EAAO,SAAS,IACX,OAGF,MAAM,KAAKA,EAAO,QAAA,CAAS,EAC/B,KAAK,CAACngC,GAAGwE,MAAMxE,EAAE,CAAC,IAAIwE,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAAC+5C,GAAehoB,CAAM,OAAO,EAAE,eAAAgoB,GAAe,QAAAhoB,EAAA,EAAS;AACjE;AAEO,SAASooB,GAAuB3+C,GAA6BwE,GAAsC;AACxG,MAAIxE,MAAMwE,EAAG,QAAO;AACpB,MAAIxE,EAAE,WAAWwE,EAAE,OAAQ,QAAO;AAClC,WAASjF,IAAI,GAAGA,IAAIS,EAAE,QAAQT,KAAK;AACjC,QAAIS,EAAET,CAAC,EAAE,SAASiF,EAAEjF,CAAC,EAAE,QAAQS,EAAET,CAAC,EAAE,SAASiF,EAAEjF,CAAC,EAAE;AAChD,aAAO;AAGX,SAAO;AACT;AAEO,SAASq/C,GACd5+C,GACAwE,GACS;AACT,MAAIxE,MAAMwE,EAAG,QAAO;AACpB,MAAI,CAACxE,KAAK,CAACwE,UAAUxE,MAAMwE;AAC3B,MAAIxE,EAAE,WAAWwE,EAAE,OAAQ,QAAO;AAClC,WAASjF,IAAI,GAAGA,IAAIS,EAAE,QAAQT,KAAK;AACjC,QAAIS,EAAET,CAAC,EAAE,kBAAkBiF,EAAEjF,CAAC,EAAE,iBAAiBS,EAAET,CAAC,EAAE,SAASiF,EAAEjF,CAAC,EAAE;AAClE,aAAO;AAGX,SAAO;AACT;AAEO,SAASs/C,GACd7+C,GACAwE,GACS;AACT,MAAIxE,MAAMwE,EAAG,QAAO;AACpB,MAAI,CAACxE,KAAK,CAACwE,UAAUxE,MAAMwE;AAC3B,MAAIxE,EAAE,WAAWwE,EAAE,OAAQ,QAAO;AAClC,WAASjF,IAAI,GAAGA,IAAIS,EAAE,QAAQT,KAAK;AACjC,QAAIS,EAAET,CAAC,EAAE,kBAAkBiF,EAAEjF,CAAC,EAAE,iBAAiBS,EAAET,CAAC,EAAE,WAAWiF,EAAEjF,CAAC,EAAE;AACpE,aAAO;AAGX,SAAO;AACT;AAEO,SAASu/C,GAA4B/yB,GAAwBqH,GAAyC;AAC3G,MAAI,CAAC,OAAO,SAASrH,CAAc,EAAG,QAAOqH,EAAM,CAAC,GAAG,QAAQypB;AAC/D,MAAIzpB,EAAM,WAAW,EAAG,QAAOypB;AAE/B,MADIzpB,EAAM,WAAW,KACjBrH,KAAkBqH,EAAM,CAAC,EAAE,KAAM,QAAOA,EAAM,CAAC,EAAE;AAErD,WAAS7zB,IAAI,GAAGA,IAAI6zB,EAAM,QAAQ7zB,KAAK,GAAG;AACxC,UAAMoT,IAAOygB,EAAM7zB,IAAI,CAAC,GAClBjE,IAAO83B,EAAM7zB,CAAC;AACpB,QAAIwsB,IAAiBzwB,EAAK,KAAM;AAChC,UAAMyjD,IAAO,KAAK,IAAI,MAAMzjD,EAAK,OAAOqX,EAAK,IAAI,GAC3CoF,IAAInD,GAAOmX,IAAiBpZ,EAAK,QAAQosC,GAAM,GAAG,CAAC;AACzD,WAAOpsC,EAAK,QAAQrX,EAAK,OAAOqX,EAAK,QAAQoF;AAAA,EAC/C;AAEA,QAAMlF,IAAOugB,EAAMA,EAAM,SAAS,CAAC,GAC7BzgB,IAAOygB,EAAMA,EAAM,SAAS,CAAC,GAC7B2rB,IAAO,KAAK,IAAI,MAAMlsC,EAAK,OAAOF,EAAK,IAAI,GAC3CqsC,KAASnsC,EAAK,OAAOF,EAAK,QAAQosC;AACxC,SAAOlsC,EAAK,QAAQkZ,IAAiBlZ,EAAK,QAAQmsC;AACpD;AAEO,SAASC,GAAqCV,GAAuBnrB,GAAsD;AAChI,MAAI,CAAC,OAAO,SAASmrB,CAAa,EAAG,QAAOnrB,EAAM,CAAC,GAAG,QAAQypB;AAC9D,MAAIzpB,EAAM,WAAW,EAAG,QAAOypB;AAE/B,MADIzpB,EAAM,WAAW,KACjBmrB,KAAiBnrB,EAAM,CAAC,EAAE,cAAe,QAAOA,EAAM,CAAC,EAAE;AAE7D,WAAS7zB,IAAI,GAAGA,IAAI6zB,EAAM,QAAQ7zB,KAAK,GAAG;AACxC,UAAMoT,IAAOygB,EAAM7zB,IAAI,CAAC,GAClBjE,IAAO83B,EAAM7zB,CAAC;AACpB,QAAIg/C,IAAgBjjD,EAAK,cAAe;AACxC,UAAMyjD,IAAO,KAAK,IAAI,MAAMzjD,EAAK,gBAAgBqX,EAAK,aAAa,GAC7DoF,IAAInD,GAAO2pC,IAAgB5rC,EAAK,iBAAiBosC,GAAM,GAAG,CAAC;AACjE,WAAOpsC,EAAK,QAAQrX,EAAK,OAAOqX,EAAK,QAAQoF;AAAA,EAC/C;AAEA,QAAMlF,IAAOugB,EAAMA,EAAM,SAAS,CAAC,GAC7BzgB,IAAOygB,EAAMA,EAAM,SAAS,CAAC,GAC7B2rB,IAAO,KAAK,IAAI,MAAMlsC,EAAK,gBAAgBF,EAAK,aAAa,GAC7DqsC,KAASnsC,EAAK,OAAOF,EAAK,QAAQosC;AACxC,SAAOlsC,EAAK,QAAQ0rC,IAAgB1rC,EAAK,iBAAiBmsC;AAC5D;AAEO,SAASE,GAAuCX,GAAuBnrB,GAAwD;AACpI,MAAI,CAAC,OAAO,SAASmrB,CAAa,EAAG,QAAOnrB,EAAM,CAAC,GAAG,UAAU;AAChE,MAAIA,EAAM,WAAW,EAAG,QAAO;AAE/B,MADIA,EAAM,WAAW,KACjBmrB,KAAiBnrB,EAAM,CAAC,EAAE,cAAe,QAAOA,EAAM,CAAC,EAAE;AAE7D,WAAS7zB,IAAI,GAAGA,IAAI6zB,EAAM,QAAQ7zB,KAAK,GAAG;AACxC,UAAMoT,IAAOygB,EAAM7zB,IAAI,CAAC,GAClBjE,IAAO83B,EAAM7zB,CAAC;AACpB,QAAIg/C,IAAgBjjD,EAAK,cAAe;AACxC,UAAMyjD,IAAO,KAAK,IAAI,MAAMzjD,EAAK,gBAAgBqX,EAAK,aAAa,GAC7DoF,IAAInD,GAAO2pC,IAAgB5rC,EAAK,iBAAiBosC,GAAM,GAAG,CAAC;AACjE,WAAOpsC,EAAK,UAAUrX,EAAK,SAASqX,EAAK,UAAUoF;AAAA,EACrD;AAEA,QAAMlF,IAAOugB,EAAMA,EAAM,SAAS,CAAC,GAC7BzgB,IAAOygB,EAAMA,EAAM,SAAS,CAAC,GAC7B2rB,IAAO,KAAK,IAAI,MAAMlsC,EAAK,gBAAgBF,EAAK,aAAa,GAC7DqsC,KAASnsC,EAAK,SAASF,EAAK,UAAUosC;AAC5C,SAAOlsC,EAAK,UAAU0rC,IAAgB1rC,EAAK,iBAAiBmsC;AAC9D;AAEO,SAASN,GAAqBrsC,GAA0C;AAC7E,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU,IAC1DuC,EAAMvC,GAAO2qC,IAAkBC,EAAgB;AACxD;AAEO,SAASkC,GAAsB9sC,GAA0C;AAC9E,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU,IAC1DuC,EAAMvC,GAAO6qC,IAAmBC,EAAiB;AAC1D;AAEO,SAASiC,GAAuBtK,GAA+D;AACpG,SAAKA,IACE,CAAClgC,EAAMkgC,EAAO,CAAC,GAAG,GAAG,GAAG,GAAGlgC,EAAMkgC,EAAO,CAAC,GAAG,GAAG,GAAG,CAAC,IADtC,CAAC,GAAG,CAAC;AAE3B;AAEO,SAASuK,GAA+BhtC,GAA0C;AACvF,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU,IAC1DuC,EAAMvC,GAAO+qC,IAA8BC,EAA4B;AAChF;AAEO,SAASiC,GAA6BjtC,GAA4D;AACvG,QAAMktC,IAAOlpC,GAAoBhE,GAAO,CAAC,GAAGorC,IAAgC,GAAG,CAAC;AAChF,SAAO,CAAC8B,EAAK,CAAC,GAAGA,EAAK,CAAC,GAAGA,EAAK,CAAC,CAAC;AACnC;AAEA,SAASC,GAAyBntC,GAA0C;AAC1E,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU,IAC1DuC,EAAMvC,GAAOirC,IAAuBC,EAAqB;AAClE;AAEO,SAASkC,GAA+BC,GAAkF;AAC/H,QAAMC,IAAkBH,GAAyBE,GAAU,UAAU,GAC/DE,IAAgBJ,GAAyBE,GAAU,QAAQ,GAC3DG,IAAkBL,GAAyBE,GAAU,UAAU;AACrE,SAAO;AAAA,IACL,YAAYC,IAAkB;AAAA,IAC9B,UAAUC,IAAgB;AAAA,IAC1B,YAAYC,IAAkB;AAAA,EAAA;AAElC;AAEO,SAASC,GAAa/nC,GAAmB;AAC9C,SAAOA;AACT;AAEO,SAASgoC,GAAgCC,GAA6C;AAC3F,SAAI,OAAOA,KAAa,YAAY,CAAC,OAAO,SAASA,CAAQ,IAAU,IAChEprC,EAAMorC,GAAU,GAAGxC,EAA+B;AAC3D;AAEO,SAASyC,GAAsB5tC,GAAiD;AACrF,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,KAAKA,KAAS,IAAU,OACxE,KAAK,IAAI,MAAMA,CAAK;AAC7B;AAEO,SAAS6tC,GAA0BC,GAA2E;AACnH,SAAO,OAAOA,KAAW,aAAaA,IAASL;AACjD;AC3PA,SAASM,GAAmBvlD,GAA2BurC,GAAiBC,GAAyB;AAC/F,QAAMhoC,IAAOxD,EAAO,sBAAA,GACdqF,IAAIkmC,IAAU/nC,EAAK,OAAOA,EAAK,QAAQ,KACvC4B,IAAIomC,IAAUhoC,EAAK,MAAMA,EAAK,SAAS;AAC7C,SAAO,KAAK,MAAM4B,GAAGC,CAAC;AACxB;AAEO,SAASmgD,GAAWxlD,GAA2B0xB,GAA+B;AACnF,MAAIA,EAAM,cAAc,QAAQ1xB,EAAO,kBAAkB0xB,EAAM,SAAS;AACtE,QAAI;AACF,MAAA1xB,EAAO,sBAAsB0xB,EAAM,SAAS;AAAA,IAC9C,QAAQ;AAAA,IAER;AAEF,EAAAA,EAAM,WAAW,IACjBA,EAAM,OAAO,QACbA,EAAM,qBAAqB,MAC3BA,EAAM,YAAY,MAClB1xB,EAAO,UAAU,OAAO,UAAU;AACpC;AAEO,SAAS0zB,GAAkBzzB,GAAmC;AACnE,QAAM,EAAE,OAAAoT,GAAO,QAAArT,GAAQ,OAAA0xB,GAAO,QAAA+zB,GAAQ,qBAAAC,MAAwBzlD,GACxD0lD,IAAcF,EAAO,mBAAmBpyC,EAAM,WAAWA,EAAM;AAErE,GADoBA,EAAM,WAAW,KAAMsyC,KAAetyC,EAAM,WAAW,OAG3EqyC,EAAA,GACIC,KACFtyC,EAAM,eAAA,GAGRqe,EAAM,WAAW,IACjBA,EAAM,OAAOi0B,IAAc,WAAW,OACtCj0B,EAAM,YAAYre,EAAM,WACxBqe,EAAM,eAAere,EAAM,SAC3Bqe,EAAM,eAAere,EAAM,SAC3Bqe,EAAM,qBAAqBA,EAAM,SAAS,WAAW6zB,GAAmBvlD,GAAQqT,EAAM,SAASA,EAAM,OAAO,IAAI,MAEhHrT,EAAO,UAAU,IAAI,UAAU,GAC/BA,EAAO,kBAAkBqT,EAAM,SAAS;AAC1C;AAEO,SAASsgB,GAAkB1zB,GAAmC;AACnE,QAAM,EAAE,OAAAoT,GAAO,QAAArT,GAAQ,OAAA0xB,GAAO,QAAA+zB,GAAQ,QAAA3D,GAAQ,gBAAA8D,GAAgB,eAAAC,GAAe,eAAAC,EAAA,IAAkB7lD;AAC/F,MAAI,CAACyxB,EAAM,YAAYre,EAAM,cAAcqe,EAAM,UAAW;AAE5D,QAAM1wB,IAAKqS,EAAM,UAAUqe,EAAM,cAC3BzwB,IAAKoS,EAAM,UAAUqe,EAAM;AAIjC,MAHAA,EAAM,eAAere,EAAM,SAC3Bqe,EAAM,eAAere,EAAM,SAEvBqe,EAAM,SAAS,UAAU;AAC3B,UAAMq0B,IAAYR,GAAmBvlD,GAAQqT,EAAM,SAASA,EAAM,OAAO,GACnE2yC,IAAYt0B,EAAM;AAExB,QADAA,EAAM,qBAAqBq0B,GACvBC,MAAc,MAAM;AACtB,YAAMC,IAAWF,IAAYC,GACvBE,IAAQ,KAAK,MAAM,KAAK,IAAID,CAAQ,GAAG,KAAK,IAAIA,CAAQ,CAAC,GACzDE,IAA2DV,EAAO,qCAAqC1D,IACvG7+C,IAAY4+C,EAAO,aAAA;AACzB,MAAAA,EAAO,aAAa;AAAA,QAClB,aAAa5+C,EAAU,cAAgBgjD,IAAQ,MAAO,KAAK,KAAMC;AAAA,MAAA,CAClE;AAAA,IACH;AAAA,EACF,OAAO;AACL,UAAMjjD,IAAY4+C,EAAO,aAAA,GACnBphD,IAAO,KAAK,IAAI,MAAMwC,EAAU,IAAI,GACpChC,IAAMf,GAAU+C,EAAU,WAAW,GACrC/B,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBklD,KAAWplD,IAAKG,IAAMF,IAAKG,KAAOV,GAClC2lD,KAAWrlD,IAAKI,IAAMH,IAAKE,KAAOT;AACxC,IAAAohD,EAAO,aAAa;AAAA,MAClB,SAAS5+C,EAAU,UAAUkjD;AAAA,MAC7B,SAASljD,EAAU,UAAUmjD;AAAA,IAAA,CAC9B;AAAA,EACH;AAEA,EAAAT,EAAA,GACAC,EAAA,GACAC,EAAA;AACF;AAEO,SAAShyB,GAAgBzgB,GAAqBrT,GAA2B0xB,GAA+B;AAC7G,EAAIre,EAAM,cAAcqe,EAAM,aAC9B8zB,GAAWxlD,GAAQ0xB,CAAK;AAC1B;AAEO,SAAS40B,GAAYrmD,GAA6B;AACvD,QAAM,EAAE,OAAAoT,GAAO,QAAArT,GAAQ,UAAAumD,EAAA,IAAatmD;AACpC,EAAAoT,EAAM,eAAA;AACN,QAAM7P,IAAOxD,EAAO,sBAAA,GACdqF,IAAIgO,EAAM,UAAU7P,EAAK,MACzB4B,IAAIiO,EAAM,UAAU7P,EAAK;AAC/B,EAAAgjD,GAAoBnzC,EAAM,QAAQhO,GAAGD,GAAGmhD,CAAQ;AAClD;AASA,MAAME,KAAuB;AAEtB,SAASD,GAAoBE,GAAgBrhD,GAAWD,GAAWmhD,GAAgE;AACxI,QAAM/kB,IAASklB,IAAS,IAAI,OAAO;AACnC,EAAAH,EAAS/kB,GAAQn8B,GAAGD,CAAC;AACvB;AAEO,SAASuhD,GACdD,GACArhD,GACAD,GACAwhD,GACAC,GACM;AACN,QAAMC,IAAsCJ,IAAS,IAAI,OAAOA,IAAS,IAAI,QAAQ;AACrF,MAAII,KAAkBF,EAAU;AAC9B,QAAIE,MAAmBF,EAAU;AAC/B,MAAAA,EAAU,mBAAmB,MAC7BA,EAAU,mBAAmB;AAAA;AAE7B;AASJ,MALIA,EAAU,qBAAqB,KAAKF,MAAW,KAAK,KAAK,KAAKE,EAAU,gBAAgB,MAAM,KAAK,KAAKF,CAAM,MAChHE,EAAU,mBAAmB,IAE/BA,EAAU,oBAAoBF,GAE1B,KAAK,IAAIE,EAAU,gBAAgB,IAAIH,GAAsB;AAEjE,QAAMM,IAA0BH,EAAU,mBAAmB,IAAI,QAAQ;AAGzE,MADAA,EAAU,mBAAmB,GACzB,CAACC,EAAWE,GAAW1hD,GAAGD,CAAC,GAAG;AAChC,IAAAwhD,EAAU,mBAAmBG;AAC7B;AAAA,EACF;AAEA,EAAAH,EAAU,mBAAmB;AAC/B;AAEO,SAASI,GAAgB/mD,GAAiC;AAC/D,QAAM,EAAE,OAAAoT,GAAO,QAAArT,GAAQ,WAAA4mD,GAAW,YAAAC,MAAe5mD;AACjD,EAAAoT,EAAM,eAAA;AACN,QAAM7P,IAAOxD,EAAO,sBAAA,GACdqF,IAAIgO,EAAM,UAAU7P,EAAK,MACzB4B,IAAIiO,EAAM,UAAU7P,EAAK;AAC/B,EAAAmjD,GAAoBtzC,EAAM,QAAQhO,GAAGD,GAAGwhD,GAAWC,CAAU;AAC/D;AAEO,SAASI,GAAkBhnD,GAAmC;AACnE,QAAM,EAAE,OAAAoT,GAAO,QAAArT,GAAQ,UAAAumD,EAAA,IAAatmD,GAC9BuD,IAAOxD,EAAO,sBAAA,GACdqF,IAAIgO,EAAM,UAAU7P,EAAK,MACzB4B,IAAIiO,EAAM,UAAU7P,EAAK;AAC/B,EAAA+iD,EAASlzC,EAAM,WAAW,MAAM,MAAMhO,GAAGD,CAAC;AAC5C;AAEO,SAAS8hD,GAAkB7zC,GAAmB8zC,GAAyB;AAC5E,GAAIA,KAAY9zC,EAAM,WAAWA,EAAM,YACrCA,EAAM,eAAA;AAEV;ACtMO,SAAS+zC,GAActF,GAAgC;AAC5D,QAAM1Z,IAAU0Z,EAAO,eAAA;AACvB,MAAIxoC,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAW,CAACpU,GAAGD,CAAC,KAAKgjC;AACnB,IAAI/iC,IAAIiU,MAAMA,IAAOjU,IACjBA,IAAImU,MAAMA,IAAOnU,IACjBD,IAAImU,MAAMA,IAAOnU,IACjBA,IAAIqU,MAAMA,IAAOrU;AAEvB,SAAO,CAACkU,GAAMC,GAAMC,GAAMC,CAAI;AAChC;AAEO,SAASmsC,GAAe9D,GAAwB3iD,GAAwBkoD,IAAU,KAAKC,IAAU,KAAW;AACjH,QAAMvpC,IAASqpC,GAActF,CAAM,GAC7B5V,IAAW,KAAK,IAAI,MAAMnuB,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GAC/CouB,IAAW,KAAK,IAAI,MAAMpuB,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GAC/CwpC,IAAUrb,IAAWmb,GACrBG,IAAUrb,IAAWmb,GAErB,CAAC3mD,GAASC,CAAO,IAAIkhD,EAAO,UAAA,GAC5B2F,IAAQvb,IAAW,KACnBwb,IAAQvb,IAAW,KAEnBwb,IAAaF,IAAQF,GACrBK,IAAazoD,EAAO,QAAQsoD,IAAQF,GACpCM,IAAaH,IAAQF,GACrBM,IAAa3oD,EAAO,SAASuoD,IAAQF,GAErCO,IAAcJ,KAAcC,IAAa7tC,EAAMpZ,GAASgnD,GAAYC,CAAU,IAAIzoD,EAAO,QAAQ,KACjG6oD,IAAcH,KAAcC,IAAa/tC,EAAMnZ,GAASinD,GAAYC,CAAU,IAAI3oD,EAAO,SAAS;AAExG,EAAA2iD,EAAO,UAAUiG,GAAaC,CAAW;AAC3C;AAEO,SAASC,GAAWnG,GAAwB3iD,GAAgC;AACjF,QAAMuB,IAAO,KAAK,IAAI,MAAMohD,EAAO,aAAA,EAAe,IAAI,GAChDoG,IAAU/oD,EAAO,cAAc,KAAK,KAAKuB,CAAI;AACnD,SAAOqZ,EAAM,KAAK,MAAMmuC,CAAO,GAAG,GAAG/oD,EAAO,WAAW;AACzD;AAEO,SAASgpD,GAAiBhjD,GAAWwE,GAAoB;AAC9D,SAAO,EAAExE,EAAE,CAAC,KAAKwE,EAAE,CAAC,KAAKxE,EAAE,CAAC,KAAKwE,EAAE,CAAC,KAAKxE,EAAE,CAAC,KAAKwE,EAAE,CAAC,KAAKxE,EAAE,CAAC,KAAKwE,EAAE,CAAC;AACtE;AAEO,SAASy+C,GAAuBtG,GAAwB3iD,GAAwB8mC,GAA+B;AACpH,QAAM/F,IAAaknB,GAActF,CAAM,GAEjCxV,IAAa,KAAK,IAAI,GAAGntC,EAAO,cAAc8mC,CAAI,GAClDsG,IAAa,KAAK,KAAKptC,EAAO,QAAQmtC,CAAU,GAChDE,IAAc,KAAK,KAAKrtC,EAAO,SAASmtC,CAAU,GAElDG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAaptC,EAAO,QAAQ,CAAC,GAC5DutC,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAcrtC,EAAO,QAAQ,CAAC,GAE7DkpD,IAAWnoB,EAAW,CAAC,GACvBooB,IAAWpoB,EAAW,CAAC,GACvBqoB,IAAWroB,EAAW,CAAC,GACvBsoB,IAAWtoB,EAAW,CAAC,GAEvBuoB,IAAW1uC,EAAM,KAAK,MAAMsuC,IAAW/b,IAAantC,EAAO,QAAQ,GAAG,GAAGstC,IAAS,CAAC,GACnFic,IAAW3uC,EAAM,KAAK,OAAOwuC,IAAW,KAAKjc,IAAantC,EAAO,QAAQ,GAAG,GAAGstC,IAAS,CAAC,GACzFkc,IAAW5uC,EAAM,KAAK,MAAMuuC,IAAWhc,IAAantC,EAAO,QAAQ,GAAG,GAAGutC,IAAS,CAAC,GACnFkc,IAAW7uC,EAAM,KAAK,OAAOyuC,IAAW,KAAKlc,IAAantC,EAAO,QAAQ,GAAG,GAAGutC,IAAS,CAAC;AAE/F,MAAI+b,IAAWC,KAAYC,IAAWC;AACpC,WAAO,CAAA;AAGT,QAAMC,KAAgBR,IAAWE,KAAY,MAAOjc,IAAantC,EAAO,UAClE2pD,KAAgBR,IAAWE,KAAY,MAAOlc,IAAantC,EAAO,UAElEihC,IAA2B,CAAA;AACjC,WAASh7B,IAAIujD,GAAUvjD,KAAKwjD,GAAUxjD,KAAK;AACzC,aAASC,IAAIojD,GAAUpjD,KAAKqjD,GAAUrjD,KAAK,GAAG;AAC5C,YAAMimB,IAAOjmB,IAAIlG,EAAO,WAAWmtC,GAC7B/gB,IAAMnmB,IAAIjG,EAAO,WAAWmtC,GAC5BhQ,IAAQ,KAAK,KAAKj3B,IAAI,KAAKlG,EAAO,UAAUotC,CAAU,IAAID,GAC1DQ,IAAS,KAAK,KAAK1nC,IAAI,KAAKjG,EAAO,UAAUqtC,CAAW,IAAIF,GAE5DtrC,IAAKqE,IAAIwjD,GACT5nD,IAAKmE,IAAI0jD;AACf,MAAA1oB,EAAQ,KAAK;AAAA,QACX,KAAK,GAAG6F,CAAI,IAAI5gC,CAAC,IAAID,CAAC;AAAA,QACtB,MAAA6gC;AAAA,QACA,GAAA5gC;AAAA,QACA,GAAAD;AAAA,QACA,QAAQ,CAACkmB,GAAMC,GAAK+Q,GAAOwQ,CAAM;AAAA,QACjC,WAAW9rC,IAAKA,IAAKC,IAAKA;AAAA,QAC1B,KAAKilC,GAAU/mC,GAAQ8mC,GAAM5gC,GAAGD,CAAC;AAAA,MAAA,CAClC;AAAA,IACH;AAGF,SAAAg7B,EAAQ,KAAK,CAACj7B,GAAGwE,MAAMxE,EAAE,YAAYwE,EAAE,SAAS,GACzCy2B;AACT;AAEO,SAAS2oB,GAAgBjH,GAAwB3iD,GAAoE;AAC1H,QAAM8mC,IAAOgiB,GAAWnG,GAAQ3iD,CAAM;AACtC,SAAO;AAAA,IACL,MAAA8mC;AAAA,IACA,SAASmiB,GAAuBtG,GAAQ3iD,GAAQ8mC,CAAI;AAAA,EAAA;AAExD;AC/DO,SAAS+iB,GAAsB/oD,GAA2C;AAC/E,EAAIA,EAAQ,qBACZyzB,GAAkB;AAAA,IAChB,OAAOzzB,EAAQ;AAAA,IACf,QAAQA,EAAQ;AAAA,IAChB,OAAOA,EAAQ;AAAA,IACf,QAAQ;AAAA,MACN,gBAAgBA,EAAQ;AAAA,MACxB,oCAAoCA,EAAQ;AAAA,IAAA;AAAA,IAE9C,qBAAqBA,EAAQ;AAAA,EAAA,CAC9B;AACH;AAEO,SAASgpD,GAAsBhpD,GAA2C;AAC/E,EAAIA,EAAQ,qBACZ0zB,GAAkB;AAAA,IAChB,OAAO1zB,EAAQ;AAAA,IACf,QAAQA,EAAQ;AAAA,IAChB,OAAOA,EAAQ;AAAA,IACf,QAAQ;AAAA,MACN,gBAAgBA,EAAQ;AAAA,MACxB,oCAAoCA,EAAQ;AAAA,IAAA;AAAA,IAE9C,QAAQA,EAAQ;AAAA,IAChB,gBAAgB,MAAM2lD,GAAe3lD,EAAQ,QAAQA,EAAQ,QAAQA,EAAQ,YAAYA,EAAQ,UAAU;AAAA,IAC3G,eAAeA,EAAQ;AAAA,IACvB,eAAeA,EAAQ;AAAA,EAAA,CACxB;AACH;AAEO,SAASipD,GAAoBjpD,GAAyC;AAC3E,EAAIA,EAAQ,qBACZ6zB,GAAgB7zB,EAAQ,OAAOA,EAAQ,QAAQA,EAAQ,KAAK;AAC9D;AAcO,SAASkpD,GAAsBlpD,GAA2C;AAC/E,EAAIA,EAAQ,qBACZgnD,GAAkB;AAAA,IAChB,OAAOhnD,EAAQ;AAAA,IACf,QAAQA,EAAQ;AAAA,IAChB,UAAUA,EAAQ;AAAA,EAAA,CACnB;AACH;AAEO,SAASmpD,GAAsBnpD,GAA2C;AAC/E,EAAAinD,GAAkBjnD,EAAQ,OAAOA,EAAQ,MAAM,QAAQ;AACzD;AAEO,SAASulD,GAAWxlD,GAA2B0xB,GAA+B;AACnF23B,EAAAA,GAAsBrpD,GAAQ0xB,CAAK;AACrC;AAqBO,SAAS43B,GACdrpD,GACqH;AACrH,SAAO;AAAA,IACL,aAAa,CAACoT,MACZ21C,GAAsB;AAAA,MACpB,OAAA31C;AAAA,MACA,mBAAmBpT,EAAQ,qBAAA;AAAA,MAC3B,QAAQA,EAAQ;AAAA,MAChB,OAAOA,EAAQ;AAAA,MACf,gBAAgBA,EAAQ,kBAAA;AAAA,MACxB,oCAAoCA,EAAQ,sCAAA;AAAA,MAC5C,qBAAqBA,EAAQ;AAAA,IAAA,CAC9B;AAAA,IACH,aAAa,CAACoT,MACZ41C,GAAsB;AAAA,MACpB,OAAA51C;AAAA,MACA,mBAAmBpT,EAAQ,qBAAA;AAAA,MAC3B,QAAQA,EAAQ;AAAA,MAChB,OAAOA,EAAQ;AAAA,MACf,gBAAgBA,EAAQ,kBAAA;AAAA,MACxB,oCAAoCA,EAAQ,sCAAA;AAAA,MAC5C,QAAQA,EAAQ;AAAA,MAChB,QAAQA,EAAQ;AAAA,MAChB,YAAYA,EAAQ,cAAA;AAAA,MACpB,YAAYA,EAAQ,cAAA;AAAA,MACpB,eAAeA,EAAQ;AAAA,MACvB,eAAeA,EAAQ;AAAA,IAAA,CACxB;AAAA,IACH,WAAW,CAACoT,MACV61C,GAAoB;AAAA,MAClB,OAAA71C;AAAA,MACA,mBAAmBpT,EAAQ,qBAAA;AAAA,MAC3B,QAAQA,EAAQ;AAAA,MAChB,OAAOA,EAAQ;AAAA,IAAA,CAChB;AAAA,IACH,OAAO,CAACoT,MAAsB;AAC5B,UAAIpT,EAAQ,wBAAwB;AAClC,QAAAoT,EAAM,eAAA;AACN;AAAA,MACF;AACA,UAAIpT,EAAQ,kBAAA,KAAuBA,EAAQ,cAAcA,EAAQ,eAAe;AAC9E,QAAA+mD,GAAgB;AAAA,UACd,OAAA3zC;AAAA,UACA,QAAQpT,EAAQ;AAAA,UAChB,WAAWA,EAAQ;AAAA,UACnB,YAAYA,EAAQ;AAAA,QAAA,CACrB;AACD;AAAA,MACF;AACA,MAAAqmD,GAAY;AAAA,QACV,OAAAjzC;AAAA,QACA,QAAQpT,EAAQ;AAAA,QAChB,UAAUA,EAAQ;AAAA,MAAA,CACnB;AAAA,IACH;AAAA,IACA,aAAa,CAACoT,MACZ81C,GAAsB;AAAA,MACpB,OAAA91C;AAAA,MACA,mBAAmBpT,EAAQ,qBAAA;AAAA,MAC3B,QAAQA,EAAQ;AAAA,MAChB,UAAUA,EAAQ;AAAA,IAAA,CACnB;AAAA,IACH,aAAa,CAACoT,MACZ+1C,GAAsB;AAAA,MACpB,OAAA/1C;AAAA,MACA,QAAQpT,EAAQ;AAAA,MAChB,OAAOA,EAAQ;AAAA,IAAA,CAChB;AAAA,EAAA;AAEP;AC7MO,SAASspD,GAActpD,GAAqC;AACjE,QAAM,EAAE,IAAAhB,GAAI,OAAAoO,GAAO,eAAAm8C,EAAA,IAAkBvpD;AACrC,MAAIoN,EAAM,QAAQm8C,EAAe;AACjC,QAAMC,IAAa,KAAK,IAAI,GAAG,KAAK,MAAMD,CAAa,CAAC;AACxD,SAAOn8C,EAAM,OAAOo8C,KAAY;AAC9B,QAAIC,IAA2B,MAC3BC,IAAkE;AACtE,eAAW,CAAClhC,GAAKjR,CAAK,KAAKnK;AACzB,OAAI,CAACs8C,KAAenyC,EAAM,WAAWmyC,EAAY,cAC/CD,IAAYjhC,GACZkhC,IAAcnyC;AAGlB,QAAI,CAACkyC,KAAa,CAACC,EAAa;AAChC,IAAA1qD,EAAG,cAAc0qD,EAAY,OAAO,GACpCt8C,EAAM,OAAOq8C,CAAS;AAAA,EACxB;AACF;AAEO,SAASE,GAAwB3qD,GAA4BoE,GAA0C;AAC5G,MAAIpE,EAAG,cAAA,EAAiB,QAAO;AAE/B,QAAMqE,IAAUrE,EAAG,cAAA;AACnB,SAAKqE,KAELrE,EAAG,YAAYA,EAAG,YAAYqE,CAAO,GACrCrE,EAAG,YAAYA,EAAG,qBAAqB,CAAC,GACxCA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,WAAWA,EAAG,YAAY,GAAGA,EAAG,MAAMA,EAAG,MAAMA,EAAG,eAAeoE,CAAM,GAC1EpE,EAAG,YAAYA,EAAG,YAAY,IAAI,GAE3BqE,KAXc;AAYvB;AAEO,SAASumD,GAAiB5pD,GAAwC;AACvE,QAAM,EAAE,IAAAhB,GAAI,OAAAoO,GAAO,MAAApK,GAAM,QAAAI,GAAQ,aAAAymD,GAAa,eAAAN,GAAe,WAAAO,GAAW,aAAAC,GAAa,eAAAlE,EAAA,IAAkB7lD;AAEvG,MAAI8pD,KAAaC,KAAe/qD,EAAG,cAAA,GAAiB;AAClD,IAAAoE,EAAO,MAAA;AACP;AAAA,EACF;AACA,MAAIgK,EAAM,IAAIpK,EAAK,GAAG,GAAG;AACvB,IAAAI,EAAO,MAAA;AACP;AAAA,EACF;AAEA,QAAMC,IAAUsmD,GAAwB3qD,GAAIoE,CAAM;AAElD,EADAA,EAAO,MAAA,GACFC,MAEL+J,EAAM,IAAIpK,EAAK,KAAK;AAAA,IAClB,KAAKA,EAAK;AAAA,IACV,SAAAK;AAAA,IACA,QAAQL,EAAK;AAAA,IACb,MAAMA,EAAK;AAAA,IACX,UAAU6mD;AAAA,EAAA,CACX,GACDP,GAAc,EAAE,IAAAtqD,GAAI,OAAAoO,GAAO,eAAAm8C,EAAA,CAAe,GAC1C1D,EAAA;AACF;AAEO,SAASmE,GAAqBhrD,GAA4BoO,GAAqD;AACpH,aAAW,CAAA,EAAGmK,CAAK,KAAKnK;AACtB,IAAApO,EAAG,cAAcuY,EAAM,OAAO;AAElC;ACpDO,SAAS0yC,GAAkBjqD,GAAgD;AAChF,QAAM,EAAE,OAAAoT,GAAO,WAAA02C,GAAW,aAAAC,GAAa,qBAAAtE,GAAqB,YAAAF,GAAY,eAAA2E,GAAe,OAAA98C,GAAO,eAAA+8C,EAAA,IAAkBnqD;AAEhH,MADAoT,EAAM,eAAA,GACF02C,KAAaC;AACf,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO/pD,EAAQ;AAAA,IAAA;AAInB,MAAIwiC,IAAQxiC,EAAQ;AACpB,SAAIwiC,MAAU,SACZ,qBAAqBA,CAAK,GAC1BA,IAAQ,OAEVijB,EAAA,GAEAF,EAAA,GACA2E,EAAc,MAAA,GACd98C,EAAM,MAAA,GACN+8C,IAAA,GAEO;AAAA,IACL,SAAS;AAAA,IACT,OAAA3nB;AAAA,EAAA;AAEJ;AAuBO,SAAS4nB,GAAgBpqD,GAAwD;AACtF,MAAIA,EAAQ;AACV,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,OAAOA,EAAQ;AAAA,IAAA;AAInB,MAAIwiC,IAAQxiC,EAAQ;AAapB,MAZIwiC,MAAU,SACZ,qBAAqBA,CAAK,GAC1BA,IAAQ,OAEVxiC,EAAQ,oBAAA,GAERA,EAAQ,eAAe,WAAA,GACvBA,EAAQ,kBAAA,GACRA,EAAQ,2BAAA,GACRA,EAAQ,WAAA,GACRA,EAAQ,cAAc,QAAA,GAElB,CAACA,EAAQ,eAAe,CAACA,EAAQ,GAAG,iBAAiB;AACvD,IAAAgqD,GAAqBhqD,EAAQ,IAAIA,EAAQ,KAAK,GAC9CA,EAAQ,GAAG,aAAaA,EAAQ,YAAY,GAAG,GAC/CA,EAAQ,GAAG,kBAAkBA,EAAQ,YAAY,GAAG,GACpDA,EAAQ,GAAG,cAAcA,EAAQ,YAAY,OAAO;AAEpD,aAASyE,IAAI,GAAGA,IAAIzE,EAAQ,cAAc,QAAQyE,KAAK,GAAG;AACxD,YAAM4lD,IAAerqD,EAAQ,cAAcyE,CAAC;AAC5C,MAAAzE,EAAQ,GAAG,aAAaqqD,EAAa,SAAS,GAC9CrqD,EAAQ,GAAG,aAAaqqD,EAAa,WAAW,GAChDrqD,EAAQ,GAAG,aAAaqqD,EAAa,cAAc,GACnDrqD,EAAQ,GAAG,aAAaqqD,EAAa,WAAW,GAChDrqD,EAAQ,GAAG,cAAcqqD,EAAa,cAAc,GACpDrqD,EAAQ,GAAG,kBAAkBqqD,EAAa,GAAG,GAC7CrqD,EAAQ,GAAG,cAAcqqD,EAAa,OAAO;AAAA,IAC/C;AAAA,EACF;AACA,SAAArqD,EAAQ,MAAM,MAAA,GAEP;AAAA,IACL,YAAY;AAAA,IACZ,OAAAwiC;AAAA,EAAA;AAEJ;ACpGA,SAASgS,GAAoBrD,GAA0BmZ,GAAmC;AACxF,MAAIA,KAAgB,KAAKnZ,EAAY,WAAW;AAC9C,WAAO,IAAI,YAAY,CAAC;AAG1B,MAAI6D,IAAa7D,EAAY;AAC7B,WAAS1sC,IAAI,GAAGA,IAAI0sC,EAAY,QAAQ1sC,KAAK;AAC3C,IAAI0sC,EAAY1sC,CAAC,IAAI6lD,MACrBtV,KAAc;AAEhB,MAAIA,MAAe7D,EAAY;AAC7B,WAAOA;AAET,MAAI6D,KAAc;AAChB,WAAO,IAAI,YAAY,CAAC;AAG1B,QAAMN,IAAW,IAAI,YAAYM,CAAU;AAC3C,MAAIntB,IAAS;AACb,WAASpjB,IAAI,GAAGA,IAAI0sC,EAAY,QAAQ1sC,KAAK,GAAG;AAC9C,UAAM8lD,IAAMpZ,EAAY1sC,CAAC;AACzB,IAAI8lD,KAAOD,MACX5V,EAAS7sB,CAAM,IAAI0iC,GACnB1iC,KAAU;AAAA,EACZ;AACA,SAAO6sB;AACT;AAEA,SAAS8V,GAAiBC,GAA4C/xB,GAA4C;AAChH,SAAIA,KAAS,IAAU,IAAI,WAAW,CAAC,IACnC+xB,EAAc,SAAS/xB,IAClB,IAAI,WAAWA,CAAK,IAEtB+xB,EAAc,SAAS,GAAG/xB,CAAK;AACxC;AAEO,SAASgyB,GAAgBjpB,GAA6BziC,GAA4BqrD,GAA4BN,GAAsB3tC,GAA2D;AACpM,MAAI,CAACA,KAAUA,EAAO,WAAW;AAC/B,WAAO;AAAA,MACL,GAAGqlB;AAAA,MACH,kBAAkB;AAAA,IAAA;AAItB,QAAMkpB,IAAc,IAAI,WAAWvuC,CAAM;AACzC,MAAI2tC,KAAe/qD,EAAG;AACpB,WAAO;AAAA,MACL,GAAGyiC;AAAA,MACH,kBAAkBkpB;AAAA,IAAA;AAItB,QAAMC,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMD,EAAY,SAAS,CAAC,CAAC;AAClE,SAAA3rD,EAAG,YAAYA,EAAG,YAAYqrD,EAAa,cAAc,GACzDrrD,EAAG,WAAWA,EAAG,YAAY,GAAGA,EAAG,MAAM4rD,GAAa,GAAG,GAAG5rD,EAAG,MAAMA,EAAG,eAAe2rD,CAAW,GAClG3rD,EAAG,YAAYA,EAAG,YAAY,IAAI,GAE3B;AAAA,IACL,GAAGyiC;AAAA,IACH,kBAAkBkpB;AAAA,IAClB,kBAAkBC;AAAA,EAAA;AAEtB;AAEO,SAASC,GAAappB,GAA6BziC,GAA4BqrD,GAA4BN,GAAsBh2C,GAA6D;AACnM,MAAI,CAACA,KAAU,CAACA,EAAO,SAAS,CAACA,EAAO,aAAa,CAACA,EAAO;AAC3D,WAAO;AAAA,MACL,GAAG0tB;AAAA,MACH,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,iBAAiB;AAAA,IAAA;AAIrB,QAAMmP,IAAiB78B,EAAO,qBAAqB,aAAaA,EAAO,YAAY,MAC7E+2C,IAAela,MAAmB,MAClCD,IAAY,KAAK,IAAI,GAAG,KAAK,IAAI58B,EAAO,OAAO,KAAK,MAAMA,EAAO,UAAU,SAAS,CAAC,GAAGA,EAAO,eAAe,QAAQ+2C,IAAela,EAAe,SAAS,OAAO,gBAAgB,CAAC,GACrL9C,IAAgB/5B,EAAO,UAAU,SAAS,GAAG48B,IAAY,CAAC,GAC1Doa,IAAqBh3C,EAAO,eAAe,SAAS,GAAG48B,CAAS,GAChE3C,IAAgB8c,IAAela,EAAe,SAAS,GAAGD,CAAS,IAAI,QACvEqa,IAAiBj3C,EAAO,uBAAuB,aAC/Ck3C,IAAkBD,IAAiBxW,GAAoBzgC,EAAO,aAA4B48B,CAAS,IAAI,MAEvG94B,IAAO4pB,EAAQ,eACfypB,IAAmBrzC,GAAM,qBAAqB,YAC9CszC,IACJ1pB,EAAQ,qBACR,CAAC5pB,KACDA,EAAK,UAAU84B,KACf,CAACiS,GAAgB/qC,EAAK,WAAWi2B,CAAa,KAC9C,CAAC8U,GAAgB/qC,EAAK,gBAAgBkzC,CAAkB,KACxDG,MAAqBJ,KACpBA,MAAiB,CAACjzC,GAAM,aAAa,CAAC+qC,GAAgB/qC,EAAK,WAAWm2B,CAAa,IAChFod,IAAqB3pB,EAAQ,qBAAsBupB,MAAmB,CAACnzC,GAAM,eAAe,CAAC+qC,GAAgB/qC,EAAK,aAAaozC,CAAe,MAAQ,CAACD,KAAkB,CAAC,CAACnzC,GAAM,aAEjLwzC,IAAkC;AAAA,IACtC,GAAG5pB;AAAA,IACH,eAAe;AAAA,MACb,OAAOkP;AAAA,MACP,WAAW7C;AAAA,MACX,gBAAgBid;AAAA,MAChB,WAAW/c;AAAA,MACX,aAAagd,IAAkBC,KAAmB,SAAa;AAAA,IAAA;AAAA,EACjE;AAGF,MAAIlB,KAAe/qD,EAAG;AACpB,WAAOqsD;AAGT,QAAMC,IAAmBD,EAAY;AACrC,MAAI,CAACC;AACH,WAAOD;AAGT,MAAIF,GAAiB;AACnB,IAAAnsD,EAAG,WAAWA,EAAG,cAAcqrD,EAAa,SAAS,GACrDrrD,EAAG,WAAWA,EAAG,cAAcssD,EAAiB,WAAWtsD,EAAG,WAAW,GAEzEA,EAAG,WAAWA,EAAG,cAAcqrD,EAAa,WAAW,GACvDrrD,EAAG,WAAWA,EAAG,cAAcssD,EAAiB,gBAAgBtsD,EAAG,WAAW;AAE9E,UAAMyrD,IAAgBD,GAAiBa,EAAY,eAAe1a,CAAS;AAC3E,IAAA3xC,EAAG,WAAWA,EAAG,cAAcqrD,EAAa,cAAc,GAC1DrrD,EAAG,WAAWA,EAAG,cAAcssD,EAAiB,aAAab,GAAezrD,EAAG,WAAW,GAC1FA,EAAG,WAAWA,EAAG,cAAc,IAAI,GACnCqsD,EAAY,gBAAgBZ;AAAA,EAC9B;AAEA,SAAIO,KAAkBI,MACpBpsD,EAAG,WAAWA,EAAG,sBAAsBqrD,EAAa,WAAW,GAC/DrrD,EAAG,WAAWA,EAAG,sBAAsBisD,KAAmB,IAAI,YAAY,CAAC,GAAGjsD,EAAG,YAAY,GAC7FA,EAAG,WAAWA,EAAG,sBAAsB,IAAI,IAG7CqsD,EAAY,kBAAkBL,GAC9BK,EAAY,aAAaL,IAAkBC,GAAiB,UAAU,IAAKK,EAAiB,QACxFH,KAAmBC,OACrBC,EAAY,oBAAoB,KAG3BA;AACT;AC9GO,SAASE,GAAYvrD,GAAgD;AAC1E,QAAM;AAAA,IACJ,IAAAhB;AAAA,IACA,QAAA6iD;AAAA,IACA,QAAA3iD;AAAA,IACA,OAAAkO;AAAA,IACA,aAAAy8C;AAAA,IACA,aAAA2B;AAAA,IACA,oBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,eAAAxB;AAAA,IACA,iBAAApB;AAAA,IACA,wBAAAX;AAAA,IACA,eAAAhB;AAAA,IACA,kBAAAe;AAAA,EAAA,IACEloD;AAEJ,EAAAhB,EAAG,WAAW,MAAM,MAAM,KAAK,CAAC,GAChCA,EAAG,MAAMA,EAAG,gBAAgB;AAE5B,QAAM,EAAE,MAAAgnC,GAAM,SAAA7F,EAAA,IAAY2oB,EAAA,GACpB7oB,IAAaknB,EAAA,GACbtG,IAAc,IAAI,IAAI1gB,EAAQ,IAAI,CAAAn9B,MAAQA,EAAK,GAAG,CAAC;AAEzD,EAAAhE,EAAG,WAAWwsD,EAAY,OAAO,GACjCxsD,EAAG,gBAAgBwsD,EAAY,GAAG,GAClCxsD,EAAG,iBAAiBwsD,EAAY,SAAS,IAAO3J,EAAO,WAAW,GAClE7iD,EAAG,UAAUwsD,EAAY,UAAU,CAAC,GACpCxsD,EAAG,UAAUwsD,EAAY,aAAaC,EAAmB,UAAU,GACnEzsD,EAAG,UAAUwsD,EAAY,WAAWC,EAAmB,QAAQ,GAC/DzsD,EAAG,UAAUwsD,EAAY,aAAaC,EAAmB,UAAU;AAEnE,QAAME,IAA8B,CAAA;AACpC,aAAW,CAAA,EAAGljC,CAAM,KAAKrb;AACvB,IAAIyzC,EAAY,IAAIp4B,EAAO,GAAG,KACzBy/B,EAAiBz/B,EAAO,QAAQwX,CAAU,KAC/C0rB,EAAc,KAAKljC,CAAM;AAE3B,EAAAkjC,EAAc,KAAK,CAACzmD,GAAGwE,MAAMxE,EAAE,OAAOwE,EAAE,IAAI;AAE5C,aAAW+e,KAAUkjC;AACnB,IAAAljC,EAAO,WAAWohC,GAClB7qD,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYypB,EAAO,OAAO,GAC5CzpB,EAAG,UAAUwsD,EAAY,SAAS/iC,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,CAAC,GACxGzpB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC;AAGvC,MAAI4sD,IAAgB;AACpB,QAAMC,IAAgC,CAAA;AACtC,aAAW7oD,KAAQm9B,GAAS;AAC1B,UAAM1X,IAASrb,EAAM,IAAIpK,EAAK,GAAG;AACjC,QAAI,CAACylB,GAAQ;AACX,MAAAojC,EAAa,KAAK7oD,CAAI;AACtB;AAAA,IACF;AACA,IAAAylB,EAAO,WAAWohC,GAClB7qD,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYypB,EAAO,OAAO,GAC5CzpB,EAAG,UAAUwsD,EAAY,SAAS/iC,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,GAAGA,EAAO,OAAO,CAAC,CAAC,GACxGzpB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC,GACrC4sD,KAAiB;AAAA,EACnB;AAEA,QAAME,IAAmCD,EAAa,MAAA,GAChDE,IAA4B,KAC5BC,IAA0B,CAAA;AAChC,EAAIhmB,IAAO,KAAGgmB,EAAc,KAAKhmB,IAAO,CAAC,GACrCA,IAAO9mC,EAAO,eAAa8sD,EAAc,KAAKhmB,IAAO,CAAC;AAC1D,aAAWimB,KAAgBD,GAAe;AACxC,UAAME,IAAqB/D,EAAuB8D,CAAY;AAC9D,eAAWjpD,KAAQkpD;AACjB,MAAI9+C,EAAM,IAAIpK,EAAK,GAAG,MACtBA,EAAK,aAAa+oD,GAClBD,EAAgB,KAAK9oD,CAAI;AAAA,EAE7B;AACA,EAAAknD,EAAc,SAAS4B,CAAe,GAEtC9sD,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI;AAEvB,MAAImtD,IAAiB,GACjBC,IAAiB;AACrB,MAAIV,EAAY,SAAS,GAAG;AAC1B,IAAA1sD,EAAG,OAAOA,EAAG,KAAK,GAClBA,EAAG,UAAUA,EAAG,KAAKA,EAAG,mBAAmB;AAC3C,aAASyF,IAAI,GAAGA,IAAIinD,EAAY,QAAQjnD,KAAK,GAAG;AAC9C,YAAM4nD,IAAQX,EAAYjnD,CAAC;AAC3B,MAAI4nD,EAAM,cAAc,MAExBrtD,EAAG,WAAWqtD,EAAM,aAAa,OAAO,GACxCrtD,EAAG,gBAAgBqtD,EAAM,aAAa,GAAG,GACzCrtD,EAAG,iBAAiBqtD,EAAM,aAAa,SAAS,IAAOxK,EAAO,WAAW,GACzE7iD,EAAG,UAAUqtD,EAAM,aAAa,YAAYA,EAAM,WAAW,GAC7DrtD,EAAG,UAAUqtD,EAAM,aAAa,eAAeA,EAAM,cAAc,GACnErtD,EAAG,UAAUqtD,EAAM,aAAa,gBAAgBA,EAAM,cAAc,CAAC,GAAGA,EAAM,cAAc,CAAC,CAAC,GAC9FrtD,EAAG,UAAUqtD,EAAM,aAAa,eAAeA,EAAM,YAAY,GACjErtD,EAAG,UAAUqtD,EAAM,aAAa,mBAAmBA,EAAM,gBAAgB,GACzErtD,EAAG,UAAUqtD,EAAM,aAAa,sBAAsBA,EAAM,qBAAqB,GACjFrtD,EAAG,UAAUqtD,EAAM,aAAa,sBAAsBA,EAAM,oBAAoB,CAAC,GAAGA,EAAM,oBAAoB,CAAC,GAAGA,EAAM,oBAAoB,CAAC,CAAC,GAC9IrtD,EAAG,UAAUqtD,EAAM,aAAa,cAAcA,EAAM,gBAAgB,GACpErtD,EAAG,UAAUqtD,EAAM,aAAa,UAAU,CAAC,GAC3CrtD,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYqtD,EAAM,aAAa,cAAc,GAC3DA,EAAM,kBACRrtD,EAAG,aAAaA,EAAG,QAAQqtD,EAAM,YAAYrtD,EAAG,cAAc,CAAC,IAE/DA,EAAG,WAAWA,EAAG,QAAQ,GAAGqtD,EAAM,UAAU,GAE9CF,KAAkBE,EAAM,YACxBD,KAAkB;AAAA,IACpB;AACA,IAAAptD,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI;AAAA,EACzB;AAEA,SAAO;AAAA,IACL,MAAAgnC;AAAA,IACA,SAAS7F,EAAQ;AAAA,IACjB,UAAUyrB;AAAA,IACV,QAAQO;AAAA,IACR,UAAUR,EAAc;AAAA,IACxB,WAAWC;AAAA,IACX,aAAaC,EAAa;AAAA,IAC1B,WAAWF,EAAc,SAASC,IAAgBQ;AAAA,EAAA;AAEtD;AC1KO,SAASE,GAAgBttD,GAA+C;AAkD7E,QAAMU,IAAUL,GAAcL,GAjDf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgCiC,GAC5CutD,IAAU5sD,GAAuBX,GAAIU,GAAS,SAAS,GACvD8sD,IAAU7sD,GAAuBX,GAAIU,GAAS,SAAS,GACvD+sD,IAAW9sD,GAAuBX,GAAIU,GAAS,UAAU,GACzDgtD,IAAc/sD,GAAuBX,GAAIU,GAAS,aAAa,GAC/DitD,IAAYhtD,GAAuBX,GAAIU,GAAS,WAAW,GAC3DktD,IAAcjtD,GAAuBX,GAAIU,GAAS,aAAa,GAE/D6C,IAAMvD,EAAG,kBAAA,GACT6tD,IAAM7tD,EAAG,aAAA;AACf,MAAI,CAACuD,KAAO,CAACsqD;AACX,UAAM,IAAI,MAAM,0BAA0B;AAG5C,EAAA7tD,EAAG,gBAAgBuD,CAAG,GACtBvD,EAAG,WAAWA,EAAG,cAAc6tD,CAAG,GAClC7tD,EAAG,WAAWA,EAAG,cAAc,IAAI,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,GAAGA,EAAG,WAAW;AAEjH,QAAM8tD,IAAQ9tD,EAAG,kBAAkBU,GAAS,OAAO,GAC7CqtD,IAAM/tD,EAAG,kBAAkBU,GAAS,KAAK;AAC/C,MAAIotD,IAAQ,KAAKC,IAAM;AACrB,UAAM,IAAI,MAAM,8BAA8B;AAEhD,SAAA/tD,EAAG,wBAAwB8tD,CAAK,GAChC9tD,EAAG,wBAAwB+tD,CAAG,GAC9B/tD,EAAG,oBAAoB8tD,GAAO,GAAG9tD,EAAG,OAAO,IAAO,IAAI,CAAC,GACvDA,EAAG,oBAAoB+tD,GAAK,GAAG/tD,EAAG,OAAO,IAAO,IAAI,CAAC,GAErDA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GAE5B;AAAA,IACL,SAAAU;AAAA,IACA,KAAA6C;AAAA,IACA,KAAAsqD;AAAA,IACA,SAAAN;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA,WAAAC;AAAA,IACA,aAAAC;AAAA,EAAA;AAEJ;AAEO,SAASI,GAAiBhuD,GAA0C;AAwEzE,QAAMU,IAAUL,GAAcL,GAvEV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAsDsC,GACtDutD,IAAU5sD,GAAuBX,GAAIU,GAAS,SAAS,GACvDutD,IAAattD,GAAuBX,GAAIU,GAAS,YAAY,GAC7DwtD,IAAgBvtD,GAAuBX,GAAIU,GAAS,eAAe,GACnEytD,IAAgBxtD,GAAuBX,GAAIU,GAAS,eAAe,GACnE0tD,IAAoBztD,GAAuBX,GAAIU,GAAS,mBAAmB,GAC3E2tD,IAAuB1tD,GAAuBX,GAAIU,GAAS,sBAAsB,GACjF4tD,IAAuB3tD,GAAuBX,GAAIU,GAAS,sBAAsB,GACjF6tD,IAAW5tD,GAAuBX,GAAIU,GAAS,UAAU,GACzD8tD,IAAe7tD,GAAuBX,GAAIU,GAAS,cAAc,GACjE+tD,IAAiB9tD,GAAuBX,GAAIU,GAAS,gBAAgB,GAErE6C,IAAMvD,EAAG,kBAAA,GACT0uD,IAAY1uD,EAAG,aAAA,GACf2uD,IAAc3uD,EAAG,aAAA,GACjB4uD,IAAiB5uD,EAAG,aAAA,GACpB6uD,IAAc7uD,EAAG,aAAA,GACjB8uD,IAAiB9uD,EAAG,cAAA;AAC1B,MAAI,CAACuD,KAAO,CAACmrD,KAAa,CAACC,KAAe,CAACC,KAAkB,CAACC,KAAe,CAACC;AAC5E,UAAM,IAAI,MAAM,gCAAgC;AAGlD,EAAA9uD,EAAG,gBAAgBuD,CAAG,GAEtBvD,EAAG,WAAWA,EAAG,cAAc0uD,CAAS,GACxC1uD,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,QAAM+uD,IAAS/uD,EAAG,kBAAkBU,GAAS,WAAW;AACxD,MAAIquD,IAAS;AACX,UAAM,IAAI,MAAM,oCAAoC;AAEtD,EAAA/uD,EAAG,wBAAwB+uD,CAAM,GACjC/uD,EAAG,oBAAoB+uD,GAAQ,GAAG/uD,EAAG,OAAO,IAAO,GAAG,CAAC,GAEvDA,EAAG,WAAWA,EAAG,cAAc2uD,CAAW,GAC1C3uD,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,QAAMgvD,IAAWhvD,EAAG,kBAAkBU,GAAS,QAAQ;AACvD,MAAIsuD,IAAW;AACb,UAAM,IAAI,MAAM,iCAAiC;AAEnD,EAAAhvD,EAAG,wBAAwBgvD,CAAQ,GACnChvD,EAAG,qBAAqBgvD,GAAU,GAAGhvD,EAAG,gBAAgB,GAAG,CAAC,GAE5DA,EAAG,WAAWA,EAAG,cAAc4uD,CAAc,GAC7C5uD,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,QAAMivD,IAAcjvD,EAAG,kBAAkBU,GAAS,WAAW;AAC7D,MAAIuuD,IAAc;AAChB,UAAM,IAAI,MAAM,qCAAqC;AAEvD,SAAAjvD,EAAG,wBAAwBivD,CAAW,GACtCjvD,EAAG,qBAAqBivD,GAAa,GAAGjvD,EAAG,eAAe,GAAG,CAAC,GAE9DA,EAAG,WAAWA,EAAG,sBAAsB6uD,CAAW,GAClD7uD,EAAG,WAAWA,EAAG,sBAAsB,GAAGA,EAAG,YAAY,GAEzDA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GACnCA,EAAG,WAAWA,EAAG,sBAAsB,IAAI,GAE3CA,EAAG,YAAYA,EAAG,YAAY8uD,CAAc,GAC5C9uD,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,OAAO,GACjEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,OAAO,GACjEA,EAAG,WAAWA,EAAG,YAAY,GAAGA,EAAG,MAAM,GAAG,GAAG,GAAGA,EAAG,MAAMA,EAAG,eAAe,IAAI,WAAW,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC,CAAC,GACjHA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAE3B;AAAA,IACL,SAAAU;AAAA,IACA,KAAA6C;AAAA,IACA,WAAAmrD;AAAA,IACA,aAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,SAAAvB;AAAA,IACA,YAAAU;AAAA,IACA,eAAAC;AAAA,IACA,eAAAC;AAAA,IACA,gBAAAM;AAAA,IACA,mBAAAL;AAAA,IACA,sBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,UAAAC;AAAA,IACA,cAAAC;AAAA,EAAA;AAEJ;AC3PO,SAAS/H,GAAoBh0B,GAAwC;AAC1E,EAAAA,EAAM,YAAY,MACdA,EAAM,UAAU,SAClB,qBAAqBA,EAAM,KAAK,GAChCA,EAAM,QAAQ;AAElB;AAEO,SAASy8B,GAAmBluD,GAA0C;AAC3E,QAAM,EAAE,OAAAyxB,GAAO,QAAAowB,GAAQ,QAAA5G,GAAQ,YAAAkT,GAAY,QAAA9I,GAAQ,UAAA+I,MAAapuD,GAC1D2mC,IAAOkb,EAAO,aAAA;AACpB,EAAA4D,GAAoBh0B,CAAK,GACzBA,EAAM,YAAY;AAAA,IAChB,SAAS7W,GAAA;AAAA,IACT,YAAY,KAAK,IAAI,GAAGuzC,CAAU;AAAA,IAClC,MAAAxnB;AAAA,IACA,IAAIsU;AAAA,IACJ,QAAAoK;AAAA,EAAA;AAGF,QAAMpxC,IAAO,MAAY;AACvB,UAAM8mC,IAAYtpB,EAAM;AACxB,QAAI,CAACspB,EAAW;AAEhB,UAAMK,IAAU,KAAK,IAAI,GAAGxgC,GAAA,IAAUmgC,EAAU,OAAO,GACjDM,IAAON,EAAU,cAAc,IAAI,IAAIjhC,EAAMshC,IAAUL,EAAU,YAAY,GAAG,CAAC;AACvF,QAAIO,IAAQD;AACZ,QAAI;AACF,MAAAC,IAAQP,EAAU,OAAOM,CAAI;AAAA,IAC/B,QAAQ;AACN,MAAAC,IAAQD;AAAA,IACV;AAcA,QAbK,OAAO,SAASC,CAAK,MACxBA,IAAQD,IAEVC,IAAQxhC,EAAMwhC,GAAO,GAAG,CAAC,GAEzBuG,EAAO,aAAa;AAAA,MAClB,MAAM9G,EAAU,KAAK,QAAQA,EAAU,GAAG,OAAOA,EAAU,KAAK,QAAQO;AAAA,MACxE,SAASP,EAAU,KAAK,WAAWA,EAAU,GAAG,UAAUA,EAAU,KAAK,WAAWO;AAAA,MACpF,SAASP,EAAU,KAAK,WAAWA,EAAU,GAAG,UAAUA,EAAU,KAAK,WAAWO;AAAA,MACpF,aAAaP,EAAU,KAAK,eAAeA,EAAU,GAAG,cAAcA,EAAU,KAAK,eAAeO;AAAA,IAAA,CACrG,GACD8S,EAAA,GAEI/S,KAAQ,GAAG;AACb,MAAA5pB,EAAM,YAAY,MAClBA,EAAM,QAAQ;AACd;AAAA,IACF;AAEA,IAAAA,EAAM,QAAQ,sBAAsBxd,CAAI;AAAA,EAC1C;AAEA,EAAAwd,EAAM,QAAQ,sBAAsBxd,CAAI;AAC1C;ACrDO,SAASo6C,GAAyBC,GAAuD;AAC9F,QAAMzkC,IAAU,KAAK,IAAIykC,IAAU,KAAK,IAAI,GACtCxkC,IAAU,KAAK,IAAI,GAAGwkC,IAAU,CAAC;AACvC,SAAO;AAAA,IACL,SAAAzkC;AAAA,IACA,SAAS,KAAK,IAAIA,GAASC,CAAO;AAAA,EAAA;AAEtC;AAEO,SAASykC,GAAkBD,GAAiBE,GAAgCC,GAAsE;AACvJ,QAAMC,IAAWL,GAAyBC,CAAO;AACjD,MAAIzkC,IAAU2kC,KAAmBE,EAAS,SACtC5kC,IAAU2kC,KAAmBC,EAAS;AAC1C,SAAA7kC,IAAU,KAAK,IAAI,MAAMA,CAAO,GAChCC,IAAU,KAAK,IAAI,MAAMA,CAAO,GAC5BD,IAAUC,MACZD,IAAUC,IAEL,EAAE,SAAAD,GAAS,SAAAC,EAAA;AACpB;AAEO,SAAS6kC,GACd9M,GACAh4B,GACAC,GACAtpB,GACAmlD,GACc;AACd,QAAMtnC,IAAUwjC,EAAO,aAAA,GACjBpT,IAA0B;AAAA,IAC9B,MAAM,OAAOjuC,EAAK,QAAS,YAAY,OAAO,SAASA,EAAK,IAAI,IAAIsZ,EAAMtZ,EAAK,MAAMqpB,GAASC,CAAO,IAAIzL,EAAQ;AAAA,IACjH,SAAS,OAAO7d,EAAK,WAAY,YAAY,OAAO,SAASA,EAAK,OAAO,IAAIA,EAAK,UAAU6d,EAAQ;AAAA,IACpG,SAAS,OAAO7d,EAAK,WAAY,YAAY,OAAO,SAASA,EAAK,OAAO,IAAIA,EAAK,UAAU6d,EAAQ;AAAA,IACpG,aAAa,OAAO7d,EAAK,eAAgB,YAAY,OAAO,SAASA,EAAK,WAAW,IAAIA,EAAK,cAAc6d,EAAQ;AAAA,EAAA;AAGtH,EAAAwjC,EAAO,aAAapT,CAAS,GAC7BkX,EAAA;AACA,QAAM1K,IAAS4G,EAAO,aAAA;AACtB,SAAAA,EAAO,aAAaxjC,CAAO,GACpB48B;AACT;AAEO,SAAS2T,GACd1vD,GACA2vD,GACAC,GACAjlC,GACAC,GACAhpB,IAAc,GAC6B;AAC3C,QAAML,IAAO,KAAK,IAAIouD,IAAgB3vD,EAAO,OAAO4vD,IAAiB5vD,EAAO,MAAM,GAC5E4E,IAAW,OAAO,SAASrD,CAAI,KAAKA,IAAO,IAAIA,IAAO,GACtDsuD,IAAcj1C,EAAMhW,GAAU+lB,GAASC,CAAO,GAC9CklC,IAAgBH,IAAgBE,GAChCE,IAAgBH,IAAiBC;AAEvC,SAAO;AAAA,IACL,SAASjrD;AAAA,IACT,QAAQ;AAAA,MACN,MAAMirD;AAAA,MACN,UAAU7vD,EAAO,QAAQ8vD,KAAiB;AAAA,MAC1C,UAAU9vD,EAAO,SAAS+vD,KAAiB;AAAA,MAC3C,aAAAnuD;AAAA,IAAA;AAAA,EACF;AAEJ;AAEO,SAASouD,GACdrN,GACAh4B,GACAC,GACAyX,GACA3gC,GACAC,GAC8B;AAC9B,QAAM4wB,IAAQowB,EAAO,aAAA,GACfsN,IAAWr1C,EAAM2X,EAAM,OAAO8P,GAAQ1X,GAASC,CAAO;AAC5D,MAAIqlC,MAAa19B,EAAM,KAAM,QAAO;AAEpC,QAAM,CAACrwB,GAAQC,CAAM,IAAIwgD,EAAO,cAAcjhD,GAASC,CAAO,GACxDuuD,IAAKvN,EAAO,gBAAA,GACZ9gD,IAAKH,IAAUwuD,EAAG,QAAQ,KAC1BpuD,IAAKH,IAAUuuD,EAAG,SAAS,KAC3BnuD,IAAMf,GAAUuxB,EAAM,WAAW,GACjCvwB,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBklD,IAAWplD,IAAKouD,IAAYjuD,IAAOF,IAAKmuD,IAAYhuD,GACpDilD,IAAWrlD,IAAKouD,IAAYhuD,IAAOH,IAAKmuD,IAAYjuD,GACpD4mD,IAAc1mD,IAAS+kD,GACvB4B,IAAc1mD,IAAS+kD;AAE7B,SAAO;AAAA,IACL,MAAM+I;AAAA,IACN,SAASrH,IAAcsH,EAAG,SAAS,IAAID;AAAA,IACvC,SAASpH,IAAcqH,EAAG,UAAU,IAAID;AAAA,EAAA;AAE5C;AAEO,SAASE,GACdxN,GACAh4B,GACAC,GACAwlC,GACA1uD,GACAC,GAC8B;AAC9B,QAAM4wB,IAAQowB,EAAO,aAAA,GACfsN,IAAWr1C,EAAMw1C,GAAYzlC,GAASC,CAAO;AACnD,MAAIqlC,MAAa19B,EAAM,KAAM,QAAO;AAEpC,QAAM,CAACrwB,GAAQC,CAAM,IAAIwgD,EAAO,cAAcjhD,GAASC,CAAO,GACxDuuD,IAAKvN,EAAO,gBAAA,GACZ9gD,IAAKH,IAAUwuD,EAAG,QAAQ,KAC1BpuD,IAAKH,IAAUuuD,EAAG,SAAS,KAC3BnuD,IAAMf,GAAUuxB,EAAM,WAAW,GACjCvwB,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBklD,IAAWplD,IAAKouD,IAAYjuD,IAAOF,IAAKmuD,IAAYhuD,GACpDilD,IAAWrlD,IAAKouD,IAAYhuD,IAAOH,IAAKmuD,IAAYjuD,GACpD4mD,IAAc1mD,IAAS+kD,GACvB4B,IAAc1mD,IAAS+kD;AAE7B,SAAO;AAAA,IACL,MAAM+I;AAAA,IACN,SAASrH,IAAcsH,EAAG,SAAS,IAAID;AAAA,IACvC,SAASpH,IAAcqH,EAAG,UAAU,IAAID;AAAA,EAAA;AAE5C;AC/HO,MAAMI,KAAwB;AAE9B,SAASC,GAAmBC,GAA6Cp1C,GAAmC;AACjH,MAAI,CAACo1C,KAAkBA,EAAe,WAAW,UAAU,CAAA;AAC3D,MAAI,CAACp1C,KAAOA,KAAO,UAAU,CAAA;AAC7B,QAAMq1C,IAAS,KAAKr1C;AACpB,SAAOo1C,EACJ,IAAI,CAAAE,MAAOA,IAAMD,CAAM,EACvB,OAAO,OAAK,OAAO,SAAS3qD,CAAC,KAAKA,IAAI,CAAC,EACvC,KAAK,CAACG,GAAGwE,MAAMxE,IAAIwE,CAAC;AACzB;AAIO,SAASkmD,GAAkBC,GAAsBz1C,GAAqB0sC,GAAyBgJ,GAAmC;AACvI,MAAID,EAAW,WAAW,EAAG,QAAO;AAEpC,QAAMvqD,IAAU,KAAK,IAAI8U,IAAc,MAAO,IAAI;AAElD,MAAI0sC,MAAc,MAAM;AACtB,eAAWiJ,KAAQF;AACjB,UAAIE,IAAO31C,IAAc9U;AACvB,eAAO,EAAE,MAAM,QAAQ,MAAMyqD,EAAA;AAGjC,WAAO;AAAA,EACT;AAEA,WAAStrD,IAAIorD,EAAW,SAAS,GAAGprD,KAAK,GAAGA;AAC1C,QAAIorD,EAAWprD,CAAC,IAAI2V,IAAc9U;AAChC,aAAO,EAAE,MAAM,QAAQ,MAAMuqD,EAAWprD,CAAC,EAAA;AAI7C,SAAIqrD,KAAY11C,KAAey1C,EAAW,CAAC,IAAIvqD,IACtC,EAAE,MAAM,MAAA,IAGV;AACT;AAaO,SAAS0qD,GAAwBrrC,GAAgC2qC,GAAoBW,GAAsBC,GAAsB/B,GAA0B;AAChK,QAAMgC,IAAYxrC,EAAI,OAAO,aAAA,GACvB,CAACyrC,GAAaC,CAAW,IAAI1rC,EAAI,OAAO,cAAcsrC,GAAcC,CAAY,GAChFd,IAAKzqC,EAAI,OAAO,gBAAA,GAChB2rC,IAAiBx2C,EAAMw1C,GAAY3qC,EAAI,SAASA,EAAI,OAAO;AACjE,MAAI2rC,MAAmBH,EAAU,KAAM;AAEvC,QAAMlvD,IAAMf,GAAUiwD,EAAU,WAAW,GACrCjvD,IAAM,KAAK,IAAID,CAAG,GAClBE,IAAM,KAAK,IAAIF,CAAG,GAClBsvD,IAAWN,IAAeb,EAAG,QAAQ,KACrCoB,IAAWN,IAAed,EAAG,SAAS;AAE5C,EAAAzqC,EAAI,oBAAA;AAEJ,QAAM8rC,IAAuB,CAAC1rD,MAAoD;AAChF,UAAMohD,IAAWoK,IAAWxrD,IAAK7D,IAAOsvD,IAAWzrD,IAAK5D,GAClDilD,IAAWmK,IAAWxrD,IAAK5D,IAAOqvD,IAAWzrD,IAAK7D;AACxD,WAAO;AAAA,MACL,SAASkvD,IAAcjK,IAAUiJ,EAAG,SAAS,IAAIrqD;AAAA,MACjD,SAASsrD,IAAcjK,IAAUgJ,EAAG,UAAU,IAAIrqD;AAAA,IAAA;AAAA,EAEtD,GAEM2rD,IAAcD,EAAqBH,CAAc;AACvD,EAAA3rC,EAAI,mBAAmB,YAAY;AAAA,IACjC,SAAS/J,GAAA;AAAA,IACT,YAAY,KAAK,IAAI,GAAGuzC,CAAU;AAAA,IAClC,MAAMgC;AAAA,IACN,IAAI,EAAE,MAAMG,GAAgB,SAASI,EAAY,SAAS,SAASA,EAAY,SAAS,aAAaP,EAAU,YAAA;AAAA,IAC/G,QAAQnL;AAAA,EAAA;AAGV,QAAM/wC,IAAO,MAAY;AACvB,UAAM8mC,IAAYp2B,EAAI,mBAAmB;AACzC,QAAI,CAACo2B,EAAW;AAEhB,UAAMK,IAAU,KAAK,IAAI,GAAGxgC,GAAA,IAAUmgC,EAAU,OAAO,GACjDM,IAA6BvhC,EAAMshC,IAAU+S,GAAY,GAAG,CAAC,GAC7D7S,IAAQxhC,EAAMuhC,IAAOA,KAAQ,IAAI,IAAIA,IAAO,GAAG,CAAC,GAEhDt2C,IAAIorD,EAAU,QAAQG,IAAiBH,EAAU,QAAQ7U,GACzD,EAAE,SAAAr3C,GAAS,SAAAC,MAAYusD,EAAqB1rD,CAAC;AAEnD,IAAA4f,EAAI,OAAO,aAAa,EAAE,MAAM5f,GAAG,SAAAd,GAAS,SAAAC,GAAS,aAAaisD,EAAU,YAAA,CAAa;AAEzF,UAAMQ,IAAatV,KAAQ;AAC3B,IAAIsV,MACFhsC,EAAI,eAAA,GACJA,EAAI,mBAAmB,YAAY,MACnCA,EAAI,mBAAmB,QAAQ,OAGjCA,EAAI,kBAAkBA,EAAI,OAAO,aAAA,CAAc,GAC/CA,EAAI,cAAA,GAECgsC,MACHhsC,EAAI,mBAAmB,QAAQ,sBAAsB1Q,CAAI;AAAA,EAE7D;AAEA,EAAA0Q,EAAI,mBAAmB,QAAQ,sBAAsB1Q,CAAI;AAC3D;ACnCA,MAAM28C,KAAyB;AAgBxB,MAAMC,GAAgB;AAAA,EAuF3B,YAAY9wD,GAA2Bb,GAAwBc,IAAkC,CAAA,GAAI;AAtFpF,IAAAK,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAID,GAAA;AACb,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA;AACS,IAAAA,EAAA;AAET,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,eAAuB;AACvB,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,0BAAqC;AAAA,MAC3C,UAAU;AAAA,MACV,MAAM;AAAA,MACN,oBAAoB;AAAA,MACpB,WAAW;AAAA,MACX,cAAc;AAAA,MACd,cAAc;AAAA,IAAA;AAER,IAAAA,EAAA,2BAAoB;AACpB,IAAAA,EAAA,wBAAiB;AACjB,IAAAA,EAAA,4CAAqCyhD;AACrC,IAAAzhD,EAAA;AACA,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,4BAAqB;AACrB,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,yBAAiC;AACjC,IAAAA,EAAA,yBAAiC;AACjC,IAAAA,EAAA,kCAA2B;AAC3B,IAAAA,EAAA,8BAA8C2kD;AAC9C,IAAA3kD,EAAA,4BAAgD;AAAA,MACtD,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAEQ,IAAAA,EAAA,yCAAkB,IAAA;AAC3B,IAAAA,EAAA,mCAA6CwiD,GAAoBZ,EAAwB;AACzF,IAAA5hD,EAAA,4CAA0E;AAC1E,IAAAA,EAAA,8CAA8E;AAC9E,IAAAA,EAAA,6BAAsB;AACtB,IAAAA,EAAA,8BAAyC,CAAC,GAAG,CAAC;AAC9C,IAAAA,EAAA,iCAA0B;AAC1B,IAAAA,EAAA,sCAA+B;AAC/B,IAAAA,EAAA,oCAAuD,CAAC,GAAGsiD,EAA8B;AACzF,IAAAtiD,EAAA,4BAAmD;AAAA,MACzD,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,YAAY;AAAA,IAAA;AAEN,IAAAA,EAAA,mCAAY,IAAA;AACZ,IAAAA,EAAA,mBAAsB,CAAA;AACtB,IAAAA,EAAA,0BAAmB;AACnB,IAAAA,EAAA,uBAA+B,EAAE,kBAAkB,GAAG,gBAAgB,GAAG,kBAAkB,KAAA;AAC3F,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,oBAAa;AAEJ,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAgBf,SAAK,SAASN,GACd,KAAK,SAASb,GACd,KAAK,oBAAoBc,EAAQ,mBACjC,KAAK,UAAUA,EAAQ,SACvB,KAAK,cAAcA,EAAQ,aAC3B,KAAK,gBAAgBA,EAAQ,eAC7B,KAAK,oBAAoBA,EAAQ,mBACjC,KAAK,YAAYA,EAAQ,aAAa,IACtC,KAAK,gBAAgB,KAAK,IAAI,IAAI,KAAK,MAAMA,EAAQ,iBAAiB,GAAG,CAAC,GAC1E,KAAK,qBAAqB,OAAOA,EAAQ,sBAAuB,YAAY,OAAO,SAASA,EAAQ,kBAAkB,IAAIA,EAAQ,qBAAqB,GACvJ,KAAK,iBAAiBA,EAAQ,kBAAkB,IAChD,KAAK,qCACH,OAAOA,EAAQ,sCAAuC,YAAY,OAAO,SAASA,EAAQ,kCAAkC,IACxH,KAAK,IAAI,GAAGA,EAAQ,kCAAkC,IACtD8hD,IACN,KAAK,4BAA4BmB,GAAwBjjD,EAAQ,eAAe,GAChF,KAAK,qCAAqCsjD,GAAqCtjD,EAAQ,wBAAwB,GAC/G,KAAK,uCAAuC0jD,GAAuC1jD,EAAQ,0BAA0B,GACrH,KAAK,sBAAsBqkD,GAAsBrkD,EAAQ,YAAY,GACrE,KAAK,0BAA0B4jD,GAAqB5jD,EAAQ,gBAAgB,GAC5E,KAAK,+BAA+BukD,GAA+BvkD,EAAQ,qBAAqB,GAChG,KAAK,6BAA6BwkD,GAA6BxkD,EAAQ,mBAAmB,GAC1F,KAAK,qBAAqB2kD,GAA+B3kD,EAAQ,kBAAkB,GACnF,KAAK,kBAAkBmlD,GAAsBnlD,EAAQ,OAAO,GAC5D,KAAK,kBAAkBmlD,GAAsBnlD,EAAQ,OAAO,GAC5D,KAAK,2BAA2BilD,GAAgCjlD,EAAQ,gBAAgB,QAAQ,GAChG,KAAK,uBAAuBolD,GAA0BplD,EAAQ,gBAAgB,MAAM,GACpF,KAAK,YAAYwvD,GAAmBxvD,EAAQ,WAAW,KAAK,OAAO,GAAG,GACtE,KAAK,mBAAmB,EAAQA,EAAQ,kBACxC,KAAK,eAAeA,EAAQ,SAAS;AAErC,UAAMhB,IAAKe,EAAO,WAAW,UAAU;AAAA,MACrC,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,uBAAuBC,EAAQ,yBAAyB;AAAA,IAAA,CACzD;AACD,QAAI,CAAChB;AACH,YAAM,IAAI,MAAM,sBAAsB;AAExC,SAAK,KAAKA,GAEV,KAAK,cAAcstD,GAAgB,KAAK,EAAE,GAC1C,KAAK,gBAAgB,IAAI7L,GAAc;AAAA,MACrC,WAAW,KAAK;AAAA,MAChB,gBAAgBzgD,EAAQ,eAAe,kBAAkB;AAAA,MACzD,YAAYA,EAAQ,eAAe,cAAc;AAAA,MACjD,kBAAkBA,EAAQ,eAAe,oBAAoB;AAAA,MAC7D,iBAAiBA,EAAQ,eAAe,mBAAmB;AAAA,MAC3D,YAAY,CAACgD,GAAMI,MACjB0tD,GAAgB;AAAA,QACd,IAAI,KAAK;AAAA,QACT,OAAO,KAAK;AAAA,QACZ,MAAA9tD;AAAA,QACA,QAAAI;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,eAAe,KAAK;AAAA,QACpB,WAAW,KAAK;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,eAAe,MAAM,KAAK,cAAA;AAAA,MAAc,CACzC;AAAA,MACH,aAAa,CAACJ,GAAMM,GAAOytD,MAAiB;AAC1C,aAAK,cAAc,EAAE,MAAA/tD,GAAM,OAAAM,GAAO,cAAAytD,GAAc,GAChD,QAAQ,KAAK,oBAAoB/tD,EAAK,KAAKM,CAAK;AAAA,MAClD;AAAA,IAAA,CACD,GAED,KAAK,iBAAiB,IAAI,eAAe,MAAM,KAAK,QAAQ,GAC5D,KAAK,eAAe,QAAQvD,CAAM,GAClC,KAAK,oBAAoBghB,GAA+B,MAAM,KAAK,QAAQ;AAE3E,UAAMiwC,IAAgB3H,GAA4B;AAAA,MAChD,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,sBAAsB,MAAM,KAAK;AAAA,MACjC,mBAAmB,MAAM,KAAK;AAAA,MAC9B,uCAAuC,MAAM,KAAK;AAAA,MAClD,qBAAqB,MAAM,KAAK,oBAAA;AAAA,MAChC,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,eAAe,MAAM,KAAK,oBAAoB,KAAK,OAAO,cAAc;AAAA,MACxE,eAAe,MAAM,KAAK,cAAA;AAAA,MAC1B,eAAe,MAAM,KAAK;AAAA,MAC1B,eAAe,MAAM,KAAK;AAAA,MAC1B,QAAQ,CAAC9nB,GAAQn8B,GAAGD,MAAM,KAAK,OAAOo8B,GAAQn8B,GAAGD,CAAC;AAAA,MAClD,iBAAiB,MAAM,KAAK,UAAU,SAAS;AAAA,MAC/C,YAAY,CAAC2hD,GAAW1hD,GAAGD,MAAM,KAAK,eAAe2hD,GAAW1hD,GAAGD,CAAC;AAAA,MACpE,eAAe,KAAK;AAAA,IAAA,CACrB;AACD,SAAK,mBAAmB6rD,EAAc,aACtC,KAAK,mBAAmBA,EAAc,aACtC,KAAK,iBAAiBA,EAAc,WACpC,KAAK,aAAaA,EAAc,OAChC,KAAK,mBAAmBA,EAAc,aACtC,KAAK,mBAAmBA,EAAc,aACtC,KAAK,mBAAmB,CAAC59C,MAAiB,KAAK,mBAAmBA,CAAK,GACvE,KAAK,uBAAuB,CAACA,MAAiB,KAAK,uBAAuBA,CAAK,GAE/EsuC,GAAgC3hD,GAAQ,KAAK,mBAAmB,GAEhE,KAAK,WAAW,EAAE,UAAU,EAAA,CAAG,GAC/B,KAAK,OAAA;AAAA,EACP;AAAA,EAtHQ,oBAA4C;AAClD,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,IAAA;AAAA,EAE1B;AAAA,EA6GQ,kBAAwB;AAC9B,UAAM+d,IAASywC,GAAkB,KAAK,SAAS,KAAK,iBAAiB,KAAK,eAAe;AACzF,SAAK,UAAUzwC,EAAO,SACtB,KAAK,UAAUA,EAAO;AAAA,EACxB;AAAA,EAEQ,uBAAuBtd,GAA2C;AACxE,WAAOywD,GAA8B,KAAK,QAAQ,KAAK,SAAS,KAAK,SAASzwD,GAAM,MAAM0wD,GAAsB,KAAK,QAAQ,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,CAAC;AAAA,EAC7K;AAAA,EAEQ,sBAA4B;AAClCC,IAAAA,GAA2B,KAAK,kBAAkB;AAAA,EACpD;AAAA,EAEQ,mBAAmBlW,GAAsBkT,GAAoB9I,GAAqC;AACxG,SAAK,gCAAgC,KAAK,OAAO,eAAe,MAAMpK,EAAO,IAAI,GACjFiT,GAAmB;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,QAAAjT;AAAA,MACA,YAAAkT;AAAA,MACA,QAAA9I;AAAA,MACA,UAAU,MAAM;AACd6L,QAAAA,GAAsB,KAAK,QAAQ,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU,GAChF,KAAK,oBAAoB,KAAK,OAAO,aAAA,CAAc,GACnD,KAAK,cAAA;AAAA,MACP;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEQ,2BAA+C;AACrD,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,eAAe;AAAA,MACf,eAAe,IAAI,WAAW,CAAC;AAAA,MAC/B,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,IAAA;AAAA,EAEtB;AAAA,EAEQ,sBAAsBtf,GAAoC;AAChE,WAAO;AAAA,MACL,IAAAA;AAAA,MACA,SAASob,GAAiB,KAAK,EAAE;AAAA,MACjC,SAAS,KAAK,yBAAA;AAAA,MACd,oBAAoBnK,GAAoB,KAAK,yBAAyB;AAAA,MACtE,6BAA6BE,GAAiC,KAAK,kCAAkC;AAAA,MACrG,+BAA+BC,GAAmC,KAAK,oCAAoC;AAAA,MAC3G,cAAc,KAAK;AAAA,MACnB,eAAe,CAAC,GAAG,KAAK,oBAAoB;AAAA,MAC5C,kBAAkB,KAAK;AAAA,MACvB,uBAAuB,KAAK;AAAA,MAC5B,qBAAqB,CAAC,GAAG,KAAK,0BAA0B;AAAA,IAAA;AAAA,EAE5D;AAAA,EAEQ,iBAAiB5I,IAAkBwW,IAAgD;AACzF,UAAM5X,IAAS,OAAOoB,KAAWwW,EAAsB,GACjDtP,IAAW,KAAK,YAAY,IAAItI,CAAM;AAC5C,QAAIsI,EAAU,QAAOA;AAErB,UAAM8P,IAAU,KAAK,sBAAsBpY,CAAM;AACjD,gBAAK,YAAY,IAAIA,GAAQoY,CAAO,GAC7BA;AAAA,EACT;AAAA,EAEQ,mBAAmB1xD,GAA6B;AACtD,IAAI,KAAK,eAAe,KAAK,GAAG,oBAChC,KAAK,GAAG,aAAaA,EAAQ,SAAS,GACtC,KAAK,GAAG,aAAaA,EAAQ,WAAW,GACxC,KAAK,GAAG,aAAaA,EAAQ,cAAc,GAC3C,KAAK,GAAG,aAAaA,EAAQ,WAAW,GACxC,KAAK,GAAG,cAAcA,EAAQ,cAAc,GAC5C,KAAK,GAAG,kBAAkBA,EAAQ,GAAG,GACrC,KAAK,GAAG,cAAcA,EAAQ,OAAO;AAAA,EACvC;AAAA,EAEQ,uBAA2C;AACjD,UAAMgE,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9CkU,IAA0B,CAAA;AAChC,eAAWy0C,KAAS,KAAK,YAAY,OAAA,GAAU;AAC7C,YAAMgF,IAAiB,KAAK,aAAahF,EAAM,EAAE;AACjD,MAAAz0C,EAAI,KAAK;AAAA,QACP,cAAcy0C,EAAM;AAAA,QACpB,YAAYA,EAAM,QAAQ;AAAA,QAC1B,iBAAiBA,EAAM,QAAQ;AAAA,QAC/B,kBAAkBA,EAAM,QAAQ;AAAA,QAChC,eAAeA,EAAM;AAAA,QACrB,cAAcA,EAAM;AAAA,QACpB,kBAAkB,KAAK,oBAAoBA,EAAM,EAAE;AAAA,QACnD,uBAAuBA,EAAM;AAAA,QAC7B,qBAAqBA,EAAM;AAAA,QAC3B,gBAAAgF;AAAA,QACA,aAAaA,IAAiB3tD;AAAA,MAAA,CAC/B;AAAA,IACH;AACA,WAAOkU;AAAA,EACT;AAAA,EAEQ,qBAA2B;AACjC,SAAK,cAAc,mBAAmB,GACtC,KAAK,cAAc,iBAAiB,GACpC,KAAK,cAAc,mBAAmB;AAAA,EACxC;AAAA,EAEQ,gCAAgCwC,GAAqBk1C,GAA0B;AACrF,IAAI,KAAK,IAAIl1C,IAAck1C,CAAU,IAAI,QACzC,KAAK,mBAAA;AAAA,EACP;AAAA,EAEQ,wBAAwB9uD,GAAoB8wD,IAAkB,IAAY;AAChF,UAAMjzC,IAAU,KAAK,OAAO,aAAA;AAC5B,IAAIizC,KACF,KAAK,oBAAA,GAEP,KAAK,gCAAgCjzC,EAAQ,MAAM7d,EAAK,IAAI,GAC5D,KAAK,OAAO,aAAaA,CAAI,GAC7B,KAAK,oBAAoB,KAAK,OAAO,aAAA,CAAc,GACnD,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,aAAa2a,GAAqB;AAChC,SAAK,YAAY,OAAOA,KAAS,EAAE,GACnC,KAAK,cAAc,aAAa,KAAK,SAAS;AAAA,EAChD;AAAA,EAEA,aAAa0O,GAAoCC,GAA0C;AACzF,UAAMynC,IAAkBpM,GAAsBt7B,CAAO,GAC/C2nC,IAAkBrM,GAAsBr7B,CAAO;AACrD,QAAI,KAAK,oBAAoBynC,KAAmB,KAAK,oBAAoBC;AACvE;AAGF,SAAK,kBAAkBD,GACvB,KAAK,kBAAkBC,GACvB,KAAK,gBAAA,GACL,KAAK,mBAAA;AAEL,UAAMvW,IAAS,KAAK,uBAAuB,EAAE,GACvC58B,IAAU,KAAK,OAAO,aAAA;AAC5B,IAAIrD,GAAgBqD,GAAS48B,CAAM,KAGnC,KAAK,wBAAwBA,CAAM;AAAA,EACrC;AAAA,EAEA,kBAAkBj7C,GAA4D;AAC5E,SAAK,2BAA2BilD,GAAgCjlD,GAAS,QAAQ,GACjF,KAAK,uBAAuBolD,GAA0BplD,GAAS,MAAM;AAAA,EACvE;AAAA,EAEA,aAAaQ,GAA6BixD,GAA6C;AACrF,UAAMxW,IAAS,KAAK,uBAAuBz6C,CAAI,GACzC6d,IAAU,KAAK,OAAO,aAAA;AAC5B,QAAIrD,GAAgBqD,GAAS48B,CAAM,EAAG;AAEtC,UAAMkT,IAAalJ,GAAgCwM,GAAY,YAAY,KAAK,wBAAwB,GAClGpM,IAASD,GAA0BqM,GAAY,UAAU,KAAK,oBAAoB;AACxF,QAAItD,KAAc,GAAG;AACnB,WAAK,wBAAwBlT,CAAM;AACnC;AAAA,IACF;AAEA,SAAK,mBAAmBA,GAAQkT,GAAY9I,CAAM;AAAA,EACpD;AAAA,EAEA,eAA6B;AAC3B,WAAO,KAAK,OAAO,aAAA;AAAA,EACrB;AAAA,EAEA,eAAqD;AACnD,WAAO,EAAE,SAAS,KAAK,SAAS,SAAS,KAAK,QAAA;AAAA,EAChD;AAAA,EAEA,gCAAwC;AACtC,UAAMqM,IAAQ,KAAK,UAAU,OAAO,CAAA3sD,MAAKA,KAAK,KAAK,WAAWA,KAAK,KAAK,OAAO;AAC/E,WAAI2sD,EAAM,SAAS,IACVA,EAAMA,EAAM,SAAS,CAAC,IAExB,KAAK;AAAA,EACd;AAAA,EAEA,kBAA2B;AACzB,WAAO,KAAK,mBAAmB,cAAc;AAAA,EAC/C;AAAA,EAEA,mBAAmBtX,GAAuB;AACxC,SAAK,iBAAiBA,CAAO;AAAA,EAC/B;AAAA,EAEA,qBAAqBA,GAAuB;AAC1C,UAAMpB,IAAS,OAAOoB,KAAWwW,EAAsB,GACjDvE,IAAQ,KAAK,YAAY,IAAIrT,CAAM;AACzC,IAAKqT,MACL,KAAK,YAAY,OAAOrT,CAAM,GAC9B,KAAK,mBAAmBqT,EAAM,OAAO,GACrC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,gBAAgBjwC,GAAuCg+B,IAAkBwW,IAA8B;AACrG,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO;AAE3C,IADAiS,EAAM,UAAUsF,GAAuBtF,EAAM,SAAS,KAAK,IAAIA,EAAM,SAAS,KAAK,aAAajwC,CAAM,GAClG,GAACA,KAAUA,EAAO,WAAW,MAGjC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,iBAAiB49B,GAA6CI,IAAkBwW,IAA8B;AAC5G,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC55C,IAAO8jD,GAAuBtK,CAAM;AAC1C,IAAIqS,EAAM,cAAc,CAAC,MAAM7rD,EAAK,CAAC,KAAK6rD,EAAM,cAAc,CAAC,MAAM7rD,EAAK,CAAC,MAC3E6rD,EAAM,gBAAgB7rD,GACtB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,aAAauT,GAAyCqmC,IAAkBwW,IAA8B;AACpG,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO;AAC3C,IAAAiS,EAAM,UAAUuF,GAAoBvF,EAAM,SAAS,KAAK,IAAIA,EAAM,SAAS,KAAK,aAAat4C,CAAM,GACnG,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,mBAAmB89C,GAAuB;AACxC,UAAMrxD,IAAO,EAAQqxD;AACrB,IAAI,KAAK,sBAAsBrxD,MAC/B,KAAK,oBAAoBA,GACrBA,UAAW,WAAA;AAAA,EACjB;AAAA,EAEA,mBAAmB0iD,GAAqD9I,IAAkBwW,IAA8B;AACtH,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC0X,IAAY7O,GAAwBC,CAAe;AACzD,IAAIW,GAAuBwI,EAAM,oBAAoByF,CAAS,MAC9DzF,EAAM,qBAAqByF,GAC3B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,4BAA4BvO,GAAuEnJ,IAAkBwW,IAA8B;AACjJ,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC0X,IAAYxO,GAAqCC,CAAwB;AAC/E,IAAIO,GAAoCuI,EAAM,6BAA6ByF,CAAS,MACpFzF,EAAM,8BAA8ByF,GACpC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,8BAA8BnO,GAA2EvJ,IAAkBwW,IAA8B;AACvJ,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC0X,IAAYpO,GAAuCC,CAA0B;AACnF,IAAII,GAAsCsI,EAAM,+BAA+ByF,CAAS,MACxFzF,EAAM,gCAAgCyF,GACtC,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,gBAAgBjvB,GAAoCuX,IAAkBwW,IAA8B;AAClG,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC55C,IAAO6jD,GAAsBxhB,CAAO;AAC1C,IAAIwpB,EAAM,iBAAiB7rD,MAC3B6rD,EAAM,eAAe7rD,GACrB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,oBAAoBumC,GAAkCqT,IAAkBwW,IAA8B;AACpG,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC55C,IAAOojD,GAAqB7c,CAAK;AACvC,IAAIslB,EAAM,qBAAqB7rD,MAC/B6rD,EAAM,mBAAmB7rD,GACzB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,yBAAyBqiC,GAAoCuX,IAAkBwW,IAA8B;AAC3G,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC55C,IAAO+jD,GAA+B1hB,CAAO;AACnD,IAAIwpB,EAAM,0BAA0B7rD,MACpC6rD,EAAM,wBAAwB7rD,GAC9B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,uBAAuBuxD,GAAkC3X,IAAkBwW,IAA8B;AACvG,UAAMvE,IAAQ,KAAK,iBAAiBjS,CAAO,GACrC55C,IAAOgkD,GAA6BuN,CAAK;AAC/C,IAAI1F,EAAM,oBAAoB,CAAC,MAAM7rD,EAAK,CAAC,KAAK6rD,EAAM,oBAAoB,CAAC,MAAM7rD,EAAK,CAAC,KAAK6rD,EAAM,oBAAoB,CAAC,MAAM7rD,EAAK,CAAC,MAGnI6rD,EAAM,sBAAsB7rD,GAC5B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,sBAAsBokD,GAA0D;AAC9E,UAAMpkD,IAAOmkD,GAA+BC,CAAQ,GAC9C/sC,IAAO,KAAK;AAClB,IAAIA,EAAK,eAAerX,EAAK,cAAcqX,EAAK,aAAarX,EAAK,YAAYqX,EAAK,eAAerX,EAAK,eAGvG,KAAK,qBAAqBA,GAC1B,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,aAAmB;AACjBwxD,IAAAA,GAAgB,KAAK,QAAQ,KAAK,gBAAgB;AAAA,EACpD;AAAA,EAEA,cAAc1mB,GAAiBC,GAAmC;AAChE,UAAMhoC,IAAO,KAAK,OAAO,sBAAA,GACnB3B,IAAK0pC,IAAU/nC,EAAK,MACpB1B,IAAK0pC,IAAUhoC,EAAK;AAC1B,WAAO,KAAK,OAAO,cAAc3B,GAAIC,CAAE;AAAA,EACzC;AAAA,EAEA,cAAcT,GAAgBC,GAAkC;AAC9D,WAAO,KAAK,OAAO,cAAcD,GAAQC,CAAM;AAAA,EACjD;AAAA,EAEA,cAAcD,GAAgBC,GAAgBowD,GAA6C;AACzF,QAAI,CAAC,OAAO,SAASrwD,CAAM,KAAK,CAAC,OAAO,SAASC,CAAM,EAAG;AAC1D,UAAMowB,IAAQ,KAAK,OAAO,aAAA,GACpBhxB,IAAO,KAAK,IAAI,MAAMgxB,EAAM,IAAI,GAChC29B,IAAK,KAAK,OAAO,gBAAA;AACvB,SAAK;AAAA,MACH;AAAA,QACE,SAAShuD,IAASguD,EAAG,SAAS,IAAI3uD;AAAA,QAClC,SAASY,IAAS+tD,EAAG,UAAU,IAAI3uD;AAAA,MAAA;AAAA,MAErCgxD;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,iBAAmE;AACjE,WAAO,KAAK,OAAO,eAAA;AAAA,EACrB;AAAA,EAEA,wBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAAwB;AACtB,WAAOQ,GAAqB,KAAK,MAAM;AAAA,EACzC;AAAA,EAEA,cAAcR,GAA6C;AACzD,UAAMhgC,IAAQ,KAAK,OAAO,aAAA;AAC1B,IAAI,KAAK,IAAIA,EAAM,cAAc,KAAK,kBAAkB,IAAI,QAC5D,KAAK,aAAa,EAAE,aAAa,KAAK,mBAAA,GAAsBggC,CAAU;AAAA,EACxE;AAAA,EAEA,aAAarX,IAAkBwW,IAAgC;AAC7D,UAAMvE,IAAQ,KAAK,YAAY,IAAI,OAAOjS,KAAWwW,EAAsB,CAAC,GACtEsB,IAAqB7F,GAAO,+BAA+B,KAAK;AACtE,QAAI6F,KAAsBA,EAAmB,SAAS,GAAG;AACvD,YAAMzxD,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrDgjD,IAAgBjpC,GAAyB,KAAK,OAAO,OAAO,GAAG/Z,CAAI;AACzE,UAAIgjD,IAAgB,GAAG;AACrB,cAAMJ,IAAOc,GAAqCV,GAAeyO,CAAkB;AACnF,eAAOp4C,EAAMupC,GAAMtB,IAAmBC,EAAiB;AAAA,MACzD;AAAA,IACF;AAEA,UAAMvhD,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrDwwB,IAAiB,KAAK,OAAO,cAAc,KAAK,KAAKxwB,CAAI,GACzD63B,IAAQ+zB,GAAO,sBAAsB,KAAK,2BAC1ChJ,IAAOW,GAA4B/yB,GAAgBqH,CAAK;AAC9D,WAAOxe,EAAMupC,GAAMtB,IAAmBC,EAAiB;AAAA,EACzD;AAAA,EAEA,mBAAmB5H,IAAkBwW,IAAgC;AACnE,WAAO,KAAK,aAAaxW,CAAO;AAAA,EAClC;AAAA,EAEA,oBAAoBA,IAAkBwW,IAAgC;AACpE,UAAMvE,IAAQ,KAAK,YAAY,IAAI,OAAOjS,KAAWwW,EAAsB,CAAC,GACtEsB,IAAqB7F,GAAO,iCAAiC,KAAK;AACxE,QAAI6F,KAAsBA,EAAmB,SAAS,GAAG;AACvD,YAAMzxD,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrDgjD,IAAgBjpC,GAAyB,KAAK,OAAO,OAAO,GAAG/Z,CAAI;AACzE,UAAIgjD,IAAgB;AAClB,eAAOG,GAAqBQ,GAAuCX,GAAeyO,CAAkB,CAAC;AAAA,IAEzG;AACA,WAAO7F,GAAO,oBAAoB,KAAK;AAAA,EACzC;AAAA,EAEA,WAAWoF,GAA6C;AACtD,UAAMluD,IAAO,KAAK,OAAO,sBAAA,GACnB4uD,IAAK,KAAK,IAAI,GAAG5uD,EAAK,SAAS,CAAC,GAChC6uD,IAAK,KAAK,IAAI,GAAG7uD,EAAK,UAAU,CAAC,GACjC8uD,IAAYzD,GAAwB,KAAK,QAAQuD,GAAIC,GAAI,KAAK,SAAS,KAAK,SAAS,KAAK,kBAAkB;AAClH,SAAK,UAAUC,EAAU,SACzB,KAAK,gBAAA,GACL,KAAK,aAAaA,EAAU,QAAQZ,CAAU;AAAA,EAChD;AAAA,EAEA,OAAOlwB,GAAgB3gC,GAAiBC,GAAiB4wD,GAA6C;AACpG,UAAMxW,IAASiU,GAAoB,KAAK,QAAQ,KAAK,SAAS,KAAK,SAAS3tB,GAAQ3gC,GAASC,CAAO;AACpG,IAAKo6C,KACL,KAAK,aAAaA,GAAQwW,CAAU;AAAA,EACtC;AAAA,EAEA,gBAAgBhL,GAAgB7lD,GAAiBC,GAAuB;AACtE,QAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,MAAA6lD,GAAoBD,GAAQ7lD,GAASC,GAAS,KAAK,eAAe,CAACimD,GAAW1hD,GAAGD,MAAM,KAAK,eAAe2hD,GAAW1hD,GAAGD,CAAC,CAAC;AAC3H;AAAA,IACF;AACA,IAAAohD,GAAoBE,GAAQ7lD,GAASC,GAAS,CAAC0gC,GAAQn8B,GAAGD,MAAM,KAAK,OAAOo8B,GAAQn8B,GAAGD,CAAC,CAAC;AAAA,EAC3F;AAAA,EAEA,OAAO1E,GAAcG,GAAiBC,GAAiB4wD,GAA6C;AAClG,UAAMxW,IAASoU,GAAoB,KAAK,QAAQ,KAAK,SAAS,KAAK,SAAS5uD,GAAMG,GAASC,CAAO;AAClG,IAAKo6C,KACL,KAAK,aAAaA,GAAQwW,CAAU;AAAA,EACtC;AAAA,EAEA,aAAahC,GAA6CK,GAA0B;AAClF,SAAK,YAAYN,GAAmBC,GAAgB,KAAK,OAAO,GAAG,GACnE,KAAK,mBAAmB,EAAQK,GAChC,KAAK,mBAAA;AAAA,EACP;AAAA,EAEA,aAAah6B,GAAoE;AAC/E,SAAK,eAAeA,CAAM;AAAA,EAC5B;AAAA,EAEQ,eAAeA,GAAoE;AACzF,IAAI,OAAOA,KAAW,YAAY,OAAO,SAASA,CAAM,KACtD,KAAK,aAAa,KAAK,IAAI,GAAGA,CAAM,GACpC,KAAK,aAAa,KAAK,IAAI,GAAGA,CAAM,KAC3BA,KAAU,QAAQ,OAAOA,KAAW,YAC7C,KAAK,aAAa,OAAOA,EAAO,KAAM,YAAY,OAAO,SAASA,EAAO,CAAC,IAAI,KAAK,IAAI,GAAGA,EAAO,CAAC,IAAI,KACtG,KAAK,aAAa,OAAOA,EAAO,KAAM,YAAY,OAAO,SAASA,EAAO,CAAC,IAAI,KAAK,IAAI,GAAGA,EAAO,CAAC,IAAI,QAEtG,KAAK,aAAa,KAClB,KAAK,aAAa;AAAA,EAEtB;AAAA,EAEQ,+BAA0D;AAChE,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,oBAAoB,KAAK;AAAA,MACzB,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,qBAAqB,MAAM,KAAK,oBAAA;AAAA,MAChC,gBAAgB,MAAMo7B,GAAsB,KAAK,QAAQ,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AAAA,MACtG,mBAAmB,CAAAz/B,MAAS,KAAK,oBAAoBA,CAAK;AAAA,MAC1D,eAAe,MAAM,KAAK,cAAA;AAAA,IAAc;AAAA,EAE5C;AAAA,EAEQ,eAAeq1B,GAAyBlmD,GAAiBC,GAA0B;AACzF,UAAMyxD,IAAU,KAAK,mBAAmB,WAClCC,IAAWD,IAAUA,EAAQ,GAAG,OAAO,KAAK,OAAO,eAAe,MAClEzC,IAAa,KAAK,UAAU,OAAO,CAAA9qD,MAAKA,KAAK,KAAK,WAAWA,KAAK,KAAK,OAAO,GAC9EyZ,IAASoxC,GAAkBC,GAAY0C,GAAUzL,GAAW,KAAK,gBAAgB;AACvF,QAAI,CAACtoC,EAAQ,QAAO;AAEpB,QAAI8wC;AAEJ,QAAI9wC,EAAO,SAAS,OAAO;AACzB,YAAMjb,IAAO,KAAK,OAAO,sBAAA,GACnB4uD,IAAK,KAAK,IAAI,GAAG5uD,EAAK,SAAS,CAAC,GAChC6uD,IAAK,KAAK,IAAI,GAAG7uD,EAAK,UAAU,CAAC,GACjC8uD,IAAYzD,GAAwB,KAAK,QAAQuD,GAAIC,GAAI,KAAK,SAAS,KAAK,SAAS,KAAK,kBAAkB;AAClH,WAAK,UAAUC,EAAU,SACzB,KAAK,gBAAA,GACL/C,IAAa+C,EAAU,OAAO;AAAA,IAChC;AACE,MAAA/C,IAAa9wC,EAAO;AAGtB,UAAMlZ,IAAU,KAAK,IAAI,KAAK,IAAIgqD,CAAU,IAAI,MAAO,IAAI;AAE3D,QAAIgD;AAEF,WAD8CA,EAAQ,GAAG,OAAOA,EAAQ,KAAK,OAAOhtD,IAAU,OAAOgtD,EAAQ,GAAG,OAAOA,EAAQ,KAAK,OAAOhtD,IAAU,QAAQ,UACpIwhD,KAAa,KAAK,IAAIwL,EAAQ,GAAG,OAAOhD,CAAU,KAAKhqD;AAC9E,eAAO;AAAA,eAEA,KAAK,IAAIitD,IAAWjD,CAAU,KAAKhqD;AAC5C,aAAO;AAGT,WAAA0qD,GAAwB,KAAK,6BAAA,GAAgCV,GAAY1uD,GAASC,GAAS0uD,EAAqB,GACzG;AAAA,EACT;AAAA,EAEA,SAAe;AACb,QAAI,KAAK,aAAa,KAAK,eAAe,KAAK,GAAG,gBAAiB;AACnE,UAAMiD,IAAe,KAAK,UAAU53C,GAAA,IAAU;AAC9C,SAAK,eAAe;AAEpB,UAAM4D,IAAS+sC,GAAY;AAAA,MACzB,IAAI,KAAK;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,oBAAoB,KAAK;AAAA,MACzB,aAAa,KAAK,qBAAA;AAAA,MAClB,eAAe,KAAK;AAAA,MACpB,iBAAiB,MAAMkH,GAAuB,KAAK,QAAQ,KAAK,MAAM;AAAA,MACtE,wBAAwB,CAAAzsB,MAAQ0sB,GAA8B,KAAK,QAAQ,KAAK,QAAQ1sB,CAAI;AAAA,MAC5F,eAAe,MAAMisB,GAAqB,KAAK,MAAM;AAAA,MACrD,kBAAkBU;AAAAA,IAAA,CACnB;AACD,QAAI,KAAK,SAAS;AAChB,YAAMC,IAAiB,KAAK,cAAc,YAAA;AAC1C,WAAK,QAAQ;AAAA,QACX,MAAMp0C,EAAO;AAAA,QACb,SAASA,EAAO;AAAA,QAChB,UAAUA,EAAO;AAAA,QACjB,QAAQA,EAAO;AAAA,QACf,UAAUA,EAAO;AAAA,QACjB,OAAO,KAAK,MAAM;AAAA,QAClB,UAAUo0C,EAAe;AAAA,QACzB,QAAQA,EAAe;AAAA,QACvB,SAASA,EAAe;AAAA,QACxB,QAAQA,EAAe;AAAA,QACvB,SAASA,EAAe;AAAA,QACxB,WAAWp0C,EAAO;AAAA,QAClB,aAAaA,EAAO;AAAA,QACpB,WAAWA,EAAO;AAAA,QAClB,SAAS5D,OAAU43C;AAAA,MAAA,CACpB;AAAA,IACH;AAAA,EACF;AAAA,EAEA,gBAAsB;AACpB,IAAI,KAAK,UAAU,QAAQ,KAAK,aAAa,KAAK,eAAe,KAAK,GAAG,cAAA,MACzE,KAAK,QAAQ,sBAAsB,MAAM;AACvC,WAAK,QAAQ,MACb,KAAK,OAAA;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEA,SAAe;AACb,IAAA5Q,GAAqB,KAAK,QAAQ,KAAK,IAAI,KAAK,MAAM,GACtD,KAAK,cAAA;AAAA,EACP;AAAA,EAEQ,mBAAmBxuC,GAAoB;AAC7C,UAAMoL,IAASyrC,GAAkB;AAAA,MAC/B,OAAA72C;AAAA,MACA,WAAW,KAAK;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,qBAAqB,MAAM,KAAK,oBAAA;AAAA,MAChC,YAAY,MAAM,KAAK,WAAA;AAAA,MACvB,eAAe,KAAK;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ,eAAe,KAAK;AAAA,IAAA,CACrB;AACD,QAAKoL,EAAO,SACZ;AAAA,WAAK,QAAQA,EAAO,OACpB,KAAK,cAAc;AACnB,iBAAW6tC,KAAS,KAAK,YAAY,OAAA;AACnC,QAAAA,EAAM,UAAU;AAAA,UACd,GAAGA,EAAM;AAAA,UACT,mBAAmB;AAAA,QAAA;AAAA;AAAA,EAGzB;AAAA,EAEQ,uBAAuBwG,GAAqB;AAClD,QAAI,MAAK,WACT;AAAA,WAAK,cAAc,IACnB,KAAK,MAAM,MAAA,GAEX,KAAK,cAAcvG,GAAgB,KAAK,EAAE;AAC1C,iBAAWD,KAAS,KAAK,YAAY,OAAA;AACnC,QAAAA,EAAM,UAAUW,GAAiB,KAAK,EAAE,GACxCX,EAAM,UAAU;AAAA,UACd,GAAGA,EAAM;AAAA,UACT,mBAAmB;AAAA,QAAA,GAEjBA,EAAM,QAAQ,oBAAoBA,EAAM,QAAQ,iBAAiB,SAAS,MAC5EA,EAAM,UAAUsF,GAAuBtF,EAAM,SAAS,KAAK,IAAIA,EAAM,SAAS,KAAK,aAAaA,EAAM,QAAQ,gBAAgB,IAE5HA,EAAM,QAAQ,kBAChBA,EAAM,UAAUuF,GAAoBvF,EAAM,SAAS,KAAK,IAAIA,EAAM,SAAS,KAAK,aAAaA,EAAM,QAAQ,aAAa;AAI5H,WAAK,OAAA,GACL,KAAK,oBAAA;AAAA;AAAA,EACP;AAAA,EAEA,UAAgB;AACd,UAAM7tC,IAAS4rC,GAAgB;AAAA,MAC7B,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ,qBAAqB,MAAM,KAAK,oBAAA;AAAA,MAChC,gBAAgB,KAAK;AAAA,MACrB,mBAAmB,KAAK;AAAA,MACxB,4BAA4B,MAAMzI,GAAmC,KAAK,QAAQ,KAAK,mBAAmB;AAAA,MAC1G,YAAY,MAAM,KAAK,WAAA;AAAA,MACvB,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK;AAAA,MAClB,IAAI,KAAK;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,eAAe,MAAM,KAAK,KAAK,YAAY,UAAU,CAAA0K,MAASA,EAAM,OAAO;AAAA,IAAA,CAC5E;AACD,IAAK7tC,EAAO,eACZ,KAAK,YAAY,IACjB,KAAK,QAAQA,EAAO;AAAA,EACtB;AACF;ACv1BA,MAAMs0C,KAA4C,CAAA;AAElD,SAAShrB,GAAiBvwB,GAAmC;AAC3D,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK,IAAIA,IAAQ;AACvE;AAEO,SAASw7C,GAAU;AAAA,EACxB,QAAA7zD;AAAA,EACA,WAAA+D;AAAA,EACA,mBAAA+vD;AAAA,EACA,SAAA/uB;AAAA,EACA,aAAAgvB;AAAA,EACA,eAAA9I;AAAA,EACA,mBAAA+I;AAAA,EACA,oBAAAzH,IAAqB;AAAA,EACrB,eAAA0H,IAAgB;AAAA,EAChB,UAAAC,IAAW;AAAA,EACX,oBAAAC,IAAqB;AAAA,EACrB,WAAAjtB,IAAY;AAAA,EACZ,gBAAAktB,IAAiB;AAAA,EACjB,SAAAzpC;AAAA,EACA,SAAAC;AAAA,EACA,gBAAAypC;AAAA,EACA,WAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,WAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,cAAAznC,IAAe;AAAA,EACf,mBAAA0nC;AAAA,EACA,WAAAxkC;AAAA,EACA,OAAAnK;AAAA,EACA,UAAA4uC;AACF,GAAuC;AACrC,QAAMvW,IAAehuB,EAA8B,IAAI,GACjDD,IAAYC,EAAiC,IAAI,GACjDwkC,IAAmBxkC,EAAiC,IAAI,GACxDuF,IAAcvF,EAA+B,IAAI,GACjDirB,IAAoBjrB,EAA4B,IAAI,GACpDykC,IAAwBzkC,EAA4B,IAAI,GACxD0kC,IAAmB1kC,EAA4BujC,EAAoB,GACnEoB,KAAoB3kC,EAAO,EAAK,GAChC4kC,KAAsB5kC,EAAoB,oBAAI,KAAK,GACnD6kC,KAAwB7kC,EAA2C,oBAAI,KAAK,GAE5E8kC,KAAuB9kC,EAAOyjC,CAAiB,GAC/CsB,KAAa/kC,EAAO0U,CAAO,GAC3BswB,IAAiBhlC,EAAO0jC,CAAW,GACnCuB,IAAmBjlC,EAAO46B,CAAa,GACvCsK,IAAuBllC,EAAO2jC,CAAiB,GAE/C,CAACn+B,IAAgB2/B,EAAiB,IAAIlhB,GAAS,CAAC,GAChD,CAACmhB,GAAYC,EAAa,IAAIphB,GAAgC,IAAI,GAClEqhB,KAAkBtlC,EAAOpD,CAAY;AAE3C,EAAA6H,EAAU,MAAM;AACd,IAAAqgC,GAAqB,UAAUrB;AAAA,EACjC,GAAG,CAACA,CAAiB,CAAC,GACtBh/B,EAAU,MAAM;AACd,IAAAsgC,GAAW,UAAUrwB;AAAA,EACvB,GAAG,CAACA,CAAO,CAAC,GACZjQ,EAAU,MAAM;AACd,IAAAugC,EAAe,UAAUtB;AAAA,EAC3B,GAAG,CAACA,CAAW,CAAC,GAChBj/B,EAAU,MAAM;AACd,IAAAwgC,EAAiB,UAAUrK;AAAA,EAC7B,GAAG,CAACA,CAAa,CAAC,GAClBn2B,EAAU,MAAM;AACd,IAAAygC,EAAqB,UAAUvB;AAAA,EACjC,GAAG,CAACA,CAAiB,CAAC,GACtBl/B,EAAU,MAAM;AACd,IAAA6gC,GAAgB,UAAU1oC,GACrBA,KAAcyoC,GAAc,IAAI;AAAA,EACvC,GAAG,CAACzoC,CAAY,CAAC;AAEjB,QAAMsE,KAAcZ,GAAuB,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,GAAG3K,EAAA,IAAU,CAACA,CAAK,CAAC,GAEvH4vC,KAA0BjlC;AAAA,IAC9B,OAAO;AAAA,MACL,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,GAAGgkC;AAAA,IAAA;AAAA,IAEL,CAACA,CAAiB;AAAA,EAAA,GAGdkB,KAAqBjtB,GAAiBqrB,CAAa,GAEnD6B,KAAsBrkC;AAAA,IAC1B,CAACc,OAAuC;AAAA,MACtC,GAAGA;AAAA,MACH,aAAaA,EAAM,cAAcsjC;AAAA,IAAA;AAAA,IAEnC,CAACA,EAAkB;AAAA,EAAA,GAGfE,KAAsBtkC;AAAA,IAC1B,CAACc,MACK,OAAOA,EAAM,eAAgB,YAAY,CAAC,OAAO,SAASA,EAAM,WAAW,IACtEA,IAEF;AAAA,MACL,GAAGA;AAAA,MACH,aAAaA,EAAM,cAAcsjC;AAAA,IAAA;AAAA,IAGrC,CAACA,EAAkB;AAAA,EAAA,GAGfG,KAAsBvkC,EAAY,CAAC6T,MAAgC;AACvE,IAAA8vB,GAAW,UAAU9vB,CAAK,GACtBqwB,GAAgB,WAASD,GAAcpwB,CAAK;AAAA,EAClD,GAAG,CAAA,CAAE,GAEC2wB,KAAmBtlC,GAAQ,MAC1B8kC,IACE;AAAA,IACL,QAAQA,EAAW,IAAI,YAAYA,EAAW,SAAS,QAAQ,CAAC,KAAK,GAAG,mBAAmBA,EAAW,aAAa,GAAG;AAAA,IACtH,iBAAiBA,EAAW,OAAO,eAAeA,EAAW,QAAQ,eAAeA,EAAW,QAAQ;AAAA,IACvG,cAAcA,EAAW,KAAK,UAAUA,EAAW,aAAa,GAAG,WAAWA,EAAW,eAAe,GAAG;AAAA,IAC3G,kBAAkBA,EAAW,QAAQ,aAAaA,EAAW,UAAU,GAAG,cAAcA,EAAW,WAAW,GAAG,aAAaA,EAAW,UAAU,GAAG,cAAcA,EAAW,WAAW,GAAG;AAAA,IAC7L,UAAUA,EAAW,MAAM;AAAA,EAAA,EAC3B,KAAK;AAAA,CAAI,IAPa,qCAQvB,CAACA,CAAU,CAAC,GAITS,KAAmBzkC,EAAY,MAAM;AACzC,UAAM5wB,IAASg0D,EAAiB;AAChC,QAAI,CAACh0D,EAAQ;AACb,UAAM4kB,IAAM5kB,EAAO,WAAW,IAAI;AAClC,QAAI,CAAC4kB,EAAK;AAEV,UAAMjhB,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9CH,KAAOxD,EAAO,sBAAA,GACdyB,KAAI,KAAK,IAAI,GAAG,KAAK,MAAM+B,GAAK,QAAQG,CAAG,CAAC,GAC5CjC,KAAI,KAAK,IAAI,GAAG,KAAK,MAAM8B,GAAK,SAASG,CAAG,CAAC;AACnD,KAAI3D,EAAO,UAAUyB,MAAKzB,EAAO,WAAW0B,QAC1C1B,EAAO,QAAQyB,IACfzB,EAAO,SAAS0B;AAGlB,UAAMwgC,KAAe1+B,GAAK,OACpB2+B,IAAgB3+B,GAAK;AAC3B,IAAAohB,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAG5kB,EAAO,OAAOA,EAAO,MAAM,GAC/C4kB,EAAI,aAAajhB,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC;AAErC,UAAM2xD,IAAUpB,EAAiB;AACjC,aAASxvD,IAAI,GAAGA,IAAI4wD,EAAQ,QAAQ5wD,KAAK;AACvC,MAAAkgB,EAAI,KAAA,GACJ0wC,EAAQ5wD,CAAC,EAAE,KAAKkgB,GAAKsd,IAAcC,CAAa,GAChDvd,EAAI,QAAA;AAAA,EAER,GAAG,CAAA,CAAE,GAECyf,KAAuBzT,EAAY,MAAM;AAC7C,IAAIujC,GAAkB,YACtBA,GAAkB,UAAU,IAC5B,sBAAsB,MAAM;AAC1B,MAAAA,GAAkB,UAAU,IAC5BkB,GAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACA,EAAgB,CAAC,GAEflxB,KAAuBvT;AAAA,IAC3B,CAACihB,GAAY0jB,GAAkB7qB,MAAwB;AACrD,YAAM4qB,KAAUpB,EAAiB,QAAQ,OAAO,CAAA7vD,OAAKA,GAAE,OAAOwtC,CAAE;AAChE,MAAAyjB,GAAQ,KAAK,EAAE,IAAAzjB,GAAI,UAAA0jB,GAAU,MAAA7qB,GAAM,GACnC4qB,GAAQ,KAAK,CAACnwD,IAAGwE,OAAMxE,GAAE,WAAWwE,GAAE,QAAQ,GAC9CuqD,EAAiB,UAAUoB,IAC3BjxB,GAAA;AAAA,IACF;AAAA,IACA,CAACA,EAAoB;AAAA,EAAA,GAGjBD,KAAyBxT;AAAA,IAC7B,CAACihB,MAAe;AACd,MAAAqiB,EAAiB,UAAUA,EAAiB,QAAQ,OAAO,CAAA7vD,MAAKA,EAAE,OAAOwtC,CAAE,GAC3ExN,GAAA;AAAA,IACF;AAAA,IACA,CAACA,EAAoB;AAAA,EAAA,GAGjBpP,IAAqBrE,EAAY,CAACihB,GAAYigB,MAAoB;AACtE,IAAIA,IACFsC,GAAoB,QAAQ,IAAIviB,CAAE,IAElCuiB,GAAoB,QAAQ,OAAOviB,CAAE,GAEvC9c,EAAY,SAAS,mBAAmBq/B,GAAoB,QAAQ,OAAO,CAAC;AAAA,EAC9E,GAAG,CAAA,CAAE,GAECxW,IAAsBhtB,EAAY,MAAMwjC,GAAoB,QAAQ,OAAO,GAAG,EAAE,GAIhFzW,KAAgB/sB,EAAY,CAACvvB,GAAgBC,MAA0C;AAC3F,UAAMugC,IAAW9M,EAAY;AAC7B,WAAK8M,IACEtd,GAAiBsd,EAAS,cAAcxgC,GAAQC,CAAM,CAAC,IADxC;AAAA,EAExB,GAAG,CAAA,CAAE,GAECo8C,KAAgB9sB,EAAY,CAAC2a,GAAiBC,MAA2C;AAC7F,UAAM3J,IAAW9M,EAAY;AAC7B,QAAI,CAAC8M,EAAU,QAAO;AACtB,UAAM9gB,KAAM8gB,EAAS,cAAc0J,GAASC,CAAO;AACnD,QAAI,CAAC,MAAM,QAAQzqB,EAAG,KAAKA,GAAI,SAAS,EAAG,QAAO;AAClD,UAAM1b,KAAI,OAAO0b,GAAI,CAAC,CAAC,GACjB3b,KAAI,OAAO2b,GAAI,CAAC,CAAC;AACvB,WAAI,CAAC,OAAO,SAAS1b,EAAC,KAAK,CAAC,OAAO,SAASD,EAAC,IAAU,OAChD,CAACC,IAAGD,EAAC;AAAA,EACd,GAAG,CAAA,CAAE,GAECq4C,IAA4B7sB,EAAY,CAAC4kC,OAC7CnB,GAAsB,QAAQ,IAAImB,CAAQ,GACnC,MAAM;AACX,IAAAnB,GAAsB,QAAQ,OAAOmB,CAAQ;AAAA,EAC/C,IACC,CAAA,CAAE,GAICC,KAAsB7kC;AAAA,IAC1B,CAAC8kC,MAAqC;AACpC,MAAApB,GAAqB,UAAUW,GAAoBS,CAAY,CAAC;AAChE,YAAMC,IAAYtB,GAAsB;AACxC,UAAIsB,EAAU,OAAO,GAAG;AACtB,cAAMC,IAAW,MAAM,KAAKD,CAAS;AACrC,iBAASjxD,KAAI,GAAGA,KAAIkxD,EAAS,QAAQlxD,MAAK;AACxC,UAAAkxD,EAASlxD,EAAC,EAAEgxD,CAAY;AAAA,MAE5B;AACA,MAAAjb,EAAkB,UAAA,GAClBwZ,EAAsB,UAAA,GACtB5vB,GAAA;AAAA,IACF;AAAA,IACA,CAACA,IAAsB4wB,EAAmB;AAAA,EAAA;AAK5C,EAAAhhC,EAAU,MAAM;AACd,UAAMj0B,IAASuvB,EAAU;AACzB,QAAI,CAACvvB,KAAU,CAACb,EAAQ;AAExB,UAAM0iC,IAAW,IAAIivB,GAAgB9wD,GAAQb,GAAQ;AAAA,MACnD,mBAAmBs2D;AAAA,MACnB,SAASN;AAAA,MACT,aAAa,CAAA9hD,MAAS;AACpB,QAAAmhD,EAAe,UAAUnhD,CAAK;AAAA,MAChC;AAAA,MACA,eAAe,MAAM;AACnB,QAAAohD,EAAiB,UAAA;AAAA,MACnB;AAAA,MACA,mBAAmB,MAAM;AACvB,QAAAC,EAAqB,UAAA;AAAA,MACvB;AAAA,MACA,WAAAruB;AAAA,MACA,oBAAAqlB;AAAA,MACA,oBAAoB0H;AAAA,MACpB,gBAAAG;AAAA,MACA,SAAAzpC;AAAA,MACA,SAAAC;AAAA,MACA,gBAAAypC;AAAA,MACA,WAAAC;AAAA,MACA,kBAAAC;AAAA,MACA,WAAAC;AAAA,MACA,uBAAAC;AAAA,IAAA,CACD;AAED,WAAA7+B,EAAY,UAAU8M,GACtB8yB,GAAkB,CAAA/vD,MAAKA,IAAI,CAAC,GACxB1B,KAAW2+B,EAAS,aAAaqzB,GAAoBhyD,CAAS,CAAC,GACnE2+B,EAAS,mBAAmBuyB,GAAoB,QAAQ,OAAO,CAAC,GAEzD,MAAM;AACX,MAAAvyB,EAAS,QAAA,GACT9M,EAAY,UAAU;AAAA,IACxB;AAAA,EACF,GAAG,CAAC51B,GAAQg2D,IAAqB5B,GAAgBkC,IAAqBT,IAAoBE,EAAmB,CAAC,GAI9GjhC,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,aAAasR,CAAS;AAAA,EAC7C,GAAG,CAACA,CAAS,CAAC,GAEdpS,EAAU,MAAM;AACd,UAAM4N,IAAW9M,EAAY;AAC7B,IAAI,CAAC8M,KAAY,CAAC3+B,KACd2+B,EAAS,qBACbA,EAAS,aAAaqzB,GAAoBhyD,CAAS,CAAC;AAAA,EACtD,GAAG,CAACA,GAAWgyD,EAAmB,CAAC,GAEnCjhC,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,WAAA;AAAA,EACvB,GAAG,CAACs+B,CAAQ,CAAC,GACbp/B,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,cAAA;AAAA,EACvB,GAAG,CAACu+B,CAAkB,CAAC,GAEvBr/B,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,aAAajL,GAASC,CAAO;AAAA,EACpD,GAAG,CAACD,GAASC,CAAO,CAAC,GACrBkK,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,kBAAkBy+B,CAAc;AAAA,EACvD,GAAG,CAACA,CAAc,CAAC,GACnBv/B,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,aAAa0+B,GAAWC,CAAgB;AAAA,EAC/D,GAAG,CAACD,GAAWC,CAAgB,CAAC,GAChCz/B,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,aAAa4+B,CAAS;AAAA,EAC7C,GAAG,CAACA,CAAS,CAAC,GACd1/B,EAAU,MAAM;AACd,IAAAc,EAAY,SAAS,sBAAsB22B,CAAkB;AAAA,EAC/D,GAAG,CAACA,CAAkB,CAAC,GAIvBz3B,EAAU,MAAM;AACd,UAAMj0B,IAASg0D,EAAiB;AAChC,QAAI,CAACh0D,EAAQ;AACb,IAAAy6C,EAAkB,UAAUpW,IAC5BA,GAAA;AAEA,UAAMnQ,IAAW,IAAI,eAAe,MAAMmQ,IAAsB;AAChE,WAAAnQ,EAAS,QAAQl0B,CAAM,GAChB,MAAM;AACX,MAAAk0B,EAAS,WAAA,GACLumB,EAAkB,YAAYpW,OAChCoW,EAAkB,UAAU;AAAA,IAEhC;AAAA,EACF,GAAG,CAACpW,EAAoB,CAAC,GAEzBpQ,EAAU,MAAMjT,GAA+B,MAAMqjB,GAAA,CAAsB,GAAG,CAACA,EAAoB,CAAC;AAIpG,QAAMwxB,IAAe/lC;AAAA,IACnB,OAAO;AAAA,MACL,QAAA3wB;AAAA,MACA,aAAA41B;AAAA,MACA,gBAAAC;AAAA,MACA,WAAAzF;AAAA,MACA,cAAAiuB;AAAA,MACA,mBAAA/C;AAAA,MACA,uBAAAwZ;AAAA,MACA,eAAAtW;AAAA,MACA,eAAAD;AAAA,MACA,sBAAAvZ;AAAA,MACA,wBAAAC;AAAA,MACA,sBAAAC;AAAA,MACA,2BAAAoZ;AAAA,MACA,oBAAAxoB;AAAA,MACA,qBAAA2oB;AAAA,IAAA;AAAA,IAEF,CAACz+C,GAAQ61B,IAAgB2oB,IAAeD,IAAevZ,IAAsBC,IAAwBC,IAAsBoZ,GAA2BxoB,GAAoB2oB,CAAmB;AAAA,EAAA,GAGzLkY,KAAwBtmC,EAAOqkC,CAAkB;AACvD,EAAA5/B,EAAU,MAAM;AACd,IAAA6hC,GAAsB,UAAUjC;AAAA,EAClC,GAAG,CAACA,CAAkB,CAAC;AAEvB,QAAMlgC,KAAoB/C;AAAA,IACxB,CAACvsB,MAA0C;AACzC,YAAM0xD,IAAKD,GAAsB;AACjC,UAAI,CAACC,EAAI;AACT,YAAM/rD,IAAQ0zC,GAAcr5C,EAAE,SAASA,EAAE,OAAO,GAC1C2xD,KAAc,CAAC,CAAChsD,KAASA,EAAM,CAAC,KAAK,KAAKA,EAAM,CAAC,KAAK,KAAK,CAAC,CAAC7K,KAAU6K,EAAM,CAAC,KAAK7K,EAAO,SAAS6K,EAAM,CAAC,KAAK7K,EAAO;AAC5H,MAAA42D,EAAG,EAAE,YAAY/rD,GAAO,SAAS3F,EAAE,SAAS,SAASA,EAAE,SAAS,aAAA2xD,GAAA,CAAa;AAAA,IAC/E;AAAA,IACA,CAACtY,IAAev+C,CAAM;AAAA,EAAA,GAGlB40B,KAAqBnD,EAAY,MAAM;AAC3C,IAAAklC,GAAsB,UAAU,EAAE,YAAY,MAAM,SAAS,IAAI,SAAS,IAAI,aAAa,GAAA,CAAO;AAAA,EACpG,GAAG,CAAA,CAAE;AAEL,SACE,gBAAA1hC,GAACK,IAAA,EAAsB,OAAOohC,GAC5B,UAAA,gBAAAxoB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKmQ;AAAA,MACL,WAAAluB;AAAA,MACA,OAAOoB;AAAA,MACP,eAAemjC,IAAqBlgC,KAAoB;AAAA,MACxD,gBAAgBkgC,IAAqB9/B,KAAqB;AAAA,MAE1D,UAAA;AAAA,QAAA,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK7E;AAAA,YACL,WAAU;AAAA,YACV,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,aAAa;AAAA,YAAA;AAAA,UACf;AAAA,QAAA;AAAA,QAEF,gBAAA6E;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK4/B;AAAA,YACL,WAAU;AAAA,YACV,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,SAAS;AAAA,cACT,eAAe;AAAA,cACf,aAAa;AAAA,YAAA;AAAA,UACf;AAAA,QAAA;AAAA,QAEDD;AAAA,QACA3nC,KACC,gBAAAgI,GAAC,OAAA,EAAI,iCAA6B,IAAC,OAAO2gC,IACvC,UAAAK,GAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAGN;AAEJ;AChcA,SAASa,GAAezoB,GAAiD;AACvE,QAAMr0B,IAA6B,CAAA;AACnC,WAASzU,IAAI,GAAGA,IAAI8oC,EAAQ,QAAQ9oC,KAAK,GAAG;AAC1C,UAAMurB,IAASud,EAAQ9oC,CAAC,GAClBmV,IAAWZ,GAAmB,CAAC/B,GAAc+Y,GAAQ,WAAW,CAAC,CAAC;AACxE,QAAIpW,EAAS,WAAW,EAAG;AAE3B,QAAItB,IAAO,GACPe,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW/B,KAAWmC;AACpB,MAAAtB,KAAQb,EAAQ,MACZA,EAAQ,OAAO4B,MAAMA,IAAO5B,EAAQ,OACpCA,EAAQ,OAAO6B,MAAMA,IAAO7B,EAAQ,OACpCA,EAAQ,OAAO8B,MAAMA,IAAO9B,EAAQ,OACpCA,EAAQ,OAAO+B,MAAMA,IAAO/B,EAAQ;AAE1C,IAAI,CAAC,OAAO,SAAS4B,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAEvGN,EAAS,KAAK;AAAA,MACZ,UAAU8W,EAAO,MAAMvrB;AAAA,MACvB,aAAaA;AAAA,MACb,UAAAmV;AAAA,MACA,MAAM,KAAK,IAAI,MAAMtB,CAAI;AAAA,MACzB,MAAAe;AAAA,MACA,MAAAC;AAAA,MACA,MAAAC;AAAA,MACA,MAAAC;AAAA,IAAA,CACD;AAAA,EACH;AACA,SAAON;AACT;AAaA,MAAM+8C,KAAuB,KACvBC,KAA2C,CAAA;AAEjD,SAASC,GAAW5+C,GAAewC,GAAaC,GAAa6lB,GAAkBu2B,GAA0B;AACvG,MAAIA,KAAY,KAAKp8C,KAAOD,EAAK,QAAO;AACxC,QAAMoc,KAAS5e,IAAQwC,KAAO8lB;AAC9B,SAAI,CAAC,OAAO,SAAS1J,CAAK,KAAKA,KAAS,IAAU,IAC9CA,KAASigC,IAAW,IAAUA,IAAW,IACtC,KAAK,MAAMjgC,CAAK;AACzB;AAEA,SAASkgC,GAA6B9oB,GAAoE;AACxG,MAAIA,EAAQ,WAAW,EAAG,QAAO;AAEjC,MAAIl0B,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAWwW,KAAUud;AACnB,IAAIvd,EAAO,OAAO3W,MAAMA,IAAO2W,EAAO,OAClCA,EAAO,OAAO1W,MAAMA,IAAO0W,EAAO,OAClCA,EAAO,OAAOzW,MAAMA,IAAOyW,EAAO,OAClCA,EAAO,OAAOxW,MAAMA,IAAOwW,EAAO;AAExC,MAAI,CAAC,OAAO,SAAS3W,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI;AACrG,WAAO;AAGT,QAAM88C,IAAY,KAAK,KAAK,KAAK,KAAK/oB,EAAQ,SAAS,CAAC,CAAC,GACnD6oB,IAAW,KAAK,IAAI,GAAG,KAAK,IAAIH,IAAsBK,CAAS,CAAC,GAChEC,IAAYh9C,IAAOF,KAAQE,IAAOF,KAAQ+8C,IAAW,GACrDI,IAAah9C,IAAOF,KAAQE,IAAOF,KAAQ88C,IAAW,GACtDK,IAAU,MAAM,KAAK,EAAE,QAAQL,IAAWA,KAAY,MAAM,EAAc;AAEhF,WAASM,IAAmB,GAAGA,IAAmBnpB,EAAQ,QAAQmpB,KAAoB,GAAG;AACvF,UAAM1mC,IAASud,EAAQmpB,CAAgB,GACjChhC,IAAWygC,GAAWnmC,EAAO,MAAM3W,GAAME,GAAMg9C,GAAWH,CAAQ,GAClEzgC,IAAWwgC,GAAWnmC,EAAO,MAAM3W,GAAME,GAAMg9C,GAAWH,CAAQ,GAClExgC,IAAWugC,GAAWnmC,EAAO,MAAM1W,GAAME,GAAMg9C,GAAYJ,CAAQ,GACnEvgC,IAAWsgC,GAAWnmC,EAAO,MAAM1W,GAAME,GAAMg9C,GAAYJ,CAAQ;AACzE,aAASjiB,IAAQve,GAAUue,KAASte,GAAUse,KAAS;AACrD,eAASD,IAAQxe,GAAUwe,KAASve,GAAUue,KAAS;AACrD,QAAAuiB,EAAQtiB,IAAQiiB,IAAWliB,CAAK,EAAE,KAAKwiB,CAAgB;AAAA,EAG7D;AAEA,SAAO;AAAA,IACL,MAAAr9C;AAAA,IACA,MAAAC;AAAA,IACA,MAAAC;AAAA,IACA,MAAAC;AAAA,IACA,UAAA48C;AAAA,IACA,WAAAG;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC;AAAA,EAAA;AAEJ;AAEA,SAASE,GAA0B9lD,GAAuCzL,GAAWD,GAA8B;AAEjH,MADI,CAAC0L,KACDzL,IAAIyL,EAAM,QAAQzL,IAAIyL,EAAM,QAAQ1L,IAAI0L,EAAM,QAAQ1L,IAAI0L,EAAM;AAClE,WAAOqlD;AAET,QAAMhiB,IAAQiiB,GAAW/wD,GAAGyL,EAAM,MAAMA,EAAM,MAAMA,EAAM,WAAWA,EAAM,QAAQ,GAC7EsjC,IAAQgiB,GAAWhxD,GAAG0L,EAAM,MAAMA,EAAM,MAAMA,EAAM,YAAYA,EAAM,QAAQ;AACpF,SAAOA,EAAM,QAAQsjC,IAAQtjC,EAAM,WAAWqjC,CAAK,KAAKgiB;AAC1D;AAEA,SAASU,GAAeC,GAAsBC,GAA8E;AAC1H,MAAI,MAAM,QAAQA,CAAqB,GAAG;AACxC,UAAMC,IAAYD,EAAsBD,CAAY;AACpD,QAAI,OAAOE,KAAc,YAAYA,EAAU,SAAS,EAAG,QAAOA;AAAA,EACpE;AACA,MAAID,aAAiC,KAAK;AACxC,UAAME,IAAUF,EAAsB,IAAID,CAAY;AACtD,QAAI,OAAOG,KAAY,YAAYA,EAAQ,SAAS,EAAG,QAAOA;AAAA,EAChE;AACA,SAAO,OAAOH,CAAY;AAC5B;AAEO,SAASI,GAAsBn8C,GAA4CyyB,GAAkDvtC,IAAgC,CAAA,GAAwB;AAC1L,QAAMk3D,IAAY,KAAK;AAAA,IACrB;AAAA,IACA,KAAK;AAAA,MACH,KAAK,MAAMp8C,GAAW,SAAS,CAAC;AAAA,MAChC,KAAK,OAAOA,GAAW,WAAW,UAAU,KAAK,CAAC;AAAA,MAClDA,GAAW,gBAAgB,UAAU;AAAA,MACrCA,GAAW,qBAAqB,aAAaA,EAAU,UAAU,SAAS,OAAO;AAAA,IAAA;AAAA,EACnF;AAGF,MAAIq2B,IAAkC;AACtC,MAAIr2B,GAAW,uBAAuB,aAAa;AACjD,UAAM5b,IAAS4b,EAAU;AACzB,QAAI42C,IAAQxyD,EAAO;AACnB,aAASuF,IAAI,GAAGA,IAAIvF,EAAO,QAAQuF,KAAK;AAEtC,MADYvF,EAAOuF,CAAC,IACVyyD,MACVxF,KAAS;AAEX,QAAIA,MAAUxyD,EAAO;AACnB,MAAAiyC,IAAcjyC;AAAA,aACLwyD,IAAQ,GAAG;AACpB,YAAMhd,IAAW,IAAI,YAAYgd,CAAK;AACtC,UAAI7pC,IAAS;AACb,eAASpjB,IAAI,GAAGA,IAAIvF,EAAO,QAAQuF,KAAK,GAAG;AACzC,cAAM8lD,IAAMrrD,EAAOuF,CAAC;AACpB,QAAI8lD,KAAO2M,MACXxiB,EAAS7sB,CAAM,IAAI0iC,GACnB1iC,KAAU;AAAA,MACZ;AACA,MAAAspB,IAAcuD;AAAA,IAChB;AACE,MAAAvD,IAAc,IAAI,YAAY,CAAC;AAAA,EAEnC;AAEA,QAAMwC,IAAaxC,IAAcA,EAAY,SAAS+lB,GAEhDxY,IAAkBsX,GAAezoB,KAAW,EAAE;AACpD,MAAI,CAACzyB,KAAa64B,MAAe,KAAK+K,EAAgB,WAAW;AAC/D,WAAO;AAAA,MACL,QAAQ,CAAA;AAAA,MACR,iBAAiB/K;AAAA,MACjB,uBAAuB;AAAA,MACvB,qBAAqBA;AAAA,IAAA;AAIzB,QAAMwjB,wBAA0B,IAAA,GAC1BC,wBAA0B,IAAA,GAC1BC,IAAsBhB,GAA6B3X,CAAe;AACxE,MAAI4Y,IAAc;AAElB,WAAS7yD,IAAI,GAAGA,IAAIkvC,GAAYlvC,KAAK,GAAG;AACtC,UAAMq6B,IAAaqS,IAAcA,EAAY1sC,CAAC,IAAIA,GAC5CW,IAAI0V,EAAU,UAAUgkB,IAAa,CAAC,GACtC,IAAIhkB,EAAU,UAAUgkB,IAAa,IAAI,CAAC;AAChD,QAAI,CAAC,OAAO,SAAS15B,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,EAAG;AAChD,QAAImyD,IAAoC;AACxC,UAAMC,IAAyBb,GAA0BU,GAAqBjyD,GAAG,CAAC;AAClF,QAAIoyD,EAAuB,WAAW,EAAG;AAEzC,eAAWd,KAAoBc,GAAwB;AACrD,YAAMxnC,IAAS0uB,EAAgBgY,CAAgB;AAC/C,UAAI/9C,IAAS;AACb,iBAAWlB,KAAWuY,EAAO;AAC3B,YAAKvW,GAAuBrU,GAAG,GAAGqS,CAAO,GACzC;AAAA,UAAAkB,IAAS;AACT;AAAA;AAEF,MAAKA,MACD,CAAC4+C,KAAcvnC,EAAO,OAAOunC,EAAW,UAC1CA,IAAavnC;AAAA,IAEjB;AAEA,QAAI,CAACunC,EAAY;AACjB,IAAAD,KAAe;AAEf,UAAMT,IAAe/7C,EAAU,eAAegkB,CAAU,KAAK,GACvD24B,IAAiBN,EAAoB,IAAII,EAAW,WAAW,yBAAS,IAAA;AAC9E,IAAAE,EAAe,IAAIZ,IAAeY,EAAe,IAAIZ,CAAY,KAAK,KAAK,CAAC,GAC5EM,EAAoB,IAAII,EAAW,aAAaE,CAAc,GAC9DL,EAAoB,IAAIG,EAAW,cAAcH,EAAoB,IAAIG,EAAW,WAAW,KAAK,KAAK,CAAC;AAAA,EAC5G;AAEA,QAAMG,IAAsB13D,EAAQ,uBAAuB,IACrD23D,IAA0B,CAAA;AAChC,aAAW3nC,KAAU0uB,GAAiB;AACpC,UAAMkZ,IAAaR,EAAoB,IAAIpnC,EAAO,WAAW,KAAK;AAClE,QAAI,CAAC0nC,KAAuBE,KAAc,EAAG;AAC7C,UAAMC,IAAWV,EAAoB,IAAInnC,EAAO,WAAW,yBAAS,IAAA,GAC9D8nC,IAA+B,MAAM,KAAKD,EAAS,SAAS,EAC/D,IAAI,CAAC,CAAChB,GAAcn+B,CAAK,OAAO;AAAA,MAC/B,SAASk+B,GAAeC,GAAc72D,EAAQ,qBAAqB;AAAA,MACnE,cAAA62D;AAAA,MACA,OAAAn+B;AAAA,IAAA,EACA,EACD,KAAK,CAACxzB,GAAGwE,MAAMA,EAAE,QAAQxE,EAAE,SAASA,EAAE,eAAewE,EAAE,YAAY;AAEtE,IAAAiuD,EAAO,KAAK;AAAA,MACV,UAAU3nC,EAAO;AAAA,MACjB,aAAaA,EAAO;AAAA,MACpB,YAAA4nC;AAAA,MACA,aAAAE;AAAA,IAAA,CACD;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAAH;AAAA,IACA,iBAAiBhkB;AAAA,IACjB,uBAAuB2jB;AAAA,IACvB,qBAAqB,KAAK,IAAI,GAAG3jB,IAAa2jB,CAAW;AAAA,EAAA;AAE7D;AC3QA,SAASS,GAAgBxgD,GAAuB;AAC9C,SAAOA,EAAM,QAAQ,8BAA8B,EAAE;AACvD;AAEA,SAASygD,GAAWr8C,GAAqB;AACvC,SAAQA,KAAM,OAAOA,KAAM,OAASA,KAAM,OAAOA,KAAM;AACzD;AAEA,SAASs8C,GAAYt8C,GAAqB;AACxC,SAAOA,KAAM,OAAOA,KAAM;AAC5B;AAEA,SAASu8C,GAAkBv8C,GAAqB;AAC9C,SAAOA,MAAO,OAAOA,MAAO,OAAOA,MAAO,OAAOs8C,GAAYt8C,CAAE;AACjE;AAEA,MAAMw8C,GAAU;AAAA,EAKd,YAAYC,GAAkB;AAJb,IAAA/3D,EAAA;AAET,IAAAA,EAAA,eAAQ;AAGd,SAAK,OAAO03D,GAAgBK,EAAS,KAAA,CAAM;AAAA,EAC7C;AAAA,EAEA,QAAkC;AAChC,QAAI,CAAC,KAAK,KAAM,QAAO;AAEvB,UAAMC,IAAe,KAAK,SAAA;AAC1B,QAAI,CAACA,EAAc,QAAO;AAE1B,UAAMC,IAAoBD,EAAa,YAAA;AACvC,QAAIC,MAAsB,aAAaA,MAAsB;AAC3D,aAAO;AAGT,SAAK,eAAA;AACL,UAAMC,IAAiB,KAAK,SAAA;AAC5B,QAAIA,GAAgB;AAClB,YAAMC,IAAWD,EAAe,YAAA;AAChC,OAAIC,MAAa,OAAOA,MAAa,OAAOA,MAAa,UACvD,KAAK,SAAA,GACL,KAAK,eAAA;AAAA,IAET;AAEA,QAAI,KAAK,cAAc,OAAO;AAE5B,aADA,KAAK,eAAA,GACA,KAAK,MAAA,IACNF,MAAsB,YACjB,EAAE,MAAM,WAAW,aAAa,CAAA,EAAC,IAEnC,EAAE,MAAM,gBAAgB,aAAa,CAAA,EAAC,IAJnB;AAO5B,QAAIG;AACJ,QAAI;AACF,MAAAA,IAAS,KAAK,gBAAA;AAAA,IAChB,QAAQ;AACN,aAAO;AAAA,IACT;AAGA,QADA,KAAK,eAAA,GACD,CAAC,KAAK,MAAA,EAAS,QAAO;AAE1B,QAAIH,MAAsB,WAAW;AACnC,YAAM7gD,IAAUihD,GAAqBD,CAAM;AAC3C,aAAKhhD,IACE;AAAA,QACL,MAAM;AAAA,QACN,aAAaA;AAAA,MAAA,IAHM;AAAA,IAKvB;AAEA,UAAM0B,IAAew/C,GAA0BF,CAAM;AACrD,WAAKt/C,IACE;AAAA,MACL,MAAM;AAAA,MACN,aAAaA;AAAA,IAAA,IAHW;AAAA,EAK5B;AAAA,EAEQ,QAAiB;AACvB,WAAO,KAAK,SAAS,KAAK,KAAK;AAAA,EACjC;AAAA,EAEQ,cAAsB;AAC5B,WAAO,KAAK,KAAK,KAAK,KAAK,KAAK;AAAA,EAClC;AAAA,EAEQ,iBAAuB;AAC7B,WAAO,CAAC,KAAK,WAAW,KAAK,KAAK,KAAK,YAAA,CAAa;AAClD,WAAK,SAAS;AAAA,EAElB;AAAA,EAEQ,WAA0B;AAEhC,QADA,KAAK,eAAA,GACD,KAAK,MAAA,EAAS,QAAO;AAEzB,UAAMiE,IAAQ,KAAK;AACnB,WAAO,CAAC,KAAK,MAAA,KAAW46C,GAAW,KAAK,YAAA,CAAa;AACnD,WAAK,SAAS;AAEhB,WAAI,KAAK,UAAU56C,IAAc,OAC1B,KAAK,KAAK,MAAMA,GAAO,KAAK,KAAK;AAAA,EAC1C;AAAA,EAEQ,WAA0B;AAChC,UAAMw7C,IAAQ,KAAK,OACbC,IAAO,KAAK,SAAA;AAClB,gBAAK,QAAQD,GACNC;AAAA,EACT;AAAA,EAEQ,cAAc5d,GAAyB;AAC7C,UAAM2d,IAAQ,KAAK,OACbC,IAAO,KAAK,SAAA;AAClB,WAAI,CAACA,KAAQA,EAAK,kBAAkB5d,EAAO,iBACzC,KAAK,QAAQ2d,GACN,MAEF;AAAA,EACT;AAAA,EAEQ,kBAA6B;AAEnC,QADA,KAAK,eAAA,GACD,KAAK,YAAA,MAAkB;AACzB,YAAM,IAAI,MAAM,cAAc;AAEhC,SAAK,SAAS;AAEd,UAAME,IAAoB,CAAA;AAC1B,eAAa;AACX,WAAK,eAAA,GACD,KAAK,YAAA,MAAkB,MACzBA,EAAO,KAAK,KAAK,iBAAiB,IAElCA,EAAO,KAAK,KAAK,sBAAsB,GAGzC,KAAK,eAAA;AACL,YAAMn9C,IAAK,KAAK,YAAA;AAChB,UAAIA,MAAO,KAAK;AACd,aAAK,SAAS;AACd;AAAA,MACF;AACA,UAAIA,MAAO,KAAK;AACd,aAAK,SAAS;AACd;AAAA,MACF;AACA,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AAEA,WAAOm9C;AAAA,EACT;AAAA,EAEQ,uBAAsC;AAC5C,SAAK,eAAA;AACL,UAAMA,IAAmB,CAAA;AACzB,eAAa;AACX,WAAK,eAAA;AACL,YAAMn9C,IAAK,KAAK,YAAA;AAChB,UAAI,CAACA,KAAM,CAACu8C,GAAkBv8C,CAAE,EAAG;AACnC,YAAMo9C,IAAM,KAAK,WAAA;AACjB,UAAIA,MAAQ,KAAM;AAClB,MAAAD,EAAO,KAAKC,CAAG,GACf,KAAK,eAAA;AACL,YAAMv4D,IAAO,KAAK,YAAA;AAClB,UAAI,CAACA,KAAQA,MAAS,OAAOA,MAAS,IAAK;AAC3C,UAAI,CAAC03D,GAAkB13D,CAAI;AACzB,cAAM,IAAI,MAAM,oBAAoB;AAAA,IAExC;AAEA,QAAIs4D,EAAO,SAAS;AAClB,YAAM,IAAI,MAAM,kCAAkC;AAEpD,WAAO,CAACA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,EAC9B;AAAA,EAEQ,aAA4B;AAElC,QADA,KAAK,eAAA,GACD,KAAK,MAAA,EAAS,QAAO;AAEzB,UAAMx9C,IADQ,KAAK,KAAK,MAAM,KAAK,KAAK,EACpB,MAAM,4CAA4C;AACtE,QAAI,CAACA,EAAO,QAAO;AACnB,UAAM/D,IAAQ,OAAO+D,EAAM,CAAC,CAAC;AAC7B,WAAK,OAAO,SAAS/D,CAAK,KAC1B,KAAK,SAAS+D,EAAM,CAAC,EAAE,QAChB/D,KAF6B;AAAA,EAGtC;AACF;AAEA,SAASyhD,GAAazhD,GAAwC;AAC5D,SACE,MAAM,QAAQA,CAAK,KACnBA,EAAM,UAAU,KAChB,OAAOA,EAAM,CAAC,KAAM,YACpB,OAAO,SAASA,EAAM,CAAC,CAAC,KACxB,OAAOA,EAAM,CAAC,KAAM,YACpB,OAAO,SAASA,EAAM,CAAC,CAAC;AAE5B;AAEA,SAASmhD,GAAqBnhD,GAA8C;AAC1E,MAAI,CAAC,MAAM,QAAQA,CAAK,EAAG,QAAO;AAClC,QAAME,IAAiC,CAAA;AACvC,aAAWwhD,KAAa1hD,GAAO;AAC7B,QAAI,CAAC,MAAM,QAAQ0hD,CAAS,EAAG,QAAO;AACtC,UAAMpqD,IAAwB,CAAA;AAC9B,eAAWqqD,KAAcD,GAAW;AAClC,UAAI,CAACD,GAAaE,CAAU,EAAG,QAAO;AACtC,MAAArqD,EAAK,KAAK,CAACqqD,EAAW,CAAC,GAAGA,EAAW,CAAC,CAAC,CAAC;AAAA,IAC1C;AACA,IAAAzhD,EAAQ,KAAK5I,CAAI;AAAA,EACnB;AACA,SAAO4I;AACT;AAEA,SAASkhD,GAA0BphD,GAAmD;AACpF,MAAI,CAAC,MAAM,QAAQA,CAAK,EAAG,QAAO;AAClC,QAAM4B,IAA2C,CAAA;AACjD,aAAWggD,KAAgB5hD,GAAO;AAChC,UAAME,IAAUihD,GAAqBS,CAAY;AACjD,QAAI,CAAC1hD,EAAS,QAAO;AACrB,IAAA0B,EAAa,KAAK1B,CAAO;AAAA,EAC3B;AACA,SAAO0B;AACT;AAEO,SAASigD,GAASC,GAAuC;AAC9D,SAAI,OAAOA,KAAQ,WAAiB,OAC7B,IAAIlB,GAAUkB,CAAG,EAAE,MAAA;AAC5B;","x_google_ignoreList":[3,4,5,6]}
|