Merge pull request #4056 from marcoarnulfo/fix/set-bounds-compound-member

Properties and Transform: X, Y, W and H of a compound path's member set only that path
This commit is contained in:
Brandon Thomas
2026-10-25 10:37:22 -04:00
committed by GitHub
2 changed files with 29 additions and 1 deletions
+1 -1
View File
@@ -1804,7 +1804,7 @@ fn distribute_spacing(s: &mut Session, p: &Value) -> Result<Value> {
}
fn set_bounds(s: &mut Session, p: &Value) -> Result<Value> {
match bounds_transform(s, p, selected_roots(s)?, 0.0)? {
match bounds_transform(s, p, selected_roots_to_transform(s)?, 0.0)? {
Bounds::Anchors(ids, b) => set_anchor_bounds(s, p, ids, b),
Bounds::Objects(ids, xf) => apply_transform(s, "Transform", ids, xf, p, false),
}
+28
View File
@@ -2451,6 +2451,34 @@ fn an_isolated_compound_paths_member_moves_alone() {
assert_eq!((x0(&s, outer), x0(&s, hole)), (5.0, 55.0), "the compound path selected: the whole ring");
}
/// The X, Y, W and H of the Properties and Transform panels run `object.setBounds`, which takes the
/// same objects as the other transforms: a path of a compound path selected alone sets its own
/// box and leaves the ring around it (#4046). The hole is off-centre, and a plain rectangle
/// outside the ring keeps "everything moved" from passing.
#[test]
fn set_bounds_of_a_compound_paths_member_sets_only_that_path() {
let x = |s: &Session, id: NodeId| {
let b = s.doc().unwrap().doc.node(id).unwrap().geometric_bounds().unwrap();
(b.x0, b.x1)
};
let mut s = session();
let (c, outer, hole) = isolated_ring(&mut s);
let other = rect(&mut s, 100.0, 0.0, 10.0, 10.0);
s.execute("select.set", &json!({"ids": [hole.0]})).unwrap();
s.execute("object.setBounds", &json!({"width": 20, "reference": 0})).unwrap();
assert_eq!((x(&s, outer), x(&s, hole)), ((0.0, 40.0), (10.0, 30.0)), "isolated: only the hole is wider");
s.execute("object.setBounds", &json!({"x": 25, "reference": 0})).unwrap();
assert_eq!((x(&s, outer), x(&s, hole)), ((0.0, 40.0), (25.0, 45.0)), "isolated: only the hole moved");
s.execute("object.exitIsolation", &json!({})).unwrap();
s.execute("select.set", &json!({"ids": [hole.0]})).unwrap();
s.execute("object.setBounds", &json!({"x": 12, "reference": 0})).unwrap();
assert_eq!((x(&s, outer), x(&s, hole)), ((0.0, 40.0), (12.0, 32.0)), "not isolated: still only the hole");
s.execute("select.set", &json!({"ids": [c.0]})).unwrap();
s.execute("object.setBounds", &json!({"x": 5, "reference": 0})).unwrap();
assert_eq!((x(&s, outer), x(&s, hole)), ((5.0, 45.0), (17.0, 37.0)), "the compound path selected: the whole ring");
assert_eq!(x(&s, other), (100.0, 110.0), "the rectangle outside never moves");
}
/// `depth` and `childLimit` slice a summary read; a level that shows fewer children
/// than it has reports `childCount`, and invalid values are rejected, not reinterpreted.
#[test]