Skip to content

Scale a page's display space by its /UserUnit (#729) - #737

Merged
yhay81 merged 2 commits into
mainfrom
claude/729-page-user-unit
Nov 7, 2026
Merged

yhay81 merged 2 commits into
mainfrom
claude/729-page-user-unit

Conversation

@yhay81

@yhay81 yhay81 commented Nov 7, 2026 •

Copy link
Copy Markdown
Owner

Closes #729

A page's /UserUnit scales its display coordinates to physical points (1/72 inch), following the owner's decision. A page with /MediaBox [0 0 400 300] /UserUnit 2 measures 800 by 600 points and renders at 800 by 600 pixels at 72 dpi.

What changed

  • The page index resolves the page’s own finite, positive /UserUnit through the store. Missing or invalid values use 1. For a reference chain it records each object read, so editing the last object updates derived geometry. Invalid containers are never copied for the unit.
  • For scaled pages, the bindings and the interpreter use the same full-precision box, rotation and unit. Raster dimensions, clipped and batch rendering, text layout and content extraction use that geometry. Narrow crops keep their true visible extent and origin. Unit-one rendering retains hayro's native viewport.
  • The SVG root carries the physical dimensions and the corresponding viewport in hayro's drawing coordinates. The existing string is edited in place, after checking the final byte length and budgeting any capacity growth.
  • Page boxes and setters, annotations and links, canvas drawing and page placement, OCR and rotation removal use physical points. The canvas writes the inverse matrix at round-trip precision and uses the same coefficients for its patterns.
  • The English and Japanese concepts pages and the page API document physical points. Internally, _core.page_space returns (rotation, box, unit) and _core.canvas_source_page carries the unit after the box.

Acceptance

  • The owner recorded the display-space decision on Honor or expose /UserUnit in page geometry and rendering #729.
  • Public API tests cover units 1 and 2, raster dimensions and pixels at 72 and 144 dpi, extraction and search, clipping, page boxes and rotation, annotations and links, canvas, OCR, indirect values, edits and undo.
  • Review regressions cover a saved canvas and gradient at units 750 and 30000, a two-hop unit reference, indirect box coordinates, all four rotations of a sub-unit crop, a 52010-pixel decimal page including its final column, and the exact SVG output limit. Rust tests cover invalid-unit retention, SVG buffer growth, and raw RGBA rendering.

Checks

python3 tools/check.py --locked passed on 89287512. The Python suite passed 8,205 tests and the Rust workspace passed 665 tests. Ruff, ty, rustfmt and Clippy also passed.

Follow-up

Not a port from pylopdf.

Display coordinates are points of 1/72 inch, as the owner decided on
2026-11-07. A page with a [0 0 400 300] MediaBox and /UserUnit 2 is 800
by 600 points: its boxes, text and paths, clips, annotation and link
rectangles, canvas, and OCR layer use those points, and it renders 800
by 600 pixels at 72 dpi.

pyropdf_store::pages::user_unit is the one rule (a finite number above 0,
else 1; not inherited). The store's Page and the engine's new display
module both apply it, so geometry and rendering share one conversion.
The SVG's width and height are in points; its viewBox stays in user
space units.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@yhay81 yhay81 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

I recommend fixing the four coordinate errors and the two unbudgeted copies below before merging. I reproduced the coordinate errors on 8e111a7b through the public Python API. All 433 tests in the ten related test modules passed locally, and the current head passed CI.

Comment thread python/pyropdf/_canvas.py Resolved
Comment thread crates/pyropdf-engine/src/display.rs Resolved
Comment thread crates/pyropdf-python/src/pages.rs Resolved
Comment thread crates/pyropdf-engine/src/display.rs Resolved
Comment thread crates/pyropdf-store/src/pages/mod.rs Resolved
Comment thread crates/pyropdf-engine/src/render/svg.rs Resolved
@yhay81
yhay81 merged commit fb4aba3 into main Nov 7, 2026
16 checks passed
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.

Honor or expose /UserUnit in page geometry and rendering

1 participant