diff --git a/crates/engine/src/cmd/buildcmds/trace.rs b/crates/engine/src/cmd/buildcmds/trace.rs index 308e300ec..832219d5f 100644 --- a/crates/engine/src/cmd/buildcmds/trace.rs +++ b/crates/engine/src/cmd/buildcmds/trace.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use vectorcraft_color::Swatch; use vectorcraft_doc::ImageObject; @@ -557,6 +559,16 @@ pub(super) fn trace_make(s: &mut Session, p: &Value, expand: bool) -> Result = HashMap::new(); + for (rgb, paint) in &library { + let chosen = by_color.entry(*rgb).or_insert(paint); + if !matches!(**chosen, Paint::Solid { swatch: Some(_), .. }) && matches!(paint, Paint::Solid { swatch: Some(_), .. }) { + *chosen = paint; + } + } let id = s.edit(label, |d, sel| { let src = d.node(target).cloned().ok_or(EngineError::NoNode(target))?; let mut image = if is_trace_group(&src) { @@ -584,12 +596,8 @@ pub(super) fn trace_make(s: &mut Session, p: &Value, expand: bool) -> Result [200, 40, 40, 255], + 20..40 => [40, 160, 60, 255], + _ => [tr, tg, tb, 255], + }); + add_image(&mut s, &r, Affine::IDENTITY); + let params = json!({"mode": "color", "palette": "documentLibrary", "library": "document", "colors": 8}); + let res = s.execute("imageTrace.makeAndExpand", &json!({"params": params})).unwrap(); + let g = node(&s, NodeId(res["id"].as_u64().unwrap())); + let got: Vec = g.children().unwrap().iter().map(|n| n.appearance.fill_paint()).collect(); + let red = Color::rgb8(200, 40, 40); + let reds: Vec<&Paint> = got.iter().filter(|p| p.color().map(|c| c.to_rgba8(1.0)) == Some(red.to_rgba8(1.0))).collect(); + assert!(!reds.is_empty(), "{got:?}"); + assert!(reds.iter().all(|p| matches!(p, Paint::Solid { swatch: Some(w), .. } if w == "Ink")), "{got:?}"); + let tints: Vec<&Paint> = got.iter().filter(|p| p.color().map(|c| c.to_rgba8(1.0)) == Some([tr, tg, tb, 255])).collect(); + assert!(!tints.is_empty(), "{got:?}"); + assert!(tints.iter().all(|p| matches!(p, Paint::Solid { swatch: Some(w), tint, .. } if w == "Sky" && *tint == 0.5)), "{got:?}"); + // Editing the global swatch recolors the trace. + s.execute("swatch.edit", &json!({"name": "Ink", "color": "#ff8800"})).unwrap(); + let g = node(&s, NodeId(res["id"].as_u64().unwrap())); + let orange = Color::rgb8(255, 136, 0).to_rgba8(1.0); + assert!(g.children().unwrap().iter().any(|n| n.appearance.fill_paint().color().map(|c| c.to_rgba8(1.0)) == Some(orange))); +} + #[test] fn image_trace_document_library_matches_a_lab_spot_by_its_cmyk_equivalent() { let _g = crate::tests_colormgmt::GLOBAL.lock().unwrap_or_else(|e| e.into_inner()); diff --git a/docs/image-trace-adjustments.md b/docs/image-trace-adjustments.md index b124de96a..0de13b953 100644 --- a/docs/image-trace-adjustments.md +++ b/docs/image-trace-adjustments.md @@ -49,7 +49,9 @@ and traces as All. **Document Library linked colors.** With Library › Document Swatches, with or without a color group, a traced fill or stroke whose color comes from a global or spot swatch is linked to that swatch, and one whose color comes from a tint swatch is linked to its base at the tint. Editing the swatch -recolors the trace. Colors from process swatches and from swatch libraries are not linked. +recolors the trace. Colors from process swatches and from swatch libraries are not linked. When +several swatches show the same color, the first of them in the list that is a global, spot or tint +swatch gives the link. **Document Library** traces with the library's colors as they are. Each pixel takes the library color nearest to it in lightness and hue, with a difference in hue or chroma counted three times