open-plant 1.2.8 → 1.2.9
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/README.md +3 -0
- package/dist/assets/roi-clip-worker-BRaTL8Jd.js +2 -0
- package/dist/assets/roi-clip-worker-BRaTL8Jd.js.map +1 -0
- package/dist/index.cjs +10 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1769 -1623
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/react/draw-layer.d.ts +8 -2
- package/dist/types/react/draw-layer.d.ts.map +1 -1
- package/dist/types/react/wsi-viewer-canvas.d.ts +4 -3
- package/dist/types/react/wsi-viewer-canvas.d.ts.map +1 -1
- package/dist/types/wsi/brush-stroke.d.ts +1 -0
- package/dist/types/wsi/brush-stroke.d.ts.map +1 -1
- package/dist/types/wsi/point-clip-hybrid.d.ts.map +1 -1
- package/dist/types/wsi/point-clip.d.ts +3 -2
- package/dist/types/wsi/point-clip.d.ts.map +1 -1
- package/dist/types/wsi/roi-geometry.d.ts +23 -0
- package/dist/types/wsi/roi-geometry.d.ts.map +1 -0
- package/dist/types/wsi/roi-term-stats.d.ts.map +1 -1
- package/dist/types/wsi/types.d.ts +5 -1
- package/dist/types/wsi/types.d.ts.map +1 -1
- package/dist/types/wsi/wsi-tile-renderer.d.ts +3 -0
- package/dist/types/wsi/wsi-tile-renderer.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/assets/roi-clip-worker-D3hALtsJ.js +0 -2
- package/dist/assets/roi-clip-worker-D3hALtsJ.js.map +0 -1
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","../src/wsi/brush-stroke.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/react/draw-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/point-clip.ts","../src/wsi/webgpu.ts","../src/wsi/point-clip-hybrid.ts","../src/wsi/point-clip-worker-client.ts","../src/wsi/roi-term-stats.ts","../src/wsi/tile-scheduler.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer-canvas.tsx"],"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(\n gl: WebGL2RenderingContext,\n program: WebGLProgram,\n uniformName: string,\n): 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): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n 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}\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 };\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\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getMatrix(): Float32Array {\n const viewWidth = this.viewportWidth / this.viewState.zoom;\n const viewHeight = this.viewportHeight / this.viewState.zoom;\n\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\n return new Float32Array([\n sx,\n 0,\n 0,\n 0,\n sy,\n 0,\n tx,\n ty,\n 1,\n ]);\n }\n}\n","import {\n\tcreateProgram,\n\trequireUniformLocation,\n\trequireWebGL2,\n} from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n\tid: string;\n\tbounds: Bounds;\n\ttexture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n\tcanvas: HTMLCanvasElement;\n\timageWidth: number;\n\timageHeight: number;\n\tclearColor?: [number, number, number, number];\n\tinitialViewState?: Partial<ViewState>;\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\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly imageWidth: number;\n\tprivate readonly imageHeight: number;\n\tprivate readonly clearColor: [number, number, number, number];\n\tprivate readonly program: WebGLProgram;\n\tprivate readonly vao: WebGLVertexArrayObject;\n\tprivate readonly quadBuffer: WebGLBuffer;\n\tprivate readonly uCameraLocation: WebGLUniformLocation;\n\tprivate readonly uBoundsLocation: WebGLUniformLocation;\n\tprivate readonly uTextureLocation: WebGLUniformLocation;\n\tprivate readonly resizeObserver: ResizeObserver;\n\n\tprivate tiles: LoadedTile[] = [];\n\tprivate frameId: number | null = null;\n\tprivate loadVersion = 0;\n\tprivate destroyed = false;\n\tprivate fitted = false;\n\tprivate controlledViewState = false;\n\n\tconstructor(options: M1TileRendererOptions) {\n\t\tthis.canvas = options.canvas;\n\t\tthis.imageWidth = Math.max(1, options.imageWidth);\n\t\tthis.imageHeight = Math.max(1, options.imageHeight);\n\t\tthis.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n\t\tthis.gl = requireWebGL2(this.canvas);\n\t\tthis.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n\t\tconst vao = this.gl.createVertexArray();\n\t\tconst quadBuffer = this.gl.createBuffer();\n\t\tif (!vao || !quadBuffer) {\n\t\t\tthrow new Error(\"Failed to create WebGL buffers.\");\n\t\t}\n\n\t\tthis.vao = vao;\n\t\tthis.quadBuffer = quadBuffer;\n\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n\t\tconst quadVertices = new Float32Array([\n\t\t\t0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1,\n\t\t]);\n\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n\t\tconst unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n\t\tconst uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n\t\tif (unitLocation < 0 || uvLocation < 0) {\n\t\t\tthrow new Error(\"Failed to get attribute locations.\");\n\t\t}\n\n\t\tconst stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n\t\tthis.gl.enableVertexAttribArray(unitLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tunitLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t0,\n\t\t);\n\t\tthis.gl.enableVertexAttribArray(uvLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tuvLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t2 * Float32Array.BYTES_PER_ELEMENT,\n\t\t);\n\n\t\tthis.gl.bindVertexArray(null);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n\t\tthis.uCameraLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uCamera\",\n\t\t);\n\t\tthis.uBoundsLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uBounds\",\n\t\t);\n\t\tthis.uTextureLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uTexture\",\n\t\t);\n\n\t\tif (options.initialViewState) {\n\t\t\tthis.controlledViewState = true;\n\t\t\tthis.camera.setViewState(options.initialViewState);\n\t\t}\n\n\t\tthis.resizeObserver = new ResizeObserver(() => {\n\t\t\tthis.resize();\n\t\t});\n\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.resize();\n\t}\n\n\tasync setTiles(tiles: TileDefinition[]): Promise<void> {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst version = ++this.loadVersion;\n\n\t\tconst loaded = await Promise.all(\n\t\t\ttiles.map(async (tile) => {\n\t\t\t\tconst loadedTile = await this.loadTile(tile, version);\n\t\t\t\treturn loadedTile;\n\t\t\t}),\n\t\t);\n\n\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\tfor (const tile of loaded) {\n\t\t\t\tif (tile) {\n\t\t\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n\t\tthis.requestRender();\n\t}\n\n\tsetViewState(viewState: Partial<ViewState>): void {\n\t\tthis.controlledViewState = true;\n\t\tthis.camera.setViewState(viewState);\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): ViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.loadVersion += 1;\n\n\t\tif (this.frameId !== null) {\n\t\t\tcancelAnimationFrame(this.frameId);\n\t\t\tthis.frameId = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = [];\n\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tthis.gl.deleteVertexArray(this.vao);\n\t\tthis.gl.deleteProgram(this.program);\n\t}\n\n\tprivate async loadTile(\n\t\ttile: TileDefinition,\n\t\tversion: number,\n\t): Promise<LoadedTile | null> {\n\t\ttry {\n\t\t\tconst response = await fetch(tile.url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tile fetch failed: ${response.status} ${response.statusText}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst blob = await response.blob();\n\t\t\tconst bitmap = await createImageBitmap(blob);\n\n\t\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\t\tbitmap.close();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst texture = this.gl.createTexture();\n\t\t\tif (!texture) {\n\t\t\t\tbitmap.close();\n\t\t\t\tthrow new Error(\"Failed to create tile texture.\");\n\t\t\t}\n\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_S,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_T,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MIN_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MAG_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\tbitmap,\n\t\t\t);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\t\tbitmap.close();\n\n\t\t\treturn {\n\t\t\t\tid: tile.id,\n\t\t\t\tbounds: tile.bounds,\n\t\t\t\ttexture,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate resize(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n\t\tconst targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n\t\tif (\n\t\t\tthis.canvas.width !== targetWidth ||\n\t\t\tthis.canvas.height !== targetHeight\n\t\t) {\n\t\t\tthis.canvas.width = targetWidth;\n\t\t\tthis.canvas.height = targetHeight;\n\t\t}\n\n\t\tthis.camera.setViewport(cssWidth, cssHeight);\n\t\tthis.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n\t\tif (!this.fitted && !this.controlledViewState) {\n\t\t\tthis.fitToImage();\n\t\t\tthis.fitted = true;\n\t\t}\n\n\t\tthis.requestRender();\n\t}\n\n\tprivate fitToImage(): void {\n\t\tconst viewport = this.camera.getViewportSize();\n\n\t\tconst zoom = Math.min(\n\t\t\tviewport.width / this.imageWidth,\n\t\t\tviewport.height / this.imageHeight,\n\t\t);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tconst visibleWorldWidth = viewport.width / safeZoom;\n\t\tconst visibleWorldHeight = viewport.height / safeZoom;\n\n\t\tconst offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n\t\tconst offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: safeZoom,\n\t\t\toffsetX,\n\t\t\toffsetY,\n\t\t});\n\t}\n\n\tprivate requestRender(): void {\n\t\tif (this.frameId !== null || this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.frameId = requestAnimationFrame(() => {\n\t\t\tthis.frameId = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tprivate render(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gl.clearColor(\n\t\t\tthis.clearColor[0],\n\t\t\tthis.clearColor[1],\n\t\t\tthis.clearColor[2],\n\t\t\tthis.clearColor[3],\n\t\t);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tthis.gl.useProgram(this.program);\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.uniformMatrix3fv(\n\t\t\tthis.uCameraLocation,\n\t\t\tfalse,\n\t\t\tthis.camera.getMatrix(),\n\t\t);\n\t\tthis.gl.uniform1i(this.uTextureLocation, 0);\n\n\t\tfor (const tile of this.tiles) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n\t\t\tthis.gl.uniform4f(\n\t\t\t\tthis.uBoundsLocation,\n\t\t\t\ttile.bounds[0],\n\t\t\t\ttile.bounds[1],\n\t\t\t\ttile.bounds[2],\n\t\t\t\ttile.bounds[3],\n\t\t\t);\n\t\t\tthis.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\tthis.gl.bindVertexArray(null);\n\t}\n\n\tprivate disposeTiles(tiles: LoadedTile[]): void {\n\t\tfor (const tile of tiles) {\n\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t}\n\t}\n}\n","export 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}\n\ninterface RasterConfig {\n\tminX: number;\n\tminY: number;\n\tstep: number;\n\tpadding: number;\n\twidth: number;\n\theight: number;\n}\n\ninterface BoundaryEdge {\n\tstart: number;\n\tend: number;\n\tdir: 0 | 1 | 2 | 3;\n}\n\nconst DEFAULT_MIN_RASTER_STEP = 0.1;\nconst DEFAULT_MAX_RASTER_PIXELS = 4_000_000;\nconst DEFAULT_MAX_RASTER_SIZE = 4096;\nconst DEFAULT_CIRCLE_SIDES = 64;\nconst MIN_RADIUS = 1e-6;\nconst ALPHA_THRESHOLD = 24;\n\nfunction clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nfunction closeRing(\n\tcoordinates: BrushStrokeCoordinate[],\n): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(([x, y]) => [x, y] as BrushStrokeCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction sanitizePath(\n\tpoints: BrushStrokeCoordinate[],\n): 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 createCirclePolygon(\n\tcenter: BrushStrokeCoordinate,\n\tradius: number,\n\tsides: number,\n): 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([\n\t\t\tcenter[0] + Math.cos(t) * radius,\n\t\t\tcenter[1] + Math.sin(t) * radius,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction createBoundsFallback(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): 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 computeExpandedBounds(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): BrushStrokeBounds {\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\tconst pad = Math.max(radius, 1);\n\treturn [minX - pad, minY - pad, maxX + pad, maxY + pad];\n}\n\nfunction resolveRasterConfig(\n\tbounds: BrushStrokeBounds,\n\tradius: number,\n\toptions: BrushStrokePolygonOptions,\n): RasterConfig {\n\tconst minRasterStep = Math.max(\n\t\tDEFAULT_MIN_RASTER_STEP,\n\t\tNumber(options.minRasterStep) || 0,\n\t);\n\tconst maxRasterPixels = Math.max(\n\t\t32_768,\n\t\tMath.floor(options.maxRasterPixels || DEFAULT_MAX_RASTER_PIXELS),\n\t);\n\tconst maxRasterSize = Math.max(\n\t\t256,\n\t\tMath.floor(options.maxRasterSize || DEFAULT_MAX_RASTER_SIZE),\n\t);\n\n\tconst widthWorld = Math.max(1e-3, bounds[2] - bounds[0]);\n\tconst heightWorld = Math.max(1e-3, bounds[3] - bounds[1]);\n\tlet step = Math.max(minRasterStep, Number.EPSILON);\n\tlet padding = 3;\n\tlet width = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\tlet height = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\n\twhile (\n\t\twidth > maxRasterSize ||\n\t\theight > maxRasterSize ||\n\t\twidth * height > maxRasterPixels\n\t) {\n\t\tstep *= 1.15;\n\t\twidth = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\t\theight = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\t\tif (step > Math.max(widthWorld, heightWorld)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twidth = Math.max(8, width);\n\theight = Math.max(8, height);\n\n\treturn {\n\t\tminX: bounds[0],\n\t\tminY: bounds[1],\n\t\tstep,\n\t\tpadding,\n\t\twidth,\n\t\theight,\n\t};\n}\n\ntype AnyCanvas2DContext =\n\t| CanvasRenderingContext2D\n\t| OffscreenCanvasRenderingContext2D;\n\nfunction createRasterContext(\n\twidth: number,\n\theight: number,\n): AnyCanvas2DContext | null {\n\tif (typeof OffscreenCanvas !== \"undefined\") {\n\t\tconst canvas = new OffscreenCanvas(width, height);\n\t\tconst context = canvas.getContext(\"2d\", { willReadFrequently: true });\n\t\tif (context) return context;\n\t}\n\tif (typeof document !== \"undefined\") {\n\t\tconst canvas = document.createElement(\"canvas\");\n\t\tcanvas.width = width;\n\t\tcanvas.height = height;\n\t\treturn canvas.getContext(\"2d\", { willReadFrequently: true });\n\t}\n\treturn null;\n}\n\nfunction worldToRaster(\n\tpoint: BrushStrokeCoordinate,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate {\n\treturn [\n\t\t(point[0] - config.minX) / config.step + config.padding,\n\t\t(point[1] - config.minY) / config.step + config.padding,\n\t];\n}\n\nfunction rasterizeStrokeMask(\n\tpath: BrushStrokeCoordinate[],\n\tradius: number,\n\tconfig: RasterConfig,\n): Uint8Array {\n\tconst context = createRasterContext(config.width, config.height);\n\tif (!context) return new Uint8Array(0);\n\n\tcontext.clearRect(0, 0, config.width, config.height);\n\tcontext.fillStyle = \"#ffffff\";\n\tcontext.strokeStyle = \"#ffffff\";\n\tcontext.lineCap = \"round\";\n\tcontext.lineJoin = \"round\";\n\tcontext.lineWidth = (radius * 2) / config.step;\n\n\tconst points = path.map(point => worldToRaster(point, config));\n\tif (points.length <= 1) {\n\t\tconst p = points[0];\n\t\tif (!p) return new Uint8Array(0);\n\t\tcontext.beginPath();\n\t\tcontext.arc(p[0], p[1], radius / config.step, 0, Math.PI * 2);\n\t\tcontext.fill();\n\t} else {\n\t\tcontext.beginPath();\n\t\tcontext.moveTo(points[0][0], points[0][1]);\n\t\tfor (let i = 1; i < points.length; i += 1) {\n\t\t\tcontext.lineTo(points[i][0], points[i][1]);\n\t\t}\n\t\tcontext.stroke();\n\t}\n\n\tconst image = context.getImageData(0, 0, config.width, config.height);\n\tconst out = new Uint8Array(config.width * config.height);\n\tfor (let i = 0; i < out.length; i += 1) {\n\t\tout[i] = image.data[i * 4 + 3] >= ALPHA_THRESHOLD ? 1 : 0;\n\t}\n\treturn out;\n}\n\nfunction buildBoundaryEdges(mask: Uint8Array, width: number, height: number): BoundaryEdge[] {\n\tconst edges: BoundaryEdge[] = [];\n\tconst stride = width + 1;\n\tconst vertex = (x: number, y: number): number => y * stride + x;\n\tconst at = (x: number, y: number): boolean =>\n\t\tx >= 0 && y >= 0 && x < width && y < height && mask[y * width + x] > 0;\n\n\tfor (let y = 0; y < height; y += 1) {\n\t\tfor (let x = 0; x < width; x += 1) {\n\t\t\tif (!at(x, y)) continue;\n\t\t\tif (!at(x, y - 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y),\n\t\t\t\t\tend: vertex(x + 1, y),\n\t\t\t\t\tdir: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x + 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y),\n\t\t\t\t\tend: vertex(x + 1, y + 1),\n\t\t\t\t\tdir: 1,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x, y + 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y + 1),\n\t\t\t\t\tend: vertex(x, y + 1),\n\t\t\t\t\tdir: 2,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x - 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y + 1),\n\t\t\t\t\tend: vertex(x, y),\n\t\t\t\t\tdir: 3,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn edges;\n}\n\nfunction turnPriority(fromDir: number, toDir: number): number {\n\tconst delta = (toDir - fromDir + 4) % 4;\n\tif (delta === 1) return 0; // right\n\tif (delta === 0) return 1; // straight\n\tif (delta === 3) return 2; // left\n\treturn 3; // reverse\n}\n\nfunction traceLoops(edges: BoundaryEdge[]): number[][] {\n\tif (!edges.length) return [];\n\n\tconst outgoing = new Map<number, number[]>();\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tconst entry = outgoing.get(edges[i].start);\n\t\tif (entry) {\n\t\t\tentry.push(i);\n\t\t} else {\n\t\t\toutgoing.set(edges[i].start, [i]);\n\t\t}\n\t}\n\n\tconst used = new Uint8Array(edges.length);\n\tconst loops: number[][] = [];\n\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tif (used[i]) continue;\n\n\t\tconst first = edges[i];\n\t\tconst startVertex = first.start;\n\t\tlet currentVertex = first.end;\n\t\tlet currentDir = first.dir;\n\t\tconst loop: number[] = [first.start, first.end];\n\t\tused[i] = 1;\n\n\t\tlet guard = 0;\n\t\tconst guardLimit = edges.length * 3;\n\t\twhile (currentVertex !== startVertex && guard < guardLimit) {\n\t\t\tconst candidates = outgoing.get(currentVertex);\n\t\t\tif (!candidates || candidates.length === 0) break;\n\n\t\t\tlet bestIndex = -1;\n\t\t\tlet bestPriority = Infinity;\n\t\t\tfor (const edgeIndex of candidates) {\n\t\t\t\tif (used[edgeIndex]) continue;\n\t\t\t\tconst candidate = edges[edgeIndex];\n\t\t\t\tconst priority = turnPriority(currentDir, candidate.dir);\n\t\t\t\tif (priority < bestPriority) {\n\t\t\t\t\tbestPriority = priority;\n\t\t\t\t\tbestIndex = edgeIndex;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bestIndex < 0) break;\n\t\t\tused[bestIndex] = 1;\n\t\t\tconst next = edges[bestIndex];\n\t\t\tcurrentVertex = next.end;\n\t\t\tcurrentDir = next.dir;\n\t\t\tloop.push(currentVertex);\n\t\t\tguard += 1;\n\t\t}\n\n\t\tif (\n\t\t\tloop.length >= 4 &&\n\t\t\tloop[0] === loop[loop.length - 1]\n\t\t) {\n\t\t\tloops.push(loop);\n\t\t}\n\t}\n\n\treturn loops;\n}\n\nfunction toWorldRing(\n\tvertexLoop: number[],\n\twidth: number,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate[] {\n\tconst stride = width + 1;\n\tconst ring: BrushStrokeCoordinate[] = [];\n\tfor (const id of vertexLoop) {\n\t\tconst x = id % stride;\n\t\tconst y = Math.floor(id / stride);\n\t\tring.push([\n\t\t\tconfig.minX + (x - config.padding) * config.step,\n\t\t\tconfig.minY + (y - config.padding) * config.step,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction polygonSignedArea(ring: BrushStrokeCoordinate[]): number {\n\tif (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 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(\n\tpoints: BrushStrokeCoordinate[],\n\ttolerance: number,\n): 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(\n\tring: BrushStrokeCoordinate[],\n\ttolerance: number,\n): 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 clampRingToBounds(\n\tring: BrushStrokeCoordinate[],\n\tbounds: BrushStrokeBounds | undefined,\n): BrushStrokeCoordinate[] {\n\tif (!bounds) return 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\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(\n\t\t\tcreateCirclePolygon(points[0], radius, circleSides),\n\t\t\toptions.clipBounds,\n\t\t);\n\t}\n\n\tconst bounds = computeExpandedBounds(points, radius);\n\tconst raster = resolveRasterConfig(bounds, radius, options);\n\tconst mask = rasterizeStrokeMask(points, radius, raster);\n\tif (!mask.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tconst edges = buildBoundaryEdges(mask, raster.width, raster.height);\n\tconst loops = traceLoops(edges);\n\tif (!loops.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tlet bestRing: BrushStrokeCoordinate[] = [];\n\tlet bestArea = 0;\n\tfor (const loop of loops) {\n\t\tconst ring = toWorldRing(loop, raster.width, raster);\n\t\tconst area = Math.abs(polygonSignedArea(ring));\n\t\tif (area <= bestArea) continue;\n\t\tbestArea = area;\n\t\tbestRing = ring;\n\t}\n\n\tif (!bestRing.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: raster.step * 0.2;\n\tconst simplified = simplifyClosedRing(\n\t\tremoveCollinearVertices(bestRing, raster.step * 1e-3),\n\t\ttolerance,\n\t);\n\treturn clampRingToBounds(simplified, options.clipBounds);\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 { TermPalette, 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 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 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 buildTermPalette(\n\tterms:\n\t\t| Array<{ termId?: string | null; termColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): TermPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst termToPaletteIndex = new Map<string, number>();\n\n\tfor (const term of terms ?? []) {\n\t\tconst termId = String(term?.termId ?? \"\");\n\t\tif (!termId || termToPaletteIndex.has(termId)) continue;\n\n\t\ttermToPaletteIndex.set(termId, palette.length);\n\t\tpalette.push(hexToRgba(term?.termColor));\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, termToPaletteIndex };\n}\n\nexport function createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram {\n\tconst vs = gl.createShader(gl.VERTEX_SHADER);\n\tconst fs = gl.createShader(gl.FRAGMENT_SHADER);\n\tif (!vs || !fs) {\n\t\tthrow new Error(\"Shader allocation failed\");\n\t}\n\n\tgl.shaderSource(vs, vertexSource);\n\tgl.compileShader(vs);\n\tif (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(vs) || \"vertex compile failed\");\n\t}\n\n\tgl.shaderSource(fs, fragmentSource);\n\tgl.compileShader(fs);\n\tif (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(fs) || \"fragment compile failed\");\n\t}\n\n\tconst program = gl.createProgram();\n\tif (!program) {\n\t\tthrow new Error(\"Program allocation failed\");\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tthrow new Error(gl.getProgramInfoLog(program) || \"program link failed\");\n\t}\n\n\treturn program;\n}\n","import { type CSSProperties, type MutableRefObject, type PointerEvent as ReactPointerEvent, type RefObject, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { buildBrushStrokePolygon } from \"../wsi/brush-stroke\";\nimport { calcScaleResolution } from \"../wsi/utils\";\n\nexport type StampDrawTool = \"stamp-rectangle\" | \"stamp-circle\" | \"stamp-rectangle-4096px\" | \"stamp-rectangle-2mm2\" | \"stamp-circle-2mm2\" | \"stamp-circle-hpf-0.2mm2\";\n\nexport type DrawTool = \"cursor\" | \"freehand\" | \"rectangle\" | \"circular\" | \"brush\" | StampDrawTool;\n\nexport type DrawCoordinate = [number, number];\n\nexport type DrawBounds = [number, number, number, number];\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: DrawCoordinate[];\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 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 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 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 /**\n * Brush edge detail factor. Higher values create rounder/finer edges.\n * Range: 0.25 ~ 4. Default: 1.\n */\n edgeDetail?: number;\n /**\n * When true, a brush \"tap\" (click without drag) on ROI selects that ROI\n * instead of creating a brush stroke.\n */\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?: DrawCoordinate[][];\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n regionLabelStyle?: Partial<RegionLabelStyle>;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\ninterface DrawSession {\n isDrawing: boolean;\n pointerId: number | null;\n start: DrawCoordinate | null;\n current: DrawCoordinate | null;\n cursor: DrawCoordinate | null;\n points: DrawCoordinate[];\n stampCenter: DrawCoordinate | null;\n}\n\ninterface ResolvedBrushOptions {\n radius: number;\n edgeDetail: number;\n clickSelectRoi: boolean;\n fillColor: string;\n fillOpacity: number;\n cursorColor: string;\n cursorActiveColor: string;\n cursorLineWidth: number;\n cursorLineDash: number[];\n}\n\nconst DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nconst FREEHAND_MIN_POINTS = 3;\nconst FREEHAND_SCREEN_STEP = 2;\nconst CIRCLE_SIDES = 96;\nconst MIN_AREA_PX = 1;\nconst EMPTY_REGIONS: DrawRegion[] = [];\nconst EMPTY_DASH: number[] = [];\nconst MICRONS_PER_MM = 1000;\nconst DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE = 4096;\nconst LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\nconst WHEEL_ZOOM_IN_FACTOR = 1.12;\nconst WHEEL_ZOOM_OUT_FACTOR = 0.89;\nconst DEFAULT_BRUSH_RADIUS = 32;\nconst DEFAULT_BRUSH_FILL_COLOR = \"#000000\";\nconst DEFAULT_BRUSH_FILL_OPACITY = 0.1;\nconst DEFAULT_BRUSH_CURSOR_COLOR = \"#FFCF00\";\nconst DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR = \"#FF0000\";\nconst DEFAULT_BRUSH_CURSOR_LINE_WIDTH = 1.5;\nconst DEFAULT_BRUSH_CURSOR_DASH = [2, 2];\nconst DEFAULT_BRUSH_EDGE_DETAIL = 1;\nconst MIN_BRUSH_EDGE_DETAIL = 0.25;\nconst MAX_BRUSH_EDGE_DETAIL = 4;\nconst MIN_BRUSH_RASTER_STEP = 0.1;\nconst BRUSH_RASTER_DIAMETER_SAMPLES = 96;\nconst BRUSH_SCREEN_STEP = 1.5;\n\nconst 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\nconst 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\nconst DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 12,\n fontWeight: 500,\n textColor: \"#ffffff\",\n backgroundColor: \"rgba(8, 14, 22, 0.88)\",\n borderColor: \"rgba(255, 77, 79, 0.85)\",\n borderWidth: 1,\n paddingX: 6,\n paddingY: 4,\n offsetY: 10,\n borderRadius: 3,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction isStampTool(tool: DrawTool): tool is StampDrawTool {\n return (\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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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 return {\n radius,\n edgeDetail,\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\nfunction mm2ToUm2(areaMm2: number): number {\n return areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nfunction createSquareFromCenter(center: DrawCoordinate | null, halfLength: number): DrawCoordinate[] {\n if (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\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\nfunction 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 function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n\n const out = coords.map(([x, y]) => [x, y] as DrawCoordinate);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n\n return out;\n}\n\nexport function createRectangle(start: DrawCoordinate | null, end: DrawCoordinate | null): DrawCoordinate[] {\n if (!start || !end) return [];\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\nfunction polygonArea(coords: DrawCoordinate[]): number {\n if (!Array.isArray(coords) || coords.length < 4) return 0;\n\n let sum = 0;\n for (let i = 0; i < coords.length - 1; i += 1) {\n const a = coords[i];\n const b = coords[i + 1];\n sum += a[0] * b[1] - b[0] * a[1];\n }\n\n return Math.abs(sum * 0.5);\n}\n\nfunction 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\nfunction isValidPolygon(coords: DrawCoordinate[]): boolean {\n return Array.isArray(coords) && coords.length >= 4 && polygonArea(coords) > MIN_AREA_PX;\n}\n\nfunction 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\nfunction drawPath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], strokeStyle: RegionStrokeStyle, close = false, fill = false): void {\n if (points.length === 0) return;\n\n ctx.beginPath();\n tracePath(ctx, points, close);\n if (fill && close) {\n ctx.fillStyle = DRAW_FILL;\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\nfunction 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\nfunction 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\nfunction 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\nfunction isNestedRingCoordinates(coordinates: DrawOverlayCoordinates): boolean {\n const first = coordinates[0];\n return Array.isArray(first) && Array.isArray(first[0]);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is [number, number] {\n return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);\n}\n\nfunction 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\nfunction 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\nfunction 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\nfunction resolveLabelStyle(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\nfunction 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\nfunction getTopAnchor(coords: DrawCoordinate[]): 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) > 0.5) 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 return [(minX + maxX) * 0.5, minY];\n}\n\nfunction drawRegionLabel(ctx: CanvasRenderingContext2D, text: string, anchor: DrawCoordinate, canvasWidth: number, canvasHeight: number, labelStyle: RegionLabelStyle): 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 = ctx.measureText(label).width;\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const x = clamp(anchor[0], boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1);\n const y = clamp(anchor[1] - labelStyle.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 = 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\nfunction clampWorld(coord: DrawCoordinate, imageWidth: number, imageHeight: number): DrawCoordinate {\n return [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nfunction toCoord(value: DrawCoordinate | number[]): 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 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 regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n hoveredRegionId = null,\n activeRegionId = null,\n regionLabelStyle,\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 points: [],\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\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\n const resolvedLabelStyle = useMemo(() => resolveLabelStyle(regionLabelStyle), [regionLabelStyle]);\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 }, []);\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = projectorRef.current;\n if (!projector || points.length === 0) return [];\n\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 [projectorRef]\n );\n\n const worldRadiusToScreenPixels = useCallback(\n (center: DrawCoordinate, worldRadius: number): number => {\n if (!Number.isFinite(worldRadius) || worldRadius <= 0) return 0;\n const projector = projectorRef.current;\n if (!projector) return 0;\n const a = toCoord(projector.worldToScreen(center[0], center[1]));\n const b = toCoord(projector.worldToScreen(center[0] + worldRadius, center[1]));\n if (!a || !b) return 0;\n return Math.hypot(b[0] - a[0], b[1] - a[1]);\n },\n [projectorRef]\n );\n\n const micronsToWorldPixels = useCallback(\n (lengthUm: number): number => {\n if (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n // If mpp is missing, fall back to 1um/px assumption.\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 buildStampCoords = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate | null): DrawCoordinate[] => {\n if (!center) return [];\n\n let areaMm2 = 0;\n if (stampTool === \"stamp-rectangle-4096px\") {\n const halfLength = resolvedStampOptions.rectanglePixelSize * 0.5;\n const fixed = createSquareFromCenter(center, halfLength);\n return fixed.map(point => clampWorld(point, imageWidth, imageHeight));\n }\n\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);\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 [micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions]\n );\n\n const buildPreviewCoords = useCallback((): DrawCoordinate[] => {\n const session = sessionRef.current;\n if (isStampTool(tool)) {\n return buildStampCoords(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);\n }\n if (tool === \"circular\") {\n return createCircle(session.start, session.current);\n }\n\n return [];\n }, [tool, buildStampCoords]);\n\n const drawBrushStrokePreview = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.points.length === 0) return;\n\n const screenPoints = worldToScreenPoints(session.points);\n if (screenPoints.length === 0) return;\n const anchor = session.points[session.points.length - 1] ?? session.points[0];\n const radiusPx = worldRadiusToScreenPixels(anchor, 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 [worldToScreenPoints, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\n\n const drawBrushCursor = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n const cursor = session.cursor;\n if (!cursor) return;\n const screen = toCoord(projectorRef.current?.worldToScreen(cursor[0], cursor[1]) ?? []);\n if (!screen) return;\n const radiusPx = worldRadiusToScreenPixels(cursor, 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 [projectorRef, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\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 // Persisted ROI outlines always remain visible.\n if (mergedPersistedRegions.length > 0) {\n for (let i = 0; i < mergedPersistedRegions.length; i += 1) {\n const region = mergedPersistedRegions[i];\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const screen = worldToScreenPoints(closed);\n if (screen.length >= 4) {\n const regionKey = region.id ?? i;\n const state: RegionStyleContext[\"state\"] = 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: i,\n state,\n });\n strokeStyle = mergeStrokeStyle(strokeStyle, resolved || undefined);\n }\n drawPath(ctx, screen, strokeStyle, true, false);\n }\n }\n }\n\n if (mergedPatchRegions.length > 0) {\n for (let i = 0; i < mergedPatchRegions.length; i += 1) {\n const region = mergedPatchRegions[i];\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const screen = worldToScreenPoints(closed);\n if (screen.length < 4) continue;\n drawPath(ctx, screen, resolvedPatchStrokeStyle, true, false);\n }\n }\n\n if (Array.isArray(overlayShapes) && overlayShapes.length > 0) {\n const debugOverlay = Boolean((globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__);\n const imageOuterRing = worldToScreenPoints(\n closeRing([\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ])\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) {\n const debugKey = String(shape.id ?? i);\n const debugSignature = `${imageOuterRing.length}|${closedRings.length}|${holeRings.length}|${shape.invertedFill.fillColor}`;\n if (overlayDebugSnapshotRef.current.get(debugKey) !== debugSignature) {\n overlayDebugSnapshotRef.current.set(debugKey, debugSignature);\n console.debug(\"[open-plant] invertedFill\", {\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 }\n drawInvertedFillMask(ctx, imageOuterRing, holeRings, shape.invertedFill.fillColor);\n }\n\n if (renderRings.length === 0) continue;\n const strokeStyle = mergeStrokeStyle(resolvedStrokeStyle, 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\n if (active) {\n if (tool === \"brush\") {\n drawBrushStrokePreview(ctx);\n drawBrushCursor(ctx);\n } else {\n const preview = buildPreviewCoords();\n 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);\n }\n } else {\n const polygon = worldToScreenPoints(preview);\n if (polygon.length >= 4) {\n drawPath(ctx, polygon, resolvedStrokeStyle, true, true);\n }\n }\n }\n }\n }\n\n // Draw labels last so they stay visually on top.\n if (mergedPersistedRegions.length > 0) {\n for (const region of mergedPersistedRegions) {\n if (!region.label) continue;\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const anchorWorld = getTopAnchor(closed);\n if (!anchorWorld) continue;\n const anchorScreen = toCoord(projectorRef.current?.worldToScreen(anchorWorld[0], anchorWorld[1]) ?? []);\n if (!anchorScreen) continue;\n drawRegionLabel(ctx, region.label, anchorScreen, canvasWidth, canvasHeight, resolvedLabelStyle);\n }\n }\n }, [\n active,\n tool,\n buildPreviewCoords,\n drawBrushStrokePreview,\n drawBrushCursor,\n resizeCanvas,\n worldToScreenPoints,\n imageWidth,\n imageHeight,\n projectorRef,\n mergedPersistedRegions,\n overlayShapes,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n mergedPatchRegions,\n resolvedPatchStrokeStyle,\n resolveRegionStrokeStyle,\n resolvedLabelStyle,\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 try {\n canvas.releasePointerCapture(session.pointerId);\n } catch {\n // noop\n }\n }\n\n session.isDrawing = false;\n session.pointerId = null;\n session.start = null;\n session.current = null;\n session.points = [];\n session.stampCenter = null;\n if (!preserveCursor) {\n session.cursor = null;\n }\n }, []);\n\n const toWorld = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): 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 finishSession = useCallback(() => {\n const session = sessionRef.current;\n if (!session.isDrawing) {\n resetSession(true);\n requestDraw();\n return;\n }\n\n let coordinates: 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);\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 = resolvedBrushOptions.edgeDetail;\n const minRasterStep = Math.max(\n MIN_BRUSH_RASTER_STEP,\n (resolvedBrushOptions.radius * 2) / (BRUSH_RASTER_DIAMETER_SAMPLES * edgeDetail),\n );\n coordinates = buildBrushStrokePolygon(session.points, {\n radius: resolvedBrushOptions.radius,\n clipBounds: [0, 0, imageWidth, imageHeight],\n minRasterStep,\n circleSides: Math.max(24, Math.round(64 * edgeDetail)),\n simplifyTolerance: minRasterStep * 0.4,\n }) as DrawCoordinate[];\n }\n\n if ((tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\" || tool === \"brush\") && isValidPolygon(coordinates) && onDrawComplete) {\n const intent: 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 }, [tool, onDrawComplete, resetSession, requestDraw, resolvedBrushOptions.radius, resolvedBrushOptions.edgeDetail, resolvedBrushOptions.clickSelectRoi, imageWidth, imageHeight, onBrushTap]);\n\n const handleStampAt = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate): void => {\n const coordinates = buildStampCoords(stampTool, center);\n if (!isValidPolygon(coordinates)) return;\n const intent: DrawIntent = stampTool === \"stamp-rectangle-4096px\" ? \"patch\" : \"roi\";\n const result: 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 PatchDrawResult);\n }\n },\n [buildStampCoords, onDrawComplete, onPatchComplete]\n );\n\n const appendBrushPoint = useCallback(\n (session: DrawSession, world: DrawCoordinate): void => {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = BRUSH_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n if (!prev) {\n session.points.push(world);\n session.current = world;\n return;\n }\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 } else {\n session.points[session.points.length - 1] = world;\n }\n session.current = world;\n },\n [projectorRef]\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\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.points = tool === \"freehand\" || tool === \"brush\" ? [world] : [];\n requestDraw();\n },\n [active, tool, toWorld, 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\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n event.preventDefault();\n event.stopPropagation();\n requestDraw();\n return;\n }\n\n const session = sessionRef.current;\n if (tool === \"brush\") {\n session.cursor = world;\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n requestDraw();\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n appendBrushPoint(session, world);\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, 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 if (world) {\n session.cursor = world;\n if (tool === \"brush\") {\n appendBrushPoint(session, world);\n } else {\n session.current = world;\n }\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 finishSession();\n },\n [finishSession, toWorld, 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 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(() => {\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 if (!canvas || typeof projector?.zoomBy !== \"function\") 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 projector.zoomBy(event.deltaY < 0 ? WHEEL_ZOOM_IN_FACTOR : WHEEL_ZOOM_OUT_FACTOR, screenX, screenY);\n requestDraw();\n }}\n />\n );\n}\n","import type { WsiImageSource, WsiTerm } from \"./types\";\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: any, 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(\"이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요\");\n }\n\n const terms: WsiTerm[] = Array.isArray(raw?.terms)\n ? raw.terms.map((term: any) => ({\n termId: String(term?.termId ?? \"\"),\n termName: String(term?.termName ?? \"\"),\n termColor: String(term?.termColor ?? \"\"),\n }))\n : [];\n\n const normalizedPath = ensureLeadingSlash(tilePath);\n const imsTileRoot = joinImsTileRoot(tileBaseUrl);\n const tileUrlBuilder = isIms ? (tier: number, x: number, y: number): string => `${imsTileRoot}${normalizedPath}/${tier}/${y}_${x}.webp` : undefined;\n\n return {\n 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 terms,\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);\n }\n const normalizedPath = ensureLeadingSlash(source.tilePath);\n return `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import {\n\ttype CSSProperties,\n\ttype MutableRefObject,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\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\nexport interface OverviewMapProjector {\n\tgetViewState: () => WsiViewState;\n\tsetViewState: (next: Partial<WsiViewState>) => void;\n\tsetViewCenter?: (worldX: number, worldY: number) => void;\n\tgetViewBounds?: () => number[];\n\tgetViewCorners?: () => Array<[number, number]>;\n}\n\nexport type OverviewMapPosition =\n\t| \"bottom-right\"\n\t| \"bottom-left\"\n\t| \"top-right\"\n\t| \"top-left\";\n\nexport interface OverviewMapOptions {\n\twidth: number;\n\theight: number;\n\tmargin: number;\n\tposition: OverviewMapPosition;\n\tborderRadius: number;\n\tborderWidth: number;\n\tbackgroundColor: string;\n\tborderColor: string;\n\tviewportStrokeColor: string;\n\tviewportFillColor: string;\n\tinteractive: boolean;\n\tshowThumbnail: boolean;\n\tmaxThumbnailTiles: number;\n}\n\nexport interface OverviewMapProps {\n\tsource: WsiImageSource;\n\tprojectorRef: RefObject<OverviewMapProjector | null>;\n\tauthToken?: string;\n\toptions?: Partial<OverviewMapOptions>;\n\tinvalidateRef?: MutableRefObject<(() => void) | null>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n\twidth: 220,\n\theight: 140,\n\tmargin: 16,\n\tposition: \"bottom-right\",\n\tborderRadius: 10,\n\tborderWidth: 1.5,\n\tbackgroundColor: \"rgba(4, 10, 18, 0.88)\",\n\tborderColor: \"rgba(230, 244, 255, 0.35)\",\n\tviewportStrokeColor: \"rgba(255, 106, 61, 0.95)\",\n\tviewportFillColor: \"rgba(255, 106, 61, 0.2)\",\n\tinteractive: true,\n\tshowThumbnail: true,\n\tmaxThumbnailTiles: 16,\n};\n\nfunction toPositiveNumber(\n\tvalue: number | undefined,\n\tfallback: number,\n\tmin = 1,\n): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.max(min, value);\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n\treturn (\n\t\tArray.isArray(bounds) &&\n\t\tbounds.length === 4 &&\n\t\tNumber.isFinite(bounds[0]) &&\n\t\tNumber.isFinite(bounds[1]) &&\n\t\tNumber.isFinite(bounds[2]) &&\n\t\tNumber.isFinite(bounds[3])\n\t);\n}\n\nexport function OverviewMap({\n\tsource,\n\tprojectorRef,\n\tauthToken = \"\",\n\toptions,\n\tinvalidateRef,\n\tclassName,\n\tstyle,\n}: OverviewMapProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n\tconst lastBoundsRef = useRef<Bounds | null>(null);\n\tconst draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n\t\tactive: false,\n\t\tpointerId: null,\n\t});\n\tconst rafRef = useRef<number | null>(null);\n\tconst drawPendingRef = useRef(false);\n\n\tconst width = toPositiveNumber(\n\t\toptions?.width,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.width,\n\t\t64,\n\t);\n\tconst height = toPositiveNumber(\n\t\toptions?.height,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.height,\n\t\t48,\n\t);\n\tconst margin = toPositiveNumber(\n\t\toptions?.margin,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.margin,\n\t\t0,\n\t);\n\tconst borderRadius = toPositiveNumber(\n\t\toptions?.borderRadius,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius,\n\t\t0,\n\t);\n\tconst borderWidth = toPositiveNumber(\n\t\toptions?.borderWidth,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth,\n\t\t0,\n\t);\n\tconst maxThumbnailTiles = Math.max(\n\t\t1,\n\t\tMath.round(\n\t\t\ttoPositiveNumber(\n\t\t\t\toptions?.maxThumbnailTiles,\n\t\t\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles,\n\t\t\t\t1,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst backgroundColor =\n\t\toptions?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n\tconst borderColor =\n\t\toptions?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n\tconst viewportStrokeColor =\n\t\toptions?.viewportStrokeColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportStrokeColor;\n\tconst viewportFillColor =\n\t\toptions?.viewportFillColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n\tconst interactive =\n\t\toptions?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n\tconst showThumbnail =\n\t\toptions?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n\tconst position =\n\t\toptions?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n\n\tconst mergedStyle = useMemo<CSSProperties>(() => {\n\t\tconst pos: CSSProperties = {};\n\t\tif (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n\t\telse pos.right = margin;\n\t\tif (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n\t\telse pos.bottom = margin;\n\n\t\treturn {\n\t\t\tposition: \"absolute\",\n\t\t\t...pos,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tborderRadius,\n\t\t\toverflow: \"hidden\",\n\t\t\tzIndex: 4,\n\t\t\tpointerEvents: interactive ? \"auto\" : \"none\",\n\t\t\ttouchAction: \"none\",\n\t\t\tboxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n\t\t\t...style,\n\t\t};\n\t}, [margin, position, width, height, borderRadius, interactive, style]);\n\n\tconst draw = useCallback(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst ctx = canvas.getContext(\"2d\");\n\t\tif (!ctx) return;\n\n\t\tconst cssW = width;\n\t\tconst cssH = height;\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\t\tif (canvas.width !== pixelW || canvas.height !== pixelH) {\n\t\t\tcanvas.width = pixelW;\n\t\t\tcanvas.height = pixelH;\n\t\t}\n\n\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, cssW, cssH);\n\n\t\tconst preview = thumbnailRef.current;\n\t\tif (preview) {\n\t\t\tctx.drawImage(preview, 0, 0, cssW, cssH);\n\t\t}\n\n\t\tctx.strokeStyle = borderColor;\n\t\tctx.lineWidth = borderWidth;\n\t\tctx.strokeRect(\n\t\t\tborderWidth * 0.5,\n\t\t\tborderWidth * 0.5,\n\t\t\tcssW - borderWidth,\n\t\t\tcssH - borderWidth,\n\t\t);\n\n\t\tconst projector = projectorRef.current;\n\t\tconst bounds = projector?.getViewBounds?.();\n\t\tconst corners = projector?.getViewCorners?.();\n\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t? bounds\n\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t? lastBoundsRef.current\n\t\t\t\t: null;\n\t\tif (!safeBounds) return;\n\t\tlastBoundsRef.current = safeBounds;\n\n\t\tconst sx = cssW / Math.max(1, source.width);\n\t\tconst sy = cssH / Math.max(1, source.height);\n\n\t\tconst safeCorners =\n\t\t\tArray.isArray(corners) &&\n\t\t\tcorners.length >= 4 &&\n\t\t\tcorners.every(\n\t\t\t\t(point) =>\n\t\t\t\t\tArray.isArray(point) &&\n\t\t\t\t\tpoint.length >= 2 &&\n\t\t\t\t\tNumber.isFinite(point[0]) &&\n\t\t\t\t\tNumber.isFinite(point[1]),\n\t\t\t)\n\t\t\t\t? (corners as Array<[number, number]>)\n\t\t\t\t: null;\n\n\t\tif (safeCorners) {\n\t\t\tctx.beginPath();\n\t\t\tfor (let i = 0; i < safeCorners.length; i += 1) {\n\t\t\t\tconst point = safeCorners[i];\n\t\t\t\tconst x = clamp(point[0] * sx, 0, cssW);\n\t\t\t\tconst y = clamp(point[1] * sy, 0, cssH);\n\t\t\t\tif (i === 0) ctx.moveTo(x, y);\n\t\t\t\telse ctx.lineTo(x, y);\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t\tctx.fillStyle = viewportFillColor;\n\t\t\tctx.fill();\n\t\t\tctx.strokeStyle = viewportStrokeColor;\n\t\t\tctx.lineWidth = 1.5;\n\t\t\tctx.stroke();\n\t\t\treturn;\n\t\t}\n\n\t\tconst left = clamp(safeBounds[0] * sx, 0, cssW);\n\t\tconst top = clamp(safeBounds[1] * sy, 0, cssH);\n\t\tconst right = clamp(safeBounds[2] * sx, 0, cssW);\n\t\tconst bottom = clamp(safeBounds[3] * sy, 0, cssH);\n\t\tconst rectW = Math.max(1, right - left);\n\t\tconst rectH = Math.max(1, bottom - top);\n\n\t\tctx.fillStyle = viewportFillColor;\n\t\tctx.fillRect(left, top, rectW, rectH);\n\n\t\tctx.strokeStyle = viewportStrokeColor;\n\t\tctx.lineWidth = 1.5;\n\t\tctx.strokeRect(\n\t\t\tleft + 0.5,\n\t\t\ttop + 0.5,\n\t\t\tMath.max(1, rectW - 1),\n\t\t\tMath.max(1, rectH - 1),\n\t\t);\n\t}, [\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tborderWidth,\n\t\tprojectorRef,\n\t\tsource.width,\n\t\tsource.height,\n\t\tviewportFillColor,\n\t\tviewportStrokeColor,\n\t]);\n\n\tconst requestDraw = useCallback(() => {\n\t\tif (drawPendingRef.current) return;\n\t\tdrawPendingRef.current = true;\n\t\trafRef.current = requestAnimationFrame(() => {\n\t\t\tdrawPendingRef.current = false;\n\t\t\trafRef.current = null;\n\t\t\tdraw();\n\t\t});\n\t}, [draw]);\n\n\tconst toWorldFromClient = useCallback(\n\t\t(clientX: number, clientY: number): [number, number] | null => {\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return null;\n\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tif (!rect.width || !rect.height) return null;\n\n\t\t\tconst nx = clamp((clientX - rect.left) / rect.width, 0, 1);\n\t\t\tconst ny = clamp((clientY - rect.top) / rect.height, 0, 1);\n\t\t\treturn [nx * source.width, ny * source.height];\n\t\t},\n\t\t[source.width, source.height],\n\t);\n\n\tconst recenterTo = useCallback(\n\t\t(worldX: number, worldY: number) => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector) return;\n\n\t\t\tif (projector.setViewCenter) {\n\t\t\t\tprojector.setViewCenter(worldX, worldY);\n\t\t\t\trequestDraw();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bounds = projector.getViewBounds?.();\n\t\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t\t? bounds\n\t\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t\t? lastBoundsRef.current\n\t\t\t\t\t: null;\n\t\t\tif (!safeBounds) return;\n\n\t\t\tconst visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n\t\t\tconst visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n\t\t\tprojector.setViewState({\n\t\t\t\toffsetX: worldX - visibleW * 0.5,\n\t\t\t\toffsetY: worldY - visibleH * 0.5,\n\t\t\t});\n\t\t\trequestDraw();\n\t\t},\n\t\t[projectorRef, requestDraw],\n\t);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!interactive) return;\n\t\t\tif (event.button !== 0) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tcanvas.setPointerCapture(event.pointerId);\n\t\t\tdraggingRef.current = { active: true, pointerId: event.pointerId };\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[interactive, toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerUp = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas && canvas.hasPointerCapture(event.pointerId)) {\n\t\t\t\ttry {\n\t\t\t\t\tcanvas.releasePointerCapture(event.pointerId);\n\t\t\t\t} catch {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\trequestDraw();\n\t\t},\n\t\t[requestDraw],\n\t);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tthumbnailRef.current = null;\n\t\trequestDraw();\n\n\t\tconst tier = 0;\n\t\tconst levelScale = 2 ** (source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(source.height / levelScale);\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\t\tconst tileCount = tilesX * tilesY;\n\n\t\tif (!showThumbnail || tileCount > maxThumbnailTiles) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst preview = document.createElement(\"canvas\");\n\t\tpreview.width = Math.max(1, Math.round(width));\n\t\tpreview.height = Math.max(1, Math.round(height));\n\t\tconst ctx = preview.getContext(\"2d\");\n\t\tif (!ctx) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, preview.width, preview.height);\n\n\t\tconst requests: Array<{\n\t\t\turl: string;\n\t\t\tbounds: Bounds;\n\t\t}> = [];\n\n\t\tfor (let y = 0; y < tilesY; y += 1) {\n\t\t\tfor (let x = 0; x < tilesX; x += 1) {\n\t\t\t\tconst left = x * source.tileSize * levelScale;\n\t\t\t\tconst top = y * source.tileSize * levelScale;\n\t\t\t\tconst right =\n\t\t\t\t\tMath.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom =\n\t\t\t\t\tMath.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\t\t\t\trequests.push({\n\t\t\t\t\turl: toTileUrl(source, tier, x, y),\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvoid Promise.allSettled(\n\t\t\trequests.map(async (tile) => {\n\t\t\t\tconst useAuthHeader = !!authToken;\n\t\t\t\tconst response = await fetch(tile.url, {\n\t\t\t\t\theaders: useAuthHeader ? { Authorization: authToken } : undefined,\n\t\t\t\t});\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\tconst bitmap = await createImageBitmap(await response.blob());\n\t\t\t\treturn { tile, bitmap };\n\t\t\t}),\n\t\t).then((results) => {\n\t\t\tif (cancelled) {\n\t\t\t\tfor (const result of results) {\n\t\t\t\t\tif (result.status === \"fulfilled\") {\n\t\t\t\t\t\tresult.value.bitmap.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sx = preview.width / Math.max(1, source.width);\n\t\t\tconst sy = preview.height / Math.max(1, source.height);\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.status !== \"fulfilled\") continue;\n\t\t\t\tconst {\n\t\t\t\t\ttile: { bounds },\n\t\t\t\t\tbitmap,\n\t\t\t\t} = result.value;\n\t\t\t\tconst dx = bounds[0] * sx;\n\t\t\t\tconst dy = bounds[1] * sy;\n\t\t\t\tconst dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n\t\t\t\tconst dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n\t\t\t\tctx.drawImage(bitmap, dx, dy, dw, dh);\n\t\t\t\tbitmap.close();\n\t\t\t}\n\n\t\t\tthumbnailRef.current = preview;\n\t\t\trequestDraw();\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [\n\t\tsource,\n\t\tauthToken,\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tshowThumbnail,\n\t\tmaxThumbnailTiles,\n\t\trequestDraw,\n\t]);\n\n\tuseEffect(() => {\n\t\trequestDraw();\n\t}, [requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!invalidateRef) return undefined;\n\t\tinvalidateRef.current = requestDraw;\n\t\treturn () => {\n\t\t\tif (invalidateRef.current === requestDraw) {\n\t\t\t\tinvalidateRef.current = null;\n\t\t\t}\n\t\t};\n\t}, [invalidateRef, requestDraw]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\tif (rafRef.current !== null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tdrawPendingRef.current = false;\n\t\t},\n\t\t[],\n\t);\n\n\treturn (\n\t\t<canvas\n\t\t\tref={canvasRef}\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerCancel={handlePointerUp}\n\t\t\tonContextMenu={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t}}\n\t\t\tonWheel={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}}\n\t\t/>\n\t);\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 type { WsiPointData } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiPolygon = RoiCoordinate[];\n\ninterface PreparedPolygon {\n\tring: RoiPolygon;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\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),\n\t);\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n\tif (!Array.isArray(coords) || coords.length < 3) return [];\n\tconst out = coords.map(([x, y]) => [x, y] as RoiCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n\tconst prepared: PreparedPolygon[] = [];\n\tfor (const poly of polygons ?? []) {\n\t\tconst ring = closeRing(poly);\n\t\tif (ring.length < 4) continue;\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n\t\tprepared.push({ ring, minX, minY, maxX, maxY });\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): 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\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction isInsideAnyPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: PreparedPolygon[],\n): boolean {\n\tfor (const poly of polygons) {\n\t\tif (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (isInsideRing(x, y, poly.ring)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nexport function filterPointDataByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): WsiPointData | null {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn null;\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tpositions: new Float32Array(0),\n\t\t\tpaletteIndices: new Uint16Array(0),\n\t\t};\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tconst positions = pointData.positions;\n\tconst terms = pointData.paletteIndices;\n\tconst pointIds =\n\t\tpointData.ids instanceof Uint32Array && pointData.ids.length >= count\n\t\t\t? pointData.ids\n\t\t\t: null;\n\n\tconst nextPositions = new Float32Array(count * 2);\n\tconst nextTerms = new Uint16Array(count);\n\tconst nextIds = pointIds ? new Uint32Array(count) : null;\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tnextPositions[cursor * 2] = x;\n\t\tnextPositions[cursor * 2 + 1] = y;\n\t\tnextTerms[cursor] = terms[i];\n\t\tif (nextIds) {\n\t\t\tnextIds[cursor] = pointIds![i];\n\t\t}\n\t\tcursor += 1;\n\t}\n\n\tconst output: WsiPointData = {\n\t\tcount: cursor,\n\t\tpositions: nextPositions.subarray(0, cursor * 2),\n\t\tpaletteIndices: nextTerms.subarray(0, cursor),\n\t};\n\tif (nextIds) {\n\t\toutput.ids = nextIds.subarray(0, cursor);\n\t}\n\treturn output;\n}\n\nexport function filterPointIndicesByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): Uint32Array {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tif (count === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positions = pointData.positions;\n\tconst out = new Uint32Array(count);\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tout[cursor] = i;\n\t\tcursor += 1;\n\t}\n\n\treturn 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\tctx.device.queue.writeBuffer(\n\t\tpositionsBuffer,\n\t\t0,\n\t\tpositions.buffer,\n\t\tpositions.byteOffset,\n\t\tpositionBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tboundsBuffer,\n\t\t0,\n\t\tbounds.buffer,\n\t\tbounds.byteOffset,\n\t\tboundsBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tuniformBuffer,\n\t\t0,\n\t\tnew Uint32Array([safePointCount, boundsCount, 0, 0]),\n\t);\n\n\tconst bindGroup = ctx.device.createBindGroup({\n\t\tlayout: ctx.bindGroupLayout,\n\t\tentries: [\n\t\t\t{ binding: 0, resource: { buffer: positionsBuffer } },\n\t\t\t{ binding: 1, resource: { buffer: boundsBuffer } },\n\t\t\t{ binding: 2, resource: { buffer: outputBuffer } },\n\t\t\t{ binding: 3, resource: { buffer: uniformBuffer } },\n\t\t],\n\t});\n\n\tconst commandEncoder = ctx.device.createCommandEncoder();\n\tconst pass = commandEncoder.beginComputePass();\n\tpass.setPipeline(ctx.pipeline);\n\tpass.setBindGroup(0, bindGroup);\n\tpass.dispatchWorkgroups(Math.ceil(safePointCount / 256));\n\tpass.end();\n\n\tcommandEncoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, outputBytes);\n\tctx.device.queue.submit([commandEncoder.finish()]);\n\n\tawait readBuffer.mapAsync(GPU_MAP_MODE_READ);\n\tconst mapped = readBuffer.getMappedRange();\n\tconst out = new Uint32Array(mapped.slice(0));\n\treadBuffer.unmap();\n\n\tpositionsBuffer.destroy();\n\tboundsBuffer.destroy();\n\toutputBuffer.destroy();\n\tuniformBuffer.destroy();\n\treadBuffer.destroy();\n\n\treturn out;\n}\n","import { filterPointDataByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { WsiPointData } from \"./types\";\nimport { prefilterPointsByBoundsWebGpu } from \"./webgpu\";\n\ninterface PreparedPolygon {\n ring: RoiPolygon;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\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\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n const out = coords.map(([x, y]) => [x, y] as [number, number]);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n return out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n const prepared: PreparedPolygon[] = [];\n for (const poly of polygons ?? []) {\n const ring = closeRing(poly);\n if (ring.length < 4) continue;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of ring) {\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 if (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n prepared.push({ ring, minX, minY, maxX, maxY });\n }\n return prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): boolean {\n let inside = false;\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n const xi = ring[i][0];\n const yi = ring[i][1];\n const xj = ring[j][0];\n const yj = ring[j][1];\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi || Number.EPSILON) + xi;\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\nfunction isInsideAnyPolygon(x: number, y: number, polygons: PreparedPolygon[]): boolean {\n for (const poly of polygons) {\n if (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n continue;\n }\n if (isInsideRing(x, y, poly.ring)) {\n return true;\n }\n }\n return false;\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 = preparePolygons(polygons ?? []);\n if (prepared.length === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\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 = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids : null;\n if (safeCount === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\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 poly = prepared[i];\n bboxFlat[base] = poly.minX;\n bboxFlat[base + 1] = poly.minY;\n bboxFlat[base + 2] = poly.maxX;\n bboxFlat[base + 3] = poly.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 (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 return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n ...(pointIds ? { ids: new Uint32Array(0) } : {}),\n },\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 (!isInsideAnyPolygon(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 (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 nextTerms = new Uint16Array(candidateCount);\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 (!isInsideAnyPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextTerms[cursor] = pointData.paletteIndices[pointIndex];\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: nextTerms.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","import { filterPointDataByPolygons, filterPointIndicesByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { RoiClipWorkerRequest, RoiClipWorkerResponse } from \"./point-clip-worker-protocol\";\nimport type { WsiPointData } from \"./types\";\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\nlet workerInstance: Worker | null = null;\nlet workerSupported = true;\nlet requestId = 1;\nconst pendingById = new Map<number, PendingWorkerRequest>();\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction createWorker(): Worker | null {\n if (!workerSupported) return null;\n if (workerInstance) return workerInstance;\n try {\n const worker = new Worker(new URL(\"../workers/roi-clip-worker.ts\", import.meta.url), { type: \"module\" });\n worker.addEventListener(\"message\", handleWorkerMessage);\n worker.addEventListener(\"error\", handleWorkerError);\n workerInstance = worker;\n return worker;\n } catch {\n workerSupported = false;\n return null;\n }\n}\n\nfunction handleWorkerMessage(event: MessageEvent<RoiClipWorkerResponse>): void {\n const msg = event.data;\n if (!msg) return;\n const pending = pendingById.get(msg.id);\n if (!pending) return;\n pendingById.delete(msg.id);\n\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: Number.isFinite(msg.durationMs) ? msg.durationMs : 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 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 (ids) {\n output.ids = ids.subarray(0, count);\n }\n\n pending.resolve({\n data: output,\n meta: {\n mode: \"worker\",\n durationMs: Number.isFinite(msg.durationMs) ? msg.durationMs : nowMs() - pending.startMs,\n },\n });\n}\n\nfunction handleWorkerError(): void {\n workerSupported = false;\n if (workerInstance) {\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n }\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker crashed\"));\n }\n pendingById.clear();\n}\n\nexport function terminateRoiClipWorker(): void {\n if (!workerInstance) return;\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker terminated\"));\n }\n pendingById.clear();\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 worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n data: filterPointDataByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const termsCopy = pointData.paletteIndices.slice(0, safeCount);\n const idsCopy = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.slice(0, safeCount) : null;\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"data\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n paletteIndices: termsCopy.buffer,\n ids: idsCopy?.buffer,\n polygons: polygons ?? [],\n };\n const transfer: Transferable[] = [positionsCopy.buffer, termsCopy.buffer];\n if (idsCopy) {\n transfer.push(idsCopy.buffer);\n }\n worker.postMessage(msg, transfer);\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 worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n indices: filterPointIndicesByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipIndexResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"index\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-index-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n polygons: polygons ?? [],\n };\n worker.postMessage(msg, [positionsCopy.buffer]);\n });\n}\n","import type { WsiPointData, WsiRegion } from \"./types\";\n\nexport interface RoiTermCount {\n\ttermId: string;\n\tpaletteIndex: number;\n\tcount: number;\n}\n\nexport interface RoiPointGroup {\n\tregionId: string | number;\n\tregionIndex: number;\n\ttotalCount: number;\n\ttermCounts: RoiTermCount[];\n}\n\nexport interface RoiPointGroupOptions {\n\tpaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n\tincludeEmptyRegions?: boolean;\n}\n\nexport interface RoiPointGroupStats {\n\tgroups: RoiPointGroup[];\n\tinputPointCount: number;\n\tpointsInsideAnyRegion: number;\n\tunmatchedPointCount: number;\n}\n\ninterface PreparedRegion {\n\tregionId: string | number;\n\tregionIndex: number;\n\tring: Array<[number, number]>;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n\tarea: number;\n}\n\nfunction closeRing(\n\tcoordinates: readonly [number, number][],\n): Array<[number, number]> {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(\n\t\t(point): [number, number] => [Number(point[0]), Number(point[1])],\n\t);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction polygonArea(ring: Array<[number, number]>): number {\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst [ax, ay] = ring[i];\n\t\tconst [bx, by] = ring[i + 1];\n\t\tsum += ax * by - bx * ay;\n\t}\n\treturn Math.abs(sum * 0.5);\n}\n\nfunction prepareRegions(regions: readonly WsiRegion[]): PreparedRegion[] {\n\tconst prepared: PreparedRegion[] = [];\n\tfor (let i = 0; i < regions.length; i += 1) {\n\t\tconst region = regions[i];\n\t\tif (!region?.coordinates?.length) continue;\n\n\t\tconst ring = closeRing(region.coordinates);\n\t\tif (ring.length < 4) continue;\n\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (\n\t\t\t!Number.isFinite(minX) ||\n\t\t\t!Number.isFinite(minY) ||\n\t\t\t!Number.isFinite(maxX) ||\n\t\t\t!Number.isFinite(maxY)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tprepared.push({\n\t\t\tregionId: region.id ?? i,\n\t\t\tregionIndex: i,\n\t\t\tring,\n\t\t\tminX,\n\t\t\tminY,\n\t\t\tmaxX,\n\t\t\tmaxY,\n\t\t\tarea: Math.max(1e-6, polygonArea(ring)),\n\t\t});\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: Array<[number, number]>): 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\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction resolveTermId(\n\tpaletteIndex: number,\n\tpaletteIndexToTermId: RoiPointGroupOptions[\"paletteIndexToTermId\"],\n): string {\n\tif (Array.isArray(paletteIndexToTermId)) {\n\t\tconst fromArray = paletteIndexToTermId[paletteIndex];\n\t\tif (typeof fromArray === \"string\" && fromArray.length > 0) return fromArray;\n\t}\n\tif (paletteIndexToTermId instanceof Map) {\n\t\tconst fromMap = paletteIndexToTermId.get(paletteIndex);\n\t\tif (typeof fromMap === \"string\" && fromMap.length > 0) return fromMap;\n\t}\n\treturn String(paletteIndex);\n}\n\nexport function computeRoiPointGroups(\n\tpointData: WsiPointData | null | undefined,\n\tregions: readonly WsiRegion[] | null | undefined,\n\toptions: RoiPointGroupOptions = {},\n): RoiPointGroupStats {\n\tconst baseCount = 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),\n\t);\n\n\tlet drawIndices: Uint32Array | null = null;\n\tif (pointData?.drawIndices instanceof Uint32Array) {\n\t\tconst source = pointData.drawIndices;\n\t\tlet valid = source.length;\n\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\tconst idx = source[i];\n\t\t\tif (idx < baseCount) continue;\n\t\t\tvalid -= 1;\n\t\t}\n\t\tif (valid === source.length) {\n\t\t\tdrawIndices = source;\n\t\t} else if (valid > 0) {\n\t\t\tconst filtered = new Uint32Array(valid);\n\t\t\tlet cursor = 0;\n\t\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\t\tconst idx = source[i];\n\t\t\t\tif (idx >= baseCount) continue;\n\t\t\t\tfiltered[cursor] = idx;\n\t\t\t\tcursor += 1;\n\t\t\t}\n\t\t\tdrawIndices = filtered;\n\t\t} else {\n\t\t\tdrawIndices = new Uint32Array(0);\n\t\t}\n\t}\n\n\tconst inputCount = drawIndices ? drawIndices.length : baseCount;\n\n\tconst preparedRegions = prepareRegions(regions ?? []);\n\tif (!pointData || inputCount === 0 || preparedRegions.length === 0) {\n\t\treturn {\n\t\t\tgroups: [],\n\t\t\tinputPointCount: inputCount,\n\t\t\tpointsInsideAnyRegion: 0,\n\t\t\tunmatchedPointCount: inputCount,\n\t\t};\n\t}\n\n\tconst regionTermCounters = new Map<number, Map<number, number>>();\n\tconst regionTotalCounters = new Map<number, number>();\n\tlet insideCount = 0;\n\n\tfor (let i = 0; i < inputCount; i += 1) {\n\t\tconst pointIndex = drawIndices ? drawIndices[i] : i;\n\t\tconst x = pointData.positions[pointIndex * 2];\n\t\tconst y = pointData.positions[pointIndex * 2 + 1];\n\t\tlet bestRegion: PreparedRegion | null = null;\n\n\t\tfor (const region of preparedRegions) {\n\t\t\tif (x < region.minX || x > region.maxX || y < region.minY || y > region.maxY) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isInsideRing(x, y, region.ring)) continue;\n\t\t\tif (!bestRegion || region.area < bestRegion.area) {\n\t\t\t\tbestRegion = region;\n\t\t\t}\n\t\t}\n\n\t\tif (!bestRegion) continue;\n\t\tinsideCount += 1;\n\n\t\tconst paletteIndex = pointData.paletteIndices[pointIndex] ?? 0;\n\t\tconst regionTermMap =\n\t\t\tregionTermCounters.get(bestRegion.regionIndex) ?? new Map<number, number>();\n\t\tregionTermMap.set(paletteIndex, (regionTermMap.get(paletteIndex) ?? 0) + 1);\n\t\tregionTermCounters.set(bestRegion.regionIndex, regionTermMap);\n\t\tregionTotalCounters.set(\n\t\t\tbestRegion.regionIndex,\n\t\t\t(regionTotalCounters.get(bestRegion.regionIndex) ?? 0) + 1,\n\t\t);\n\t}\n\n\tconst includeEmptyRegions = options.includeEmptyRegions ?? false;\n\tconst groups: RoiPointGroup[] = [];\n\tfor (const region of preparedRegions) {\n\t\tconst totalCount = regionTotalCounters.get(region.regionIndex) ?? 0;\n\t\tif (!includeEmptyRegions && totalCount <= 0) continue;\n\t\tconst termMap = regionTermCounters.get(region.regionIndex) ?? new Map();\n\t\tconst termCounts: RoiTermCount[] = Array.from(termMap.entries())\n\t\t\t.map(([paletteIndex, count]) => ({\n\t\t\t\ttermId: resolveTermId(paletteIndex, options.paletteIndexToTermId),\n\t\t\t\tpaletteIndex,\n\t\t\t\tcount,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.count - a.count || a.paletteIndex - b.paletteIndex);\n\n\t\tgroups.push({\n\t\t\tregionId: region.regionId,\n\t\t\tregionIndex: region.regionIndex,\n\t\t\ttotalCount,\n\t\t\ttermCounts,\n\t\t});\n\t}\n\n\treturn {\n\t\tgroups,\n\t\tinputPointCount: inputCount,\n\t\tpointsInsideAnyRegion: insideCount,\n\t\tunmatchedPointCount: Math.max(0, inputCount - insideCount),\n\t};\n}\n","export 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 nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\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 = window.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\twindow.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 { toTileUrl } from \"./image-info\";\nimport {\n\tTileScheduler,\n\ttype ScheduledTile,\n\ttype TileBounds,\n} from \"./tile-scheduler\";\nimport type {\n\tWsiImageSource,\n\tWsiPointData,\n\tWsiRenderStats,\n\tWsiViewState,\n} from \"./types\";\nimport { clamp, createProgram } from \"./utils\";\n\ntype Bounds = TileBounds;\n\ninterface CachedTile {\n\tkey: string;\n\ttexture: WebGLTexture;\n\tbounds: Bounds;\n\ttier: number;\n\tlastUsed: number;\n}\n\ninterface TileVertexProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tvbo: WebGLBuffer;\n\tuCamera: WebGLUniformLocation;\n\tuBounds: WebGLUniformLocation;\n\tuTexture: WebGLUniformLocation;\n}\n\ninterface PointProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tposBuffer: WebGLBuffer;\n\ttermBuffer: WebGLBuffer;\n\tindexBuffer: WebGLBuffer;\n\tpaletteTexture: WebGLTexture;\n\tuCamera: WebGLUniformLocation;\n\tuPointSize: WebGLUniformLocation;\n\tuPalette: WebGLUniformLocation;\n\tuPaletteSize: WebGLUniformLocation;\n}\n\ninterface OrthoViewport {\n\twidth: number;\n\theight: number;\n}\n\ntype WorldPoint = [number, number];\nconst DEFAULT_ROTATION_DRAG_SENSITIVITY = 0.35;\nconst MIN_POINT_SIZE_PX = 0.5;\nconst MAX_POINT_SIZE_PX = 256;\n\ninterface PointSizeStop {\n\tzoom: number;\n\tsize: number;\n}\n\nconst DEFAULT_POINT_SIZE_STOPS: readonly PointSizeStop[] = [\n\t{ zoom: 1, size: 2.8 },\n\t{ zoom: 2, size: 3.4 },\n\t{ zoom: 3, size: 4.2 },\n\t{ zoom: 4, size: 5.3 },\n\t{ zoom: 5, size: 6.8 },\n\t{ zoom: 6, size: 8.4 },\n\t{ zoom: 7, size: 9.8 },\n\t{ zoom: 8, size: 11.2 },\n\t{ zoom: 9, size: 14.0 },\n\t{ zoom: 10, size: 17.5 },\n\t{ zoom: 11, size: 22.0 },\n\t{ zoom: 12, size: 28.0 },\n];\n\nexport type PointSizeByZoom = Readonly<Record<number, number>>;\n\nexport interface WsiTileSchedulerConfig {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n}\n\nexport interface WsiTileRendererOptions {\n\tonViewStateChange?: (next: WsiViewState) => void;\n\tonStats?: (stats: WsiRenderStats) => void;\n\tauthToken?: string;\n\tpointSizeByZoom?: PointSizeByZoom;\n\tmaxCacheTiles?: number;\n\tctrlDragRotate?: boolean;\n\trotationDragSensitivityDegPerPixel?: number;\n\ttileScheduler?: WsiTileSchedulerConfig;\n\tonTileError?: (event: WsiTileErrorEvent) => void;\n\tonContextLost?: () => void;\n\tonContextRestored?: () => void;\n}\n\nexport interface WsiTileErrorEvent {\n\ttile: ScheduledTile;\n\terror: unknown;\n\tattemptCount: number;\n}\n\nclass OrthoCamera {\n\tprivate viewportWidth = 1;\n\tprivate viewportHeight = 1;\n\tprivate viewState: WsiViewState = {\n\t\tzoom: 1,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\trotationDeg: 0,\n\t};\n\n\tsetViewport(width: number, height: number): void {\n\t\tthis.viewportWidth = Math.max(1, width);\n\t\tthis.viewportHeight = Math.max(1, height);\n\t}\n\n\tgetViewport(): OrthoViewport {\n\t\treturn { width: this.viewportWidth, height: this.viewportHeight };\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tif (typeof next.zoom === \"number\") {\n\t\t\tthis.viewState.zoom = Math.max(0.0001, next.zoom);\n\t\t}\n\t\tif (typeof next.offsetX === \"number\") {\n\t\t\tthis.viewState.offsetX = next.offsetX;\n\t\t}\n\t\tif (typeof next.offsetY === \"number\") {\n\t\t\tthis.viewState.offsetY = next.offsetY;\n\t\t}\n\t\tif (typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg)) {\n\t\t\tthis.viewState.rotationDeg = next.rotationDeg;\n\t\t}\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn { ...this.viewState };\n\t}\n\n\tgetCenter(): WorldPoint {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\treturn [\n\t\t\tthis.viewState.offsetX + this.viewportWidth / (2 * zoom),\n\t\t\tthis.viewState.offsetY + this.viewportHeight / (2 * zoom),\n\t\t];\n\t}\n\n\tsetCenter(centerX: number, centerY: number): void {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tthis.viewState.offsetX = centerX - this.viewportWidth / (2 * zoom);\n\t\tthis.viewState.offsetY = centerY - this.viewportHeight / (2 * zoom);\n\t}\n\n\tscreenToWorld(screenX: number, screenY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = (screenX - this.viewportWidth * 0.5) / zoom;\n\t\tconst dy = (screenY - this.viewportHeight * 0.5) / zoom;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\treturn [centerX + dx * cos - dy * sin, centerY + dx * sin + dy * cos];\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = worldX - centerX;\n\t\tconst dy = worldY - centerY;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst rx = dx * cos + dy * sin;\n\t\tconst ry = -dx * sin + dy * cos;\n\t\treturn [\n\t\t\tthis.viewportWidth * 0.5 + rx * zoom,\n\t\t\tthis.viewportHeight * 0.5 + ry * zoom,\n\t\t];\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\tconst w = this.viewportWidth;\n\t\tconst h = this.viewportHeight;\n\t\treturn [\n\t\t\tthis.screenToWorld(0, 0),\n\t\t\tthis.screenToWorld(w, 0),\n\t\t\tthis.screenToWorld(w, h),\n\t\t\tthis.screenToWorld(0, h),\n\t\t];\n\t}\n\n\tgetMatrix(): Float32Array {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst rad = toRadians(this.viewState.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\n\t\tconst ax = (2 * zoom * cos) / this.viewportWidth;\n\t\tconst bx = (2 * zoom * sin) / this.viewportWidth;\n\t\tconst ay = (2 * zoom * sin) / this.viewportHeight;\n\t\tconst by = (-2 * zoom * cos) / this.viewportHeight;\n\t\tconst tx = -(ax * centerX + bx * centerY);\n\t\tconst ty = -(ay * centerX + by * centerY);\n\n\t\treturn new Float32Array([ax, ay, 0, bx, by, 0, tx, ty, 1]);\n\t}\n}\n\nfunction toRadians(deg: number): number {\n\treturn (deg * Math.PI) / 180;\n}\n\nfunction nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nfunction requireUniformLocation(\n\tgl: WebGL2RenderingContext,\n\tprogram: WebGLProgram,\n\tname: string,\n): WebGLUniformLocation {\n\tconst location = gl.getUniformLocation(program, name);\n\tif (!location) {\n\t\tthrow new Error(`uniform location lookup failed: ${name}`);\n\t}\n\treturn location;\n}\n\nfunction isSameArrayView(\n\ta: ArrayBufferView | null | undefined,\n\tb: ArrayBufferView | null | undefined,\n): boolean {\n\tif (!a || !b) return a === b;\n\treturn (\n\t\ta.buffer === b.buffer &&\n\t\ta.byteOffset === b.byteOffset &&\n\t\ta.byteLength === b.byteLength\n\t);\n}\n\nfunction clonePointSizeStops(stops: readonly PointSizeStop[]): PointSizeStop[] {\n\treturn stops.map(stop => ({ zoom: stop.zoom, size: stop.size }));\n}\n\nfunction normalizePointSizeStops(pointSizeByZoom: PointSizeByZoom | null | undefined): PointSizeStop[] {\n\tif (!pointSizeByZoom) return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\n\tconst parsed = new Map<number, number>();\n\tfor (const [zoomKey, rawSize] of Object.entries(pointSizeByZoom)) {\n\t\tconst zoom = Number(zoomKey);\n\t\tconst size = Number(rawSize);\n\t\tif (!Number.isFinite(zoom) || !Number.isFinite(size) || size <= 0) continue;\n\t\tparsed.set(zoom, size);\n\t}\n\n\tif (parsed.size === 0) {\n\t\treturn clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\t}\n\n\treturn Array.from(parsed.entries())\n\t\t.sort((a, b) => a[0] - b[0])\n\t\t.map(([zoom, size]) => ({ zoom, size }));\n}\n\nfunction arePointSizeStopsEqual(a: readonly PointSizeStop[], b: readonly PointSizeStop[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tif (a[i].zoom !== b[i].zoom || a[i].size !== b[i].size) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction resolvePointSizeByZoomStops(continuousZoom: number, stops: readonly PointSizeStop[]): number {\n\tif (!Number.isFinite(continuousZoom)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n\tif (stops.length === 0) return MIN_POINT_SIZE_PX;\n\tif (stops.length === 1) return stops[0].size;\n\tif (continuousZoom <= stops[0].zoom) return stops[0].size;\n\n\tfor (let i = 1; i < stops.length; i += 1) {\n\t\tconst prev = stops[i - 1];\n\t\tconst next = stops[i];\n\t\tif (continuousZoom > next.zoom) continue;\n\t\tconst span = Math.max(1e-6, next.zoom - prev.zoom);\n\t\tconst t = clamp((continuousZoom - prev.zoom) / span, 0, 1);\n\t\treturn prev.size + (next.size - prev.size) * t;\n\t}\n\n\tconst last = stops[stops.length - 1];\n\tconst prev = stops[stops.length - 2];\n\tconst span = Math.max(1e-6, last.zoom - prev.zoom);\n\tconst slope = (last.size - prev.size) / span;\n\treturn last.size + (continuousZoom - last.zoom) * slope;\n}\n\nexport class WsiTileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly source: WsiImageSource;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly onViewStateChange?: (next: WsiViewState) => void;\n\tprivate readonly onStats?: (stats: WsiRenderStats) => void;\n\tprivate readonly onTileError?: (event: WsiTileErrorEvent) => void;\n\tprivate readonly onContextLost?: () => void;\n\tprivate readonly onContextRestored?: () => void;\n\tprivate readonly resizeObserver: ResizeObserver;\n\tprivate tileProgram: TileVertexProgram;\n\tprivate pointProgram: PointProgram;\n\tprivate readonly tileScheduler: TileScheduler;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate contextLost = false;\n\tprivate frame: number | null = null;\n\tprivate frameSerial = 0;\n\tprivate dragging = false;\n\tprivate interactionMode: \"none\" | \"pan\" | \"rotate\" = \"none\";\n\tprivate rotateLastAngleRad: number | null = null;\n\tprivate pointerId: number | null = null;\n\tprivate lastPointerX = 0;\n\tprivate lastPointerY = 0;\n\tprivate interactionLocked = false;\n\tprivate ctrlDragRotate = true;\n\tprivate rotationDragSensitivityDegPerPixel = 0.35;\n\tprivate maxCacheTiles: number;\n\tprivate fitZoom = 1;\n\tprivate minZoom = 1e-6;\n\tprivate maxZoom = 1;\n\tprivate currentTier = 0;\n\tprivate pointCount = 0;\n\tprivate usePointIndices = false;\n\tprivate pointBuffersDirty = true;\n\tprivate pointPaletteSize = 1;\n\tprivate pointSizeStops: PointSizeStop[] = clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\tprivate lastPointData: WsiPointData | null = null;\n\tprivate lastPointPalette: Uint8Array | null = null;\n\tprivate cache = new Map<string, CachedTile>();\n\n\tprivate readonly boundPointerDown: (event: PointerEvent) => void;\n\tprivate readonly boundPointerMove: (event: PointerEvent) => void;\n\tprivate readonly boundPointerUp: (event: PointerEvent) => void;\n\tprivate readonly boundWheel: (event: WheelEvent) => void;\n\tprivate readonly boundDoubleClick: (event: MouseEvent) => void;\n\tprivate readonly boundContextMenu: (event: MouseEvent) => void;\n\tprivate readonly boundContextLost: (event: Event) => void;\n\tprivate readonly boundContextRestored: (event: Event) => void;\n\n\tconstructor(\n\t\tcanvas: HTMLCanvasElement,\n\t\tsource: WsiImageSource,\n\t\toptions: WsiTileRendererOptions = {},\n\t) {\n\t\tthis.canvas = canvas;\n\t\tthis.source = source;\n\t\tthis.onViewStateChange = options.onViewStateChange;\n\t\tthis.onStats = options.onStats;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onContextLost = options.onContextLost;\n\t\tthis.onContextRestored = options.onContextRestored;\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.maxCacheTiles = Math.max(32, Math.floor(options.maxCacheTiles ?? 320));\n\t\tthis.ctrlDragRotate = options.ctrlDragRotate ?? true;\n\t\tthis.rotationDragSensitivityDegPerPixel =\n\t\t\ttypeof options.rotationDragSensitivityDegPerPixel === \"number\" &&\n\t\t\tNumber.isFinite(options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t? Math.max(0, options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t: DEFAULT_ROTATION_DRAG_SENSITIVITY;\n\t\tthis.pointSizeStops = normalizePointSizeStops(options.pointSizeByZoom);\n\n\t\tconst gl = canvas.getContext(\"webgl2\", {\n\t\t\talpha: false,\n\t\t\tantialias: false,\n\t\t\tdepth: false,\n\t\t\tstencil: false,\n\t\t\tpowerPreference: \"high-performance\",\n\t\t});\n\t\tif (!gl) {\n\t\t\tthrow new Error(\"WebGL2 not supported\");\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.tileScheduler = new TileScheduler({\n\t\t\tauthToken: this.authToken,\n\t\t\tmaxConcurrency: options.tileScheduler?.maxConcurrency ?? 12,\n\t\t\tmaxRetries: options.tileScheduler?.maxRetries ?? 2,\n\t\t\tretryBaseDelayMs: options.tileScheduler?.retryBaseDelayMs ?? 120,\n\t\t\tretryMaxDelayMs: options.tileScheduler?.retryMaxDelayMs ?? 1200,\n\t\t\tonTileLoad: (tile, bitmap) => this.handleTileLoaded(tile, bitmap),\n\t\t\tonTileError: (tile, error, attemptCount) => {\n\t\t\t\tthis.onTileError?.({ tile, error, attemptCount });\n\t\t\t\tconsole.warn(\"tile load failed\", tile.url, error);\n\t\t\t},\n\t\t});\n\n\t\tthis.resizeObserver = new ResizeObserver(() => this.resize());\n\t\tthis.resizeObserver.observe(canvas);\n\n\t\tthis.boundPointerDown = (event: PointerEvent) => this.onPointerDown(event);\n\t\tthis.boundPointerMove = (event: PointerEvent) => this.onPointerMove(event);\n\t\tthis.boundPointerUp = (event: PointerEvent) => this.onPointerUp(event);\n\t\tthis.boundWheel = (event: WheelEvent) => this.onWheel(event);\n\t\tthis.boundDoubleClick = (event: MouseEvent) => this.onDoubleClick(event);\n\t\tthis.boundContextMenu = (event: MouseEvent) => this.onContextMenu(event);\n\t\tthis.boundContextLost = (event: Event) => this.onWebGlContextLost(event);\n\t\tthis.boundContextRestored = (event: Event) =>\n\t\t\tthis.onWebGlContextRestored(event);\n\n\t\tcanvas.addEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tcanvas.addEventListener(\"pointermove\", this.boundPointerMove);\n\t\tcanvas.addEventListener(\"pointerup\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"wheel\", this.boundWheel, { passive: false });\n\t\tcanvas.addEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tcanvas.addEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tcanvas.addEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tcanvas.addEventListener(\"webglcontextrestored\", this.boundContextRestored);\n\n\t\tthis.fitToImage();\n\t\tthis.resize();\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t\tthis.tileScheduler.setAuthToken(this.authToken);\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tconst normalized: Partial<WsiViewState> = { ...next };\n\t\tif (typeof normalized.zoom === \"number\") {\n\t\t\tnormalized.zoom = clamp(normalized.zoom, this.minZoom, this.maxZoom);\n\t\t}\n\t\tthis.camera.setViewState(normalized);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tsetPointPalette(colors: Uint8Array | null | undefined): void {\n\t\tif (!colors || colors.length === 0) {\n\t\t\tthis.lastPointPalette = null;\n\t\t\treturn;\n\t\t}\n\t\tthis.lastPointPalette = new Uint8Array(colors);\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\t\tconst gl = this.gl;\n\t\tconst paletteSize = Math.max(1, Math.floor(this.lastPointPalette.length / 4));\n\t\tthis.pointPaletteSize = paletteSize;\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.pointProgram.paletteTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tpaletteSize,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tthis.lastPointPalette,\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tthis.requestRender();\n\t}\n\n\tsetPointData(points: WsiPointData | null | undefined): void {\n\t\tif (!points || !points.count || !points.positions || !points.paletteIndices) {\n\t\t\tthis.lastPointData = null;\n\t\t\tthis.pointCount = 0;\n\t\t\tthis.usePointIndices = false;\n\t\t\tthis.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst safeCount = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tpoints.count,\n\t\t\t\tMath.floor(points.positions.length / 2),\n\t\t\t\tpoints.paletteIndices.length,\n\t\t\t),\n\t\t);\n\t\tconst nextPositions = points.positions.subarray(0, safeCount * 2);\n\t\tconst nextPaletteIndices = points.paletteIndices.subarray(0, safeCount);\n\t\tconst hasDrawIndices = points.drawIndices instanceof Uint32Array;\n\t\tconst nextDrawIndices = hasDrawIndices\n\t\t\t? this.sanitizeDrawIndices(points.drawIndices as Uint32Array, safeCount)\n\t\t\t: null;\n\t\tconst prev = this.lastPointData;\n\t\tlet geometryChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t!prev ||\n\t\t\tprev.count !== safeCount ||\n\t\t\t!isSameArrayView(prev.positions, nextPositions) ||\n\t\t\t!isSameArrayView(prev.paletteIndices, nextPaletteIndices);\n\t\tlet drawIndicesChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t(hasDrawIndices &&\n\t\t\t\t(!prev?.drawIndices ||\n\t\t\t\t\t!isSameArrayView(prev.drawIndices, nextDrawIndices))) ||\n\t\t\t(!hasDrawIndices && !!prev?.drawIndices);\n\n\t\tthis.lastPointData = {\n\t\t\tcount: safeCount,\n\t\t\tpositions: nextPositions,\n\t\t\tpaletteIndices: nextPaletteIndices,\n\t\t\tdrawIndices: hasDrawIndices ? nextDrawIndices ?? undefined : undefined,\n\t\t};\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\n\t\tconst gl = this.gl;\n\t\tif (geometryChanged) {\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.posBuffer);\n\t\t\tgl.bufferData(gl.ARRAY_BUFFER, this.lastPointData.positions, gl.STATIC_DRAW);\n\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.termBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ARRAY_BUFFER,\n\t\t\t\tthis.lastPointData.paletteIndices,\n\t\t\t\tgl.STATIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\t}\n\n\t\tif (hasDrawIndices && drawIndicesChanged) {\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.pointProgram.indexBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ELEMENT_ARRAY_BUFFER,\n\t\t\t\tnextDrawIndices ?? new Uint32Array(0),\n\t\t\t\tgl.DYNAMIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\t\t}\n\n\t\tthis.usePointIndices = hasDrawIndices;\n\t\tthis.pointCount = hasDrawIndices\n\t\t\t? (nextDrawIndices?.length ?? 0)\n\t\t\t: this.lastPointData.count;\n\t\tif (geometryChanged || drawIndicesChanged) {\n\t\t\tthis.pointBuffersDirty = false;\n\t\t}\n\t\tthis.requestRender();\n\t}\n\n\tprivate sanitizeDrawIndices(\n\t\tdrawIndices: Uint32Array,\n\t\tmaxExclusive: number,\n\t): Uint32Array {\n\t\tif (maxExclusive <= 0 || drawIndices.length === 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tlet validCount = drawIndices.length;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tif (drawIndices[i] < maxExclusive) continue;\n\t\t\tvalidCount -= 1;\n\t\t}\n\t\tif (validCount === drawIndices.length) {\n\t\t\treturn drawIndices;\n\t\t}\n\t\tif (validCount <= 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tconst filtered = new Uint32Array(validCount);\n\t\tlet cursor = 0;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tconst idx = drawIndices[i];\n\t\t\tif (idx >= maxExclusive) continue;\n\t\t\tfiltered[cursor] = idx;\n\t\t\tcursor += 1;\n\t\t}\n\t\treturn filtered;\n\t}\n\n\tsetInteractionLock(locked: boolean): void {\n\t\tconst next = Boolean(locked);\n\t\tif (this.interactionLocked === next) return;\n\t\tthis.interactionLocked = next;\n\t\tif (next) this.cancelDrag();\n\t}\n\n\tsetPointSizeByZoom(pointSizeByZoom: PointSizeByZoom | null | undefined): void {\n\t\tconst nextStops = normalizePointSizeStops(pointSizeByZoom);\n\t\tif (arePointSizeStopsEqual(this.pointSizeStops, nextStops)) return;\n\t\tthis.pointSizeStops = nextStops;\n\t\tthis.requestRender();\n\t}\n\n\tcancelDrag(): void {\n\t\tif (this.pointerId !== null && this.canvas.hasPointerCapture(this.pointerId)) {\n\t\t\ttry {\n\t\t\t\tthis.canvas.releasePointerCapture(this.pointerId);\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\t\tthis.dragging = false;\n\t\tthis.interactionMode = \"none\";\n\t\tthis.rotateLastAngleRad = null;\n\t\tthis.pointerId = null;\n\t\tthis.canvas.classList.remove(\"dragging\");\n\t}\n\n\tprivate getPointerAngleRad(clientX: number, clientY: number): number {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = clientX - rect.left - rect.width * 0.5;\n\t\tconst y = clientY - rect.top - rect.height * 0.5;\n\t\treturn Math.atan2(y, x);\n\t}\n\n\tscreenToWorld(clientX: number, clientY: number): [number, number] {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst sx = clientX - rect.left;\n\t\tconst sy = clientY - rect.top;\n\t\treturn this.camera.screenToWorld(sx, sy);\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): [number, number] {\n\t\treturn this.camera.worldToScreen(worldX, worldY);\n\t}\n\n\tsetViewCenter(worldX: number, worldY: number): void {\n\t\tif (!Number.isFinite(worldX) || !Number.isFinite(worldY)) return;\n\t\tthis.camera.setCenter(worldX, worldY);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\treturn this.camera.getViewCorners();\n\t}\n\n\tresetRotation(): void {\n\t\tconst state = this.camera.getViewState();\n\t\tif (Math.abs(state.rotationDeg) < 1e-6) return;\n\t\tthis.camera.setViewState({ rotationDeg: 0 });\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetPointSizeByZoom(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n\t\tconst size = resolvePointSizeByZoomStops(continuousZoom, this.pointSizeStops);\n\t\treturn clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n\t}\n\n\tfitToImage(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst vw = Math.max(1, rect.width || 1);\n\t\tconst vh = Math.max(1, rect.height || 1);\n\n\t\tconst zoom = Math.min(vw / this.source.width, vh / this.source.height);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tthis.fitZoom = safeZoom;\n\t\tthis.minZoom = Math.max(this.fitZoom * 0.5, 1e-6);\n\t\tthis.maxZoom = Math.max(1, this.fitZoom * 8);\n\t\tif (this.minZoom > this.maxZoom) {\n\t\t\tthis.minZoom = this.maxZoom;\n\t\t}\n\n\t\tconst visibleWorldW = vw / safeZoom;\n\t\tconst visibleWorldH = vh / safeZoom;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: clamp(safeZoom, this.minZoom, this.maxZoom),\n\t\t\toffsetX: (this.source.width - visibleWorldW) * 0.5,\n\t\t\toffsetY: (this.source.height - visibleWorldH) * 0.5,\n\t\t\trotationDeg: 0,\n\t\t});\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tzoomBy(factor: number, screenX: number, screenY: number): void {\n\t\tconst state = this.camera.getViewState();\n\t\tconst nextZoom = clamp(state.zoom * factor, this.minZoom, this.maxZoom);\n\t\tif (nextZoom === state.zoom) return;\n\n\t\tconst [worldX, worldY] = this.camera.screenToWorld(screenX, screenY);\n\n\t\tthis.camera.setViewState({ zoom: nextZoom });\n\n\t\tconst vp = this.camera.getViewport();\n\t\tconst dx = screenX - vp.width * 0.5;\n\t\tconst dy = screenY - vp.height * 0.5;\n\t\tconst rad = toRadians(this.camera.getViewState().rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n\t\tconst worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n\t\tthis.camera.setCenter(worldX - worldDx, worldY - worldDy);\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tclampViewState(): void {\n\t\tconst bounds = this.getViewBounds();\n\t\tconst visibleW = Math.max(1e-6, bounds[2] - bounds[0]);\n\t\tconst visibleH = Math.max(1e-6, bounds[3] - bounds[1]);\n\t\tconst marginX = visibleW * 0.2;\n\t\tconst marginY = visibleH * 0.2;\n\n\t\tconst [centerX, centerY] = this.camera.getCenter();\n\t\tconst halfW = visibleW * 0.5;\n\t\tconst halfH = visibleH * 0.5;\n\n\t\tconst minCenterX = halfW - marginX;\n\t\tconst maxCenterX = this.source.width - halfW + marginX;\n\t\tconst minCenterY = halfH - marginY;\n\t\tconst maxCenterY = this.source.height - halfH + marginY;\n\n\t\tconst nextCenterX =\n\t\t\tminCenterX <= maxCenterX\n\t\t\t\t? clamp(centerX, minCenterX, maxCenterX)\n\t\t\t\t: this.source.width * 0.5;\n\t\tconst nextCenterY =\n\t\t\tminCenterY <= maxCenterY\n\t\t\t\t? clamp(centerY, minCenterY, maxCenterY)\n\t\t\t\t: this.source.height * 0.5;\n\n\t\tthis.camera.setCenter(nextCenterX, nextCenterY);\n\t}\n\n\temitViewState(): void {\n\t\tthis.onViewStateChange?.(this.camera.getViewState());\n\t}\n\n\tselectTier(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst rawTier = this.source.maxTierZoom + Math.log2(zoom);\n\t\treturn clamp(Math.floor(rawTier), 0, this.source.maxTierZoom);\n\t}\n\n\tgetViewBounds(): Bounds {\n\t\tconst corners = this.camera.getViewCorners();\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of corners) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\treturn [minX, minY, maxX, maxY];\n\t}\n\n\tintersectsBounds(a: Bounds, b: Bounds): boolean {\n\t\treturn !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n\t}\n\n\tgetVisibleTiles(): ScheduledTile[] {\n\t\tconst tier = this.selectTier();\n\t\tthis.currentTier = tier;\n\n\t\tconst viewBounds = this.getViewBounds();\n\n\t\tconst levelScale = Math.pow(2, this.source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(this.source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(this.source.height / levelScale);\n\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / this.source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / this.source.tileSize));\n\n\t\tconst viewMinX = viewBounds[0];\n\t\tconst viewMinY = viewBounds[1];\n\t\tconst viewMaxX = viewBounds[2];\n\t\tconst viewMaxY = viewBounds[3];\n\n\t\tconst minTileX = clamp(\n\t\t\tMath.floor(viewMinX / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst maxTileX = clamp(\n\t\t\tMath.floor((viewMaxX - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst minTileY = clamp(\n\t\t\tMath.floor(viewMinY / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\t\tconst maxTileY = clamp(\n\t\t\tMath.floor((viewMaxY - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\n\t\tif (minTileX > maxTileX || minTileY > maxTileY) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst centerTileX = (viewMinX + viewMaxX) * 0.5 / levelScale / this.source.tileSize;\n\t\tconst centerTileY = (viewMinY + viewMaxY) * 0.5 / levelScale / this.source.tileSize;\n\n\t\tconst visible: ScheduledTile[] = [];\n\t\tfor (let y = minTileY; y <= maxTileY; y += 1) {\n\t\t\tfor (let x = minTileX; x <= maxTileX; x += 1) {\n\t\t\t\tconst left = x * this.source.tileSize * levelScale;\n\t\t\t\tconst top = y * this.source.tileSize * levelScale;\n\t\t\t\tconst right = Math.min((x + 1) * this.source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom = Math.min((y + 1) * this.source.tileSize, levelHeight) * levelScale;\n\n\t\t\t\tconst dx = x - centerTileX;\n\t\t\t\tconst dy = y - centerTileY;\n\t\t\t\tvisible.push({\n\t\t\t\t\tkey: `${tier}/${x}/${y}`,\n\t\t\t\t\ttier,\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t\tdistance2: dx * dx + dy * dy,\n\t\t\t\t\turl: toTileUrl(this.source, tier, x, y),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvisible.sort((a, b) => a.distance2 - b.distance2);\n\t\treturn visible;\n\t}\n\n\ttrimCache(): void {\n\t\tif (this.cache.size <= this.maxCacheTiles) return;\n\n\t\tconst entries = Array.from(this.cache.entries());\n\t\tentries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n\n\t\tconst removeCount = this.cache.size - this.maxCacheTiles;\n\t\tfor (let i = 0; i < removeCount; i += 1) {\n\t\t\tconst [key, value] = entries[i];\n\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\tthis.cache.delete(key);\n\t\t}\n\t}\n\n\trender(): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n\t\tconst frameStartMs = nowMs();\n\t\tthis.frameSerial += 1;\n\n\t\tconst gl = this.gl;\n\t\tconst tileProgram = this.tileProgram;\n\t\tconst pointProgram = this.pointProgram;\n\n\t\tgl.clearColor(0.03, 0.06, 0.1, 1);\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\tconst visible = this.getVisibleTiles();\n\t\tconst viewBounds = this.getViewBounds();\n\t\tconst visibleKeys = new Set(visible.map((tile) => tile.key));\n\n\t\tgl.useProgram(tileProgram.program);\n\t\tgl.bindVertexArray(tileProgram.vao);\n\t\tgl.uniformMatrix3fv(tileProgram.uCamera, false, this.camera.getMatrix());\n\t\tgl.uniform1i(tileProgram.uTexture, 0);\n\n\t\tconst fallbackTiles: CachedTile[] = [];\n\t\tfor (const [, cached] of this.cache) {\n\t\t\tif (visibleKeys.has(cached.key)) continue;\n\t\t\tif (!this.intersectsBounds(cached.bounds, viewBounds)) continue;\n\t\t\tfallbackTiles.push(cached);\n\t\t}\n\n\t\tfallbackTiles.sort((a, b) => a.tier - b.tier);\n\t\tfor (const cached of fallbackTiles) {\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tlet renderedTiles = 0;\n\t\tconst missingTiles: ScheduledTile[] = [];\n\t\tfor (const tile of visible) {\n\t\t\tconst cached = this.cache.get(tile.key);\n\t\t\tif (!cached) {\n\t\t\t\tmissingTiles.push(tile);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t\trenderedTiles += 1;\n\t\t}\n\t\tthis.tileScheduler.schedule(missingTiles);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tgl.bindVertexArray(null);\n\n\t\tlet renderedPoints = 0;\n\t\tif (this.pointCount > 0) {\n\t\t\tgl.enable(gl.BLEND);\n\t\t\tgl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\t\t\tgl.useProgram(pointProgram.program);\n\t\t\tgl.bindVertexArray(pointProgram.vao);\n\t\t\tgl.uniformMatrix3fv(pointProgram.uCamera, false, this.camera.getMatrix());\n\t\t\tgl.uniform1f(pointProgram.uPointSize, this.getPointSizeByZoom());\n\t\t\tgl.uniform1f(pointProgram.uPaletteSize, this.pointPaletteSize);\n\t\t\tgl.uniform1i(pointProgram.uPalette, 1);\n\t\t\tgl.activeTexture(gl.TEXTURE1);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, pointProgram.paletteTexture);\n\t\t\tif (this.usePointIndices) {\n\t\t\t\tgl.drawElements(gl.POINTS, this.pointCount, gl.UNSIGNED_INT, 0);\n\t\t\t} else {\n\t\t\t\tgl.drawArrays(gl.POINTS, 0, this.pointCount);\n\t\t\t}\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\t\tgl.bindVertexArray(null);\n\t\t\trenderedPoints = this.pointCount;\n\t\t}\n\n\t\tif (this.onStats) {\n\t\t\tconst schedulerStats = this.tileScheduler.getSnapshot();\n\t\t\tconst cacheHits = renderedTiles;\n\t\t\tconst cacheMisses = missingTiles.length;\n\t\t\tconst drawCalls =\n\t\t\t\tfallbackTiles.length + renderedTiles + (renderedPoints > 0 ? 1 : 0);\n\t\t\tthis.onStats({\n\t\t\t\ttier: this.currentTier,\n\t\t\t\tvisible: visible.length,\n\t\t\t\trendered: renderedTiles,\n\t\t\t\tpoints: renderedPoints,\n\t\t\t\tfallback: fallbackTiles.length,\n\t\t\t\tcache: this.cache.size,\n\t\t\t\tinflight: schedulerStats.inflight,\n\t\t\t\tqueued: schedulerStats.queued,\n\t\t\t\tretries: schedulerStats.retries,\n\t\t\t\tfailed: schedulerStats.failed,\n\t\t\t\taborted: schedulerStats.aborted,\n\t\t\t\tcacheHits,\n\t\t\t\tcacheMisses,\n\t\t\t\tdrawCalls,\n\t\t\t\tframeMs: nowMs() - frameStartMs,\n\t\t\t});\n\t\t}\n\t}\n\n\trequestRender(): void {\n\t\tif (\n\t\t\tthis.frame !== null ||\n\t\t\tthis.destroyed ||\n\t\t\tthis.contextLost ||\n\t\t\tthis.gl.isContextLost()\n\t\t)\n\t\t\treturn;\n\t\tthis.frame = requestAnimationFrame(() => {\n\t\t\tthis.frame = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tresize(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssW = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssH = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\n\t\tif (this.canvas.width !== pixelW || this.canvas.height !== pixelH) {\n\t\t\tthis.canvas.width = pixelW;\n\t\t\tthis.canvas.height = pixelH;\n\t\t}\n\n\t\tthis.camera.setViewport(cssW, cssH);\n\t\tthis.gl.viewport(0, 0, pixelW, pixelH);\n\t\tthis.requestRender();\n\t}\n\n\tonPointerDown(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst wantsRotate = this.ctrlDragRotate && (event.ctrlKey || event.metaKey);\n\t\tconst allowButton = event.button === 0 || (wantsRotate && event.button === 2);\n\t\tif (!allowButton) return;\n\t\tif (wantsRotate) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tthis.dragging = true;\n\t\tthis.interactionMode =\n\t\t\twantsRotate ? \"rotate\" : \"pan\";\n\t\tthis.pointerId = event.pointerId;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\t\tthis.rotateLastAngleRad =\n\t\t\tthis.interactionMode === \"rotate\"\n\t\t\t\t? this.getPointerAngleRad(event.clientX, event.clientY)\n\t\t\t\t: null;\n\t\tthis.canvas.classList.add(\"dragging\");\n\t\tthis.canvas.setPointerCapture(event.pointerId);\n\t}\n\n\tonPointerMove(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (!this.dragging || event.pointerId !== this.pointerId) return;\n\n\t\tconst dx = event.clientX - this.lastPointerX;\n\t\tconst dy = event.clientY - this.lastPointerY;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\n\t\tif (this.interactionMode === \"rotate\") {\n\t\t\tconst nextAngle = this.getPointerAngleRad(event.clientX, event.clientY);\n\t\t\tconst prevAngle = this.rotateLastAngleRad;\n\t\t\tthis.rotateLastAngleRad = nextAngle;\n\t\t\tif (prevAngle !== null) {\n\t\t\t\tconst rawDelta = nextAngle - prevAngle;\n\t\t\t\tconst delta = Math.atan2(Math.sin(rawDelta), Math.cos(rawDelta));\n\n\t\t\t\tconst sensitivityScale =\n\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY > 0\n\t\t\t\t\t\t? this.rotationDragSensitivityDegPerPixel /\n\t\t\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY\n\t\t\t\t\t\t: 1;\n\t\t\t\tconst state = this.camera.getViewState();\n\t\t\t\tthis.camera.setViewState({\n\t\t\t\t\trotationDeg:\n\t\t\t\t\t\tstate.rotationDeg - ((delta * 180) / Math.PI) * sensitivityScale,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tconst state = this.camera.getViewState();\n\t\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\t\tconst rad = toRadians(state.rotationDeg);\n\t\t\tconst cos = Math.cos(rad);\n\t\t\tconst sin = Math.sin(rad);\n\t\t\tconst worldDx = (dx * cos - dy * sin) / zoom;\n\t\t\tconst worldDy = (dx * sin + dy * cos) / zoom;\n\t\t\tthis.camera.setViewState({\n\t\t\t\toffsetX: state.offsetX - worldDx,\n\t\t\t\toffsetY: state.offsetY - worldDy,\n\t\t\t});\n\t\t}\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tonPointerUp(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (event.pointerId !== this.pointerId) return;\n\t\tthis.cancelDrag();\n\t}\n\n\tonWheel(event: WheelEvent): void {\n\t\tif (this.interactionLocked) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tconst factor = event.deltaY < 0 ? 1.12 : 0.89;\n\t\tthis.zoomBy(factor, x, y);\n\t}\n\n\tonDoubleClick(event: MouseEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tthis.zoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n\t}\n\n\tonContextMenu(event: MouseEvent): void {\n\t\tif (this.dragging || event.ctrlKey || event.metaKey) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\tprivate onWebGlContextLost(event: Event): void {\n\t\tevent.preventDefault();\n\t\tif (this.destroyed || this.contextLost) return;\n\t\tthis.contextLost = true;\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.clear();\n\t\tthis.cache.clear();\n\t\tthis.onContextLost?.();\n\t}\n\n\tprivate onWebGlContextRestored(_event: Event): void {\n\t\tif (this.destroyed) return;\n\t\tthis.contextLost = false;\n\t\tthis.cache.clear();\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.lastPointPalette && this.lastPointPalette.length > 0) {\n\t\t\tthis.setPointPalette(this.lastPointPalette);\n\t\t}\n\t\tif (this.lastPointData) {\n\t\t\tthis.setPointData(this.lastPointData);\n\t\t} else {\n\t\t\tthis.pointCount = 0;\n\t\t}\n\n\t\tthis.resize();\n\t\tthis.requestRender();\n\t\tthis.onContextRestored?.();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.canvas.removeEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tthis.canvas.removeEventListener(\"pointermove\", this.boundPointerMove);\n\t\tthis.canvas.removeEventListener(\"pointerup\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"wheel\", this.boundWheel);\n\t\tthis.canvas.removeEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tthis.canvas.removeEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tthis.canvas.removeEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tthis.canvas.removeEventListener(\n\t\t\t\"webglcontextrestored\",\n\t\t\tthis.boundContextRestored,\n\t\t);\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.destroy();\n\n\t\tif (!this.contextLost && !this.gl.isContextLost()) {\n\t\t\tfor (const [, value] of this.cache) {\n\t\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\t}\n\t\t\tthis.gl.deleteBuffer(this.tileProgram.vbo);\n\t\t\tthis.gl.deleteVertexArray(this.tileProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.tileProgram.program);\n\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.posBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.termBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.indexBuffer);\n\t\t\tthis.gl.deleteTexture(this.pointProgram.paletteTexture);\n\t\t\tthis.gl.deleteVertexArray(this.pointProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.pointProgram.program);\n\t\t}\n\t\tthis.cache.clear();\n\t}\n\n\tprivate initTileProgram(): TileVertexProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst 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\t\tconst fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n out vec4 outColor;\n void main() {\n outColor = texture(uTexture, vUv);\n }`;\n\n\t\tconst program = createProgram(gl, vertex, fragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uBounds = requireUniformLocation(gl, program, \"uBounds\");\n\t\tconst uTexture = requireUniformLocation(gl, program, \"uTexture\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst vbo = gl.createBuffer();\n\t\tif (!vao || !vbo) {\n\t\t\tthrow new Error(\"buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n\t\tgl.bufferData(\n\t\t\tgl.ARRAY_BUFFER,\n\t\t\tnew Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]),\n\t\t\tgl.STATIC_DRAW,\n\t\t);\n\n\t\tconst aUnit = gl.getAttribLocation(program, \"aUnit\");\n\t\tconst aUv = gl.getAttribLocation(program, \"aUv\");\n\t\tif (aUnit < 0 || aUv < 0) {\n\t\t\tthrow new Error(\"tile attribute lookup failed\");\n\t\t}\n\t\tgl.enableVertexAttribArray(aUnit);\n\t\tgl.enableVertexAttribArray(aUv);\n\t\tgl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n\t\tgl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n\t\treturn { program, vao, vbo, uCamera, uBounds, uTexture };\n\t}\n\n\tprivate initPointProgram(): PointProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aTerm;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vTerm;\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 vTerm = aTerm;\n }`;\n\n\t\tconst pointFragment = `#version 300 es\n precision highp float;\n flat in uint vTerm;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\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(vTerm), 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 ringWidth = clamp(3.0 / max(1.0, uPointSize), 0.12, 0.62);\n float innerRadius = 1.0 - ringWidth;\n float aa = 1.5 / max(1.0, uPointSize);\n\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float alpha = outerMask * innerMask * color.a;\n if (alpha <= 0.001) discard;\n\n outColor = vec4(color.rgb * alpha, alpha);\n }`;\n\n\t\tconst program = createProgram(gl, pointVertex, pointFragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uPointSize = requireUniformLocation(gl, program, \"uPointSize\");\n\t\tconst uPalette = requireUniformLocation(gl, program, \"uPalette\");\n\t\tconst uPaletteSize = requireUniformLocation(gl, program, \"uPaletteSize\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst posBuffer = gl.createBuffer();\n\t\tconst termBuffer = gl.createBuffer();\n\t\tconst indexBuffer = gl.createBuffer();\n\t\tconst paletteTexture = gl.createTexture();\n\t\tif (!vao || !posBuffer || !termBuffer || !indexBuffer || !paletteTexture) {\n\t\t\tthrow new Error(\"point buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst posLoc = gl.getAttribLocation(program, \"aPosition\");\n\t\tif (posLoc < 0) {\n\t\t\tthrow new Error(\"point position attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(posLoc);\n\t\tgl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, termBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst termLoc = gl.getAttribLocation(program, \"aTerm\");\n\t\tif (termLoc < 0) {\n\t\t\tthrow new Error(\"point term attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(termLoc);\n\t\tgl.vertexAttribIPointer(termLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\n\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, paletteTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\t1,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tnew Uint8Array([160, 160, 160, 255]),\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\n\t\treturn {\n\t\t\tprogram,\n\t\t\tvao,\n\t\t\tposBuffer,\n\t\t\ttermBuffer,\n\t\t\tindexBuffer,\n\t\t\tpaletteTexture,\n\t\t\tuCamera,\n\t\t\tuPointSize,\n\t\t\tuPalette,\n\t\t\tuPaletteSize,\n\t\t};\n\t}\n\n\tprivate handleTileLoaded(tile: ScheduledTile, bitmap: ImageBitmap): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\t\tif (this.cache.has(tile.key)) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\n\t\tconst texture = this.createTextureFromBitmap(bitmap);\n\t\tbitmap.close();\n\t\tif (!texture) return;\n\n\t\tthis.cache.set(tile.key, {\n\t\t\tkey: tile.key,\n\t\t\ttexture,\n\t\t\tbounds: tile.bounds,\n\t\t\ttier: tile.tier,\n\t\t\tlastUsed: this.frameSerial,\n\t\t});\n\t\tthis.trimCache();\n\t\tthis.requestRender();\n\t}\n\n\tprivate createTextureFromBitmap(bitmap: ImageBitmap): WebGLTexture | null {\n\t\tif (this.contextLost || this.gl.isContextLost()) return null;\n\t\tconst gl = this.gl;\n\t\tconst texture = gl.createTexture();\n\t\tif (!texture) return null;\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, texture);\n\t\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\treturn texture;\n\t}\n}\n","import { type CSSProperties, type MouseEvent as ReactMouseEvent, type MutableRefObject, type ReactNode, type PointerEvent as ReactPointerEvent, useCallback, 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 { computeRoiPointGroups, type RoiPointGroupStats } from \"../wsi/roi-term-stats\";\nimport type { WsiImageSource, WsiPointData, WsiRegion, WsiRenderStats, WsiViewState } from \"../wsi/types\";\nimport { type PointSizeByZoom, type WsiTileErrorEvent, WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { BrushOptions, DrawCoordinate, DrawOverlayShape, DrawResult, DrawTool, PatchDrawResult, RegionLabelStyle, RegionStrokeStyle, RegionStrokeStyleResolver, StampOptions } from \"./draw-layer\";\nimport { DrawLayer } from \"./draw-layer\";\nimport { OverviewMap, type OverviewMapOptions } from \"./overview-map\";\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawCoordinate[][] = [];\nconst EMPTY_CLIPPED_POINTS: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n};\nconst POINT_HIT_RADIUS_SCALE = 0.65;\nconst MIN_POINT_HIT_RADIUS_PX = 4;\nconst MIN_POINT_HIT_GRID_SIZE = 24;\nconst MAX_POINT_HIT_GRID_SIZE = 1024;\nconst POINT_HIT_GRID_DENSITY_SCALE = 4;\n\nexport interface RegionHoverEvent {\n region: WsiRegion | null;\n regionId: string | number | null;\n regionIndex: number;\n coordinate: DrawCoordinate | null;\n}\n\nexport interface RegionClickEvent {\n region: WsiRegion;\n regionId: string | number;\n regionIndex: number;\n coordinate: DrawCoordinate;\n}\n\nexport interface PointHitEvent {\n index: number;\n id: number | null;\n coordinate: DrawCoordinate;\n pointCoordinate: DrawCoordinate;\n}\n\nexport interface PointClickEvent extends PointHitEvent {\n button: number;\n}\n\nexport interface PointHoverEvent {\n index: number | null;\n id: number | null;\n coordinate: DrawCoordinate | null;\n pointCoordinate: DrawCoordinate | null;\n}\n\nexport interface PointClipStatsEvent {\n mode: PointClipMode;\n durationMs: number;\n inputCount: number;\n outputCount: number;\n polygonCount: number;\n usedWebGpu?: boolean;\n candidateCount?: number;\n bridgedToDraw?: boolean;\n}\n\nexport interface PointerWorldMoveEvent {\n coordinate: DrawCoordinate | null;\n clientX: number;\n clientY: number;\n insideImage: boolean;\n}\n\nexport interface WsiCustomLayerContext {\n source: WsiImageSource;\n viewState: WsiViewState;\n drawTool: DrawTool;\n interactionLock: boolean;\n worldToScreen: (worldX: number, worldY: number) => DrawCoordinate | null;\n screenToWorld: (clientX: number, clientY: number) => DrawCoordinate | null;\n requestRedraw: () => void;\n}\n\nexport interface WsiCustomLayer {\n id?: string | number;\n zIndex?: number;\n pointerEvents?: CSSProperties[\"pointerEvents\"];\n className?: string;\n style?: CSSProperties;\n render: (context: WsiCustomLayerContext) => ReactNode;\n}\n\ninterface PointSpatialIndex {\n cellSize: number;\n safeCount: number;\n positions: Float32Array;\n ids: Uint32Array | null;\n buckets: Map<number, Map<number, number[]>>;\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\n return Math.max(0, Math.min(Math.floor(pointData.count ?? 0), Math.floor((pointData.positions?.length ?? 0) / 2), pointData.paletteIndices?.length ?? 0));\n}\n\nfunction sanitizeDrawIndices(drawIndices: Uint32Array | undefined, maxExclusive: number): Uint32Array | null {\n if (!(drawIndices instanceof Uint32Array) || maxExclusive <= 0 || drawIndices.length === 0) {\n return null;\n }\n\n let invalidFound = false;\n for (let i = 0; i < drawIndices.length; i += 1) {\n if (drawIndices[i] < maxExclusive) continue;\n invalidFound = true;\n break;\n }\n if (!invalidFound) {\n return drawIndices;\n }\n\n const out = new Uint32Array(drawIndices.length);\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 out[cursor] = idx;\n cursor += 1;\n }\n return out.subarray(0, cursor);\n}\n\nfunction resolvePointHitGridSize(source: WsiImageSource | null, visibleCount: number): number {\n if (!source || visibleCount <= 0) return 256;\n const area = Math.max(1, source.width * source.height);\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 buildPointSpatialIndex(pointData: WsiPointData | null | undefined, source: WsiImageSource | null): PointSpatialIndex | null {\n if (!pointData || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) {\n return null;\n }\n\n const positions = pointData.positions.subarray(0, safeCount * 2);\n const ids = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.subarray(0, safeCount) : null;\n const drawIndices = sanitizeDrawIndices(pointData.drawIndices, safeCount);\n const visibleCount = drawIndices ? drawIndices.length : safeCount;\n if (visibleCount === 0) {\n return null;\n }\n\n const cellSize = resolvePointHitGridSize(source, visibleCount);\n const buckets = new Map<number, Map<number, number[]>>();\n\n const pushBucket = (pointIndex: number): void => {\n const px = positions[pointIndex * 2];\n const py = positions[pointIndex * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) return;\n\n const cellX = Math.floor(px / cellSize);\n const cellY = Math.floor(py / cellSize);\n let column = buckets.get(cellX);\n if (!column) {\n column = new Map<number, number[]>();\n buckets.set(cellX, column);\n }\n const bucket = column.get(cellY);\n if (bucket) {\n bucket.push(pointIndex);\n } else {\n column.set(cellY, [pointIndex]);\n }\n };\n\n if (drawIndices) {\n for (let i = 0; i < drawIndices.length; i += 1) {\n pushBucket(drawIndices[i] ?? 0);\n }\n } else {\n for (let i = 0; i < safeCount; i += 1) {\n pushBucket(i);\n }\n }\n\n if (buckets.size === 0) {\n return null;\n }\n\n return {\n cellSize,\n safeCount,\n positions,\n ids,\n buckets,\n };\n}\n\nfunction resolveRegionId(region: WsiRegion, index: number): string | number {\n return region.id ?? index;\n}\n\nfunction isPointInPolygon(point: DrawCoordinate, polygon: DrawCoordinate[]): boolean {\n if (!Array.isArray(polygon) || polygon.length < 3) return false;\n\n const [x, y] = point;\n let inside = false;\n\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const [xi, yi] = polygon[i];\n const [xj, yj] = polygon[j];\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / Math.max(1e-12, yj - yi) + xi;\n if (intersect) inside = !inside;\n }\n\n return inside;\n}\n\nfunction pickRegionAt(\n coord: DrawCoordinate,\n regions: WsiRegion[]\n): {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n} | null {\n for (let i = regions.length - 1; i >= 0; i -= 1) {\n const region = regions[i];\n if (!region?.coordinates?.length) continue;\n if (!isPointInPolygon(coord, region.coordinates)) continue;\n return {\n region,\n regionIndex: i,\n regionId: resolveRegionId(region, i),\n };\n }\n return null;\n}\n\nexport interface WsiViewerCanvasProps {\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 debugOverlay?: boolean;\n debugOverlayStyle?: CSSProperties;\n fitNonce?: number;\n rotationResetNonce?: number;\n authToken?: string;\n ctrlDragRotate?: boolean;\n pointData?: WsiPointData | null;\n pointPalette?: Uint8Array | null;\n pointSizeByZoom?: PointSizeByZoom;\n roiRegions?: WsiRegion[];\n roiPolygons?: DrawCoordinate[][];\n clipPointsToRois?: boolean;\n clipMode?: PointClipMode;\n onClipStats?: (event: PointClipStatsEvent) => void;\n onRoiPointGroups?: (stats: RoiPointGroupStats) => void;\n roiPaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n interactionLock?: boolean;\n drawTool?: DrawTool;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n customLayers?: WsiCustomLayer[];\n patchRegions?: WsiRegion[];\n regionLabelStyle?: Partial<RegionLabelStyle>;\n onPointerWorldMove?: (event: PointerWorldMoveEvent) => void;\n onPointHover?: (event: PointHoverEvent) => void;\n onPointClick?: (event: PointClickEvent) => void;\n onRegionHover?: (event: RegionHoverEvent) => void;\n onRegionClick?: (event: RegionClickEvent) => void;\n onActiveRegionChange?: (regionId: string | number | null) => void;\n getCellByCoordinatesRef?: MutableRefObject<((coordinate: DrawCoordinate) => PointHitEvent | null) | null>;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n showOverviewMap?: boolean;\n overviewMapOptions?: Partial<OverviewMapOptions>;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function WsiViewerCanvas({\n source,\n viewState,\n onViewStateChange,\n onStats,\n onTileError,\n onContextLost,\n onContextRestored,\n debugOverlay = false,\n debugOverlayStyle,\n fitNonce = 0,\n rotationResetNonce = 0,\n authToken = \"\",\n ctrlDragRotate = true,\n pointData = null,\n pointPalette = null,\n pointSizeByZoom,\n roiRegions,\n roiPolygons,\n clipPointsToRois = false,\n clipMode = \"worker\",\n onClipStats,\n onRoiPointGroups,\n roiPaletteIndexToTermId,\n interactionLock = false,\n drawTool = \"cursor\",\n stampOptions,\n brushOptions,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n customLayers,\n patchRegions,\n regionLabelStyle,\n onPointerWorldMove,\n onPointHover,\n onPointClick,\n onRegionHover,\n onRegionClick,\n onActiveRegionChange,\n getCellByCoordinatesRef,\n onDrawComplete,\n onPatchComplete,\n showOverviewMap = false,\n overviewMapOptions,\n className,\n style,\n}: WsiViewerCanvasProps): React.ReactElement {\n const canvasRef = 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 onViewStateChangeRef = useRef<typeof onViewStateChange>(onViewStateChange);\n const onStatsRef = useRef<typeof onStats>(onStats);\n const debugOverlayRef = useRef(debugOverlay);\n const [isOverviewOpen, setIsOverviewOpen] = useState(true);\n const [hoveredRegionId, setHoveredRegionId] = useState<string | number | null>(null);\n const [activeRegionId, setActiveRegionId] = useState<string | number | null>(null);\n const [customLayerViewState, setCustomLayerViewState] = useState<WsiViewState | null>(null);\n const [debugStats, setDebugStats] = useState<WsiRenderStats | null>(null);\n const hoveredRegionIdRef = useRef<string | number | null>(null);\n const hoveredPointIndexRef = useRef<number | null>(null);\n const hoveredPointIdRef = useRef<number | null>(null);\n const clipRunIdRef = useRef(0);\n const safeRoiRegions = roiRegions ?? EMPTY_ROI_REGIONS;\n const safePatchRegions = patchRegions ?? EMPTY_ROI_REGIONS;\n const safeRoiPolygons = roiPolygons ?? EMPTY_ROI_POLYGONS;\n const shouldTrackCustomLayerViewState = (customLayers?.length ?? 0) > 0;\n\n const mergedStyle = useMemo<CSSProperties>(() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }), [style]);\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 effectiveRoiRegions = useMemo<WsiRegion[]>(() => {\n if (safeRoiRegions.length > 0) {\n return safeRoiRegions;\n }\n if (safeRoiPolygons.length === 0) {\n return EMPTY_ROI_REGIONS;\n }\n return safeRoiPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [safeRoiRegions, safeRoiPolygons]);\n\n const clipPolygons = useMemo(() => effectiveRoiRegions.map(region => region.coordinates), [effectiveRoiRegions]);\n\n const [renderPointData, setRenderPointData] = useState<WsiPointData | null>(pointData);\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 outputCount = data?.drawIndices ? data.drawIndices.length : (data?.count ?? 0);\n setRenderPointData(data);\n onClipStats?.({\n mode: stats.mode,\n durationMs: stats.durationMs,\n inputCount: pointData.count,\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 as RoiPolygon[], { 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 as RoiPolygon[]);\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 const shouldEnablePointHitTest = Boolean(onPointHover || onPointClick || getCellByCoordinatesRef);\n const pointSpatialIndex = useMemo(() => {\n if (!shouldEnablePointHitTest) return null;\n return buildPointSpatialIndex(renderPointData, source);\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.getPointSizeByZoom();\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 = pointSpatialIndex.cellSize;\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 const column = pointSpatialIndex.buckets.get(cx);\n if (!column) continue;\n\n for (let cy = baseCellY - cellRadius; cy <= baseCellY + cellRadius; cy += 1) {\n const bucket = column.get(cy);\n if (!bucket || bucket.length === 0) continue;\n\n for (let i = 0; i < bucket.length; i += 1) {\n const pointIndex = bucket[i];\n if (pointIndex >= pointSpatialIndex.safeCount) continue;\n\n const px = pointSpatialIndex.positions[pointIndex * 2];\n const py = pointSpatialIndex.positions[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 [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 const overviewWidth = useMemo(() => {\n const value = Number(overviewMapOptions?.width ?? 220);\n return Number.isFinite(value) ? Math.max(64, value) : 220;\n }, [overviewMapOptions?.width]);\n const overviewHeight = useMemo(() => {\n const value = Number(overviewMapOptions?.height ?? 140);\n return Number.isFinite(value) ? Math.max(48, value) : 140;\n }, [overviewMapOptions?.height]);\n const overviewMargin = useMemo(() => {\n const value = Number(overviewMapOptions?.margin ?? 16);\n return Number.isFinite(value) ? Math.max(0, value) : 16;\n }, [overviewMapOptions?.margin]);\n const overviewPosition = overviewMapOptions?.position || \"bottom-right\";\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 const commitActiveRegion = useCallback(\n (next: string | number | null) => {\n setActiveRegionId(prev => {\n if (String(prev) === String(next)) {\n return prev;\n }\n onActiveRegionChange?.(next);\n return next;\n });\n },\n [onActiveRegionChange]\n );\n\n useEffect(() => {\n onViewStateChangeRef.current = onViewStateChange;\n }, [onViewStateChange]);\n\n useEffect(() => {\n onStatsRef.current = onStats;\n }, [onStats]);\n\n useEffect(() => {\n debugOverlayRef.current = debugOverlay;\n if (!debugOverlay) setDebugStats(null);\n }, [debugOverlay]);\n\n const handleRendererStats = useCallback((stats: WsiRenderStats): void => {\n onStatsRef.current?.(stats);\n if (debugOverlayRef.current) {\n setDebugStats(stats);\n }\n }, []);\n\n const debugOverlayText = useMemo(() => {\n if (!debugStats) {\n return \"stats: waiting for first frame...\";\n }\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 useEffect(() => {\n const hasActive = activeRegionId === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(activeRegionId));\n if (!hasActive && activeRegionId !== null) {\n commitActiveRegion(null);\n }\n\n const currentHover = hoveredRegionIdRef.current;\n const hasHover = currentHover === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(currentHover));\n\n if (!hasHover && currentHover !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n }, [effectiveRoiRegions, activeRegionId, onRegionHover, commitActiveRegion]);\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 const emitViewStateChange = useCallback(\n (next: WsiViewState): void => {\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(next);\n }\n const callback = onViewStateChangeRef.current;\n if (callback) {\n callback(next);\n }\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n },\n [shouldTrackCustomLayerViewState]\n );\n\n useEffect(() => {\n if (!showOverviewMap) {\n setIsOverviewOpen(false);\n return;\n }\n setIsOverviewOpen(true);\n }, [showOverviewMap, source?.id]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [drawTool, onRegionHover]);\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 const resolveWorldCoord = 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 resolveScreenCoord = useCallback((worldX: number, worldY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.worldToScreen(worldX, worldY);\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 requestCustomLayerRedraw = useCallback(() => {\n rendererRef.current?.requestRender();\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n }, []);\n\n const effectiveCustomLayerViewState = useMemo<WsiViewState | null>(() => {\n return customLayerViewState ?? rendererRef.current?.getViewState() ?? null;\n }, [customLayerViewState]);\n\n const customLayerContext = useMemo<WsiCustomLayerContext | null>(() => {\n if (!source) return null;\n const viewStateForLayer = effectiveCustomLayerViewState;\n if (!viewStateForLayer) return null;\n return {\n source,\n viewState: viewStateForLayer,\n drawTool,\n interactionLock,\n worldToScreen: resolveScreenCoord,\n screenToWorld: resolveWorldCoord,\n requestRedraw: requestCustomLayerRedraw,\n };\n }, [source, effectiveCustomLayerViewState, drawTool, interactionLock, resolveScreenCoord, resolveWorldCoord, requestCustomLayerRedraw]);\n\n const handleRegionPointerMove = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n const isCanvasEvent = event.target === canvasRef.current;\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (onPointerWorldMove) {\n const insideImage = !!coord && coord[0] >= 0 && coord[1] >= 0 && !!source && coord[0] <= source.width && coord[1] <= source.height;\n onPointerWorldMove({\n coordinate: coord,\n clientX: event.clientX,\n clientY: event.clientY,\n insideImage,\n });\n }\n\n if (drawTool !== \"cursor\") return;\n if (!isCanvasEvent) {\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n return;\n }\n if (!coord) {\n emitPointHover(null, null);\n return;\n }\n\n if (onPointHover) {\n emitPointHover(getCellByCoordinates(coord), coord);\n }\n if (!effectiveRoiRegions.length) return;\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n const nextHoverId = hit?.regionId ?? null;\n const prevHoverId = hoveredRegionIdRef.current;\n if (String(prevHoverId) === String(nextHoverId)) return;\n\n hoveredRegionIdRef.current = nextHoverId;\n setHoveredRegionId(nextHoverId);\n onRegionHover?.({\n region: hit?.region ?? null,\n regionId: nextHoverId,\n regionIndex: hit?.regionIndex ?? -1,\n coordinate: coord,\n });\n },\n [drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionHover, onPointerWorldMove, source, emitPointHover, getCellByCoordinates, onPointHover]\n );\n\n const handleRegionPointerLeave = useCallback(() => {\n onPointerWorldMove?.({\n coordinate: null,\n clientX: -1,\n clientY: -1,\n insideImage: false,\n });\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [onRegionHover, onPointerWorldMove, emitPointHover]);\n\n const handleRegionClick = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n\n if (!effectiveRoiRegions.length) {\n commitActiveRegion(null);\n return;\n }\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n if (!hit) {\n commitActiveRegion(null);\n return;\n }\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n },\n [drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionClick, activeRegionId, commitActiveRegion, emitPointClick]\n );\n\n const handleBrushTap = useCallback(\n (coord: DrawCoordinate): boolean => {\n if (drawTool !== \"brush\") return false;\n if (brushOptions?.clickSelectRoi !== true) return false;\n if (!effectiveRoiRegions.length) return false;\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n if (!hit) return false;\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n return true;\n },\n [drawTool, brushOptions?.clickSelectRoi, effectiveRoiRegions, activeRegionId, commitActiveRegion, onRegionClick]\n );\n\n const handleRegionContextMenu = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (!onPointClick) return;\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n event.preventDefault();\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n },\n [drawTool, resolveWorldCoord, emitPointClick, onPointClick]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !source) {\n return;\n }\n\n const renderer = new WsiTileRenderer(canvas, source, {\n onViewStateChange: emitViewStateChange,\n onStats: handleRendererStats,\n onTileError,\n onContextLost,\n onContextRestored,\n authToken,\n ctrlDragRotate,\n pointSizeByZoom,\n });\n\n rendererRef.current = renderer;\n if (viewState) {\n renderer.setViewState(viewState);\n }\n renderer.setInteractionLock(interactionLock);\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(renderer.getViewState());\n }\n\n return () => {\n renderer.destroy();\n rendererRef.current = null;\n };\n }, [source, handleRendererStats, onTileError, onContextLost, onContextRestored, authToken, ctrlDragRotate, pointSizeByZoom, emitViewStateChange, shouldTrackCustomLayerViewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !viewState) {\n return;\n }\n renderer.setViewState(viewState);\n }, [viewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.fitToImage();\n }, [fitNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.resetRotation();\n }, [rotationResetNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !pointPalette) {\n return;\n }\n renderer.setPointPalette(pointPalette);\n }, [pointPalette]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointSizeByZoom(pointSizeByZoom);\n }, [pointSizeByZoom]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointData(renderPointData);\n }, [renderPointData]);\n\n useEffect(() => {\n if (!onRoiPointGroups) return;\n const sourcePoints = clipPointsToRois ? renderPointData : pointData;\n const stats = computeRoiPointGroups(sourcePoints, effectiveRoiRegions, {\n paletteIndexToTermId: roiPaletteIndexToTermId,\n includeEmptyRegions: true,\n });\n onRoiPointGroups(stats);\n }, [onRoiPointGroups, clipPointsToRois, pointData, renderPointData, effectiveRoiRegions, roiPaletteIndexToTermId]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setInteractionLock(interactionLock);\n }, [interactionLock]);\n\n return (\n <div className={className} style={mergedStyle} onPointerMove={handleRegionPointerMove} onPointerLeave={handleRegionPointerLeave} onClick={handleRegionClick} onContextMenu={handleRegionContextMenu}>\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 cursor: drawTool === \"cursor\" && hoveredRegionId !== null ? \"pointer\" : interactionLock ? \"crosshair\" : \"grab\",\n }}\n />\n {source && customLayerContext && Array.isArray(customLayers) && customLayers.length > 0\n ? customLayers.map((layer, index) => (\n <div\n key={layer.id ?? index}\n className={layer.className}\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: layer.zIndex ?? 3,\n pointerEvents: layer.pointerEvents ?? \"none\",\n ...layer.style,\n }}\n >\n {layer.render(customLayerContext)}\n </div>\n ))\n : null}\n {source ? (\n <DrawLayer\n tool={drawTool}\n enabled={drawTool !== \"cursor\"}\n imageWidth={source.width}\n imageHeight={source.height}\n imageMpp={source.mpp}\n imageZoom={source.maxTierZoom}\n stampOptions={stampOptions}\n brushOptions={brushOptions}\n projectorRef={rendererRef}\n onBrushTap={handleBrushTap}\n viewStateSignal={viewState}\n persistedRegions={effectiveRoiRegions}\n patchRegions={safePatchRegions}\n regionStrokeStyle={regionStrokeStyle}\n regionStrokeHoverStyle={regionStrokeHoverStyle}\n regionStrokeActiveStyle={regionStrokeActiveStyle}\n patchStrokeStyle={patchStrokeStyle}\n resolveRegionStrokeStyle={resolveRegionStrokeStyle}\n overlayShapes={overlayShapes}\n hoveredRegionId={hoveredRegionId}\n activeRegionId={activeRegionId}\n regionLabelStyle={regionLabelStyle}\n invalidateRef={drawInvalidateRef}\n onDrawComplete={onDrawComplete}\n onPatchComplete={onPatchComplete}\n />\n ) : null}\n {debugOverlay ? (\n <pre data-open-plant-debug-overlay style={mergedDebugOverlayStyle}>\n {debugOverlayText}\n </pre>\n ) : null}\n {source && showOverviewMap ? (\n isOverviewOpen ? (\n <>\n <OverviewMap source={source} projectorRef={rendererRef} authToken={authToken} options={overviewMapOptions} invalidateRef={overviewInvalidateRef} />\n <button\n type=\"button\"\n aria-label=\"Hide overview map\"\n onClick={() => setIsOverviewOpen(false)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin + overviewHeight + 8 } : { bottom: overviewMargin + overviewHeight + 8 }),\n width: 20,\n height: 20,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.4)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#fff\",\n fontSize: 13,\n lineHeight: 1,\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n ×\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Show overview map\"\n onClick={() => setIsOverviewOpen(true)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin } : { bottom: overviewMargin }),\n height: 24,\n minWidth: 40,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.45)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#dff8ff\",\n fontSize: 11,\n fontWeight: 700,\n cursor: \"pointer\",\n padding: \"0 8px\",\n }}\n >\n Map\n </button>\n )\n ) : null}\n </div>\n );\n}\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","context","OrthoCamera$1","__publicField","width","height","next","viewWidth","viewHeight","sx","sy","tx","ty","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","options","OrthoCamera","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","zoom","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","DEFAULT_MIN_RASTER_STEP","DEFAULT_MAX_RASTER_PIXELS","DEFAULT_MAX_RASTER_SIZE","DEFAULT_CIRCLE_SIDES","MIN_RADIUS","ALPHA_THRESHOLD","clamp","value","min","max","closeRing","coordinates","out","x","y","first","last","sanitizePath","points","point","prev","createCirclePolygon","center","radius","sides","ring","t","createBoundsFallback","minX","minY","maxX","maxY","pad","computeExpandedBounds","resolveRasterConfig","bounds","minRasterStep","maxRasterPixels","maxRasterSize","widthWorld","heightWorld","step","padding","createRasterContext","worldToRaster","config","rasterizeStrokeMask","path","p","i","image","buildBoundaryEdges","mask","edges","vertex","at","turnPriority","fromDir","toDir","delta","traceLoops","outgoing","entry","used","loops","startVertex","currentVertex","currentDir","loop","guard","guardLimit","candidates","bestIndex","bestPriority","edgeIndex","candidate","priority","toWorldRing","vertexLoop","id","polygonSignedArea","sum","a","b","removeCollinearVertices","epsilon","closed","curr","cross","pointLineDistanceSquared","abx","aby","len2","dx","dy","simplifyRdp","tolerance","keep","tolerance2","stack","start","end","maxDist2","split","dist2","simplifyClosedRing","open","simplified","clampRingToBounds","buildBrushStrokePolygon","circleSides","raster","bestRing","bestArea","area","DEFAULT_POINT_COLOR","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcScaleLength","length","unit","isSameViewState","toBearerToken","trimmed","token","hexToRgba","hex","match","n","buildTermPalette","terms","palette","termToPaletteIndex","term","termId","colors","vs","fs","DRAW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","EMPTY_REGIONS","EMPTY_DASH","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","MIN_BRUSH_RASTER_STEP","BRUSH_RASTER_DIAMETER_SAMPLES","BRUSH_SCREEN_STEP","DEFAULT_REGION_STROKE_STYLE","DEFAULT_PATCH_STROKE_STYLE","DEFAULT_REGION_LABEL_STYLE","isStampTool","tool","clampPositiveOrFallback","fallback","resolveStampOptions","clampUnitOpacity","sanitizeBrushLineDash","item","resolveBrushEdgeDetail","resolveBrushOptions","cursorLineWidth","edgeDetail","mm2ToUm2","areaMm2","createSquareFromCenter","halfLength","createCircleFromCenter","coords","createRectangle","createCircle","centerX","centerY","polygonArea","computeBounds","isValidPolygon","tracePath","ctx","close","drawPath","strokeStyle","fill","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","isNestedRingCoordinates","isFiniteNumber","isCoordinatePair","isCoordinateRing","collectOverlayRings","normalizeOverlayRings","sourceRings","normalized","drawInvertedFillMask","outerRing","holeRings","fillColor","resolveLabelStyle","px","py","bw","oy","br","drawRoundedRect","r","getTopAnchor","drawRegionLabel","text","anchor","canvasWidth","canvasHeight","labelStyle","label","boxWidth","boxHeight","left","top","clampWorld","coord","imageWidth","imageHeight","toCoord","DrawLayer","stampOptions","brushOptions","projectorRef","onBrushTap","onDrawComplete","onPatchComplete","enabled","viewStateSignal","persistedRegions","patchRegions","persistedPolygons","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","patchStrokeStyle","resolveRegionStrokeStyle","overlayShapes","hoveredRegionId","activeRegionId","regionLabelStyle","invalidateRef","className","canvasRef","useRef","drawPendingRef","overlayDebugSnapshotRef","lastToolRef","sessionRef","active","mergedPersistedRegions","useMemo","index","mergedPatchRegions","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedPatchStrokeStyle","resolvedLabelStyle","resolvedStampOptions","resolvedBrushOptions","mergedStyle","resizeCanvas","useCallback","w","h","worldToScreenPoints","projector","worldRadiusToScreenPixels","worldRadius","micronsToWorldPixels","lengthUm","mppValue","imageZoomValue","viewZoomRaw","viewZoom","continuousZoom","umPerScreenPixel","buildStampCoords","stampTool","areaUm2","buildPreviewCoords","session","drawBrushStrokePreview","screenPoints","radiusPx","drawBrushCursor","cursor","screen","drawOverlay","region","regionKey","state","resolved","debugOverlay","imageOuterRing","shape","renderRings","closedRings","debugKey","debugSignature","preview","line","polygon","anchorWorld","anchorScreen","requestDraw","resetSession","preserveCursor","toWorld","event","raw","finishSession","tapPoint","handleStampAt","intent","result","appendBrushPoint","world","minWorldStep","minWorldStep2","handlePointerDown","handlePointerMove","handlePointerUp","handlePointerLeave","changed","useEffect","observer","onKeyDown","jsx","screenX","screenY","trimTrailingSlash","ensureLeadingSlash","joinImsTileRoot","tileBaseUrl","parsed","origin","normalizeImageInfo","ims","isIms","tileSize","maxTierZoom","tilePath","normalizedPath","imsTileRoot","tileUrlBuilder","tier","toTileUrl","DEFAULT_OVERVIEW_MAP_OPTIONS","toPositiveNumber","isFiniteBounds","OverviewMap","authToken","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderRadius","borderWidth","maxThumbnailTiles","backgroundColor","borderColor","viewportStrokeColor","viewportFillColor","interactive","showThumbnail","position","pos","draw","cssW","cssH","pixelW","pixelH","corners","safeBounds","safeCorners","right","bottom","rectW","rectH","toWorldFromClient","clientX","clientY","nx","ny","recenterTo","worldX","worldY","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","requests","useAuthHeader","results","dw","dh","TileViewerCanvas","rendererRef","renderer","sanitizePointCount","pointData","preparePolygons","polygons","prepared","poly","isInsideRing","inside","j","xi","yi","xj","yj","isInsideAnyPolygon","filterPointDataByPolygons","count","positions","pointIds","nextPositions","nextTerms","nextIds","output","filterPointIndicesByPolygons","contextPromise","BBOX_PREFILTER_SHADER","hasWebGpu","nav","getNavigatorGpu","gpu","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","pointCount","boundsCount","safePointCount","positionBytes","boundsBytes","outputBytes","limit","positionsBuffer","boundsBuffer","outputBuffer","uniformBuffer","readBuffer","bindGroup","commandEncoder","pass","mapped","nowMs","filterPointDataByPolygonsHybrid","bridgeToDraw","safeCount","bboxFlat","candidateMask","usedWebGpu","candidateCount","candidateIndices","candidateCursor","data","drawIndices","visibleCount","pointIndex","compactData","workerInstance","workerSupported","requestId","pendingById","createWorker","worker","handleWorkerMessage","handleWorkerError","msg","pending","indices","paletteIndices","ids","terminateRoiClipWorker","filterPointDataByPolygonsInWorker","positionsCopy","termsCopy","idsCopy","startMs","resolve","reject","transfer","filterPointIndicesByPolygonsInWorker","ax","ay","bx","by","prepareRegions","regions","resolveTermId","paletteIndex","paletteIndexToTermId","fromArray","fromMap","computeRoiPointGroups","baseCount","valid","filtered","idx","inputCount","preparedRegions","regionTermCounters","regionTotalCounters","insideCount","bestRegion","regionTermMap","includeEmptyRegions","groups","totalCount","termMap","termCounts","shouldAttachAuthHeader","url","host","TileScheduler","nextVisibleKeys","inflight","queued","visibleKeys","nextQueue","key","earliestReadyAt","delay","now","controller","inflightEntry","nextAttempt","retryDelay","existing","attempt","exp","jitter","DEFAULT_ROTATION_DRAG_SENSITIVITY","MIN_POINT_SIZE_PX","MAX_POINT_SIZE_PX","DEFAULT_POINT_SIZE_STOPS","rad","toRadians","cos","sin","rx","ry","deg","name","isSameArrayView","clonePointSizeStops","stops","stop","normalizePointSizeStops","pointSizeByZoom","zoomKey","rawSize","size","arePointSizeStopsEqual","resolvePointSizeByZoomStops","span","slope","WsiTileRenderer","attemptCount","paletteSize","nextPaletteIndices","hasDrawIndices","nextDrawIndices","geometryChanged","drawIndicesChanged","maxExclusive","validCount","locked","nextStops","vw","vh","visibleWorldW","visibleWorldH","factor","nextZoom","vp","worldDx","worldDy","marginX","marginY","halfW","halfH","minCenterX","maxCenterX","minCenterY","maxCenterY","nextCenterX","nextCenterY","rawTier","viewBounds","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","visible","entries","removeCount","frameStartMs","tileProgram","pointProgram","fallbackTiles","cached","renderedTiles","missingTiles","renderedPoints","schedulerStats","cacheHits","cacheMisses","drawCalls","wantsRotate","nextAngle","prevAngle","rawDelta","sensitivityScale","_event","uCamera","uBounds","uTexture","vbo","aUnit","aUv","uPointSize","uPalette","uPaletteSize","posBuffer","termBuffer","indexBuffer","paletteTexture","posLoc","termLoc","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","EMPTY_CLIPPED_POINTS","POINT_HIT_RADIUS_SCALE","MIN_POINT_HIT_RADIUS_PX","MIN_POINT_HIT_GRID_SIZE","MAX_POINT_HIT_GRID_SIZE","POINT_HIT_GRID_DENSITY_SCALE","sanitizeDrawIndices","invalidFound","resolvePointHitGridSize","buildPointSpatialIndex","cellSize","buckets","pushBucket","cellX","cellY","column","bucket","resolveRegionId","isPointInPolygon","pickRegionAt","WsiViewerCanvas","onViewStateChange","onStats","onTileError","onContextLost","onContextRestored","debugOverlayStyle","fitNonce","rotationResetNonce","ctrlDragRotate","pointPalette","roiRegions","roiPolygons","clipPointsToRois","clipMode","onClipStats","onRoiPointGroups","roiPaletteIndexToTermId","interactionLock","drawTool","customLayers","onPointerWorldMove","onPointHover","onPointClick","onRegionHover","onRegionClick","onActiveRegionChange","getCellByCoordinatesRef","showOverviewMap","overviewMapOptions","drawInvalidateRef","overviewInvalidateRef","onViewStateChangeRef","onStatsRef","debugOverlayRef","isOverviewOpen","setIsOverviewOpen","useState","setHoveredRegionId","setActiveRegionId","customLayerViewState","setCustomLayerViewState","debugStats","setDebugStats","hoveredRegionIdRef","hoveredPointIndexRef","hoveredPointIdRef","clipRunIdRef","safeRoiRegions","safePatchRegions","safeRoiPolygons","shouldTrackCustomLayerViewState","mergedDebugOverlayStyle","effectiveRoiRegions","clipPolygons","renderPointData","setRenderPointData","runId","applyResult","stats","outputCount","shouldEnablePointHitTest","pointSpatialIndex","getCellByCoordinates","coordinate","pointSizePx","hitRadiusWorld","baseCellX","baseCellY","cellRadius","nearestIndex","nearestDist2","nearestX","nearestY","cx","cy","pointId","emitPointHover","hit","nextIndex","nextId","emitPointClick","button","overviewHeight","overviewMargin","overviewPosition","commitActiveRegion","handleRendererStats","debugOverlayText","currentHover","hoveredPointIndex","emitViewStateChange","callback","resolveWorldCoord","resolveScreenCoord","requestCustomLayerRedraw","effectiveCustomLayerViewState","customLayerContext","viewStateForLayer","handleRegionPointerMove","isCanvasEvent","insideImage","nextHoverId","prevHoverId","handleRegionPointerLeave","handleRegionClick","nextActive","handleBrushTap","handleRegionContextMenu","jsxs","layer","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/core/gl-utils.ts","../src/core/ortho-camera.ts","../src/core/m1-tile-renderer.ts","../src/wsi/brush-stroke.ts","../src/wsi/roi-geometry.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/react/draw-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/point-clip.ts","../src/wsi/webgpu.ts","../src/wsi/point-clip-hybrid.ts","../src/wsi/point-clip-worker-client.ts","../src/wsi/roi-term-stats.ts","../src/wsi/tile-scheduler.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer-canvas.tsx"],"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(\n gl: WebGL2RenderingContext,\n program: WebGLProgram,\n uniformName: string,\n): 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): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n 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}\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 };\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\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getMatrix(): Float32Array {\n const viewWidth = this.viewportWidth / this.viewState.zoom;\n const viewHeight = this.viewportHeight / this.viewState.zoom;\n\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\n return new Float32Array([\n sx,\n 0,\n 0,\n 0,\n sy,\n 0,\n tx,\n ty,\n 1,\n ]);\n }\n}\n","import {\n\tcreateProgram,\n\trequireUniformLocation,\n\trequireWebGL2,\n} from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n\tid: string;\n\tbounds: Bounds;\n\ttexture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n\tcanvas: HTMLCanvasElement;\n\timageWidth: number;\n\timageHeight: number;\n\tclearColor?: [number, number, number, number];\n\tinitialViewState?: Partial<ViewState>;\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\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly imageWidth: number;\n\tprivate readonly imageHeight: number;\n\tprivate readonly clearColor: [number, number, number, number];\n\tprivate readonly program: WebGLProgram;\n\tprivate readonly vao: WebGLVertexArrayObject;\n\tprivate readonly quadBuffer: WebGLBuffer;\n\tprivate readonly uCameraLocation: WebGLUniformLocation;\n\tprivate readonly uBoundsLocation: WebGLUniformLocation;\n\tprivate readonly uTextureLocation: WebGLUniformLocation;\n\tprivate readonly resizeObserver: ResizeObserver;\n\n\tprivate tiles: LoadedTile[] = [];\n\tprivate frameId: number | null = null;\n\tprivate loadVersion = 0;\n\tprivate destroyed = false;\n\tprivate fitted = false;\n\tprivate controlledViewState = false;\n\n\tconstructor(options: M1TileRendererOptions) {\n\t\tthis.canvas = options.canvas;\n\t\tthis.imageWidth = Math.max(1, options.imageWidth);\n\t\tthis.imageHeight = Math.max(1, options.imageHeight);\n\t\tthis.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n\t\tthis.gl = requireWebGL2(this.canvas);\n\t\tthis.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n\t\tconst vao = this.gl.createVertexArray();\n\t\tconst quadBuffer = this.gl.createBuffer();\n\t\tif (!vao || !quadBuffer) {\n\t\t\tthrow new Error(\"Failed to create WebGL buffers.\");\n\t\t}\n\n\t\tthis.vao = vao;\n\t\tthis.quadBuffer = quadBuffer;\n\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n\t\tconst quadVertices = new Float32Array([\n\t\t\t0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1,\n\t\t]);\n\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n\t\tconst unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n\t\tconst uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n\t\tif (unitLocation < 0 || uvLocation < 0) {\n\t\t\tthrow new Error(\"Failed to get attribute locations.\");\n\t\t}\n\n\t\tconst stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n\t\tthis.gl.enableVertexAttribArray(unitLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tunitLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t0,\n\t\t);\n\t\tthis.gl.enableVertexAttribArray(uvLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tuvLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t2 * Float32Array.BYTES_PER_ELEMENT,\n\t\t);\n\n\t\tthis.gl.bindVertexArray(null);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n\t\tthis.uCameraLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uCamera\",\n\t\t);\n\t\tthis.uBoundsLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uBounds\",\n\t\t);\n\t\tthis.uTextureLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uTexture\",\n\t\t);\n\n\t\tif (options.initialViewState) {\n\t\t\tthis.controlledViewState = true;\n\t\t\tthis.camera.setViewState(options.initialViewState);\n\t\t}\n\n\t\tthis.resizeObserver = new ResizeObserver(() => {\n\t\t\tthis.resize();\n\t\t});\n\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.resize();\n\t}\n\n\tasync setTiles(tiles: TileDefinition[]): Promise<void> {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst version = ++this.loadVersion;\n\n\t\tconst loaded = await Promise.all(\n\t\t\ttiles.map(async (tile) => {\n\t\t\t\tconst loadedTile = await this.loadTile(tile, version);\n\t\t\t\treturn loadedTile;\n\t\t\t}),\n\t\t);\n\n\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\tfor (const tile of loaded) {\n\t\t\t\tif (tile) {\n\t\t\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n\t\tthis.requestRender();\n\t}\n\n\tsetViewState(viewState: Partial<ViewState>): void {\n\t\tthis.controlledViewState = true;\n\t\tthis.camera.setViewState(viewState);\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): ViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.loadVersion += 1;\n\n\t\tif (this.frameId !== null) {\n\t\t\tcancelAnimationFrame(this.frameId);\n\t\t\tthis.frameId = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = [];\n\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tthis.gl.deleteVertexArray(this.vao);\n\t\tthis.gl.deleteProgram(this.program);\n\t}\n\n\tprivate async loadTile(\n\t\ttile: TileDefinition,\n\t\tversion: number,\n\t): Promise<LoadedTile | null> {\n\t\ttry {\n\t\t\tconst response = await fetch(tile.url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tile fetch failed: ${response.status} ${response.statusText}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst blob = await response.blob();\n\t\t\tconst bitmap = await createImageBitmap(blob);\n\n\t\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\t\tbitmap.close();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst texture = this.gl.createTexture();\n\t\t\tif (!texture) {\n\t\t\t\tbitmap.close();\n\t\t\t\tthrow new Error(\"Failed to create tile texture.\");\n\t\t\t}\n\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_S,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_T,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MIN_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MAG_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\tbitmap,\n\t\t\t);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\t\tbitmap.close();\n\n\t\t\treturn {\n\t\t\t\tid: tile.id,\n\t\t\t\tbounds: tile.bounds,\n\t\t\t\ttexture,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate resize(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n\t\tconst targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n\t\tif (\n\t\t\tthis.canvas.width !== targetWidth ||\n\t\t\tthis.canvas.height !== targetHeight\n\t\t) {\n\t\t\tthis.canvas.width = targetWidth;\n\t\t\tthis.canvas.height = targetHeight;\n\t\t}\n\n\t\tthis.camera.setViewport(cssWidth, cssHeight);\n\t\tthis.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n\t\tif (!this.fitted && !this.controlledViewState) {\n\t\t\tthis.fitToImage();\n\t\t\tthis.fitted = true;\n\t\t}\n\n\t\tthis.requestRender();\n\t}\n\n\tprivate fitToImage(): void {\n\t\tconst viewport = this.camera.getViewportSize();\n\n\t\tconst zoom = Math.min(\n\t\t\tviewport.width / this.imageWidth,\n\t\t\tviewport.height / this.imageHeight,\n\t\t);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tconst visibleWorldWidth = viewport.width / safeZoom;\n\t\tconst visibleWorldHeight = viewport.height / safeZoom;\n\n\t\tconst offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n\t\tconst offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: safeZoom,\n\t\t\toffsetX,\n\t\t\toffsetY,\n\t\t});\n\t}\n\n\tprivate requestRender(): void {\n\t\tif (this.frameId !== null || this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.frameId = requestAnimationFrame(() => {\n\t\t\tthis.frameId = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tprivate render(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gl.clearColor(\n\t\t\tthis.clearColor[0],\n\t\t\tthis.clearColor[1],\n\t\t\tthis.clearColor[2],\n\t\t\tthis.clearColor[3],\n\t\t);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tthis.gl.useProgram(this.program);\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.uniformMatrix3fv(\n\t\t\tthis.uCameraLocation,\n\t\t\tfalse,\n\t\t\tthis.camera.getMatrix(),\n\t\t);\n\t\tthis.gl.uniform1i(this.uTextureLocation, 0);\n\n\t\tfor (const tile of this.tiles) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n\t\t\tthis.gl.uniform4f(\n\t\t\t\tthis.uBoundsLocation,\n\t\t\t\ttile.bounds[0],\n\t\t\t\ttile.bounds[1],\n\t\t\t\ttile.bounds[2],\n\t\t\t\ttile.bounds[3],\n\t\t\t);\n\t\t\tthis.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\tthis.gl.bindVertexArray(null);\n\t}\n\n\tprivate disposeTiles(tiles: LoadedTile[]): void {\n\t\tfor (const tile of tiles) {\n\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t}\n\t}\n}\n","export 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\ninterface RasterConfig {\n\tminX: number;\n\tminY: number;\n\tstep: number;\n\tpadding: number;\n\twidth: number;\n\theight: number;\n}\n\ninterface BoundaryEdge {\n\tstart: number;\n\tend: number;\n\tdir: 0 | 1 | 2 | 3;\n}\n\nconst DEFAULT_MIN_RASTER_STEP = 0.1;\nconst DEFAULT_MAX_RASTER_PIXELS = 4_000_000;\nconst DEFAULT_MAX_RASTER_SIZE = 4096;\nconst DEFAULT_CIRCLE_SIDES = 64;\nconst DEFAULT_SMOOTHING_PASSES = 1;\nconst MAX_SMOOTHING_PASSES = 4;\nconst MIN_RADIUS = 1e-6;\nconst ALPHA_THRESHOLD = 24;\n\nfunction clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nfunction closeRing(\n\tcoordinates: BrushStrokeCoordinate[],\n): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(([x, y]) => [x, y] as BrushStrokeCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction sanitizePath(\n\tpoints: BrushStrokeCoordinate[],\n): 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 createCirclePolygon(\n\tcenter: BrushStrokeCoordinate,\n\tradius: number,\n\tsides: number,\n): 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([\n\t\t\tcenter[0] + Math.cos(t) * radius,\n\t\t\tcenter[1] + Math.sin(t) * radius,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction createBoundsFallback(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): 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 computeExpandedBounds(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): BrushStrokeBounds {\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\tconst pad = Math.max(radius, 1);\n\treturn [minX - pad, minY - pad, maxX + pad, maxY + pad];\n}\n\nfunction resolveRasterConfig(\n\tbounds: BrushStrokeBounds,\n\tradius: number,\n\toptions: BrushStrokePolygonOptions,\n): RasterConfig {\n\tconst minRasterStep = Math.max(\n\t\tDEFAULT_MIN_RASTER_STEP,\n\t\tNumber(options.minRasterStep) || 0,\n\t);\n\tconst maxRasterPixels = Math.max(\n\t\t32_768,\n\t\tMath.floor(options.maxRasterPixels || DEFAULT_MAX_RASTER_PIXELS),\n\t);\n\tconst maxRasterSize = Math.max(\n\t\t256,\n\t\tMath.floor(options.maxRasterSize || DEFAULT_MAX_RASTER_SIZE),\n\t);\n\n\tconst widthWorld = Math.max(1e-3, bounds[2] - bounds[0]);\n\tconst heightWorld = Math.max(1e-3, bounds[3] - bounds[1]);\n\tlet step = Math.max(minRasterStep, Number.EPSILON);\n\tlet padding = 3;\n\tlet width = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\tlet height = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\n\twhile (\n\t\twidth > maxRasterSize ||\n\t\theight > maxRasterSize ||\n\t\twidth * height > maxRasterPixels\n\t) {\n\t\tstep *= 1.15;\n\t\twidth = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\t\theight = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\t\tif (step > Math.max(widthWorld, heightWorld)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twidth = Math.max(8, width);\n\theight = Math.max(8, height);\n\n\treturn {\n\t\tminX: bounds[0],\n\t\tminY: bounds[1],\n\t\tstep,\n\t\tpadding,\n\t\twidth,\n\t\theight,\n\t};\n}\n\ntype AnyCanvas2DContext =\n\t| CanvasRenderingContext2D\n\t| OffscreenCanvasRenderingContext2D;\n\nfunction createRasterContext(\n\twidth: number,\n\theight: number,\n): AnyCanvas2DContext | null {\n\tif (typeof OffscreenCanvas !== \"undefined\") {\n\t\tconst canvas = new OffscreenCanvas(width, height);\n\t\tconst context = canvas.getContext(\"2d\", { willReadFrequently: true });\n\t\tif (context) return context;\n\t}\n\tif (typeof document !== \"undefined\") {\n\t\tconst canvas = document.createElement(\"canvas\");\n\t\tcanvas.width = width;\n\t\tcanvas.height = height;\n\t\treturn canvas.getContext(\"2d\", { willReadFrequently: true });\n\t}\n\treturn null;\n}\n\nfunction worldToRaster(\n\tpoint: BrushStrokeCoordinate,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate {\n\treturn [\n\t\t(point[0] - config.minX) / config.step + config.padding,\n\t\t(point[1] - config.minY) / config.step + config.padding,\n\t];\n}\n\nfunction rasterizeStrokeMask(\n\tpath: BrushStrokeCoordinate[],\n\tradius: number,\n\tconfig: RasterConfig,\n): Uint8Array {\n\tconst context = createRasterContext(config.width, config.height);\n\tif (!context) return new Uint8Array(0);\n\n\tcontext.clearRect(0, 0, config.width, config.height);\n\tcontext.fillStyle = \"#ffffff\";\n\tcontext.strokeStyle = \"#ffffff\";\n\tcontext.lineCap = \"round\";\n\tcontext.lineJoin = \"round\";\n\tcontext.lineWidth = (radius * 2) / config.step;\n\n\tconst points = path.map(point => worldToRaster(point, config));\n\tif (points.length <= 1) {\n\t\tconst p = points[0];\n\t\tif (!p) return new Uint8Array(0);\n\t\tcontext.beginPath();\n\t\tcontext.arc(p[0], p[1], radius / config.step, 0, Math.PI * 2);\n\t\tcontext.fill();\n\t} else {\n\t\tcontext.beginPath();\n\t\tcontext.moveTo(points[0][0], points[0][1]);\n\t\tfor (let i = 1; i < points.length; i += 1) {\n\t\t\tcontext.lineTo(points[i][0], points[i][1]);\n\t\t}\n\t\tcontext.stroke();\n\t}\n\n\tconst image = context.getImageData(0, 0, config.width, config.height);\n\tconst out = new Uint8Array(config.width * config.height);\n\tfor (let i = 0; i < out.length; i += 1) {\n\t\tout[i] = image.data[i * 4 + 3] >= ALPHA_THRESHOLD ? 1 : 0;\n\t}\n\treturn out;\n}\n\nfunction buildBoundaryEdges(mask: Uint8Array, width: number, height: number): BoundaryEdge[] {\n\tconst edges: BoundaryEdge[] = [];\n\tconst stride = width + 1;\n\tconst vertex = (x: number, y: number): number => y * stride + x;\n\tconst at = (x: number, y: number): boolean =>\n\t\tx >= 0 && y >= 0 && x < width && y < height && mask[y * width + x] > 0;\n\n\tfor (let y = 0; y < height; y += 1) {\n\t\tfor (let x = 0; x < width; x += 1) {\n\t\t\tif (!at(x, y)) continue;\n\t\t\tif (!at(x, y - 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y),\n\t\t\t\t\tend: vertex(x + 1, y),\n\t\t\t\t\tdir: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x + 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y),\n\t\t\t\t\tend: vertex(x + 1, y + 1),\n\t\t\t\t\tdir: 1,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x, y + 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y + 1),\n\t\t\t\t\tend: vertex(x, y + 1),\n\t\t\t\t\tdir: 2,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x - 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y + 1),\n\t\t\t\t\tend: vertex(x, y),\n\t\t\t\t\tdir: 3,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn edges;\n}\n\nfunction turnPriority(fromDir: number, toDir: number): number {\n\tconst delta = (toDir - fromDir + 4) % 4;\n\tif (delta === 1) return 0; // right\n\tif (delta === 0) return 1; // straight\n\tif (delta === 3) return 2; // left\n\treturn 3; // reverse\n}\n\nfunction traceLoops(edges: BoundaryEdge[]): number[][] {\n\tif (!edges.length) return [];\n\n\tconst outgoing = new Map<number, number[]>();\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tconst entry = outgoing.get(edges[i].start);\n\t\tif (entry) {\n\t\t\tentry.push(i);\n\t\t} else {\n\t\t\toutgoing.set(edges[i].start, [i]);\n\t\t}\n\t}\n\n\tconst used = new Uint8Array(edges.length);\n\tconst loops: number[][] = [];\n\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tif (used[i]) continue;\n\n\t\tconst first = edges[i];\n\t\tconst startVertex = first.start;\n\t\tlet currentVertex = first.end;\n\t\tlet currentDir = first.dir;\n\t\tconst loop: number[] = [first.start, first.end];\n\t\tused[i] = 1;\n\n\t\tlet guard = 0;\n\t\tconst guardLimit = edges.length * 3;\n\t\twhile (currentVertex !== startVertex && guard < guardLimit) {\n\t\t\tconst candidates = outgoing.get(currentVertex);\n\t\t\tif (!candidates || candidates.length === 0) break;\n\n\t\t\tlet bestIndex = -1;\n\t\t\tlet bestPriority = Infinity;\n\t\t\tfor (const edgeIndex of candidates) {\n\t\t\t\tif (used[edgeIndex]) continue;\n\t\t\t\tconst candidate = edges[edgeIndex];\n\t\t\t\tconst priority = turnPriority(currentDir, candidate.dir);\n\t\t\t\tif (priority < bestPriority) {\n\t\t\t\t\tbestPriority = priority;\n\t\t\t\t\tbestIndex = edgeIndex;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bestIndex < 0) break;\n\t\t\tused[bestIndex] = 1;\n\t\t\tconst next = edges[bestIndex];\n\t\t\tcurrentVertex = next.end;\n\t\t\tcurrentDir = next.dir;\n\t\t\tloop.push(currentVertex);\n\t\t\tguard += 1;\n\t\t}\n\n\t\tif (\n\t\t\tloop.length >= 4 &&\n\t\t\tloop[0] === loop[loop.length - 1]\n\t\t) {\n\t\t\tloops.push(loop);\n\t\t}\n\t}\n\n\treturn loops;\n}\n\nfunction toWorldRing(\n\tvertexLoop: number[],\n\twidth: number,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate[] {\n\tconst stride = width + 1;\n\tconst ring: BrushStrokeCoordinate[] = [];\n\tfor (const id of vertexLoop) {\n\t\tconst x = id % stride;\n\t\tconst y = Math.floor(id / stride);\n\t\tring.push([\n\t\t\tconfig.minX + (x - config.padding) * config.step,\n\t\t\tconfig.minY + (y - config.padding) * config.step,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction polygonSignedArea(ring: BrushStrokeCoordinate[]): number {\n\tif (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 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(\n\tpoints: BrushStrokeCoordinate[],\n\ttolerance: number,\n): 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(\n\tring: BrushStrokeCoordinate[],\n\ttolerance: number,\n): 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\nfunction clampRingToBounds(\n\tring: BrushStrokeCoordinate[],\n\tbounds: BrushStrokeBounds | undefined,\n): BrushStrokeCoordinate[] {\n\tif (!bounds) return 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\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(\n\t\t\tcreateCirclePolygon(points[0], radius, circleSides),\n\t\t\toptions.clipBounds,\n\t\t);\n\t}\n\n\tconst bounds = computeExpandedBounds(points, radius);\n\tconst raster = resolveRasterConfig(bounds, radius, options);\n\tconst mask = rasterizeStrokeMask(points, radius, raster);\n\tif (!mask.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tconst edges = buildBoundaryEdges(mask, raster.width, raster.height);\n\tconst loops = traceLoops(edges);\n\tif (!loops.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tlet bestRing: BrushStrokeCoordinate[] = [];\n\tlet bestArea = 0;\n\tfor (const loop of loops) {\n\t\tconst ring = toWorldRing(loop, raster.width, raster);\n\t\tconst area = Math.abs(polygonSignedArea(ring));\n\t\tif (area <= bestArea) continue;\n\t\tbestArea = area;\n\t\tbestRing = ring;\n\t}\n\n\tif (!bestRing.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: raster.step * 0.2;\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\tconst simplified = simplifyClosedRing(\n\t\tsmoothClosedRingChaikin(\n\t\t\tremoveCollinearVertices(bestRing, raster.step * 1e-3),\n\t\t\tsmoothingPasses,\n\t\t),\n\t\ttolerance,\n\t);\n\treturn clampRingToBounds(simplified, options.clipBounds);\n}\n","export type RoiCoordinate = [number, number];\nexport type RoiLinearRing = RoiCoordinate[];\nexport type RoiPolygonRings = RoiLinearRing[];\nexport type RoiMultiPolygon = RoiPolygonRings[];\nexport type RoiGeometry = RoiLinearRing | RoiPolygonRings | RoiMultiPolygon;\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 (!geometry) return [];\n\n\tif (isLinearRing(geometry)) {\n\t\tconst polygon = normalizePolygonRings([geometry]);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (isPolygonRings(geometry)) {\n\t\tconst polygon = normalizePolygonRings(geometry);\n\t\treturn polygon.length > 0 ? [polygon] : [];\n\t}\n\n\tif (isMultiPolygon(geometry)) {\n\t\tconst out: RoiMultiPolygon = [];\n\t\tfor (const polygon of geometry) {\n\t\t\tconst normalized = normalizePolygonRings(polygon);\n\t\t\tif (normalized.length > 0) out.push(normalized);\n\t\t}\n\t\treturn out;\n\t}\n\n\treturn [];\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\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + 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 { TermPalette, 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 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 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 buildTermPalette(\n\tterms:\n\t\t| Array<{ termId?: string | null; termColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): TermPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst termToPaletteIndex = new Map<string, number>();\n\n\tfor (const term of terms ?? []) {\n\t\tconst termId = String(term?.termId ?? \"\");\n\t\tif (!termId || termToPaletteIndex.has(termId)) continue;\n\n\t\ttermToPaletteIndex.set(termId, palette.length);\n\t\tpalette.push(hexToRgba(term?.termColor));\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, termToPaletteIndex };\n}\n\nexport function createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram {\n\tconst vs = gl.createShader(gl.VERTEX_SHADER);\n\tconst fs = gl.createShader(gl.FRAGMENT_SHADER);\n\tif (!vs || !fs) {\n\t\tthrow new Error(\"Shader allocation failed\");\n\t}\n\n\tgl.shaderSource(vs, vertexSource);\n\tgl.compileShader(vs);\n\tif (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(vs) || \"vertex compile failed\");\n\t}\n\n\tgl.shaderSource(fs, fragmentSource);\n\tgl.compileShader(fs);\n\tif (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(fs) || \"fragment compile failed\");\n\t}\n\n\tconst program = gl.createProgram();\n\tif (!program) {\n\t\tthrow new Error(\"Program allocation failed\");\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tthrow new Error(gl.getProgramInfoLog(program) || \"program link failed\");\n\t}\n\n\treturn program;\n}\n","import { type CSSProperties, type MutableRefObject, type PointerEvent as ReactPointerEvent, type RefObject, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { buildBrushStrokePolygon } from \"../wsi/brush-stroke\";\nimport { normalizeRoiGeometry, type RoiGeometry } from \"../wsi/roi-geometry\";\nimport { calcScaleResolution } from \"../wsi/utils\";\n\nexport type StampDrawTool = \"stamp-rectangle\" | \"stamp-circle\" | \"stamp-rectangle-4096px\" | \"stamp-rectangle-2mm2\" | \"stamp-circle-2mm2\" | \"stamp-circle-hpf-0.2mm2\";\n\nexport type DrawTool = \"cursor\" | \"freehand\" | \"rectangle\" | \"circular\" | \"brush\" | StampDrawTool;\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 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 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 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 /**\n * Brush edge detail factor. Higher values create rounder/finer edges.\n * Range: 0.25 ~ 4. Default: 1.\n */\n edgeDetail?: number;\n /**\n * Post-smoothing passes for brush outline to reduce stair-stepping.\n * Range: 0 ~ 4. Default: 1.\n */\n edgeSmoothing?: number;\n /**\n * When true, a brush \"tap\" (click without drag) on ROI selects that ROI\n * instead of creating a brush stroke.\n */\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 regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n regionLabelStyle?: Partial<RegionLabelStyle>;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\ninterface DrawSession {\n isDrawing: boolean;\n pointerId: number | null;\n start: DrawCoordinate | null;\n current: DrawCoordinate | null;\n cursor: DrawCoordinate | null;\n points: DrawCoordinate[];\n stampCenter: DrawCoordinate | null;\n}\n\ninterface NormalizedDrawRegionPolygon {\n outer: DrawCoordinate[];\n holes: DrawCoordinate[][];\n}\n\ninterface PreparedRenderedRegion {\n region: DrawRegion;\n regionIndex: number;\n regionKey: string | number;\n polygons: NormalizedDrawRegionPolygon[];\n}\n\ninterface 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\nconst DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nconst FREEHAND_MIN_POINTS = 3;\nconst FREEHAND_SCREEN_STEP = 2;\nconst CIRCLE_SIDES = 96;\nconst MIN_AREA_PX = 1;\nconst EMPTY_REGIONS: DrawRegion[] = [];\nconst EMPTY_DASH: number[] = [];\nconst MICRONS_PER_MM = 1000;\nconst DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE = 4096;\nconst LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\nconst WHEEL_ZOOM_IN_FACTOR = 1.12;\nconst WHEEL_ZOOM_OUT_FACTOR = 0.89;\nconst DEFAULT_BRUSH_RADIUS = 32;\nconst DEFAULT_BRUSH_FILL_COLOR = \"#000000\";\nconst DEFAULT_BRUSH_FILL_OPACITY = 0.1;\nconst DEFAULT_BRUSH_CURSOR_COLOR = \"#FFCF00\";\nconst DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR = \"#FF0000\";\nconst DEFAULT_BRUSH_CURSOR_LINE_WIDTH = 1.5;\nconst DEFAULT_BRUSH_CURSOR_DASH = [2, 2];\nconst DEFAULT_BRUSH_EDGE_DETAIL = 1;\nconst MIN_BRUSH_EDGE_DETAIL = 0.25;\nconst MAX_BRUSH_EDGE_DETAIL = 4;\nconst DEFAULT_BRUSH_EDGE_SMOOTHING = 1;\nconst MIN_BRUSH_EDGE_SMOOTHING = 0;\nconst MAX_BRUSH_EDGE_SMOOTHING = 4;\nconst MIN_BRUSH_RASTER_STEP = 0.05;\nconst BRUSH_RASTER_DIAMETER_SAMPLES = 256;\nconst BRUSH_SCREEN_STEP = 1.5;\n\nconst 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\nconst 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\nconst DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 12,\n fontWeight: 500,\n textColor: \"#ffffff\",\n backgroundColor: \"rgba(8, 14, 22, 0.88)\",\n borderColor: \"rgba(255, 77, 79, 0.85)\",\n borderWidth: 1,\n paddingX: 6,\n paddingY: 4,\n offsetY: 10,\n borderRadius: 3,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction isStampTool(tool: DrawTool): tool is StampDrawTool {\n return (\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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction 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\nfunction mm2ToUm2(areaMm2: number): number {\n return areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nfunction createSquareFromCenter(center: DrawCoordinate | null, halfLength: number): DrawCoordinate[] {\n if (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\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\nfunction 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 function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n\n const out = coords.map(([x, y]) => [x, y] as DrawCoordinate);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n\n return out;\n}\n\nexport function createRectangle(start: DrawCoordinate | null, end: DrawCoordinate | null): DrawCoordinate[] {\n if (!start || !end) return [];\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\nfunction polygonArea(coords: DrawCoordinate[]): number {\n if (!Array.isArray(coords) || coords.length < 4) return 0;\n\n let sum = 0;\n for (let i = 0; i < coords.length - 1; i += 1) {\n const a = coords[i];\n const b = coords[i + 1];\n sum += a[0] * b[1] - b[0] * a[1];\n }\n\n return Math.abs(sum * 0.5);\n}\n\nfunction 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\nfunction isValidPolygon(coords: DrawCoordinate[]): boolean {\n return Array.isArray(coords) && coords.length >= 4 && polygonArea(coords) > MIN_AREA_PX;\n}\n\nfunction 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\nfunction drawPath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], strokeStyle: RegionStrokeStyle, close = false, fill = false): void {\n if (points.length === 0) return;\n\n ctx.beginPath();\n tracePath(ctx, points, close);\n if (fill && close) {\n ctx.fillStyle = DRAW_FILL;\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\nfunction 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\nfunction 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\nfunction 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\nfunction isNestedRingCoordinates(coordinates: DrawOverlayCoordinates): boolean {\n const first = coordinates[0];\n return Array.isArray(first) && Array.isArray(first[0]);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is [number, number] {\n return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);\n}\n\nfunction 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\nfunction 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\nfunction 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\nfunction resolveLabelStyle(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\nfunction 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\nfunction getTopAnchor(coords: DrawCoordinate[]): 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) > 0.5) 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 return [(minX + maxX) * 0.5, minY];\n}\n\nfunction getTopAnchorFromPolygons(polygons: NormalizedDrawRegionPolygon[]): DrawCoordinate | null {\n let best: DrawCoordinate | null = null;\n for (const polygon of polygons) {\n const anchor = getTopAnchor(polygon.outer);\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\nfunction normalizeDrawRegionPolygons(coordinates: DrawRegionCoordinates): NormalizedDrawRegionPolygon[] {\n const multipolygon = normalizeRoiGeometry(coordinates as RoiGeometry);\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\nfunction drawRegionLabel(ctx: CanvasRenderingContext2D, text: string, anchor: DrawCoordinate, canvasWidth: number, canvasHeight: number, labelStyle: RegionLabelStyle): 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 = ctx.measureText(label).width;\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const x = clamp(anchor[0], boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1);\n const y = clamp(anchor[1] - labelStyle.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 = 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\nfunction clampWorld(coord: DrawCoordinate, imageWidth: number, imageHeight: number): DrawCoordinate {\n return [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nfunction toCoord(value: DrawCoordinate | number[]): 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 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 regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n hoveredRegionId = null,\n activeRegionId = null,\n regionLabelStyle,\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 points: [],\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\n const resolvedLabelStyle = useMemo(() => resolveLabelStyle(regionLabelStyle), [regionLabelStyle]);\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 }, []);\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = projectorRef.current;\n if (!projector || points.length === 0) return [];\n\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 [projectorRef]\n );\n\n const worldRadiusToScreenPixels = useCallback(\n (center: DrawCoordinate, worldRadius: number): number => {\n if (!Number.isFinite(worldRadius) || worldRadius <= 0) return 0;\n const projector = projectorRef.current;\n if (!projector) return 0;\n const a = toCoord(projector.worldToScreen(center[0], center[1]));\n const b = toCoord(projector.worldToScreen(center[0] + worldRadius, center[1]));\n if (!a || !b) return 0;\n return Math.hypot(b[0] - a[0], b[1] - a[1]);\n },\n [projectorRef]\n );\n\n const micronsToWorldPixels = useCallback(\n (lengthUm: number): number => {\n if (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n // If mpp is missing, fall back to 1um/px assumption.\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 buildStampCoords = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate | null): DrawCoordinate[] => {\n if (!center) return [];\n\n let areaMm2 = 0;\n if (stampTool === \"stamp-rectangle-4096px\") {\n const halfLength = resolvedStampOptions.rectanglePixelSize * 0.5;\n const fixed = createSquareFromCenter(center, halfLength);\n return fixed.map(point => clampWorld(point, imageWidth, imageHeight));\n }\n\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);\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 [micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions]\n );\n\n const buildPreviewCoords = useCallback((): DrawCoordinate[] => {\n const session = sessionRef.current;\n if (isStampTool(tool)) {\n return buildStampCoords(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);\n }\n if (tool === \"circular\") {\n return createCircle(session.start, session.current);\n }\n\n return [];\n }, [tool, buildStampCoords]);\n\n const drawBrushStrokePreview = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.points.length === 0) return;\n\n const screenPoints = worldToScreenPoints(session.points);\n if (screenPoints.length === 0) return;\n const anchor = session.points[session.points.length - 1] ?? session.points[0];\n const radiusPx = worldRadiusToScreenPixels(anchor, 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 [worldToScreenPoints, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\n\n const drawBrushCursor = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n const cursor = session.cursor;\n if (!cursor) return;\n const screen = toCoord(projectorRef.current?.worldToScreen(cursor[0], cursor[1]) ?? []);\n if (!screen) return;\n const radiusPx = worldRadiusToScreenPixels(cursor, 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 [projectorRef, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\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 // Persisted ROI outlines always remain visible.\n if (preparedPersistedRegions.length > 0) {\n for (const entry of preparedPersistedRegions) {\n const { region, polygons, regionIndex, regionKey } = entry;\n const state: RegionStyleContext[\"state\"] = 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\n for (const polygon of polygons) {\n const screenOuter = worldToScreenPoints(polygon.outer);\n if (screenOuter.length >= 4) {\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 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 debugOverlay = Boolean((globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__);\n const imageOuterRing = worldToScreenPoints(\n closeRing([\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ])\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) {\n const debugKey = String(shape.id ?? i);\n const debugSignature = `${imageOuterRing.length}|${closedRings.length}|${holeRings.length}|${shape.invertedFill.fillColor}`;\n if (overlayDebugSnapshotRef.current.get(debugKey) !== debugSignature) {\n overlayDebugSnapshotRef.current.set(debugKey, debugSignature);\n console.debug(\"[open-plant] invertedFill\", {\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 }\n drawInvertedFillMask(ctx, imageOuterRing, holeRings, shape.invertedFill.fillColor);\n }\n\n if (renderRings.length === 0) continue;\n const strokeStyle = mergeStrokeStyle(resolvedStrokeStyle, 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\n if (active) {\n if (tool === \"brush\") {\n drawBrushStrokePreview(ctx);\n drawBrushCursor(ctx);\n } else {\n const preview = buildPreviewCoords();\n 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);\n }\n } else {\n const polygon = worldToScreenPoints(preview);\n if (polygon.length >= 4) {\n drawPath(ctx, polygon, resolvedStrokeStyle, true, true);\n }\n }\n }\n }\n }\n\n // Draw labels last so they stay visually on top.\n if (preparedPersistedRegions.length > 0) {\n for (const entry of preparedPersistedRegions) {\n if (!entry.region.label) continue;\n const anchorWorld = getTopAnchorFromPolygons(entry.polygons);\n if (!anchorWorld) continue;\n const anchorScreen = toCoord(projectorRef.current?.worldToScreen(anchorWorld[0], anchorWorld[1]) ?? []);\n if (!anchorScreen) continue;\n drawRegionLabel(ctx, entry.region.label, anchorScreen, canvasWidth, canvasHeight, resolvedLabelStyle);\n }\n }\n }, [\n active,\n tool,\n buildPreviewCoords,\n drawBrushStrokePreview,\n drawBrushCursor,\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 preparedPatchRegions,\n resolvedPatchStrokeStyle,\n resolveRegionStrokeStyle,\n resolvedLabelStyle,\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 try {\n canvas.releasePointerCapture(session.pointerId);\n } catch {\n // noop\n }\n }\n\n session.isDrawing = false;\n session.pointerId = null;\n session.start = null;\n session.current = null;\n session.points = [];\n session.stampCenter = null;\n if (!preserveCursor) {\n session.cursor = null;\n }\n }, []);\n\n const toWorld = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): 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 finishSession = useCallback(() => {\n const session = sessionRef.current;\n if (!session.isDrawing) {\n resetSession(true);\n requestDraw();\n return;\n }\n\n let coordinates: 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);\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 = resolvedBrushOptions.edgeDetail;\n const minRasterStep = Math.max(\n MIN_BRUSH_RASTER_STEP,\n (resolvedBrushOptions.radius * 2) / (BRUSH_RASTER_DIAMETER_SAMPLES * edgeDetail),\n );\n coordinates = buildBrushStrokePolygon(session.points, {\n radius: resolvedBrushOptions.radius,\n clipBounds: [0, 0, imageWidth, imageHeight],\n minRasterStep,\n circleSides: Math.max(24, Math.round(64 * edgeDetail)),\n simplifyTolerance: minRasterStep * 0.25,\n smoothingPasses: resolvedBrushOptions.edgeSmoothing,\n }) as DrawCoordinate[];\n }\n\n if ((tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\" || tool === \"brush\") && isValidPolygon(coordinates) && onDrawComplete) {\n const intent: 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 }, [tool, onDrawComplete, resetSession, requestDraw, resolvedBrushOptions.radius, resolvedBrushOptions.edgeDetail, resolvedBrushOptions.edgeSmoothing, resolvedBrushOptions.clickSelectRoi, imageWidth, imageHeight, onBrushTap]);\n\n const handleStampAt = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate): void => {\n const coordinates = buildStampCoords(stampTool, center);\n if (!isValidPolygon(coordinates)) return;\n const intent: DrawIntent = stampTool === \"stamp-rectangle-4096px\" ? \"patch\" : \"roi\";\n const result: 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 PatchDrawResult);\n }\n },\n [buildStampCoords, onDrawComplete, onPatchComplete]\n );\n\n const appendBrushPoint = useCallback(\n (session: DrawSession, world: DrawCoordinate): void => {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = BRUSH_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n if (!prev) {\n session.points.push(world);\n session.current = world;\n return;\n }\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 } else {\n session.points[session.points.length - 1] = world;\n }\n session.current = world;\n },\n [projectorRef]\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\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.points = tool === \"freehand\" || tool === \"brush\" ? [world] : [];\n requestDraw();\n },\n [active, tool, toWorld, 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\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n event.preventDefault();\n event.stopPropagation();\n requestDraw();\n return;\n }\n\n const session = sessionRef.current;\n if (tool === \"brush\") {\n session.cursor = world;\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n requestDraw();\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n appendBrushPoint(session, world);\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, 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 if (world) {\n session.cursor = world;\n if (tool === \"brush\") {\n appendBrushPoint(session, world);\n } else {\n session.current = world;\n }\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 finishSession();\n },\n [finishSession, toWorld, 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 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(() => {\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 if (!canvas || typeof projector?.zoomBy !== \"function\") 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 projector.zoomBy(event.deltaY < 0 ? WHEEL_ZOOM_IN_FACTOR : WHEEL_ZOOM_OUT_FACTOR, screenX, screenY);\n requestDraw();\n }}\n />\n );\n}\n","import type { WsiImageSource, WsiTerm } from \"./types\";\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: any, 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(\"이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요\");\n }\n\n const terms: WsiTerm[] = Array.isArray(raw?.terms)\n ? raw.terms.map((term: any) => ({\n termId: String(term?.termId ?? \"\"),\n termName: String(term?.termName ?? \"\"),\n termColor: String(term?.termColor ?? \"\"),\n }))\n : [];\n\n const normalizedPath = ensureLeadingSlash(tilePath);\n const imsTileRoot = joinImsTileRoot(tileBaseUrl);\n const tileUrlBuilder = isIms ? (tier: number, x: number, y: number): string => `${imsTileRoot}${normalizedPath}/${tier}/${y}_${x}.webp` : undefined;\n\n return {\n 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 terms,\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);\n }\n const normalizedPath = ensureLeadingSlash(source.tilePath);\n return `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import {\n\ttype CSSProperties,\n\ttype MutableRefObject,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\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\nexport interface OverviewMapProjector {\n\tgetViewState: () => WsiViewState;\n\tsetViewState: (next: Partial<WsiViewState>) => void;\n\tsetViewCenter?: (worldX: number, worldY: number) => void;\n\tgetViewBounds?: () => number[];\n\tgetViewCorners?: () => Array<[number, number]>;\n}\n\nexport type OverviewMapPosition =\n\t| \"bottom-right\"\n\t| \"bottom-left\"\n\t| \"top-right\"\n\t| \"top-left\";\n\nexport interface OverviewMapOptions {\n\twidth: number;\n\theight: number;\n\tmargin: number;\n\tposition: OverviewMapPosition;\n\tborderRadius: number;\n\tborderWidth: number;\n\tbackgroundColor: string;\n\tborderColor: string;\n\tviewportStrokeColor: string;\n\tviewportFillColor: string;\n\tinteractive: boolean;\n\tshowThumbnail: boolean;\n\tmaxThumbnailTiles: number;\n}\n\nexport interface OverviewMapProps {\n\tsource: WsiImageSource;\n\tprojectorRef: RefObject<OverviewMapProjector | null>;\n\tauthToken?: string;\n\toptions?: Partial<OverviewMapOptions>;\n\tinvalidateRef?: MutableRefObject<(() => void) | null>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n\twidth: 220,\n\theight: 140,\n\tmargin: 16,\n\tposition: \"bottom-right\",\n\tborderRadius: 10,\n\tborderWidth: 1.5,\n\tbackgroundColor: \"rgba(4, 10, 18, 0.88)\",\n\tborderColor: \"rgba(230, 244, 255, 0.35)\",\n\tviewportStrokeColor: \"rgba(255, 106, 61, 0.95)\",\n\tviewportFillColor: \"rgba(255, 106, 61, 0.2)\",\n\tinteractive: true,\n\tshowThumbnail: true,\n\tmaxThumbnailTiles: 16,\n};\n\nfunction toPositiveNumber(\n\tvalue: number | undefined,\n\tfallback: number,\n\tmin = 1,\n): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.max(min, value);\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n\treturn (\n\t\tArray.isArray(bounds) &&\n\t\tbounds.length === 4 &&\n\t\tNumber.isFinite(bounds[0]) &&\n\t\tNumber.isFinite(bounds[1]) &&\n\t\tNumber.isFinite(bounds[2]) &&\n\t\tNumber.isFinite(bounds[3])\n\t);\n}\n\nexport function OverviewMap({\n\tsource,\n\tprojectorRef,\n\tauthToken = \"\",\n\toptions,\n\tinvalidateRef,\n\tclassName,\n\tstyle,\n}: OverviewMapProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n\tconst lastBoundsRef = useRef<Bounds | null>(null);\n\tconst draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n\t\tactive: false,\n\t\tpointerId: null,\n\t});\n\tconst rafRef = useRef<number | null>(null);\n\tconst drawPendingRef = useRef(false);\n\n\tconst width = toPositiveNumber(\n\t\toptions?.width,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.width,\n\t\t64,\n\t);\n\tconst height = toPositiveNumber(\n\t\toptions?.height,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.height,\n\t\t48,\n\t);\n\tconst margin = toPositiveNumber(\n\t\toptions?.margin,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.margin,\n\t\t0,\n\t);\n\tconst borderRadius = toPositiveNumber(\n\t\toptions?.borderRadius,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius,\n\t\t0,\n\t);\n\tconst borderWidth = toPositiveNumber(\n\t\toptions?.borderWidth,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth,\n\t\t0,\n\t);\n\tconst maxThumbnailTiles = Math.max(\n\t\t1,\n\t\tMath.round(\n\t\t\ttoPositiveNumber(\n\t\t\t\toptions?.maxThumbnailTiles,\n\t\t\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles,\n\t\t\t\t1,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst backgroundColor =\n\t\toptions?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n\tconst borderColor =\n\t\toptions?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n\tconst viewportStrokeColor =\n\t\toptions?.viewportStrokeColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportStrokeColor;\n\tconst viewportFillColor =\n\t\toptions?.viewportFillColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n\tconst interactive =\n\t\toptions?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n\tconst showThumbnail =\n\t\toptions?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n\tconst position =\n\t\toptions?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n\n\tconst mergedStyle = useMemo<CSSProperties>(() => {\n\t\tconst pos: CSSProperties = {};\n\t\tif (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n\t\telse pos.right = margin;\n\t\tif (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n\t\telse pos.bottom = margin;\n\n\t\treturn {\n\t\t\tposition: \"absolute\",\n\t\t\t...pos,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tborderRadius,\n\t\t\toverflow: \"hidden\",\n\t\t\tzIndex: 4,\n\t\t\tpointerEvents: interactive ? \"auto\" : \"none\",\n\t\t\ttouchAction: \"none\",\n\t\t\tboxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n\t\t\t...style,\n\t\t};\n\t}, [margin, position, width, height, borderRadius, interactive, style]);\n\n\tconst draw = useCallback(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst ctx = canvas.getContext(\"2d\");\n\t\tif (!ctx) return;\n\n\t\tconst cssW = width;\n\t\tconst cssH = height;\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\t\tif (canvas.width !== pixelW || canvas.height !== pixelH) {\n\t\t\tcanvas.width = pixelW;\n\t\t\tcanvas.height = pixelH;\n\t\t}\n\n\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, cssW, cssH);\n\n\t\tconst preview = thumbnailRef.current;\n\t\tif (preview) {\n\t\t\tctx.drawImage(preview, 0, 0, cssW, cssH);\n\t\t}\n\n\t\tctx.strokeStyle = borderColor;\n\t\tctx.lineWidth = borderWidth;\n\t\tctx.strokeRect(\n\t\t\tborderWidth * 0.5,\n\t\t\tborderWidth * 0.5,\n\t\t\tcssW - borderWidth,\n\t\t\tcssH - borderWidth,\n\t\t);\n\n\t\tconst projector = projectorRef.current;\n\t\tconst bounds = projector?.getViewBounds?.();\n\t\tconst corners = projector?.getViewCorners?.();\n\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t? bounds\n\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t? lastBoundsRef.current\n\t\t\t\t: null;\n\t\tif (!safeBounds) return;\n\t\tlastBoundsRef.current = safeBounds;\n\n\t\tconst sx = cssW / Math.max(1, source.width);\n\t\tconst sy = cssH / Math.max(1, source.height);\n\n\t\tconst safeCorners =\n\t\t\tArray.isArray(corners) &&\n\t\t\tcorners.length >= 4 &&\n\t\t\tcorners.every(\n\t\t\t\t(point) =>\n\t\t\t\t\tArray.isArray(point) &&\n\t\t\t\t\tpoint.length >= 2 &&\n\t\t\t\t\tNumber.isFinite(point[0]) &&\n\t\t\t\t\tNumber.isFinite(point[1]),\n\t\t\t)\n\t\t\t\t? (corners as Array<[number, number]>)\n\t\t\t\t: null;\n\n\t\tif (safeCorners) {\n\t\t\tctx.beginPath();\n\t\t\tfor (let i = 0; i < safeCorners.length; i += 1) {\n\t\t\t\tconst point = safeCorners[i];\n\t\t\t\tconst x = clamp(point[0] * sx, 0, cssW);\n\t\t\t\tconst y = clamp(point[1] * sy, 0, cssH);\n\t\t\t\tif (i === 0) ctx.moveTo(x, y);\n\t\t\t\telse ctx.lineTo(x, y);\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t\tctx.fillStyle = viewportFillColor;\n\t\t\tctx.fill();\n\t\t\tctx.strokeStyle = viewportStrokeColor;\n\t\t\tctx.lineWidth = 1.5;\n\t\t\tctx.stroke();\n\t\t\treturn;\n\t\t}\n\n\t\tconst left = clamp(safeBounds[0] * sx, 0, cssW);\n\t\tconst top = clamp(safeBounds[1] * sy, 0, cssH);\n\t\tconst right = clamp(safeBounds[2] * sx, 0, cssW);\n\t\tconst bottom = clamp(safeBounds[3] * sy, 0, cssH);\n\t\tconst rectW = Math.max(1, right - left);\n\t\tconst rectH = Math.max(1, bottom - top);\n\n\t\tctx.fillStyle = viewportFillColor;\n\t\tctx.fillRect(left, top, rectW, rectH);\n\n\t\tctx.strokeStyle = viewportStrokeColor;\n\t\tctx.lineWidth = 1.5;\n\t\tctx.strokeRect(\n\t\t\tleft + 0.5,\n\t\t\ttop + 0.5,\n\t\t\tMath.max(1, rectW - 1),\n\t\t\tMath.max(1, rectH - 1),\n\t\t);\n\t}, [\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tborderWidth,\n\t\tprojectorRef,\n\t\tsource.width,\n\t\tsource.height,\n\t\tviewportFillColor,\n\t\tviewportStrokeColor,\n\t]);\n\n\tconst requestDraw = useCallback(() => {\n\t\tif (drawPendingRef.current) return;\n\t\tdrawPendingRef.current = true;\n\t\trafRef.current = requestAnimationFrame(() => {\n\t\t\tdrawPendingRef.current = false;\n\t\t\trafRef.current = null;\n\t\t\tdraw();\n\t\t});\n\t}, [draw]);\n\n\tconst toWorldFromClient = useCallback(\n\t\t(clientX: number, clientY: number): [number, number] | null => {\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return null;\n\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tif (!rect.width || !rect.height) return null;\n\n\t\t\tconst nx = clamp((clientX - rect.left) / rect.width, 0, 1);\n\t\t\tconst ny = clamp((clientY - rect.top) / rect.height, 0, 1);\n\t\t\treturn [nx * source.width, ny * source.height];\n\t\t},\n\t\t[source.width, source.height],\n\t);\n\n\tconst recenterTo = useCallback(\n\t\t(worldX: number, worldY: number) => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector) return;\n\n\t\t\tif (projector.setViewCenter) {\n\t\t\t\tprojector.setViewCenter(worldX, worldY);\n\t\t\t\trequestDraw();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bounds = projector.getViewBounds?.();\n\t\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t\t? bounds\n\t\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t\t? lastBoundsRef.current\n\t\t\t\t\t: null;\n\t\t\tif (!safeBounds) return;\n\n\t\t\tconst visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n\t\t\tconst visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n\t\t\tprojector.setViewState({\n\t\t\t\toffsetX: worldX - visibleW * 0.5,\n\t\t\t\toffsetY: worldY - visibleH * 0.5,\n\t\t\t});\n\t\t\trequestDraw();\n\t\t},\n\t\t[projectorRef, requestDraw],\n\t);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!interactive) return;\n\t\t\tif (event.button !== 0) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tcanvas.setPointerCapture(event.pointerId);\n\t\t\tdraggingRef.current = { active: true, pointerId: event.pointerId };\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[interactive, toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerUp = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas && canvas.hasPointerCapture(event.pointerId)) {\n\t\t\t\ttry {\n\t\t\t\t\tcanvas.releasePointerCapture(event.pointerId);\n\t\t\t\t} catch {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\trequestDraw();\n\t\t},\n\t\t[requestDraw],\n\t);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tthumbnailRef.current = null;\n\t\trequestDraw();\n\n\t\tconst tier = 0;\n\t\tconst levelScale = 2 ** (source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(source.height / levelScale);\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\t\tconst tileCount = tilesX * tilesY;\n\n\t\tif (!showThumbnail || tileCount > maxThumbnailTiles) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst preview = document.createElement(\"canvas\");\n\t\tpreview.width = Math.max(1, Math.round(width));\n\t\tpreview.height = Math.max(1, Math.round(height));\n\t\tconst ctx = preview.getContext(\"2d\");\n\t\tif (!ctx) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, preview.width, preview.height);\n\n\t\tconst requests: Array<{\n\t\t\turl: string;\n\t\t\tbounds: Bounds;\n\t\t}> = [];\n\n\t\tfor (let y = 0; y < tilesY; y += 1) {\n\t\t\tfor (let x = 0; x < tilesX; x += 1) {\n\t\t\t\tconst left = x * source.tileSize * levelScale;\n\t\t\t\tconst top = y * source.tileSize * levelScale;\n\t\t\t\tconst right =\n\t\t\t\t\tMath.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom =\n\t\t\t\t\tMath.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\t\t\t\trequests.push({\n\t\t\t\t\turl: toTileUrl(source, tier, x, y),\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvoid Promise.allSettled(\n\t\t\trequests.map(async (tile) => {\n\t\t\t\tconst useAuthHeader = !!authToken;\n\t\t\t\tconst response = await fetch(tile.url, {\n\t\t\t\t\theaders: useAuthHeader ? { Authorization: authToken } : undefined,\n\t\t\t\t});\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\tconst bitmap = await createImageBitmap(await response.blob());\n\t\t\t\treturn { tile, bitmap };\n\t\t\t}),\n\t\t).then((results) => {\n\t\t\tif (cancelled) {\n\t\t\t\tfor (const result of results) {\n\t\t\t\t\tif (result.status === \"fulfilled\") {\n\t\t\t\t\t\tresult.value.bitmap.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sx = preview.width / Math.max(1, source.width);\n\t\t\tconst sy = preview.height / Math.max(1, source.height);\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.status !== \"fulfilled\") continue;\n\t\t\t\tconst {\n\t\t\t\t\ttile: { bounds },\n\t\t\t\t\tbitmap,\n\t\t\t\t} = result.value;\n\t\t\t\tconst dx = bounds[0] * sx;\n\t\t\t\tconst dy = bounds[1] * sy;\n\t\t\t\tconst dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n\t\t\t\tconst dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n\t\t\t\tctx.drawImage(bitmap, dx, dy, dw, dh);\n\t\t\t\tbitmap.close();\n\t\t\t}\n\n\t\t\tthumbnailRef.current = preview;\n\t\t\trequestDraw();\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [\n\t\tsource,\n\t\tauthToken,\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tshowThumbnail,\n\t\tmaxThumbnailTiles,\n\t\trequestDraw,\n\t]);\n\n\tuseEffect(() => {\n\t\trequestDraw();\n\t}, [requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!invalidateRef) return undefined;\n\t\tinvalidateRef.current = requestDraw;\n\t\treturn () => {\n\t\t\tif (invalidateRef.current === requestDraw) {\n\t\t\t\tinvalidateRef.current = null;\n\t\t\t}\n\t\t};\n\t}, [invalidateRef, requestDraw]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\tif (rafRef.current !== null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tdrawPendingRef.current = false;\n\t\t},\n\t\t[],\n\t);\n\n\treturn (\n\t\t<canvas\n\t\t\tref={canvasRef}\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerCancel={handlePointerUp}\n\t\t\tonContextMenu={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t}}\n\t\t\tonWheel={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}}\n\t\t/>\n\t);\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 type { WsiPointData } from \"./types\";\nimport {\n\tpointInAnyPreparedPolygon,\n\tprepareRoiPolygons,\n\ttype RoiCoordinate,\n\ttype RoiGeometry,\n} from \"./roi-geometry\";\n\nexport type { RoiCoordinate };\nexport type RoiPolygon = RoiGeometry;\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\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),\n\t);\n}\n\nexport function filterPointDataByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): WsiPointData | null {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn null;\n\t}\n\n\tconst prepared = prepareRoiPolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tpositions: new Float32Array(0),\n\t\t\tpaletteIndices: new Uint16Array(0),\n\t\t};\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tconst positions = pointData.positions;\n\tconst terms = pointData.paletteIndices;\n\tconst pointIds =\n\t\tpointData.ids instanceof Uint32Array && pointData.ids.length >= count\n\t\t\t? pointData.ids\n\t\t\t: null;\n\n\tconst nextPositions = new Float32Array(count * 2);\n\tconst nextTerms = new Uint16Array(count);\n\tconst nextIds = pointIds ? new Uint32Array(count) : null;\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n\t\tnextPositions[cursor * 2] = x;\n\t\tnextPositions[cursor * 2 + 1] = y;\n\t\tnextTerms[cursor] = terms[i];\n\t\tif (nextIds) {\n\t\t\tnextIds[cursor] = pointIds![i];\n\t\t}\n\t\tcursor += 1;\n\t}\n\n\tconst output: WsiPointData = {\n\t\tcount: cursor,\n\t\tpositions: nextPositions.subarray(0, cursor * 2),\n\t\tpaletteIndices: nextTerms.subarray(0, cursor),\n\t};\n\tif (nextIds) {\n\t\toutput.ids = nextIds.subarray(0, cursor);\n\t}\n\treturn output;\n}\n\nexport function filterPointIndicesByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): Uint32Array {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst prepared = prepareRoiPolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tif (count === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positions = pointData.positions;\n\tconst out = new Uint32Array(count);\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!pointInAnyPreparedPolygon(x, y, prepared)) continue;\n\t\tout[cursor] = i;\n\t\tcursor += 1;\n\t}\n\n\treturn 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\tctx.device.queue.writeBuffer(\n\t\tpositionsBuffer,\n\t\t0,\n\t\tpositions.buffer,\n\t\tpositions.byteOffset,\n\t\tpositionBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tboundsBuffer,\n\t\t0,\n\t\tbounds.buffer,\n\t\tbounds.byteOffset,\n\t\tboundsBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tuniformBuffer,\n\t\t0,\n\t\tnew Uint32Array([safePointCount, boundsCount, 0, 0]),\n\t);\n\n\tconst bindGroup = ctx.device.createBindGroup({\n\t\tlayout: ctx.bindGroupLayout,\n\t\tentries: [\n\t\t\t{ binding: 0, resource: { buffer: positionsBuffer } },\n\t\t\t{ binding: 1, resource: { buffer: boundsBuffer } },\n\t\t\t{ binding: 2, resource: { buffer: outputBuffer } },\n\t\t\t{ binding: 3, resource: { buffer: uniformBuffer } },\n\t\t],\n\t});\n\n\tconst commandEncoder = ctx.device.createCommandEncoder();\n\tconst pass = commandEncoder.beginComputePass();\n\tpass.setPipeline(ctx.pipeline);\n\tpass.setBindGroup(0, bindGroup);\n\tpass.dispatchWorkgroups(Math.ceil(safePointCount / 256));\n\tpass.end();\n\n\tcommandEncoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, outputBytes);\n\tctx.device.queue.submit([commandEncoder.finish()]);\n\n\tawait readBuffer.mapAsync(GPU_MAP_MODE_READ);\n\tconst mapped = readBuffer.getMappedRange();\n\tconst out = new Uint32Array(mapped.slice(0));\n\treadBuffer.unmap();\n\n\tpositionsBuffer.destroy();\n\tboundsBuffer.destroy();\n\toutputBuffer.destroy();\n\tuniformBuffer.destroy();\n\treadBuffer.destroy();\n\n\treturn out;\n}\n","import { filterPointDataByPolygons, type RoiPolygon } from \"./point-clip\";\nimport {\n pointInAnyPreparedPolygon,\n prepareRoiPolygons,\n} from \"./roi-geometry\";\nimport type { WsiPointData } from \"./types\";\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\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\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 return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\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 = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids : null;\n if (safeCount === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\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 (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 return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n ...(pointIds ? { ids: new Uint32Array(0) } : {}),\n },\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 (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 nextTerms = new Uint16Array(candidateCount);\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 nextTerms[cursor] = pointData.paletteIndices[pointIndex];\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: nextTerms.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","import { filterPointDataByPolygons, filterPointIndicesByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { RoiClipWorkerRequest, RoiClipWorkerResponse } from \"./point-clip-worker-protocol\";\nimport type { WsiPointData } from \"./types\";\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\nlet workerInstance: Worker | null = null;\nlet workerSupported = true;\nlet requestId = 1;\nconst pendingById = new Map<number, PendingWorkerRequest>();\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction createWorker(): Worker | null {\n if (!workerSupported) return null;\n if (workerInstance) return workerInstance;\n try {\n const worker = new Worker(new URL(\"../workers/roi-clip-worker.ts\", import.meta.url), { type: \"module\" });\n worker.addEventListener(\"message\", handleWorkerMessage);\n worker.addEventListener(\"error\", handleWorkerError);\n workerInstance = worker;\n return worker;\n } catch {\n workerSupported = false;\n return null;\n }\n}\n\nfunction handleWorkerMessage(event: MessageEvent<RoiClipWorkerResponse>): void {\n const msg = event.data;\n if (!msg) return;\n const pending = pendingById.get(msg.id);\n if (!pending) return;\n pendingById.delete(msg.id);\n\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: Number.isFinite(msg.durationMs) ? msg.durationMs : 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 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 (ids) {\n output.ids = ids.subarray(0, count);\n }\n\n pending.resolve({\n data: output,\n meta: {\n mode: \"worker\",\n durationMs: Number.isFinite(msg.durationMs) ? msg.durationMs : nowMs() - pending.startMs,\n },\n });\n}\n\nfunction handleWorkerError(): void {\n workerSupported = false;\n if (workerInstance) {\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n }\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker crashed\"));\n }\n pendingById.clear();\n}\n\nexport function terminateRoiClipWorker(): void {\n if (!workerInstance) return;\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker terminated\"));\n }\n pendingById.clear();\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 worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n data: filterPointDataByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const termsCopy = pointData.paletteIndices.slice(0, safeCount);\n const idsCopy = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.slice(0, safeCount) : null;\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"data\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n paletteIndices: termsCopy.buffer,\n ids: idsCopy?.buffer,\n polygons: polygons ?? [],\n };\n const transfer: Transferable[] = [positionsCopy.buffer, termsCopy.buffer];\n if (idsCopy) {\n transfer.push(idsCopy.buffer);\n }\n worker.postMessage(msg, transfer);\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 worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n indices: filterPointIndicesByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipIndexResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"index\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-index-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n polygons: polygons ?? [],\n };\n worker.postMessage(msg, [positionsCopy.buffer]);\n });\n}\n","import type { WsiPointData, WsiRegion } from \"./types\";\nimport {\n\tpointInPreparedPolygon,\n\tprepareRoiPolygons,\n\ttype PreparedRoiPolygon,\n\ttype RoiGeometry,\n} from \"./roi-geometry\";\n\nexport interface RoiTermCount {\n\ttermId: string;\n\tpaletteIndex: number;\n\tcount: number;\n}\n\nexport interface RoiPointGroup {\n\tregionId: string | number;\n\tregionIndex: number;\n\ttotalCount: number;\n\ttermCounts: RoiTermCount[];\n}\n\nexport interface RoiPointGroupOptions {\n\tpaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n\tincludeEmptyRegions?: boolean;\n}\n\nexport interface RoiPointGroupStats {\n\tgroups: RoiPointGroup[];\n\tinputPointCount: number;\n\tpointsInsideAnyRegion: number;\n\tunmatchedPointCount: number;\n}\n\ninterface PreparedRegion {\n\tregionId: string | number;\n\tregionIndex: number;\n\tpolygons: PreparedRoiPolygon[];\n\tarea: number;\n}\n\nfunction prepareRegions(regions: readonly WsiRegion[]): PreparedRegion[] {\n\tconst prepared: PreparedRegion[] = [];\n\tfor (let i = 0; i < regions.length; i += 1) {\n\t\tconst region = regions[i];\n\t\tconst polygons = prepareRoiPolygons([region?.coordinates as RoiGeometry | null | undefined]);\n\t\tif (polygons.length === 0) continue;\n\n\t\tlet area = 0;\n\t\tfor (const polygon of polygons) {\n\t\t\tarea += polygon.area;\n\t\t}\n\n\t\tprepared.push({\n\t\t\tregionId: region.id ?? i,\n\t\t\tregionIndex: i,\n\t\t\tpolygons,\n\t\t\tarea: Math.max(1e-6, area),\n\t\t});\n\t}\n\treturn prepared;\n}\n\nfunction resolveTermId(\n\tpaletteIndex: number,\n\tpaletteIndexToTermId: RoiPointGroupOptions[\"paletteIndexToTermId\"],\n): string {\n\tif (Array.isArray(paletteIndexToTermId)) {\n\t\tconst fromArray = paletteIndexToTermId[paletteIndex];\n\t\tif (typeof fromArray === \"string\" && fromArray.length > 0) return fromArray;\n\t}\n\tif (paletteIndexToTermId instanceof Map) {\n\t\tconst fromMap = paletteIndexToTermId.get(paletteIndex);\n\t\tif (typeof fromMap === \"string\" && fromMap.length > 0) return fromMap;\n\t}\n\treturn String(paletteIndex);\n}\n\nexport function computeRoiPointGroups(\n\tpointData: WsiPointData | null | undefined,\n\tregions: readonly WsiRegion[] | null | undefined,\n\toptions: RoiPointGroupOptions = {},\n): RoiPointGroupStats {\n\tconst baseCount = 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),\n\t);\n\n\tlet drawIndices: Uint32Array | null = null;\n\tif (pointData?.drawIndices instanceof Uint32Array) {\n\t\tconst source = pointData.drawIndices;\n\t\tlet valid = source.length;\n\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\tconst idx = source[i];\n\t\t\tif (idx < baseCount) continue;\n\t\t\tvalid -= 1;\n\t\t}\n\t\tif (valid === source.length) {\n\t\t\tdrawIndices = source;\n\t\t} else if (valid > 0) {\n\t\t\tconst filtered = new Uint32Array(valid);\n\t\t\tlet cursor = 0;\n\t\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\t\tconst idx = source[i];\n\t\t\t\tif (idx >= baseCount) continue;\n\t\t\t\tfiltered[cursor] = idx;\n\t\t\t\tcursor += 1;\n\t\t\t}\n\t\t\tdrawIndices = filtered;\n\t\t} else {\n\t\t\tdrawIndices = new Uint32Array(0);\n\t\t}\n\t}\n\n\tconst inputCount = drawIndices ? drawIndices.length : baseCount;\n\n\tconst preparedRegions = prepareRegions(regions ?? []);\n\tif (!pointData || inputCount === 0 || preparedRegions.length === 0) {\n\t\treturn {\n\t\t\tgroups: [],\n\t\t\tinputPointCount: inputCount,\n\t\t\tpointsInsideAnyRegion: 0,\n\t\t\tunmatchedPointCount: inputCount,\n\t\t};\n\t}\n\n\tconst regionTermCounters = new Map<number, Map<number, number>>();\n\tconst regionTotalCounters = new Map<number, number>();\n\tlet insideCount = 0;\n\n\tfor (let i = 0; i < inputCount; i += 1) {\n\t\tconst pointIndex = drawIndices ? drawIndices[i] : i;\n\t\tconst x = pointData.positions[pointIndex * 2];\n\t\tconst y = pointData.positions[pointIndex * 2 + 1];\n\t\tlet bestRegion: PreparedRegion | null = null;\n\n\t\tfor (const region of preparedRegions) {\n\t\t\tlet inside = false;\n\t\t\tfor (const polygon of region.polygons) {\n\t\t\t\tif (!pointInPreparedPolygon(x, y, polygon)) continue;\n\t\t\t\tinside = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!inside) continue;\n\t\t\tif (!bestRegion || region.area < bestRegion.area) {\n\t\t\t\tbestRegion = region;\n\t\t\t}\n\t\t}\n\n\t\tif (!bestRegion) continue;\n\t\tinsideCount += 1;\n\n\t\tconst paletteIndex = pointData.paletteIndices[pointIndex] ?? 0;\n\t\tconst regionTermMap =\n\t\t\tregionTermCounters.get(bestRegion.regionIndex) ?? new Map<number, number>();\n\t\tregionTermMap.set(paletteIndex, (regionTermMap.get(paletteIndex) ?? 0) + 1);\n\t\tregionTermCounters.set(bestRegion.regionIndex, regionTermMap);\n\t\tregionTotalCounters.set(\n\t\t\tbestRegion.regionIndex,\n\t\t\t(regionTotalCounters.get(bestRegion.regionIndex) ?? 0) + 1,\n\t\t);\n\t}\n\n\tconst includeEmptyRegions = options.includeEmptyRegions ?? false;\n\tconst groups: RoiPointGroup[] = [];\n\tfor (const region of preparedRegions) {\n\t\tconst totalCount = regionTotalCounters.get(region.regionIndex) ?? 0;\n\t\tif (!includeEmptyRegions && totalCount <= 0) continue;\n\t\tconst termMap = regionTermCounters.get(region.regionIndex) ?? new Map();\n\t\tconst termCounts: RoiTermCount[] = Array.from(termMap.entries())\n\t\t\t.map(([paletteIndex, count]) => ({\n\t\t\t\ttermId: resolveTermId(paletteIndex, options.paletteIndexToTermId),\n\t\t\t\tpaletteIndex,\n\t\t\t\tcount,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.count - a.count || a.paletteIndex - b.paletteIndex);\n\n\t\tgroups.push({\n\t\t\tregionId: region.regionId,\n\t\t\tregionIndex: region.regionIndex,\n\t\t\ttotalCount,\n\t\t\ttermCounts,\n\t\t});\n\t}\n\n\treturn {\n\t\tgroups,\n\t\tinputPointCount: inputCount,\n\t\tpointsInsideAnyRegion: insideCount,\n\t\tunmatchedPointCount: Math.max(0, inputCount - insideCount),\n\t};\n}\n","export 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 nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\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 = window.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\twindow.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 { toTileUrl } from \"./image-info\";\nimport {\n\tTileScheduler,\n\ttype ScheduledTile,\n\ttype TileBounds,\n} from \"./tile-scheduler\";\nimport type {\n\tWsiImageSource,\n\tWsiPointData,\n\tWsiRenderStats,\n\tWsiViewState,\n} from \"./types\";\nimport { clamp, createProgram } from \"./utils\";\n\ntype Bounds = TileBounds;\n\ninterface CachedTile {\n\tkey: string;\n\ttexture: WebGLTexture;\n\tbounds: Bounds;\n\ttier: number;\n\tlastUsed: number;\n}\n\ninterface TileVertexProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tvbo: WebGLBuffer;\n\tuCamera: WebGLUniformLocation;\n\tuBounds: WebGLUniformLocation;\n\tuTexture: WebGLUniformLocation;\n}\n\ninterface PointProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tposBuffer: WebGLBuffer;\n\ttermBuffer: WebGLBuffer;\n\tindexBuffer: WebGLBuffer;\n\tpaletteTexture: WebGLTexture;\n\tuCamera: WebGLUniformLocation;\n\tuPointSize: WebGLUniformLocation;\n\tuPalette: WebGLUniformLocation;\n\tuPaletteSize: WebGLUniformLocation;\n\tuPointStrokeScale: WebGLUniformLocation;\n}\n\ninterface OrthoViewport {\n\twidth: number;\n\theight: number;\n}\n\ntype WorldPoint = [number, number];\nconst DEFAULT_ROTATION_DRAG_SENSITIVITY = 0.35;\nconst MIN_POINT_SIZE_PX = 0.5;\nconst MAX_POINT_SIZE_PX = 256;\n\ninterface PointSizeStop {\n\tzoom: number;\n\tsize: number;\n}\n\nconst DEFAULT_POINT_SIZE_STOPS: readonly PointSizeStop[] = [\n\t{ zoom: 1, size: 2.8 },\n\t{ zoom: 2, size: 3.4 },\n\t{ zoom: 3, size: 4.2 },\n\t{ zoom: 4, size: 5.3 },\n\t{ zoom: 5, size: 6.8 },\n\t{ zoom: 6, size: 8.4 },\n\t{ zoom: 7, size: 9.8 },\n\t{ zoom: 8, size: 11.2 },\n\t{ zoom: 9, size: 14.0 },\n\t{ zoom: 10, size: 17.5 },\n\t{ zoom: 11, size: 22.0 },\n\t{ zoom: 12, size: 28.0 },\n];\n\nexport type PointSizeByZoom = Readonly<Record<number, number>>;\n\nexport interface WsiTileSchedulerConfig {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n}\n\nexport interface WsiTileRendererOptions {\n\tonViewStateChange?: (next: WsiViewState) => void;\n\tonStats?: (stats: WsiRenderStats) => void;\n\tauthToken?: string;\n\tpointSizeByZoom?: PointSizeByZoom;\n\tpointStrokeScale?: number;\n\tmaxCacheTiles?: number;\n\tctrlDragRotate?: boolean;\n\trotationDragSensitivityDegPerPixel?: number;\n\ttileScheduler?: WsiTileSchedulerConfig;\n\tonTileError?: (event: WsiTileErrorEvent) => void;\n\tonContextLost?: () => void;\n\tonContextRestored?: () => void;\n}\n\nexport interface WsiTileErrorEvent {\n\ttile: ScheduledTile;\n\terror: unknown;\n\tattemptCount: number;\n}\n\nclass OrthoCamera {\n\tprivate viewportWidth = 1;\n\tprivate viewportHeight = 1;\n\tprivate viewState: WsiViewState = {\n\t\tzoom: 1,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\trotationDeg: 0,\n\t};\n\n\tsetViewport(width: number, height: number): void {\n\t\tthis.viewportWidth = Math.max(1, width);\n\t\tthis.viewportHeight = Math.max(1, height);\n\t}\n\n\tgetViewport(): OrthoViewport {\n\t\treturn { width: this.viewportWidth, height: this.viewportHeight };\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tif (typeof next.zoom === \"number\") {\n\t\t\tthis.viewState.zoom = Math.max(0.0001, next.zoom);\n\t\t}\n\t\tif (typeof next.offsetX === \"number\") {\n\t\t\tthis.viewState.offsetX = next.offsetX;\n\t\t}\n\t\tif (typeof next.offsetY === \"number\") {\n\t\t\tthis.viewState.offsetY = next.offsetY;\n\t\t}\n\t\tif (typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg)) {\n\t\t\tthis.viewState.rotationDeg = next.rotationDeg;\n\t\t}\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn { ...this.viewState };\n\t}\n\n\tgetCenter(): WorldPoint {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\treturn [\n\t\t\tthis.viewState.offsetX + this.viewportWidth / (2 * zoom),\n\t\t\tthis.viewState.offsetY + this.viewportHeight / (2 * zoom),\n\t\t];\n\t}\n\n\tsetCenter(centerX: number, centerY: number): void {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tthis.viewState.offsetX = centerX - this.viewportWidth / (2 * zoom);\n\t\tthis.viewState.offsetY = centerY - this.viewportHeight / (2 * zoom);\n\t}\n\n\tscreenToWorld(screenX: number, screenY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = (screenX - this.viewportWidth * 0.5) / zoom;\n\t\tconst dy = (screenY - this.viewportHeight * 0.5) / zoom;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\treturn [centerX + dx * cos - dy * sin, centerY + dx * sin + dy * cos];\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = worldX - centerX;\n\t\tconst dy = worldY - centerY;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst rx = dx * cos + dy * sin;\n\t\tconst ry = -dx * sin + dy * cos;\n\t\treturn [\n\t\t\tthis.viewportWidth * 0.5 + rx * zoom,\n\t\t\tthis.viewportHeight * 0.5 + ry * zoom,\n\t\t];\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\tconst w = this.viewportWidth;\n\t\tconst h = this.viewportHeight;\n\t\treturn [\n\t\t\tthis.screenToWorld(0, 0),\n\t\t\tthis.screenToWorld(w, 0),\n\t\t\tthis.screenToWorld(w, h),\n\t\t\tthis.screenToWorld(0, h),\n\t\t];\n\t}\n\n\tgetMatrix(): Float32Array {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst rad = toRadians(this.viewState.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\n\t\tconst ax = (2 * zoom * cos) / this.viewportWidth;\n\t\tconst bx = (2 * zoom * sin) / this.viewportWidth;\n\t\tconst ay = (2 * zoom * sin) / this.viewportHeight;\n\t\tconst by = (-2 * zoom * cos) / this.viewportHeight;\n\t\tconst tx = -(ax * centerX + bx * centerY);\n\t\tconst ty = -(ay * centerX + by * centerY);\n\n\t\treturn new Float32Array([ax, ay, 0, bx, by, 0, tx, ty, 1]);\n\t}\n}\n\nfunction toRadians(deg: number): number {\n\treturn (deg * Math.PI) / 180;\n}\n\nfunction nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nfunction requireUniformLocation(\n\tgl: WebGL2RenderingContext,\n\tprogram: WebGLProgram,\n\tname: string,\n): WebGLUniformLocation {\n\tconst location = gl.getUniformLocation(program, name);\n\tif (!location) {\n\t\tthrow new Error(`uniform location lookup failed: ${name}`);\n\t}\n\treturn location;\n}\n\nfunction isSameArrayView(\n\ta: ArrayBufferView | null | undefined,\n\tb: ArrayBufferView | null | undefined,\n): boolean {\n\tif (!a || !b) return a === b;\n\treturn (\n\t\ta.buffer === b.buffer &&\n\t\ta.byteOffset === b.byteOffset &&\n\t\ta.byteLength === b.byteLength\n\t);\n}\n\nfunction clonePointSizeStops(stops: readonly PointSizeStop[]): PointSizeStop[] {\n\treturn stops.map(stop => ({ zoom: stop.zoom, size: stop.size }));\n}\n\nfunction normalizePointSizeStops(pointSizeByZoom: PointSizeByZoom | null | undefined): PointSizeStop[] {\n\tif (!pointSizeByZoom) return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\n\tconst parsed = new Map<number, number>();\n\tfor (const [zoomKey, rawSize] of Object.entries(pointSizeByZoom)) {\n\t\tconst zoom = Number(zoomKey);\n\t\tconst size = Number(rawSize);\n\t\tif (!Number.isFinite(zoom) || !Number.isFinite(size) || size <= 0) continue;\n\t\tparsed.set(zoom, size);\n\t}\n\n\tif (parsed.size === 0) {\n\t\treturn clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\t}\n\n\treturn Array.from(parsed.entries())\n\t\t.sort((a, b) => a[0] - b[0])\n\t\t.map(([zoom, size]) => ({ zoom, size }));\n}\n\nfunction arePointSizeStopsEqual(a: readonly PointSizeStop[], b: readonly PointSizeStop[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tif (a[i].zoom !== b[i].zoom || a[i].size !== b[i].size) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction resolvePointSizeByZoomStops(continuousZoom: number, stops: readonly PointSizeStop[]): number {\n\tif (!Number.isFinite(continuousZoom)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n\tif (stops.length === 0) return MIN_POINT_SIZE_PX;\n\tif (stops.length === 1) return stops[0].size;\n\tif (continuousZoom <= stops[0].zoom) return stops[0].size;\n\n\tfor (let i = 1; i < stops.length; i += 1) {\n\t\tconst prev = stops[i - 1];\n\t\tconst next = stops[i];\n\t\tif (continuousZoom > next.zoom) continue;\n\t\tconst span = Math.max(1e-6, next.zoom - prev.zoom);\n\t\tconst t = clamp((continuousZoom - prev.zoom) / span, 0, 1);\n\t\treturn prev.size + (next.size - prev.size) * t;\n\t}\n\n\tconst last = stops[stops.length - 1];\n\tconst prev = stops[stops.length - 2];\n\tconst span = Math.max(1e-6, last.zoom - prev.zoom);\n\tconst slope = (last.size - prev.size) / span;\n\treturn last.size + (continuousZoom - last.zoom) * slope;\n}\n\nconst MIN_STROKE_SCALE = 0.1;\nconst MAX_STROKE_SCALE = 5.0;\n\nfunction normalizeStrokeScale(value: number | null | undefined): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return 1.0;\n\treturn clamp(value, MIN_STROKE_SCALE, MAX_STROKE_SCALE);\n}\n\nexport class WsiTileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly source: WsiImageSource;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly onViewStateChange?: (next: WsiViewState) => void;\n\tprivate readonly onStats?: (stats: WsiRenderStats) => void;\n\tprivate readonly onTileError?: (event: WsiTileErrorEvent) => void;\n\tprivate readonly onContextLost?: () => void;\n\tprivate readonly onContextRestored?: () => void;\n\tprivate readonly resizeObserver: ResizeObserver;\n\tprivate tileProgram: TileVertexProgram;\n\tprivate pointProgram: PointProgram;\n\tprivate readonly tileScheduler: TileScheduler;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate contextLost = false;\n\tprivate frame: number | null = null;\n\tprivate frameSerial = 0;\n\tprivate dragging = false;\n\tprivate interactionMode: \"none\" | \"pan\" | \"rotate\" = \"none\";\n\tprivate rotateLastAngleRad: number | null = null;\n\tprivate pointerId: number | null = null;\n\tprivate lastPointerX = 0;\n\tprivate lastPointerY = 0;\n\tprivate interactionLocked = false;\n\tprivate ctrlDragRotate = true;\n\tprivate rotationDragSensitivityDegPerPixel = 0.35;\n\tprivate maxCacheTiles: number;\n\tprivate fitZoom = 1;\n\tprivate minZoom = 1e-6;\n\tprivate maxZoom = 1;\n\tprivate currentTier = 0;\n\tprivate pointCount = 0;\n\tprivate usePointIndices = false;\n\tprivate pointBuffersDirty = true;\n\tprivate pointPaletteSize = 1;\n\tprivate pointSizeStops: PointSizeStop[] = clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\tprivate pointStrokeScale = 1.0;\n\tprivate lastPointData: WsiPointData | null = null;\n\tprivate lastPointPalette: Uint8Array | null = null;\n\tprivate cache = new Map<string, CachedTile>();\n\n\tprivate readonly boundPointerDown: (event: PointerEvent) => void;\n\tprivate readonly boundPointerMove: (event: PointerEvent) => void;\n\tprivate readonly boundPointerUp: (event: PointerEvent) => void;\n\tprivate readonly boundWheel: (event: WheelEvent) => void;\n\tprivate readonly boundDoubleClick: (event: MouseEvent) => void;\n\tprivate readonly boundContextMenu: (event: MouseEvent) => void;\n\tprivate readonly boundContextLost: (event: Event) => void;\n\tprivate readonly boundContextRestored: (event: Event) => void;\n\n\tconstructor(\n\t\tcanvas: HTMLCanvasElement,\n\t\tsource: WsiImageSource,\n\t\toptions: WsiTileRendererOptions = {},\n\t) {\n\t\tthis.canvas = canvas;\n\t\tthis.source = source;\n\t\tthis.onViewStateChange = options.onViewStateChange;\n\t\tthis.onStats = options.onStats;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onContextLost = options.onContextLost;\n\t\tthis.onContextRestored = options.onContextRestored;\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.maxCacheTiles = Math.max(32, Math.floor(options.maxCacheTiles ?? 320));\n\t\tthis.ctrlDragRotate = options.ctrlDragRotate ?? true;\n\t\tthis.rotationDragSensitivityDegPerPixel =\n\t\t\ttypeof options.rotationDragSensitivityDegPerPixel === \"number\" &&\n\t\t\tNumber.isFinite(options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t? Math.max(0, options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t: DEFAULT_ROTATION_DRAG_SENSITIVITY;\n\t\tthis.pointSizeStops = normalizePointSizeStops(options.pointSizeByZoom);\n\t\tthis.pointStrokeScale = normalizeStrokeScale(options.pointStrokeScale);\n\n\t\tconst gl = canvas.getContext(\"webgl2\", {\n\t\t\talpha: false,\n\t\t\tantialias: false,\n\t\t\tdepth: false,\n\t\t\tstencil: false,\n\t\t\tpowerPreference: \"high-performance\",\n\t\t});\n\t\tif (!gl) {\n\t\t\tthrow new Error(\"WebGL2 not supported\");\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.tileScheduler = new TileScheduler({\n\t\t\tauthToken: this.authToken,\n\t\t\tmaxConcurrency: options.tileScheduler?.maxConcurrency ?? 12,\n\t\t\tmaxRetries: options.tileScheduler?.maxRetries ?? 2,\n\t\t\tretryBaseDelayMs: options.tileScheduler?.retryBaseDelayMs ?? 120,\n\t\t\tretryMaxDelayMs: options.tileScheduler?.retryMaxDelayMs ?? 1200,\n\t\t\tonTileLoad: (tile, bitmap) => this.handleTileLoaded(tile, bitmap),\n\t\t\tonTileError: (tile, error, attemptCount) => {\n\t\t\t\tthis.onTileError?.({ tile, error, attemptCount });\n\t\t\t\tconsole.warn(\"tile load failed\", tile.url, error);\n\t\t\t},\n\t\t});\n\n\t\tthis.resizeObserver = new ResizeObserver(() => this.resize());\n\t\tthis.resizeObserver.observe(canvas);\n\n\t\tthis.boundPointerDown = (event: PointerEvent) => this.onPointerDown(event);\n\t\tthis.boundPointerMove = (event: PointerEvent) => this.onPointerMove(event);\n\t\tthis.boundPointerUp = (event: PointerEvent) => this.onPointerUp(event);\n\t\tthis.boundWheel = (event: WheelEvent) => this.onWheel(event);\n\t\tthis.boundDoubleClick = (event: MouseEvent) => this.onDoubleClick(event);\n\t\tthis.boundContextMenu = (event: MouseEvent) => this.onContextMenu(event);\n\t\tthis.boundContextLost = (event: Event) => this.onWebGlContextLost(event);\n\t\tthis.boundContextRestored = (event: Event) =>\n\t\t\tthis.onWebGlContextRestored(event);\n\n\t\tcanvas.addEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tcanvas.addEventListener(\"pointermove\", this.boundPointerMove);\n\t\tcanvas.addEventListener(\"pointerup\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"wheel\", this.boundWheel, { passive: false });\n\t\tcanvas.addEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tcanvas.addEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tcanvas.addEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tcanvas.addEventListener(\"webglcontextrestored\", this.boundContextRestored);\n\n\t\tthis.fitToImage();\n\t\tthis.resize();\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t\tthis.tileScheduler.setAuthToken(this.authToken);\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tconst normalized: Partial<WsiViewState> = { ...next };\n\t\tif (typeof normalized.zoom === \"number\") {\n\t\t\tnormalized.zoom = clamp(normalized.zoom, this.minZoom, this.maxZoom);\n\t\t}\n\t\tthis.camera.setViewState(normalized);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tsetPointPalette(colors: Uint8Array | null | undefined): void {\n\t\tif (!colors || colors.length === 0) {\n\t\t\tthis.lastPointPalette = null;\n\t\t\treturn;\n\t\t}\n\t\tthis.lastPointPalette = new Uint8Array(colors);\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\t\tconst gl = this.gl;\n\t\tconst paletteSize = Math.max(1, Math.floor(this.lastPointPalette.length / 4));\n\t\tthis.pointPaletteSize = paletteSize;\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.pointProgram.paletteTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tpaletteSize,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tthis.lastPointPalette,\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tthis.requestRender();\n\t}\n\n\tsetPointData(points: WsiPointData | null | undefined): void {\n\t\tif (!points || !points.count || !points.positions || !points.paletteIndices) {\n\t\t\tthis.lastPointData = null;\n\t\t\tthis.pointCount = 0;\n\t\t\tthis.usePointIndices = false;\n\t\t\tthis.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst safeCount = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tpoints.count,\n\t\t\t\tMath.floor(points.positions.length / 2),\n\t\t\t\tpoints.paletteIndices.length,\n\t\t\t),\n\t\t);\n\t\tconst nextPositions = points.positions.subarray(0, safeCount * 2);\n\t\tconst nextPaletteIndices = points.paletteIndices.subarray(0, safeCount);\n\t\tconst hasDrawIndices = points.drawIndices instanceof Uint32Array;\n\t\tconst nextDrawIndices = hasDrawIndices\n\t\t\t? this.sanitizeDrawIndices(points.drawIndices as Uint32Array, safeCount)\n\t\t\t: null;\n\t\tconst prev = this.lastPointData;\n\t\tlet geometryChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t!prev ||\n\t\t\tprev.count !== safeCount ||\n\t\t\t!isSameArrayView(prev.positions, nextPositions) ||\n\t\t\t!isSameArrayView(prev.paletteIndices, nextPaletteIndices);\n\t\tlet drawIndicesChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t(hasDrawIndices &&\n\t\t\t\t(!prev?.drawIndices ||\n\t\t\t\t\t!isSameArrayView(prev.drawIndices, nextDrawIndices))) ||\n\t\t\t(!hasDrawIndices && !!prev?.drawIndices);\n\n\t\tthis.lastPointData = {\n\t\t\tcount: safeCount,\n\t\t\tpositions: nextPositions,\n\t\t\tpaletteIndices: nextPaletteIndices,\n\t\t\tdrawIndices: hasDrawIndices ? nextDrawIndices ?? undefined : undefined,\n\t\t};\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\n\t\tconst gl = this.gl;\n\t\tif (geometryChanged) {\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.posBuffer);\n\t\t\tgl.bufferData(gl.ARRAY_BUFFER, this.lastPointData.positions, gl.STATIC_DRAW);\n\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.termBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ARRAY_BUFFER,\n\t\t\t\tthis.lastPointData.paletteIndices,\n\t\t\t\tgl.STATIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\t}\n\n\t\tif (hasDrawIndices && drawIndicesChanged) {\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.pointProgram.indexBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ELEMENT_ARRAY_BUFFER,\n\t\t\t\tnextDrawIndices ?? new Uint32Array(0),\n\t\t\t\tgl.DYNAMIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\t\t}\n\n\t\tthis.usePointIndices = hasDrawIndices;\n\t\tthis.pointCount = hasDrawIndices\n\t\t\t? (nextDrawIndices?.length ?? 0)\n\t\t\t: this.lastPointData.count;\n\t\tif (geometryChanged || drawIndicesChanged) {\n\t\t\tthis.pointBuffersDirty = false;\n\t\t}\n\t\tthis.requestRender();\n\t}\n\n\tprivate sanitizeDrawIndices(\n\t\tdrawIndices: Uint32Array,\n\t\tmaxExclusive: number,\n\t): Uint32Array {\n\t\tif (maxExclusive <= 0 || drawIndices.length === 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tlet validCount = drawIndices.length;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tif (drawIndices[i] < maxExclusive) continue;\n\t\t\tvalidCount -= 1;\n\t\t}\n\t\tif (validCount === drawIndices.length) {\n\t\t\treturn drawIndices;\n\t\t}\n\t\tif (validCount <= 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tconst filtered = new Uint32Array(validCount);\n\t\tlet cursor = 0;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tconst idx = drawIndices[i];\n\t\t\tif (idx >= maxExclusive) continue;\n\t\t\tfiltered[cursor] = idx;\n\t\t\tcursor += 1;\n\t\t}\n\t\treturn filtered;\n\t}\n\n\tsetInteractionLock(locked: boolean): void {\n\t\tconst next = Boolean(locked);\n\t\tif (this.interactionLocked === next) return;\n\t\tthis.interactionLocked = next;\n\t\tif (next) this.cancelDrag();\n\t}\n\n\tsetPointSizeByZoom(pointSizeByZoom: PointSizeByZoom | null | undefined): void {\n\t\tconst nextStops = normalizePointSizeStops(pointSizeByZoom);\n\t\tif (arePointSizeStopsEqual(this.pointSizeStops, nextStops)) return;\n\t\tthis.pointSizeStops = nextStops;\n\t\tthis.requestRender();\n\t}\n\n\tsetPointStrokeScale(scale: number | null | undefined): void {\n\t\tconst next = normalizeStrokeScale(scale);\n\t\tif (this.pointStrokeScale === next) return;\n\t\tthis.pointStrokeScale = next;\n\t\tthis.requestRender();\n\t}\n\n\tcancelDrag(): void {\n\t\tif (this.pointerId !== null && this.canvas.hasPointerCapture(this.pointerId)) {\n\t\t\ttry {\n\t\t\t\tthis.canvas.releasePointerCapture(this.pointerId);\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\t\tthis.dragging = false;\n\t\tthis.interactionMode = \"none\";\n\t\tthis.rotateLastAngleRad = null;\n\t\tthis.pointerId = null;\n\t\tthis.canvas.classList.remove(\"dragging\");\n\t}\n\n\tprivate getPointerAngleRad(clientX: number, clientY: number): number {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = clientX - rect.left - rect.width * 0.5;\n\t\tconst y = clientY - rect.top - rect.height * 0.5;\n\t\treturn Math.atan2(y, x);\n\t}\n\n\tscreenToWorld(clientX: number, clientY: number): [number, number] {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst sx = clientX - rect.left;\n\t\tconst sy = clientY - rect.top;\n\t\treturn this.camera.screenToWorld(sx, sy);\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): [number, number] {\n\t\treturn this.camera.worldToScreen(worldX, worldY);\n\t}\n\n\tsetViewCenter(worldX: number, worldY: number): void {\n\t\tif (!Number.isFinite(worldX) || !Number.isFinite(worldY)) return;\n\t\tthis.camera.setCenter(worldX, worldY);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\treturn this.camera.getViewCorners();\n\t}\n\n\tresetRotation(): void {\n\t\tconst state = this.camera.getViewState();\n\t\tif (Math.abs(state.rotationDeg) < 1e-6) return;\n\t\tthis.camera.setViewState({ rotationDeg: 0 });\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetPointSizeByZoom(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n\t\tconst size = resolvePointSizeByZoomStops(continuousZoom, this.pointSizeStops);\n\t\treturn clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n\t}\n\n\tfitToImage(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst vw = Math.max(1, rect.width || 1);\n\t\tconst vh = Math.max(1, rect.height || 1);\n\n\t\tconst zoom = Math.min(vw / this.source.width, vh / this.source.height);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tthis.fitZoom = safeZoom;\n\t\tthis.minZoom = Math.max(this.fitZoom * 0.5, 1e-6);\n\t\tthis.maxZoom = Math.max(1, this.fitZoom * 8);\n\t\tif (this.minZoom > this.maxZoom) {\n\t\t\tthis.minZoom = this.maxZoom;\n\t\t}\n\n\t\tconst visibleWorldW = vw / safeZoom;\n\t\tconst visibleWorldH = vh / safeZoom;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: clamp(safeZoom, this.minZoom, this.maxZoom),\n\t\t\toffsetX: (this.source.width - visibleWorldW) * 0.5,\n\t\t\toffsetY: (this.source.height - visibleWorldH) * 0.5,\n\t\t\trotationDeg: 0,\n\t\t});\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tzoomBy(factor: number, screenX: number, screenY: number): void {\n\t\tconst state = this.camera.getViewState();\n\t\tconst nextZoom = clamp(state.zoom * factor, this.minZoom, this.maxZoom);\n\t\tif (nextZoom === state.zoom) return;\n\n\t\tconst [worldX, worldY] = this.camera.screenToWorld(screenX, screenY);\n\n\t\tthis.camera.setViewState({ zoom: nextZoom });\n\n\t\tconst vp = this.camera.getViewport();\n\t\tconst dx = screenX - vp.width * 0.5;\n\t\tconst dy = screenY - vp.height * 0.5;\n\t\tconst rad = toRadians(this.camera.getViewState().rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n\t\tconst worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n\t\tthis.camera.setCenter(worldX - worldDx, worldY - worldDy);\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tclampViewState(): void {\n\t\tconst bounds = this.getViewBounds();\n\t\tconst visibleW = Math.max(1e-6, bounds[2] - bounds[0]);\n\t\tconst visibleH = Math.max(1e-6, bounds[3] - bounds[1]);\n\t\tconst marginX = visibleW * 0.2;\n\t\tconst marginY = visibleH * 0.2;\n\n\t\tconst [centerX, centerY] = this.camera.getCenter();\n\t\tconst halfW = visibleW * 0.5;\n\t\tconst halfH = visibleH * 0.5;\n\n\t\tconst minCenterX = halfW - marginX;\n\t\tconst maxCenterX = this.source.width - halfW + marginX;\n\t\tconst minCenterY = halfH - marginY;\n\t\tconst maxCenterY = this.source.height - halfH + marginY;\n\n\t\tconst nextCenterX =\n\t\t\tminCenterX <= maxCenterX\n\t\t\t\t? clamp(centerX, minCenterX, maxCenterX)\n\t\t\t\t: this.source.width * 0.5;\n\t\tconst nextCenterY =\n\t\t\tminCenterY <= maxCenterY\n\t\t\t\t? clamp(centerY, minCenterY, maxCenterY)\n\t\t\t\t: this.source.height * 0.5;\n\n\t\tthis.camera.setCenter(nextCenterX, nextCenterY);\n\t}\n\n\temitViewState(): void {\n\t\tthis.onViewStateChange?.(this.camera.getViewState());\n\t}\n\n\tselectTier(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst rawTier = this.source.maxTierZoom + Math.log2(zoom);\n\t\treturn clamp(Math.floor(rawTier), 0, this.source.maxTierZoom);\n\t}\n\n\tgetViewBounds(): Bounds {\n\t\tconst corners = this.camera.getViewCorners();\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of corners) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\treturn [minX, minY, maxX, maxY];\n\t}\n\n\tintersectsBounds(a: Bounds, b: Bounds): boolean {\n\t\treturn !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n\t}\n\n\tgetVisibleTiles(): ScheduledTile[] {\n\t\tconst tier = this.selectTier();\n\t\tthis.currentTier = tier;\n\n\t\tconst viewBounds = this.getViewBounds();\n\n\t\tconst levelScale = Math.pow(2, this.source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(this.source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(this.source.height / levelScale);\n\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / this.source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / this.source.tileSize));\n\n\t\tconst viewMinX = viewBounds[0];\n\t\tconst viewMinY = viewBounds[1];\n\t\tconst viewMaxX = viewBounds[2];\n\t\tconst viewMaxY = viewBounds[3];\n\n\t\tconst minTileX = clamp(\n\t\t\tMath.floor(viewMinX / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst maxTileX = clamp(\n\t\t\tMath.floor((viewMaxX - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst minTileY = clamp(\n\t\t\tMath.floor(viewMinY / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\t\tconst maxTileY = clamp(\n\t\t\tMath.floor((viewMaxY - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\n\t\tif (minTileX > maxTileX || minTileY > maxTileY) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst centerTileX = (viewMinX + viewMaxX) * 0.5 / levelScale / this.source.tileSize;\n\t\tconst centerTileY = (viewMinY + viewMaxY) * 0.5 / levelScale / this.source.tileSize;\n\n\t\tconst visible: ScheduledTile[] = [];\n\t\tfor (let y = minTileY; y <= maxTileY; y += 1) {\n\t\t\tfor (let x = minTileX; x <= maxTileX; x += 1) {\n\t\t\t\tconst left = x * this.source.tileSize * levelScale;\n\t\t\t\tconst top = y * this.source.tileSize * levelScale;\n\t\t\t\tconst right = Math.min((x + 1) * this.source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom = Math.min((y + 1) * this.source.tileSize, levelHeight) * levelScale;\n\n\t\t\t\tconst dx = x - centerTileX;\n\t\t\t\tconst dy = y - centerTileY;\n\t\t\t\tvisible.push({\n\t\t\t\t\tkey: `${tier}/${x}/${y}`,\n\t\t\t\t\ttier,\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t\tdistance2: dx * dx + dy * dy,\n\t\t\t\t\turl: toTileUrl(this.source, tier, x, y),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvisible.sort((a, b) => a.distance2 - b.distance2);\n\t\treturn visible;\n\t}\n\n\ttrimCache(): void {\n\t\tif (this.cache.size <= this.maxCacheTiles) return;\n\n\t\tconst entries = Array.from(this.cache.entries());\n\t\tentries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n\n\t\tconst removeCount = this.cache.size - this.maxCacheTiles;\n\t\tfor (let i = 0; i < removeCount; i += 1) {\n\t\t\tconst [key, value] = entries[i];\n\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\tthis.cache.delete(key);\n\t\t}\n\t}\n\n\trender(): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n\t\tconst frameStartMs = nowMs();\n\t\tthis.frameSerial += 1;\n\n\t\tconst gl = this.gl;\n\t\tconst tileProgram = this.tileProgram;\n\t\tconst pointProgram = this.pointProgram;\n\n\t\tgl.clearColor(0.03, 0.06, 0.1, 1);\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\tconst visible = this.getVisibleTiles();\n\t\tconst viewBounds = this.getViewBounds();\n\t\tconst visibleKeys = new Set(visible.map((tile) => tile.key));\n\n\t\tgl.useProgram(tileProgram.program);\n\t\tgl.bindVertexArray(tileProgram.vao);\n\t\tgl.uniformMatrix3fv(tileProgram.uCamera, false, this.camera.getMatrix());\n\t\tgl.uniform1i(tileProgram.uTexture, 0);\n\n\t\tconst fallbackTiles: CachedTile[] = [];\n\t\tfor (const [, cached] of this.cache) {\n\t\t\tif (visibleKeys.has(cached.key)) continue;\n\t\t\tif (!this.intersectsBounds(cached.bounds, viewBounds)) continue;\n\t\t\tfallbackTiles.push(cached);\n\t\t}\n\n\t\tfallbackTiles.sort((a, b) => a.tier - b.tier);\n\t\tfor (const cached of fallbackTiles) {\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tlet renderedTiles = 0;\n\t\tconst missingTiles: ScheduledTile[] = [];\n\t\tfor (const tile of visible) {\n\t\t\tconst cached = this.cache.get(tile.key);\n\t\t\tif (!cached) {\n\t\t\t\tmissingTiles.push(tile);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t\trenderedTiles += 1;\n\t\t}\n\t\tthis.tileScheduler.schedule(missingTiles);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tgl.bindVertexArray(null);\n\n\t\tlet renderedPoints = 0;\n\t\tif (this.pointCount > 0) {\n\t\t\tgl.enable(gl.BLEND);\n\t\t\tgl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\t\t\tgl.useProgram(pointProgram.program);\n\t\t\tgl.bindVertexArray(pointProgram.vao);\n\t\t\tgl.uniformMatrix3fv(pointProgram.uCamera, false, this.camera.getMatrix());\n\t\t\tgl.uniform1f(pointProgram.uPointSize, this.getPointSizeByZoom());\n\t\t\tgl.uniform1f(pointProgram.uPointStrokeScale, this.pointStrokeScale);\n\t\t\tgl.uniform1f(pointProgram.uPaletteSize, this.pointPaletteSize);\n\t\t\tgl.uniform1i(pointProgram.uPalette, 1);\n\t\t\tgl.activeTexture(gl.TEXTURE1);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, pointProgram.paletteTexture);\n\t\t\tif (this.usePointIndices) {\n\t\t\t\tgl.drawElements(gl.POINTS, this.pointCount, gl.UNSIGNED_INT, 0);\n\t\t\t} else {\n\t\t\t\tgl.drawArrays(gl.POINTS, 0, this.pointCount);\n\t\t\t}\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\t\tgl.bindVertexArray(null);\n\t\t\trenderedPoints = this.pointCount;\n\t\t}\n\n\t\tif (this.onStats) {\n\t\t\tconst schedulerStats = this.tileScheduler.getSnapshot();\n\t\t\tconst cacheHits = renderedTiles;\n\t\t\tconst cacheMisses = missingTiles.length;\n\t\t\tconst drawCalls =\n\t\t\t\tfallbackTiles.length + renderedTiles + (renderedPoints > 0 ? 1 : 0);\n\t\t\tthis.onStats({\n\t\t\t\ttier: this.currentTier,\n\t\t\t\tvisible: visible.length,\n\t\t\t\trendered: renderedTiles,\n\t\t\t\tpoints: renderedPoints,\n\t\t\t\tfallback: fallbackTiles.length,\n\t\t\t\tcache: this.cache.size,\n\t\t\t\tinflight: schedulerStats.inflight,\n\t\t\t\tqueued: schedulerStats.queued,\n\t\t\t\tretries: schedulerStats.retries,\n\t\t\t\tfailed: schedulerStats.failed,\n\t\t\t\taborted: schedulerStats.aborted,\n\t\t\t\tcacheHits,\n\t\t\t\tcacheMisses,\n\t\t\t\tdrawCalls,\n\t\t\t\tframeMs: nowMs() - frameStartMs,\n\t\t\t});\n\t\t}\n\t}\n\n\trequestRender(): void {\n\t\tif (\n\t\t\tthis.frame !== null ||\n\t\t\tthis.destroyed ||\n\t\t\tthis.contextLost ||\n\t\t\tthis.gl.isContextLost()\n\t\t)\n\t\t\treturn;\n\t\tthis.frame = requestAnimationFrame(() => {\n\t\t\tthis.frame = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tresize(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssW = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssH = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\n\t\tif (this.canvas.width !== pixelW || this.canvas.height !== pixelH) {\n\t\t\tthis.canvas.width = pixelW;\n\t\t\tthis.canvas.height = pixelH;\n\t\t}\n\n\t\tthis.camera.setViewport(cssW, cssH);\n\t\tthis.gl.viewport(0, 0, pixelW, pixelH);\n\t\tthis.requestRender();\n\t}\n\n\tonPointerDown(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst wantsRotate = this.ctrlDragRotate && (event.ctrlKey || event.metaKey);\n\t\tconst allowButton = event.button === 0 || (wantsRotate && event.button === 2);\n\t\tif (!allowButton) return;\n\t\tif (wantsRotate) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tthis.dragging = true;\n\t\tthis.interactionMode =\n\t\t\twantsRotate ? \"rotate\" : \"pan\";\n\t\tthis.pointerId = event.pointerId;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\t\tthis.rotateLastAngleRad =\n\t\t\tthis.interactionMode === \"rotate\"\n\t\t\t\t? this.getPointerAngleRad(event.clientX, event.clientY)\n\t\t\t\t: null;\n\t\tthis.canvas.classList.add(\"dragging\");\n\t\tthis.canvas.setPointerCapture(event.pointerId);\n\t}\n\n\tonPointerMove(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (!this.dragging || event.pointerId !== this.pointerId) return;\n\n\t\tconst dx = event.clientX - this.lastPointerX;\n\t\tconst dy = event.clientY - this.lastPointerY;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\n\t\tif (this.interactionMode === \"rotate\") {\n\t\t\tconst nextAngle = this.getPointerAngleRad(event.clientX, event.clientY);\n\t\t\tconst prevAngle = this.rotateLastAngleRad;\n\t\t\tthis.rotateLastAngleRad = nextAngle;\n\t\t\tif (prevAngle !== null) {\n\t\t\t\tconst rawDelta = nextAngle - prevAngle;\n\t\t\t\tconst delta = Math.atan2(Math.sin(rawDelta), Math.cos(rawDelta));\n\n\t\t\t\tconst sensitivityScale =\n\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY > 0\n\t\t\t\t\t\t? this.rotationDragSensitivityDegPerPixel /\n\t\t\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY\n\t\t\t\t\t\t: 1;\n\t\t\t\tconst state = this.camera.getViewState();\n\t\t\t\tthis.camera.setViewState({\n\t\t\t\t\trotationDeg:\n\t\t\t\t\t\tstate.rotationDeg - ((delta * 180) / Math.PI) * sensitivityScale,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tconst state = this.camera.getViewState();\n\t\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\t\tconst rad = toRadians(state.rotationDeg);\n\t\t\tconst cos = Math.cos(rad);\n\t\t\tconst sin = Math.sin(rad);\n\t\t\tconst worldDx = (dx * cos - dy * sin) / zoom;\n\t\t\tconst worldDy = (dx * sin + dy * cos) / zoom;\n\t\t\tthis.camera.setViewState({\n\t\t\t\toffsetX: state.offsetX - worldDx,\n\t\t\t\toffsetY: state.offsetY - worldDy,\n\t\t\t});\n\t\t}\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tonPointerUp(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (event.pointerId !== this.pointerId) return;\n\t\tthis.cancelDrag();\n\t}\n\n\tonWheel(event: WheelEvent): void {\n\t\tif (this.interactionLocked) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tconst factor = event.deltaY < 0 ? 1.12 : 0.89;\n\t\tthis.zoomBy(factor, x, y);\n\t}\n\n\tonDoubleClick(event: MouseEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tthis.zoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n\t}\n\n\tonContextMenu(event: MouseEvent): void {\n\t\tif (this.dragging || event.ctrlKey || event.metaKey) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\tprivate onWebGlContextLost(event: Event): void {\n\t\tevent.preventDefault();\n\t\tif (this.destroyed || this.contextLost) return;\n\t\tthis.contextLost = true;\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.clear();\n\t\tthis.cache.clear();\n\t\tthis.onContextLost?.();\n\t}\n\n\tprivate onWebGlContextRestored(_event: Event): void {\n\t\tif (this.destroyed) return;\n\t\tthis.contextLost = false;\n\t\tthis.cache.clear();\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.lastPointPalette && this.lastPointPalette.length > 0) {\n\t\t\tthis.setPointPalette(this.lastPointPalette);\n\t\t}\n\t\tif (this.lastPointData) {\n\t\t\tthis.setPointData(this.lastPointData);\n\t\t} else {\n\t\t\tthis.pointCount = 0;\n\t\t}\n\n\t\tthis.resize();\n\t\tthis.requestRender();\n\t\tthis.onContextRestored?.();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.canvas.removeEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tthis.canvas.removeEventListener(\"pointermove\", this.boundPointerMove);\n\t\tthis.canvas.removeEventListener(\"pointerup\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"wheel\", this.boundWheel);\n\t\tthis.canvas.removeEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tthis.canvas.removeEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tthis.canvas.removeEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tthis.canvas.removeEventListener(\n\t\t\t\"webglcontextrestored\",\n\t\t\tthis.boundContextRestored,\n\t\t);\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.destroy();\n\n\t\tif (!this.contextLost && !this.gl.isContextLost()) {\n\t\t\tfor (const [, value] of this.cache) {\n\t\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\t}\n\t\t\tthis.gl.deleteBuffer(this.tileProgram.vbo);\n\t\t\tthis.gl.deleteVertexArray(this.tileProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.tileProgram.program);\n\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.posBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.termBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.indexBuffer);\n\t\t\tthis.gl.deleteTexture(this.pointProgram.paletteTexture);\n\t\t\tthis.gl.deleteVertexArray(this.pointProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.pointProgram.program);\n\t\t}\n\t\tthis.cache.clear();\n\t}\n\n\tprivate initTileProgram(): TileVertexProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst 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\t\tconst fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n out vec4 outColor;\n void main() {\n outColor = texture(uTexture, vUv);\n }`;\n\n\t\tconst program = createProgram(gl, vertex, fragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uBounds = requireUniformLocation(gl, program, \"uBounds\");\n\t\tconst uTexture = requireUniformLocation(gl, program, \"uTexture\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst vbo = gl.createBuffer();\n\t\tif (!vao || !vbo) {\n\t\t\tthrow new Error(\"buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n\t\tgl.bufferData(\n\t\t\tgl.ARRAY_BUFFER,\n\t\t\tnew Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]),\n\t\t\tgl.STATIC_DRAW,\n\t\t);\n\n\t\tconst aUnit = gl.getAttribLocation(program, \"aUnit\");\n\t\tconst aUv = gl.getAttribLocation(program, \"aUv\");\n\t\tif (aUnit < 0 || aUv < 0) {\n\t\t\tthrow new Error(\"tile attribute lookup failed\");\n\t\t}\n\t\tgl.enableVertexAttribArray(aUnit);\n\t\tgl.enableVertexAttribArray(aUv);\n\t\tgl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n\t\tgl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n\t\treturn { program, vao, vbo, uCamera, uBounds, uTexture };\n\t}\n\n\tprivate initPointProgram(): PointProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aTerm;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vTerm;\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 vTerm = aTerm;\n }`;\n\n\t\tconst pointFragment = `#version 300 es\n precision highp float;\n flat in uint vTerm;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\n uniform float uPointStrokeScale;\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(vTerm), 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 s = uPointStrokeScale;\n float ringWidth = clamp(3.0 * s / max(1.0, uPointSize), 0.12 * s, 0.62 * s);\n float innerRadius = 1.0 - ringWidth;\n float aa = 1.5 / max(1.0, uPointSize);\n\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float alpha = outerMask * innerMask * color.a;\n if (alpha <= 0.001) discard;\n\n outColor = vec4(color.rgb * alpha, alpha);\n }`;\n\n\t\tconst program = createProgram(gl, pointVertex, pointFragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uPointSize = requireUniformLocation(gl, program, \"uPointSize\");\n\t\tconst uPointStrokeScale = requireUniformLocation(gl, program, \"uPointStrokeScale\");\n\t\tconst uPalette = requireUniformLocation(gl, program, \"uPalette\");\n\t\tconst uPaletteSize = requireUniformLocation(gl, program, \"uPaletteSize\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst posBuffer = gl.createBuffer();\n\t\tconst termBuffer = gl.createBuffer();\n\t\tconst indexBuffer = gl.createBuffer();\n\t\tconst paletteTexture = gl.createTexture();\n\t\tif (!vao || !posBuffer || !termBuffer || !indexBuffer || !paletteTexture) {\n\t\t\tthrow new Error(\"point buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst posLoc = gl.getAttribLocation(program, \"aPosition\");\n\t\tif (posLoc < 0) {\n\t\t\tthrow new Error(\"point position attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(posLoc);\n\t\tgl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, termBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst termLoc = gl.getAttribLocation(program, \"aTerm\");\n\t\tif (termLoc < 0) {\n\t\t\tthrow new Error(\"point term attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(termLoc);\n\t\tgl.vertexAttribIPointer(termLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\n\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, paletteTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\t1,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tnew Uint8Array([160, 160, 160, 255]),\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\n\t\treturn {\n\t\t\tprogram,\n\t\t\tvao,\n\t\t\tposBuffer,\n\t\t\ttermBuffer,\n\t\t\tindexBuffer,\n\t\t\tpaletteTexture,\n\t\t\tuCamera,\n\t\t\tuPointSize,\n\t\t\tuPointStrokeScale,\n\t\t\tuPalette,\n\t\t\tuPaletteSize,\n\t\t};\n\t}\n\n\tprivate handleTileLoaded(tile: ScheduledTile, bitmap: ImageBitmap): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\t\tif (this.cache.has(tile.key)) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\n\t\tconst texture = this.createTextureFromBitmap(bitmap);\n\t\tbitmap.close();\n\t\tif (!texture) return;\n\n\t\tthis.cache.set(tile.key, {\n\t\t\tkey: tile.key,\n\t\t\ttexture,\n\t\t\tbounds: tile.bounds,\n\t\t\ttier: tile.tier,\n\t\t\tlastUsed: this.frameSerial,\n\t\t});\n\t\tthis.trimCache();\n\t\tthis.requestRender();\n\t}\n\n\tprivate createTextureFromBitmap(bitmap: ImageBitmap): WebGLTexture | null {\n\t\tif (this.contextLost || this.gl.isContextLost()) return null;\n\t\tconst gl = this.gl;\n\t\tconst texture = gl.createTexture();\n\t\tif (!texture) return null;\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, texture);\n\t\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\treturn texture;\n\t}\n}\n","import { type CSSProperties, type MouseEvent as ReactMouseEvent, type MutableRefObject, type ReactNode, type PointerEvent as ReactPointerEvent, useCallback, 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 {\n pointInPreparedPolygon,\n prepareRoiPolygons,\n type PreparedRoiPolygon,\n type RoiGeometry,\n} from \"../wsi/roi-geometry\";\nimport { computeRoiPointGroups, type RoiPointGroupStats } from \"../wsi/roi-term-stats\";\nimport type { WsiImageSource, WsiPointData, WsiRegion, WsiRenderStats, WsiViewState } from \"../wsi/types\";\nimport { type PointSizeByZoom, type WsiTileErrorEvent, WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { BrushOptions, DrawCoordinate, DrawOverlayShape, DrawRegionCoordinates, DrawResult, DrawTool, PatchDrawResult, RegionLabelStyle, RegionStrokeStyle, RegionStrokeStyleResolver, StampOptions } from \"./draw-layer\";\nimport { DrawLayer } from \"./draw-layer\";\nimport { OverviewMap, type OverviewMapOptions } from \"./overview-map\";\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawRegionCoordinates[] = [];\nconst EMPTY_CLIPPED_POINTS: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n};\nconst POINT_HIT_RADIUS_SCALE = 0.65;\nconst MIN_POINT_HIT_RADIUS_PX = 4;\nconst MIN_POINT_HIT_GRID_SIZE = 24;\nconst MAX_POINT_HIT_GRID_SIZE = 1024;\nconst POINT_HIT_GRID_DENSITY_SCALE = 4;\n\nexport interface RegionHoverEvent {\n region: WsiRegion | null;\n regionId: string | number | null;\n regionIndex: number;\n coordinate: DrawCoordinate | null;\n}\n\nexport interface RegionClickEvent {\n region: WsiRegion;\n regionId: string | number;\n regionIndex: number;\n coordinate: DrawCoordinate;\n}\n\nexport interface PointHitEvent {\n index: number;\n id: number | null;\n coordinate: DrawCoordinate;\n pointCoordinate: DrawCoordinate;\n}\n\nexport interface PointClickEvent extends PointHitEvent {\n button: number;\n}\n\nexport interface PointHoverEvent {\n index: number | null;\n id: number | null;\n coordinate: DrawCoordinate | null;\n pointCoordinate: DrawCoordinate | null;\n}\n\nexport interface PointClipStatsEvent {\n mode: PointClipMode;\n durationMs: number;\n inputCount: number;\n outputCount: number;\n polygonCount: number;\n usedWebGpu?: boolean;\n candidateCount?: number;\n bridgedToDraw?: boolean;\n}\n\nexport interface PointerWorldMoveEvent {\n coordinate: DrawCoordinate | null;\n clientX: number;\n clientY: number;\n insideImage: boolean;\n}\n\nexport interface WsiCustomLayerContext {\n source: WsiImageSource;\n viewState: WsiViewState;\n drawTool: DrawTool;\n interactionLock: boolean;\n worldToScreen: (worldX: number, worldY: number) => DrawCoordinate | null;\n screenToWorld: (clientX: number, clientY: number) => DrawCoordinate | null;\n requestRedraw: () => void;\n}\n\nexport interface WsiCustomLayer {\n id?: string | number;\n zIndex?: number;\n pointerEvents?: CSSProperties[\"pointerEvents\"];\n className?: string;\n style?: CSSProperties;\n render: (context: WsiCustomLayerContext) => ReactNode;\n}\n\ninterface PointSpatialIndex {\n cellSize: number;\n safeCount: number;\n positions: Float32Array;\n ids: Uint32Array | null;\n buckets: Map<number, Map<number, number[]>>;\n}\n\ninterface PreparedRegionHit {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n polygons: PreparedRoiPolygon[];\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\n return Math.max(0, Math.min(Math.floor(pointData.count ?? 0), Math.floor((pointData.positions?.length ?? 0) / 2), pointData.paletteIndices?.length ?? 0));\n}\n\nfunction sanitizeDrawIndices(drawIndices: Uint32Array | undefined, maxExclusive: number): Uint32Array | null {\n if (!(drawIndices instanceof Uint32Array) || maxExclusive <= 0 || drawIndices.length === 0) {\n return null;\n }\n\n let invalidFound = false;\n for (let i = 0; i < drawIndices.length; i += 1) {\n if (drawIndices[i] < maxExclusive) continue;\n invalidFound = true;\n break;\n }\n if (!invalidFound) {\n return drawIndices;\n }\n\n const out = new Uint32Array(drawIndices.length);\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 out[cursor] = idx;\n cursor += 1;\n }\n return out.subarray(0, cursor);\n}\n\nfunction resolvePointHitGridSize(source: WsiImageSource | null, visibleCount: number): number {\n if (!source || visibleCount <= 0) return 256;\n const area = Math.max(1, source.width * source.height);\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 buildPointSpatialIndex(pointData: WsiPointData | null | undefined, source: WsiImageSource | null): PointSpatialIndex | null {\n if (!pointData || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) {\n return null;\n }\n\n const positions = pointData.positions.subarray(0, safeCount * 2);\n const ids = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.subarray(0, safeCount) : null;\n const drawIndices = sanitizeDrawIndices(pointData.drawIndices, safeCount);\n const visibleCount = drawIndices ? drawIndices.length : safeCount;\n if (visibleCount === 0) {\n return null;\n }\n\n const cellSize = resolvePointHitGridSize(source, visibleCount);\n const buckets = new Map<number, Map<number, number[]>>();\n\n const pushBucket = (pointIndex: number): void => {\n const px = positions[pointIndex * 2];\n const py = positions[pointIndex * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) return;\n\n const cellX = Math.floor(px / cellSize);\n const cellY = Math.floor(py / cellSize);\n let column = buckets.get(cellX);\n if (!column) {\n column = new Map<number, number[]>();\n buckets.set(cellX, column);\n }\n const bucket = column.get(cellY);\n if (bucket) {\n bucket.push(pointIndex);\n } else {\n column.set(cellY, [pointIndex]);\n }\n };\n\n if (drawIndices) {\n for (let i = 0; i < drawIndices.length; i += 1) {\n pushBucket(drawIndices[i] ?? 0);\n }\n } else {\n for (let i = 0; i < safeCount; i += 1) {\n pushBucket(i);\n }\n }\n\n if (buckets.size === 0) {\n return null;\n }\n\n return {\n cellSize,\n safeCount,\n positions,\n ids,\n buckets,\n };\n}\n\nfunction resolveRegionId(region: WsiRegion, index: number): string | number {\n return region.id ?? index;\n}\n\nfunction prepareRegionHits(\n regions: WsiRegion[]\n): PreparedRegionHit[] {\n const out: PreparedRegionHit[] = [];\n for (let i = 0; i < regions.length; i += 1) {\n const region = regions[i];\n const polygons = prepareRoiPolygons([region?.coordinates as RoiGeometry | null | undefined]);\n if (polygons.length === 0) continue;\n out.push({\n region,\n regionIndex: i,\n regionId: resolveRegionId(region, i),\n polygons,\n });\n }\n return out;\n}\n\nfunction pickPreparedRegionAt(\n coord: DrawCoordinate,\n regions: PreparedRegionHit[]\n): {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n} | null {\n const x = coord[0];\n const y = coord[1];\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 (!pointInPreparedPolygon(x, y, polygon)) continue;\n return {\n region: region.region,\n regionIndex: region.regionIndex,\n regionId: region.regionId,\n };\n }\n }\n return null;\n}\n\nexport interface WsiViewerCanvasProps {\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 debugOverlay?: boolean;\n debugOverlayStyle?: CSSProperties;\n fitNonce?: number;\n rotationResetNonce?: number;\n authToken?: string;\n ctrlDragRotate?: boolean;\n pointData?: WsiPointData | null;\n pointPalette?: Uint8Array | null;\n pointSizeByZoom?: PointSizeByZoom;\n pointStrokeScale?: number;\n roiRegions?: WsiRegion[];\n roiPolygons?: DrawRegionCoordinates[];\n clipPointsToRois?: boolean;\n clipMode?: PointClipMode;\n onClipStats?: (event: PointClipStatsEvent) => void;\n onRoiPointGroups?: (stats: RoiPointGroupStats) => void;\n roiPaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n interactionLock?: boolean;\n drawTool?: DrawTool;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n customLayers?: WsiCustomLayer[];\n patchRegions?: WsiRegion[];\n regionLabelStyle?: Partial<RegionLabelStyle>;\n onPointerWorldMove?: (event: PointerWorldMoveEvent) => void;\n onPointHover?: (event: PointHoverEvent) => void;\n onPointClick?: (event: PointClickEvent) => void;\n onRegionHover?: (event: RegionHoverEvent) => void;\n onRegionClick?: (event: RegionClickEvent) => void;\n onActiveRegionChange?: (regionId: string | number | null) => void;\n getCellByCoordinatesRef?: MutableRefObject<((coordinate: DrawCoordinate) => PointHitEvent | null) | null>;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n showOverviewMap?: boolean;\n overviewMapOptions?: Partial<OverviewMapOptions>;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function WsiViewerCanvas({\n source,\n viewState,\n onViewStateChange,\n onStats,\n onTileError,\n onContextLost,\n onContextRestored,\n debugOverlay = false,\n debugOverlayStyle,\n fitNonce = 0,\n rotationResetNonce = 0,\n authToken = \"\",\n ctrlDragRotate = true,\n pointData = null,\n pointPalette = null,\n pointSizeByZoom,\n pointStrokeScale,\n roiRegions,\n roiPolygons,\n clipPointsToRois = false,\n clipMode = \"worker\",\n onClipStats,\n onRoiPointGroups,\n roiPaletteIndexToTermId,\n interactionLock = false,\n drawTool = \"cursor\",\n stampOptions,\n brushOptions,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n customLayers,\n patchRegions,\n regionLabelStyle,\n onPointerWorldMove,\n onPointHover,\n onPointClick,\n onRegionHover,\n onRegionClick,\n onActiveRegionChange,\n getCellByCoordinatesRef,\n onDrawComplete,\n onPatchComplete,\n showOverviewMap = false,\n overviewMapOptions,\n className,\n style,\n}: WsiViewerCanvasProps): React.ReactElement {\n const canvasRef = 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 onViewStateChangeRef = useRef<typeof onViewStateChange>(onViewStateChange);\n const onStatsRef = useRef<typeof onStats>(onStats);\n const debugOverlayRef = useRef(debugOverlay);\n const [isOverviewOpen, setIsOverviewOpen] = useState(true);\n const [hoveredRegionId, setHoveredRegionId] = useState<string | number | null>(null);\n const [activeRegionId, setActiveRegionId] = useState<string | number | null>(null);\n const [customLayerViewState, setCustomLayerViewState] = useState<WsiViewState | null>(null);\n const [debugStats, setDebugStats] = useState<WsiRenderStats | null>(null);\n const hoveredRegionIdRef = useRef<string | number | null>(null);\n const hoveredPointIndexRef = useRef<number | null>(null);\n const hoveredPointIdRef = useRef<number | null>(null);\n const clipRunIdRef = useRef(0);\n const safeRoiRegions = roiRegions ?? EMPTY_ROI_REGIONS;\n const safePatchRegions = patchRegions ?? EMPTY_ROI_REGIONS;\n const safeRoiPolygons = roiPolygons ?? EMPTY_ROI_POLYGONS;\n const shouldTrackCustomLayerViewState = (customLayers?.length ?? 0) > 0;\n\n const mergedStyle = useMemo<CSSProperties>(() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }), [style]);\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 effectiveRoiRegions = useMemo<WsiRegion[]>(() => {\n if (safeRoiRegions.length > 0) {\n return safeRoiRegions;\n }\n if (safeRoiPolygons.length === 0) {\n return EMPTY_ROI_REGIONS;\n }\n return safeRoiPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [safeRoiRegions, safeRoiPolygons]);\n const preparedRegionHits = useMemo(() => prepareRegionHits(effectiveRoiRegions), [effectiveRoiRegions]);\n\n const clipPolygons = useMemo<RoiPolygon[]>(\n () => effectiveRoiRegions.map(region => region.coordinates as RoiPolygon),\n [effectiveRoiRegions]\n );\n\n const [renderPointData, setRenderPointData] = useState<WsiPointData | null>(pointData);\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 outputCount = data?.drawIndices ? data.drawIndices.length : (data?.count ?? 0);\n setRenderPointData(data);\n onClipStats?.({\n mode: stats.mode,\n durationMs: stats.durationMs,\n inputCount: pointData.count,\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 const shouldEnablePointHitTest = Boolean(onPointHover || onPointClick || getCellByCoordinatesRef);\n const pointSpatialIndex = useMemo(() => {\n if (!shouldEnablePointHitTest) return null;\n return buildPointSpatialIndex(renderPointData, source);\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.getPointSizeByZoom();\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 = pointSpatialIndex.cellSize;\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 const column = pointSpatialIndex.buckets.get(cx);\n if (!column) continue;\n\n for (let cy = baseCellY - cellRadius; cy <= baseCellY + cellRadius; cy += 1) {\n const bucket = column.get(cy);\n if (!bucket || bucket.length === 0) continue;\n\n for (let i = 0; i < bucket.length; i += 1) {\n const pointIndex = bucket[i];\n if (pointIndex >= pointSpatialIndex.safeCount) continue;\n\n const px = pointSpatialIndex.positions[pointIndex * 2];\n const py = pointSpatialIndex.positions[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 [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 const overviewWidth = useMemo(() => {\n const value = Number(overviewMapOptions?.width ?? 220);\n return Number.isFinite(value) ? Math.max(64, value) : 220;\n }, [overviewMapOptions?.width]);\n const overviewHeight = useMemo(() => {\n const value = Number(overviewMapOptions?.height ?? 140);\n return Number.isFinite(value) ? Math.max(48, value) : 140;\n }, [overviewMapOptions?.height]);\n const overviewMargin = useMemo(() => {\n const value = Number(overviewMapOptions?.margin ?? 16);\n return Number.isFinite(value) ? Math.max(0, value) : 16;\n }, [overviewMapOptions?.margin]);\n const overviewPosition = overviewMapOptions?.position || \"bottom-right\";\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 const commitActiveRegion = useCallback(\n (next: string | number | null) => {\n setActiveRegionId(prev => {\n if (String(prev) === String(next)) {\n return prev;\n }\n onActiveRegionChange?.(next);\n return next;\n });\n },\n [onActiveRegionChange]\n );\n\n useEffect(() => {\n onViewStateChangeRef.current = onViewStateChange;\n }, [onViewStateChange]);\n\n useEffect(() => {\n onStatsRef.current = onStats;\n }, [onStats]);\n\n useEffect(() => {\n debugOverlayRef.current = debugOverlay;\n if (!debugOverlay) setDebugStats(null);\n }, [debugOverlay]);\n\n const handleRendererStats = useCallback((stats: WsiRenderStats): void => {\n onStatsRef.current?.(stats);\n if (debugOverlayRef.current) {\n setDebugStats(stats);\n }\n }, []);\n\n const debugOverlayText = useMemo(() => {\n if (!debugStats) {\n return \"stats: waiting for first frame...\";\n }\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 useEffect(() => {\n const hasActive = activeRegionId === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(activeRegionId));\n if (!hasActive && activeRegionId !== null) {\n commitActiveRegion(null);\n }\n\n const currentHover = hoveredRegionIdRef.current;\n const hasHover = currentHover === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(currentHover));\n\n if (!hasHover && currentHover !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n }, [effectiveRoiRegions, activeRegionId, onRegionHover, commitActiveRegion]);\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 const emitViewStateChange = useCallback(\n (next: WsiViewState): void => {\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(next);\n }\n const callback = onViewStateChangeRef.current;\n if (callback) {\n callback(next);\n }\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n },\n [shouldTrackCustomLayerViewState]\n );\n\n useEffect(() => {\n if (!showOverviewMap) {\n setIsOverviewOpen(false);\n return;\n }\n setIsOverviewOpen(true);\n }, [showOverviewMap, source?.id]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [drawTool, onRegionHover]);\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 const resolveWorldCoord = 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 resolveScreenCoord = useCallback((worldX: number, worldY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.worldToScreen(worldX, worldY);\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 requestCustomLayerRedraw = useCallback(() => {\n rendererRef.current?.requestRender();\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n }, []);\n\n const effectiveCustomLayerViewState = useMemo<WsiViewState | null>(() => {\n return customLayerViewState ?? rendererRef.current?.getViewState() ?? null;\n }, [customLayerViewState]);\n\n const customLayerContext = useMemo<WsiCustomLayerContext | null>(() => {\n if (!source) return null;\n const viewStateForLayer = effectiveCustomLayerViewState;\n if (!viewStateForLayer) return null;\n return {\n source,\n viewState: viewStateForLayer,\n drawTool,\n interactionLock,\n worldToScreen: resolveScreenCoord,\n screenToWorld: resolveWorldCoord,\n requestRedraw: requestCustomLayerRedraw,\n };\n }, [source, effectiveCustomLayerViewState, drawTool, interactionLock, resolveScreenCoord, resolveWorldCoord, requestCustomLayerRedraw]);\n\n const handleRegionPointerMove = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n const isCanvasEvent = event.target === canvasRef.current;\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (onPointerWorldMove) {\n const insideImage = !!coord && coord[0] >= 0 && coord[1] >= 0 && !!source && coord[0] <= source.width && coord[1] <= source.height;\n onPointerWorldMove({\n coordinate: coord,\n clientX: event.clientX,\n clientY: event.clientY,\n insideImage,\n });\n }\n\n if (drawTool !== \"cursor\") return;\n if (!isCanvasEvent) {\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n return;\n }\n if (!coord) {\n emitPointHover(null, null);\n return;\n }\n\n if (onPointHover) {\n emitPointHover(getCellByCoordinates(coord), coord);\n }\n if (!preparedRegionHits.length) return;\n\n const hit = pickPreparedRegionAt(coord, preparedRegionHits);\n const nextHoverId = hit?.regionId ?? null;\n const prevHoverId = hoveredRegionIdRef.current;\n if (String(prevHoverId) === String(nextHoverId)) return;\n\n hoveredRegionIdRef.current = nextHoverId;\n setHoveredRegionId(nextHoverId);\n onRegionHover?.({\n region: hit?.region ?? null,\n regionId: nextHoverId,\n regionIndex: hit?.regionIndex ?? -1,\n coordinate: coord,\n });\n },\n [drawTool, preparedRegionHits, resolveWorldCoord, onRegionHover, onPointerWorldMove, source, emitPointHover, getCellByCoordinates, onPointHover]\n );\n\n const handleRegionPointerLeave = useCallback(() => {\n onPointerWorldMove?.({\n coordinate: null,\n clientX: -1,\n clientY: -1,\n insideImage: false,\n });\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [onRegionHover, onPointerWorldMove, emitPointHover]);\n\n const handleRegionClick = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n\n if (!preparedRegionHits.length) {\n commitActiveRegion(null);\n return;\n }\n\n const hit = pickPreparedRegionAt(coord, preparedRegionHits);\n if (!hit) {\n commitActiveRegion(null);\n return;\n }\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n },\n [drawTool, preparedRegionHits, resolveWorldCoord, onRegionClick, activeRegionId, commitActiveRegion, emitPointClick]\n );\n\n const handleBrushTap = useCallback(\n (coord: DrawCoordinate): boolean => {\n if (drawTool !== \"brush\") return false;\n if (brushOptions?.clickSelectRoi !== true) return false;\n if (!preparedRegionHits.length) return false;\n\n const hit = pickPreparedRegionAt(coord, preparedRegionHits);\n if (!hit) return false;\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n return true;\n },\n [drawTool, brushOptions?.clickSelectRoi, preparedRegionHits, activeRegionId, commitActiveRegion, onRegionClick]\n );\n\n const handleRegionContextMenu = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (!onPointClick) return;\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n event.preventDefault();\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n },\n [drawTool, resolveWorldCoord, emitPointClick, onPointClick]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !source) {\n return;\n }\n\n const renderer = new WsiTileRenderer(canvas, source, {\n onViewStateChange: emitViewStateChange,\n onStats: handleRendererStats,\n onTileError,\n onContextLost,\n onContextRestored,\n authToken,\n ctrlDragRotate,\n pointSizeByZoom,\n pointStrokeScale,\n });\n\n rendererRef.current = renderer;\n if (viewState) {\n renderer.setViewState(viewState);\n }\n renderer.setInteractionLock(interactionLock);\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(renderer.getViewState());\n }\n\n return () => {\n renderer.destroy();\n rendererRef.current = null;\n };\n }, [source, handleRendererStats, onTileError, onContextLost, onContextRestored, authToken, ctrlDragRotate, pointSizeByZoom, pointStrokeScale, emitViewStateChange, shouldTrackCustomLayerViewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !viewState) {\n return;\n }\n renderer.setViewState(viewState);\n }, [viewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.fitToImage();\n }, [fitNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.resetRotation();\n }, [rotationResetNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !pointPalette) {\n return;\n }\n renderer.setPointPalette(pointPalette);\n }, [pointPalette]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointSizeByZoom(pointSizeByZoom);\n }, [pointSizeByZoom]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.setPointStrokeScale(pointStrokeScale);\n }, [pointStrokeScale]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointData(renderPointData);\n }, [renderPointData]);\n\n useEffect(() => {\n if (!onRoiPointGroups) return;\n const sourcePoints = clipPointsToRois ? renderPointData : pointData;\n const stats = computeRoiPointGroups(sourcePoints, effectiveRoiRegions, {\n paletteIndexToTermId: roiPaletteIndexToTermId,\n includeEmptyRegions: true,\n });\n onRoiPointGroups(stats);\n }, [onRoiPointGroups, clipPointsToRois, pointData, renderPointData, effectiveRoiRegions, roiPaletteIndexToTermId]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setInteractionLock(interactionLock);\n }, [interactionLock]);\n\n return (\n <div className={className} style={mergedStyle} onPointerMove={handleRegionPointerMove} onPointerLeave={handleRegionPointerLeave} onClick={handleRegionClick} onContextMenu={handleRegionContextMenu}>\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 cursor: drawTool === \"cursor\" && hoveredRegionId !== null ? \"pointer\" : interactionLock ? \"crosshair\" : \"grab\",\n }}\n />\n {source && customLayerContext && Array.isArray(customLayers) && customLayers.length > 0\n ? customLayers.map((layer, index) => (\n <div\n key={layer.id ?? index}\n className={layer.className}\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: layer.zIndex ?? 3,\n pointerEvents: layer.pointerEvents ?? \"none\",\n ...layer.style,\n }}\n >\n {layer.render(customLayerContext)}\n </div>\n ))\n : null}\n {source ? (\n <DrawLayer\n tool={drawTool}\n enabled={drawTool !== \"cursor\"}\n imageWidth={source.width}\n imageHeight={source.height}\n imageMpp={source.mpp}\n imageZoom={source.maxTierZoom}\n stampOptions={stampOptions}\n brushOptions={brushOptions}\n projectorRef={rendererRef}\n onBrushTap={handleBrushTap}\n viewStateSignal={viewState}\n persistedRegions={effectiveRoiRegions}\n patchRegions={safePatchRegions}\n regionStrokeStyle={regionStrokeStyle}\n regionStrokeHoverStyle={regionStrokeHoverStyle}\n regionStrokeActiveStyle={regionStrokeActiveStyle}\n patchStrokeStyle={patchStrokeStyle}\n resolveRegionStrokeStyle={resolveRegionStrokeStyle}\n overlayShapes={overlayShapes}\n hoveredRegionId={hoveredRegionId}\n activeRegionId={activeRegionId}\n regionLabelStyle={regionLabelStyle}\n invalidateRef={drawInvalidateRef}\n onDrawComplete={onDrawComplete}\n onPatchComplete={onPatchComplete}\n />\n ) : null}\n {debugOverlay ? (\n <pre data-open-plant-debug-overlay style={mergedDebugOverlayStyle}>\n {debugOverlayText}\n </pre>\n ) : null}\n {source && showOverviewMap ? (\n isOverviewOpen ? (\n <>\n <OverviewMap source={source} projectorRef={rendererRef} authToken={authToken} options={overviewMapOptions} invalidateRef={overviewInvalidateRef} />\n <button\n type=\"button\"\n aria-label=\"Hide overview map\"\n onClick={() => setIsOverviewOpen(false)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin + overviewHeight + 8 } : { bottom: overviewMargin + overviewHeight + 8 }),\n width: 20,\n height: 20,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.4)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#fff\",\n fontSize: 13,\n lineHeight: 1,\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n ×\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Show overview map\"\n onClick={() => setIsOverviewOpen(true)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin } : { bottom: overviewMargin }),\n height: 24,\n minWidth: 40,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.45)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#dff8ff\",\n fontSize: 11,\n fontWeight: 700,\n cursor: \"pointer\",\n padding: \"0 8px\",\n }}\n >\n Map\n </button>\n )\n ) : null}\n </div>\n );\n}\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","context","OrthoCamera$1","__publicField","width","height","next","viewWidth","viewHeight","sx","sy","tx","ty","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","options","OrthoCamera","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","zoom","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","DEFAULT_MIN_RASTER_STEP","DEFAULT_MAX_RASTER_PIXELS","DEFAULT_MAX_RASTER_SIZE","DEFAULT_CIRCLE_SIDES","DEFAULT_SMOOTHING_PASSES","MAX_SMOOTHING_PASSES","MIN_RADIUS","ALPHA_THRESHOLD","clamp","value","min","max","closeRing","coordinates","out","x","y","first","last","sanitizePath","points","point","prev","createCirclePolygon","center","radius","sides","ring","t","createBoundsFallback","minX","minY","maxX","maxY","pad","computeExpandedBounds","resolveRasterConfig","bounds","minRasterStep","maxRasterPixels","maxRasterSize","widthWorld","heightWorld","step","padding","createRasterContext","worldToRaster","config","rasterizeStrokeMask","path","p","i","image","buildBoundaryEdges","mask","edges","vertex","at","turnPriority","fromDir","toDir","delta","traceLoops","outgoing","entry","used","loops","startVertex","currentVertex","currentDir","loop","guard","guardLimit","candidates","bestIndex","bestPriority","edgeIndex","candidate","priority","toWorldRing","vertexLoop","id","polygonSignedArea","sum","a","b","removeCollinearVertices","epsilon","closed","curr","cross","pointLineDistanceSquared","abx","aby","len2","dx","dy","simplifyRdp","tolerance","keep","tolerance2","stack","start","end","maxDist2","split","dist2","simplifyClosedRing","open","simplified","smoothClosedRingChaikin","iterations","pass","clampRingToBounds","buildBrushStrokePolygon","circleSides","raster","bestRing","bestArea","area","smoothingPasses","isFiniteNumber","isCoordinatePair","isLinearRing","isPolygonRings","isMultiPolygon","polygon","closeRoiRing","normalizePolygonRings","rings","normalized","outerIndex","outerArea","normalizeRoiGeometry","geometry","pointInRing","inside","j","xi","yi","xj","yj","prepareRoiPolygons","geometries","prepared","multipolygon","outer","pointInPreparedPolygon","hole","pointInAnyPreparedPolygon","polygons","DEFAULT_POINT_COLOR","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcScaleLength","length","unit","isSameViewState","toBearerToken","trimmed","token","hexToRgba","hex","match","n","buildTermPalette","terms","palette","termToPaletteIndex","term","termId","colors","vs","fs","DRAW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","EMPTY_REGIONS","EMPTY_DASH","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","MIN_BRUSH_RASTER_STEP","BRUSH_RASTER_DIAMETER_SAMPLES","BRUSH_SCREEN_STEP","DEFAULT_REGION_STROKE_STYLE","DEFAULT_PATCH_STROKE_STYLE","DEFAULT_REGION_LABEL_STYLE","isStampTool","tool","clampPositiveOrFallback","fallback","resolveStampOptions","clampUnitOpacity","sanitizeBrushLineDash","item","resolveBrushEdgeDetail","resolveBrushEdgeSmoothing","resolveBrushOptions","cursorLineWidth","edgeDetail","edgeSmoothing","mm2ToUm2","areaMm2","createSquareFromCenter","halfLength","createCircleFromCenter","coords","createRectangle","createCircle","centerX","centerY","polygonArea","computeBounds","isValidPolygon","tracePath","ctx","close","drawPath","strokeStyle","fill","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","isNestedRingCoordinates","isCoordinateRing","collectOverlayRings","normalizeOverlayRings","sourceRings","drawInvertedFillMask","outerRing","holeRings","fillColor","resolveLabelStyle","px","py","bw","oy","br","drawRoundedRect","r","getTopAnchor","getTopAnchorFromPolygons","best","anchor","normalizeDrawRegionPolygons","normalizedOuter","holes","drawRegionLabel","text","canvasWidth","canvasHeight","labelStyle","label","boxWidth","boxHeight","left","top","clampWorld","coord","imageWidth","imageHeight","toCoord","DrawLayer","stampOptions","brushOptions","projectorRef","onBrushTap","onDrawComplete","onPatchComplete","enabled","viewStateSignal","persistedRegions","patchRegions","persistedPolygons","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","patchStrokeStyle","resolveRegionStrokeStyle","overlayShapes","hoveredRegionId","activeRegionId","regionLabelStyle","invalidateRef","className","canvasRef","useRef","drawPendingRef","overlayDebugSnapshotRef","lastToolRef","sessionRef","active","mergedPersistedRegions","useMemo","index","mergedPatchRegions","preparedPersistedRegions","region","preparedPatchRegions","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedPatchStrokeStyle","resolvedLabelStyle","resolvedStampOptions","resolvedBrushOptions","mergedStyle","resizeCanvas","useCallback","w","h","worldToScreenPoints","projector","worldRadiusToScreenPixels","worldRadius","micronsToWorldPixels","lengthUm","mppValue","imageZoomValue","viewZoomRaw","viewZoom","continuousZoom","umPerScreenPixel","buildStampCoords","stampTool","areaUm2","buildPreviewCoords","session","drawBrushStrokePreview","screenPoints","radiusPx","drawBrushCursor","cursor","screen","drawOverlay","regionIndex","regionKey","state","resolved","screenOuter","screenHole","debugOverlay","imageOuterRing","shape","renderRings","closedRings","debugKey","debugSignature","preview","line","anchorWorld","anchorScreen","requestDraw","resetSession","preserveCursor","toWorld","event","raw","finishSession","tapPoint","handleStampAt","intent","result","appendBrushPoint","world","minWorldStep","minWorldStep2","handlePointerDown","handlePointerMove","handlePointerUp","handlePointerLeave","changed","useEffect","observer","onKeyDown","jsx","screenX","screenY","trimTrailingSlash","ensureLeadingSlash","joinImsTileRoot","tileBaseUrl","parsed","origin","normalizeImageInfo","ims","isIms","tileSize","maxTierZoom","tilePath","normalizedPath","imsTileRoot","tileUrlBuilder","tier","toTileUrl","DEFAULT_OVERVIEW_MAP_OPTIONS","toPositiveNumber","isFiniteBounds","OverviewMap","authToken","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderRadius","borderWidth","maxThumbnailTiles","backgroundColor","borderColor","viewportStrokeColor","viewportFillColor","interactive","showThumbnail","position","pos","draw","cssW","cssH","pixelW","pixelH","corners","safeBounds","safeCorners","right","bottom","rectW","rectH","toWorldFromClient","clientX","clientY","nx","ny","recenterTo","worldX","worldY","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","requests","useAuthHeader","results","dw","dh","TileViewerCanvas","rendererRef","renderer","sanitizePointCount","pointData","filterPointDataByPolygons","count","positions","pointIds","nextPositions","nextTerms","nextIds","output","filterPointIndicesByPolygons","contextPromise","BBOX_PREFILTER_SHADER","hasWebGpu","nav","getNavigatorGpu","gpu","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","pointCount","boundsCount","safePointCount","positionBytes","boundsBytes","outputBytes","limit","positionsBuffer","boundsBuffer","outputBuffer","uniformBuffer","readBuffer","bindGroup","commandEncoder","mapped","nowMs","filterPointDataByPolygonsHybrid","bridgeToDraw","safeCount","bboxFlat","candidateMask","usedWebGpu","candidateCount","candidateIndices","candidateCursor","data","drawIndices","visibleCount","pointIndex","compactData","workerInstance","workerSupported","requestId","pendingById","createWorker","worker","handleWorkerMessage","handleWorkerError","msg","pending","indices","paletteIndices","ids","terminateRoiClipWorker","filterPointDataByPolygonsInWorker","positionsCopy","termsCopy","idsCopy","startMs","resolve","reject","transfer","filterPointIndicesByPolygonsInWorker","prepareRegions","regions","resolveTermId","paletteIndex","paletteIndexToTermId","fromArray","fromMap","computeRoiPointGroups","baseCount","valid","filtered","idx","inputCount","preparedRegions","regionTermCounters","regionTotalCounters","insideCount","bestRegion","regionTermMap","includeEmptyRegions","groups","totalCount","termMap","termCounts","shouldAttachAuthHeader","url","host","TileScheduler","nextVisibleKeys","inflight","queued","visibleKeys","nextQueue","key","earliestReadyAt","delay","now","controller","inflightEntry","nextAttempt","retryDelay","existing","attempt","exp","jitter","DEFAULT_ROTATION_DRAG_SENSITIVITY","MIN_POINT_SIZE_PX","MAX_POINT_SIZE_PX","DEFAULT_POINT_SIZE_STOPS","rad","toRadians","cos","sin","rx","ry","ax","bx","ay","by","deg","name","isSameArrayView","clonePointSizeStops","stops","stop","normalizePointSizeStops","pointSizeByZoom","zoomKey","rawSize","size","arePointSizeStopsEqual","resolvePointSizeByZoomStops","span","slope","MIN_STROKE_SCALE","MAX_STROKE_SCALE","normalizeStrokeScale","WsiTileRenderer","attemptCount","paletteSize","nextPaletteIndices","hasDrawIndices","nextDrawIndices","geometryChanged","drawIndicesChanged","maxExclusive","validCount","locked","nextStops","scale","vw","vh","visibleWorldW","visibleWorldH","factor","nextZoom","vp","worldDx","worldDy","marginX","marginY","halfW","halfH","minCenterX","maxCenterX","minCenterY","maxCenterY","nextCenterX","nextCenterY","rawTier","viewBounds","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","visible","entries","removeCount","frameStartMs","tileProgram","pointProgram","fallbackTiles","cached","renderedTiles","missingTiles","renderedPoints","schedulerStats","cacheHits","cacheMisses","drawCalls","wantsRotate","nextAngle","prevAngle","rawDelta","sensitivityScale","_event","uCamera","uBounds","uTexture","vbo","aUnit","aUv","uPointSize","uPointStrokeScale","uPalette","uPaletteSize","posBuffer","termBuffer","indexBuffer","paletteTexture","posLoc","termLoc","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","EMPTY_CLIPPED_POINTS","POINT_HIT_RADIUS_SCALE","MIN_POINT_HIT_RADIUS_PX","MIN_POINT_HIT_GRID_SIZE","MAX_POINT_HIT_GRID_SIZE","POINT_HIT_GRID_DENSITY_SCALE","sanitizeDrawIndices","invalidFound","resolvePointHitGridSize","buildPointSpatialIndex","cellSize","buckets","pushBucket","cellX","cellY","column","bucket","resolveRegionId","prepareRegionHits","pickPreparedRegionAt","WsiViewerCanvas","onViewStateChange","onStats","onTileError","onContextLost","onContextRestored","debugOverlayStyle","fitNonce","rotationResetNonce","ctrlDragRotate","pointPalette","pointStrokeScale","roiRegions","roiPolygons","clipPointsToRois","clipMode","onClipStats","onRoiPointGroups","roiPaletteIndexToTermId","interactionLock","drawTool","customLayers","onPointerWorldMove","onPointHover","onPointClick","onRegionHover","onRegionClick","onActiveRegionChange","getCellByCoordinatesRef","showOverviewMap","overviewMapOptions","drawInvalidateRef","overviewInvalidateRef","onViewStateChangeRef","onStatsRef","debugOverlayRef","isOverviewOpen","setIsOverviewOpen","useState","setHoveredRegionId","setActiveRegionId","customLayerViewState","setCustomLayerViewState","debugStats","setDebugStats","hoveredRegionIdRef","hoveredPointIndexRef","hoveredPointIdRef","clipRunIdRef","safeRoiRegions","safePatchRegions","safeRoiPolygons","shouldTrackCustomLayerViewState","mergedDebugOverlayStyle","effectiveRoiRegions","preparedRegionHits","clipPolygons","renderPointData","setRenderPointData","runId","applyResult","stats","outputCount","shouldEnablePointHitTest","pointSpatialIndex","getCellByCoordinates","coordinate","pointSizePx","hitRadiusWorld","baseCellX","baseCellY","cellRadius","nearestIndex","nearestDist2","nearestX","nearestY","cx","cy","pointId","emitPointHover","hit","nextIndex","nextId","emitPointClick","button","overviewHeight","overviewMargin","overviewPosition","commitActiveRegion","handleRendererStats","debugOverlayText","currentHover","hoveredPointIndex","emitViewStateChange","callback","resolveWorldCoord","resolveScreenCoord","requestCustomLayerRedraw","effectiveCustomLayerViewState","customLayerContext","viewStateForLayer","handleRegionPointerMove","isCanvasEvent","insideImage","nextHoverId","prevHoverId","handleRegionPointerLeave","handleRegionClick","nextActive","handleBrushTap","handleRegionContextMenu","jsxs","layer","Fragment"],"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,GACdX,GACAU,GACAE,GACsB;AACtB,QAAMC,IAAWb,EAAG,mBAAmBU,GAASE,CAAW;AAC3D,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,mCAAmCD,CAAW,EAAE;AAElE,SAAOC;AACT;AAEO,SAASC,GAAcC,GAAmD;AAC/E,QAAMC,IAAUD,EAAO,WAAW,UAAU;AAAA,IAC1C,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,EAAA,CAClB;AAED,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,0BAA0B;AAG5C,SAAOA;AACT;ACpEO,IAAAC,KAAA,MAAkB;AAAA,EAAlB;AACG,IAAAC,EAAA,uBAAgB;AAChB,IAAAA,EAAA,wBAAiB;AAEjB,IAAAA,EAAA,mBAAuB;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IAAA;AAAA;AAAA,EAGR,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;AAAA,EAEpD;AAAA,EAEA,eAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EACnB;AAAA,EAEA,YAA0B;AACxB,UAAMC,IAAY,KAAK,gBAAgB,KAAK,UAAU,MAChDC,IAAa,KAAK,iBAAiB,KAAK,UAAU,MAElDC,IAAK,IAAIF,GACTG,IAAK,KAAKF,GACVG,IAAK,KAAK,KAAK,UAAU,UAAUF,GACnCG,IAAK,IAAI,KAAK,UAAU,UAAUF;AAExC,WAAO,IAAI,aAAa;AAAA,MACtBD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAC;AAAA,MACA;AAAA,MACAC;AAAA,MACAC;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AACF;AC7CA,MAAMC,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,EAsB3B,YAAYC,GAAgC;AArB3B,IAAAb,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAIc,GAAA;AACb,IAAAd,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;AAG7B,SAAK,SAASa,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,KAAKjB,GAAc,KAAK,MAAM,GACnC,KAAK,UAAUT,GAAc,KAAK,IAAIuB,IAAeC,EAAe;AAEpE,UAAMI,IAAM,KAAK,GAAG,kBAAA,GACdC,IAAa,KAAK,GAAG,aAAA;AAC3B,QAAI,CAACD,KAAO,CAACC;AACZ,YAAM,IAAI,MAAM,iCAAiC;AAGlD,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;AAAA,MACrC;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,IAAA,CAC7C;AAED,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;AACpC,YAAM,IAAI,MAAM,oCAAoC;AAGrD,UAAMC,IAAS,IAAI,aAAa;AAChC,SAAK,GAAG,wBAAwBF,CAAY,GAC5C,KAAK,GAAG;AAAA,MACPA;AAAA,MACA;AAAA,MACA,KAAK,GAAG;AAAA,MACR;AAAA,MACAE;AAAA,MACA;AAAA,IAAA,GAED,KAAK,GAAG,wBAAwBD,CAAU,GAC1C,KAAK,GAAG;AAAA,MACPA;AAAA,MACA;AAAA,MACA,KAAK,GAAG;AAAA,MACR;AAAA,MACAC;AAAA,MACA,IAAI,aAAa;AAAA,IAAA,GAGlB,KAAK,GAAG,gBAAgB,IAAI,GAC5B,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,IAAI,GAE7C,KAAK,kBAAkB3B;AAAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAED,KAAK,kBAAkBA;AAAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAED,KAAK,mBAAmBA;AAAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAGGoB,EAAQ,qBACX,KAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,EAAQ,gBAAgB,IAGlD,KAAK,iBAAiB,IAAI,eAAe,MAAM;AAC9C,WAAK,OAAA;AAAA,IACN,CAAC,GAED,KAAK,eAAe,QAAQ,KAAK,MAAM,GACvC,KAAK,OAAA;AAAA,EACN;AAAA,EAEA,MAAM,SAASQ,GAAwC;AACtD,QAAI,KAAK;AACR;AAGD,UAAMC,IAAU,EAAE,KAAK,aAEjBC,IAAS,MAAM,QAAQ;AAAA,MAC5BF,EAAM,IAAI,OAAOG,MACG,MAAM,KAAK,SAASA,GAAMF,CAAO,CAEpD;AAAA,IAAA;AAGF,QAAI,KAAK,aAAaA,MAAY,KAAK,aAAa;AACnD,iBAAWE,KAAQD;AAClB,QAAIC,KACH,KAAK,GAAG,cAAcA,EAAK,OAAO;AAGpC;AAAA,IACD;AAEA,SAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQD,EAAO,OAAO,CAACC,MAA6BA,MAAS,IAAI,GACtE,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAaC,GAAqC;AACjD,SAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,CAAS,GAClC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,eAA0B;AACzB,WAAO,KAAK,OAAO,aAAA;AAAA,EACpB;AAAA,EAEA,UAAgB;AACf,IAAI,KAAK,cAIT,KAAK,YAAY,IACjB,KAAK,eAAe,GAEhB,KAAK,YAAY,SACpB,qBAAqB,KAAK,OAAO,GACjC,KAAK,UAAU,OAGhB,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,EACnC;AAAA,EAEA,MAAc,SACbD,GACAF,GAC6B;AAC7B,QAAI;AACH,YAAMI,IAAW,MAAM,MAAMF,EAAK,GAAG;AACrC,UAAI,CAACE,EAAS;AACb,cAAM,IAAI;AAAA,UACT,sBAAsBA,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,QAAA;AAI9D,YAAMC,IAAO,MAAMD,EAAS,KAAA,GACtBE,IAAS,MAAM,kBAAkBD,CAAI;AAE3C,UAAI,KAAK,aAAaL,MAAY,KAAK;AACtC,eAAAM,EAAO,MAAA,GACA;AAGR,YAAMC,IAAU,KAAK,GAAG,cAAA;AACxB,UAAI,CAACA;AACJ,cAAAD,EAAO,MAAA,GACD,IAAI,MAAM,gCAAgC;AAGjD,kBAAK,GAAG,YAAY,KAAK,GAAG,YAAYC,CAAO,GAC/C,KAAK,GAAG,YAAY,KAAK,GAAG,qBAAqB,CAAC,GAClD,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR;AAAA,QACA,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACRD;AAAA,MAAA,GAED,KAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5CA,EAAO,MAAA,GAEA;AAAA,QACN,IAAIJ,EAAK;AAAA,QACT,QAAQA,EAAK;AAAA,QACb,SAAAK;AAAA,MAAA;AAAA,IAEF,SAASC,GAAO;AACf,qBAAQ,MAAM,sCAAsCN,EAAK,EAAE,IAAIM,CAAK,GAC7D;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,SAAe;AACtB,QAAI,KAAK;AACR;AAGD,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,KACC,KAAK,OAAO,UAAUC,KACtB,KAAK,OAAO,WAAWC,OAEvB,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGtB,KAAK,OAAO,YAAYJ,GAAUC,CAAS,GAC3C,KAAK,GAAG,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,GAExD,CAAC,KAAK,UAAU,CAAC,KAAK,wBACzB,KAAK,WAAA,GACL,KAAK,SAAS,KAGf,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,aAAmB;AAC1B,UAAMI,IAAW,KAAK,OAAO,gBAAA,GAEvBC,IAAO,KAAK;AAAA,MACjBD,EAAS,QAAQ,KAAK;AAAA,MACtBA,EAAS,SAAS,KAAK;AAAA,IAAA,GAElBE,IAAW,OAAO,SAASD,CAAI,KAAKA,IAAO,IAAIA,IAAO,GAEtDE,IAAoBH,EAAS,QAAQE,GACrCE,IAAqBJ,EAAS,SAASE,GAEvCG,KAAW,KAAK,aAAaF,KAAqB,KAClDG,KAAW,KAAK,cAAcF,KAAsB;AAE1D,SAAK,OAAO,aAAa;AAAA,MACxB,MAAMF;AAAA,MACN,SAAAG;AAAA,MACA,SAAAC;AAAA,IAAA,CACA;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC7B,IAAI,KAAK,YAAY,QAAQ,KAAK,cAIlC,KAAK,UAAU,sBAAsB,MAAM;AAC1C,WAAK,UAAU,MACf,KAAK,OAAA;AAAA,IACN,CAAC;AAAA,EACF;AAAA,EAEQ,SAAe;AACtB,QAAI,MAAK,WAIT;AAAA,WAAK,GAAG;AAAA,QACP,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,MAAA,GAElB,KAAK,GAAG,MAAM,KAAK,GAAG,gBAAgB,GAEtC,KAAK,GAAG,WAAW,KAAK,OAAO,GAC/B,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG;AAAA,QACP,KAAK;AAAA,QACL;AAAA,QACA,KAAK,OAAO,UAAA;AAAA,MAAU,GAEvB,KAAK,GAAG,UAAU,KAAK,kBAAkB,CAAC;AAE1C,iBAAWnB,KAAQ,KAAK;AACvB,aAAK,GAAG,cAAc,KAAK,GAAG,QAAQ,GACtC,KAAK,GAAG,YAAY,KAAK,GAAG,YAAYA,EAAK,OAAO,GACpD,KAAK,GAAG;AAAA,UACP,KAAK;AAAA,UACLA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,QAAA,GAEd,KAAK,GAAG,WAAW,KAAK,GAAG,gBAAgB,GAAG,CAAC;AAGhD,WAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5C,KAAK,GAAG,gBAAgB,IAAI;AAAA;AAAA,EAC7B;AAAA,EAEQ,aAAaH,GAA2B;AAC/C,eAAWG,KAAQH;AAClB,WAAK,GAAG,cAAcG,EAAK,OAAO;AAAA,EAEpC;AACD;ACtXA,MAAMoB,KAA0B,KAC1BC,KAA4B,KAC5BC,KAA0B,MAC1BC,KAAuB,IACvBC,KAA2B,GAC3BC,KAAuB,GACvBC,KAAa,MACbC,KAAkB;AAExB,SAASC,GAAMC,GAAeC,GAAaC,GAAqB;AAC/D,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC1C;AAEA,SAASG,GACRC,GAC0B;AAC1B,MAAI,CAAC,MAAM,QAAQA,CAAW,KAAKA,EAAY,SAAS,EAAG,QAAO,CAAA;AAClE,QAAMC,IAAMD,EAAY,IAAI,CAAC,CAACE,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAA0B,GACjEC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MACxBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBH;AACR;AAEA,SAASK,GACRC,GAC0B;AAC1B,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAA;AAC1D,QAAMN,IAA+B,CAAA;AACrC,aAAWO,KAASD,GAAQ;AAC3B,QAAI,CAAC,MAAM,QAAQC,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAMN,IAAI,OAAOM,EAAM,CAAC,CAAC,GACnBL,IAAI,OAAOK,EAAM,CAAC,CAAC;AACzB,QAAI,CAAC,OAAO,SAASN,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,EAAG;AAChD,UAAMM,IAAOR,EAAIA,EAAI,SAAS,CAAC;AAC/B,IAAIQ,KAAQ,KAAK,IAAIA,EAAK,CAAC,IAAIP,CAAC,IAAI,QAAQ,KAAK,IAAIO,EAAK,CAAC,IAAIN,CAAC,IAAI,QAGpEF,EAAI,KAAK,CAACC,GAAGC,CAAC,CAAC;AAAA,EAChB;AACA,SAAOF;AACR;AAEA,SAASS,GACRC,GACAC,GACAC,GAC0B;AAC1B,MAAID,KAAUnB,MAAcoB,IAAQ,UAAU,CAAA;AAC9C,QAAMC,IAAgC,CAAA;AACtC,WAAS,IAAI,GAAG,KAAKD,GAAO,KAAK,GAAG;AACnC,UAAME,IAAK,IAAIF,IAAS,KAAK,KAAK;AAClC,IAAAC,EAAK,KAAK;AAAA,MACTH,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH;AAAA,MAC1BD,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH;AAAA,IAAA,CAC1B;AAAA,EACF;AACA,SAAOb,GAAUe,CAAI;AACtB;AAEA,SAASE,GACRT,GACAK,GAC0B;AAC1B,MAAI,CAACL,EAAO,OAAQ,QAAO,CAAA;AAC3B,MAAIU,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAW,CAAClB,GAAGC,CAAC,KAAKI;AACpB,IAAIL,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,MAAI,CAAC,OAAO,SAASc,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,EAAG,QAAO,CAAA;AAC7D,QAAMG,IAAM,KAAK,IAAIT,GAAQ,CAAC;AAC9B,SAAOb,GAAU;AAAA,IAChB,CAACkB,IAAOI,GAAKH,IAAOG,CAAG;AAAA,IACvB,CAACF,IAAOE,GAAKH,IAAOG,CAAG;AAAA,IACvB,CAACF,IAAOE,GAAKD,IAAOC,CAAG;AAAA,IACvB,CAACJ,IAAOI,GAAKD,IAAOC,CAAG;AAAA,EAAA,CACvB;AACF;AAEA,SAASC,GACRf,GACAK,GACoB;AACpB,MAAIK,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAW,CAAClB,GAAGC,CAAC,KAAKI;AACpB,IAAIL,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,QAAMkB,IAAM,KAAK,IAAIT,GAAQ,CAAC;AAC9B,SAAO,CAACK,IAAOI,GAAKH,IAAOG,GAAKF,IAAOE,GAAKD,IAAOC,CAAG;AACvD;AAEA,SAASE,GACRC,GACAZ,GACAxD,GACe;AACf,QAAMqE,IAAgB,KAAK;AAAA,IAC1BtC;AAAA,IACA,OAAO/B,EAAQ,aAAa,KAAK;AAAA,EAAA,GAE5BsE,IAAkB,KAAK;AAAA,IAC5B;AAAA,IACA,KAAK,MAAMtE,EAAQ,mBAAmBgC,EAAyB;AAAA,EAAA,GAE1DuC,IAAgB,KAAK;AAAA,IAC1B;AAAA,IACA,KAAK,MAAMvE,EAAQ,iBAAiBiC,EAAuB;AAAA,EAAA,GAGtDuC,IAAa,KAAK,IAAI,MAAMJ,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GACjDK,IAAc,KAAK,IAAI,MAAML,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC;AACxD,MAAIM,IAAO,KAAK,IAAIL,GAAe,OAAO,OAAO,GAC7CM,IAAU,GACVvF,IAAQ,KAAK,KAAKoF,IAAaE,CAAI,IAAIC,IAAU,IAAI,GACrDtF,IAAS,KAAK,KAAKoF,IAAcC,CAAI,IAAIC,IAAU,IAAI;AAE3D,UACCvF,IAAQmF,KACRlF,IAASkF,KACTnF,IAAQC,IAASiF,OAEjBI,KAAQ,MACRtF,IAAQ,KAAK,KAAKoF,IAAaE,CAAI,IAAIC,IAAU,IAAI,GACrDtF,IAAS,KAAK,KAAKoF,IAAcC,CAAI,IAAIC,IAAU,IAAI,GACnD,EAAAD,IAAO,KAAK,IAAIF,GAAYC,CAAW;AAA3C;AAKD,SAAArF,IAAQ,KAAK,IAAI,GAAGA,CAAK,GACzBC,IAAS,KAAK,IAAI,GAAGA,CAAM,GAEpB;AAAA,IACN,MAAM+E,EAAO,CAAC;AAAA,IACd,MAAMA,EAAO,CAAC;AAAA,IACd,MAAAM;AAAA,IACA,SAAAC;AAAA,IACA,OAAAvF;AAAA,IACA,QAAAC;AAAA,EAAA;AAEF;AAMA,SAASuF,GACRxF,GACAC,GAC4B;AAC5B,MAAI,OAAO,kBAAoB,KAAa;AAE3C,UAAMJ,IADS,IAAI,gBAAgBG,GAAOC,CAAM,EACzB,WAAW,MAAM,EAAE,oBAAoB,IAAM;AACpE,QAAIJ,EAAS,QAAOA;AAAA,EACrB;AACA,MAAI,OAAO,WAAa,KAAa;AACpC,UAAMD,IAAS,SAAS,cAAc,QAAQ;AAC9C,WAAAA,EAAO,QAAQI,GACfJ,EAAO,SAASK,GACTL,EAAO,WAAW,MAAM,EAAE,oBAAoB,IAAM;AAAA,EAC5D;AACA,SAAO;AACR;AAEA,SAAS6F,GACRzB,GACA0B,GACwB;AACxB,SAAO;AAAA,KACL1B,EAAM,CAAC,IAAI0B,EAAO,QAAQA,EAAO,OAAOA,EAAO;AAAA,KAC/C1B,EAAM,CAAC,IAAI0B,EAAO,QAAQA,EAAO,OAAOA,EAAO;AAAA,EAAA;AAElD;AAEA,SAASC,GACRC,GACAxB,GACAsB,GACa;AACb,QAAM7F,IAAU2F,GAAoBE,EAAO,OAAOA,EAAO,MAAM;AAC/D,MAAI,CAAC7F,EAAS,QAAO,IAAI,WAAW,CAAC;AAErC,EAAAA,EAAQ,UAAU,GAAG,GAAG6F,EAAO,OAAOA,EAAO,MAAM,GACnD7F,EAAQ,YAAY,WACpBA,EAAQ,cAAc,WACtBA,EAAQ,UAAU,SAClBA,EAAQ,WAAW,SACnBA,EAAQ,YAAauE,IAAS,IAAKsB,EAAO;AAE1C,QAAM3B,IAAS6B,EAAK,IAAI,OAASH,GAAczB,GAAO0B,CAAM,CAAC;AAC7D,MAAI3B,EAAO,UAAU,GAAG;AACvB,UAAM8B,IAAI9B,EAAO,CAAC;AAClB,QAAI,CAAC8B,EAAG,QAAO,IAAI,WAAW,CAAC;AAC/B,IAAAhG,EAAQ,UAAA,GACRA,EAAQ,IAAIgG,EAAE,CAAC,GAAGA,EAAE,CAAC,GAAGzB,IAASsB,EAAO,MAAM,GAAG,KAAK,KAAK,CAAC,GAC5D7F,EAAQ,KAAA;AAAA,EACT,OAAO;AACN,IAAAA,EAAQ,UAAA,GACRA,EAAQ,OAAOkE,EAAO,CAAC,EAAE,CAAC,GAAGA,EAAO,CAAC,EAAE,CAAC,CAAC;AACzC,aAAS+B,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK;AACvC,MAAAjG,EAAQ,OAAOkE,EAAO+B,CAAC,EAAE,CAAC,GAAG/B,EAAO+B,CAAC,EAAE,CAAC,CAAC;AAE1C,IAAAjG,EAAQ,OAAA;AAAA,EACT;AAEA,QAAMkG,IAAQlG,EAAQ,aAAa,GAAG,GAAG6F,EAAO,OAAOA,EAAO,MAAM,GAC9DjC,IAAM,IAAI,WAAWiC,EAAO,QAAQA,EAAO,MAAM;AACvD,WAASI,IAAI,GAAGA,IAAIrC,EAAI,QAAQqC,KAAK;AACpC,IAAArC,EAAIqC,CAAC,IAAIC,EAAM,KAAKD,IAAI,IAAI,CAAC,KAAK5C,KAAkB,IAAI;AAEzD,SAAOO;AACR;AAEA,SAASuC,GAAmBC,GAAkBjG,GAAeC,GAAgC;AAC5F,QAAMiG,IAAwB,CAAA,GACxB/E,IAASnB,IAAQ,GACjBmG,IAAS,CAACzC,GAAWC,MAAsBA,IAAIxC,IAASuC,GACxD0C,IAAK,CAAC1C,GAAWC,MACtBD,KAAK,KAAKC,KAAK,KAAKD,IAAI1D,KAAS2D,IAAI1D,KAAUgG,EAAKtC,IAAI3D,IAAQ0D,CAAC,IAAI;AAEtE,WAASC,IAAI,GAAGA,IAAI1D,GAAQ0D,KAAK;AAChC,aAASD,IAAI,GAAGA,IAAI1D,GAAO0D,KAAK;AAC/B,MAAK0C,EAAG1C,GAAGC,CAAC,MACPyC,EAAG1C,GAAGC,IAAI,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,GAAGC,CAAC;AAAA,QAClB,KAAKwC,EAAOzC,IAAI,GAAGC,CAAC;AAAA,QACpB,KAAK;AAAA,MAAA,CACL,GAEGyC,EAAG1C,IAAI,GAAGC,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,IAAI,GAAGC,CAAC;AAAA,QACtB,KAAKwC,EAAOzC,IAAI,GAAGC,IAAI,CAAC;AAAA,QACxB,KAAK;AAAA,MAAA,CACL,GAEGyC,EAAG1C,GAAGC,IAAI,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,IAAI,GAAGC,IAAI,CAAC;AAAA,QAC1B,KAAKwC,EAAOzC,GAAGC,IAAI,CAAC;AAAA,QACpB,KAAK;AAAA,MAAA,CACL,GAEGyC,EAAG1C,IAAI,GAAGC,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,GAAGC,IAAI,CAAC;AAAA,QACtB,KAAKwC,EAAOzC,GAAGC,CAAC;AAAA,QAChB,KAAK;AAAA,MAAA,CACL;AAKJ,SAAOuC;AACR;AAEA,SAASG,GAAaC,GAAiBC,GAAuB;AAC7D,QAAMC,KAASD,IAAQD,IAAU,KAAK;AACtC,SAAIE,MAAU,IAAU,IACpBA,MAAU,IAAU,IACpBA,MAAU,IAAU,IACjB;AACR;AAEA,SAASC,GAAWP,GAAmC;AACtD,MAAI,CAACA,EAAM,OAAQ,QAAO,CAAA;AAE1B,QAAMQ,wBAAe,IAAA;AACrB,WAAS,IAAI,GAAG,IAAIR,EAAM,QAAQ,KAAK,GAAG;AACzC,UAAMS,IAAQD,EAAS,IAAIR,EAAM,CAAC,EAAE,KAAK;AACzC,IAAIS,IACHA,EAAM,KAAK,CAAC,IAEZD,EAAS,IAAIR,EAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAElC;AAEA,QAAMU,IAAO,IAAI,WAAWV,EAAM,MAAM,GAClCW,IAAoB,CAAA;AAE1B,WAAS,IAAI,GAAG,IAAIX,EAAM,QAAQ,KAAK,GAAG;AACzC,QAAIU,EAAK,CAAC,EAAG;AAEb,UAAMhD,IAAQsC,EAAM,CAAC,GACfY,IAAclD,EAAM;AAC1B,QAAImD,IAAgBnD,EAAM,KACtBoD,IAAapD,EAAM;AACvB,UAAMqD,IAAiB,CAACrD,EAAM,OAAOA,EAAM,GAAG;AAC9C,IAAAgD,EAAK,CAAC,IAAI;AAEV,QAAIM,IAAQ;AACZ,UAAMC,IAAajB,EAAM,SAAS;AAClC,WAAOa,MAAkBD,KAAeI,IAAQC,KAAY;AAC3D,YAAMC,IAAaV,EAAS,IAAIK,CAAa;AAC7C,UAAI,CAACK,KAAcA,EAAW,WAAW,EAAG;AAE5C,UAAIC,IAAY,IACZC,IAAe;AACnB,iBAAWC,KAAaH,GAAY;AACnC,YAAIR,EAAKW,CAAS,EAAG;AACrB,cAAMC,IAAYtB,EAAMqB,CAAS,GAC3BE,IAAWpB,GAAaW,GAAYQ,EAAU,GAAG;AACvD,QAAIC,IAAWH,MACdA,IAAeG,GACfJ,IAAYE;AAAA,MAEd;AAEA,UAAIF,IAAY,EAAG;AACnB,MAAAT,EAAKS,CAAS,IAAI;AAClB,YAAMnH,IAAOgG,EAAMmB,CAAS;AAC5B,MAAAN,IAAgB7G,EAAK,KACrB8G,IAAa9G,EAAK,KAClB+G,EAAK,KAAKF,CAAa,GACvBG,KAAS;AAAA,IACV;AAEA,IACCD,EAAK,UAAU,KACfA,EAAK,CAAC,MAAMA,EAAKA,EAAK,SAAS,CAAC,KAEhCJ,EAAM,KAAKI,CAAI;AAAA,EAEjB;AAEA,SAAOJ;AACR;AAEA,SAASa,GACRC,GACA3H,GACA0F,GAC0B;AAC1B,QAAMvE,IAASnB,IAAQ,GACjBsE,IAAgC,CAAA;AACtC,aAAWsD,KAAMD,GAAY;AAC5B,UAAMjE,IAAIkE,IAAKzG,GACTwC,IAAI,KAAK,MAAMiE,IAAKzG,CAAM;AAChC,IAAAmD,EAAK,KAAK;AAAA,MACToB,EAAO,QAAQhC,IAAIgC,EAAO,WAAWA,EAAO;AAAA,MAC5CA,EAAO,QAAQ/B,IAAI+B,EAAO,WAAWA,EAAO;AAAA,IAAA,CAC5C;AAAA,EACF;AACA,SAAOnC,GAAUe,CAAI;AACtB;AAEA,SAASuD,GAAkBvD,GAAuC;AACjE,MAAIA,EAAK,SAAS,EAAG,QAAO;AAC5B,MAAIwD,IAAM;AACV,WAAShC,IAAI,GAAGA,IAAIxB,EAAK,SAAS,GAAGwB,KAAK,GAAG;AAC5C,UAAMiC,IAAIzD,EAAKwB,CAAC,GACVkC,IAAI1D,EAAKwB,IAAI,CAAC;AACpB,IAAAgC,KAAOC,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,EAChC;AACA,SAAOD,IAAM;AACd;AAEA,SAASG,GACR3D,GACA4D,IAAU,MACgB;AAC1B,QAAMC,IAAS5E,GAAUe,CAAI;AAC7B,MAAI6D,EAAO,SAAS,EAAG,QAAOA;AAC9B,QAAM1E,IAA+B,CAAC0E,EAAO,CAAC,CAAC;AAC/C,WAAS,IAAI,GAAG,IAAIA,EAAO,SAAS,GAAG,KAAK,GAAG;AAC9C,UAAMlE,IAAOR,EAAIA,EAAI,SAAS,CAAC,GACzB2E,IAAOD,EAAO,CAAC,GACfjI,IAAOiI,EAAO,IAAI,CAAC,GACnBE,KACJD,EAAK,CAAC,IAAInE,EAAK,CAAC,MAAM/D,EAAK,CAAC,IAAIkI,EAAK,CAAC,MACtCA,EAAK,CAAC,IAAInE,EAAK,CAAC,MAAM/D,EAAK,CAAC,IAAIkI,EAAK,CAAC;AACxC,IAAI,KAAK,IAAIC,CAAK,KAAKH,KACvBzE,EAAI,KAAK2E,CAAI;AAAA,EACd;AACA,SAAA3E,EAAI,KAAKA,EAAI,CAAC,CAAC,GACRF,GAAUE,CAAG;AACrB;AAEA,SAAS6E,GACRzC,GACAkC,GACAC,GACS;AACT,QAAMO,IAAMP,EAAE,CAAC,IAAID,EAAE,CAAC,GAChBS,IAAMR,EAAE,CAAC,IAAID,EAAE,CAAC,GAChBU,IAAOF,IAAMA,IAAMC,IAAMA;AAC/B,MAAIC,KAAQ,OAAO;AAClB,UAAMC,IAAK7C,EAAE,CAAC,IAAIkC,EAAE,CAAC,GACfY,IAAK9C,EAAE,CAAC,IAAIkC,EAAE,CAAC;AACrB,WAAOW,IAAKA,IAAKC,IAAKA;AAAAA,EACvB;AACA,QAAMpE,IAAIpB;AAAAA,MACP0C,EAAE,CAAC,IAAIkC,EAAE,CAAC,KAAKQ,KAAO1C,EAAE,CAAC,IAAIkC,EAAE,CAAC,KAAKS,KAAOC;AAAA,IAC9C;AAAA,IACA;AAAA,EAAA,GAEK/E,IAAIqE,EAAE,CAAC,IAAIQ,IAAMhE,GACjBZ,IAAIoE,EAAE,CAAC,IAAIS,IAAMjE,GACjBmE,IAAK7C,EAAE,CAAC,IAAInC,GACZiF,IAAK9C,EAAE,CAAC,IAAIlC;AAClB,SAAO+E,IAAKA,IAAKC,IAAKA;AACvB;AAEA,SAASC,GACR7E,GACA8E,GAC0B;AAC1B,MAAI9E,EAAO,UAAU,KAAK8E,KAAa,EAAG,QAAO9E,EAAO,MAAA;AAExD,QAAM+E,IAAO,IAAI,WAAW/E,EAAO,MAAM;AACzC,EAAA+E,EAAK,CAAC,IAAI,GACVA,EAAK/E,EAAO,SAAS,CAAC,IAAI;AAC1B,QAAMgF,IAAaF,IAAYA,GACzBG,IAAiC,CAAC,CAAC,GAAGjF,EAAO,SAAS,CAAC,CAAC;AAE9D,SAAOiF,EAAM,SAAS,KAAG;AACxB,UAAM9I,IAAO8I,EAAM,IAAA;AACnB,QAAI,CAAC9I,EAAM;AACX,UAAM,CAAC+I,GAAOC,CAAG,IAAIhJ;AACrB,QAAIgJ,IAAMD,KAAS,EAAG;AAEtB,QAAIE,IAAW,GACXC,IAAQ;AACZ,aAAStD,IAAImD,IAAQ,GAAGnD,IAAIoD,GAAKpD,KAAK,GAAG;AACxC,YAAMuD,IAAQf,GAAyBvE,EAAO+B,CAAC,GAAG/B,EAAOkF,CAAK,GAAGlF,EAAOmF,CAAG,CAAC;AAC5E,MAAIG,IAAQF,MACXA,IAAWE,GACXD,IAAQtD;AAAA,IAEV;AAEA,IAAIsD,KAAS,KAAKD,IAAWJ,MAC5BD,EAAKM,CAAK,IAAI,GACdJ,EAAM,KAAK,CAACC,GAAOG,CAAK,GAAG,CAACA,GAAOF,CAAG,CAAC;AAAA,EAEzC;AAEA,QAAMzF,IAA+B,CAAA;AACrC,WAASqC,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK;AACvC,IAAIgD,EAAKhD,CAAC,OAAO,KAAK/B,EAAO+B,CAAC,CAAC;AAEhC,SAAOrC;AACR;AAEA,SAAS6F,GACRhF,GACAuE,GAC0B;AAC1B,QAAMV,IAAS5E,GAAUe,CAAI;AAC7B,MAAI6D,EAAO,SAAS,KAAKU,KAAa,EAAG,QAAOV;AAChD,QAAMoB,IAAOpB,EAAO,MAAM,GAAG,EAAE,GACzBqB,IAAaZ,GAAYW,GAAMV,CAAS;AAC9C,SAAIW,EAAW,SAAS,IAAUrB,IAC3B5E,GAAUiG,CAAU;AAC5B;AAEA,SAASC,GACRnF,GACAoF,GAC0B;AAC1B,MAAIjG,IAAMF,GAAUe,CAAI;AACxB,MAAIoF,KAAc,KAAKjG,EAAI,SAAS,EAAG,QAAOA;AAE9C,WAASkG,IAAO,GAAGA,IAAOD,GAAYC,KAAQ,GAAG;AAChD,UAAMJ,IAAO9F,EAAI,MAAM,GAAG,EAAE;AAC5B,QAAI8F,EAAK,SAAS,EAAG;AACrB,UAAMrJ,IAAgC,CAAA;AACtC,aAAS4F,IAAI,GAAGA,IAAIyD,EAAK,QAAQzD,KAAK,GAAG;AACxC,YAAM,IAAIyD,EAAKzD,CAAC,GACVkC,IAAIuB,GAAMzD,IAAI,KAAKyD,EAAK,MAAM;AACpC,MAAArJ,EAAK;AAAA,QACJ,CAAC,EAAE,CAAC,IAAI,OAAO8H,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,IAAAvE,IAAMF,GAAUrD,CAAI;AAAA,EACrB;AACA,SAAOuD;AACR;AAEA,SAASmG,GACRtF,GACAU,GAC0B;AAC1B,SAAKA,IACEzB;AAAAA,IACNe,EAAK,IAAI,CAAC,CAACZ,GAAGC,CAAC,MAAM;AAAA,MACpBR,GAAMO,GAAGsB,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,MAC7B7B,GAAMQ,GAAGqB,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IAAA,CACJ;AAAA,EAAA,IALPV;AAOrB;AAEO,SAASuF,GACfjE,GACAhF,GAC0B;AAC1B,QAAMmD,IAASD,GAAa8B,CAAI,GAC1BxB,IAAS,KAAK,IAAInB,IAAY,OAAOrC,EAAQ,MAAM,KAAK,CAAC;AAC/D,MAAImD,EAAO,WAAW,KAAK,CAAC,OAAO,SAASK,CAAM,EAAG,QAAO,CAAA;AAE5D,QAAM0F,IAAc,KAAK,IAAI,IAAI,KAAK,MAAMlJ,EAAQ,eAAekC,EAAoB,CAAC;AACxF,MAAIiB,EAAO,WAAW;AACrB,WAAO6F;AAAA,MACN1F,GAAoBH,EAAO,CAAC,GAAGK,GAAQ0F,CAAW;AAAA,MAClDlJ,EAAQ;AAAA,IAAA;AAIV,QAAMoE,IAASF,GAAsBf,GAAQK,CAAM,GAC7C2F,IAAShF,GAAoBC,GAAQZ,GAAQxD,CAAO,GACpDqF,IAAON,GAAoB5B,GAAQK,GAAQ2F,CAAM;AACvD,MAAI,CAAC9D,EAAK;AACT,WAAO2D,GAAkBpF,GAAqBT,GAAQK,CAAM,GAAGxD,EAAQ,UAAU;AAGlF,QAAMsF,IAAQF,GAAmBC,GAAM8D,EAAO,OAAOA,EAAO,MAAM,GAC5DlD,IAAQJ,GAAWP,CAAK;AAC9B,MAAI,CAACW,EAAM;AACV,WAAO+C,GAAkBpF,GAAqBT,GAAQK,CAAM,GAAGxD,EAAQ,UAAU;AAGlF,MAAIoJ,IAAoC,CAAA,GACpCC,IAAW;AACf,aAAWhD,KAAQJ,GAAO;AACzB,UAAMvC,IAAOoD,GAAYT,GAAM8C,EAAO,OAAOA,CAAM,GAC7CG,IAAO,KAAK,IAAIrC,GAAkBvD,CAAI,CAAC;AAC7C,IAAI4F,KAAQD,MACZA,IAAWC,GACXF,IAAW1F;AAAA,EACZ;AAEA,MAAI,CAAC0F,EAAS;AACb,WAAOJ,GAAkBpF,GAAqBT,GAAQK,CAAM,GAAGxD,EAAQ,UAAU;AAGlF,QAAMiI,IACL,OAAOjI,EAAQ,qBAAsB,YAAY,OAAO,SAASA,EAAQ,iBAAiB,IACvF,KAAK,IAAI,GAAGA,EAAQ,iBAAiB,IACrCmJ,EAAO,OAAO,KACZI,IACL,OAAOvJ,EAAQ,mBAAoB,YAAY,OAAO,SAASA,EAAQ,eAAe,IACnF,KAAK,MAAMuC,GAAMvC,EAAQ,iBAAiB,GAAGoC,EAAoB,CAAC,IAClED,IACEyG,IAAaF;AAAA,IAClBG;AAAA,MACCxB,GAAwB+B,GAAUD,EAAO,OAAO,IAAI;AAAA,MACpDI;AAAA,IAAA;AAAA,IAEDtB;AAAA,EAAA;AAED,SAAOe,GAAkBJ,GAAY5I,EAAQ,UAAU;AACxD;ACrkBA,SAASwJ,GAAehH,GAAiC;AACxD,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK;AAC1D;AAEA,SAASiH,GAAiBjH,GAAwC;AACjE,SACC,MAAM,QAAQA,CAAK,KACnBA,EAAM,UAAU,KAChBgH,GAAehH,EAAM,CAAC,CAAC,KACvBgH,GAAehH,EAAM,CAAC,CAAC;AAEzB;AAEA,SAASkH,GAAalH,GAAwC;AAC7D,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,KAAKA,EAAM,MAAM,CAAAY,MAASqG,GAAiBrG,CAAK,CAAC;AAChG;AAEA,SAASuG,GAAenH,GAA0C;AACjE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,KAAKA,EAAM,MAAM,CAAAkB,MAAQgG,GAAahG,CAAI,CAAC;AAC1F;AAEA,SAASkG,GAAepH,GAA0C;AACjE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,KAAKA,EAAM,MAAM,CAAAqH,MAAWF,GAAeE,CAAO,CAAC;AAClG;AAEO,SAASC,GAAalH,GAAsD;AAClF,MAAI,CAAC,MAAM,QAAQA,CAAW,KAAKA,EAAY,SAAS,EAAG,QAAO,CAAA;AAClE,QAAMC,IAAqB,CAAA;AAC3B,aAAWO,KAASR,GAAa;AAChC,QAAI,CAAC,MAAM,QAAQQ,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAMN,IAAI,OAAOM,EAAM,CAAC,CAAC,GACnBL,IAAI,OAAOK,EAAM,CAAC,CAAC;AACzB,QAAI,CAAC,OAAO,SAASN,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,EAAG;AAChD,UAAMM,IAAOR,EAAIA,EAAI,SAAS,CAAC;AAC/B,IAAIQ,KAAQA,EAAK,CAAC,MAAMP,KAAKO,EAAK,CAAC,MAAMN,KACzCF,EAAI,KAAK,CAACC,GAAGC,CAAC,CAAC;AAAA,EAChB;AACA,MAAIF,EAAI,SAAS,EAAG,QAAO,CAAA;AAC3B,QAAMG,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,UAAIG,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBH,EAAI,UAAU,IAAIA,IAAM,CAAA;AAChC;AAEO,SAASoE,GAAkBvD,GAA6B;AAC9D,MAAI,CAAC,MAAM,QAAQA,CAAI,KAAKA,EAAK,SAAS,EAAG,QAAO;AACpD,MAAIwD,IAAM;AACV,WAAShC,IAAI,GAAGA,IAAIxB,EAAK,SAAS,GAAGwB,KAAK,GAAG;AAC5C,UAAMiC,IAAIzD,EAAKwB,CAAC,GACVkC,IAAI1D,EAAKwB,IAAI,CAAC;AACpB,IAAAgC,KAAOC,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,EAChC;AACA,SAAOD,IAAM;AACd;AAEA,SAAS6C,GAAsBC,GAAyC;AACvE,MAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,WAAW,EAAG,QAAO,CAAA;AACxD,QAAMC,IAA8B,CAAA;AACpC,aAAWvG,KAAQsG,GAAO;AACzB,UAAMzC,IAASuC,GAAapG,CAAI;AAChC,IAAI6D,EAAO,UAAU,KAAG0C,EAAW,KAAK1C,CAAM;AAAA,EAC/C;AACA,MAAI0C,EAAW,WAAW,EAAG,QAAO,CAAA;AACpC,MAAIA,EAAW,WAAW,UAAU,CAACA,EAAW,CAAC,CAAC;AAElD,MAAIC,IAAa,GACbC,IAAY;AAChB,WAASjF,IAAI,GAAGA,IAAI+E,EAAW,QAAQ/E,KAAK,GAAG;AAC9C,UAAMoE,IAAO,KAAK,IAAIrC,GAAkBgD,EAAW/E,CAAC,CAAC,CAAC;AACtD,IAAIoE,KAAQa,MACZA,IAAYb,GACZY,IAAahF;AAAA,EACd;AAEA,QAAMrC,IAAuB,CAACoH,EAAWC,CAAU,CAAC;AACpD,WAAShF,IAAI,GAAGA,IAAI+E,EAAW,QAAQ/E,KAAK;AAC3C,IAAIA,MAAMgF,KACVrH,EAAI,KAAKoH,EAAW/E,CAAC,CAAC;AAEvB,SAAOrC;AACR;AAEO,SAASuH,GAAqBC,GAA2D;AAC/F,MAAI,CAACA,EAAU,QAAO,CAAA;AAEtB,MAAIX,GAAaW,CAAQ,GAAG;AAC3B,UAAMR,IAAUE,GAAsB,CAACM,CAAQ,CAAC;AAChD,WAAOR,EAAQ,SAAS,IAAI,CAACA,CAAO,IAAI,CAAA;AAAA,EACzC;AAEA,MAAIF,GAAeU,CAAQ,GAAG;AAC7B,UAAMR,IAAUE,GAAsBM,CAAQ;AAC9C,WAAOR,EAAQ,SAAS,IAAI,CAACA,CAAO,IAAI,CAAA;AAAA,EACzC;AAEA,MAAID,GAAeS,CAAQ,GAAG;AAC7B,UAAMxH,IAAuB,CAAA;AAC7B,eAAWgH,KAAWQ,GAAU;AAC/B,YAAMJ,IAAaF,GAAsBF,CAAO;AAChD,MAAII,EAAW,SAAS,KAAGpH,EAAI,KAAKoH,CAAU;AAAA,IAC/C;AACA,WAAOpH;AAAA,EACR;AAEA,SAAO,CAAA;AACR;AAEO,SAASyH,GAAYxH,GAAWC,GAAWW,GAA8B;AAC/E,MAAI6G,IAAS;AACb,WAAS,IAAI,GAAGC,IAAI9G,EAAK,SAAS,GAAG,IAAIA,EAAK,QAAQ8G,IAAI,GAAG,KAAK,GAAG;AACpE,UAAMC,IAAK/G,EAAK,CAAC,EAAE,CAAC,GACdgH,IAAKhH,EAAK,CAAC,EAAE,CAAC,GACdiH,IAAKjH,EAAK8G,CAAC,EAAE,CAAC,GACdI,IAAKlH,EAAK8G,CAAC,EAAE,CAAC;AAIpB,IAFCE,IAAK3H,KAAM6H,IAAK7H,KAChBD,KAAM6H,IAAKF,MAAO1H,IAAI2H,MAASE,IAAKF,KAAO,OAAO,WAAWD,UACtC,CAACF;AAAA,EAC1B;AACA,SAAOA;AACR;AAmBO,SAASM,GACfC,GACuB;AACvB,QAAMC,IAAiC,CAAA;AACvC,aAAWV,KAAYS,KAAc,IAAI;AACxC,UAAME,IAAeZ,GAAqBC,CAAQ;AAClD,eAAWR,KAAWmB,GAAc;AACnC,YAAMC,IAAQpB,EAAQ,CAAC;AACvB,UAAI,CAACoB,KAASA,EAAM,SAAS,EAAG;AAChC,UAAIpH,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,iBAAW,CAAClB,GAAGC,CAAC,KAAKkI;AACpB,QAAInI,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,UACC,CAAC,OAAO,SAASc,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI;AAErB;AAED,UAAIsF,IAAO,KAAK,IAAIrC,GAAkBgE,CAAK,CAAC;AAC5C,eAAS/F,IAAI,GAAGA,IAAI2E,EAAQ,QAAQ3E,KAAK;AACxC,QAAAoE,KAAQ,KAAK,IAAIrC,GAAkB4C,EAAQ3E,CAAC,CAAC,CAAC;AAE/C,MAAA6F,EAAS,KAAK;AAAA,QACb,OAAAE;AAAA,QACA,OAAOpB,EAAQ,MAAM,CAAC;AAAA,QACtB,MAAAhG;AAAA,QACA,MAAAC;AAAA,QACA,MAAAC;AAAA,QACA,MAAAC;AAAA,QACA,MAAM,KAAK,IAAI,MAAMsF,CAAI;AAAA,MAAA,CACzB;AAAA,IACF;AAAA,EACD;AACA,SAAOyB;AACR;AAEO,SAASG,GACfpI,GACAC,GACA8G,GACU;AAIV,MAHI/G,IAAI+G,EAAQ,QAAQ/G,IAAI+G,EAAQ,QAAQ9G,IAAI8G,EAAQ,QAAQ9G,IAAI8G,EAAQ,QAGxE,CAACS,GAAYxH,GAAGC,GAAG8G,EAAQ,KAAK,EAAG,QAAO;AAC9C,aAAWsB,KAAQtB,EAAQ;AAC1B,QAAIS,GAAYxH,GAAGC,GAAGoI,CAAI,EAAG,QAAO;AAErC,SAAO;AACR;AAEO,SAASC,GACftI,GACAC,GACAsI,GACU;AACV,aAAWxB,KAAWwB;AACrB,QAAKH,GAAuBpI,GAAGC,GAAG8G,CAAO;AACzC,aAAO;AAER,SAAO;AACR;ACnOO,MAAMyB,KAAwD;AAAA,EACpE;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAChB;ACCO,SAAS/I,GAAMC,GAAeC,GAAaC,GAAqB;AACtE,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC1C;AAEO,SAAS+I,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,GACAC,GACAC,GACS;AAET,MAAIK,IAAS,MADMR,GAAoBC,GAAUC,GAAWC,CAAW;AAEvE,MAAI,OAAOF,CAAQ,GAAG;AACrB,QAAIQ,IAAO;AACX,WAAID,IAAS,QACZA,KAAU,KACVC,IAAO,OAED,GAAGD,EAAO,YAAY,CAAC,CAAC,IAAIC,CAAI;AAAA,EACxC;AACA,SAAO,GAAG,KAAK,MAAMD,IAAS,GAAI,IAAI,GAAI;AAC3C;AAEO,SAASE,GACf9E,GACAC,GACU;AACV,SAAI,CAACD,KAAK,CAACC,IAAU,KACjB,CAACD,KAAK,CAACC,IAAU,KAEpB,KAAK,KAAKD,EAAE,QAAQ,MAAMC,EAAE,QAAQ,EAAE,IAAI,QAC1C,KAAK,KAAKD,EAAE,WAAW,MAAMC,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKD,EAAE,WAAW,MAAMC,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKD,EAAE,eAAe,MAAMC,EAAE,eAAe,EAAE,IAAI;AAE1D;AAEO,SAAS8E,GAAc1J,GAA0C;AACvE,QAAM2J,IAAU,OAAO3J,KAAS,EAAE,EAAE,KAAA;AACpC,MAAI,CAAC2J,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,GAAGjB,EAAmB;AAE1C,QAAMkB,IAAI,OAAO,SAASD,EAAM,CAAC,GAAG,EAAE;AACtC,SAAO,CAAEC,KAAK,KAAM,KAAMA,KAAK,IAAK,KAAKA,IAAI,KAAK,GAAG;AACtD;AAEO,SAASC,GACfC,GAIc;AACd,QAAMC,IAAmD;AAAA,IACxD,CAAC,GAAGrB,EAAmB;AAAA,EAAA,GAElBsB,wBAAyB,IAAA;AAE/B,aAAWC,KAAQH,KAAS,IAAI;AAC/B,UAAMI,IAAS,OAAOD,GAAM,UAAU,EAAE;AACxC,IAAI,CAACC,KAAUF,EAAmB,IAAIE,CAAM,MAE5CF,EAAmB,IAAIE,GAAQH,EAAQ,MAAM,GAC7CA,EAAQ,KAAKN,GAAUQ,GAAM,SAAS,CAAC;AAAA,EACxC;AAEA,QAAME,IAAS,IAAI,WAAWJ,EAAQ,SAAS,CAAC;AAChD,WAAS,IAAI,GAAG,IAAIA,EAAQ,QAAQ,KAAK;AACxC,IAAAI,EAAO,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC,GAC5BI,EAAO,IAAI,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC,GAChCI,EAAO,IAAI,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC,GAChCI,EAAO,IAAI,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC;AAGjC,SAAO,EAAE,QAAAI,GAAQ,oBAAAH,EAAA;AAClB;AAEO,SAAStO,GACfL,GACAM,GACAC,GACe;AACf,QAAMwO,IAAK/O,EAAG,aAAaA,EAAG,aAAa,GACrCgP,IAAKhP,EAAG,aAAaA,EAAG,eAAe;AAC7C,MAAI,CAAC+O,KAAM,CAACC;AACX,UAAM,IAAI,MAAM,0BAA0B;AAK3C,MAFAhP,EAAG,aAAa+O,GAAIzO,CAAY,GAChCN,EAAG,cAAc+O,CAAE,GACf,CAAC/O,EAAG,mBAAmB+O,GAAI/O,EAAG,cAAc;AAC/C,UAAM,IAAI,MAAMA,EAAG,iBAAiB+O,CAAE,KAAK,uBAAuB;AAKnE,MAFA/O,EAAG,aAAagP,GAAIzO,CAAc,GAClCP,EAAG,cAAcgP,CAAE,GACf,CAAChP,EAAG,mBAAmBgP,GAAIhP,EAAG,cAAc;AAC/C,UAAM,IAAI,MAAMA,EAAG,iBAAiBgP,CAAE,KAAK,yBAAyB;AAGrE,QAAMtO,IAAUV,EAAG,cAAA;AACnB,MAAI,CAACU;AACJ,UAAM,IAAI,MAAM,2BAA2B;AAU5C,MAPAV,EAAG,aAAaU,GAASqO,CAAE,GAC3B/O,EAAG,aAAaU,GAASsO,CAAE,GAC3BhP,EAAG,YAAYU,CAAO,GAEtBV,EAAG,aAAa+O,CAAE,GAClB/O,EAAG,aAAagP,CAAE,GAEd,CAAChP,EAAG,oBAAoBU,GAASV,EAAG,WAAW;AAClD,UAAM,IAAI,MAAMA,EAAG,kBAAkBU,CAAO,KAAK,qBAAqB;AAGvE,SAAOA;AACR;ACgDA,MAAMuO,KAAY,2BACZC,KAAsB,GACtBC,KAAuB,GACvBC,KAAe,IACfC,KAAc,GACdC,KAA8B,CAAA,GAC9BC,KAAuB,CAAA,GACvBC,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,GAC3BC,KAAwB,MACxBC,KAAgC,KAChCC,KAAoB,KAEpBC,KAAiD;AAAA,EACrD,OAAO;AAAA,EACP,OAAO;AAAA,EAEP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AACjB,GAEMC,KAAgD;AAAA,EACpD,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,GAEMC,KAA+C;AAAA,EACnD,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;AAEA,SAAS3M,GAAMC,GAAeC,GAAaC,GAAqB;AAC9D,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC3C;AAEA,SAAS2M,GAAYC,GAAuC;AAC1D,SACEA,MAAS,qBAAqBA,MAAS,kBAAkBA,MAAS,4BAA4BA,MAAS,0BAA0BA,MAAS,uBAAuBA,MAAS;AAE9K;AAEA,SAASC,GAAwB7M,GAA2B8M,GAA0B;AACpF,SAAI,OAAO9M,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,KAAKA,KAAS,IAC5D8M,IAEF9M;AACT;AAEA,SAAS+M,GAAoBvP,GAA2D;AACtF,SAAO;AAAA,IACL,kBAAkBqP,GAAwBrP,GAAS,kBAAkB0N,EAAgC;AAAA,IACrG,eAAe2B,GAAwBrP,GAAS,eAAe2N,EAA6B;AAAA,IAC5F,oBAAoB0B,GAAwBrP,GAAS,oBAAoB4N,EAAkC;AAAA,EAAA;AAE/G;AAEA,SAAS4B,GAAiBhN,GAA2B8M,GAA0B;AAC7E,SAAI,OAAO9M,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU8M,IAC1D/M,GAAMC,GAAO,GAAG,CAAC;AAC1B;AAEA,SAASiN,GAAsBjN,GAAuC;AACpE,MAAI,CAAC,MAAM,QAAQA,CAAK,EAAG,QAAO8L;AAClC,QAAMzL,IAAML,EAAM,OAAO,CAAAkN,MAAQ,OAAO,SAASA,CAAI,KAAKA,KAAQ,CAAC;AACnE,SAAO7M,EAAI,SAAS,IAAIA,IAAMyL;AAChC;AAEA,SAASqB,GAAuBnN,GAAmC;AACjE,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU+L,KAC1DhM,GAAMC,GAAOgM,IAAuBC,EAAqB;AAClE;AAEA,SAASmB,GAA0BpN,GAAmC;AACpE,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUkM,KAC1D,KAAK,MAAMnM,GAAMC,GAAOmM,IAA0BC,EAAwB,CAAC;AACpF;AAEA,SAASiB,GAAoB7P,GAAyD;AACpF,QAAMwD,IAAS6L,GAAwBrP,GAAS,QAAQgO,EAAoB,GACtE8B,IAAkBT,GAAwBrP,GAAS,iBAAiBqO,EAA+B,GACnG0B,IAAaJ,GAAuB3P,GAAS,UAAU,GACvDgQ,IAAgBJ,GAA0B5P,GAAS,aAAa;AACtE,SAAO;AAAA,IACL,QAAAwD;AAAA,IACA,YAAAuM;AAAA,IACA,eAAAC;AAAA,IACA,gBAAgBhQ,GAAS,mBAAmB;AAAA,IAC5C,WAAWA,GAAS,aAAaiO;AAAA,IACjC,aAAauB,GAAiBxP,GAAS,aAAakO,EAA0B;AAAA,IAC9E,aAAalO,GAAS,eAAemO;AAAA,IACrC,mBAAmBnO,GAAS,qBAAqBoO;AAAA,IACjD,iBAAA0B;AAAA,IACA,gBAAgBL,GAAsBzP,GAAS,cAAc;AAAA,EAAA;AAEjE;AAEA,SAASiQ,GAASC,GAAyB;AACzC,SAAOA,IAAUzC,KAAiBA;AACpC;AAEA,SAAS0C,GAAuB5M,GAA+B6M,GAAsC;AACnG,SAAI,CAAC7M,KAAU,CAAC,OAAO,SAAS6M,CAAU,KAAKA,KAAc,IAAU,CAAA,IAChEzN,GAAU;AAAA,IACf,CAACY,EAAO,CAAC,IAAI6M,GAAY7M,EAAO,CAAC,IAAI6M,CAAU;AAAA,IAC/C,CAAC7M,EAAO,CAAC,IAAI6M,GAAY7M,EAAO,CAAC,IAAI6M,CAAU;AAAA,IAC/C,CAAC7M,EAAO,CAAC,IAAI6M,GAAY7M,EAAO,CAAC,IAAI6M,CAAU;AAAA,IAC/C,CAAC7M,EAAO,CAAC,IAAI6M,GAAY7M,EAAO,CAAC,IAAI6M,CAAU;AAAA,EAAA,CAChD;AACH;AAEA,SAASC,GAAuB9M,GAA+BC,GAAgBC,IAAQ4J,IAAgC;AACrH,MAAI,CAAC9J,KAAU,CAAC,OAAO,SAASC,CAAM,KAAKA,KAAU,EAAG,QAAO,CAAA;AAE/D,QAAM8M,IAA2B,CAAA;AACjC,WAAS,IAAI,GAAG,KAAK7M,GAAO,KAAK,GAAG;AAClC,UAAME,IAAK,IAAIF,IAAS,KAAK,KAAK;AAClC,IAAA6M,EAAO,KAAK,CAAC/M,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH,GAAQD,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH,CAAM,CAAC;AAAA,EAClF;AAEA,SAAOb,GAAU2N,CAAM;AACzB;AAEO,SAAS3N,GAAU2N,GAA4C;AACpE,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AAExD,QAAMzN,IAAMyN,EAAO,IAAI,CAAC,CAACxN,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,GACrDC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MAExBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC7CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAGxBH;AACT;AAEO,SAAS0N,GAAgBlI,GAA8BC,GAA8C;AAC1G,SAAI,CAACD,KAAS,CAACC,IAAY,CAAA,IAEpB3F,GAAU;AAAA,IACf,CAAC0F,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,SAASkI,GAAanI,GAA8BC,GAA4B7E,IAAQ4J,IAAgC;AAC7H,MAAI,CAAChF,KAAS,CAACC,UAAY,CAAA;AAE3B,QAAMmI,KAAWpI,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChCoI,KAAWrI,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChC9E,IAAS,KAAK,MAAM8E,EAAI,CAAC,IAAID,EAAM,CAAC,GAAGC,EAAI,CAAC,IAAID,EAAM,CAAC,CAAC,IAAI;AAClE,MAAI7E,IAAS,EAAG,QAAO,CAAA;AAEvB,QAAM8M,IAA2B,CAAA;AACjC,WAASpL,IAAI,GAAGA,KAAKzB,GAAOyB,KAAK,GAAG;AAClC,UAAMvB,IAAKuB,IAAIzB,IAAS,KAAK,KAAK;AAClC,IAAA6M,EAAO,KAAK,CAACG,IAAU,KAAK,IAAI9M,CAAC,IAAIH,GAAQkN,IAAU,KAAK,IAAI/M,CAAC,IAAIH,CAAM,CAAC;AAAA,EAC9E;AAEA,SAAOb,GAAU2N,CAAM;AACzB;AAEA,SAASK,GAAYL,GAAkC;AACrD,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO;AAExD,MAAIpJ,IAAM;AACV,WAAShC,IAAI,GAAGA,IAAIoL,EAAO,SAAS,GAAGpL,KAAK,GAAG;AAC7C,UAAMiC,IAAImJ,EAAOpL,CAAC,GACZkC,IAAIkJ,EAAOpL,IAAI,CAAC;AACtB,IAAAgC,KAAOC,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,EACjC;AAEA,SAAO,KAAK,IAAID,IAAM,GAAG;AAC3B;AAEA,SAAS0J,GAAcN,GAAsC;AAC3D,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAErE,MAAIzM,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AAEX,aAAW,CAAClB,GAAGC,CAAC,KAAKuN;AACnB,IAAIxN,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAGvB,SAAO,CAACc,GAAMC,GAAMC,GAAMC,CAAI;AAChC;AAEA,SAAS6M,GAAeP,GAAmC;AACzD,SAAO,MAAM,QAAQA,CAAM,KAAKA,EAAO,UAAU,KAAKK,GAAYL,CAAM,IAAIhD;AAC9E;AAEA,SAASwD,GAAUC,GAA+B5N,GAA0B6N,IAAQ,IAAa;AAC/F,MAAI7N,EAAO,WAAW,GAEtB;AAAA,IAAA4N,EAAI,OAAO5N,EAAO,CAAC,EAAE,CAAC,GAAGA,EAAO,CAAC,EAAE,CAAC,CAAC;AACrC,aAAS+B,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK;AACtC,MAAA6L,EAAI,OAAO5N,EAAO+B,CAAC,EAAE,CAAC,GAAG/B,EAAO+B,CAAC,EAAE,CAAC,CAAC;AAGvC,IAAI8L,KACFD,EAAI,UAAA;AAAA;AAER;AAEA,SAASE,GAASF,GAA+B5N,GAA0B+N,GAAgCF,IAAQ,IAAOG,IAAO,IAAa;AAC5I,EAAIhO,EAAO,WAAW,MAEtB4N,EAAI,UAAA,GACJD,GAAUC,GAAK5N,GAAQ6N,CAAK,GACxBG,KAAQH,MACVD,EAAI,YAAY7D,IAChB6D,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,YAAYvD,EAAU,GAC1BuD,EAAI,cAAc,oBAClBA,EAAI,aAAa,GACjBA,EAAI,gBAAgB,GACpBA,EAAI,gBAAgB;AACtB;AAEA,SAASK,GAAmBC,GAAkE;AAC5F,QAAMC,IAAO,MAAM,QAAQD,GAAO,QAAQ,IAAIA,EAAM,SAAS,OAAO,CAAA7O,MAAS,OAAO,SAASA,CAAK,KAAKA,KAAS,CAAC,IAAIgL,IAC/GpO,IAAQ,OAAOiS,GAAO,SAAU,YAAY,OAAO,SAASA,EAAM,KAAK,IAAI,KAAK,IAAI,GAAGA,EAAM,KAAK,IAAIrC,GAA4B,OAClIuC,IAAa,OAAOF,GAAO,cAAe,YAAY,OAAO,SAASA,EAAM,UAAU,IAAI,KAAK,IAAI,GAAGA,EAAM,UAAU,IAAIrC,GAA4B,YACtJwC,IAAgB,OAAOH,GAAO,iBAAkB,YAAY,OAAO,SAASA,EAAM,aAAa,IAAIA,EAAM,gBAAgBrC,GAA4B,eACrJyC,IAAgB,OAAOJ,GAAO,iBAAkB,YAAY,OAAO,SAASA,EAAM,aAAa,IAAIA,EAAM,gBAAgBrC,GAA4B;AAC3J,SAAO;AAAA,IACL,OAAOqC,GAAO,SAASrC,GAA4B;AAAA,IACnD,OAAA5P;AAAA,IACA,UAAUkS,EAAK,SAASA,IAAO9D;AAAA,IAC/B,UAAU6D,GAAO,YAAYrC,GAA4B;AAAA,IACzD,SAASqC,GAAO,WAAWrC,GAA4B;AAAA,IACvD,aAAaqC,GAAO,eAAerC,GAA4B;AAAA,IAC/D,YAAAuC;AAAA,IACA,eAAAC;AAAA,IACA,eAAAC;AAAA,EAAA;AAEJ;AAEA,SAASC,GAAiBC,GAAyBC,GAAqE;AACtH,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;AAEA,SAASE,GAAe1K,GAAuCC,GAAgD;AAC7G,SAAID,KAAM,QAA2BC,MAAM,QAAQA,MAAM,SAChD,KAEF,OAAOD,CAAC,MAAM,OAAOC,CAAC;AAC/B;AAEA,SAAS0K,GAAwBlP,GAA8C;AAC7E,QAAMI,IAAQJ,EAAY,CAAC;AAC3B,SAAO,MAAM,QAAQI,CAAK,KAAK,MAAM,QAAQA,EAAM,CAAC,CAAC;AACvD;AAEA,SAASwG,GAAehH,GAAiC;AACvD,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK;AAC3D;AAEA,SAASiH,GAAiBjH,GAA2C;AACnE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAKgH,GAAehH,EAAM,CAAC,CAAC,KAAKgH,GAAehH,EAAM,CAAC,CAAC;AACzG;AAEA,SAASuP,GAAiBvP,GAA2C;AACnE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAKA,EAAM,MAAM,CAAAY,MAASqG,GAAiBrG,CAAK,CAAC;AAClG;AAEA,SAAS4O,GAAoBxP,GAAgBK,GAA+B;AAC1E,MAAI,GAAC,MAAM,QAAQL,CAAK,KAAKA,EAAM,WAAW,IAC9C;AAAA,QAAIuP,GAAiBvP,CAAK,GAAG;AAC3B,MAAAK,EAAI,KAAKL,EAAM,IAAI,CAAC,CAACM,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,CAAC;AACxD;AAAA,IACF;AACA,eAAW2M,KAAQlN;AACjB,MAAAwP,GAAoBtC,GAAM7M,CAAG;AAAA;AAEjC;AAEA,SAASoP,GAAsBrP,GAAqCoO,GAAoC;AACtG,QAAMkB,IAAkC,CAAA;AACxC,EAAAF,GAAoBpP,GAAasP,CAAW;AAC5C,QAAMrP,IAA0B,CAAA;AAChC,aAAWa,KAAQwO,GAAa;AAC9B,QAAIxO,EAAK,SAAS,EAAG;AACrB,UAAMuG,IAAa+G,IAAQrO,GAAUe,CAAI,IAAIA;AAC7C,IAAIuG,EAAW,WAAW+G,IAAQ,IAAI,MACpCnO,EAAI,KAAKoH,CAAU;AAAA,EAEvB;AACA,SAAOpH;AACT;AAEA,SAASsP,GAAqBpB,GAA+BqB,GAA6BC,GAA+BC,GAAyB;AAChJ,MAAI,EAAAF,EAAU,SAAS,KAAKC,EAAU,WAAW,IACjD;AAAA,IAAAtB,EAAI,KAAA,GACJA,EAAI,UAAA,GACJD,GAAUC,GAAKqB,GAAW,EAAI;AAC9B,eAAW1O,KAAQ2O;AACjB,MAAI3O,EAAK,SAAS,KAClBoN,GAAUC,GAAKrN,GAAM,EAAI;AAE3B,IAAAqN,EAAI,YAAYuB,GAChBvB,EAAI,KAAK,SAAS,GAClBA,EAAI,QAAA;AAAA;AACN;AAEA,SAASwB,GAAkBlB,GAAgE;AACzF,QAAMmB,IAAK,OAAOnB,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAInC,GAA2B,UACvIuD,IAAK,OAAOpB,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAInC,GAA2B,UACvIjC,IAAK,OAAOoE,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAInC,GAA2B,UACvIwD,IAAK,OAAOrB,GAAO,eAAgB,YAAY,OAAO,SAASA,EAAM,WAAW,IAAI,KAAK,IAAI,GAAGA,EAAM,WAAW,IAAInC,GAA2B,aAChJyD,IAAK,OAAOtB,GAAO,WAAY,YAAY,OAAO,SAASA,EAAM,OAAO,IAAIA,EAAM,UAAUnC,GAA2B,SACvH0D,IAAK,OAAOvB,GAAO,gBAAiB,YAAY,OAAO,SAASA,EAAM,YAAY,IAAI,KAAK,IAAI,GAAGA,EAAM,YAAY,IAAInC,GAA2B;AACzJ,SAAO;AAAA,IACL,YAAYmC,GAAO,cAAcnC,GAA2B;AAAA,IAC5D,UAAUjC;AAAA,IACV,YAAYoE,GAAO,cAAcnC,GAA2B;AAAA,IAC5D,WAAWmC,GAAO,aAAanC,GAA2B;AAAA,IAC1D,iBAAiBmC,GAAO,mBAAmBnC,GAA2B;AAAA,IACtE,aAAamC,GAAO,eAAenC,GAA2B;AAAA,IAC9D,aAAawD;AAAA,IACb,UAAUF;AAAA,IACV,UAAUC;AAAA,IACV,SAASE;AAAA,IACT,cAAcC;AAAA,EAAA;AAElB;AAEA,SAASC,GAAgB9B,GAA+BjO,GAAWC,GAAW3D,GAAeC,GAAgBmE,GAAsB;AACjI,QAAMsP,IAAI,KAAK,IAAI,GAAG,KAAK,IAAItP,GAAQpE,IAAQ,KAAKC,IAAS,GAAG,CAAC;AACjE,EAAA0R,EAAI,UAAA,GACJA,EAAI,OAAOjO,IAAIgQ,GAAG/P,CAAC,GACnBgO,EAAI,OAAOjO,IAAI1D,IAAQ0T,GAAG/P,CAAC,GAC3BgO,EAAI,iBAAiBjO,IAAI1D,GAAO2D,GAAGD,IAAI1D,GAAO2D,IAAI+P,CAAC,GACnD/B,EAAI,OAAOjO,IAAI1D,GAAO2D,IAAI1D,IAASyT,CAAC,GACpC/B,EAAI,iBAAiBjO,IAAI1D,GAAO2D,IAAI1D,GAAQyD,IAAI1D,IAAQ0T,GAAG/P,IAAI1D,CAAM,GACrE0R,EAAI,OAAOjO,IAAIgQ,GAAG/P,IAAI1D,CAAM,GAC5B0R,EAAI,iBAAiBjO,GAAGC,IAAI1D,GAAQyD,GAAGC,IAAI1D,IAASyT,CAAC,GACrD/B,EAAI,OAAOjO,GAAGC,IAAI+P,CAAC,GACnB/B,EAAI,iBAAiBjO,GAAGC,GAAGD,IAAIgQ,GAAG/P,CAAC,GACnCgO,EAAI,UAAA;AACN;AAEA,SAASgC,GAAazC,GAAiD;AACrE,MAAI,CAACA,EAAO,OAAQ,QAAO;AAE3B,MAAIxM,IAAO;AACX,aAAWV,KAASkN;AAClB,IAAIlN,EAAM,CAAC,IAAIU,MAAMA,IAAOV,EAAM,CAAC;AAErC,MAAI,CAAC,OAAO,SAASU,CAAI,EAAG,QAAO;AAEnC,MAAID,IAAO,OACPE,IAAO;AACX,aAAWX,KAASkN;AAClB,IAAI,KAAK,IAAIlN,EAAM,CAAC,IAAIU,CAAI,IAAI,QAC5BV,EAAM,CAAC,IAAIS,MAAMA,IAAOT,EAAM,CAAC,IAC/BA,EAAM,CAAC,IAAIW,MAAMA,IAAOX,EAAM,CAAC;AAGrC,SAAI,CAAC,OAAO,SAASS,CAAI,KAAK,CAAC,OAAO,SAASE,CAAI,IAAU,OACtD,EAAEF,IAAOE,KAAQ,KAAKD,CAAI;AACnC;AAEA,SAASkP,GAAyB3H,GAAgE;AAChG,MAAI4H,IAA8B;AAClC,aAAWpJ,KAAWwB,GAAU;AAC9B,UAAM6H,IAASH,GAAalJ,EAAQ,KAAK;AACzC,IAAKqJ,MACD,CAACD,KAAQC,EAAO,CAAC,IAAID,EAAK,CAAC,KAAMC,EAAO,CAAC,MAAMD,EAAK,CAAC,KAAKC,EAAO,CAAC,IAAID,EAAK,CAAC,OAC9EA,IAAOC;AAAA,EAEX;AACA,SAAOD;AACT;AAEA,SAASE,GAA4BvQ,GAAmE;AACtG,QAAMoI,IAAeZ,GAAqBxH,CAA0B;AACpE,MAAIoI,EAAa,WAAW,EAAG,QAAO,CAAA;AAEtC,QAAMnI,IAAqC,CAAA;AAC3C,aAAWgH,KAAWmB,GAAc;AAClC,UAAMC,IAAQpB,EAAQ,CAAC;AACvB,QAAI,CAACoB,KAASA,EAAM,SAAS,EAAG;AAChC,UAAMmI,IAAkBnI,EAAM,IAAI,CAAC,CAACnI,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,GAChEsQ,IAA4B,CAAA;AAClC,aAASnO,IAAI,GAAGA,IAAI2E,EAAQ,QAAQ3E,KAAK,GAAG;AAC1C,YAAMiG,IAAOtB,EAAQ3E,CAAC;AACtB,MAAI,CAACiG,KAAQA,EAAK,SAAS,KAC3BkI,EAAM,KAAKlI,EAAK,IAAI,CAAC,CAACrI,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,CAAC;AAAA,IAC3D;AACA,IAAAF,EAAI,KAAK;AAAA,MACP,OAAOuQ;AAAA,MACP,OAAAC;AAAA,IAAA,CACD;AAAA,EACH;AACA,SAAOxQ;AACT;AAEA,SAASyQ,GAAgBvC,GAA+BwC,GAAcL,GAAwBM,GAAqBC,GAAsBC,GAAoC;AAC3K,QAAMC,IAAQJ,EAAK,KAAA;AACnB,MAAI,CAACI,EAAO;AAEZ,EAAA5C,EAAI,KAAA,GACJA,EAAI,OAAO,GAAG2C,EAAW,UAAU,IAAIA,EAAW,QAAQ,MAAMA,EAAW,UAAU,IACrF3C,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,QAAM6C,IADY7C,EAAI,YAAY4C,CAAK,EAAE,QACZD,EAAW,WAAW,GAC7CG,IAAYH,EAAW,WAAWA,EAAW,WAAW,GAExD5Q,IAAIP,GAAM2Q,EAAO,CAAC,GAAGU,IAAW,MAAM,GAAGJ,IAAcI,IAAW,MAAM,CAAC,GACzE7Q,IAAIR,GAAM2Q,EAAO,CAAC,IAAIQ,EAAW,SAASG,IAAY,MAAM,GAAGJ,IAAeI,IAAY,MAAM,CAAC,GACjGC,IAAOhR,IAAI8Q,IAAW,KACtBG,IAAMhR,IAAI8Q,IAAY;AAE5B,EAAA9C,EAAI,YAAY2C,EAAW,iBAC3B3C,EAAI,cAAc2C,EAAW,aAC7B3C,EAAI,YAAY2C,EAAW,aAC3Bb,GAAgB9B,GAAK+C,GAAMC,GAAKH,GAAUC,GAAWH,EAAW,YAAY,GAC5E3C,EAAI,KAAA,GACA2C,EAAW,cAAc,KAC3B3C,EAAI,OAAA,GAGNA,EAAI,YAAY2C,EAAW,WAC3B3C,EAAI,SAAS4C,GAAO7Q,GAAGC,IAAI,GAAG,GAC9BgO,EAAI,QAAA;AACN;AAEA,SAASiD,GAAWC,GAAuBC,GAAoBC,GAAqC;AAClG,SAAO,CAAC5R,GAAM0R,EAAM,CAAC,GAAG,GAAGC,CAAU,GAAG3R,GAAM0R,EAAM,CAAC,GAAG,GAAGE,CAAW,CAAC;AACzE;AAEA,SAASC,GAAQ5R,GAAyD;AACxE,MAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,EAAG,QAAO;AACtD,QAAMM,IAAI,OAAON,EAAM,CAAC,CAAC,GACnBO,IAAI,OAAOP,EAAM,CAAC,CAAC;AACzB,SAAI,CAAC,OAAO,SAASM,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,IAAU,OAChD,CAACD,GAAGC,CAAC;AACd;AAEO,SAASsR,GAAU;AAAA,EACxB,MAAAjF;AAAA,EACA,YAAA8E;AAAA,EACA,aAAAC;AAAA,EACA,UAAA3I;AAAA,EACA,WAAAC;AAAA,EACA,cAAA6I;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,0BAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC,KAAkB;AAAA,EAClB,gBAAAC,KAAiB;AAAA,EACjB,kBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAtE;AACF,GAAuC;AACrC,QAAMuE,IAAYC,EAAiC,IAAI,GACjDC,KAAiBD,EAAO,EAAK,GAC7BE,KAA0BF,EAA4B,oBAAI,KAAK,GAC/DG,KAAcH,EAAiBzG,CAAI,GACnC6G,KAAaJ,EAAoB;AAAA,IACrC,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ,CAAA;AAAA,IACR,aAAa;AAAA,EAAA,CACd,GAEKK,KAAStB,KAAWxF,MAAS,UAC7B+G,IAAyBC,EAAsB,MAC/CtB,KAAoBA,EAAiB,SAAS,IACzCA,IAEL,CAACE,KAAqBA,EAAkB,WAAW,IAC9CzH,KAEFyH,EAAkB,IAAI,CAACpS,GAAayT,OAAW;AAAA,IACpD,IAAIA;AAAA,IACJ,aAAAzT;AAAA,EAAA,EACA,GACD,CAACkS,GAAkBE,CAAiB,CAAC,GAClCsB,IAAqBF,EAAsB,MAAMrB,KAAgBxH,IAAe,CAACwH,CAAY,CAAC,GAC9FwB,IAA2BH,EAAkC,MAAM;AACvE,UAAMvT,IAAgC,CAAA;AACtC,aAASqC,IAAI,GAAGA,IAAIiR,EAAuB,QAAQjR,KAAK,GAAG;AACzD,YAAMsR,IAASL,EAAuBjR,CAAC,GACjCmG,IAAW8H,GAA4BqD,EAAO,WAAW;AAC/D,MAAInL,EAAS,WAAW,KACxBxI,EAAI,KAAK;AAAA,QACP,QAAA2T;AAAA,QACA,aAAatR;AAAA,QACb,WAAWsR,EAAO,MAAMtR;AAAA,QACxB,UAAAmG;AAAA,MAAA,CACD;AAAA,IACH;AACA,WAAOxI;AAAA,EACT,GAAG,CAACsT,CAAsB,CAAC,GACrBM,IAAuBL,EAAkC,MAAM;AACnE,UAAMvT,IAAgC,CAAA;AACtC,aAASqC,IAAI,GAAGA,IAAIoR,EAAmB,QAAQpR,KAAK,GAAG;AACrD,YAAMsR,IAASF,EAAmBpR,CAAC,GAC7BmG,IAAW8H,GAA4BqD,EAAO,WAAW;AAC/D,MAAInL,EAAS,WAAW,KACxBxI,EAAI,KAAK;AAAA,QACP,QAAA2T;AAAA,QACA,aAAatR;AAAA,QACb,WAAWsR,EAAO,MAAMtR;AAAA,QACxB,UAAAmG;AAAA,MAAA,CACD;AAAA,IACH;AACA,WAAOxI;AAAA,EACT,GAAG,CAACyT,CAAkB,CAAC,GAEjBI,IAAsBN,EAAQ,MAAMhF,GAAmB6D,CAAiB,GAAG,CAACA,CAAiB,CAAC,GAC9F0B,KAA2BP,EAAQ,MAAM1E,GAAiBgF,GAAqBxB,CAAsB,GAAG,CAACwB,GAAqBxB,CAAsB,CAAC,GACrJ0B,KAA4BR,EAAQ,MAAM1E,GAAiBgF,GAAqBvB,CAAuB,GAAG,CAACuB,GAAqBvB,CAAuB,CAAC,GACxJ0B,KAA2BT,EAAQ,MAAM1E,GAAiBzC,IAA4BmG,CAAgB,GAAG,CAACA,CAAgB,CAAC,GAE3H0B,KAAqBV,EAAQ,MAAM7D,GAAkBkD,EAAgB,GAAG,CAACA,EAAgB,CAAC,GAC1FsB,KAAuBX,EAAQ,MAAM7G,GAAoB+E,CAAY,GAAG,CAACA,CAAY,CAAC,GACtF0C,IAAuBZ,EAAQ,MAAMvG,GAAoB0E,CAAY,GAAG,CAACA,CAAY,CAAC,GAEtF0C,IAAcb;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,eAAeF,KAAS,SAAS;AAAA,MACjC,QAAQA,KAAU9G,MAAS,UAAU,SAAS,cAAe;AAAA,MAC7D,GAAGiC;AAAA,IAAA;AAAA,IAEL,CAAC6E,IAAQ9G,GAAMiC,EAAK;AAAA,EAAA,GAGhB6F,IAAeC,EAAY,MAAM;AACrC,UAAMnY,IAAS4W,EAAU;AACzB,QAAI,CAAC5W,EAAQ;AAEb,UAAMkC,IAAOlC,EAAO,sBAAA,GACdqC,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9C+V,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMlW,EAAK,QAAQG,CAAG,CAAC,GAC5CgW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMnW,EAAK,SAASG,CAAG,CAAC;AAEnD,KAAIrC,EAAO,UAAUoY,KAAKpY,EAAO,WAAWqY,OAC1CrY,EAAO,QAAQoY,GACfpY,EAAO,SAASqY;AAAA,EAEpB,GAAG,CAAA,CAAE,GAECC,IAAsBH;AAAA,IAC1B,CAAChU,MAA+C;AAC9C,YAAMoU,IAAY/C,EAAa;AAC/B,UAAI,CAAC+C,KAAapU,EAAO,WAAW,UAAU,CAAA;AAE9C,YAAMN,IAAM,IAAI,MAAsBM,EAAO,MAAM;AACnD,eAAS+B,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK,GAAG;AACzC,cAAM+O,IAAQG,GAAQmD,EAAU,cAAcpU,EAAO+B,CAAC,EAAE,CAAC,GAAG/B,EAAO+B,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,YAAI,CAAC+O,EAAO,QAAO,CAAA;AACnB,QAAApR,EAAIqC,CAAC,IAAI+O;AAAA,MACX;AACA,aAAOpR;AAAA,IACT;AAAA,IACA,CAAC2R,CAAY;AAAA,EAAA,GAGTgD,KAA4BL;AAAA,IAChC,CAAC5T,GAAwBkU,MAAgC;AACvD,UAAI,CAAC,OAAO,SAASA,CAAW,KAAKA,KAAe,EAAG,QAAO;AAC9D,YAAMF,IAAY/C,EAAa;AAC/B,UAAI,CAAC+C,EAAW,QAAO;AACvB,YAAMpQ,IAAIiN,GAAQmD,EAAU,cAAchU,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,CAAC,GACzD6D,IAAIgN,GAAQmD,EAAU,cAAchU,EAAO,CAAC,IAAIkU,GAAalU,EAAO,CAAC,CAAC,CAAC;AAC7E,aAAI,CAAC4D,KAAK,CAACC,IAAU,IACd,KAAK,MAAMA,EAAE,CAAC,IAAID,EAAE,CAAC,GAAGC,EAAE,CAAC,IAAID,EAAE,CAAC,CAAC;AAAA,IAC5C;AAAA,IACA,CAACqN,CAAY;AAAA,EAAA,GAGTkD,KAAuBP;AAAA,IAC3B,CAACQ,MAA6B;AAC5B,UAAI,CAAC,OAAO,SAASA,CAAQ,KAAKA,KAAY,EAAG,QAAO;AAGxD,YAAMC,IAAW,OAAOpM,KAAa,YAAY,OAAO,SAASA,CAAQ,KAAKA,IAAW,IAAIA,IAAW,GAClGqM,IAAiB,OAAOpM,KAAc,YAAY,OAAO,SAASA,CAAS,IAAIA,IAAY,GAC3FqM,IAActD,EAAa,SAAS,eAAA,EAAiB,MACrDuD,IAAW,OAAOD,KAAgB,YAAY,OAAO,SAASA,CAAW,KAAKA,IAAc,IAAIA,IAAc,GAC9GE,IAAiBH,IAAiB,KAAK,KAAKE,CAAQ,GACpDE,IAAmB,KAAK,IAAI,MAAM1M,GAAoBqM,GAAUC,GAAgBG,CAAc,CAAC;AAErG,aADqBL,IAAWM,IACVF;AAAA,IACxB;AAAA,IACA,CAACvM,GAAUC,GAAW+I,CAAY;AAAA,EAAA,GAG9B0D,KAAmBf;AAAA,IACvB,CAACgB,GAA0B5U,MAAoD;AAC7E,UAAI,CAACA,EAAQ,QAAO,CAAA;AAEpB,UAAI2M,IAAU;AACd,UAAIiI,MAAc,0BAA0B;AAC1C,cAAM/H,IAAa2G,GAAqB,qBAAqB;AAE7D,eADc5G,GAAuB5M,GAAQ6M,CAAU,EAC1C,IAAI,CAAAhN,MAAS4Q,GAAW5Q,GAAO8Q,GAAYC,CAAW,CAAC;AAAA,MACtE;AAOA,UALIgE,MAAc,qBAAqBA,MAAc,yBACnDjI,IAAUiI,MAAc,yBAAyBzK,KAAmCqJ,GAAqB,oBAChGoB,MAAc,kBAAkBA,MAAc,uBAAuBA,MAAc,+BAC5FjI,IAAUiI,MAAc,4BAA4BtK,KAA6BsK,MAAc,sBAAsBxK,KAAgCoJ,GAAqB,gBAExK,CAAC,OAAO,SAAS7G,CAAO,KAAKA,KAAW,UAAU,CAAA;AAEtD,YAAMkI,IAAUnI,GAASC,CAAO;AAChC,UAAII,IAA2B,CAAA;AAC/B,UAAI6H,MAAc,qBAAqBA,MAAc,wBAAwB;AAC3E,cAAM/H,IAAasH,GAAqB,KAAK,KAAKU,CAAO,IAAI,GAAG;AAChE,QAAA9H,IAASH,GAAuB5M,GAAQ6M,CAAU;AAAA,MACpD,WAAW+H,MAAc,kBAAkBA,MAAc,uBAAuBA,MAAc,2BAA2B;AACvH,cAAM3U,IAASkU,GAAqB,KAAK,KAAKU,IAAU,KAAK,EAAE,CAAC;AAChE,QAAA9H,IAASD,GAAuB9M,GAAQC,CAAM;AAAA,MAChD;AAEA,aAAK8M,EAAO,SACLA,EAAO,IAAI,CAAAlN,MAAS4Q,GAAW5Q,GAAO8Q,GAAYC,CAAW,CAAC,IAD1C,CAAA;AAAA,IAE7B;AAAA,IACA,CAACuD,IAAsBxD,GAAYC,GAAa4C,EAAoB;AAAA,EAAA,GAGhEsB,IAAqBlB,EAAY,MAAwB;AAC7D,UAAMmB,IAAUrC,GAAW;AAC3B,WAAI9G,GAAYC,CAAI,IACX8I,GAAiB9I,GAAMkJ,EAAQ,WAAW,IAE/ClJ,MAAS,UACJ,CAAA,IAEJkJ,EAAQ,YAETlJ,MAAS,aACJkJ,EAAQ,SAEblJ,MAAS,cACJmB,GAAgB+H,EAAQ,OAAOA,EAAQ,OAAO,IAEnDlJ,MAAS,aACJoB,GAAa8H,EAAQ,OAAOA,EAAQ,OAAO,IAG7C,CAAA,IAZwB,CAAA;AAAA,EAajC,GAAG,CAAClJ,GAAM8I,EAAgB,CAAC,GAErBK,KAAyBpB;AAAA,IAC7B,CAACpG,MAAwC;AACvC,YAAMuH,IAAUrC,GAAW;AAC3B,UAAI,CAACqC,EAAQ,aAAaA,EAAQ,OAAO,WAAW,EAAG;AAEvD,YAAME,IAAelB,EAAoBgB,EAAQ,MAAM;AACvD,UAAIE,EAAa,WAAW,EAAG;AAC/B,YAAMtF,IAASoF,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,KAAKA,EAAQ,OAAO,CAAC,GACtEG,IAAWjB,GAA0BtE,GAAQ8D,EAAqB,MAAM;AAC9E,UAAI,GAAC,OAAO,SAASyB,CAAQ,KAAKA,KAAY,IAS9C;AAAA,YAPA1H,EAAI,KAAA,GACJA,EAAI,cAAciG,EAAqB,aACvCjG,EAAI,YAAYiG,EAAqB,WACrCjG,EAAI,cAAciG,EAAqB,WACvCjG,EAAI,UAAU,SACdA,EAAI,WAAW,SACfA,EAAI,YAAY0H,IAAW,GACvBD,EAAa,WAAW;AAC1B,UAAAzH,EAAI,UAAA,GACJA,EAAI,IAAIyH,EAAa,CAAC,EAAE,CAAC,GAAGA,EAAa,CAAC,EAAE,CAAC,GAAGC,GAAU,GAAG,KAAK,KAAK,CAAC,GACxE1H,EAAI,KAAA;AAAA,aACC;AACL,UAAAA,EAAI,UAAA,GACJA,EAAI,OAAOyH,EAAa,CAAC,EAAE,CAAC,GAAGA,EAAa,CAAC,EAAE,CAAC,CAAC;AACjD,mBAAStT,IAAI,GAAGA,IAAIsT,EAAa,QAAQtT,KAAK;AAC5C,YAAA6L,EAAI,OAAOyH,EAAatT,CAAC,EAAE,CAAC,GAAGsT,EAAatT,CAAC,EAAE,CAAC,CAAC;AAEnD,UAAA6L,EAAI,OAAA;AAAA,QACN;AACA,QAAAA,EAAI,QAAA;AAAA;AAAA,IACN;AAAA,IACA,CAACuG,GAAqBE,IAA2BR,CAAoB;AAAA,EAAA,GAGjE0B,KAAkBvB;AAAA,IACtB,CAACpG,MAAwC;AACvC,YAAMuH,IAAUrC,GAAW,SACrB0C,IAASL,EAAQ;AACvB,UAAI,CAACK,EAAQ;AACb,YAAMC,IAASxE,GAAQI,EAAa,SAAS,cAAcmE,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,KAAK,CAAA,CAAE;AACtF,UAAI,CAACC,EAAQ;AACb,YAAMH,IAAWjB,GAA0BmB,GAAQ3B,EAAqB,MAAM;AAC9E,MAAI,CAAC,OAAO,SAASyB,CAAQ,KAAKA,KAAY,MAE9C1H,EAAI,KAAA,GACJA,EAAI,UAAA,GACJA,EAAI,IAAI6H,EAAO,CAAC,GAAGA,EAAO,CAAC,GAAGH,GAAU,GAAG,KAAK,KAAK,CAAC,GACtD1H,EAAI,cAAcuH,EAAQ,YAAYtB,EAAqB,oBAAoBA,EAAqB,aACpGjG,EAAI,YAAYiG,EAAqB,iBACrCjG,EAAI,YAAYiG,EAAqB,cAAc,GACnDjG,EAAI,OAAA,GACJA,EAAI,YAAYvD,EAAU,GAC1BuD,EAAI,QAAA;AAAA,IACN;AAAA,IACA,CAACyD,GAAcgD,IAA2BR,CAAoB;AAAA,EAAA,GAG1D6B,KAAc1B,EAAY,MAAM;AACpC,IAAAD,EAAA;AAEA,UAAMlY,IAAS4W,EAAU;AACzB,QAAI,CAAC5W,EAAQ;AAEb,UAAM+R,IAAM/R,EAAO,WAAW,IAAI;AAClC,QAAI,CAAC+R,EAAK;AAEV,UAAM1P,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9CmS,IAAcxU,EAAO,QAAQqC,GAC7BoS,IAAezU,EAAO,SAASqC;AAMrC,QALA0P,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAG/R,EAAO,OAAOA,EAAO,MAAM,GAC/C+R,EAAI,aAAa1P,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAGjCkV,EAAyB,SAAS;AACpC,iBAAWxQ,KAASwQ,GAA0B;AAC5C,cAAM,EAAE,QAAAC,GAAQ,UAAAnL,GAAU,aAAAyN,GAAa,WAAAC,OAAchT,GAC/CiT,KAAqCnH,GAAe2D,IAAgBuD,EAAS,IAAI,WAAWlH,GAAe0D,IAAiBwD,EAAS,IAAI,UAAU;AACzJ,YAAI7H,KAAc8H,OAAU,WAAWpC,KAA4BoC,OAAU,UAAUrC,KAA2BD;AAElH,YAAIrB,GAA0B;AAC5B,gBAAM4D,KAAW5D,EAAyB;AAAA,YACxC,QAAAmB;AAAA,YACA,UAAUuC;AAAA,YACV,aAAAD;AAAA,YACA,OAAAE;AAAA,UAAA,CACD;AACD,UAAA9H,KAAcQ,GAAiBR,IAAa+H,MAAY,MAAS;AAAA,QACnE;AAEA,mBAAWpP,MAAWwB,GAAU;AAC9B,gBAAM6N,KAAc5B,EAAoBzN,GAAQ,KAAK;AACrD,UAAIqP,GAAY,UAAU,KACxBjI,GAASF,GAAKmI,IAAahI,IAAa,IAAM,EAAK;AAErD,qBAAW/F,MAAQtB,GAAQ,OAAO;AAChC,kBAAMsP,KAAa7B,EAAoBnM,EAAI;AAC3C,YAAIgO,GAAW,UAAU,KACvBlI,GAASF,GAAKoI,IAAYjI,IAAa,IAAM,EAAK;AAAA,UAEtD;AAAA,QACF;AAAA,MACF;AAGF,QAAIuF,EAAqB,SAAS;AAChC,iBAAW1Q,KAAS0Q;AAClB,mBAAW5M,KAAW9D,EAAM,UAAU;AACpC,gBAAMmT,IAAc5B,EAAoBzN,EAAQ,KAAK;AACrD,UAAIqP,EAAY,UAAU,KACxBjI,GAASF,GAAKmI,GAAarC,IAA0B,IAAM,EAAK;AAElE,qBAAW1L,KAAQtB,EAAQ,OAAO;AAChC,kBAAMsP,KAAa7B,EAAoBnM,CAAI;AAC3C,YAAIgO,GAAW,UAAU,KACvBlI,GAASF,GAAKoI,IAAYtC,IAA0B,IAAM,EAAK;AAAA,UAEnE;AAAA,QACF;AAIJ,QAAI,MAAM,QAAQvB,CAAa,KAAKA,EAAc,SAAS,GAAG;AAC5D,YAAM8D,IAAe,EAAS,WAA0D,8BAClFC,IAAiB/B;AAAA,QACrB3U,GAAU;AAAA,UACR,CAAC,GAAG,CAAC;AAAA,UACL,CAACuR,GAAY,CAAC;AAAA,UACd,CAACA,GAAYC,CAAW;AAAA,UACxB,CAAC,GAAGA,CAAW;AAAA,QAAA,CAChB;AAAA,MAAA;AAEH,eAASjP,IAAI,GAAGA,IAAIoQ,EAAc,QAAQpQ,KAAK,GAAG;AAChD,cAAMoU,IAAQhE,EAAcpQ,CAAC;AAC7B,YAAI,CAACoU,GAAO,aAAa,UAAUA,EAAM,YAAY,GAAO;AAE5D,cAAM/R,KAAS+R,EAAM,UAAUxH,GAAwBwH,EAAM,WAAW,GAClEC,KAActH,GAAsBqH,EAAM,aAAa/R,EAAM;AAEnE,YAAI+R,EAAM,cAAc,WAAW;AACjC,gBAAMjH,KAAgC,CAAA,GAChCmH,KAAcvH,GAAsBqH,EAAM,aAAa,EAAI;AACjE,qBAAW5V,MAAQ8V,IAAa;AAC9B,kBAAMZ,KAAStB,EAAoB5T,EAAI;AACvC,YAAIkV,GAAO,UAAU,KACnBvG,GAAU,KAAKuG,EAAM;AAAA,UAEzB;AACA,cAAIQ,GAAc;AAChB,kBAAMK,KAAW,OAAOH,EAAM,MAAMpU,CAAC,GAC/BwU,KAAiB,GAAGL,EAAe,MAAM,IAAIG,GAAY,MAAM,IAAInH,GAAU,MAAM,IAAIiH,EAAM,aAAa,SAAS;AACzH,YAAIvD,GAAwB,QAAQ,IAAI0D,EAAQ,MAAMC,OACpD3D,GAAwB,QAAQ,IAAI0D,IAAUC,EAAc,GAC5D,QAAQ,MAAM,6BAA6B;AAAA,cACzC,IAAIJ,EAAM,MAAMpU;AAAA,cAChB,iBAAiBmU,EAAe;AAAA,cAChC,iBAAiBG,GAAY;AAAA,cAC7B,eAAenH,GAAU;AAAA,cACzB,WAAWiH,EAAM,aAAa;AAAA,YAAA,CAC/B;AAAA,UAEL;AACA,UAAAnH,GAAqBpB,GAAKsI,GAAgBhH,IAAWiH,EAAM,aAAa,SAAS;AAAA,QACnF;AAEA,YAAIC,GAAY,WAAW,EAAG;AAC9B,cAAMrI,KAAcQ,GAAiBgF,GAAqB4C,EAAM,UAAUA,EAAM,WAAW;AAC3F,mBAAW5V,MAAQ6V,IAAa;AAC9B,gBAAMX,KAAStB,EAAoB5T,EAAI;AACvC,UAAIkV,GAAO,SAAS,KACpB3H,GAASF,GAAK6H,IAAQ1H,IAAa3J,IAAQ+R,EAAM,QAAQ,EAAK;AAAA,QAChE;AAAA,MACF;AAAA,IACF;AAEA,QAAIpD;AACF,UAAI9G,MAAS;AACX,QAAAmJ,GAAuBxH,CAAG,GAC1B2H,GAAgB3H,CAAG;AAAA,WACd;AACL,cAAM4I,IAAUtB,EAAA;AAChB,YAAIsB,EAAQ,SAAS;AACnB,cAAIvK,MAAS,YAAY;AACvB,kBAAMwK,IAAOtC,EAAoBqC,CAAO;AACxC,YAAIC,EAAK,UAAU,KACjB3I,GAASF,GAAK6I,GAAMlD,GAAqB,IAAO,EAAK,GAEnDkD,EAAK,UAAU,KACjB3I,GAASF,GAAKuG,EAAoB3U,GAAUgX,CAAO,CAAC,GAAGjD,GAAqB,IAAM,EAAI;AAAA,UAE1F,OAAO;AACL,kBAAM7M,IAAUyN,EAAoBqC,CAAO;AAC3C,YAAI9P,EAAQ,UAAU,KACpBoH,GAASF,GAAKlH,GAAS6M,GAAqB,IAAM,EAAI;AAAA,UAE1D;AAAA,MAEJ;AAIF,QAAIH,EAAyB,SAAS;AACpC,iBAAWxQ,KAASwQ,GAA0B;AAC5C,YAAI,CAACxQ,EAAM,OAAO,MAAO;AACzB,cAAM8T,IAAc7G,GAAyBjN,EAAM,QAAQ;AAC3D,YAAI,CAAC8T,EAAa;AAClB,cAAMC,IAAe1F,GAAQI,EAAa,SAAS,cAAcqF,EAAY,CAAC,GAAGA,EAAY,CAAC,CAAC,KAAK,CAAA,CAAE;AACtG,QAAKC,KACLxG,GAAgBvC,GAAKhL,EAAM,OAAO,OAAO+T,GAActG,GAAaC,GAAcqD,EAAkB;AAAA,MACtG;AAAA,EAEJ,GAAG;AAAA,IACDZ;AAAA,IACA9G;AAAA,IACAiJ;AAAA,IACAE;AAAA,IACAG;AAAA,IACAxB;AAAA,IACAI;AAAA,IACApD;AAAA,IACAC;AAAA,IACAK;AAAA,IACA+B;AAAA,IACAjB;AAAA,IACAC;AAAA,IACAC;AAAA,IACAkB;AAAA,IACAC;AAAA,IACAC;AAAA,IACAH;AAAA,IACAI;AAAA,IACAxB;AAAA,IACAyB;AAAA,EAAA,CACD,GAEKiD,IAAc5C,EAAY,MAAM;AACpC,IAAIrB,GAAe,YACnBA,GAAe,UAAU,IACzB,sBAAsB,MAAM;AAC1B,MAAAA,GAAe,UAAU,IACzB+C,GAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACA,EAAW,CAAC,GAEVmB,KAAe7C,EAAY,CAAC8C,IAAiB,OAAU;AAC3D,UAAM3B,IAAUrC,GAAW,SACrBjX,IAAS4W,EAAU;AAEzB,QAAI5W,KAAUsZ,EAAQ,cAAc,QAAQtZ,EAAO,kBAAkBsZ,EAAQ,SAAS;AACpF,UAAI;AACF,QAAAtZ,EAAO,sBAAsBsZ,EAAQ,SAAS;AAAA,MAChD,QAAQ;AAAA,MAER;AAGF,IAAAA,EAAQ,YAAY,IACpBA,EAAQ,YAAY,MACpBA,EAAQ,QAAQ,MAChBA,EAAQ,UAAU,MAClBA,EAAQ,SAAS,CAAA,GACjBA,EAAQ,cAAc,MACjB2B,MACH3B,EAAQ,SAAS;AAAA,EAErB,GAAG,CAAA,CAAE,GAEC4B,KAAU/C;AAAA,IACd,CAACgD,MAAuE;AACtE,YAAM5C,IAAY/C,EAAa;AAC/B,UAAI,CAAC+C,KAAarD,KAAc,KAAKC,KAAe,EAAG,QAAO;AAE9D,YAAMiG,IAAMhG,GAAQmD,EAAU,cAAc4C,EAAM,SAASA,EAAM,OAAO,CAAC;AACzE,aAAKC,IACEpG,GAAWoG,GAAKlG,GAAYC,CAAW,IAD7B;AAAA,IAEnB;AAAA,IACA,CAACK,GAAcN,GAAYC,CAAW;AAAA,EAAA,GAGlCkG,KAAgBlD,EAAY,MAAM;AACtC,UAAMmB,IAAUrC,GAAW;AAC3B,QAAI,CAACqC,EAAQ,WAAW;AACtB,MAAA0B,GAAa,EAAI,GACjBD,EAAA;AACA;AAAA,IACF;AAEA,QAAInX,IAAgC,CAAA;AACpC,QAAIwM,MAAS;AACX,MAAIkJ,EAAQ,OAAO,UAAUnL,OAC3BvK,IAAcD,GAAU2V,EAAQ,MAAM;AAAA,aAE/BlJ,MAAS;AAClB,MAAAxM,IAAc2N,GAAgB+H,EAAQ,OAAOA,EAAQ,OAAO;AAAA,aACnDlJ,MAAS;AAClB,MAAAxM,IAAc4N,GAAa8H,EAAQ,OAAOA,EAAQ,OAAO;AAAA,aAChDlJ,MAAS,SAAS;AAC3B,YAAMkL,IAAWhC,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,KAAKA,EAAQ,WAAWA,EAAQ;AACzF,UAAItB,EAAqB,kBAAkBsD,KAAYhC,EAAQ,OAAO,UAAU,KAAK7D,IAAa6F,CAAQ,GAAG;AAC3G,QAAAN,GAAa,EAAI,GACjBD,EAAA;AACA;AAAA,MACF;AACA,YAAMhK,IAAaiH,EAAqB,YAClC3S,IAAgB,KAAK;AAAA,QACzBwK;AAAA,QACCmI,EAAqB,SAAS,KAAMlI,KAAgCiB;AAAA,MAAA;AAEvE,MAAAnN,IAAcqG,GAAwBqP,EAAQ,QAAQ;AAAA,QACpD,QAAQtB,EAAqB;AAAA,QAC7B,YAAY,CAAC,GAAG,GAAG9C,GAAYC,CAAW;AAAA,QAC1C,eAAA9P;AAAA,QACA,aAAa,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK0L,CAAU,CAAC;AAAA,QACrD,mBAAmB1L,IAAgB;AAAA,QACnC,iBAAiB2S,EAAqB;AAAA,MAAA,CACvC;AAAA,IACH;AAEA,KAAK5H,MAAS,cAAcA,MAAS,eAAeA,MAAS,cAAcA,MAAS,YAAYyB,GAAejO,CAAW,KAAK8R,KAE7HA,EAAe;AAAA,MACb,MAAAtF;AAAA,MACA,QAHyBA,MAAS,UAAU,UAAU;AAAA,MAItD,aAAAxM;AAAA,MACA,MAAMgO,GAAchO,CAAW;AAAA,MAC/B,QAAQ+N,GAAY/N,CAAW;AAAA,IAAA,CAChC,GAGHoX,GAAa,EAAI,GACjBD,EAAA;AAAA,EACF,GAAG,CAAC3K,GAAMsF,GAAgBsF,IAAcD,GAAa/C,EAAqB,QAAQA,EAAqB,YAAYA,EAAqB,eAAeA,EAAqB,gBAAgB9C,GAAYC,GAAaM,CAAU,CAAC,GAE1N8F,KAAgBpD;AAAA,IACpB,CAACgB,GAA0B5U,MAAiC;AAC1D,YAAMX,IAAcsV,GAAiBC,GAAW5U,CAAM;AACtD,UAAI,CAACsN,GAAejO,CAAW,EAAG;AAClC,YAAM4X,IAAqBrC,MAAc,2BAA2B,UAAU,OACxEsC,IAAqB;AAAA,QACzB,MAAMtC;AAAA,QACN,QAAAqC;AAAA,QACA,aAAA5X;AAAA,QACA,MAAMgO,GAAchO,CAAW;AAAA,QAC/B,QAAQ+N,GAAY/N,CAAW;AAAA,MAAA;AAEjC,MAAA8R,IAAiB+F,CAAM,GACnBD,MAAW,WAAW7F,KACxBA,EAAgB8F,CAAyB;AAAA,IAE7C;AAAA,IACA,CAACvC,IAAkBxD,GAAgBC,CAAe;AAAA,EAAA,GAG9C+F,KAAmBvD;AAAA,IACvB,CAACmB,GAAsBqC,MAAgC;AACrD,YAAMpD,IAAY/C,EAAa,SACzB/S,IAAO,KAAK,IAAI,MAAM8V,GAAW,eAAA,EAAiB,QAAQ,CAAC,GAC3DqD,IAAe7L,KAAoBtN,GACnCoZ,IAAgBD,IAAeA,GAC/BvX,IAAOiV,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC;AACrD,UAAI,CAACjV,GAAM;AACT,QAAAiV,EAAQ,OAAO,KAAKqC,CAAK,GACzBrC,EAAQ,UAAUqC;AAClB;AAAA,MACF;AACA,YAAM7S,IAAK6S,EAAM,CAAC,IAAItX,EAAK,CAAC,GACtB0E,IAAK4S,EAAM,CAAC,IAAItX,EAAK,CAAC;AAC5B,MAAIyE,IAAKA,IAAKC,IAAKA,KAAM8S,IACvBvC,EAAQ,OAAO,KAAKqC,CAAK,IAEzBrC,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,IAAIqC,GAE9CrC,EAAQ,UAAUqC;AAAA,IACpB;AAAA,IACA,CAACnG,CAAY;AAAA,EAAA,GAGTsG,KAAoB3D;AAAA,IACxB,CAACgD,MAAgD;AAG/C,UAFI,CAACjE,MACD9G,MAAS,YACT+K,EAAM,WAAW,EAAG;AAExB,YAAMQ,IAAQT,GAAQC,CAAK;AAC3B,UAAI,CAACQ,EAAO;AAKZ,UAHAR,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEFhL,GAAYC,CAAI,GAAG;AACrB,cAAMkJ,IAAUrC,GAAW;AAC3BqC,QAAAA,EAAQ,cAAcqC,GACtBJ,GAAcnL,GAAMuL,CAAK,GACzBZ,EAAA;AACA;AAAA,MACF;AAEA,YAAM/a,IAAS4W,EAAU;AACzB,MAAI5W,KACFA,EAAO,kBAAkBmb,EAAM,SAAS;AAG1C,YAAM7B,IAAUrC,GAAW;AAC3B,MAAAqC,EAAQ,YAAY,IACpBA,EAAQ,YAAY6B,EAAM,WAC1B7B,EAAQ,QAAQqC,GAChBrC,EAAQ,UAAUqC,GAClBrC,EAAQ,SAASqC,GACjBrC,EAAQ,SAASlJ,MAAS,cAAcA,MAAS,UAAU,CAACuL,CAAK,IAAI,CAAA,GACrEZ,EAAA;AAAA,IACF;AAAA,IACA,CAAC7D,IAAQ9G,GAAM8K,IAASK,IAAeR,CAAW;AAAA,EAAA,GAG9CgB,KAAoB5D;AAAA,IACxB,CAACgD,MAAgD;AAE/C,UADI,CAACjE,MACD9G,MAAS,SAAU;AAEvB,YAAMuL,IAAQT,GAAQC,CAAK;AAC3B,UAAI,CAACQ,EAAO;AAEZ,UAAIxL,GAAYC,CAAI,GAAG;AACrB,cAAMkJ,IAAUrC,GAAW;AAC3BqC,QAAAA,EAAQ,cAAcqC,GACtBR,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNJ,EAAA;AACA;AAAA,MACF;AAEA,YAAMzB,IAAUrC,GAAW;AAC3B,UAAI7G,MAAS,SAAS;AAEpB,YADAkJ,EAAQ,SAASqC,GACb,CAACrC,EAAQ,aAAaA,EAAQ,cAAc6B,EAAM,WAAW;AAC/D,UAAAJ,EAAA;AACA;AAAA,QACF;AACA,QAAAI,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNO,GAAiBpC,GAASqC,CAAK,GAC/BZ,EAAA;AACA;AAAA,MACF;AAEA,UAAI,GAACzB,EAAQ,aAAaA,EAAQ,cAAc6B,EAAM,YAMtD;AAAA,YAHAA,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEF/K,MAAS,YAAY;AACvB,gBAAMmI,IAAY/C,EAAa,SACzB/S,IAAO,KAAK,IAAI,MAAM8V,GAAW,eAAA,EAAiB,QAAQ,CAAC,GAC3DqD,IAAexN,KAAuB3L,GACtCoZ,IAAgBD,IAAeA,GAC/BvX,IAAOiV,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC;AAErD,cAAI,CAACjV;AACH,YAAAiV,EAAQ,OAAO,KAAKqC,CAAK;AAAA,eACpB;AACL,kBAAM7S,IAAK6S,EAAM,CAAC,IAAItX,EAAK,CAAC,GACtB0E,KAAK4S,EAAM,CAAC,IAAItX,EAAK,CAAC;AAC5B,YAAIyE,IAAKA,IAAKC,KAAKA,MAAM8S,KACvBvC,EAAQ,OAAO,KAAKqC,CAAK;AAAA,UAE7B;AAAA,QACF;AACE,UAAArC,EAAQ,UAAUqC;AAGpB,QAAAZ,EAAA;AAAA;AAAA,IACF;AAAA,IACA,CAAC7D,IAAQ9G,GAAM8K,IAASH,GAAavF,GAAckG,EAAgB;AAAA,EAAA,GAG/DM,KAAkB7D;AAAA,IACtB,CAACgD,MAAgD;AAC/C,YAAM7B,IAAUrC,GAAW;AAC3B,UAAI,CAACqC,EAAQ,aAAaA,EAAQ,cAAc6B,EAAM,UAAW;AAEjE,MAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,YAAMQ,IAAQT,GAAQC,CAAK;AAC3B,MAAIQ,MACFrC,EAAQ,SAASqC,GACbvL,MAAS,UACXsL,GAAiBpC,GAASqC,CAAK,IAE/BrC,EAAQ,UAAUqC;AAGtB,YAAM3b,IAAS4W,EAAU;AACzB,UAAI5W,KAAUA,EAAO,kBAAkBmb,EAAM,SAAS;AACpD,YAAI;AACF,UAAAnb,EAAO,sBAAsBmb,EAAM,SAAS;AAAA,QAC9C,QAAQ;AAAA,QAER;AAGF,MAAAE,GAAA;AAAA,IACF;AAAA,IACA,CAACA,IAAeH,IAAS9K,GAAMsL,EAAgB;AAAA,EAAA,GAG3CO,KAAqB9D,EAAY,MAAM;AAC3C,UAAMmB,IAAUrC,GAAW;AAC3B,QAAIiF,IAAU;AACd,IAAI9L,MAAS,WAAW,CAACkJ,EAAQ,aAAaA,EAAQ,WACpDA,EAAQ,SAAS,MACjB4C,IAAU,KAER/L,GAAYC,CAAI,KAAKkJ,EAAQ,gBAC/BA,EAAQ,cAAc,MACtB4C,IAAU,KAERA,KACFnB,EAAA;AAAA,EAEJ,GAAG,CAAC3K,GAAM2K,CAAW,CAAC;AAEtB,SAAAoB,EAAU,MAAM;AACd,IAAAjE,EAAA,GACA6C,EAAA;AAEA,UAAM/a,IAAS4W,EAAU;AACzB,QAAI,CAAC5W,EAAQ;AAEb,UAAMoc,IAAW,IAAI,eAAe,MAAM;AACxC,MAAAlE,EAAA,GACA6C,EAAA;AAAA,IACF,CAAC;AACD,WAAAqB,EAAS,QAAQpc,CAAM,GAEhB,MAAM;AACX,MAAAoc,EAAS,WAAA;AAAA,IACX;AAAA,EACF,GAAG,CAAClE,GAAc6C,CAAW,CAAC,GAE9BoB,EAAU,MAAM;AACd,IAAKjF,MACH8D,GAAA,GAEFD,EAAA;AAAA,EACF,GAAG,CAAC7D,IAAQ6D,GAAaC,EAAY,CAAC,GAEtCmB,EAAU,MAAM;AACd,IAAInF,GAAY,YAAY5G,MAG5B4G,GAAY,UAAU5G,GACtB4K,GAAA,GACAD,EAAA;AAAA,EACF,GAAG,CAAC3K,GAAM4K,IAAcD,CAAW,CAAC,GAEpCoB,EAAU,MAAM;AACd,IAAApB,EAAA;AAAA,EACF,GAAG,CAAClF,GAAiBsB,GAAwBb,GAAeyE,CAAW,CAAC,GAExEoB,EAAU,MAAM;AACd,QAAKzF;AACL,aAAAA,EAAc,UAAUqE,GACjB,MAAM;AACX,QAAIrE,EAAc,YAAYqE,MAC5BrE,EAAc,UAAU;AAAA,MAE5B;AAAA,EACF,GAAG,CAACA,GAAeqE,CAAW,CAAC,GAE/BoB,EAAU,MAAM;AACd,QAAI,CAACjF,GAAQ;AAEb,UAAMmF,IAAY,CAAClB,MAA+B;AAChD,MAAIA,EAAM,QAAQ,aAClBH,GAAA,GACAD,EAAA;AAAA,IACF;AAEA,kBAAO,iBAAiB,WAAWsB,CAAS,GACrC,MAAM;AACX,aAAO,oBAAoB,WAAWA,CAAS;AAAA,IACjD;AAAA,EACF,GAAG,CAACnF,IAAQ8D,IAAcD,CAAW,CAAC,GAGpC,gBAAAuB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK1F;AAAA,MACL,WAAAD;AAAA,MACA,OAAOsB;AAAA,MACP,eAAe6D;AAAA,MACf,eAAeC;AAAA,MACf,aAAaC;AAAA,MACb,iBAAiBA;AAAA,MACjB,gBAAgBC;AAAA,MAChB,eAAe,CAAAd,MAAS;AACtB,QAAIjE,QAAc,eAAA;AAAA,MACpB;AAAA,MACA,SAAS,CAAAiE,MAAS;AAChB,YAAI,CAACjE,GAAQ;AACb,cAAMlX,IAAS4W,EAAU,SACnB2B,IAAY/C,EAAa;AAC/B,YAAI,CAACxV,KAAU,OAAOuY,GAAW,UAAW,WAAY;AACxD,QAAA4C,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,cAAMjZ,IAAOlC,EAAO,sBAAA,GACduc,IAAUpB,EAAM,UAAUjZ,EAAK,MAC/Bsa,IAAUrB,EAAM,UAAUjZ,EAAK;AACrC,QAAAqW,EAAU,OAAO4C,EAAM,SAAS,IAAIrM,KAAuBC,IAAuBwN,GAASC,CAAO,GAClGzB,EAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAGN;AC3gDA,SAAS0B,GAAkBjZ,GAAuB;AAChD,SAAO,OAAOA,KAAS,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC/C;AAEA,SAASkZ,GAAmBlZ,GAAuB;AACjD,QAAM4X,IAAM,OAAO5X,KAAS,EAAE;AAC9B,SAAO4X,EAAI,WAAW,GAAG,IAAIA,IAAM,IAAIA,CAAG;AAC5C;AAEA,SAASuB,GAAgBC,GAA6B;AACpD,QAAMjK,IAAO8J,GAAkBG,CAAW;AAC1C,MAAI,CAACjK,EAAM,QAAO;AAGlB,MAAI,mBAAmB,KAAKA,CAAI,EAAG,QAAOA;AAE1C,MAAIkK,IAAqB;AACzB,MAAI;AACF,IAAAA,IAAS,IAAI,IAAIlK,CAAI;AAAA,EACvB,QAAQ;AACN,IAAAkK,IAAS;AAAA,EACX;AAEA,MAAIA,GAAQ;AACV,UAAMC,IAAS,GAAGD,EAAO,QAAQ,KAAKA,EAAO,IAAI,IAC3C7W,IAAOyW,GAAkBI,EAAO,YAAY,EAAE;AAIpD,WAAI,UAAU,KAAK7W,CAAI,IAAU,GAAG8W,CAAM,GAAG9W,CAAI,KAC7C,YAAY,KAAKA,CAAI,IAAU,GAAG8W,CAAM,GAAG9W,CAAI,KAC5C,GAAG8W,CAAM,GAAG9W,CAAI;AAAA,EACzB;AAGA,SAAI,UAAU,KAAK2M,CAAI,IAAU,SAC7B,YAAY,KAAKA,CAAI,IAAU,GAAGA,CAAI,KACnC,GAAGA,CAAI;AAChB;AAEO,SAASoK,GAAmB3B,GAAUwB,GAAqC;AAChF,QAAMI,IAAM5B,GAAK,WAAW,CAAA,GACtB6B,IAAQ,CAAC,CAAC7B,GAAK,SAEfhb,IAAQ,OAAO4c,EAAI,SAAS5B,GAAK,SAAS,CAAC,GAC3C/a,IAAS,OAAO2c,EAAI,UAAU5B,GAAK,UAAU,CAAC,GAC9C8B,IAAW,OAAOF,EAAI,YAAY5B,GAAK,YAAY,CAAC,GACpD+B,IAAc,OAAOH,EAAI,QAAQ5B,GAAK,QAAQ,CAAC,GAC/CgC,IAAW,OAAOJ,EAAI,QAAQ5B,GAAK,QAAQ,EAAE,GAC7CzO,IAAM,OAAOqQ,EAAI,OAAO5B,GAAK,OAAO,CAAC;AAE3C,MAAI,CAAChb,KAAS,CAACC,KAAU,CAAC6c,KAAY,CAACE;AACrC,UAAM,IAAI,MAAM,qDAAqD;AAGvE,QAAM1P,IAAmB,MAAM,QAAQ0N,GAAK,KAAK,IAC7CA,EAAI,MAAM,IAAI,CAACvN,OAAe;AAAA,IAC5B,QAAQ,OAAOA,GAAM,UAAU,EAAE;AAAA,IACjC,UAAU,OAAOA,GAAM,YAAY,EAAE;AAAA,IACrC,WAAW,OAAOA,GAAM,aAAa,EAAE;AAAA,EAAA,EACvC,IACF,CAAA,GAEEwP,IAAiBX,GAAmBU,CAAQ,GAC5CE,IAAcX,GAAgBC,CAAW,GACzCW,IAAiBN,IAAQ,CAACO,GAAc,GAAWzZ,MAAsB,GAAGuZ,CAAW,GAAGD,CAAc,IAAIG,CAAI,IAAIzZ,CAAC,IAAI,CAAC,UAAU;AAE1I,SAAO;AAAA,IACL,IAAIqX,GAAK,OAAO;AAAA,IAChB,MAAMA,GAAK,QAAQ;AAAA,IACnB,OAAAhb;AAAA,IACA,QAAAC;AAAA,IACA,KAAK,OAAO,SAASsM,CAAG,KAAKA,IAAM,IAAIA,IAAM;AAAA,IAC7C,UAAAuQ;AAAA,IACA,aAAa,OAAO,SAASC,CAAW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMA,CAAW,CAAC,IAAI;AAAA,IACnF,UAAAC;AAAA,IACA,aAAAR;AAAA,IACA,OAAAlP;AAAA,IACA,gBAAA6P;AAAA,EAAA;AAEJ;AAEO,SAASE,GAAUte,GAA6Eqe,GAAc1Z,GAAWC,GAAmB;AACjJ,MAAI5E,EAAO;AACT,WAAOA,EAAO,eAAeqe,GAAM1Z,GAAGC,CAAC;AAEzC,QAAMsZ,IAAiBX,GAAmBvd,EAAO,QAAQ;AACzD,SAAO,GAAGA,EAAO,WAAW,GAAGke,CAAc,IAAIG,CAAI,IAAIzZ,CAAC,IAAID,CAAC;AACjE;AClCA,MAAM4Z,KAAmD;AAAA,EACxD,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,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AACpB;AAEA,SAASC,GACRna,GACA8M,GACA7M,IAAM,GACG;AACT,SAAI,OAAOD,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU8M,IAC1D,KAAK,IAAI7M,GAAKD,CAAK;AAC3B;AAEA,SAASoa,GAAexY,GAAuD;AAC9E,SACC,MAAM,QAAQA,CAAM,KACpBA,EAAO,WAAW,KAClB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC;AAE3B;AAEO,SAASyY,GAAY;AAAA,EAC3B,QAAA1e;AAAA,EACA,cAAAqW;AAAA,EACA,WAAAsI,IAAY;AAAA,EACZ,SAAA9c;AAAA,EACA,eAAA0V;AAAA,EACA,WAAAC;AAAA,EACA,OAAAtE;AACD,GAAyC;AACxC,QAAMuE,IAAYC,EAAiC,IAAI,GACjDkH,IAAelH,EAAiC,IAAI,GACpDmH,IAAgBnH,EAAsB,IAAI,GAC1CoH,IAAcpH,EAAsD;AAAA,IACzE,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA,CACX,GACKqH,IAASrH,EAAsB,IAAI,GACnCC,IAAiBD,EAAO,EAAK,GAE7BzW,IAAQud;AAAA,IACb3c,GAAS;AAAA,IACT0c,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKrd,IAASsd;AAAA,IACd3c,GAAS;AAAA,IACT0c,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKS,IAASR;AAAA,IACd3c,GAAS;AAAA,IACT0c,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKU,IAAeT;AAAA,IACpB3c,GAAS;AAAA,IACT0c,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKW,IAAcV;AAAA,IACnB3c,GAAS;AAAA,IACT0c,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKY,IAAoB,KAAK;AAAA,IAC9B;AAAA,IACA,KAAK;AAAA,MACJX;AAAA,QACC3c,GAAS;AAAA,QACT0c,GAA6B;AAAA,QAC7B;AAAA,MAAA;AAAA,IACD;AAAA,EACD,GAGKa,IACLvd,GAAS,mBAAmB0c,GAA6B,iBACpDc,IACLxd,GAAS,eAAe0c,GAA6B,aAChDe,IACLzd,GAAS,uBACT0c,GAA6B,qBACxBgB,KACL1d,GAAS,qBACT0c,GAA6B,mBACxBiB,KACL3d,GAAS,eAAe0c,GAA6B,aAChDkB,KACL5d,GAAS,iBAAiB0c,GAA6B,eAClDmB,IACL7d,GAAS,YAAY0c,GAA6B,UAE7CzF,KAAcb,EAAuB,MAAM;AAChD,UAAM0H,IAAqB,CAAA;AAC3B,WAAID,MAAa,cAAcA,MAAa,kBAAmB,OAAOV,MAC7D,QAAQA,GACbU,MAAa,cAAcA,MAAa,gBAAiB,MAAMV,MAC1D,SAASA,GAEX;AAAA,MACN,UAAU;AAAA,MACV,GAAGW;AAAA,MACH,OAAA1e;AAAA,MACA,QAAAC;AAAA,MACA,cAAA+d;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAeO,KAAc,SAAS;AAAA,MACtC,aAAa;AAAA,MACb,WAAW;AAAA,MACX,GAAGtM;AAAA,IAAA;AAAA,EAEL,GAAG,CAAC8L,GAAQU,GAAUze,GAAOC,GAAQ+d,GAAcO,IAAatM,CAAK,CAAC,GAEhE0M,KAAO5G,EAAY,MAAM;AAC9B,UAAMnY,IAAS4W,EAAU;AACzB,QAAI,CAAC5W,EAAQ;AAEb,UAAM+R,IAAM/R,EAAO,WAAW,IAAI;AAClC,QAAI,CAAC+R,EAAK;AAEV,UAAMiN,IAAO5e,GACP6e,IAAO5e,GACPgC,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9C6c,KAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO3c,CAAG,CAAC,GAC3C8c,KAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO5c,CAAG,CAAC;AACjD,KAAIrC,EAAO,UAAUkf,MAAUlf,EAAO,WAAWmf,QAChDnf,EAAO,QAAQkf,IACflf,EAAO,SAASmf,KAGjBpN,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAG/R,EAAO,OAAOA,EAAO,MAAM,GAC/C+R,EAAI,aAAa1P,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAErC0P,EAAI,YAAYwM,GAChBxM,EAAI,SAAS,GAAG,GAAGiN,GAAMC,CAAI;AAE7B,UAAMtE,KAAUoD,EAAa;AAC7B,IAAIpD,MACH5I,EAAI,UAAU4I,IAAS,GAAG,GAAGqE,GAAMC,CAAI,GAGxClN,EAAI,cAAcyM,GAClBzM,EAAI,YAAYsM,GAChBtM,EAAI;AAAA,MACHsM,IAAc;AAAA,MACdA,IAAc;AAAA,MACdW,IAAOX;AAAA,MACPY,IAAOZ;AAAA,IAAA;AAGR,UAAM9F,KAAY/C,EAAa,SACzBpQ,KAASmT,IAAW,gBAAA,GACpB6G,IAAU7G,IAAW,iBAAA,GACrB8G,IAAazB,GAAexY,EAAM,IACrCA,KACAwY,GAAeI,EAAc,OAAO,IACnCA,EAAc,UACd;AACJ,QAAI,CAACqB,EAAY;AACjB,IAAArB,EAAc,UAAUqB;AAExB,UAAM5e,IAAKue,IAAO,KAAK,IAAI,GAAG7f,EAAO,KAAK,GACpCuB,IAAKue,IAAO,KAAK,IAAI,GAAG9f,EAAO,MAAM,GAErCmgB,KACL,MAAM,QAAQF,CAAO,KACrBA,EAAQ,UAAU,KAClBA,EAAQ;AAAA,MACP,CAAChb,MACA,MAAM,QAAQA,CAAK,KACnBA,EAAM,UAAU,KAChB,OAAO,SAASA,EAAM,CAAC,CAAC,KACxB,OAAO,SAASA,EAAM,CAAC,CAAC;AAAA,IAAA,IAEtBgb,IACD;AAEJ,QAAIE,IAAa;AAChB,MAAAvN,EAAI,UAAA;AACJ,eAAS7L,IAAI,GAAGA,IAAIoZ,GAAY,QAAQpZ,KAAK,GAAG;AAC/C,cAAM9B,KAAQkb,GAAYpZ,CAAC,GACrBpC,KAAIP,GAAMa,GAAM,CAAC,IAAI3D,GAAI,GAAGue,CAAI,GAChCjb,KAAIR,GAAMa,GAAM,CAAC,IAAI1D,GAAI,GAAGue,CAAI;AACtC,QAAI/Y,MAAM,IAAG6L,EAAI,OAAOjO,IAAGC,EAAC,IACvBgO,EAAI,OAAOjO,IAAGC,EAAC;AAAA,MACrB;AACA,MAAAgO,EAAI,UAAA,GACJA,EAAI,YAAY2M,IAChB3M,EAAI,KAAA,GACJA,EAAI,cAAc0M,GAClB1M,EAAI,YAAY,KAChBA,EAAI,OAAA;AACJ;AAAA,IACD;AAEA,UAAM+C,KAAOvR,GAAM8b,EAAW,CAAC,IAAI5e,GAAI,GAAGue,CAAI,GACxCjK,KAAMxR,GAAM8b,EAAW,CAAC,IAAI3e,GAAI,GAAGue,CAAI,GACvCM,IAAQhc,GAAM8b,EAAW,CAAC,IAAI5e,GAAI,GAAGue,CAAI,GACzCQ,KAASjc,GAAM8b,EAAW,CAAC,IAAI3e,GAAI,GAAGue,CAAI,GAC1CQ,KAAQ,KAAK,IAAI,GAAGF,IAAQzK,EAAI,GAChC4K,KAAQ,KAAK,IAAI,GAAGF,KAASzK,EAAG;AAEtC,IAAAhD,EAAI,YAAY2M,IAChB3M,EAAI,SAAS+C,IAAMC,IAAK0K,IAAOC,EAAK,GAEpC3N,EAAI,cAAc0M,GAClB1M,EAAI,YAAY,KAChBA,EAAI;AAAA,MACH+C,KAAO;AAAA,MACPC,KAAM;AAAA,MACN,KAAK,IAAI,GAAG0K,KAAQ,CAAC;AAAA,MACrB,KAAK,IAAI,GAAGC,KAAQ,CAAC;AAAA,IAAA;AAAA,EAEvB,GAAG;AAAA,IACFtf;AAAA,IACAC;AAAA,IACAke;AAAA,IACAC;AAAA,IACAH;AAAA,IACA7I;AAAA,IACArW,EAAO;AAAA,IACPA,EAAO;AAAA,IACPuf;AAAA,IACAD;AAAA,EAAA,CACA,GAEK1D,IAAc5C,EAAY,MAAM;AACrC,IAAIrB,EAAe,YACnBA,EAAe,UAAU,IACzBoH,EAAO,UAAU,sBAAsB,MAAM;AAC5C,MAAApH,EAAe,UAAU,IACzBoH,EAAO,UAAU,MACjBa,GAAA;AAAA,IACD,CAAC;AAAA,EACF,GAAG,CAACA,EAAI,CAAC,GAEHY,KAAoBxH;AAAA,IACzB,CAACyH,GAAiBC,MAA6C;AAC9D,YAAM7f,IAAS4W,EAAU;AACzB,UAAI,CAAC5W,EAAQ,QAAO;AAEpB,YAAMkC,IAAOlC,EAAO,sBAAA;AACpB,UAAI,CAACkC,EAAK,SAAS,CAACA,EAAK,OAAQ,QAAO;AAExC,YAAM4d,IAAKvc,IAAOqc,IAAU1d,EAAK,QAAQA,EAAK,OAAO,GAAG,CAAC,GACnD6d,KAAKxc,IAAOsc,IAAU3d,EAAK,OAAOA,EAAK,QAAQ,GAAG,CAAC;AACzD,aAAO,CAAC4d,IAAK3gB,EAAO,OAAO4gB,KAAK5gB,EAAO,MAAM;AAAA,IAC9C;AAAA,IACA,CAACA,EAAO,OAAOA,EAAO,MAAM;AAAA,EAAA,GAGvB6gB,KAAa7H;AAAA,IAClB,CAAC8H,GAAgBC,MAAmB;AACnC,YAAM3H,IAAY/C,EAAa;AAC/B,UAAI,CAAC+C,EAAW;AAEhB,UAAIA,EAAU,eAAe;AAC5B,QAAAA,EAAU,cAAc0H,GAAQC,CAAM,GACtCnF,EAAA;AACA;AAAA,MACD;AAEA,YAAM3V,IAASmT,EAAU,gBAAA,GACnB8G,IAAazB,GAAexY,CAAM,IACrCA,IACAwY,GAAeI,EAAc,OAAO,IACnCA,EAAc,UACd;AACJ,UAAI,CAACqB,EAAY;AAEjB,YAAMc,KAAW,KAAK,IAAI,MAAMd,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC,GACvDe,KAAW,KAAK,IAAI,MAAMf,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC;AAE7D,MAAA9G,EAAU,aAAa;AAAA,QACtB,SAAS0H,IAASE,KAAW;AAAA,QAC7B,SAASD,IAASE,KAAW;AAAA,MAAA,CAC7B,GACDrF,EAAA;AAAA,IACD;AAAA,IACA,CAACvF,GAAcuF,CAAW;AAAA,EAAA,GAGrBe,KAAoB3D;AAAA,IACzB,CAACgD,MAAgD;AAEhD,UADI,CAACwD,MACDxD,EAAM,WAAW,EAAG;AAExB,YAAMnb,IAAS4W,EAAU;AACzB,UAAI,CAAC5W,EAAQ;AAEb,YAAM2b,IAAQgE,GAAkBxE,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKQ,MAELR,EAAM,eAAA,GACNA,EAAM,gBAAA,GAENnb,EAAO,kBAAkBmb,EAAM,SAAS,GACxC8C,EAAY,UAAU,EAAE,QAAQ,IAAM,WAAW9C,EAAM,UAAA,GACvD6E,GAAWrE,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,CAACgD,IAAagB,IAAmBK,EAAU;AAAA,EAAA,GAGtCjE,KAAoB5D;AAAA,IACzB,CAACgD,MAAgD;AAChD,YAAMkF,IAAOpC,EAAY;AACzB,UAAI,CAACoC,EAAK,UAAUA,EAAK,cAAclF,EAAM,UAAW;AAExD,YAAMQ,IAAQgE,GAAkBxE,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKQ,MAELR,EAAM,eAAA,GACNA,EAAM,gBAAA,GACN6E,GAAWrE,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,CAACgE,IAAmBK,EAAU;AAAA,EAAA,GAGzBhE,KAAkB7D;AAAA,IACvB,CAACgD,MAAgD;AAChD,YAAMkF,IAAOpC,EAAY;AACzB,UAAI,CAACoC,EAAK,UAAUA,EAAK,cAAclF,EAAM,UAAW;AAExD,YAAMnb,IAAS4W,EAAU;AACzB,UAAI5W,KAAUA,EAAO,kBAAkBmb,EAAM,SAAS;AACrD,YAAI;AACH,UAAAnb,EAAO,sBAAsBmb,EAAM,SAAS;AAAA,QAC7C,QAAQ;AAAA,QAER;AAGD,MAAA8C,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAClDlD,EAAA;AAAA,IACD;AAAA,IACA,CAACA,CAAW;AAAA,EAAA;AAGb,SAAAoB,EAAU,MAAM;AACf,QAAImE,IAAY;AAChB,IAAAvC,EAAa,UAAU,MACvBhD,EAAA;AAEA,UAAMyC,IAAO,GACP+C,IAAa,MAAMphB,EAAO,cAAcqe,IACxCgD,IAAa,KAAK,KAAKrhB,EAAO,QAAQohB,CAAU,GAChDE,IAAc,KAAK,KAAKthB,EAAO,SAASohB,CAAU,GAClDG,KAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAarhB,EAAO,QAAQ,CAAC,GAC5DwhB,KAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAActhB,EAAO,QAAQ,CAAC,GAC7DyhB,KAAYF,KAASC;AAE3B,QAAI,CAAC/B,MAAiBgC,KAAYtC;AACjC;AAGD,UAAM3D,KAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,GAAQ,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAMva,CAAK,CAAC,GAC7Cua,GAAQ,SAAS,KAAK,IAAI,GAAG,KAAK,MAAMta,CAAM,CAAC;AAC/C,UAAM0R,KAAM4I,GAAQ,WAAW,IAAI;AACnC,QAAI,CAAC5I;AACJ;AAGD,IAAAA,GAAI,YAAYwM,GAChBxM,GAAI,SAAS,GAAG,GAAG4I,GAAQ,OAAOA,GAAQ,MAAM;AAEhD,UAAMkG,IAGD,CAAA;AAEL,aAAS9c,IAAI,GAAGA,IAAI4c,IAAQ5c,KAAK;AAChC,eAASD,IAAI,GAAGA,IAAI4c,IAAQ5c,KAAK,GAAG;AACnC,cAAMgR,IAAOhR,IAAI3E,EAAO,WAAWohB,GAC7BxL,KAAMhR,IAAI5E,EAAO,WAAWohB,GAC5BhB,KACL,KAAK,KAAKzb,IAAI,KAAK3E,EAAO,UAAUqhB,CAAU,IAAID,GAC7Cf,KACL,KAAK,KAAKzb,IAAI,KAAK5E,EAAO,UAAUshB,CAAW,IAAIF;AACpD,QAAAM,EAAS,KAAK;AAAA,UACb,KAAKpD,GAAUte,GAAQqe,GAAM1Z,GAAGC,CAAC;AAAA,UACjC,QAAQ,CAAC+Q,GAAMC,IAAKwK,IAAOC,EAAM;AAAA,QAAA,CACjC;AAAA,MACF;AAGD,WAAK,QAAQ;AAAA,MACZqB,EAAS,IAAI,OAAOlf,MAAS;AAC5B,cAAMmf,IAAgB,CAAC,CAAChD,GAClBjc,IAAW,MAAM,MAAMF,EAAK,KAAK;AAAA,UACtC,SAASmf,IAAgB,EAAE,eAAehD,MAAc;AAAA,QAAA,CACxD;AACD,YAAI,CAACjc,EAAS;AACb,gBAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,EAAE;AAE1C,cAAME,KAAS,MAAM,kBAAkB,MAAMF,EAAS,MAAM;AAC5D,eAAO,EAAE,MAAAF,GAAM,QAAAI,GAAA;AAAA,MAChB,CAAC;AAAA,IAAA,EACA,KAAK,CAACgf,MAAY;AACnB,UAAIT,GAAW;AACd,mBAAW7E,MAAUsF;AACpB,UAAItF,GAAO,WAAW,eACrBA,GAAO,MAAM,OAAO,MAAA;AAGtB;AAAA,MACD;AAEA,YAAMhb,IAAKka,GAAQ,QAAQ,KAAK,IAAI,GAAGxb,EAAO,KAAK,GAC7CuB,IAAKia,GAAQ,SAAS,KAAK,IAAI,GAAGxb,EAAO,MAAM;AACrD,iBAAWsc,MAAUsF,GAAS;AAC7B,YAAItF,GAAO,WAAW,YAAa;AACnC,cAAM;AAAA,UACL,MAAM,EAAE,QAAArW,GAAA;AAAA,UACR,QAAArD;AAAA,QAAA,IACG0Z,GAAO,OACL3S,IAAK1D,GAAO,CAAC,IAAI3E,GACjBsI,KAAK3D,GAAO,CAAC,IAAI1E,GACjBsgB,KAAK,KAAK,IAAI,IAAI5b,GAAO,CAAC,IAAIA,GAAO,CAAC,KAAK3E,CAAE,GAC7CwgB,KAAK,KAAK,IAAI,IAAI7b,GAAO,CAAC,IAAIA,GAAO,CAAC,KAAK1E,CAAE;AACnD,QAAAqR,GAAI,UAAUhQ,IAAQ+G,GAAIC,IAAIiY,IAAIC,EAAE,GACpClf,GAAO,MAAA;AAAA,MACR;AAEA,MAAAgc,EAAa,UAAUpD,IACvBI,EAAA;AAAA,IACD,CAAC,GAEM,MAAM;AACZ,MAAAuF,IAAY;AAAA,IACb;AAAA,EACD,GAAG;AAAA,IACFnhB;AAAA,IACA2e;AAAA,IACA1d;AAAA,IACAC;AAAA,IACAke;AAAA,IACAK;AAAA,IACAN;AAAA,IACAvD;AAAA,EAAA,CACA,GAEDoB,EAAU,MAAM;AACf,IAAApB,EAAA;AAAA,EACD,GAAG,CAACA,CAAW,CAAC,GAEhBoB,EAAU,MAAM;AACf,QAAKzF;AACL,aAAAA,EAAc,UAAUqE,GACjB,MAAM;AACZ,QAAIrE,EAAc,YAAYqE,MAC7BrE,EAAc,UAAU;AAAA,MAE1B;AAAA,EACD,GAAG,CAACA,GAAeqE,CAAW,CAAC,GAE/BoB;AAAA,IACC,MAAM,MAAM;AACX,MAAA8B,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAC9CC,EAAO,YAAY,SACtB,qBAAqBA,EAAO,OAAO,GACnCA,EAAO,UAAU,OAElBpH,EAAe,UAAU;AAAA,IAC1B;AAAA,IACA,CAAA;AAAA,EAAC,GAID,gBAAAwF;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,KAAK1F;AAAA,MACL,WAAAD;AAAA,MACA,OAAOsB;AAAA,MACP,eAAe6D;AAAA,MACf,eAAeC;AAAA,MACf,aAAaC;AAAA,MACb,iBAAiBA;AAAA,MACjB,eAAe,CAACb,MAAU;AACzB,QAAAA,EAAM,eAAA;AAAA,MACP;AAAA,MACA,SAAS,CAACA,MAAU;AACnB,QAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AAAA,MACP;AAAA,IAAA;AAAA,EAAA;AAGH;ACniBO,SAAS+F,GAAiB;AAAA,EAChC,YAAAhM;AAAA,EACA,aAAAC;AAAA,EACA,OAAA3T;AAAA,EACA,WAAAI;AAAA,EACA,WAAA+U;AAAA,EACA,OAAAtE;AACD,GAA8C;AAC7C,QAAMuE,IAAYC,EAAiC,IAAI,GACjDsK,IAActK,EAA8B,IAAI,GAChDoB,IAAcb;AAAA,IACnB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,SAAS,SAAS,GAAG/E;IAC7D,CAACA,CAAK;AAAA,EAAA;AAGP,SAAA8J,EAAU,MAAM;AACf,UAAMnc,IAAS4W,EAAU;AACzB,QAAI,CAAC5W;AACJ;AAGD,UAAMohB,IAAW,IAAIrgB,GAAe;AAAA,MACnC,QAAAf;AAAA,MACA,YAAAkV;AAAA,MACA,aAAAC;AAAA,MACA,kBAAkBvT;AAAA,IAAA,CAClB;AAED,WAAAuf,EAAY,UAAUC,GACjBA,EAAS,SAAS5f,CAAK,GAErB,MAAM;AACZ,MAAA4f,EAAS,QAAA,GACTD,EAAY,UAAU;AAAA,IACvB;AAAA,EACD,GAAG,CAACjM,GAAYC,CAAW,CAAC,GAE5BgH,EAAU,MAAM;AACf,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAIAA,EAAS,SAAS5f,CAAK;AAAA,EAC7B,GAAG,CAACA,CAAK,CAAC,GAEV2a,EAAU,MAAM;AACf,UAAMiF,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACxf,KAIlBwf,EAAS,aAAaxf,CAAS;AAAA,EAChC,GAAG,CAACA,CAAS,CAAC,sBAEN,UAAA,EAAO,KAAKgV,GAAW,WAAAD,GAAsB,OAAOsB,GAAa;AAC1E;AC3DA,SAASoJ,GAAmBC,GAAiC;AAC5D,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,IAAA;AAAA,EACrC;AAEF;AAEO,SAASC,GACfD,GACAjV,GACsB;AACtB,MAAI,CAACiV,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACxE,WAAO;AAGR,QAAMvV,IAAWF,GAAmBQ,KAAY,EAAE;AAClD,MAAIN,EAAS,WAAW;AACvB,WAAO;AAAA,MACN,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAInC,QAAMyV,IAAQH,GAAmBC,CAAS,GACpCG,IAAYH,EAAU,WACtB5T,IAAQ4T,EAAU,gBAClBI,IACLJ,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAUE,IAC7DF,EAAU,MACV,MAEEK,IAAgB,IAAI,aAAaH,IAAQ,CAAC,GAC1CI,IAAY,IAAI,YAAYJ,CAAK,GACjCK,IAAUH,IAAW,IAAI,YAAYF,CAAK,IAAI;AACpD,MAAI7H,IAAS;AAEb,WAASzT,IAAI,GAAGA,IAAIsb,GAAOtb,KAAK,GAAG;AAClC,UAAMpC,IAAI2d,EAAUvb,IAAI,CAAC,GACnBnC,IAAI0d,EAAUvb,IAAI,IAAI,CAAC;AAC7B,IAAKkG,GAA0BtI,GAAGC,GAAGgI,CAAQ,MAC7C4V,EAAchI,IAAS,CAAC,IAAI7V,GAC5B6d,EAAchI,IAAS,IAAI,CAAC,IAAI5V,GAChC6d,EAAUjI,CAAM,IAAIjM,EAAMxH,CAAC,GACvB2b,MACHA,EAAQlI,CAAM,IAAI+H,EAAUxb,CAAC,IAE9ByT,KAAU;AAAA,EACX;AAEA,QAAMmI,IAAuB;AAAA,IAC5B,OAAOnI;AAAA,IACP,WAAWgI,EAAc,SAAS,GAAGhI,IAAS,CAAC;AAAA,IAC/C,gBAAgBiI,EAAU,SAAS,GAAGjI,CAAM;AAAA,EAAA;AAE7C,SAAIkI,MACHC,EAAO,MAAMD,EAAQ,SAAS,GAAGlI,CAAM,IAEjCmI;AACR;AAEO,SAASC,GACfT,GACAjV,GACc;AACd,MAAI,CAACiV,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACxE,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMvV,IAAWF,GAAmBQ,KAAY,EAAE;AAClD,MAAIN,EAAS,WAAW;AACvB,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMyV,IAAQH,GAAmBC,CAAS;AAC1C,MAAIE,MAAU;AACb,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAYH,EAAU,WACtBzd,IAAM,IAAI,YAAY2d,CAAK;AACjC,MAAI7H,IAAS;AAEb,WAASzT,IAAI,GAAGA,IAAIsb,GAAOtb,KAAK,GAAG;AAClC,UAAMpC,IAAI2d,EAAUvb,IAAI,CAAC,GACnBnC,IAAI0d,EAAUvb,IAAI,IAAI,CAAC;AAC7B,IAAKkG,GAA0BtI,GAAGC,GAAGgI,CAAQ,MAC7ClI,EAAI8V,CAAM,IAAIzT,GACdyT,KAAU;AAAA,EACX;AAEA,SAAO9V,EAAI,SAAS,GAAG8V,CAAM;AAC9B;ACbA,IAAIqI,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,QAAMza,IAAYya;AAClB,SAAI,OAAOza,EAAU,kBAAmB,aAAmB,OACpDA;AACR;AAEA,MAAM0a,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,IAASV,GAAA;AACf,MAAI,CAACU;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,SAAIhB,OACJA,MAAkB,YAAY;AAC7B,UAAMc,IAASV,GAAA;AACf,QAAI,CAACU,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,MAAMhB,IAAuB;AAAA,QACjE,YAAY;AAAA,MAAA;AAAA,IACb,CACA;AAED,WAAO,EAAE,QAAAgB,GAAQ,UAAAE,GAAU,iBAAAD,EAAA;AAAA,EAC5B,GAAA,GAEOlB;AACR;AAEA,SAASoB,GAAM5f,GAAekC,GAAsB;AACnD,SAAO,KAAK,KAAKlC,IAAQkC,CAAI,IAAIA;AAClC;AAEA,eAAsB2d,GACrB5B,GACA6B,GACAle,GAC8B;AAC9B,QAAM2M,IAAM,MAAMiR,GAAA;AAClB,MAAI,CAACjR,EAAK,QAAO;AAEjB,QAAMyP,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAM8B,CAAU,CAAC,GAC1CC,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMne,EAAO,SAAS,CAAC,CAAC;AAC7D,MAAIoc,MAAU,KAAK+B,MAAgB;AAClC,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAiB,KAAK,IAAIhC,GAAO,KAAK,MAAMC,EAAU,SAAS,CAAC,CAAC;AACvE,MAAI+B,MAAmB;AACtB,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAgBD,IAAiB,IAAI,aAAa,mBAClDE,IAAcH,IAAc,IAAI,aAAa,mBAC7CI,IAAcH,IAAiB,YAAY,mBAE3CI,IAAQ,OAAO7R,EAAI,OAAO,OAAO,2BAA2B;AAClE,MAAI0R,IAAgBG,KAASF,IAAcE,KAASD,IAAcC;AACjE,WAAO;AAGR,QAAMC,IAAkB9R,EAAI,OAAO,aAAa;AAAA,IAC/C,MAAMqR,GAAMK,GAAe,CAAC;AAAA,IAC5B,OAAOlB,KAA2BC;AAAA,EAAA,CAClC,GACKsB,IAAe/R,EAAI,OAAO,aAAa;AAAA,IAC5C,MAAMqR,GAAMM,GAAa,CAAC;AAAA,IAC1B,OAAOnB,KAA2BC;AAAA,EAAA,CAClC,GACKuB,IAAehS,EAAI,OAAO,aAAa;AAAA,IAC5C,MAAMqR,GAAMO,GAAa,CAAC;AAAA,IAC1B,OAAOpB,KAA2BE;AAAA,EAAA,CAClC,GACKuB,IAAgBjS,EAAI,OAAO,aAAa;AAAA,IAC7C,MAAM;AAAA,IACN,OAAO2Q,KAA2BF;AAAA,EAAA,CAClC,GACKyB,IAAalS,EAAI,OAAO,aAAa;AAAA,IAC1C,MAAMqR,GAAMO,GAAa,CAAC;AAAA,IAC1B,OAAOnB,KAA4BG;AAAA,EAAA,CACnC;AAED,EAAA5Q,EAAI,OAAO,MAAM;AAAA,IAChB8R;AAAA,IACA;AAAA,IACApC,EAAU;AAAA,IACVA,EAAU;AAAA,IACVgC;AAAA,EAAA,GAED1R,EAAI,OAAO,MAAM;AAAA,IAChB+R;AAAA,IACA;AAAA,IACA1e,EAAO;AAAA,IACPA,EAAO;AAAA,IACPse;AAAA,EAAA,GAED3R,EAAI,OAAO,MAAM;AAAA,IAChBiS;AAAA,IACA;AAAA,IACA,IAAI,YAAY,CAACR,GAAgBD,GAAa,GAAG,CAAC,CAAC;AAAA,EAAA;AAGpD,QAAMW,IAAYnS,EAAI,OAAO,gBAAgB;AAAA,IAC5C,QAAQA,EAAI;AAAA,IACZ,SAAS;AAAA,MACR,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ8R,IAAgB;AAAA,MAClD,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAa;AAAA,MAC/C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAa;AAAA,MAC/C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAc;AAAA,IAAE;AAAA,EACnD,CACA,GAEKG,IAAiBpS,EAAI,OAAO,qBAAA,GAC5BhI,IAAOoa,EAAe,iBAAA;AAC5B,EAAApa,EAAK,YAAYgI,EAAI,QAAQ,GAC7BhI,EAAK,aAAa,GAAGma,CAAS,GAC9Bna,EAAK,mBAAmB,KAAK,KAAKyZ,IAAiB,GAAG,CAAC,GACvDzZ,EAAK,IAAA,GAELoa,EAAe,mBAAmBJ,GAAc,GAAGE,GAAY,GAAGN,CAAW,GAC7E5R,EAAI,OAAO,MAAM,OAAO,CAACoS,EAAe,OAAA,CAAQ,CAAC,GAEjD,MAAMF,EAAW,SAASrB,EAAiB;AAC3C,QAAMwB,IAASH,EAAW,eAAA,GACpBpgB,IAAM,IAAI,YAAYugB,EAAO,MAAM,CAAC,CAAC;AAC3C,SAAAH,EAAW,MAAA,GAEXJ,EAAgB,QAAA,GAChBC,EAAa,QAAA,GACbC,EAAa,QAAA,GACbC,EAAc,QAAA,GACdC,EAAW,QAAA,GAEJpgB;AACR;AClUA,SAASwgB,KAAgB;AACvB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC5D,YAAY,IAAA,IAEd,KAAK,IAAA;AACd;AAEA,eAAsBC,GACpBhD,GACAjV,GACArL,IAAkC,CAAA,GACF;AAChC,QAAMqI,IAAQgb,GAAA,GACRE,IAAevjB,EAAQ,iBAAiB;AAC9C,MAAI,CAACsgB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY+C,OAAUhb;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAM0C,IAAWF,GAAmBQ,KAAY,EAAE;AAClD,MAAIN,EAAS,WAAW;AACtB,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,IAAI,aAAa,CAAC;AAAA,QAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,MAAA;AAAA,MAEnC,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYsY,OAAUhb;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAMmb,IAAY,KAAK,IAAI,GAAG,KAAK,IAAIlD,EAAU,OAAO,KAAK,MAAMA,EAAU,UAAU,SAAS,CAAC,GAAGA,EAAU,eAAe,MAAM,CAAC,GAC9HI,IAAWJ,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAUkD,IAAYlD,EAAU,MAAM;AAC7G,MAAIkD,MAAc;AAChB,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,IAAI,aAAa,CAAC;AAAA,QAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,MAAA;AAAA,MAEnC,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYH,OAAUhb;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAMob,IAAW,IAAI,aAAa1Y,EAAS,SAAS,CAAC;AACrD,WAAS7F,IAAI,GAAGA,IAAI6F,EAAS,QAAQ7F,KAAK,GAAG;AAC3C,UAAMyM,IAAOzM,IAAI,GACX2E,IAAUkB,EAAS7F,CAAC;AAC1B,IAAAue,EAAS9R,CAAI,IAAI9H,EAAQ,MACzB4Z,EAAS9R,IAAO,CAAC,IAAI9H,EAAQ,MAC7B4Z,EAAS9R,IAAO,CAAC,IAAI9H,EAAQ,MAC7B4Z,EAAS9R,IAAO,CAAC,IAAI9H,EAAQ;AAAA,EAC/B;AAEA,MAAI6Z,IAAoC,MACpCC,IAAa;AACjB,MAAI;AACF,IAAAD,IAAgB,MAAMrB,GAA8B/B,EAAU,WAAWkD,GAAWC,CAAQ,GAC5FE,IAAa,CAAC,CAACD;AAAA,EACjB,QAAQ;AACN,IAAAA,IAAgB,MAChBC,IAAa;AAAA,EACf;AAEA,MAAI,CAACD;AAEH,WAAO;AAAA,MACL,MAFenD,GAA0BD,GAAWjV,CAAQ;AAAA,MAG5D,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYgY,OAAUhb;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgBmb;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,MAAII,IAAiB;AACrB,WAAS1e,IAAI,GAAGA,IAAIse,GAAWte,KAAK;AAClC,IAAIwe,EAAcxe,CAAC,MAAM,MAAG0e,KAAkB;AAGhD,QAAMC,IAAmB,IAAI,YAAYD,CAAc;AACvD,MAAIA,IAAiB,GAAG;AACtB,QAAIE,IAAkB;AACtB,aAAS5e,IAAI,GAAGA,IAAIse,GAAWte,KAAK;AAClC,MAAIwe,EAAcxe,CAAC,MAAM,MACzB2e,EAAiBC,CAAe,IAAI5e,GACpC4e,KAAmB;AAAA,EAEvB;AAEA,MAAIF,MAAmB,GAAG;AACxB,QAAIL,GAAc;AAChB,YAAMQ,IAAqB;AAAA,QACzB,OAAOP;AAAA,QACP,WAAWlD,EAAU,UAAU,SAAS,GAAGkD,IAAY,CAAC;AAAA,QACxD,gBAAgBlD,EAAU,eAAe,SAAS,GAAGkD,CAAS;AAAA,QAC9D,aAAa,IAAI,YAAY,CAAC;AAAA,MAAA;AAEhC,aAAI9C,MACFqD,EAAK,MAAMrD,EAAS,SAAS,GAAG8C,CAAS,IAEpC;AAAA,QACL,MAAAO;AAAA,QACA,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,YAAYV,OAAUhb;AAAA,UACtB,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,eAAe;AAAA,QAAA;AAAA,MACjB;AAAA,IAEJ;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,IAAI,aAAa,CAAC;AAAA,QAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,QACjC,GAAIqY,IAAW,EAAE,KAAK,IAAI,YAAY,CAAC,EAAA,IAAM,CAAA;AAAA,MAAC;AAAA,MAEhD,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY2C,OAAUhb;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,MAAIkb,GAAc;AAChB,UAAMS,IAAc,IAAI,YAAYJ,CAAc;AAClD,QAAIK,IAAe;AAEnB,aAAS/e,IAAI,GAAGA,IAAI0e,GAAgB1e,KAAK,GAAG;AAC1C,YAAMgf,KAAaL,EAAiB3e,CAAC,KAAK,GACpCpC,KAAIwd,EAAU,UAAU4D,KAAa,CAAC,GACtCnhB,KAAIud,EAAU,UAAU4D,KAAa,IAAI,CAAC;AAChD,MAAK9Y,GAA0BtI,IAAGC,IAAGgI,CAAQ,MAC7CiZ,EAAYC,CAAY,IAAIC,IAC5BD,KAAgB;AAAA,IAClB;AAEA,UAAMF,IAAqB;AAAA,MACzB,OAAOP;AAAA,MACP,WAAWlD,EAAU,UAAU,SAAS,GAAGkD,IAAY,CAAC;AAAA,MACxD,gBAAgBlD,EAAU,eAAe,SAAS,GAAGkD,CAAS;AAAA,MAC9D,aAAaQ,EAAY,SAAS,GAAGC,CAAY;AAAA,IAAA;AAEnD,WAAIvD,MACFqD,EAAK,MAAMrD,EAAS,SAAS,GAAG8C,CAAS,IAGpC;AAAA,MACL,MAAAO;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYV,OAAUhb;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAAub;AAAA,QACA,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,QAAMjD,IAAgB,IAAI,aAAaiD,IAAiB,CAAC,GACnDhD,IAAY,IAAI,YAAYgD,CAAc,GAC1C/C,IAAUH,IAAW,IAAI,YAAYkD,CAAc,IAAI;AAC7D,MAAIjL,IAAS;AAEb,WAASzT,IAAI,GAAGA,IAAI0e,GAAgB1e,KAAK,GAAG;AAC1C,UAAMgf,IAAaL,EAAiB3e,CAAC,KAAK,GACpCpC,IAAIwd,EAAU,UAAU4D,IAAa,CAAC,GACtCnhB,IAAIud,EAAU,UAAU4D,IAAa,IAAI,CAAC;AAChD,IAAK9Y,GAA0BtI,GAAGC,GAAGgI,CAAQ,MAC7C4V,EAAchI,IAAS,CAAC,IAAI7V,GAC5B6d,EAAchI,IAAS,IAAI,CAAC,IAAI5V,GAChC6d,EAAUjI,CAAM,IAAI2H,EAAU,eAAe4D,CAAU,GACnDrD,MACFA,EAAQlI,CAAM,IAAI+H,EAAUwD,CAAU,IAExCvL,KAAU;AAAA,EACZ;AAEA,QAAMwL,IAA4B;AAAA,IAChC,OAAOxL;AAAA,IACP,WAAWgI,EAAc,SAAS,GAAGhI,IAAS,CAAC;AAAA,IAC/C,gBAAgBiI,EAAU,SAAS,GAAGjI,CAAM;AAAA,EAAA;AAE9C,SAAIkI,MACFsD,EAAY,MAAMtD,EAAQ,SAAS,GAAGlI,CAAM,IAGvC;AAAA,IACL,MAAMwL;AAAA,IACN,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,YAAYd,OAAUhb;AAAA,MACtB,YAAY;AAAA,MACZ,gBAAAub;AAAA,MACA,eAAe;AAAA,IAAA;AAAA,EACjB;AAEJ;ACpNA,IAAIQ,KAAgC,MAChCC,KAAkB,IAClBC,KAAY;AAChB,MAAMC,yBAAkB,IAAA;AAExB,SAASlB,KAAgB;AACvB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC5D,YAAY,IAAA,IAEd,KAAK,IAAA;AACd;AAEA,SAASmB,KAA8B;AACrC,MAAI,CAACH,GAAiB,QAAO;AAC7B,MAAID,GAAgB,QAAOA;AAC3B,MAAI;AACF,UAAMK,IAAS,IAAI,OAAO,IAAA;AAAA;AAAA,MAAA,KAAA,IAAA,IAAA,sCAAA,YAAA,GAAA,EAAA;AAAA,MAAA,YAAA;AAAA,IAAA,GAA2D,EAAE,MAAM,SAAA,CAAU;AACvG,WAAAA,EAAO,iBAAiB,WAAWC,EAAmB,GACtDD,EAAO,iBAAiB,SAASE,EAAiB,GAClDP,KAAiBK,GACVA;AAAA,EACT,QAAQ;AACN,WAAAJ,KAAkB,IACX;AAAA,EACT;AACF;AAEA,SAASK,GAAoBvK,GAAkD;AAC7E,QAAMyK,IAAMzK,EAAM;AAClB,MAAI,CAACyK,EAAK;AACV,QAAMC,IAAUN,GAAY,IAAIK,EAAI,EAAE;AACtC,MAAI,CAACC,EAAS;AAGd,MAFAN,GAAY,OAAOK,EAAI,EAAE,GAErBA,EAAI,SAAS,oBAAoB;AACnC,IAAAC,EAAQ,OAAO,IAAI,MAAMD,EAAI,SAAS,oBAAoB,CAAC;AAC3D;AAAA,EACF;AAEA,MAAIA,EAAI,SAAS,0BAA0B;AACzC,QAAIC,EAAQ,SAAS,SAAS;AAC5B,MAAAA,EAAQ,OAAO,IAAI,MAAM,sDAAsD,CAAC;AAChF;AAAA,IACF;AACA,UAAMrE,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMoE,EAAI,KAAK,CAAC,GACzCE,IAAU,IAAI,YAAYF,EAAI,OAAO,EAAE,SAAS,GAAGpE,CAAK;AAC9D,IAAAqE,EAAQ,QAAQ;AAAA,MACd,SAAAC;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,OAAO,SAASF,EAAI,UAAU,IAAIA,EAAI,aAAavB,GAAA,IAAUwB,EAAQ;AAAA,MAAA;AAAA,IACnF,CACD;AACD;AAAA,EACF;AAEA,MAAIA,EAAQ,SAAS,QAAQ;AAC3B,IAAAA,EAAQ,OAAO,IAAI,MAAM,iDAAiD,CAAC;AAC3E;AAAA,EACF;AAEA,QAAMrE,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMoE,EAAI,KAAK,CAAC,GACzCnE,IAAY,IAAI,aAAamE,EAAI,SAAS,GAC1CG,IAAiB,IAAI,YAAYH,EAAI,cAAc,GACnDI,IAAMJ,EAAI,MAAM,IAAI,YAAYA,EAAI,GAAG,IAAI,MAC3C9D,IAAuB;AAAA,IAC3B,OAAAN;AAAA,IACA,WAAWC,EAAU,SAAS,GAAGD,IAAQ,CAAC;AAAA,IAC1C,gBAAgBuE,EAAe,SAAS,GAAGvE,CAAK;AAAA,EAAA;AAElD,EAAIwE,MACFlE,EAAO,MAAMkE,EAAI,SAAS,GAAGxE,CAAK,IAGpCqE,EAAQ,QAAQ;AAAA,IACd,MAAM/D;AAAA,IACN,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,YAAY,OAAO,SAAS8D,EAAI,UAAU,IAAIA,EAAI,aAAavB,GAAA,IAAUwB,EAAQ;AAAA,IAAA;AAAA,EACnF,CACD;AACH;AAEA,SAASF,KAA0B;AACjC,EAAAN,KAAkB,IACdD,OACFA,GAAe,oBAAoB,WAAWM,EAAmB,GACjEN,GAAe,oBAAoB,SAASO,EAAiB,GAC7DP,GAAe,UAAA,GACfA,KAAiB;AAEnB,aAAW,CAAA,EAAGS,CAAO,KAAKN;AACxB,IAAAM,EAAQ,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAE5C,EAAAN,GAAY,MAAA;AACd;AAEO,SAASU,KAA+B;AAC7C,MAAKb,IACL;AAAA,IAAAA,GAAe,oBAAoB,WAAWM,EAAmB,GACjEN,GAAe,oBAAoB,SAASO,EAAiB,GAC7DP,GAAe,UAAA,GACfA,KAAiB;AACjB,eAAW,CAAA,EAAGS,CAAO,KAAKN;AACxB,MAAAM,EAAQ,OAAO,IAAI,MAAM,mBAAmB,CAAC;AAE/C,IAAAN,GAAY,MAAA;AAAA;AACd;AAEA,eAAsBW,GAAkC5E,GAA4CjV,GAAqE;AACvK,MAAI,CAACiV,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,QAAMmE,IAASD,GAAA;AACf,MAAI,CAACC,GAAQ;AACX,UAAMpc,IAAQgb,GAAA;AACd,WAAO;AAAA,MACL,MAAM9C,GAA0BD,GAAWjV,CAAQ;AAAA,MACnD,MAAM,EAAE,MAAM,QAAQ,YAAYgY,GAAA,IAAUhb,EAAA;AAAA,IAAM;AAAA,EAEtD;AAEA,QAAMmb,IAAY,KAAK,IAAI,GAAG,KAAK,IAAIlD,EAAU,OAAO,KAAK,MAAMA,EAAU,UAAU,SAAS,CAAC,GAAGA,EAAU,eAAe,MAAM,CAAC,GAC9H6E,IAAgB7E,EAAU,UAAU,MAAM,GAAGkD,IAAY,CAAC,GAC1D4B,IAAY9E,EAAU,eAAe,MAAM,GAAGkD,CAAS,GACvD6B,IAAU/E,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAUkD,IAAYlD,EAAU,IAAI,MAAM,GAAGkD,CAAS,IAAI,MAC1Hxc,IAAKsd,MACLgB,IAAUjC,GAAA;AAEhB,SAAO,IAAI,QAAyB,CAACkC,GAASC,MAAW;AACvD,IAAAjB,GAAY,IAAIvd,GAAI,EAAE,MAAM,QAAQ,SAAAue,GAAS,QAAAC,GAAQ,SAAAF,GAAS;AAC9D,UAAMV,IAA4B;AAAA,MAChC,MAAM;AAAA,MACN,IAAA5d;AAAA,MACA,OAAOwc;AAAA,MACP,WAAW2B,EAAc;AAAA,MACzB,gBAAgBC,EAAU;AAAA,MAC1B,KAAKC,GAAS;AAAA,MACd,UAAUha,KAAY,CAAA;AAAA,IAAC,GAEnBoa,IAA2B,CAACN,EAAc,QAAQC,EAAU,MAAM;AACxE,IAAIC,KACFI,EAAS,KAAKJ,EAAQ,MAAM,GAE9BZ,EAAO,YAAYG,GAAKa,CAAQ;AAAA,EAClC,CAAC;AACH;AAEA,eAAsBC,GAAqCpF,GAA4CjV,GAA0E;AAC/K,MAAI,CAACiV,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,QAAMmE,IAASD,GAAA;AACf,MAAI,CAACC,GAAQ;AACX,UAAMpc,IAAQgb,GAAA;AACd,WAAO;AAAA,MACL,SAAStC,GAA6BT,GAAWjV,CAAQ;AAAA,MACzD,MAAM,EAAE,MAAM,QAAQ,YAAYgY,GAAA,IAAUhb,EAAA;AAAA,IAAM;AAAA,EAEtD;AAEA,QAAMmb,IAAY,KAAK,IAAI,GAAG,KAAK,IAAIlD,EAAU,OAAO,KAAK,MAAMA,EAAU,UAAU,SAAS,CAAC,GAAGA,EAAU,eAAe,MAAM,CAAC,GAC9H6E,IAAgB7E,EAAU,UAAU,MAAM,GAAGkD,IAAY,CAAC,GAC1Dxc,IAAKsd,MACLgB,IAAUjC,GAAA;AAEhB,SAAO,IAAI,QAA8B,CAACkC,GAASC,MAAW;AAC5D,IAAAjB,GAAY,IAAIvd,GAAI,EAAE,MAAM,SAAS,SAAAue,GAAS,QAAAC,GAAQ,SAAAF,GAAS;AAC/D,UAAMV,IAA4B;AAAA,MAChC,MAAM;AAAA,MACN,IAAA5d;AAAA,MACA,OAAOwc;AAAA,MACP,WAAW2B,EAAc;AAAA,MACzB,UAAU9Z,KAAY,CAAA;AAAA,IAAC;AAEzB,IAAAoZ,EAAO,YAAYG,GAAK,CAACO,EAAc,MAAM,CAAC;AAAA,EAChD,CAAC;AACH;ACtLA,SAASQ,GAAeC,GAAiD;AACxE,QAAM7a,IAA6B,CAAA;AACnC,WAAS7F,IAAI,GAAGA,IAAI0gB,EAAQ,QAAQ1gB,KAAK,GAAG;AAC3C,UAAMsR,IAASoP,EAAQ1gB,CAAC,GAClBmG,IAAWR,GAAmB,CAAC2L,GAAQ,WAA6C,CAAC;AAC3F,QAAInL,EAAS,WAAW,EAAG;AAE3B,QAAI/B,IAAO;AACX,eAAWO,KAAWwB;AACrB,MAAA/B,KAAQO,EAAQ;AAGjB,IAAAkB,EAAS,KAAK;AAAA,MACb,UAAUyL,EAAO,MAAMtR;AAAA,MACvB,aAAaA;AAAA,MACb,UAAAmG;AAAA,MACA,MAAM,KAAK,IAAI,MAAM/B,CAAI;AAAA,IAAA,CACzB;AAAA,EACF;AACA,SAAOyB;AACR;AAEA,SAAS8a,GACRC,GACAC,GACS;AACT,MAAI,MAAM,QAAQA,CAAoB,GAAG;AACxC,UAAMC,IAAYD,EAAqBD,CAAY;AACnD,QAAI,OAAOE,KAAc,YAAYA,EAAU,SAAS,EAAG,QAAOA;AAAA,EACnE;AACA,MAAID,aAAgC,KAAK;AACxC,UAAME,IAAUF,EAAqB,IAAID,CAAY;AACrD,QAAI,OAAOG,KAAY,YAAYA,EAAQ,SAAS,EAAG,QAAOA;AAAA,EAC/D;AACA,SAAO,OAAOH,CAAY;AAC3B;AAEO,SAASI,GACf5F,GACAsF,GACA5lB,IAAgC,CAAA,GACX;AACrB,QAAMmmB,IAAY,KAAK;AAAA,IACtB;AAAA,IACA,KAAK;AAAA,MACJ,KAAK,MAAM7F,GAAW,SAAS,CAAC;AAAA,MAChC,KAAK,OAAOA,GAAW,WAAW,UAAU,KAAK,CAAC;AAAA,MAClDA,GAAW,gBAAgB,UAAU;AAAA,IAAA;AAAA,EACtC;AAGD,MAAI0D,IAAkC;AACtC,MAAI1D,GAAW,uBAAuB,aAAa;AAClD,UAAMniB,IAASmiB,EAAU;AACzB,QAAI8F,IAAQjoB,EAAO;AACnB,aAAS+G,IAAI,GAAGA,IAAI/G,EAAO,QAAQ+G,KAAK;AAEvC,MADY/G,EAAO+G,CAAC,IACVihB,MACVC,KAAS;AAEV,QAAIA,MAAUjoB,EAAO;AACpB,MAAA6lB,IAAc7lB;AAAA,aACJioB,IAAQ,GAAG;AACrB,YAAMC,IAAW,IAAI,YAAYD,CAAK;AACtC,UAAIzN,IAAS;AACb,eAASzT,IAAI,GAAGA,IAAI/G,EAAO,QAAQ+G,KAAK,GAAG;AAC1C,cAAMohB,IAAMnoB,EAAO+G,CAAC;AACpB,QAAIohB,KAAOH,MACXE,EAAS1N,CAAM,IAAI2N,GACnB3N,KAAU;AAAA,MACX;AACA,MAAAqL,IAAcqC;AAAA,IACf;AACC,MAAArC,IAAc,IAAI,YAAY,CAAC;AAAA,EAEjC;AAEA,QAAMuC,IAAavC,IAAcA,EAAY,SAASmC,GAEhDK,IAAkBb,GAAeC,KAAW,EAAE;AACpD,MAAI,CAACtF,KAAaiG,MAAe,KAAKC,EAAgB,WAAW;AAChE,WAAO;AAAA,MACN,QAAQ,CAAA;AAAA,MACR,iBAAiBD;AAAA,MACjB,uBAAuB;AAAA,MACvB,qBAAqBA;AAAA,IAAA;AAIvB,QAAME,wBAAyB,IAAA,GACzBC,wBAA0B,IAAA;AAChC,MAAIC,IAAc;AAElB,WAASzhB,IAAI,GAAGA,IAAIqhB,GAAYrhB,KAAK,GAAG;AACvC,UAAMgf,IAAaF,IAAcA,EAAY9e,CAAC,IAAIA,GAC5CpC,IAAIwd,EAAU,UAAU4D,IAAa,CAAC,GACtCnhB,IAAIud,EAAU,UAAU4D,IAAa,IAAI,CAAC;AAChD,QAAI0C,IAAoC;AAExC,eAAWpQ,KAAUgQ,GAAiB;AACrC,UAAIjc,IAAS;AACb,iBAAWV,KAAW2M,EAAO;AAC5B,YAAKtL,GAAuBpI,GAAGC,GAAG8G,CAAO,GACzC;AAAA,UAAAU,IAAS;AACT;AAAA;AAED,MAAKA,MACD,CAACqc,KAAcpQ,EAAO,OAAOoQ,EAAW,UAC3CA,IAAapQ;AAAA,IAEf;AAEA,QAAI,CAACoQ,EAAY;AACjB,IAAAD,KAAe;AAEf,UAAMb,IAAexF,EAAU,eAAe4D,CAAU,KAAK,GACvD2C,IACLJ,EAAmB,IAAIG,EAAW,WAAW,yBAAS,IAAA;AACvD,IAAAC,EAAc,IAAIf,IAAee,EAAc,IAAIf,CAAY,KAAK,KAAK,CAAC,GAC1EW,EAAmB,IAAIG,EAAW,aAAaC,CAAa,GAC5DH,EAAoB;AAAA,MACnBE,EAAW;AAAA,OACVF,EAAoB,IAAIE,EAAW,WAAW,KAAK,KAAK;AAAA,IAAA;AAAA,EAE3D;AAEA,QAAME,IAAsB9mB,EAAQ,uBAAuB,IACrD+mB,IAA0B,CAAA;AAChC,aAAWvQ,KAAUgQ,GAAiB;AACrC,UAAMQ,IAAaN,EAAoB,IAAIlQ,EAAO,WAAW,KAAK;AAClE,QAAI,CAACsQ,KAAuBE,KAAc,EAAG;AAC7C,UAAMC,IAAUR,EAAmB,IAAIjQ,EAAO,WAAW,yBAAS,IAAA,GAC5D0Q,IAA6B,MAAM,KAAKD,EAAQ,SAAS,EAC7D,IAAI,CAAC,CAACnB,GAActF,CAAK,OAAO;AAAA,MAChC,QAAQqF,GAAcC,GAAc9lB,EAAQ,oBAAoB;AAAA,MAChE,cAAA8lB;AAAA,MACA,OAAAtF;AAAA,IAAA,EACC,EACD,KAAK,CAACrZ,GAAGC,MAAMA,EAAE,QAAQD,EAAE,SAASA,EAAE,eAAeC,EAAE,YAAY;AAErE,IAAA2f,EAAO,KAAK;AAAA,MACX,UAAUvQ,EAAO;AAAA,MACjB,aAAaA,EAAO;AAAA,MACpB,YAAAwQ;AAAA,MACA,YAAAE;AAAA,IAAA,CACA;AAAA,EACF;AAEA,SAAO;AAAA,IACN,QAAAH;AAAA,IACA,iBAAiBR;AAAA,IACjB,uBAAuBI;AAAA,IACvB,qBAAqB,KAAK,IAAI,GAAGJ,IAAaI,CAAW;AAAA,EAAA;AAE3D;ACnJA,SAAStD,KAAgB;AACxB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC7D,YAAY,IAAA,IAEb,KAAK,IAAA;AACb;AAEA,SAAS8D,GAAuBC,GAAatK,GAA4B;AACxE,MAAI,CAACA,EAAW,QAAO;AACvB,MAAI;AAEH,UAAMuK,IADS,IAAI,IAAID,GAAK,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,MAAS,EACxE,SAAS,YAAA;AAG7B,QADCC,EAAK,SAAS,eAAe,KAAKA,EAAK,WAAW,KAAK,KAAKA,EAAK,SAAS,MAAM,EACpE,QAAO;AAAA,EACrB,QAAQ;AAAA,EAER;AACA,SAAO;AACR;AAEO,MAAMC,GAAc;AAAA,EAwB1B,YAAYtnB,GAA+B;AAvB1B,IAAAb,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,MAAMa,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,aAAaoM,GAAqB;AACjC,SAAK,YAAY,OAAOA,KAAS,EAAE;AAAA,EACpC;AAAA,EAEA,SAAS5L,GAAuC;AAC/C,QAAI,KAAK,UAAW;AAEpB,UAAM+mB,wBAAsB,IAAA;AAC5B,eAAW5mB,KAAQH;AAClB,MAAA+mB,EAAgB,IAAI5mB,EAAK,GAAG;AAE7B,SAAK,cAAc4mB,GAEnB,KAAK,oBAAoBA,CAAe,GACxC,KAAK,uBAAuBA,CAAe;AAE3C,eAAW5mB,KAAQH,GAAO;AACzB,UAAI,KAAK,SAAS,IAAIG,EAAK,GAAG,GAAG;AAChC,cAAM6mB,IAAW,KAAK,SAAS,IAAI7mB,EAAK,GAAG;AAC3C,QAAI6mB,QAAmB,OAAO7mB;AAC9B;AAAA,MACD;AAEA,YAAM8mB,IAAS,KAAK,YAAY,IAAI9mB,EAAK,GAAG;AAC5C,UAAI8mB,GAAQ;AACX,QAAAA,EAAO,OAAO9mB;AACd;AAAA,MACD;AAEA,YAAM+O,IAAkB;AAAA,QACvB,MAAA/O;AAAA,QACA,SAAS;AAAA,QACT,SAAS0iB,GAAA;AAAA,MAAM;AAEhB,WAAK,MAAM,KAAK3T,CAAI,GACpB,KAAK,YAAY,IAAI/O,EAAK,KAAK+O,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,oBAAoBgY,GAAgC;AAC3D,QAAI,KAAK,MAAM,WAAW,EAAG;AAC7B,UAAMC,IAAyB,CAAA;AAC/B,eAAWjY,KAAQ,KAAK,OAAO;AAC9B,UAAI,CAACgY,EAAY,IAAIhY,EAAK,KAAK,GAAG,GAAG;AACpC,aAAK,YAAY,OAAOA,EAAK,KAAK,GAAG;AACrC;AAAA,MACD;AACA,MAAAiY,EAAU,KAAKjY,CAAI;AAAA,IACpB;AACA,SAAK,QAAQiY;AAAA,EACd;AAAA,EAEQ,uBAAuBD,GAAgC;AAC9D,eAAW,CAACE,GAAKlY,CAAI,KAAK,KAAK;AAC9B,MAAIgY,EAAY,IAAIE,CAAG,MACvB,KAAK,SAAS,OAAOA,CAAG,GACxB,KAAK,gBAAgB,GACrBlY,EAAK,WAAW,MAAA;AAAA,EAElB;AAAA,EAEQ,YAAkB;AACzB,SAAK,MAAM,KAAK,CAACvI,GAAGC,MACfD,EAAE,YAAYC,EAAE,UAAgBD,EAAE,UAAUC,EAAE,UAC9CD,EAAE,KAAK,cAAcC,EAAE,KAAK,YACxBD,EAAE,KAAK,YAAYC,EAAE,KAAK,YAE9BD,EAAE,KAAK,SAASC,EAAE,KAAK,OAAaA,EAAE,KAAK,OAAOD,EAAE,KAAK,OACtDA,EAAE,KAAK,IAAI,cAAcC,EAAE,KAAK,GAAG,CAC1C;AAAA,EACF;AAAA,EAEQ,OAAa;AACpB,QAAI,KAAK,UAAW;AAGpB,SAFA,KAAK,eAAA,GAEE,KAAK,SAAS,OAAO,KAAK,kBAAgB;AAChD,YAAM9H,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,UAAMuoB,IAAkB,KAAK,MAAM,CAAC,GAAG;AACvC,QAAI,OAAOA,KAAoB,SAAU;AACzC,UAAMC,IAAQ,KAAK,IAAI,GAAGD,IAAkBxE,IAAO;AACnD,SAAK,UAAU,OAAO,WAAW,MAAM;AACtC,WAAK,UAAU,MACf,KAAK,KAAA;AAAA,IACN,GAAGyE,CAAK;AAAA,EACT;AAAA,EAEQ,yBAA2C;AAClD,QAAI,KAAK,MAAM,WAAW,EAAG,QAAO;AACpC,UAAMC,IAAM1E,GAAA,GACNrgB,IAAQ,KAAK,MAAM,CAAC;AAC1B,WAAI,CAACA,KAASA,EAAM,UAAU+kB,IAAY,QAE1C,KAAK,MAAM,MAAA,GACX,KAAK,YAAY,OAAO/kB,EAAM,KAAK,GAAG,GAC/BA;AAAA,EACR;AAAA,EAEQ,WAAW0M,GAAuB;AACzC,UAAMsY,IAAa,IAAI,gBAAA,GACjBC,IAA8B;AAAA,MACnC,MAAMvY,EAAK;AAAA,MACX,SAASA,EAAK;AAAA,MACd,YAAAsY;AAAA,IAAA;AAED,SAAK,SAAS,IAAItY,EAAK,KAAK,KAAKuY,CAAa,GAC9C,KAAK,gBAAA;AAEL,UAAMnI,IAAgBqH,GAAuBzX,EAAK,KAAK,KAAK,KAAK,SAAS;AAC1E,UAAMA,EAAK,KAAK,KAAK;AAAA,MACpB,QAAQsY,EAAW;AAAA,MACnB,SAASlI,IAAgB,EAAE,eAAe,KAAK,cAAc;AAAA,IAAA,CAC7D,EACC,KAAK,CAACjf,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,aAAainB,EAAW,OAAO,SAAS;AAChD,QAAAjnB,EAAO,MAAA;AACP;AAAA,MACD;AACA,UAAI,CAAC,KAAK,YAAY,IAAI2O,EAAK,KAAK,GAAG,GAAG;AACzC,QAAA3O,EAAO,MAAA;AACP;AAAA,MACD;AACA,WAAK,WAAW2O,EAAK,MAAM3O,CAAM;AAAA,IAClC,CAAC,EACA,MAAM,CAACE,MAAmB;AAC1B,UAAI+mB,EAAW,OAAO,WAAW,KAAK;AACrC;AAKD,UADCtY,EAAK,UAAU,KAAK,cAAc,KAAK,YAAY,IAAIA,EAAK,KAAK,GAAG,GACpD;AAChB,aAAK,cAAc;AACnB,cAAMwY,IAAcxY,EAAK,UAAU,GAC7ByY,IAAa,KAAK,cAAcD,CAAW,GAC3CT,IAAoB;AAAA,UACzB,MAAM/X,EAAK;AAAA,UACX,SAASwY;AAAA,UACT,SAAS7E,OAAU8E;AAAA,QAAA,GAEdC,IAAW,KAAK,YAAY,IAAI1Y,EAAK,KAAK,GAAG;AACnD,QAAI0Y,KACHA,EAAS,OAAOX,EAAO,MACvBW,EAAS,UAAU,KAAK,IAAIA,EAAS,SAASX,EAAO,OAAO,GAC5DW,EAAS,UAAU,KAAK,IAAIA,EAAS,SAASX,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/X,EAAK,MAAMzO,GAAOyO,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,cAAc2Y,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,OAAO,aAAa,KAAK,OAAO,GAChC,KAAK,UAAU;AAAA,EAChB;AAAA,EAEQ,kBAAwB;AAC/B,SAAK,gBAAgB,KAAK,aAAa;AAAA,EACxC;AACD;ACpSA,MAAMC,KAAoC,MACpCC,KAAoB,KACpBC,KAAoB,KAOpBC,KAAqD;AAAA,EAC1D,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;AACnB;AAgCA,MAAM1oB,GAAY;AAAA,EAAlB;AACS,IAAAd,EAAA,uBAAgB;AAChB,IAAAA,EAAA,wBAAiB;AACjB,IAAAA,EAAA,mBAA0B;AAAA,MACjC,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,aAAa;AAAA,IAAA;AAAA;AAAA,EAGd,YAAYC,GAAeC,GAAsB;AAChD,SAAK,gBAAgB,KAAK,IAAI,GAAGD,CAAK,GACtC,KAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EACzC;AAAA,EAEA,cAA6B;AAC5B,WAAO,EAAE,OAAO,KAAK,eAAe,QAAQ,KAAK,eAAA;AAAA,EAClD;AAAA,EAEA,aAAaC,GAAmC;AAC/C,IAAI,OAAOA,EAAK,QAAS,aACxB,KAAK,UAAU,OAAO,KAAK,IAAI,MAAQA,EAAK,IAAI,IAE7C,OAAOA,EAAK,WAAY,aAC3B,KAAK,UAAU,UAAUA,EAAK,UAE3B,OAAOA,EAAK,WAAY,aAC3B,KAAK,UAAU,UAAUA,EAAK,UAE3B,OAAOA,EAAK,eAAgB,YAAY,OAAO,SAASA,EAAK,WAAW,MAC3E,KAAK,UAAU,cAAcA,EAAK;AAAA,EAEpC;AAAA,EAEA,eAA6B;AAC5B,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EAClB;AAAA,EAEA,YAAwB;AACvB,UAAMmC,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI;AAC/C,WAAO;AAAA,MACN,KAAK,UAAU,UAAU,KAAK,iBAAiB,IAAIA;AAAA,MACnD,KAAK,UAAU,UAAU,KAAK,kBAAkB,IAAIA;AAAA,IAAA;AAAA,EAEtD;AAAA,EAEA,UAAUgP,GAAiBC,GAAuB;AACjD,UAAMjP,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI;AAC/C,SAAK,UAAU,UAAUgP,IAAU,KAAK,iBAAiB,IAAIhP,IAC7D,KAAK,UAAU,UAAUiP,IAAU,KAAK,kBAAkB,IAAIjP;AAAA,EAC/D;AAAA,EAEA,cAAc8Z,GAAiBC,GAA6B;AAC3D,UAAMxC,IAAQ,KAAK,WACbvX,IAAO,KAAK,IAAI,MAAMuX,EAAM,IAAI,GAChC,CAACvI,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1B5I,KAAMyT,IAAU,KAAK,gBAAgB,OAAO9Z,GAC5CsG,KAAMyT,IAAU,KAAK,iBAAiB,OAAO/Z,GAC7CmnB,IAAMC,GAAU7P,EAAM,WAAW,GACjC8P,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG;AACxB,WAAO,CAACnY,IAAU3I,IAAKghB,IAAM/gB,IAAKghB,GAAKrY,IAAU5I,IAAKihB,IAAMhhB,IAAK+gB,CAAG;AAAA,EACrE;AAAA,EAEA,cAAc7J,GAAgBC,GAA4B;AACzD,UAAMlG,IAAQ,KAAK,WACbvX,IAAO,KAAK,IAAI,MAAMuX,EAAM,IAAI,GAChC,CAACvI,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1B5I,IAAKmX,IAASxO,GACd1I,IAAKmX,IAASxO,GACdkY,IAAMC,GAAU7P,EAAM,WAAW,GACjC8P,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAClBI,IAAKlhB,IAAKghB,IAAM/gB,IAAKghB,GACrBE,IAAK,CAACnhB,IAAKihB,IAAMhhB,IAAK+gB;AAC5B,WAAO;AAAA,MACN,KAAK,gBAAgB,MAAME,IAAKvnB;AAAA,MAChC,KAAK,iBAAiB,MAAMwnB,IAAKxnB;AAAA,IAAA;AAAA,EAEnC;AAAA,EAEA,iBAAmE;AAClE,UAAM2V,IAAI,KAAK,eACTC,IAAI,KAAK;AACf,WAAO;AAAA,MACN,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,EAEzB;AAAA,EAEA,YAA0B;AACzB,UAAM5V,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,GACzC,CAACgP,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1BkY,IAAMC,GAAU,KAAK,UAAU,WAAW,GAC1CC,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAElBM,IAAM,IAAIznB,IAAOqnB,IAAO,KAAK,eAC7BK,IAAM,IAAI1nB,IAAOsnB,IAAO,KAAK,eAC7BK,IAAM,IAAI3nB,IAAOsnB,IAAO,KAAK,gBAC7BM,IAAM,KAAK5nB,IAAOqnB,IAAO,KAAK,gBAC9BnpB,IAAK,EAAEupB,IAAKzY,IAAU0Y,IAAKzY,IAC3B9Q,IAAK,EAAEwpB,IAAK3Y,IAAU4Y,IAAK3Y;AAEjC,WAAO,IAAI,aAAa,CAACwY,GAAIE,GAAI,GAAGD,GAAIE,GAAI,GAAG1pB,GAAIC,GAAI,CAAC,CAAC;AAAA,EAC1D;AACD;AAEA,SAASipB,GAAUS,GAAqB;AACvC,SAAQA,IAAM,KAAK,KAAM;AAC1B;AAEA,SAASjG,KAAgB;AACxB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC7D,YAAY,IAAA,IAEb,KAAK,IAAA;AACb;AAEA,SAASzkB,GACRX,GACAU,GACA4qB,GACuB;AACvB,QAAMzqB,IAAWb,EAAG,mBAAmBU,GAAS4qB,CAAI;AACpD,MAAI,CAACzqB;AACJ,UAAM,IAAI,MAAM,mCAAmCyqB,CAAI,EAAE;AAE1D,SAAOzqB;AACR;AAEA,SAAS0qB,GACRriB,GACAC,GACU;AACV,SAAI,CAACD,KAAK,CAACC,IAAUD,MAAMC,IAE1BD,EAAE,WAAWC,EAAE,UACfD,EAAE,eAAeC,EAAE,cACnBD,EAAE,eAAeC,EAAE;AAErB;AAEA,SAASqiB,GAAoBC,GAAkD;AAC9E,SAAOA,EAAM,IAAI,CAAAC,OAAS,EAAE,MAAMA,EAAK,MAAM,MAAMA,EAAK,KAAA,EAAO;AAChE;AAEA,SAASC,GAAwBC,GAAsE;AACtG,MAAI,CAACA,EAAiB,QAAOJ,GAAoBd,EAAwB;AAEzE,QAAM9M,wBAAa,IAAA;AACnB,aAAW,CAACiO,GAASC,CAAO,KAAK,OAAO,QAAQF,CAAe,GAAG;AACjE,UAAMpoB,IAAO,OAAOqoB,CAAO,GACrBE,IAAO,OAAOD,CAAO;AAC3B,IAAI,CAAC,OAAO,SAAStoB,CAAI,KAAK,CAAC,OAAO,SAASuoB,CAAI,KAAKA,KAAQ,KAChEnO,EAAO,IAAIpa,GAAMuoB,CAAI;AAAA,EACtB;AAEA,SAAInO,EAAO,SAAS,IACZ4N,GAAoBd,EAAwB,IAG7C,MAAM,KAAK9M,EAAO,QAAA,CAAS,EAChC,KAAK,CAAC1U,GAAGC,MAAMD,EAAE,CAAC,IAAIC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAAC3F,GAAMuoB,CAAI,OAAO,EAAE,MAAAvoB,GAAM,MAAAuoB,EAAA,EAAO;AACzC;AAEA,SAASC,GAAuB9iB,GAA6BC,GAAsC;AAClG,MAAID,MAAMC,EAAG,QAAO;AACpB,MAAID,EAAE,WAAWC,EAAE,OAAQ,QAAO;AAClC,WAASlC,IAAI,GAAGA,IAAIiC,EAAE,QAAQjC,KAAK;AAClC,QAAIiC,EAAEjC,CAAC,EAAE,SAASkC,EAAElC,CAAC,EAAE,QAAQiC,EAAEjC,CAAC,EAAE,SAASkC,EAAElC,CAAC,EAAE;AACjD,aAAO;AAGT,SAAO;AACR;AAEA,SAASglB,GAA4BlS,GAAwB0R,GAAyC;AACrG,MAAI,CAAC,OAAO,SAAS1R,CAAc,EAAG,QAAO0R,EAAM,CAAC,GAAG,QAAQjB;AAC/D,MAAIiB,EAAM,WAAW,EAAG,QAAOjB;AAE/B,MADIiB,EAAM,WAAW,KACjB1R,KAAkB0R,EAAM,CAAC,EAAE,KAAM,QAAOA,EAAM,CAAC,EAAE;AAErD,WAASxkB,IAAI,GAAGA,IAAIwkB,EAAM,QAAQxkB,KAAK,GAAG;AACzC,UAAM7B,IAAOqmB,EAAMxkB,IAAI,CAAC,GAClB5F,IAAOoqB,EAAMxkB,CAAC;AACpB,QAAI8S,IAAiB1Y,EAAK,KAAM;AAChC,UAAM6qB,IAAO,KAAK,IAAI,MAAM7qB,EAAK,OAAO+D,EAAK,IAAI,GAC3CM,IAAIpB,IAAOyV,IAAiB3U,EAAK,QAAQ8mB,GAAM,GAAG,CAAC;AACzD,WAAO9mB,EAAK,QAAQ/D,EAAK,OAAO+D,EAAK,QAAQM;AAAA,EAC9C;AAEA,QAAMV,IAAOymB,EAAMA,EAAM,SAAS,CAAC,GAC7BrmB,IAAOqmB,EAAMA,EAAM,SAAS,CAAC,GAC7BS,IAAO,KAAK,IAAI,MAAMlnB,EAAK,OAAOI,EAAK,IAAI,GAC3C+mB,KAASnnB,EAAK,OAAOI,EAAK,QAAQ8mB;AACxC,SAAOlnB,EAAK,QAAQ+U,IAAiB/U,EAAK,QAAQmnB;AACnD;AAEA,MAAMC,KAAmB,KACnBC,KAAmB;AAEzB,SAASC,GAAqB/nB,GAA0C;AACvE,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU,IAC1DD,GAAMC,GAAO6nB,IAAkBC,EAAgB;AACvD;AAEO,MAAME,GAAgB;AAAA,EAqD5B,YACCxrB,GACAb,GACA6B,IAAkC,CAAA,GACjC;AAxDe,IAAAb,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAIc,GAAA;AACb,IAAAd,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA;AACA,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,kBAAW;AACX,IAAAA,EAAA,yBAA6C;AAC7C,IAAAA,EAAA,4BAAoC;AACpC,IAAAA,EAAA,mBAA2B;AAC3B,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,2BAAoB;AACpB,IAAAA,EAAA,wBAAiB;AACjB,IAAAA,EAAA,4CAAqC;AACrC,IAAAA,EAAA;AACA,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,yBAAkB;AAClB,IAAAA,EAAA,2BAAoB;AACpB,IAAAA,EAAA,0BAAmB;AACnB,IAAAA,EAAA,wBAAkCsqB,GAAoBd,EAAwB;AAC9E,IAAAxpB,EAAA,0BAAmB;AACnB,IAAAA,EAAA,uBAAqC;AACrC,IAAAA,EAAA,0BAAsC;AACtC,IAAAA,EAAA,mCAAY,IAAA;AAEH,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAOhB,SAAK,SAASH,GACd,KAAK,SAASb,GACd,KAAK,oBAAoB6B,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,iBAAiBA,EAAQ,kBAAkB,IAChD,KAAK,qCACJ,OAAOA,EAAQ,sCAAuC,YACtD,OAAO,SAASA,EAAQ,kCAAkC,IACvD,KAAK,IAAI,GAAGA,EAAQ,kCAAkC,IACtDwoB,IACJ,KAAK,iBAAiBoB,GAAwB5pB,EAAQ,eAAe,GACrE,KAAK,mBAAmBuqB,GAAqBvqB,EAAQ,gBAAgB;AAErE,UAAM/B,IAAKe,EAAO,WAAW,UAAU;AAAA,MACtC,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,iBAAiB;AAAA,IAAA,CACjB;AACD,QAAI,CAACf;AACJ,YAAM,IAAI,MAAM,sBAAsB;AAEvC,SAAK,KAAKA,GAEV,KAAK,cAAc,KAAK,gBAAA,GACxB,KAAK,eAAe,KAAK,iBAAA,GACzB,KAAK,gBAAgB,IAAIqpB,GAAc;AAAA,MACtC,WAAW,KAAK;AAAA,MAChB,gBAAgBtnB,EAAQ,eAAe,kBAAkB;AAAA,MACzD,YAAYA,EAAQ,eAAe,cAAc;AAAA,MACjD,kBAAkBA,EAAQ,eAAe,oBAAoB;AAAA,MAC7D,iBAAiBA,EAAQ,eAAe,mBAAmB;AAAA,MAC3D,YAAY,CAACW,GAAMI,MAAW,KAAK,iBAAiBJ,GAAMI,CAAM;AAAA,MAChE,aAAa,CAACJ,GAAMM,GAAOwpB,MAAiB;AAC3C,aAAK,cAAc,EAAE,MAAA9pB,GAAM,OAAAM,GAAO,cAAAwpB,GAAc,GAChD,QAAQ,KAAK,oBAAoB9pB,EAAK,KAAKM,CAAK;AAAA,MACjD;AAAA,IAAA,CACA,GAED,KAAK,iBAAiB,IAAI,eAAe,MAAM,KAAK,QAAQ,GAC5D,KAAK,eAAe,QAAQjC,CAAM,GAElC,KAAK,mBAAmB,CAACmb,MAAwB,KAAK,cAAcA,CAAK,GACzE,KAAK,mBAAmB,CAACA,MAAwB,KAAK,cAAcA,CAAK,GACzE,KAAK,iBAAiB,CAACA,MAAwB,KAAK,YAAYA,CAAK,GACrE,KAAK,aAAa,CAACA,MAAsB,KAAK,QAAQA,CAAK,GAC3D,KAAK,mBAAmB,CAACA,MAAsB,KAAK,cAAcA,CAAK,GACvE,KAAK,mBAAmB,CAACA,MAAsB,KAAK,cAAcA,CAAK,GACvE,KAAK,mBAAmB,CAACA,MAAiB,KAAK,mBAAmBA,CAAK,GACvE,KAAK,uBAAuB,CAACA,MAC5B,KAAK,uBAAuBA,CAAK,GAElCnb,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,aAAa,KAAK,cAAc,GACxDA,EAAO,iBAAiB,iBAAiB,KAAK,cAAc,GAC5DA,EAAO,iBAAiB,SAAS,KAAK,YAAY,EAAE,SAAS,IAAO,GACpEA,EAAO,iBAAiB,YAAY,KAAK,gBAAgB,GACzDA,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,oBAAoB,KAAK,gBAAgB,GACjEA,EAAO,iBAAiB,wBAAwB,KAAK,oBAAoB,GAEzE,KAAK,WAAA,GACL,KAAK,OAAA;AAAA,EACN;AAAA,EAEA,aAAaoN,GAAqB;AACjC,SAAK,YAAY,OAAOA,KAAS,EAAE,GACnC,KAAK,cAAc,aAAa,KAAK,SAAS;AAAA,EAC/C;AAAA,EAEA,aAAa9M,GAAmC;AAC/C,UAAM2K,IAAoC,EAAE,GAAG3K,EAAA;AAC/C,IAAI,OAAO2K,EAAW,QAAS,aAC9BA,EAAW,OAAO1H,GAAM0H,EAAW,MAAM,KAAK,SAAS,KAAK,OAAO,IAEpE,KAAK,OAAO,aAAaA,CAAU,GACnC,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,eAA6B;AAC5B,WAAO,KAAK,OAAO,aAAA;AAAA,EACpB;AAAA,EAEA,gBAAgB8C,GAA6C;AAC5D,QAAI,CAACA,KAAUA,EAAO,WAAW,GAAG;AACnC,WAAK,mBAAmB;AACxB;AAAA,IACD;AAEA,QADA,KAAK,mBAAmB,IAAI,WAAWA,CAAM,GACzC,KAAK,eAAe,KAAK,GAAG,gBAAiB;AACjD,UAAM9O,IAAK,KAAK,IACVysB,IAAc,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,iBAAiB,SAAS,CAAC,CAAC;AAC5E,SAAK,mBAAmBA,GACxBzsB,EAAG,YAAYA,EAAG,YAAY,KAAK,aAAa,cAAc,GAC9DA,EAAG;AAAA,MACFA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACHysB;AAAA,MACA;AAAA,MACA;AAAA,MACAzsB,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,KAAK;AAAA,IAAA,GAENA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAakF,GAA+C;AAC3D,QAAI,CAACA,KAAU,CAACA,EAAO,SAAS,CAACA,EAAO,aAAa,CAACA,EAAO,gBAAgB;AAC5E,WAAK,gBAAgB,MACrB,KAAK,aAAa,GAClB,KAAK,kBAAkB,IACvB,KAAK,cAAA;AACL;AAAA,IACD;AAEA,UAAMqgB,IAAY,KAAK;AAAA,MACtB;AAAA,MACA,KAAK;AAAA,QACJrgB,EAAO;AAAA,QACP,KAAK,MAAMA,EAAO,UAAU,SAAS,CAAC;AAAA,QACtCA,EAAO,eAAe;AAAA,MAAA;AAAA,IACvB,GAEKwd,IAAgBxd,EAAO,UAAU,SAAS,GAAGqgB,IAAY,CAAC,GAC1DmH,IAAqBxnB,EAAO,eAAe,SAAS,GAAGqgB,CAAS,GAChEoH,IAAiBznB,EAAO,uBAAuB,aAC/C0nB,IAAkBD,IACrB,KAAK,oBAAoBznB,EAAO,aAA4BqgB,CAAS,IACrE,MACGngB,IAAO,KAAK;AAClB,QAAIynB,IACH,KAAK,qBACL,CAACznB,KACDA,EAAK,UAAUmgB,KACf,CAACgG,GAAgBnmB,EAAK,WAAWsd,CAAa,KAC9C,CAAC6I,GAAgBnmB,EAAK,gBAAgBsnB,CAAkB,GACrDI,IACH,KAAK,qBACJH,MACC,CAACvnB,GAAM,eACP,CAACmmB,GAAgBnmB,EAAK,aAAawnB,CAAe,MACnD,CAACD,KAAkB,CAAC,CAACvnB,GAAM;AAQ7B,QANA,KAAK,gBAAgB;AAAA,MACpB,OAAOmgB;AAAA,MACP,WAAW7C;AAAA,MACX,gBAAgBgK;AAAA,MAChB,aAAaC,IAAiBC,KAAmB,SAAY;AAAA,IAAA,GAE1D,KAAK,eAAe,KAAK,GAAG,gBAAiB;AAEjD,UAAM5sB,IAAK,KAAK;AAChB,IAAI6sB,MACH7sB,EAAG,WAAWA,EAAG,cAAc,KAAK,aAAa,SAAS,GAC1DA,EAAG,WAAWA,EAAG,cAAc,KAAK,cAAc,WAAWA,EAAG,WAAW,GAE3EA,EAAG,WAAWA,EAAG,cAAc,KAAK,aAAa,UAAU,GAC3DA,EAAG;AAAA,MACFA,EAAG;AAAA,MACH,KAAK,cAAc;AAAA,MACnBA,EAAG;AAAA,IAAA,GAEJA,EAAG,WAAWA,EAAG,cAAc,IAAI,IAGhC2sB,KAAkBG,MACrB9sB,EAAG,WAAWA,EAAG,sBAAsB,KAAK,aAAa,WAAW,GACpEA,EAAG;AAAA,MACFA,EAAG;AAAA,MACH4sB,KAAmB,IAAI,YAAY,CAAC;AAAA,MACpC5sB,EAAG;AAAA,IAAA,GAEJA,EAAG,WAAWA,EAAG,sBAAsB,IAAI,IAG5C,KAAK,kBAAkB2sB,GACvB,KAAK,aAAaA,IACdC,GAAiB,UAAU,IAC5B,KAAK,cAAc,QAClBC,KAAmBC,OACtB,KAAK,oBAAoB,KAE1B,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,oBACP/G,GACAgH,GACc;AACd,QAAIA,KAAgB,KAAKhH,EAAY,WAAW;AAC/C,aAAO,IAAI,YAAY,CAAC;AAGzB,QAAIiH,IAAajH,EAAY;AAC7B,aAAS9e,IAAI,GAAGA,IAAI8e,EAAY,QAAQ9e,KAAK;AAC5C,MAAI8e,EAAY9e,CAAC,IAAI8lB,MACrBC,KAAc;AAEf,QAAIA,MAAejH,EAAY;AAC9B,aAAOA;AAER,QAAIiH,KAAc;AACjB,aAAO,IAAI,YAAY,CAAC;AAGzB,UAAM5E,IAAW,IAAI,YAAY4E,CAAU;AAC3C,QAAItS,IAAS;AACb,aAASzT,IAAI,GAAGA,IAAI8e,EAAY,QAAQ9e,KAAK,GAAG;AAC/C,YAAMohB,IAAMtC,EAAY9e,CAAC;AACzB,MAAIohB,KAAO0E,MACX3E,EAAS1N,CAAM,IAAI2N,GACnB3N,KAAU;AAAA,IACX;AACA,WAAO0N;AAAA,EACR;AAAA,EAEA,mBAAmB6E,GAAuB;AACzC,UAAM5rB,IAAO,EAAQ4rB;AACrB,IAAI,KAAK,sBAAsB5rB,MAC/B,KAAK,oBAAoBA,GACrBA,UAAW,WAAA;AAAA,EAChB;AAAA,EAEA,mBAAmBuqB,GAA2D;AAC7E,UAAMsB,IAAYvB,GAAwBC,CAAe;AACzD,IAAII,GAAuB,KAAK,gBAAgBkB,CAAS,MACzD,KAAK,iBAAiBA,GACtB,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,oBAAoBC,GAAwC;AAC3D,UAAM9rB,IAAOirB,GAAqBa,CAAK;AACvC,IAAI,KAAK,qBAAqB9rB,MAC9B,KAAK,mBAAmBA,GACxB,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAmB;AAClB,QAAI,KAAK,cAAc,QAAQ,KAAK,OAAO,kBAAkB,KAAK,SAAS;AAC1E,UAAI;AACH,aAAK,OAAO,sBAAsB,KAAK,SAAS;AAAA,MACjD,QAAQ;AAAA,MAER;AAED,SAAK,WAAW,IAChB,KAAK,kBAAkB,QACvB,KAAK,qBAAqB,MAC1B,KAAK,YAAY,MACjB,KAAK,OAAO,UAAU,OAAO,UAAU;AAAA,EACxC;AAAA,EAEQ,mBAAmBsf,GAAiBC,GAAyB;AACpE,UAAM3d,IAAO,KAAK,OAAO,sBAAA,GACnB4B,IAAI8b,IAAU1d,EAAK,OAAOA,EAAK,QAAQ,KACvC6B,IAAI8b,IAAU3d,EAAK,MAAMA,EAAK,SAAS;AAC7C,WAAO,KAAK,MAAM6B,GAAGD,CAAC;AAAA,EACvB;AAAA,EAEA,cAAc8b,GAAiBC,GAAmC;AACjE,UAAM3d,IAAO,KAAK,OAAO,sBAAA,GACnBzB,IAAKmf,IAAU1d,EAAK,MACpBxB,IAAKmf,IAAU3d,EAAK;AAC1B,WAAO,KAAK,OAAO,cAAczB,GAAIC,CAAE;AAAA,EACxC;AAAA,EAEA,cAAcuf,GAAgBC,GAAkC;AAC/D,WAAO,KAAK,OAAO,cAAcD,GAAQC,CAAM;AAAA,EAChD;AAAA,EAEA,cAAcD,GAAgBC,GAAsB;AACnD,IAAI,CAAC,OAAO,SAASD,CAAM,KAAK,CAAC,OAAO,SAASC,CAAM,MACvD,KAAK,OAAO,UAAUD,GAAQC,CAAM,GACpC,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,iBAAmE;AAClE,WAAO,KAAK,OAAO,eAAA;AAAA,EACpB;AAAA,EAEA,gBAAsB;AACrB,UAAMlG,IAAQ,KAAK,OAAO,aAAA;AAC1B,IAAI,KAAK,IAAIA,EAAM,WAAW,IAAI,SAClC,KAAK,OAAO,aAAa,EAAE,aAAa,GAAG,GAC3C,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,qBAA6B;AAC5B,UAAMvX,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrDuW,IAAiB,KAAK,OAAO,cAAc,KAAK,KAAKvW,CAAI,GACzDuoB,IAAOE,GAA4BlS,GAAgB,KAAK,cAAc;AAC5E,WAAOzV,GAAMynB,GAAMvB,IAAmBC,EAAiB;AAAA,EACxD;AAAA,EAEA,aAAmB;AAClB,UAAMxnB,IAAO,KAAK,OAAO,sBAAA,GACnBmqB,IAAK,KAAK,IAAI,GAAGnqB,EAAK,SAAS,CAAC,GAChCoqB,IAAK,KAAK,IAAI,GAAGpqB,EAAK,UAAU,CAAC,GAEjCO,IAAO,KAAK,IAAI4pB,IAAK,KAAK,OAAO,OAAOC,IAAK,KAAK,OAAO,MAAM,GAC/D5pB,IAAW,OAAO,SAASD,CAAI,KAAKA,IAAO,IAAIA,IAAO;AAE5D,SAAK,UAAUC,GACf,KAAK,UAAU,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAChD,KAAK,UAAU,KAAK,IAAI,GAAG,KAAK,UAAU,CAAC,GACvC,KAAK,UAAU,KAAK,YACvB,KAAK,UAAU,KAAK;AAGrB,UAAM6pB,IAAgBF,IAAK3pB,GACrB8pB,IAAgBF,IAAK5pB;AAE3B,SAAK,OAAO,aAAa;AAAA,MACxB,MAAMa,GAAMb,GAAU,KAAK,SAAS,KAAK,OAAO;AAAA,MAChD,UAAU,KAAK,OAAO,QAAQ6pB,KAAiB;AAAA,MAC/C,UAAU,KAAK,OAAO,SAASC,KAAiB;AAAA,MAChD,aAAa;AAAA,IAAA,CACb,GAED,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,OAAOC,GAAgBlQ,GAAiBC,GAAuB;AAC9D,UAAMxC,IAAQ,KAAK,OAAO,aAAA,GACpB0S,IAAWnpB,GAAMyW,EAAM,OAAOyS,GAAQ,KAAK,SAAS,KAAK,OAAO;AACtE,QAAIC,MAAa1S,EAAM,KAAM;AAE7B,UAAM,CAACiG,GAAQC,CAAM,IAAI,KAAK,OAAO,cAAc3D,GAASC,CAAO;AAEnE,SAAK,OAAO,aAAa,EAAE,MAAMkQ,GAAU;AAE3C,UAAMC,IAAK,KAAK,OAAO,YAAA,GACjB7jB,IAAKyT,IAAUoQ,EAAG,QAAQ,KAC1B5jB,IAAKyT,IAAUmQ,EAAG,SAAS,KAC3B/C,IAAMC,GAAU,KAAK,OAAO,aAAA,EAAe,WAAW,GACtDC,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAClBgD,IAAW9jB,IAAK4jB,IAAY5C,IAAO/gB,IAAK2jB,IAAY3C,GACpD8C,IAAW/jB,IAAK4jB,IAAY3C,IAAOhhB,IAAK2jB,IAAY5C;AAC1D,SAAK,OAAO,UAAU7J,IAAS2M,GAAS1M,IAAS2M,CAAO,GAExD,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,iBAAuB;AACtB,UAAMznB,IAAS,KAAK,cAAA,GACd+a,IAAW,KAAK,IAAI,MAAM/a,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GAC/Cgb,IAAW,KAAK,IAAI,MAAMhb,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GAC/C0nB,IAAU3M,IAAW,KACrB4M,IAAU3M,IAAW,KAErB,CAAC3O,GAASC,CAAO,IAAI,KAAK,OAAO,UAAA,GACjCsb,IAAQ7M,IAAW,KACnB8M,IAAQ7M,IAAW,KAEnB8M,IAAaF,IAAQF,GACrBK,IAAa,KAAK,OAAO,QAAQH,IAAQF,GACzCM,IAAaH,IAAQF,GACrBM,IAAa,KAAK,OAAO,SAASJ,IAAQF,GAE1CO,IACLJ,KAAcC,IACX5pB,GAAMkO,GAASyb,GAAYC,CAAU,IACrC,KAAK,OAAO,QAAQ,KAClBI,IACLH,KAAcC,IACX9pB,GAAMmO,GAAS0b,GAAYC,CAAU,IACrC,KAAK,OAAO,SAAS;AAEzB,SAAK,OAAO,UAAUC,GAAaC,CAAW;AAAA,EAC/C;AAAA,EAEA,gBAAsB;AACrB,SAAK,oBAAoB,KAAK,OAAO,aAAA,CAAc;AAAA,EACpD;AAAA,EAEA,aAAqB;AACpB,UAAM9qB,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrD+qB,IAAU,KAAK,OAAO,cAAc,KAAK,KAAK/qB,CAAI;AACxD,WAAOc,GAAM,KAAK,MAAMiqB,CAAO,GAAG,GAAG,KAAK,OAAO,WAAW;AAAA,EAC7D;AAAA,EAEA,gBAAwB;AACvB,UAAMpO,IAAU,KAAK,OAAO,eAAA;AAC5B,QAAIva,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW,CAAClB,GAAGC,CAAC,KAAKqb;AACpB,MAAItb,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,WAAO,CAACc,GAAMC,GAAMC,GAAMC,CAAI;AAAA,EAC/B;AAAA,EAEA,iBAAiBmD,GAAWC,GAAoB;AAC/C,WAAO,EAAED,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC;AAAA,EACrE;AAAA,EAEA,kBAAmC;AAClC,UAAMoV,IAAO,KAAK,WAAA;AAClB,SAAK,cAAcA;AAEnB,UAAMiQ,IAAa,KAAK,cAAA,GAElBlN,IAAa,KAAK,IAAI,GAAG,KAAK,OAAO,cAAc/C,CAAI,GACvDgD,IAAa,KAAK,KAAK,KAAK,OAAO,QAAQD,CAAU,GACrDE,IAAc,KAAK,KAAK,KAAK,OAAO,SAASF,CAAU,GAEvDG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAa,KAAK,OAAO,QAAQ,CAAC,GACjEG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAc,KAAK,OAAO,QAAQ,CAAC,GAElEiN,IAAWD,EAAW,CAAC,GACvBE,IAAWF,EAAW,CAAC,GACvBG,IAAWH,EAAW,CAAC,GACvBI,IAAWJ,EAAW,CAAC,GAEvBK,IAAWvqB;AAAAA,MAChB,KAAK,MAAMmqB,IAAWnN,IAAa,KAAK,OAAO,QAAQ;AAAA,MACvD;AAAA,MACAG,IAAS;AAAA,IAAA,GAEJqN,IAAWxqB;AAAAA,MAChB,KAAK,OAAOqqB,IAAW,KAAKrN,IAAa,KAAK,OAAO,QAAQ;AAAA,MAC7D;AAAA,MACAG,IAAS;AAAA,IAAA,GAEJsN,IAAWzqB;AAAAA,MAChB,KAAK,MAAMoqB,IAAWpN,IAAa,KAAK,OAAO,QAAQ;AAAA,MACvD;AAAA,MACAI,IAAS;AAAA,IAAA,GAEJsN,IAAW1qB;AAAAA,MAChB,KAAK,OAAOsqB,IAAW,KAAKtN,IAAa,KAAK,OAAO,QAAQ;AAAA,MAC7D;AAAA,MACAI,IAAS;AAAA,IAAA;AAGV,QAAImN,IAAWC,KAAYC,IAAWC;AACrC,aAAO,CAAA;AAGR,UAAMC,KAAeR,IAAWE,KAAY,MAAMrN,IAAa,KAAK,OAAO,UACrE4N,KAAeR,IAAWE,KAAY,MAAMtN,IAAa,KAAK,OAAO,UAErE6N,IAA2B,CAAA;AACjC,aAASrqB,IAAIiqB,GAAUjqB,KAAKkqB,GAAUlqB,KAAK;AAC1C,eAASD,IAAIgqB,GAAUhqB,KAAKiqB,GAAUjqB,KAAK,GAAG;AAC7C,cAAMgR,IAAOhR,IAAI,KAAK,OAAO,WAAWyc,GAClCxL,KAAMhR,IAAI,KAAK,OAAO,WAAWwc,GACjChB,KAAQ,KAAK,KAAKzb,IAAI,KAAK,KAAK,OAAO,UAAU0c,CAAU,IAAID,GAC/Df,KAAS,KAAK,KAAKzb,IAAI,KAAK,KAAK,OAAO,UAAU0c,CAAW,IAAIF,GAEjEzX,IAAKhF,IAAIoqB,GACTnlB,KAAKhF,IAAIoqB;AACf,QAAAC,EAAQ,KAAK;AAAA,UACZ,KAAK,GAAG5Q,CAAI,IAAI1Z,CAAC,IAAIC,CAAC;AAAA,UACtB,MAAAyZ;AAAA,UACA,GAAA1Z;AAAA,UACA,GAAAC;AAAA,UACA,QAAQ,CAAC+Q,GAAMC,IAAKwK,IAAOC,EAAM;AAAA,UACjC,WAAW1W,IAAKA,IAAKC,KAAKA;AAAA,UAC1B,KAAK0U,GAAU,KAAK,QAAQD,GAAM1Z,GAAGC,CAAC;AAAA,QAAA,CACtC;AAAA,MACF;AAGD,WAAAqqB,EAAQ,KAAK,CAACjmB,GAAGC,MAAMD,EAAE,YAAYC,EAAE,SAAS,GACzCgmB;AAAA,EACR;AAAA,EAEA,YAAkB;AACjB,QAAI,KAAK,MAAM,QAAQ,KAAK,cAAe;AAE3C,UAAMC,IAAU,MAAM,KAAK,KAAK,MAAM,SAAS;AAC/C,IAAAA,EAAQ,KAAK,CAAClmB,GAAGC,MAAMD,EAAE,CAAC,EAAE,WAAWC,EAAE,CAAC,EAAE,QAAQ;AAEpD,UAAMkmB,IAAc,KAAK,MAAM,OAAO,KAAK;AAC3C,aAASpoB,IAAI,GAAGA,IAAIooB,GAAapoB,KAAK,GAAG;AACxC,YAAM,CAAC0iB,GAAKplB,CAAK,IAAI6qB,EAAQnoB,CAAC;AAC9B,WAAK,GAAG,cAAc1C,EAAM,OAAO,GACnC,KAAK,MAAM,OAAOolB,CAAG;AAAA,IACtB;AAAA,EACD;AAAA,EAEA,SAAe;AACd,QAAI,KAAK,aAAa,KAAK,eAAe,KAAK,GAAG,gBAAiB;AACnE,UAAM2F,IAAelK,GAAA;AACrB,SAAK,eAAe;AAEpB,UAAMplB,IAAK,KAAK,IACVuvB,IAAc,KAAK,aACnBC,IAAe,KAAK;AAE1B,IAAAxvB,EAAG,WAAW,MAAM,MAAM,KAAK,CAAC,GAChCA,EAAG,MAAMA,EAAG,gBAAgB;AAE5B,UAAMmvB,IAAU,KAAK,gBAAA,GACfX,IAAa,KAAK,cAAA,GAClB/E,IAAc,IAAI,IAAI0F,EAAQ,IAAI,CAACzsB,MAASA,EAAK,GAAG,CAAC;AAE3D,IAAA1C,EAAG,WAAWuvB,EAAY,OAAO,GACjCvvB,EAAG,gBAAgBuvB,EAAY,GAAG,GAClCvvB,EAAG,iBAAiBuvB,EAAY,SAAS,IAAO,KAAK,OAAO,WAAW,GACvEvvB,EAAG,UAAUuvB,EAAY,UAAU,CAAC;AAEpC,UAAME,IAA8B,CAAA;AACpC,eAAW,CAAA,EAAGC,CAAM,KAAK,KAAK;AAC7B,MAAIjG,EAAY,IAAIiG,EAAO,GAAG,KACzB,KAAK,iBAAiBA,EAAO,QAAQlB,CAAU,KACpDiB,EAAc,KAAKC,CAAM;AAG1B,IAAAD,EAAc,KAAK,CAACvmB,GAAGC,MAAMD,EAAE,OAAOC,EAAE,IAAI;AAC5C,eAAWumB,KAAUD;AACpB,MAAAC,EAAO,WAAW,KAAK,aACvB1vB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY0vB,EAAO,OAAO,GAC5C1vB,EAAG;AAAA,QACFuvB,EAAY;AAAA,QACZG,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,MAAA,GAEhB1vB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC;AAGtC,QAAI2vB,IAAgB;AACpB,UAAMC,IAAgC,CAAA;AACtC,eAAWltB,KAAQysB,GAAS;AAC3B,YAAMO,IAAS,KAAK,MAAM,IAAIhtB,EAAK,GAAG;AACtC,UAAI,CAACgtB,GAAQ;AACZ,QAAAE,EAAa,KAAKltB,CAAI;AACtB;AAAA,MACD;AACA,MAAAgtB,EAAO,WAAW,KAAK,aACvB1vB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY0vB,EAAO,OAAO,GAC5C1vB,EAAG;AAAA,QACFuvB,EAAY;AAAA,QACZG,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,MAAA,GAEhB1vB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC,GACrC2vB,KAAiB;AAAA,IAClB;AACA,SAAK,cAAc,SAASC,CAAY,GAExC5vB,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI;AAEvB,QAAI6vB,IAAiB;AAuBrB,QAtBI,KAAK,aAAa,MACrB7vB,EAAG,OAAOA,EAAG,KAAK,GAClBA,EAAG,UAAUA,EAAG,KAAKA,EAAG,mBAAmB,GAC3CA,EAAG,WAAWwvB,EAAa,OAAO,GAClCxvB,EAAG,gBAAgBwvB,EAAa,GAAG,GACnCxvB,EAAG,iBAAiBwvB,EAAa,SAAS,IAAO,KAAK,OAAO,WAAW,GACxExvB,EAAG,UAAUwvB,EAAa,YAAY,KAAK,oBAAoB,GAC/DxvB,EAAG,UAAUwvB,EAAa,mBAAmB,KAAK,gBAAgB,GAClExvB,EAAG,UAAUwvB,EAAa,cAAc,KAAK,gBAAgB,GAC7DxvB,EAAG,UAAUwvB,EAAa,UAAU,CAAC,GACrCxvB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYwvB,EAAa,cAAc,GACrD,KAAK,kBACRxvB,EAAG,aAAaA,EAAG,QAAQ,KAAK,YAAYA,EAAG,cAAc,CAAC,IAE9DA,EAAG,WAAWA,EAAG,QAAQ,GAAG,KAAK,UAAU,GAE5CA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI,GACvB6vB,IAAiB,KAAK,aAGnB,KAAK,SAAS;AACjB,YAAMC,IAAiB,KAAK,cAAc,YAAA,GACpCC,IAAYJ,GACZK,IAAcJ,EAAa,QAC3BK,IACLR,EAAc,SAASE,KAAiBE,IAAiB,IAAI,IAAI;AAClE,WAAK,QAAQ;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,SAASV,EAAQ;AAAA,QACjB,UAAUQ;AAAA,QACV,QAAQE;AAAA,QACR,UAAUJ,EAAc;AAAA,QACxB,OAAO,KAAK,MAAM;AAAA,QAClB,UAAUK,EAAe;AAAA,QACzB,QAAQA,EAAe;AAAA,QACvB,SAASA,EAAe;AAAA,QACxB,QAAQA,EAAe;AAAA,QACvB,SAASA,EAAe;AAAA,QACxB,WAAAC;AAAA,QACA,aAAAC;AAAA,QACA,WAAAC;AAAA,QACA,SAAS7K,OAAUkK;AAAA,MAAA,CACnB;AAAA,IACF;AAAA,EACD;AAAA,EAEA,gBAAsB;AACrB,IACC,KAAK,UAAU,QACf,KAAK,aACL,KAAK,eACL,KAAK,GAAG,cAAA,MAGT,KAAK,QAAQ,sBAAsB,MAAM;AACxC,WAAK,QAAQ,MACb,KAAK,OAAA;AAAA,IACN,CAAC;AAAA,EACF;AAAA,EAEA,SAAe;AACd,UAAMrsB,IAAO,KAAK,OAAO,sBAAA,GACnB8c,IAAO,KAAK,IAAI,GAAG9c,EAAK,SAAS,KAAK,OAAO,eAAe,CAAC,GAC7D+c,IAAO,KAAK,IAAI,GAAG/c,EAAK,UAAU,KAAK,OAAO,gBAAgB,CAAC,GAC/DG,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9C6c,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO3c,CAAG,CAAC,GAC3C8c,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO5c,CAAG,CAAC;AAEjD,KAAI,KAAK,OAAO,UAAU6c,KAAU,KAAK,OAAO,WAAWC,OAC1D,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGtB,KAAK,OAAO,YAAYH,GAAMC,CAAI,GAClC,KAAK,GAAG,SAAS,GAAG,GAAGC,GAAQC,CAAM,GACrC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,cAAchE,GAA2B;AACxC,QAAI,KAAK,kBAAmB;AAC5B,UAAMgU,IAAc,KAAK,mBAAmBhU,EAAM,WAAWA,EAAM;AAEnE,KADoBA,EAAM,WAAW,KAAMgU,KAAehU,EAAM,WAAW,OAEvEgU,KACHhU,EAAM,eAAA,GAEP,KAAK,WAAW,IAChB,KAAK,kBACJgU,IAAc,WAAW,OAC1B,KAAK,YAAYhU,EAAM,WACvB,KAAK,eAAeA,EAAM,SAC1B,KAAK,eAAeA,EAAM,SAC1B,KAAK,qBACJ,KAAK,oBAAoB,WACtB,KAAK,mBAAmBA,EAAM,SAASA,EAAM,OAAO,IACpD,MACJ,KAAK,OAAO,UAAU,IAAI,UAAU,GACpC,KAAK,OAAO,kBAAkBA,EAAM,SAAS;AAAA,EAC9C;AAAA,EAEA,cAAcA,GAA2B;AAExC,QADI,KAAK,qBACL,CAAC,KAAK,YAAYA,EAAM,cAAc,KAAK,UAAW;AAE1D,UAAMrS,IAAKqS,EAAM,UAAU,KAAK,cAC1BpS,IAAKoS,EAAM,UAAU,KAAK;AAIhC,QAHA,KAAK,eAAeA,EAAM,SAC1B,KAAK,eAAeA,EAAM,SAEtB,KAAK,oBAAoB,UAAU;AACtC,YAAMiU,IAAY,KAAK,mBAAmBjU,EAAM,SAASA,EAAM,OAAO,GAChEkU,IAAY,KAAK;AAEvB,UADA,KAAK,qBAAqBD,GACtBC,MAAc,MAAM;AACvB,cAAMC,IAAWF,IAAYC,GACvBzoB,IAAQ,KAAK,MAAM,KAAK,IAAI0oB,CAAQ,GAAG,KAAK,IAAIA,CAAQ,CAAC,GAEzDC,IAEF,KAAK,qCACN/F,IAEGxP,IAAQ,KAAK,OAAO,aAAA;AAC1B,aAAK,OAAO,aAAa;AAAA,UACxB,aACCA,EAAM,cAAgBpT,IAAQ,MAAO,KAAK,KAAM2oB;AAAA,QAAA,CACjD;AAAA,MACF;AAAA,IACD,OAAO;AACN,YAAMvV,IAAQ,KAAK,OAAO,aAAA,GACpBvX,IAAO,KAAK,IAAI,MAAMuX,EAAM,IAAI,GAChC4P,IAAMC,GAAU7P,EAAM,WAAW,GACjC8P,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAClBgD,KAAW9jB,IAAKghB,IAAM/gB,IAAKghB,KAAOtnB,GAClCoqB,KAAW/jB,IAAKihB,IAAMhhB,IAAK+gB,KAAOrnB;AACxC,WAAK,OAAO,aAAa;AAAA,QACxB,SAASuX,EAAM,UAAU4S;AAAA,QACzB,SAAS5S,EAAM,UAAU6S;AAAA,MAAA,CACzB;AAAA,IACF;AAEA,SAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,YAAY1R,GAA2B;AACtC,IAAI,KAAK,qBACLA,EAAM,cAAc,KAAK,aAC7B,KAAK,WAAA;AAAA,EACN;AAAA,EAEA,QAAQA,GAAyB;AAChC,QAAI,KAAK,mBAAmB;AAC3B,MAAAA,EAAM,eAAA;AACN;AAAA,IACD;AAEA,IAAAA,EAAM,eAAA;AACN,UAAMjZ,IAAO,KAAK,OAAO,sBAAA,GACnB4B,IAAIqX,EAAM,UAAUjZ,EAAK,MACzB6B,IAAIoX,EAAM,UAAUjZ,EAAK,KACzBuqB,IAAStR,EAAM,SAAS,IAAI,OAAO;AACzC,SAAK,OAAOsR,GAAQ3oB,GAAGC,CAAC;AAAA,EACzB;AAAA,EAEA,cAAcoX,GAAyB;AACtC,QAAI,KAAK,kBAAmB;AAC5B,UAAMjZ,IAAO,KAAK,OAAO,sBAAA,GACnB4B,IAAIqX,EAAM,UAAUjZ,EAAK,MACzB6B,IAAIoX,EAAM,UAAUjZ,EAAK;AAC/B,SAAK,OAAOiZ,EAAM,WAAW,MAAM,MAAMrX,GAAGC,CAAC;AAAA,EAC9C;AAAA,EAEA,cAAcoX,GAAyB;AACtC,KAAI,KAAK,YAAYA,EAAM,WAAWA,EAAM,YAC3CA,EAAM,eAAA;AAAA,EAER;AAAA,EAEQ,mBAAmBA,GAAoB;AAE9C,IADAA,EAAM,eAAA,GACF,OAAK,aAAa,KAAK,iBAC3B,KAAK,cAAc,IACnB,KAAK,oBAAoB,IAErB,KAAK,UAAU,SAClB,qBAAqB,KAAK,KAAK,GAC/B,KAAK,QAAQ,OAGd,KAAK,WAAA,GACL,KAAK,cAAc,MAAA,GACnB,KAAK,MAAM,MAAA,GACX,KAAK,gBAAA;AAAA,EACN;AAAA,EAEQ,uBAAuBqU,GAAqB;AACnD,IAAI,KAAK,cACT,KAAK,cAAc,IACnB,KAAK,MAAM,MAAA,GAEX,KAAK,cAAc,KAAK,gBAAA,GACxB,KAAK,eAAe,KAAK,iBAAA,GACzB,KAAK,oBAAoB,IAErB,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,KAC3D,KAAK,gBAAgB,KAAK,gBAAgB,GAEvC,KAAK,gBACR,KAAK,aAAa,KAAK,aAAa,IAEpC,KAAK,aAAa,GAGnB,KAAK,OAAA,GACL,KAAK,cAAA,GACL,KAAK,oBAAA;AAAA,EACN;AAAA,EAEA,UAAgB;AACf,QAAI,MAAK,WAwBT;AAAA,UAvBA,KAAK,YAAY,IAEb,KAAK,UAAU,SAClB,qBAAqB,KAAK,KAAK,GAC/B,KAAK,QAAQ,OAGd,KAAK,eAAe,WAAA,GACpB,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,aAAa,KAAK,cAAc,GAChE,KAAK,OAAO,oBAAoB,iBAAiB,KAAK,cAAc,GACpE,KAAK,OAAO,oBAAoB,SAAS,KAAK,UAAU,GACxD,KAAK,OAAO,oBAAoB,YAAY,KAAK,gBAAgB,GACjE,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,oBAAoB,KAAK,gBAAgB,GACzE,KAAK,OAAO;AAAA,QACX;AAAA,QACA,KAAK;AAAA,MAAA,GAEN,KAAK,WAAA,GACL,KAAK,cAAc,QAAA,GAEf,CAAC,KAAK,eAAe,CAAC,KAAK,GAAG,iBAAiB;AAClD,mBAAW,CAAA,EAAGhsB,CAAK,KAAK,KAAK;AAC5B,eAAK,GAAG,cAAcA,EAAM,OAAO;AAEpC,aAAK,GAAG,aAAa,KAAK,YAAY,GAAG,GACzC,KAAK,GAAG,kBAAkB,KAAK,YAAY,GAAG,GAC9C,KAAK,GAAG,cAAc,KAAK,YAAY,OAAO,GAE9C,KAAK,GAAG,aAAa,KAAK,aAAa,SAAS,GAChD,KAAK,GAAG,aAAa,KAAK,aAAa,UAAU,GACjD,KAAK,GAAG,aAAa,KAAK,aAAa,WAAW,GAClD,KAAK,GAAG,cAAc,KAAK,aAAa,cAAc,GACtD,KAAK,GAAG,kBAAkB,KAAK,aAAa,GAAG,GAC/C,KAAK,GAAG,cAAc,KAAK,aAAa,OAAO;AAAA,MAChD;AACA,WAAK,MAAM,MAAA;AAAA;AAAA,EACZ;AAAA,EAEQ,kBAAqC;AAC5C,UAAMvE,IAAK,KAAK,IA4BVU,IAAUL,GAAcL,GA1Bf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASiC,GAC5CwwB,IAAU7vB,GAAuBX,GAAIU,GAAS,SAAS,GACvD+vB,IAAU9vB,GAAuBX,GAAIU,GAAS,SAAS,GACvDgwB,IAAW/vB,GAAuBX,GAAIU,GAAS,UAAU,GAEzDuB,IAAMjC,EAAG,kBAAA,GACT2wB,IAAM3wB,EAAG,aAAA;AACf,QAAI,CAACiC,KAAO,CAAC0uB;AACZ,YAAM,IAAI,MAAM,0BAA0B;AAG3C,IAAA3wB,EAAG,gBAAgBiC,CAAG,GACtBjC,EAAG,WAAWA,EAAG,cAAc2wB,CAAG,GAClC3wB,EAAG;AAAA,MACFA,EAAG;AAAA,MACH,IAAI,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,MACjEA,EAAG;AAAA,IAAA;AAGJ,UAAM4wB,IAAQ5wB,EAAG,kBAAkBU,GAAS,OAAO,GAC7CmwB,IAAM7wB,EAAG,kBAAkBU,GAAS,KAAK;AAC/C,QAAIkwB,IAAQ,KAAKC,IAAM;AACtB,YAAM,IAAI,MAAM,8BAA8B;AAE/C,WAAA7wB,EAAG,wBAAwB4wB,CAAK,GAChC5wB,EAAG,wBAAwB6wB,CAAG,GAC9B7wB,EAAG,oBAAoB4wB,GAAO,GAAG5wB,EAAG,OAAO,IAAO,IAAI,CAAC,GACvDA,EAAG,oBAAoB6wB,GAAK,GAAG7wB,EAAG,OAAO,IAAO,IAAI,CAAC,GAErDA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GAE5B,EAAE,SAAAU,GAAS,KAAAuB,GAAK,KAAA0uB,GAAK,SAAAH,GAAS,SAAAC,GAAS,UAAAC,EAAA;AAAA,EAC/C;AAAA,EAEQ,mBAAiC;AACxC,UAAM1wB,IAAK,KAAK,IA+CVU,IAAUL,GAAcL,GA7CV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcE;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,MA+BsC,GACtDwwB,IAAU7vB,GAAuBX,GAAIU,GAAS,SAAS,GACvDowB,IAAanwB,GAAuBX,GAAIU,GAAS,YAAY,GAC7DqwB,IAAoBpwB,GAAuBX,GAAIU,GAAS,mBAAmB,GAC3EswB,IAAWrwB,GAAuBX,GAAIU,GAAS,UAAU,GACzDuwB,IAAetwB,GAAuBX,GAAIU,GAAS,cAAc,GAEjEuB,IAAMjC,EAAG,kBAAA,GACTkxB,IAAYlxB,EAAG,aAAA,GACfmxB,IAAanxB,EAAG,aAAA,GAChBoxB,IAAcpxB,EAAG,aAAA,GACjBqxB,IAAiBrxB,EAAG,cAAA;AAC1B,QAAI,CAACiC,KAAO,CAACivB,KAAa,CAACC,KAAc,CAACC,KAAe,CAACC;AACzD,YAAM,IAAI,MAAM,gCAAgC;AAGjD,IAAArxB,EAAG,gBAAgBiC,CAAG,GAEtBjC,EAAG,WAAWA,EAAG,cAAckxB,CAAS,GACxClxB,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,UAAMsxB,IAAStxB,EAAG,kBAAkBU,GAAS,WAAW;AACxD,QAAI4wB,IAAS;AACZ,YAAM,IAAI,MAAM,oCAAoC;AAErD,IAAAtxB,EAAG,wBAAwBsxB,CAAM,GACjCtxB,EAAG,oBAAoBsxB,GAAQ,GAAGtxB,EAAG,OAAO,IAAO,GAAG,CAAC,GAEvDA,EAAG,WAAWA,EAAG,cAAcmxB,CAAU,GACzCnxB,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,UAAMuxB,IAAUvxB,EAAG,kBAAkBU,GAAS,OAAO;AACrD,QAAI6wB,IAAU;AACb,YAAM,IAAI,MAAM,gCAAgC;AAEjD,WAAAvxB,EAAG,wBAAwBuxB,CAAO,GAClCvxB,EAAG,qBAAqBuxB,GAAS,GAAGvxB,EAAG,gBAAgB,GAAG,CAAC,GAE3DA,EAAG,WAAWA,EAAG,sBAAsBoxB,CAAW,GAClDpxB,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,YAAYqxB,CAAc,GAC5CrxB,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;AAAA,MACFA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACAA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,IAAI,WAAW,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC;AAAA,IAAA,GAEpCA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAE3B;AAAA,MACN,SAAAU;AAAA,MACA,KAAAuB;AAAA,MACA,WAAAivB;AAAA,MACA,YAAAC;AAAA,MACA,aAAAC;AAAA,MACA,gBAAAC;AAAA,MACA,SAAAb;AAAA,MACA,YAAAM;AAAA,MACA,mBAAAC;AAAA,MACA,UAAAC;AAAA,MACA,cAAAC;AAAA,IAAA;AAAA,EAEF;AAAA,EAEQ,iBAAiBvuB,GAAqBI,GAA2B;AACxE,QAAI,KAAK,aAAa,KAAK,eAAe,KAAK,GAAG,iBAAiB;AAClE,MAAAA,EAAO,MAAA;AACP;AAAA,IACD;AACA,QAAI,KAAK,MAAM,IAAIJ,EAAK,GAAG,GAAG;AAC7B,MAAAI,EAAO,MAAA;AACP;AAAA,IACD;AAEA,UAAMC,IAAU,KAAK,wBAAwBD,CAAM;AAEnD,IADAA,EAAO,MAAA,GACFC,MAEL,KAAK,MAAM,IAAIL,EAAK,KAAK;AAAA,MACxB,KAAKA,EAAK;AAAA,MACV,SAAAK;AAAA,MACA,QAAQL,EAAK;AAAA,MACb,MAAMA,EAAK;AAAA,MACX,UAAU,KAAK;AAAA,IAAA,CACf,GACD,KAAK,UAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,wBAAwBI,GAA0C;AACzE,QAAI,KAAK,eAAe,KAAK,GAAG,cAAA,EAAiB,QAAO;AACxD,UAAM9C,IAAK,KAAK,IACV+C,IAAU/C,EAAG,cAAA;AACnB,WAAK+C,KAEL/C,EAAG,YAAYA,EAAG,YAAY+C,CAAO,GACrC/C,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,eAAe8C,CAAM,GAC1E9C,EAAG,YAAYA,EAAG,YAAY,IAAI,GAC3B+C,KAVc;AAAA,EAWtB;AACD;ACv5CA,MAAMyuB,KAAiC,CAAA,GACjCC,KAA8C,CAAA,GAC9CC,KAAqC;AAAA,EACzC,OAAO;AAAA,EACP,WAAW,IAAI,aAAa,CAAC;AAAA,EAC7B,gBAAgB,IAAI,YAAY,CAAC;AACnC,GACMC,KAAyB,MACzBC,KAA0B,GAC1BC,KAA0B,IAC1BC,KAA0B,MAC1BC,KAA+B;AAsFrC,SAAS3P,GAAmBC,GAAiC;AAC3D,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAMA,EAAU,SAAS,CAAC,GAAG,KAAK,OAAOA,EAAU,WAAW,UAAU,KAAK,CAAC,GAAGA,EAAU,gBAAgB,UAAU,CAAC,CAAC;AAC1J;AAEA,SAAS2P,GAAoBjM,GAAsCgH,GAA0C;AAC3G,MAAI,EAAEhH,aAAuB,gBAAgBgH,KAAgB,KAAKhH,EAAY,WAAW;AACvF,WAAO;AAGT,MAAIkM,IAAe;AACnB,WAAShrB,IAAI,GAAGA,IAAI8e,EAAY,QAAQ9e,KAAK;AAC3C,QAAI,EAAA8e,EAAY9e,CAAC,IAAI8lB,IACrB;AAAA,MAAAkF,IAAe;AACf;AAAA;AAEF,MAAI,CAACA;AACH,WAAOlM;AAGT,QAAMnhB,IAAM,IAAI,YAAYmhB,EAAY,MAAM;AAC9C,MAAIrL,IAAS;AACb,WAASzT,IAAI,GAAGA,IAAI8e,EAAY,QAAQ9e,KAAK,GAAG;AAC9C,UAAMohB,IAAMtC,EAAY9e,CAAC;AACzB,IAAIohB,KAAO0E,MACXnoB,EAAI8V,CAAM,IAAI2N,GACd3N,KAAU;AAAA,EACZ;AACA,SAAO9V,EAAI,SAAS,GAAG8V,CAAM;AAC/B;AAEA,SAASwX,GAAwBhyB,GAA+B8lB,GAA8B;AAC5F,MAAI,CAAC9lB,KAAU8lB,KAAgB,EAAG,QAAO;AACzC,QAAM3a,IAAO,KAAK,IAAI,GAAGnL,EAAO,QAAQA,EAAO,MAAM,GAE/Cic,IADa,KAAK,KAAK9Q,IAAO,KAAK,IAAI,GAAG2a,CAAY,CAAC,IACpC+L;AACzB,SAAO,KAAK,IAAIF,IAAyB,KAAK,IAAIC,IAAyB3V,CAAG,CAAC;AACjF;AAEA,SAASgW,GAAuB9P,GAA4CniB,GAAyD;AACnI,MAAI,CAACmiB,KAAa,CAACA,EAAU,aAAa,CAACA,EAAU;AACnD,WAAO;AAGT,QAAMkD,IAAYnD,GAAmBC,CAAS;AAC9C,MAAIkD,KAAa;AACf,WAAO;AAGT,QAAM/C,IAAYH,EAAU,UAAU,SAAS,GAAGkD,IAAY,CAAC,GACzDwB,IAAM1E,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAUkD,IAAYlD,EAAU,IAAI,SAAS,GAAGkD,CAAS,IAAI,MACzHQ,IAAciM,GAAoB3P,EAAU,aAAakD,CAAS,GAClES,IAAeD,IAAcA,EAAY,SAASR;AACxD,MAAIS,MAAiB;AACnB,WAAO;AAGT,QAAMoM,IAAWF,GAAwBhyB,GAAQ8lB,CAAY,GACvDqM,wBAAc,IAAA,GAEdC,IAAa,CAACrM,MAA6B;AAC/C,UAAM1R,IAAKiO,EAAUyD,IAAa,CAAC,GAC7BzR,IAAKgO,EAAUyD,IAAa,IAAI,CAAC;AACvC,QAAI,CAAC,OAAO,SAAS1R,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,EAAG;AAElD,UAAM+d,IAAQ,KAAK,MAAMhe,IAAK6d,CAAQ,GAChCI,IAAQ,KAAK,MAAMhe,IAAK4d,CAAQ;AACtC,QAAIK,IAASJ,EAAQ,IAAIE,CAAK;AAC9B,IAAKE,MACHA,wBAAa,IAAA,GACbJ,EAAQ,IAAIE,GAAOE,CAAM;AAE3B,UAAMC,IAASD,EAAO,IAAID,CAAK;AAC/B,IAAIE,IACFA,EAAO,KAAKzM,CAAU,IAEtBwM,EAAO,IAAID,GAAO,CAACvM,CAAU,CAAC;AAAA,EAElC;AAEA,MAAIF;AACF,aAAS9e,IAAI,GAAGA,IAAI8e,EAAY,QAAQ9e,KAAK;AAC3C,MAAAqrB,EAAWvM,EAAY9e,CAAC,KAAK,CAAC;AAAA;AAGhC,aAASA,IAAI,GAAGA,IAAIse,GAAWte,KAAK;AAClC,MAAAqrB,EAAWrrB,CAAC;AAIhB,SAAIorB,EAAQ,SAAS,IACZ,OAGF;AAAA,IACL,UAAAD;AAAA,IACA,WAAA7M;AAAA,IACA,WAAA/C;AAAA,IACA,KAAAuE;AAAA,IACA,SAAAsL;AAAA,EAAA;AAEJ;AAEA,SAASM,GAAgBpa,GAAmBH,GAAgC;AAC1E,SAAOG,EAAO,MAAMH;AACtB;AAEA,SAASwa,GACPjL,GACqB;AACrB,QAAM/iB,IAA2B,CAAA;AACjC,WAASqC,IAAI,GAAGA,IAAI0gB,EAAQ,QAAQ1gB,KAAK,GAAG;AAC1C,UAAMsR,IAASoP,EAAQ1gB,CAAC,GAClBmG,IAAWR,GAAmB,CAAC2L,GAAQ,WAA6C,CAAC;AAC3F,IAAInL,EAAS,WAAW,KACxBxI,EAAI,KAAK;AAAA,MACP,QAAA2T;AAAA,MACA,aAAatR;AAAA,MACb,UAAU0rB,GAAgBpa,GAAQtR,CAAC;AAAA,MACnC,UAAAmG;AAAA,IAAA,CACD;AAAA,EACH;AACA,SAAOxI;AACT;AAEA,SAASiuB,GACP7c,GACA2R,GAKO;AACP,QAAM9iB,IAAImR,EAAM,CAAC,GACXlR,IAAIkR,EAAM,CAAC;AACjB,WAAS,IAAI2R,EAAQ,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAC/C,UAAMpP,IAASoP,EAAQ,CAAC;AACxB,eAAW/b,KAAW2M,EAAO;AAC3B,UAAKtL,GAAuBpI,GAAGC,GAAG8G,CAAO;AACzC,eAAO;AAAA,UACL,QAAQ2M,EAAO;AAAA,UACf,aAAaA,EAAO;AAAA,UACpB,UAAUA,EAAO;AAAA,QAAA;AAAA,EAGvB;AACA,SAAO;AACT;AAuDO,SAASua,GAAgB;AAAA,EAC9B,QAAA5yB;AAAA,EACA,WAAAyC;AAAA,EACA,mBAAAowB;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,cAAAhY,IAAe;AAAA,EACf,mBAAAiY;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,oBAAAC,IAAqB;AAAA,EACrB,WAAAzU,IAAY;AAAA,EACZ,gBAAA0U,IAAiB;AAAA,EACjB,WAAAlR,IAAY;AAAA,EACZ,cAAAmR,IAAe;AAAA,EACf,iBAAA5H;AAAA,EACA,kBAAA6H;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,UAAAC,IAAW;AAAA,EACX,aAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,iBAAAC,KAAkB;AAAA,EAClB,UAAAC,IAAW;AAAA,EACX,cAAA7d;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAU;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,0BAAAC;AAAA,EACA,eAAAC;AAAA,EACA,cAAA8c;AAAA,EACA,cAAArd;AAAA,EACA,kBAAAU;AAAA,EACA,oBAAA4c;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,eAAAC;AAAA,EACA,eAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,gBAAAje;AAAA,EACA,iBAAAC;AAAA,EACA,iBAAAie,IAAkB;AAAA,EAClB,oBAAAC;AAAA,EACA,WAAAld;AAAA,EACA,OAAAtE;AACF,GAA6C;AAC3C,QAAMuE,KAAYC,EAAiC,IAAI,GACjDsK,IAActK,EAA+B,IAAI,GACjDid,KAAoBjd,EAA4B,IAAI,GACpDkd,KAAwBld,EAA4B,IAAI,GACxDmd,KAAuBnd,EAAiCmb,CAAiB,GACzEiC,IAAapd,EAAuBob,CAAO,GAC3CiC,KAAkBrd,EAAOuD,CAAY,GACrC,CAAC+Z,IAAgBC,EAAiB,IAAIC,GAAS,EAAI,GACnD,CAAC9d,IAAiB+d,EAAkB,IAAID,GAAiC,IAAI,GAC7E,CAAC7d,IAAgB+d,EAAiB,IAAIF,GAAiC,IAAI,GAC3E,CAACG,IAAsBC,EAAuB,IAAIJ,GAA8B,IAAI,GACpF,CAACK,GAAYC,CAAa,IAAIN,GAAgC,IAAI,GAClEO,IAAqB/d,EAA+B,IAAI,GACxDge,IAAuBhe,EAAsB,IAAI,GACjDie,IAAoBje,EAAsB,IAAI,GAC9Cke,IAAele,EAAO,CAAC,GACvBme,IAAiBrC,KAAclC,IAC/BwE,IAAmBlf,KAAgB0a,IACnCyE,IAAkBtC,KAAelC,IACjCyE,MAAmC/B,GAAc,UAAU,KAAK,GAEhEnb,KAAcb,EAAuB,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,GAAG/E,GAAA,IAAU,CAACA,EAAK,CAAC,GACvH+iB,KAA0Bhe;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,GAAGib;AAAA,IAAA;AAAA,IAEL,CAACA,CAAiB;AAAA,EAAA,GAGdgD,KAAsBje,EAAqB,MAC3C4d,EAAe,SAAS,IACnBA,IAELE,EAAgB,WAAW,IACtBzE,KAEFyE,EAAgB,IAAI,CAACtxB,GAAayT,OAAW;AAAA,IAClD,IAAIA;AAAA,IACJ,aAAAzT;AAAA,EAAA,EACA,GACD,CAACoxB,GAAgBE,CAAe,CAAC,GAC9BI,KAAqBle,EAAQ,MAAMya,GAAkBwD,EAAmB,GAAG,CAACA,EAAmB,CAAC,GAEhGE,KAAene;AAAA,IACnB,MAAMie,GAAoB,IAAI,CAAA7d,MAAUA,EAAO,WAAyB;AAAA,IACxE,CAAC6d,EAAmB;AAAA,EAAA,GAGhB,CAACG,IAAiBC,EAAkB,IAAIpB,GAA8B/S,CAAS;AAErF,EAAAnF,EAAU,MAAM;AACd,UAAMuZ,IAAQ,EAAEX,EAAa;AAC7B,QAAIzU,IAAY;AAEhB,QAAI,CAACuS;AACH,aAAA4C,GAAmBnU,CAAS,GACrB,MAAM;AACX,QAAAhB,IAAY;AAAA,MACd;AAGF,QAAI,CAACgB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,aAAAmU,GAAmB,IAAI,GAChB,MAAM;AACX,QAAAnV,IAAY;AAAA,MACd;AAGF,QAAIiV,GAAa,WAAW;AAC1B,aAAAE,GAAmB9E,EAAoB,GACvCoC,IAAc;AAAA,QACZ,MAAMD;AAAA,QACN,YAAY;AAAA,QACZ,YAAYxR,EAAU;AAAA,QACtB,aAAa;AAAA,QACb,cAAc;AAAA,MAAA,CACf,GACM,MAAM;AACX,QAAAhB,IAAY;AAAA,MACd;AAGF,UAAMqV,IAAc,CAAC5Q,GAA2B6Q,OAAoF;AAClI,UAAItV,KAAaoV,MAAUX,EAAa,QAAS;AACjD,YAAMc,KAAc9Q,GAAM,cAAcA,EAAK,YAAY,SAAUA,GAAM,SAAS;AAClF,MAAA0Q,GAAmB1Q,CAAI,GACvBgO,IAAc;AAAA,QACZ,MAAM6C,GAAM;AAAA,QACZ,YAAYA,GAAM;AAAA,QAClB,YAAYtU,EAAU;AAAA,QACtB,aAAAuU;AAAA,QACA,cAAcN,GAAa;AAAA,QAC3B,YAAYK,GAAM;AAAA,QAClB,gBAAgBA,GAAM;AAAA,QACtB,eAAeA,GAAM;AAAA,MAAA,CACtB;AAAA,IACH;AAyCA,YAvCY,YAA2B;AACrC,UAAI9C,MAAa,QAAQ;AACvB,cAAMzpB,IAAQ,YAAY,IAAA,GACpB0b,KAAOxD,GAA0BD,GAAWiU,EAAY;AAC9D,QAAAI,EAAY5Q,IAAM;AAAA,UAChB,MAAM;AAAA,UACN,YAAY,YAAY,QAAQ1b;AAAA,QAAA,CACjC;AACD;AAAA,MACF;AAEA,UAAIypB,MAAa,iBAAiB;AAChC,cAAMrX,IAAS,MAAM6I,GAAgChD,GAAWiU,IAAc,EAAE,cAAc,IAAM;AACpG,QAAAI,EAAYla,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,MAAMyK,GAAkC5E,GAAWiU,EAAY;AAC9E,QAAAI,EAAYla,EAAO,MAAM;AAAA,UACvB,MAAMA,EAAO,KAAK;AAAA,UAClB,YAAYA,EAAO,KAAK;AAAA,QAAA,CACzB;AAAA,MACH,QAAQ;AACN,cAAMpS,IAAQ,YAAY,IAAA,GACpB0b,KAAOxD,GAA0BD,GAAWiU,EAAY;AAC9D,QAAAI,EAAY5Q,IAAM;AAAA,UAChB,MAAM;AAAA,UACN,YAAY,YAAY,QAAQ1b;AAAA,QAAA,CACjC;AAAA,MACH;AAAA,IACF,GAEK,GACE,MAAM;AACX,MAAAiX,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACuS,GAAkBC,GAAUxR,GAAWiU,IAAcxC,CAAW,CAAC;AAErE,QAAM+C,KAA2B,GAAQxC,KAAgBC,MAAgBI,KACnEoC,KAAoB3e,EAAQ,MAC3B0e,KACE1E,GAAuBoE,IAAiBr2B,CAAM,IADf,MAErC,CAAC22B,IAA0BN,IAAiBr2B,CAAM,CAAC,GAEhD62B,KAAuB7d;AAAA,IAC3B,CAAC8d,MAAqD;AACpD,YAAM7U,IAAWD,EAAY;AAC7B,UAAI,CAACC,KAAY,CAAC2U,GAAmB,QAAO;AAE5C,YAAMjyB,IAAI,OAAOmyB,EAAW,CAAC,CAAC,GACxBlyB,IAAI,OAAOkyB,EAAW,CAAC,CAAC;AAC9B,UAAI,CAAC,OAAO,SAASnyB,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,EAAG,QAAO;AAEvD,YAAMtB,IAAO,KAAK,IAAI,MAAM2e,EAAS,aAAA,EAAe,IAAI,GAClD8U,KAAc9U,EAAS,mBAAA,GAEvB+U,KADc,KAAK,IAAItF,IAAyBqF,KAActF,EAAsB,IACrDnuB;AACrC,UAAI,CAAC,OAAO,SAAS0zB,EAAc,KAAKA,MAAkB,EAAG,QAAO;AAEpE,YAAM9E,KAAW0E,GAAkB,UAC7BK,KAAY,KAAK,MAAMtyB,IAAIutB,EAAQ,GACnCgF,KAAY,KAAK,MAAMtyB,IAAIstB,EAAQ,GACnCiF,KAAa,KAAK,IAAI,GAAG,KAAK,KAAKH,KAAiB9E,EAAQ,CAAC,GAC7D9nB,KAAW4sB,KAAiBA;AAElC,UAAII,KAAe,IACfC,KAAejtB,IACfktB,KAAW,GACXC,KAAW;AAEf,eAASC,KAAKP,KAAYE,IAAYK,MAAMP,KAAYE,IAAYK,MAAM,GAAG;AAC3E,cAAMjF,KAASqE,GAAkB,QAAQ,IAAIY,EAAE;AAC/C,YAAKjF;AAEL,mBAASkF,KAAKP,KAAYC,IAAYM,MAAMP,KAAYC,IAAYM,MAAM,GAAG;AAC3E,kBAAMjF,KAASD,GAAO,IAAIkF,EAAE;AAC5B,gBAAI,GAACjF,MAAUA,GAAO,WAAW;AAEjC,uBAASzrB,KAAI,GAAGA,KAAIyrB,GAAO,QAAQzrB,MAAK,GAAG;AACzC,sBAAMgf,KAAayM,GAAOzrB,EAAC;AAC3B,oBAAIgf,MAAc6Q,GAAkB,UAAW;AAE/C,sBAAMviB,KAAKuiB,GAAkB,UAAU7Q,KAAa,CAAC,GAC/CzR,KAAKsiB,GAAkB,UAAU7Q,KAAa,IAAI,CAAC,GACnDpc,KAAK0K,KAAK1P,GACViF,KAAK0K,KAAK1P,GACV0F,KAAQX,KAAKA,KAAKC,KAAKA;AAC7B,gBAAIU,KAAQ+sB,OAEZA,KAAe/sB,IACf8sB,KAAerR,IACfuR,KAAWjjB,IACXkjB,KAAWjjB;AAAA,cACb;AAAA,UACF;AAAA,MACF;AAEA,UAAI8iB,KAAe,EAAG,QAAO;AAC7B,YAAMM,KAAUd,GAAkB,MAAM,OAAOA,GAAkB,IAAIQ,EAAY,CAAC,IAAI;AACtF,aAAO;AAAA,QACL,OAAOA;AAAA,QACP,IAAIM;AAAA,QACJ,YAAY,CAAC/yB,GAAGC,CAAC;AAAA,QACjB,iBAAiB,CAAC0yB,IAAUC,EAAQ;AAAA,MAAA;AAAA,IAExC;AAAA,IACA,CAACX,EAAiB;AAAA,EAAA,GAGde,KAAiB3e;AAAA,IACrB,CAAC4e,GAA2Bd,MAAsC;AAChE,UAAI,CAAC3C,EAAc;AACnB,YAAM0D,IAAYD,GAAK,SAAS,MAC1BE,IAASF,GAAK,MAAM;AAC1B,MAAIlC,EAAqB,YAAYmC,KAAalC,EAAkB,YAAYmC,MAChFpC,EAAqB,UAAUmC,GAC/BlC,EAAkB,UAAUmC,GAC5B3D,EAAa;AAAA,QACX,OAAO0D;AAAA,QACP,IAAIC;AAAA,QACJ,YAAAhB;AAAA,QACA,iBAAiBc,GAAK,mBAAmB;AAAA,MAAA,CAC1C;AAAA,IACH;AAAA,IACA,CAACzD,CAAY;AAAA,EAAA,GAGT4D,KAAiB/e;AAAA,IACrB,CAAC8d,GAA4BkB,MAAmB;AAC9C,UAAI,CAAC5D,GAAc;AACnB,YAAMwD,IAAMf,GAAqBC,CAAU;AAC3C,MAAKc,KACLxD,GAAa;AAAA,QACX,GAAGwD;AAAA,QACH,QAAAI;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC5D,IAAcyC,EAAoB;AAAA,EAAA;AAGf,EAAA5e,EAAQ,MAAM;AAClC,UAAM5T,IAAQ,OAAOqwB,GAAoB,SAAS,GAAG;AACrD,WAAO,OAAO,SAASrwB,CAAK,IAAI,KAAK,IAAI,IAAIA,CAAK,IAAI;AAAA,EACxD,GAAG,CAACqwB,GAAoB,KAAK,CAAC;AAC9B,QAAMuD,KAAiBhgB,EAAQ,MAAM;AACnC,UAAM5T,IAAQ,OAAOqwB,GAAoB,UAAU,GAAG;AACtD,WAAO,OAAO,SAASrwB,CAAK,IAAI,KAAK,IAAI,IAAIA,CAAK,IAAI;AAAA,EACxD,GAAG,CAACqwB,GAAoB,MAAM,CAAC,GACzBwD,KAAiBjgB,EAAQ,MAAM;AACnC,UAAM5T,IAAQ,OAAOqwB,GAAoB,UAAU,EAAE;AACrD,WAAO,OAAO,SAASrwB,CAAK,IAAI,KAAK,IAAI,GAAGA,CAAK,IAAI;AAAA,EACvD,GAAG,CAACqwB,GAAoB,MAAM,CAAC,GACzByD,KAAmBzD,GAAoB,YAAY;AAEzD,EAAA1X,EAAU,MAAM;AACd,QAAKwX;AACL,aAAAA,GAAwB,UAAUqC,IAC3B,MAAM;AACX,QAAIrC,GAAwB,YAAYqC,OACtCrC,GAAwB,UAAU;AAAA,MAEtC;AAAA,EACF,GAAG,CAACA,IAAyBqC,EAAoB,CAAC;AAElD,QAAMuB,KAAqBpf;AAAA,IACzB,CAAC7X,MAAiC;AAChC,MAAAi0B,GAAkB,CAAAlwB,MACZ,OAAOA,CAAI,MAAM,OAAO/D,CAAI,IACvB+D,KAETqvB,KAAuBpzB,CAAI,GACpBA,EACR;AAAA,IACH;AAAA,IACA,CAACozB,EAAoB;AAAA,EAAA;AAGvB,EAAAvX,EAAU,MAAM;AACd,IAAA6X,GAAqB,UAAUhC;AAAA,EACjC,GAAG,CAACA,CAAiB,CAAC,GAEtB7V,EAAU,MAAM;AACd,IAAA8X,EAAW,UAAUhC;AAAA,EACvB,GAAG,CAACA,CAAO,CAAC,GAEZ9V,EAAU,MAAM;AACd,IAAA+X,GAAgB,UAAU9Z,GACrBA,KAAcua,EAAc,IAAI;AAAA,EACvC,GAAG,CAACva,CAAY,CAAC;AAEjB,QAAMod,KAAsBrf,EAAY,CAACyd,MAAgC;AACvE,IAAA3B,EAAW,UAAU2B,CAAK,GACtB1B,GAAgB,WAClBS,EAAciB,CAAK;AAAA,EAEvB,GAAG,CAAA,CAAE,GAEC6B,KAAmBrgB,EAAQ,MAC1Bsd,IAGE;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,IARF,qCASR,CAACA,CAAU,CAAC;AAEf,EAAAvY,EAAU,MAAM;AAEd,IAAI,EADc3F,OAAmB,OAAO,KAAO6e,GAAoB,KAAK,CAAC7d,GAAQH,MAAU,OAAOua,GAAgBpa,GAAQH,CAAK,CAAC,MAAM,OAAOb,EAAc,CAAC,MAC9IA,OAAmB,QACnC+gB,GAAmB,IAAI;AAGzB,UAAMG,IAAe9C,EAAmB;AAGxC,IAAI,EAFa8C,MAAiB,OAAO,KAAOrC,GAAoB,KAAK,CAAC7d,GAAQH,MAAU,OAAOua,GAAgBpa,GAAQH,CAAK,CAAC,MAAM,OAAOqgB,CAAY,CAAC,MAE1IA,MAAiB,SAChC9C,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb;AAAA,EAEL,GAAG,CAAC6B,IAAqB7e,IAAgBgd,IAAe+D,EAAkB,CAAC,GAE3Epb,EAAU,MAAM;AACd,UAAMwb,IAAoB9C,EAAqB;AAC/C,IAAI8C,MAAsB,SACtB5B,MAAqB4B,IAAoB5B,GAAkB,cAC/DlB,EAAqB,UAAU,MAC/BC,EAAkB,UAAU,MAC5BxB,IAAe;AAAA,MACb,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,iBAAiB;AAAA,IAAA,CAClB;AAAA,EACH,GAAG,CAACyC,IAAmBzC,CAAY,CAAC;AAEpC,QAAMsE,KAAsBzf;AAAA,IAC1B,CAAC7X,MAA6B;AAC5B,MAAI60B,MACFV,GAAwBn0B,CAAI;AAE9B,YAAMu3B,IAAW7D,GAAqB;AACtC,MAAI6D,KACFA,EAASv3B,CAAI,GAEfwzB,GAAkB,UAAA,GAClBC,GAAsB,UAAA;AAAA,IACxB;AAAA,IACA,CAACoB,EAA+B;AAAA,EAAA;AAGlC,EAAAhZ,EAAU,MAAM;AACd,QAAI,CAACyX,GAAiB;AACpB,MAAAQ,GAAkB,EAAK;AACvB;AAAA,IACF;AACA,IAAAA,GAAkB,EAAI;AAAA,EACxB,GAAG,CAACR,GAAiBz0B,GAAQ,EAAE,CAAC,GAEhCgd,EAAU,MAAM;AACd,IAAIgX,MAAa,YACbyB,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb;AAAA,EACH,GAAG,CAACL,GAAUK,EAAa,CAAC,GAE5BrX,EAAU,MAAM;AACd,IAAIgX,MAAa,YACb0B,EAAqB,YAAY,SACrCA,EAAqB,UAAU,MAC/BC,EAAkB,UAAU,MAC5BxB,IAAe;AAAA,MACb,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,iBAAiB;AAAA,IAAA,CAClB;AAAA,EACH,GAAG,CAACH,GAAUG,CAAY,CAAC;AAE3B,QAAMwE,KAAoB3f,EAAY,CAACyH,GAAiBC,MAA2C;AACjG,UAAMuB,IAAWD,EAAY;AAC7B,QAAI,CAACC,EAAU,QAAO;AACtB,UAAMhG,IAAMgG,EAAS,cAAcxB,GAASC,CAAO;AACnD,QAAI,CAAC,MAAM,QAAQzE,CAAG,KAAKA,EAAI,SAAS,EAAG,QAAO;AAClD,UAAMtX,IAAI,OAAOsX,EAAI,CAAC,CAAC,GACjBrX,KAAI,OAAOqX,EAAI,CAAC,CAAC;AACvB,WAAI,CAAC,OAAO,SAAStX,CAAC,KAAK,CAAC,OAAO,SAASC,EAAC,IAAU,OAChD,CAACD,GAAGC,EAAC;AAAA,EACd,GAAG,CAAA,CAAE,GAECg0B,KAAqB5f,EAAY,CAAC8H,GAAgBC,MAA0C;AAChG,UAAMkB,IAAWD,EAAY;AAC7B,QAAI,CAACC,EAAU,QAAO;AACtB,UAAMhG,IAAMgG,EAAS,cAAcnB,GAAQC,CAAM;AACjD,QAAI,CAAC,MAAM,QAAQ9E,CAAG,KAAKA,EAAI,SAAS,EAAG,QAAO;AAClD,UAAMtX,IAAI,OAAOsX,EAAI,CAAC,CAAC,GACjBrX,KAAI,OAAOqX,EAAI,CAAC,CAAC;AACvB,WAAI,CAAC,OAAO,SAAStX,CAAC,KAAK,CAAC,OAAO,SAASC,EAAC,IAAU,OAChD,CAACD,GAAGC,EAAC;AAAA,EACd,GAAG,CAAA,CAAE,GAECi0B,KAA2B7f,EAAY,MAAM;AACjD,IAAAgJ,EAAY,SAAS,cAAA,GACrB2S,GAAkB,UAAA,GAClBC,GAAsB,UAAA;AAAA,EACxB,GAAG,CAAA,CAAE,GAECkE,KAAgC7gB,EAA6B,MAC1Dod,MAAwBrT,EAAY,SAAS,aAAA,KAAkB,MACrE,CAACqT,EAAoB,CAAC,GAEnB0D,KAAqB9gB,EAAsC,MAAM;AACrE,QAAI,CAACjY,EAAQ,QAAO;AACpB,UAAMg5B,IAAoBF;AAC1B,WAAKE,IACE;AAAA,MACL,QAAAh5B;AAAA,MACA,WAAWg5B;AAAA,MACX,UAAAhF;AAAA,MACA,iBAAAD;AAAA,MACA,eAAe6E;AAAA,MACf,eAAeD;AAAA,MACf,eAAeE;AAAA,IAAA,IARc;AAAA,EAUjC,GAAG,CAAC74B,GAAQ84B,IAA+B9E,GAAUD,IAAiB6E,IAAoBD,IAAmBE,EAAwB,CAAC,GAEhII,KAA0BjgB;AAAA,IAC9B,CAACgD,MAA6C;AAC5C,YAAMkd,IAAgBld,EAAM,WAAWvE,GAAU,SAC3C3B,IAAQ6iB,GAAkB3c,EAAM,SAASA,EAAM,OAAO;AAC5D,UAAIkY,GAAoB;AACtB,cAAMiF,KAAc,CAAC,CAACrjB,KAASA,EAAM,CAAC,KAAK,KAAKA,EAAM,CAAC,KAAK,KAAK,CAAC,CAAC9V,KAAU8V,EAAM,CAAC,KAAK9V,EAAO,SAAS8V,EAAM,CAAC,KAAK9V,EAAO;AAC5H,QAAAk0B,EAAmB;AAAA,UACjB,YAAYpe;AAAA,UACZ,SAASkG,EAAM;AAAA,UACf,SAASA,EAAM;AAAA,UACf,aAAAmd;AAAA,QAAA,CACD;AAAA,MACH;AAEA,UAAInF,MAAa,SAAU;AAC3B,UAAI,CAACkF,GAAe;AAClB,QAAAvB,GAAe,MAAM,IAAI,GACrBlC,EAAmB,YAAY,SACjCA,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,UACd,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,aAAa;AAAA,UACb,YAAY;AAAA,QAAA,CACb;AAEH;AAAA,MACF;AACA,UAAI,CAACve,GAAO;AACV,QAAA6hB,GAAe,MAAM,IAAI;AACzB;AAAA,MACF;AAKA,UAHIxD,KACFwD,GAAed,GAAqB/gB,CAAK,GAAGA,CAAK,GAE/C,CAACqgB,GAAmB,OAAQ;AAEhC,YAAMyB,IAAMjF,GAAqB7c,GAAOqgB,EAAkB,GACpDiD,IAAcxB,GAAK,YAAY,MAC/ByB,KAAc5D,EAAmB;AACvC,MAAI,OAAO4D,EAAW,MAAM,OAAOD,CAAW,MAE9C3D,EAAmB,UAAU2D,GAC7BjE,GAAmBiE,CAAW,GAC9B/E,KAAgB;AAAA,QACd,QAAQuD,GAAK,UAAU;AAAA,QACvB,UAAUwB;AAAA,QACV,aAAaxB,GAAK,eAAe;AAAA,QACjC,YAAY9hB;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,CAACke,GAAUmC,IAAoBwC,IAAmBtE,IAAeH,GAAoBl0B,GAAQ23B,IAAgBd,IAAsB1C,CAAY;AAAA,EAAA,GAG3ImF,KAA2BtgB,EAAY,MAAM;AAQjD,IAPAkb,IAAqB;AAAA,MACnB,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,aAAa;AAAA,IAAA,CACd,GACDyD,GAAe,MAAM,IAAI,GACrBlC,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb;AAAA,EACH,GAAG,CAACA,IAAeH,GAAoByD,EAAc,CAAC,GAEhD4B,KAAoBvgB;AAAA,IACxB,CAACgD,MAA2C;AAE1C,UADIgY,MAAa,YACbhY,EAAM,WAAWvE,GAAU,QAAS;AAExC,YAAM3B,IAAQ6iB,GAAkB3c,EAAM,SAASA,EAAM,OAAO;AAC5D,UAAI,CAAClG,EAAO;AAGZ,UAFAiiB,GAAejiB,GAAOkG,EAAM,MAAM,GAE9B,CAACma,GAAmB,QAAQ;AAC9B,QAAAiC,GAAmB,IAAI;AACvB;AAAA,MACF;AAEA,YAAMR,IAAMjF,GAAqB7c,GAAOqgB,EAAkB;AAC1D,UAAI,CAACyB,GAAK;AACR,QAAAQ,GAAmB,IAAI;AACvB;AAAA,MACF;AAEA,YAAMoB,IAAqCniB,OAAmB,QAAQ,OAAOA,EAAc,MAAM,OAAOugB,EAAI,QAAQ,IAAI,OAAOA,EAAI;AACnI,MAAAQ,GAAmBoB,CAAU,GAC7BlF,KAAgB;AAAA,QACd,QAAQsD,EAAI;AAAA,QACZ,UAAUA,EAAI;AAAA,QACd,aAAaA,EAAI;AAAA,QACjB,YAAY9hB;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,CAACke,GAAUmC,IAAoBwC,IAAmBrE,IAAejd,IAAgB+gB,IAAoBL,EAAc;AAAA,EAAA,GAG/G0B,KAAiBzgB;AAAA,IACrB,CAAClD,MAAmC;AAGlC,UAFIke,MAAa,WACb5d,IAAc,mBAAmB,MACjC,CAAC+f,GAAmB,OAAQ,QAAO;AAEvC,YAAMyB,IAAMjF,GAAqB7c,GAAOqgB,EAAkB;AAC1D,UAAI,CAACyB,EAAK,QAAO;AAEjB,YAAM4B,IAAqCniB,OAAmB,QAAQ,OAAOA,EAAc,MAAM,OAAOugB,EAAI,QAAQ,IAAI,OAAOA,EAAI;AACnI,aAAAQ,GAAmBoB,CAAU,GAC7BlF,KAAgB;AAAA,QACd,QAAQsD,EAAI;AAAA,QACZ,UAAUA,EAAI;AAAA,QACd,aAAaA,EAAI;AAAA,QACjB,YAAY9hB;AAAA,MAAA,CACb,GACM;AAAA,IACT;AAAA,IACA,CAACke,GAAU5d,IAAc,gBAAgB+f,IAAoB9e,IAAgB+gB,IAAoB9D,EAAa;AAAA,EAAA,GAG1GoF,KAA0B1gB;AAAA,IAC9B,CAACgD,MAA2C;AAG1C,UAFI,CAACoY,MACDJ,MAAa,YACbhY,EAAM,WAAWvE,GAAU,QAAS;AACxC,MAAAuE,EAAM,eAAA;AACN,YAAMlG,IAAQ6iB,GAAkB3c,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKlG,KACLiiB,GAAejiB,GAAOkG,EAAM,MAAM;AAAA,IACpC;AAAA,IACA,CAACgY,GAAU2E,IAAmBZ,IAAgB3D,EAAY;AAAA,EAAA;AAG5D,SAAApX,EAAU,MAAM;AACd,UAAMnc,IAAS4W,GAAU;AACzB,QAAI,CAAC5W,KAAU,CAACb;AACd;AAGF,UAAMiiB,IAAW,IAAIoK,GAAgBxrB,GAAQb,GAAQ;AAAA,MACnD,mBAAmBy4B;AAAA,MACnB,SAASJ;AAAA,MACT,aAAAtF;AAAA,MACA,eAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,WAAAtU;AAAA,MACA,gBAAA0U;AAAA,MACA,iBAAA3H;AAAA,MACA,kBAAA6H;AAAA,IAAA,CACD;AAED,WAAAvR,EAAY,UAAUC,GAClBxf,KACFwf,EAAS,aAAaxf,CAAS,GAEjCwf,EAAS,mBAAmB8R,EAAe,GACvCiC,MACFV,GAAwBrT,EAAS,cAAc,GAG1C,MAAM;AACX,MAAAA,EAAS,QAAA,GACTD,EAAY,UAAU;AAAA,IACxB;AAAA,EACF,GAAG,CAAChiB,GAAQq4B,IAAqBtF,GAAaC,GAAeC,GAAmBtU,GAAW0U,GAAgB3H,GAAiB6H,GAAkBkF,IAAqBzC,EAA+B,CAAC,GAEnMhZ,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACxf,KAGlBwf,EAAS,aAAaxf,CAAS;AAAA,EACjC,GAAG,CAACA,CAAS,CAAC,GAEdua,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,WAAA;AAAA,EACX,GAAG,CAACkR,CAAQ,CAAC,GAEbnW,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KACLA,EAAS,cAAA;AAAA,EACX,GAAG,CAACmR,CAAkB,CAAC,GAEvBpW,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACqR,KAGlBrR,EAAS,gBAAgBqR,CAAY;AAAA,EACvC,GAAG,CAACA,CAAY,CAAC,GAEjBtW,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,mBAAmByJ,CAAe;AAAA,EAC7C,GAAG,CAACA,CAAe,CAAC,GAEpB1O,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KACLA,EAAS,oBAAoBsR,CAAgB;AAAA,EAC/C,GAAG,CAACA,CAAgB,CAAC,GAErBvW,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,aAAaoU,EAAe;AAAA,EACvC,GAAG,CAACA,EAAe,CAAC,GAEpBrZ,EAAU,MAAM;AACd,QAAI,CAAC6W,GAAkB;AAEvB,UAAM4C,IAAQ1O,GADO2L,IAAmB2C,KAAkBlU,GACR+T,IAAqB;AAAA,MACrE,sBAAsBpC;AAAA,MACtB,qBAAqB;AAAA,IAAA,CACtB;AACD,IAAAD,GAAiB4C,CAAK;AAAA,EACxB,GAAG,CAAC5C,IAAkBH,GAAkBvR,GAAWkU,IAAiBH,IAAqBpC,EAAuB,CAAC,GAEjH9W,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,mBAAmB8R,EAAe;AAAA,EAC7C,GAAG,CAACA,EAAe,CAAC,GAGlB,gBAAA4F,GAAC,OAAA,EAAI,WAAAniB,IAAsB,OAAOsB,IAAa,eAAemgB,IAAyB,gBAAgBK,IAA0B,SAASC,IAAmB,eAAeG,IAC1K,UAAA;AAAA,IAAA,gBAAAvc;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK1F;AAAA,QACL,WAAU;AAAA,QACV,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,aAAa;AAAA,UACb,QAAQuc,MAAa,YAAY5c,OAAoB,OAAO,YAAY2c,KAAkB,cAAc;AAAA,QAAA;AAAA,MAC1G;AAAA,IAAA;AAAA,IAED/zB,KAAU+4B,MAAsB,MAAM,QAAQ9E,CAAY,KAAKA,EAAa,SAAS,IAClFA,EAAa,IAAI,CAAC2F,GAAO1hB,MACvB,gBAAAiF;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAWyc,EAAM;AAAA,QACjB,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQA,EAAM,UAAU;AAAA,UACxB,eAAeA,EAAM,iBAAiB;AAAA,UACtC,GAAGA,EAAM;AAAA,QAAA;AAAA,QAGV,UAAAA,EAAM,OAAOb,EAAkB;AAAA,MAAA;AAAA,MAV3Ba,EAAM,MAAM1hB;AAAA,IAAA,CAYpB,IACD;AAAA,IACHlY,IACC,gBAAAmd;AAAA,MAACjH;AAAA,MAAA;AAAA,QACC,MAAM8d;AAAA,QACN,SAASA,MAAa;AAAA,QACtB,YAAYh0B,EAAO;AAAA,QACnB,aAAaA,EAAO;AAAA,QACpB,UAAUA,EAAO;AAAA,QACjB,WAAWA,EAAO;AAAA,QAClB,cAAAmW;AAAA,QACA,cAAAC;AAAA,QACA,cAAc4L;AAAA,QACd,YAAYyX;AAAA,QACZ,iBAAiBh3B;AAAA,QACjB,kBAAkByzB;AAAA,QAClB,cAAcJ;AAAA,QACd,mBAAAhf;AAAA,QACA,wBAAAC;AAAA,QACA,yBAAAC;AAAA,QACA,kBAAAC;AAAA,QACA,0BAAAC;AAAA,QACA,eAAAC;AAAA,QACA,iBAAAC;AAAA,QACA,gBAAAC;AAAA,QACA,kBAAAC;AAAA,QACA,eAAeqd;AAAA,QACf,gBAAApe;AAAA,QACA,iBAAAC;AAAA,MAAA;AAAA,IAAA,IAEA;AAAA,IACHyE,uBACE,OAAA,EAAI,iCAA6B,IAAC,OAAOgb,IACvC,cACH,IACE;AAAA,IACHj2B,KAAUy0B,IACTO,KACE,gBAAA2E,GAAAE,IAAA,EACE,UAAA;AAAA,MAAA,gBAAA1c,GAACuB,IAAA,EAAY,QAAA1e,GAAgB,cAAcgiB,GAAa,WAAArD,GAAsB,SAAS+V,GAAoB,eAAeE,GAAA,CAAuB;AAAA,MACjJ,gBAAAzX;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAW;AAAA,UACX,SAAS,MAAM8X,GAAkB,EAAK;AAAA,UACtC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,GAAIkD,GAAiB,SAAS,MAAM,IAAI,EAAE,MAAMD,GAAA,IAAmB,EAAE,OAAOA,GAAA;AAAA,YAC5E,GAAIC,GAAiB,SAAS,KAAK,IAAI,EAAE,KAAKD,KAAiBD,KAAiB,MAAM,EAAE,QAAQC,KAAiBD,KAAiB,EAAA;AAAA,YAClI,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,UAAU;AAAA,YACV,YAAY;AAAA,YACZ,QAAQ;AAAA,YACR,SAAS;AAAA,UAAA;AAAA,UAEZ,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACF,IAEA,gBAAA9a;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,MAAM8X,GAAkB,EAAI;AAAA,QACrC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,GAAIkD,GAAiB,SAAS,MAAM,IAAI,EAAE,MAAMD,GAAA,IAAmB,EAAE,OAAOA,GAAA;AAAA,UAC5E,GAAIC,GAAiB,SAAS,KAAK,IAAI,EAAE,KAAKD,GAAA,IAAmB,EAAE,QAAQA,GAAA;AAAA,UAC3E,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,cAAc;AAAA,UACd,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,SAAS;AAAA,QAAA;AAAA,QAEZ,UAAA;AAAA,MAAA;AAAA,IAAA,IAID;AAAA,EAAA,GACN;AAEJ;"}
|