Skip to content

Add per-canvas SVG text rendering - #69

Merged
donaldgray merged 2 commits into
mainfrom
feature/svgRendering
Oct 22, 2026
Merged

donaldgray merged 2 commits into
mainfrom
feature/svgRendering

Conversation

@donaldgray

@donaldgray donaldgray commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Resolves #68

Adds an SVG text rendering per canvas, linked from each canvas's rendering property in the text-augmented Manifest, similar to wellcomecollection/iiif-builder#256.

  • New JobServices.Svg flag (128); the endpoint and its rendering link are only available when the flag is enabled
  • New endpoint GET /svg/v1/{n}/{**id} returns image/svg+xml: one invisible, selectable <text> element per line, stretched over the line's bounding box, with a viewBox matching the canvas
  • rendering link added only to image canvases (not audio/video) that have at least one word; existing rendering entries are kept and duplicates skipped
  • Canvas width/height now stored on Image (ProtoMember 4/5) for the viewBox; indexes built before this change fall back to the stored Manifest
  • Builder saves the text index when Svg is requested
  • Docs: README, docs/search-api.md, docs/builder-api.md
  • The flag tables in the docs gave Pdf/TextAugmented/Annotations as 8/16/32, but the enum has them as 16/32/8 - updated.

Existing problem, not fixed here:

  • The per-canvas line/word annotation pages need the text index, which is only saved when Search, Pdf or Svg is on, so a job with Annotations alone gets 404s from those pages.

Caution

Known limitation: hyphenated words in SVG overlay

The SVG builds each line from the search index's words. When ALTO splits a word across two lines (e.g. "pro-" / "posal"), the index merges it into a single word ("proposal") on the first line, keeping only the first part's bounding box. As a result:

  • The full word is squeezed into the box of the first part, so the selectable text doesn't line up exactly with the image.
  • The second part is missing from the next line, so that line's text starts at the following word.
  • If the second part is the only word on its line, that line is missing from the SVG entirely.

Punctuation-only tokens (e.g. "—", "&", "§") are also not included, as they aren't added to the index.

On the plus side, copy/pasting across a line break gives the whole word ("proposal") rather than two fragments.

This is acceptable for now. Fixing it would mean storing the physical line layout from the ALTO alongside (or separately from) the search index - increasing storage size.

🤖 Generated with Claude Code

Add a JobServices.Svg flag (128) and a /svg/v1/{n}/{**id} Search API
endpoint that returns an SVG of a canvas's line text, positioned over
the canvas for selectable-text overlays. The text-augmented Manifest
links it from each spatial canvas's "rendering" property.

Canvas dimensions are now recorded on Image (ProtoMember 4/5) for the
SVG viewBox, falling back to the stored Manifest for older indexes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@donaldgray
donaldgray force-pushed the feature/svgRendering branch from 5c5cb03 to 10c6e34 Compare October 20, 2026 16:24
@donaldgray
donaldgray marked this pull request as ready for review October 21, 2026 15:12
@donaldgray
donaldgray requested a review from a team as a code owner October 21, 2026 15:12
@donaldgray
donaldgray merged commit 73118cc into main Oct 22, 2026
4 of 7 checks passed
@donaldgray
donaldgray deleted the feature/svgRendering branch October 22, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Store SVG layer

2 participants