feat(geometry): viewer-space conversion for citation highlighting - #15
Conversation
Adds BBox.Viewport and BBox.Normalized, plus a ViewRect type, so a frontend can draw a highlight over a rendered page instead of only naming the page a citation came from. The geometry was already correct and complete -- every coordinate the package reports is normalised, with the MediaBox origin translated to (0,0) and any /Rotate applied, so it matches Page.Width() x Page.Height() exactly. What was missing is that this contract was undocumented and untested, so nothing stopped a future change from breaking an external consumer silently. The one conversion a caller still has to make is the Y flip: PDF user space is origin bottom-left with Y up, every web rendering target is origin top-left with Y down. Getting that backwards mirrors the overlay vertically, which is a failure mode that still looks plausible -- boxes land on real rows, just the wrong ones. Doing it once here, tested, is better than each consumer rediscovering it. ViewRect is a distinct type from BBox rather than a second set of fields so the two coordinate systems cannot be mixed up at a call site. Normalized returns fractions of the page for resizable viewers, and the tests assert the two APIs agree at several scales so they cannot drift. Verified end-to-end by rendering 3M 2018 10-K page 58, projecting real cell bboxes through Viewport, and confirming the boxes land on the intended rows.
Reviewer's GuideAdds a viewer-space rectangle type and conversion helpers so citation highlight coordinates can be consumed safely by web frontends, and backs the geometry contract with focused unit and end-to-end tests. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Review limit reached
Next review available in: 53 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- Consider guarding Viewport and Normalized against obviously invalid inputs (e.g., negative page dimensions or scale) to fail fast instead of silently producing inverted or nonsensical viewer rectangles.
- You might want to offer convenience helpers that take a Page (or its width/height) directly for ViewRect conversion to reduce repetitive parameter passing and minimize call‑site mistakes with mismatched dimensions.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider guarding Viewport and Normalized against obviously invalid inputs (e.g., negative page dimensions or scale) to fail fast instead of silently producing inverted or nonsensical viewer rectangles.
- You might want to offer convenience helpers that take a Page (or its width/height) directly for ViewRect conversion to reduce repetitive parameter passing and minimize call‑site mistakes with mismatched dimensions.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Makes the citation-highlight feature buildable: viewer-space coordinates so the frontend can draw an overlay on the rendered page, not just say "page 58".
Stacked on #10 (which is stacked on #9). Merge order: #9 → #10 → #11.
The good news first
The geometry was already correct. Verified rather than assumed: every coordinate the package reports —
Char,Word,Line,Rect,Table.BBox,Table.CellsBBox— is already normalised.page.gotranslates the MediaBox origin to (0,0) and applies the/Rotatematrices, so the space matchesPage.Width()xPage.Height()exactly. Rotated pages and non-zero-origin MediaBoxes are already handled, and no per-page fixups are needed.Proved end-to-end: rendered 3M 2018 10-K page 58 at 150 DPI, projected real
CellsBBoxvalues onto the image, and the highlights land exactly on the intended rows.What was actually missing
The contract was undocumented and untested. Nothing stopped a future change to coordinate handling from silently breaking an external consumer — the frontend would just start drawing boxes in the wrong place, with no test going red.
And there is one conversion every consumer must make and can easily invert: PDF user space is origin bottom-left, Y up; every web target (CSS, canvas, SVG, PDF.js) is origin top-left, Y down. Getting it backwards mirrors the overlay vertically — a failure that still looks plausible, because the boxes land on real rows, just the wrong ones. Better to do it once, here, with a test.
API
ViewRectis a distinct type fromBBoxon purpose — the two coordinate systems should not be mixable at a call site.Viewportfor a page rasterised at known DPI (scale = dpi/72) or a PDF.jsgetViewport({scale}).Normalizedreturns fractions of the page, which is what a resizable viewer wants: percentages stay correct at any zoom or container width, so the overlay survives a re-render without recomputation.Tests
Top).ViewRectrather than emitting NaN into a JSON payload.go build,go vet,go test ./... -count=1 -raceall green.Frontend usage
Granularity available today: whole table (
Table.BBox), cell (Table.CellsBBox[i][j]), word (Page.Words), glyph (Page.Chars).Follow-up
A citation usually spans several words across one or more lines. A helper that merges a run of word bboxes into the minimal set of line rectangles — rather than one union box that swallows the whole paragraph — would give a tighter highlight. Not needed for v1; noted on HAL-547.
Closes HAL-547
Summary by Sourcery
Introduce viewer-space rectangle support to enable accurate citation highlighting overlays based on PDF geometry.
New Features:
Tests: