Implements rotation for paths, brush strokes and gradients.#21349
Implements rotation for paths, brush strokes and gradients.#21349masterpiga wants to merge 1 commit into
Conversation
|
How well does this play with gradient drawn masks? Does this change any existing mask manipulation behaviors? EDIT: Did a quick test. Gradient masks work fine and it seems to work fine. |
What happens when a pre-PR copy of darktable tries to process a post-PR sidecar or database entry? Ignoring the new angle fields is fine (versioning skips the entire iop during processing if too new), while interpreting the new format as if it were the old one is not. Let's see if I can link an old FR: fixes #14026. |
Good point. It degrades gracefully. The only information that is lost is the independent rotation of source/target shapes in retouch. I.e., if a pre-PR darktable opens a post-PR edit in which you rotated the two independently, then the source shape will be at the same angle as the target one. It seems an acceptable state of affairs to me, but I am happy to revisit if this is not ok. |
|
Thanks for the review, @jenshannoschwalm, comments addressed |
- Uses CTRL+drag for all shape rotations (already used by ellipse rotation). - Changes CTRL+click to add a node to a path or brush stroke to SHIFT+click (to prevent ambiguity w/ CTRL+drag). - Allows independent rotation of source/target shapes in retouch (heal and clone) w/ CTRL+SHIFT+drag.
|
Thanks, Hanno, all done. I also deployed |
TL;DR
CTRL+dragfor all shape rotations (already used by ellipse rotation).CTRL+clickto add a node to a path or brush stroke toSHIFT+click(to prevent ambiguity w/CTRL+drag).CTRL+SHIFT+drag.Demo
Screen.Recording.2026-06-18.at.22.32.53.mp4
What changed
dt_masks_form_t.sourcegrows fromfloat[2](dx, dy) tofloat[3](dx, dy, angle). Reading is length-aware (handles 2/3/4-float blobs), the DB write/hash use 3 floats, andduplicate/XMP round-trip the new field. Old edits load unchanged (angle = 0); downgrades degrade gracefully (the angle is simply dropped).rt_copy_in_to_out(C + the two OpenCL kernels) gains a rotated path: each destination pixel samples the source bilinearly undercentroid + R(angle)·offset. The non-rotated path is unchanged (fastmemcpy).CTRL+drag— rotate the shape under the pointer (target, or source on a clone source).CTRL+SHIFT+drag— rotate target and source together.source[2]angle.SHIFT+clickto add a node on a path/brush segment (previouslyCTRL+click), sinceCTRLis now the rotate modifier. Path creation (ctrl+click= sharp node) is unchanged.Key design choices
.xmpsidecars and the library DB interoperable across versions.dt_masks_get_source_area. It already appliessource[2], so it yields the true rotated source footprint pivot-agnostically — simpler and more correct than reconstructing a rotated AABB. Edge-clamping then covers the residual cases the ROI can't (image border, masked-out box corners), avoiding black seams in heal.Co-authored with Claude.