From ca1a8a12bceda169f55f700ae3fbfe034c03c728 Mon Sep 17 00:00:00 2001 From: aiongg <67543387+aiongg@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:49:56 -0400 Subject: [PATCH] Place: an image placed into a frame leaves Auto-Fit off (#528) * Place: an image placed into a frame fills it once and leaves Auto-Fit off * Place: the fitting test names its fitting, since a placed image no longer auto-fits --- crates/engine/src/cmd/file.rs | 6 +++--- crates/engine/src/cmd/object.rs | 4 ++-- crates/engine/src/tests.rs | 10 +++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/engine/src/cmd/file.rs b/crates/engine/src/cmd/file.rs index 3a2885c..a0c98f6 100644 --- a/crates/engine/src/cmd/file.rs +++ b/crates/engine/src/cmd/file.rs @@ -351,14 +351,14 @@ fn file_place(s: &mut Session, p: &Value) -> Result { let id = if let Some(fid) = target_frame { let it = d.item_mut(fid).ok_or(designcraft_doc::DocError::NoItem(fid))?; let r = it.inner_bounds(); - // Fill frame proportionally. + // Fill the frame proportionally once. Auto-Fit stays off, so resizing the frame crops. let k = (r.width() / nw).max(r.height() / nh); let (gw, gh) = (nw * k, nh * k); it.content = Content::Graphic(Graphic { asset: aid, size: (nw, nh), xf: Affine::translate((r.x0 + (r.width() - gw) / 2.0, r.y0 + (r.height() - gh) / 2.0)) * Affine::scale(k), - auto_fit: designcraft_doc::Fitting::FillProportionally, + auto_fit: Default::default(), fit_align: 4, crop: [0.0; 4], }); @@ -473,7 +473,7 @@ fn place_drop(s: &mut Session, p: &Value) -> Result { asset: aid, size: (nw, nh), xf: Affine::translate((r.x0 + (r.width() - nw * k) / 2.0, r.y0 + (r.height() - nh * k) / 2.0)) * Affine::scale(k), - auto_fit: designcraft_doc::Fitting::FillProportionally, + auto_fit: Default::default(), fit_align: 4, crop: [0.0; 4], }); diff --git a/crates/engine/src/cmd/object.rs b/crates/engine/src/cmd/object.rs index 17c44c2..c4f2562 100644 --- a/crates/engine/src/cmd/object.rs +++ b/crates/engine/src/cmd/object.rs @@ -2463,8 +2463,8 @@ mod fitting_tests { s.execute("object.fittingOptions", &json!({"ids": [f], "fitting": "fitProportionally", "align": 0})).unwrap(); let c = content(&s); assert!((c.x0 - 100.0).abs() < 1e-6 && (c.y0 - 100.0).abs() < 1e-6 && (c.width() - 200.0).abs() < 1e-6, "{c:?}"); - // Crop 10 pt on every side: the content spreads past the frame. - s.execute("object.fittingOptions", &json!({"ids": [f], "crop": 10, "align": 4})).unwrap(); + // Crop 10 pt on every side and fit again: the content spreads past the frame. + s.execute("object.fittingOptions", &json!({"ids": [f], "fitting": "fitProportionally", "crop": 10, "align": 4})).unwrap(); let c = content(&s); assert!((c.width() - 220.0).abs() < 1e-6, "{c:?}"); // Auto-fit: resizing the frame refits the content. diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index c1032bc..17d1ed0 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -284,7 +284,15 @@ fn place_gun_click_drag_and_into_frame() { let f = s.execute("frame.create", &json!({"rect": [300, 300, 400, 400], "content": "graphic"})).unwrap()["id"].as_u64().unwrap(); s.execute("place.load", &json!({"base64": b64})).unwrap(); s.execute("place.drop", &json!({"frame": f})).unwrap(); - assert!(matches!(s.doc().unwrap().doc.item(designcraft_doc::ItemId(f)).unwrap().content, designcraft_doc::Content::Graphic(_))); + let graphic_xf = |s: &Session| match &s.doc().unwrap().doc.item(designcraft_doc::ItemId(f)).unwrap().content { + designcraft_doc::Content::Graphic(g) => g.xf, + _ => panic!("not a graphic"), + }; + let placed = graphic_xf(&s); + // Dragging the top edge down crops the top only: the image stays where it is. + s.execute("selection.set", &json!({"ids": [f]})).unwrap(); + s.execute("transform.resize", &json!({"from": [300, 300, 400, 400], "to": [300, 340, 400, 400]})).unwrap(); + assert_eq!(graphic_xf(&s), placed); } #[test]