Skip to content

#119 Crop a pasted image (both modes) #127

Description

@brokkoli71
Feasibility Medium
Status Open

Split out of row 118 (2026-07-17, user: 'leave crop for later in an issue') once paste/move/resize/rotate/copy had landed for text pages. An image object already carries the field the renderer would need; nothing crops it. DESIGN (decided in 118, do not re-litigate): a crop is a FIELD ON THE MODEL applied when rendering, NOT a destructive re-encode of the stored PNG bytes - so it stays adjustable forever and repeated crops never degrade the picture. The stored bytes are the original. This matters most on the PDF side: insert_image has no crop parameter (and rotate only in 90 steps), which is exactly why the sidecar is the source of truth and the OCG layer is a regenerated render target. Do it ONCE for both modes: the image model and the draw path are shared (draw_image / TextPageView._snapshot_images), so a crop rect belongs next to 'rotate' and is honoured in both. UI: the natural gesture is a crop mode on the lasso selection (drag the edges inward), distinct from the corner handles which resize. Watch the same traps the rest of 118 hit: store the rect in DOCUMENT units (not the zoom you cropped at - row 116's pen-width lesson); go through _overlay_to_buffer_f, never the int-truncating helpers (that is what made rotation lumpy); and repaint via _images_changed() (the VIEW paints images, not the ink overlay). Ships with: the crop rect in ink_to_json/load_ink, one undo entry, and copy_selection carrying it. NOTE 2026-07-17: still the only thing outstanding from row 118 — paste, copy, the lasso verbs, the sidecar and the OCG layer are all Done and verified, so crop is the last piece of the image feature.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions