Skip to content

CVML-194: add_overlay_canvas() embedder overlay API - #263

Merged
elliott-imhoff merged 4 commits into
mainfrom
CVML-194-extract-bitmasks-display-option
Oct 21, 2026
Merged

elliott-imhoff merged 4 commits into
mainfrom
CVML-194-extract-bitmasks-display-option

Conversation

@elliott-imhoff

@elliott-imhoff elliott-imhoff commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Warning

🤖 This pull request was prepared in collaboration with AI.

Embedder overlay canvases (CVML-194)

Description

Adds a small public API so an embedder can draw into a canvas that ULabel places and keeps in sync with zoom and pan, without touching ULabel's DOM. Model Registry needs it for CVML-194, which draws composited segmentation rasters under the annotations.

type OverlayLayer = "below_annotations" | "above_annotations";
add_overlay_canvas(layer?: OverlayLayer): HTMLCanvasElement;
remove_overlay_canvas(canvas: HTMLCanvasElement): void;
  • add_overlay_canvas() appends one canvas to the image wrapper (imwrap_id). The canvas has:
    • backing size image_width * px_per_px × image_height * px_per_px
    • the imgsz_class
    • pointer-events: none and image-rendering: pixelated
    • a CSS size that matches the current zoom
  • It throws if called before init completes or after destroy().
  • "below_annotations" (default) stacks the canvas above the image frames and below every subtask canvas. "above_annotations" stacks it above the active subtask canvas. Both z-index values are named constants (OVERLAY_BELOW_ANNOTATIONS_Z_INDEX, OVERLAY_ABOVE_ANNOTATIONS_Z_INDEX) in src/blobs.js, derived from BACK_Z_INDEX / FRONT_Z_INDEX.
  • Overlay canvases carry imgsz_class, so rezoom() and drag_rezoom() resize them with the image. ULabel tracks them in overlay_canvases for remove_overlay_canvas() and destroy(). The FilterDistance overlay is unchanged.
  • Z-indices for the image frames, FilterDistance overlay, and loader are now named in src/blobs.js. The loader stacks above "above_annotations" overlays.
  • remove_overlay_canvas() detaches a canvas and drops ULabel's reference to it. destroy() removes any remaining canvases and clears the list. swap_frame_image() leaves overlay canvases in place; the caller owns their content.
  • Docs are in api_spec.md and types in index.d.ts. The changelog entry is under [0.31.0].

Release / version bump

Version is 0.31.0 in package.json, package-lock.json, and src/version.js. Main has since released 0.30.0 and 0.30.1; this branch merges latest main, and the overlay API changelog entry sits under [0.31.0]. On merge, a maintainer should cut the v0.31.0 tag. Model Registry then moves its pin from this branch's commit to the tag.

Testing

  • npm run lint ✅
  • npm run build ✅
  • After review fixes (f3602db): jest 521/521 on each build ✅; Chromium e2e (overlay, zoom/pan, wheel zoom, basic, API) 94/94 ✅
  • After merging main: npm test 522/522 ✅; Playwright overlay, api-behavior, and basic-functionality specs on chromium and chromium-minified: 68/68 ✅
  • npm run test:both: 522/522 on each build ✅. Adds tests/overlay_canvas.test.js (creation, backing/CSS size, layer z-order, unknown layer, before-init/after-destroy throws, resize, removal, destroy cleanup).
  • Playwright tests/e2e/overlay-canvas.spec.js plus the existing zoom specs, on chromium and chromium-minified: 38/38 ✅. The spec covers:
    • wrapper placement
    • backing size and size class
    • stacking relative to the image frames, all subtask groups, and the active subtask
    • alignment with the image after rezoom() and shift+drag drag_rezoom()
    • unchanged FilterDistance overlay sync
    • overlays surviving swap_frame_image()
    • remove and destroy cleanup

PR Checklist

  • Merged latest main
  • Version number in package.json has been bumped since last release
  • Version numbers match between package package.json and src/version.js
  • Updated documentation if necessary (currently just in api_spec.md)
  • Added changes to changelog.md

Breaking API Changes

None. The change is additive. filter_distance_overlay is now null after destroy().

elliott-imhoff and others added 3 commits October 13, 2026 09:59
Embedders get a pointer-free canvas in the image wrapper that ULabel sizes,
zoom-syncs, and removes on destroy(). FilterDistance's overlay joins the same
overlay list; its behavior is unchanged.

CVML-194

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Main released 0.30.0 and 0.30.1, so the overlay canvas API now ships as 0.31.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@elliott-imhoff
elliott-imhoff marked this pull request as ready for review October 21, 2026 19:27
Comment thread src/blobs.js
Comment thread src/index.js Outdated
- Add IMAGE_FRAME_Z_INDEX, FILTER_DISTANCE_OVERLAY_Z_INDEX and LOADER_Z_INDEX
  to blobs.js; the loader now stacks above "above_annotations" overlays.
- Remove resize_overlay_canvases(): overlay canvases carry imgsz_class, so
  rezoom()/drag_rezoom() already resize them. Restore the FilterDistance
  overlay resize call; overlay_canvases tracks embedder canvases only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@TrevorBurgoyne TrevorBurgoyne added the enhancement New feature or request label Oct 21, 2026

@TrevorBurgoyne TrevorBurgoyne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good to go once tests pass 👍

@elliott-imhoff
elliott-imhoff merged commit f957012 into main Oct 21, 2026
4 checks passed
@elliott-imhoff
elliott-imhoff deleted the CVML-194-extract-bitmasks-display-option branch October 21, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants