Skip to content

fix(pdf): Rotated photo frames print at the angle they preview at - #89

Open
patriksimms wants to merge 1 commit into
mainfrom
fix/rotated-image-export
Open

fix(pdf): Rotated photo frames print at the angle they preview at#89
patriksimms wants to merge 1 commit into
mainfrom
fix/rotated-image-export

Conversation

@patriksimms

Copy link
Copy Markdown
Owner

Problem

A rotated image frame exported axis-aligned. Text already rotated, so a rotated
layout printed with its words at an angle and its pictures square.

Solution

Photos, decorative images, and empty-slot filler art are now drawn inside a
transformation matrix that turns them around the frame's top-left corner — the
corner the preview turns an element around (transform-origin: top left). Page
space counts Y upwards where CSS counts it downwards, so the preview's angle is
negated in the export.

pdf-lib's per-call rotate option was not usable here: it turns each drawing
around its own anchor, which moves an element instead of turning it in place and
would pull a gallery's slots apart. A gallery therefore embeds its photos before
anything is painted, so one transformation can wrap the whole frame.

In scope

  • Photos in image frames and gallery slots
  • Decorative image elements
  • Filler art in photo slots a contributor left empty

Out of scope

Acceptance criteria

Criterion Evidence
A rotated image frame exports at the angle and place it previews at crops a photo to the frame at the angle the preview shows
A rotated gallery frame rotates as a unit, slots in the same relative places rotates a gallery as one frame, keeping its slots in the same relative places
A rotated decorative image exports at the angle it previews at turns a decorative image at the angle the preview shows
A rotated empty photo slot's filler art rotates with its frame turns filler art with the frame, so a slot does not move when a photo arrives
An axis-aligned frame is untouched leaves an unrotated frame exactly where it was
An exported-PDF proof shows a rotated frame with and without a photo landing in the same place screenshots below

The new tests replay the exported page's drawing operators and compare
page-space corners, so they assert where a photo actually lands rather than
which operators pdf-lib happens to write. All four rotation tests fail against
main and pass here; the axis-aligned test passes both ways.

Exported-PDF proof

Rasterised from an exported PDF of the same layout: an image frame at -12°, a
two-slot gallery at 8°, a decorative image at 15°, and a caption at -12° for
reference.

Rotated frames holding photos

Before After
before after

The same frames with no photo uploaded

Before After
before after

Validation

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 349 passed; the 14 failures need the local Postgres and S3
    services, which are unavailable in this environment and fail identically on
    main
  • bun run build with the CI Clerk test keys
  • bun run test:e2e not run locally (no services or browsers); left to CI

No configuration outside the repository is required.

Closes #86

Summary:
- rotate photos, decorative images, and empty-slot filler art around the
  frame's top-left corner, the corner the preview turns elements around
- turn a gallery as one frame by embedding its photos first and wrapping
  every slot in a single transformation
- cover placement with tests that replay the exported page's drawing
  operators and compare page-space corners
- add before/after exported-PDF proofs for a rotated frame with and
  without a photo

Rationale:
- pdf-lib's per-call rotate option turns each drawing around its own
  anchor, which would move a frame instead of turning it and would pull a
  gallery's slots apart; a transformation matrix turns the clip path, the
  photo inside it, and every slot together
- page space counts Y upwards where CSS counts it downwards, so the
  preview's clockwise angle is the negated angle in the export
- photos and filler art had to move together, or a slot would visibly
  shift as soon as a contributor added or removed a photo

Tests:
- bun run format:check
- bun run lint
- bun run typecheck
- bun run test (349 passed; 14 pre-existing failures need the local
  Postgres and S3 services, which are unavailable here)
- bun run build with test Clerk configuration

Closes #86

AI-Assisted: true
AI-Agent: claude-code
AI-Model: anthropic/claude-opus-5
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.

fix(pdf): Rotated frames export axis-aligned instead of rotated

1 participant