Fix #3233: dimensions are redrawn in the colour mode after Document Color Mode and on open

Follow-up to #3702 (CodeRabbit): dimensions are only redrawn when their
recipe changes. Document Color Mode converted their art through the colour
profile, so black became a four-ink C67 M67 Y67 K100 again, and CMYK files
saved before #3702 kept RGB dimension art.

dimension::refresh now also redraws when the document's colour mode
changes. dimension::conform, run when a document is opened or reverted
(Session::add_document, replace_document), redraws a dimension whose art
has colours in the wrong model; one that can't be redrawn keeps its art.

dimension_colours_follow_the_document_colour_model covers RGB to CMYK and
back, and a CMYK document with RGB dimension art being opened. Without the
change it finds C0.67 M0.67 Y0.67 K1 after Document Color Mode.
This commit is contained in:
Taha-Mahmoodi
2026-10-23 04:26:05 +07:00
committed by bflatastic
parent d288319e26
commit 3d24c663d2
3 changed files with 50 additions and 1 deletions
+33 -1
View File
@@ -227,13 +227,45 @@ pub(crate) fn refresh(before: &Document, doc: &mut Document) -> Result<()> {
next.moved = None;
}
}
if next != old || before.node(id).and_then(|n| n.extras().dimension.as_deref()).is_some_and(|d| d != &next) {
// A new document colour mode (Document Color Mode) redraws every dimension in it.
if next != old
|| before.color_mode != doc.color_mode
|| before.node(id).and_then(|n| n.extras().dimension.as_deref()).is_some_and(|d| d != &next)
{
replace(doc, id, next)?;
}
}
Ok(())
}
/// Redraw the dimensions of an opened document whose art isn't in its colour mode: files saved
/// before dimensions followed the colour mode have RGB dimensions in CMYK documents. A dimension
/// that can't be redrawn keeps the art it has.
pub(crate) fn conform(doc: &mut Document) {
if !doc.dimensions {
return;
}
let mode = doc.color_mode;
let off_mode = |c: &Color| match mode {
ColorMode::Rgb => matches!(c, Color::Cmyk { .. }),
ColorMode::Cmyk => matches!(c, Color::Rgb { .. }),
};
let mut stale = Vec::new();
doc.walk(|n| {
if let Some(d) = &n.extras().dimension {
let mut off = false;
n.walk(&mut |c| off |= [c.appearance.fill_paint(), c.appearance.stroke_paint()].iter().filter_map(|p| p.color()).any(|c| off_mode(&c)));
if off {
stale.push((n.id, (**d).clone()));
}
}
});
for (id, d) in stale {
// An error leaves this dimension as it was; the others are still redrawn.
let _ = replace(doc, id, d);
}
}
/// Option colour `c` as a paint in the document's colour model: in a CMYK document black is K
/// only (a rich four-ink black would print a black dimension in every plate) and other colours
/// convert through the active colour settings.
+2
View File
@@ -1587,6 +1587,7 @@ impl Session {
Self::refresh_text_bounds(&mut doc);
// Guides from files saved before guides had layers go on a layer.
doc.adopt_guides();
cmd::dimension::conform(&mut doc);
self.reset_tool_for_doc_switch();
let mut st = DocState::new(doc, path);
st.history.limit = self.prefs.history_states as usize;
@@ -1604,6 +1605,7 @@ impl Session {
doc.limit_depth();
Self::refresh_text_bounds(&mut doc);
doc.adopt_guides();
cmd::dimension::conform(&mut doc);
if self.active == Some(index) {
// Pending tool work (typing, a drag) belongs to the content being thrown away.
self.reset_tool_for_doc_switch();
+15
View File
@@ -505,4 +505,19 @@ fn dimension_colours_follow_the_document_colour_model() {
let line = edge(&mut s);
let id = dim(&mut s, line);
assert!(colours(&s, id).iter().all(|c| *c == vectorcraft_color::Color::rgb8(0, 0, 0)));
// Document Color Mode redraws dimensions in the new mode: K-only black in CMYK, RGB black back
// in RGB (not a profile conversion of the old art).
let k = vectorcraft_color::Color::cmyk(0.0, 0.0, 0.0, 1.0);
run(&mut s, "file.documentColorMode", json!({"mode":"cmyk"}));
let after = colours(&s, id);
assert!(!after.is_empty() && after.iter().all(|c| *c == k), "{after:?}");
run(&mut s, "file.documentColorMode", json!({"mode":"rgb"}));
assert!(colours(&s, id).iter().all(|c| *c == vectorcraft_color::Color::rgb8(0, 0, 0)), "{:?}", colours(&s, id));
// A CMYK file saved with RGB dimension art (before dimensions followed the colour mode) opens
// with its dimensions redrawn in CMYK.
let mut old = (*s.doc().unwrap().doc).clone();
old.color_mode = vectorcraft_doc::ColorMode::Cmyk;
s.add_document(old, None);
let opened = colours(&s, id);
assert!(!opened.is_empty() && opened.iter().all(|c| *c == k), "{opened:?}");
}