{"version":3,"file":"viz.mjs","sources":["../src/viz/font.ts","../src/viz/color.ts","../src/viz/ocr/draw-boxes.ts","../src/viz/ocr/draw-text.ts","../src/viz/canvas-factory.ts","../src/viz/ocr/side-by-side.ts","../src/viz/ocr/renderer.ts"],"sourcesContent":["import type { FontConfig } from \"./types\";\n\nexport async function loadFontFace(config: FontConfig): Promise<FontFace> {\n  const source = typeof config.source === \"string\" ? `url(${config.source})` : config.source;\n\n  const face = new FontFace(config.family, source, config.descriptors);\n  await face.load();\n  document.fonts.add(face);\n  return face;\n}\n\nexport function removeFontFace(face: FontFace): void {\n  document.fonts.delete(face);\n}\n","import type { RgbColor } from \"./types\";\n\nexport function deterministicColor(index: number): RgbColor {\n  let seed = (index + 1) * 1103515245 + 12345;\n  seed >>>= 0;\n  const r = (seed >> 16) & 0xff;\n  seed = (seed * 1103515245 + 12345) >>> 0;\n  const g = (seed >> 16) & 0xff;\n  seed = (seed * 1103515245 + 12345) >>> 0;\n  const b = (seed >> 16) & 0xff;\n  return [r, g, b];\n}\n","import type { OcrResultItem } from \"../../pipelines/ocr/core\";\nimport type { Point2D } from \"../../models/common\";\nimport type { RgbColor } from \"../types\";\nimport type { BoxStyleOptions } from \"./types\";\nimport { deterministicColor } from \"../color\";\n\nconst DEFAULT_FILL_OPACITY = 0.5;\n\ntype DrawableImage = ImageBitmap | HTMLImageElement;\n\nfunction drawPolygonPath(\n  ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n  poly: Point2D[]\n): void {\n  ctx.beginPath();\n  ctx.moveTo(poly[0][0], poly[0][1]);\n  for (let i = 1; i < poly.length; i += 1) {\n    ctx.lineTo(poly[i][0], poly[i][1]);\n  }\n  ctx.closePath();\n}\n\nexport function drawBoxesPanel(\n  ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n  image: DrawableImage,\n  items: OcrResultItem[],\n  style: BoxStyleOptions\n): void {\n  const fillOpacity = style.fillOpacity ?? DEFAULT_FILL_OPACITY;\n  const getColor = style.colorFn ?? deterministicColor;\n\n  // Draw original image\n  ctx.drawImage(image, 0, 0);\n\n  // Draw filled polygons with the specified opacity.\n  // Canvas source-over compositing with alpha gives:\n  //   result = color * alpha + original * (1 - alpha)\n  for (let i = 0; i < items.length; i += 1) {\n    const [r, g, b]: RgbColor = getColor(i);\n    ctx.save();\n    ctx.fillStyle = `rgba(${String(r)}, ${String(g)}, ${String(b)}, ${String(fillOpacity)})`;\n    drawPolygonPath(ctx, items[i].poly);\n    ctx.fill();\n    ctx.restore();\n  }\n}\n","import type { OcrResultItem } from \"../../pipelines/ocr/core\";\nimport type { Point2D } from \"../../models/common\";\nimport type { RgbColor } from \"../types\";\nimport type { BoxStyleOptions } from \"./types\";\nimport { deterministicColor } from \"../color\";\n\nconst DEFAULT_BG = \"#ffffff\";\nconst OUTLINE_LINE_WIDTH = 1;\nconst TEXT_COLOR = \"#000000\";\nconst ROTATION_THRESHOLD_DEG = 5;\nconst VERTICAL_LINE_SPACING = 2;\n\nfunction topEdgeAngle(poly: Point2D[]): number {\n  const dx = poly[1][0] - poly[0][0];\n  const dy = poly[1][1] - poly[0][1];\n  return Math.atan2(dy, dx);\n}\n\nfunction polyBounds(poly: Point2D[]): {\n  minX: number;\n  minY: number;\n  maxX: number;\n  maxY: number;\n  width: number;\n  height: number;\n} {\n  let minX = Infinity;\n  let minY = Infinity;\n  let maxX = -Infinity;\n  let maxY = -Infinity;\n  for (const [x, y] of poly) {\n    if (x < minX) minX = x;\n    if (y < minY) minY = y;\n    if (x > maxX) maxX = x;\n    if (y > maxY) maxY = y;\n  }\n  return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY };\n}\n\nfunction drawPolygonPath(\n  ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n  poly: Point2D[],\n  offsetX: number\n): void {\n  ctx.beginPath();\n  ctx.moveTo(poly[0][0] + offsetX, poly[0][1]);\n  for (let i = 1; i < poly.length; i += 1) {\n    ctx.lineTo(poly[i][0] + offsetX, poly[i][1]);\n  }\n  ctx.closePath();\n}\n\nfunction drawVerticalText(\n  ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n  text: string,\n  x: number,\n  startY: number,\n  fontSize: number,\n  fontFamily: string\n): void {\n  ctx.font = `${String(fontSize)}px \"${fontFamily}\"`;\n  let y = startY;\n  for (const char of text) {\n    ctx.fillText(char, x, y);\n    y += fontSize + VERTICAL_LINE_SPACING;\n  }\n}\n\nexport function drawTextPanel(\n  ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n  offsetX: number,\n  height: number,\n  items: OcrResultItem[],\n  style: BoxStyleOptions,\n  fontFamily: string,\n  background?: string\n): void {\n  const getColor = style.colorFn ?? deterministicColor;\n  const bg = background ?? DEFAULT_BG;\n\n  // Fill background\n  ctx.save();\n  ctx.fillStyle = bg;\n  ctx.fillRect(offsetX, 0, offsetX, height);\n  ctx.restore();\n\n  for (let i = 0; i < items.length; i += 1) {\n    const item = items[i];\n    const [r, g, b]: RgbColor = getColor(i);\n    const bounds = polyBounds(item.poly);\n    const angle = topEdgeAngle(item.poly);\n    const absDeg = Math.abs(angle * (180 / Math.PI));\n    const needsRotation = absDeg > ROTATION_THRESHOLD_DEG && absDeg < 180 - ROTATION_THRESHOLD_DEG;\n\n    // Detect vertical text: height > 2 * width and height > 30px\n    const isVertical = bounds.height > 2 * bounds.width && bounds.height > 30;\n\n    // Draw box outline\n    ctx.save();\n    ctx.lineWidth = OUTLINE_LINE_WIDTH;\n    ctx.strokeStyle = `rgb(${String(r)}, ${String(g)}, ${String(b)})`;\n    drawPolygonPath(ctx, item.poly, offsetX);\n    ctx.stroke();\n    ctx.restore();\n\n    // Draw text\n    ctx.save();\n    ctx.fillStyle = TEXT_COLOR;\n\n    if (isVertical) {\n      // Vertical text: render characters one-by-one, stacked vertically\n      ctx.textBaseline = \"top\";\n      const chars = Array.from(item.text);\n      const charCount = Math.max(1, chars.length);\n      let fontSize = Math.max(8, Math.floor(bounds.width * 0.8));\n\n      // Scale down if total character height exceeds box height\n      const totalHeight = charCount * (fontSize + VERTICAL_LINE_SPACING);\n      if (totalHeight > bounds.height) {\n        fontSize = Math.max(8, Math.floor((bounds.height / charCount) * 0.8));\n      }\n\n      // Ensure each character fits within the box width\n      ctx.font = `${String(fontSize)}px \"${fontFamily}\"`;\n      const maxCharWidth = Math.max(...chars.map((c) => ctx.measureText(c).width));\n      if (maxCharWidth > bounds.width) {\n        fontSize = Math.max(8, Math.floor(fontSize * (bounds.width / maxCharWidth)));\n      }\n\n      const x = bounds.minX + offsetX + (bounds.width - fontSize) / 2;\n      const y = bounds.minY + 2;\n      drawVerticalText(ctx, item.text, x, y, fontSize, fontFamily);\n    } else {\n      // Horizontal text\n      ctx.textBaseline = \"middle\";\n      let fontSize = Math.max(12, Math.floor(bounds.height * 0.8));\n      ctx.font = `${String(fontSize)}px \"${fontFamily}\"`;\n\n      // Shrink font if text is wider than the box\n      const measured = ctx.measureText(item.text);\n      if (measured.width > bounds.width && bounds.width > 0) {\n        fontSize = Math.max(8, Math.floor(fontSize * (bounds.width / measured.width)));\n        ctx.font = `${String(fontSize)}px \"${fontFamily}\"`;\n      }\n\n      if (needsRotation) {\n        const cx = bounds.minX + bounds.width / 2 + offsetX;\n        const cy = bounds.minY + bounds.height / 2;\n        ctx.translate(cx, cy);\n        ctx.rotate(angle);\n        ctx.fillText(item.text, -bounds.width / 2, 0);\n      } else {\n        const x = bounds.minX + offsetX + 2;\n        const y = bounds.minY + bounds.height / 2;\n        ctx.fillText(item.text, x, y);\n      }\n    }\n\n    ctx.restore();\n  }\n}\n","type AnyCanvas = OffscreenCanvas | HTMLCanvasElement;\n\nexport function createCanvas(width: number, height: number): AnyCanvas {\n  if (typeof OffscreenCanvas !== \"undefined\") {\n    return new OffscreenCanvas(width, height);\n  }\n  const canvas = document.createElement(\"canvas\");\n  canvas.width = width;\n  canvas.height = height;\n  return canvas;\n}\n\nexport function getContext2D(\n  canvas: AnyCanvas\n): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D {\n  const ctx = canvas.getContext(\"2d\");\n  if (!ctx) {\n    throw new Error(\"Failed to create 2D rendering context.\");\n  }\n  return ctx;\n}\n\nexport function canvasToBlob(canvas: AnyCanvas, type: string, quality: number): Promise<Blob> {\n  if (canvas instanceof OffscreenCanvas) {\n    return canvas.convertToBlob({ type, quality });\n  }\n  return new Promise<Blob>((resolve, reject) => {\n    canvas.toBlob(\n      (blob) => {\n        if (blob) {\n          resolve(blob);\n        } else {\n          reject(new Error(\"canvas.toBlob() returned null.\"));\n        }\n      },\n      type,\n      quality\n    );\n  });\n}\n","import type { OcrResult } from \"../../pipelines/ocr/core\";\nimport type { BoxStyleOptions } from \"./types\";\nimport { drawBoxesPanel } from \"./draw-boxes\";\nimport { drawTextPanel } from \"./draw-text\";\nimport { createCanvas, getContext2D, canvasToBlob } from \"../canvas-factory\";\n\ntype DrawableImage = ImageBitmap | HTMLImageElement;\n\nfunction imageWidth(image: DrawableImage): number {\n  return image instanceof HTMLImageElement ? image.naturalWidth : image.width;\n}\n\nfunction imageHeight(image: DrawableImage): number {\n  return image instanceof HTMLImageElement ? image.naturalHeight : image.height;\n}\n\nexport interface SideBySideOptions {\n  boxStyle: BoxStyleOptions;\n  fontFamily: string;\n  textPanelBackground: string;\n  outputFormat: string;\n  outputQuality: number;\n}\n\nexport function renderSideBySideToCanvas(\n  image: DrawableImage,\n  result: OcrResult,\n  options: SideBySideOptions\n): OffscreenCanvas | HTMLCanvasElement {\n  const w = imageWidth(image);\n  const h = imageHeight(image);\n  const canvas = createCanvas(w * 2, h);\n  const ctx = getContext2D(canvas);\n\n  drawBoxesPanel(ctx, image, result.items, options.boxStyle);\n  drawTextPanel(\n    ctx,\n    w,\n    h,\n    result.items,\n    options.boxStyle,\n    options.fontFamily,\n    options.textPanelBackground\n  );\n\n  return canvas;\n}\n\nexport async function renderSideBySideToImageBitmap(\n  image: DrawableImage,\n  result: OcrResult,\n  options: SideBySideOptions\n): Promise<ImageBitmap> {\n  const canvas = renderSideBySideToCanvas(image, result, options);\n  return createImageBitmap(canvas as ImageBitmapSource);\n}\n\nexport async function renderSideBySideToBlob(\n  image: DrawableImage,\n  result: OcrResult,\n  options: SideBySideOptions\n): Promise<Blob> {\n  const canvas = renderSideBySideToCanvas(image, result, options);\n  return canvasToBlob(canvas, `image/${options.outputFormat}`, options.outputQuality);\n}\n","import type { OcrResult } from \"../../pipelines/ocr/core\";\nimport type { OcrVisualizerOptions } from \"./types\";\nimport { loadFontFace, removeFontFace } from \"../font\";\nimport { renderSideBySideToImageBitmap, renderSideBySideToBlob } from \"./side-by-side\";\nimport type { SideBySideOptions } from \"./side-by-side\";\n\ntype DrawableImage = ImageBitmap | HTMLImageElement;\n\nconst DEFAULT_FONT_FAMILY = \"sans-serif\";\nconst DEFAULT_OUTPUT_FORMAT = \"png\";\nconst DEFAULT_OUTPUT_QUALITY = 0.92;\nconst DEFAULT_TEXT_PANEL_BG = \"#ffffff\";\n\nfunction resolveOptions(\n  base: OcrVisualizerOptions,\n  overrides?: Partial<OcrVisualizerOptions>\n): SideBySideOptions {\n  const merged = overrides ? { ...base, ...overrides } : base;\n  return {\n    boxStyle: merged.boxStyle ?? {},\n    fontFamily: merged.font?.family ?? DEFAULT_FONT_FAMILY,\n    textPanelBackground: merged.textPanelBackground ?? DEFAULT_TEXT_PANEL_BG,\n    outputFormat: merged.outputFormat ?? DEFAULT_OUTPUT_FORMAT,\n    outputQuality: merged.outputQuality ?? DEFAULT_OUTPUT_QUALITY\n  };\n}\n\nexport class OcrVisualizer {\n  private options: OcrVisualizerOptions;\n  private loadedFace: FontFace | null = null;\n\n  constructor(options?: OcrVisualizerOptions) {\n    this.options = options ?? {};\n  }\n\n  async loadFont(): Promise<void> {\n    if (!this.options.font) return;\n    if (this.loadedFace) return;\n    this.loadedFace = await loadFontFace(this.options.font);\n  }\n\n  async renderSideBySide(\n    image: DrawableImage,\n    result: OcrResult,\n    overrides?: Partial<OcrVisualizerOptions>\n  ): Promise<ImageBitmap> {\n    await this.loadFont();\n    const opts = resolveOptions(this.options, overrides);\n    return renderSideBySideToImageBitmap(image, result, opts);\n  }\n\n  async toBlob(\n    image: DrawableImage,\n    result: OcrResult,\n    overrides?: Partial<OcrVisualizerOptions>\n  ): Promise<Blob> {\n    await this.loadFont();\n    const opts = resolveOptions(this.options, overrides);\n    return renderSideBySideToBlob(image, result, opts);\n  }\n\n  dispose(): void {\n    if (this.loadedFace) {\n      removeFontFace(this.loadedFace);\n      this.loadedFace = null;\n    }\n  }\n}\n\nexport async function renderOcrToBlob(\n  image: DrawableImage,\n  result: OcrResult,\n  options?: OcrVisualizerOptions\n): Promise<Blob> {\n  const viz = new OcrVisualizer(options);\n  try {\n    return await viz.toBlob(image, result);\n  } finally {\n    viz.dispose();\n  }\n}\n"],"names":["drawPolygonPath"],"mappings":"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"}