Skip to content

Fix annotation coordinates when cropping rotated pages - #1416

Open
sunxiuguo wants to merge 2 commits into
jsvine:developfrom
sunxiuguo:fix-rotated-crop-annotations
Open

sunxiuguo wants to merge 2 commits into
jsvine:developfrom
sunxiuguo:fix-rotated-crop-annotations

Conversation

@sunxiuguo

Copy link
Copy Markdown

Summary

Fix lost or displaced annotations/hyperlinks after cropping a rotated page. Annotation /Rect coordinates are defined in the original page's coordinate system, so rotation must use root_page.width / root_page.height, rather than the cropped page dimensions.

A synthetic 300×400 page with a URI link at [50,100,150,130] illustrates the problem: page.crop(page.hyperlinks[0]'s bbox).hyperlinks is empty at 90°, 180°, and 270°. The uncropped hyperlink coordinates are correct. This also reproduces in PyPI 0.11.10.

Changes

  • Use root-page dimensions for annotation rotation (one production line).
  • Add 16 synthetic-PDF regression cases: four rotations × four rectangle endpoint orderings, with crop, nested crop, within-bbox and outside-bbox assertions.
  • Update the changelog and contributor list as requested by CONTRIBUTING.md.

Validation

Against develop 2fcbe6a6264201e9ae3e661c01c39b4111eb9af0, Python 3.12:

  • New regressions before the fix: 12 failed, 4 passed.
  • New regressions after the fix: 16 passed.
  • Complete pytest suite: 189 passed.
  • make lint: flake8, strict mypy (20 source files), Black and isort all passed with the repository's pinned tooling/type stubs.
  • Independent review: 224 additional geometry checks passed, including partial clipping, relative/nested crops and inclusion/exclusion behavior.

All fixtures are synthetic and contain no external/customer data. Uncropped pages retain existing behavior because root_page is the page itself. Remote CI has not yet run. This contribution was prepared with AI assistance and independently reviewed and tested.

Normalize raw annotation points relative to the original MediaBox before
rotation, then restore the existing root-page coordinate offsets. Keep
the unrotated path and global page bbox convention unchanged.

Expand the synthetic crop regressions to 77 cases, including nonzero and
fractional origins, endpoint ordering, nested/relative/partial crops and
actual PDFium rendering. Previous PR head: 45 failures / 32 passes;
this commit: 77 passes. Full suite: 250 passes. make lint passes.
Validated with repository-pinned pdfminer.six==20260107 on Python 3.12.14.
Independent native-renderer/API review passes 12 pages x 16 checks;
Poppler independently corroborates all 12 synthetic page geometries.

Only annotation handling changes; the global inversion work in jsvine#1381
remains separate. AI-assisted and independently reviewed. Synthetic
logical crop/link extraction only, not exported-PDF or production proof.
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.

1 participant