|
|
| 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.
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.