From fc8d4472e61686066c0fbeee7bb7817a7ae60827 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Thu, 12 Nov 2026 06:59:50 -0800 Subject: [PATCH] Color management: assigning the working profiles keeps the active color settings edit.assignProfile replaced the active color context whenever it tagged a document, even when the profiles it assigned were the working spaces already in use. The new context has the same settings, but renderers key their cached effect images on it, so every open document was redrawn and every cached blur, shadow or glow image was drawn again. The command now sets the active settings, and raises the open documents' revisions so they redraw, only when the working spaces it assigns differ from the active ones, as edit.colorSettings already does. This also fixes an intermittent failure of the test canvas::tests::a_drag_over_a_wide_blur_draws_the_blur_from_the_still_frame. The Document Setup tests assign the working profiles while it runs, and its drag frames then drew the blur again instead of reusing the still frame's image. --- crates/engine/src/cmd/colormgmt.rs | 7 +++++-- crates/engine/src/tests/colormgmt.rs | 17 +++++++++++++++++ crates/engine/tests/color_settings.rs | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/cmd/colormgmt.rs b/crates/engine/src/cmd/colormgmt.rs index da7dc42ece..9ec21b6541 100644 --- a/crates/engine/src/cmd/colormgmt.rs +++ b/crates/engine/src/cmd/colormgmt.rs @@ -274,14 +274,17 @@ fn assign_profile(s: &mut Session, p: &Value) -> Result { Ok(()) })?; let mut st = cms::active_settings(); + let before = st.clone(); if let Some(r) = &rgb { st.rgb = r.clone(); } if let Some(c) = &cmyk { st.cmyk = c.clone(); } - cms::set_active(&st).map_err(|e| bad(C, e.to_string()))?; - touch_all(s); + if st != before { + cms::set_active(&st).map_err(|e| bad(C, e.to_string()))?; + touch_all(s); + } } Ok(json!({"rgb": rgb, "cmyk": cmyk})) } diff --git a/crates/engine/src/tests/colormgmt.rs b/crates/engine/src/tests/colormgmt.rs index d0901f30a0..ae8ac0c4f0 100644 --- a/crates/engine/src/tests/colormgmt.rs +++ b/crates/engine/src/tests/colormgmt.rs @@ -308,6 +308,23 @@ fn assign_profile_is_stored_and_undoable() { assert_eq!(cmd::colormgmt::doc_profiles(&s.doc().unwrap().doc), (None, None)); } +/// Assigning the working profiles leaves the active color settings and the other documents' +/// revisions unchanged. +#[test] +fn assigning_the_working_profiles_keeps_the_active_color_settings() { + let _g = GLOBAL.lock().unwrap_or_else(|e| e.into_inner()); + let mut s = session(); + s.execute("file.new", &json!({"width": 100, "height": 100})).unwrap(); + let working = cms::active_settings(); + let active = cms::active(); + let other = s.documents()[0].revision; + let r = s.execute("edit.assignProfile", &json!({"rgb": working.rgb, "cmyk": working.cmyk})).unwrap(); + assert_eq!((r["rgb"].as_str(), r["cmyk"].as_str()), (Some(working.rgb.as_str()), Some(working.cmyk.as_str()))); + assert_eq!(cmd::colormgmt::doc_profiles(&s.doc().unwrap().doc), (Some(working.rgb.clone()), Some(working.cmyk.clone()))); + assert!(std::sync::Arc::ptr_eq(&active, &cms::active()), "the active color settings were replaced"); + assert_eq!(s.documents()[0].revision, other, "the other document's revision changed"); +} + #[test] fn proof_colors_simulate_press_on_screen() { let _g = GLOBAL.lock().unwrap_or_else(|e| e.into_inner()); diff --git a/crates/engine/tests/color_settings.rs b/crates/engine/tests/color_settings.rs index 0cc0edc4d4..c84921f6de 100644 --- a/crates/engine/tests/color_settings.rs +++ b/crates/engine/tests/color_settings.rs @@ -57,6 +57,24 @@ fn legacy_profile_name_resolves_in_commands_and_files() { cms::set_active(&before).unwrap(); } +/// Assigning a profile other than the working space replaces the active color settings and raises +/// the other open documents' revisions. +#[test] +fn assigning_another_profile_replaces_the_active_color_settings() { + let _g = settings(); + let mut s = session(); + exec(&mut s, "file.new", json!({"width": 100, "height": 100})); + let before = cms::active_settings(); + assert_ne!(before.cmyk, cms::DEVICE_CMYK); + let active = cms::active(); + let other = s.documents()[0].revision; + exec(&mut s, "edit.assignProfile", json!({"cmyk": cms::DEVICE_CMYK})); + assert_eq!(cms::active_settings().cmyk, cms::DEVICE_CMYK); + assert!(!std::sync::Arc::ptr_eq(&active, &cms::active()), "the active color settings were not replaced"); + assert!(s.documents()[0].revision > other, "the other document's revision did not change"); + cms::set_active(&before).unwrap(); +} + /// Separations Preview follows the Color Settings and the profiles loaded: a renderer draws a gray /// square on the Black plate through the new working CMYK profile, and the four process plates /// through a proof profile loaded again under the same name, as a new renderer draws them.