Skip to content

Studio: crop/reposition the input on the render, output-format pages with masked margins - #33

Merged
dxviie merged 5 commits into
mainfrom
claude/studio-crop-reposition-input-xbrf4a
Aug 6, 2026
Merged

dxviie merged 5 commits into
mainfrom
claude/studio-crop-reposition-input-xbrf4a

Conversation

@dxviie

@dxviie dxviie commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Zoom in on the interesting part of a picture or video by manipulating it right on the render, and compose it onto a fixed page whose margin is masked.

Crop / reposition (498f11c, e63b4bd)

  • Direct manipulation on the stage: drag to move, wheel to zoom on the cursor (trackpad pinches arrive as ctrl+wheel; Safari's gesture events add trackpad rotate), alt/⌥+wheel to rotate, double-click to reset. On touch, two fingers drag/pinch/twist (with a gentle quarter-turn snap) while one finger keeps scrolling the page.
  • The hatch render is too slow to follow a gesture, so the stage shows the reframed source live — with a rule-of-thirds grid and an accent border along the input's own edge so white-on-white inputs stay visible — then the pipeline recomputes from the committed view.
  • The view is applied at the single point where source pixels are extracted, so segmentation, hatching, preview, SVG/PNG exports, plot time, ordering and the video sequence export all see only the reframed picture. A video keeps one framing across scrubbing and all exported frames.
  • A ⛶ full image chip with a live zoom/angle readout (and double-click) returns to the default composition.
  • The render now contain-fits the stage (upscaling small inputs too) instead of sitting at native pixel size.

Output formats (16b6b54)

  • A6–A3 become toggles (at most one active, click again to turn off) plus a picker with more sizes — A2–A0, B-series, US letter/legal/tabloid, squares, AxiDraw beds — and a custom width × height. Named sheets auto-turn to match the input, with a manual ⇄ flip.
  • With a format active the working frame takes the page's aspect, the input starts fitted inside the margins and is composed with the crop gestures, and exports become exactly that page (e.g. 210.00mm × 297.00mm).
  • The margin is a mask: hatch segments are clipped so no ink lands within it — previewed as a dimmed band while reframing. Order sizing uses the drawn extent inside the mask.
  • Output width and margin are user settings now: presets, imports and dice rolls no longer touch them (values in stored presets are ignored), and a new input resets the format while keeping the width.

Help page (cb244bf, fdadc29)

  • The bold titles in the numbered legend link to their sections.
  • On desktop, a fixed "on this page" panel lists every section (studio ones keep their screenshot number + color) with a scroll spy; the presets section moved ahead of layers so everything counts 1–8 in order.

Engine additions

Pure, unit-tested modules in src/lib/rstr2/: viewTransform.ts (gesture/matrix math, contain fit, clamping), outputFormat.ts (format catalog, orientation, margin math), clipSegmentsToRect in hatchTools.ts.

Testing

  • 320 unit tests (60 new), svelte-check and lint clean.
  • ~90 Playwright checks across four suites: spatial correctness of pans (a test card's hatched half provably follows the drag, also under CSS upscale), byte-identical render restoration on reset, zero ink in masked margins, exact page dimensions in still + sequence SVG exports, CDP two-finger pinch+twist, single-finger scroll non-interference, preset width preservation, format reset on new sources, accent-border pixels, and help-page navigation/scroll-spy behavior.

🤖 Generated with Claude Code

https://claude.ai/code/session_012XzVKNfUqWxgWRD4A4RYDx


Generated by Claude Code

claude added 5 commits July 31, 2026 20:07
Zoom in on the interesting part of a picture or video by manipulating it
right on the stage: drag to move, wheel (or trackpad pinch, arriving as
ctrl+wheel) to zoom on the cursor, alt/option+wheel to rotate, double-click
to reset — on touch, two fingers drag/pinch/twist (with quarter-turn snap)
while one finger keeps scrolling the page.

The view transform (new pure module src/lib/rstr2/viewTransform.ts, unit
tested) is applied where source pixels are extracted, so segmentation,
hatching, preview, SVG/PNG exports, ordering and the video sequence export
all see only the reframed picture; off-frame area reads as bare paper. A
video keeps one framing across scrubbing and all exported frames. While a
gesture is in flight the stage shows the reframed source with a
rule-of-thirds grid (the hatch render is too slow to follow live), and a
"full image" chip with a zoom/angle readout offers the way back.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XzVKNfUqWxgWRD4A4RYDx
… border

The A6-A3 buttons become toggles (at most one active, off by default), a
picker adds more sizes - A2-A0, B-series, US letter/legal/tabloid, squares,
AxiDraw beds - plus a custom width x height, and named sheets auto-turn to
match the input with a manual flip. While a format is active the working
frame takes the page's aspect, the crop view composes the input into it
(starting from the whole image fitted inside the margins), exports become
exactly that page, and the margin acts as a mask: hatch segments are
clipped so no ink lands within it, previewed as a dimmed band while
reframing. Order sizing uses the drawn extent inside the mask.

Output width and margin are now the user's own settings: presets, imports
and dice rolls no longer touch them (values in stored presets are ignored),
and a new input resets the format while keeping the width.

The crop preview also gains an accent border along the input's own edge,
so where it starts and ends stays visible on inputs with white backgrounds.

New pure modules: outputFormat.ts (catalog, orientation, margin math) and
clipSegmentsToRect in hatchTools.ts; containView and source-vs-frame
clamping in viewTransform.ts - all unit tested.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XzVKNfUqWxgWRD4A4RYDx
… space

The render surfaces only ever scaled down (max-width/height: 100%), so a
small input sat at its native pixel size in a sea of empty stage. The stage
is now a size container and every render surface contain-fits its content
box via cqw/cqh, upscaling small sources as well. Sizing the element itself
(height keeps the intrinsic ratio) rather than object-fit letterboxing
keeps the element box equal to the visible render, so the paper shadow and
the crop gestures' client-to-frame mapping stay exact; older browsers
without container units keep the previous behavior. Also refreshes the
unsupported-order note that still pointed at the removed "fit on page".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XzVKNfUqWxgWRD4A4RYDx
The bold titles in the numbered legend now link to their sections, using
the site's dashed link style for affordance. On desktop (>= 1200px) a
fixed "on this page" panel sits beside the content column listing every
section - the eight studio ones with their screenshot number and color,
plus overview, prep, classic and good to know - with a small scroll spy
highlighting where the reader is. Sections got stable anchor ids, land
just below the sticky top bar (scroll-margin), and anchor jumps scroll
smoothly unless the reader prefers reduced motion. The legend and panel
are generated from one section table, so titles, numbers and colors can
no longer drift apart.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XzVKNfUqWxgWRD4A4RYDx
The panel and scroll spy follow document order, and the presets section
sat after layers — so the panel counted ...4, 6, 5, 7... Move the presets
section ahead of layers (matching the studio's own right-pane order), and
every view of the page — panel, legend, reading order — now counts 1
through 8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XzVKNfUqWxgWRD4A4RYDx
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying rstr with  Cloudflare Pages  Cloudflare Pages

Latest commit: fdadc29
Status: ✅  Deploy successful!
Preview URL: https://ed7fb338.rstr.pages.dev
Branch Preview URL: https://claude-studio-crop-repositio.rstr.pages.dev

View logs

@dxviie
dxviie merged commit a365206 into main Aug 6, 2026
2 checks passed
@dxviie
dxviie deleted the claude/studio-crop-reposition-input-xbrf4a branch August 6, 2026 14:52
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.

2 participants