mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 21:27:00 -06:00
Merge pull request #4705 from dotCooCoo/fix/trace-library-global-swatch-same-color
Image Trace: Document Library links to a global swatch that shares a process swatch's color
This commit is contained in:
@@ -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<Val
|
||||
let unit = xf.determinant().abs().sqrt();
|
||||
let (npaths, anchors, colors) = (res.paths.len(), res.anchor_count(), res.palette.len());
|
||||
let label = if expand { "Image Trace (Make and Expand)" } else { "Image Trace" };
|
||||
// A library color fills with the swatch's own color (its model kept), linked to a
|
||||
// global or spot swatch of the document. Of the swatches that trace as this color,
|
||||
// the first linked one is taken, else the first. Build the lookup once per trace.
|
||||
let mut by_color: HashMap<[u8; 3], &Paint> = 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<Val
|
||||
*path = shape.to_path();
|
||||
*live = Some(Box::new(shape));
|
||||
}
|
||||
// A library color fills with the swatch's own color (its model kept), linked to a
|
||||
// global or spot swatch of the document.
|
||||
let solid = library
|
||||
.iter()
|
||||
.find(|(rgb, _)| *rgb == tp.color)
|
||||
.map_or_else(|| Paint::solid(Color::rgb8(tp.color[0], tp.color[1], tp.color[2])), |l| l.1.clone());
|
||||
let solid =
|
||||
by_color.get(&tp.color).map_or_else(|| Paint::solid(Color::rgb8(tp.color[0], tp.color[1], tp.color[2])), |paint| (*paint).clone());
|
||||
// Gradients: a path the tracer found to be a linear gradient is filled with it.
|
||||
let paint = tp.gradient.as_ref().map_or(solid, |g| traced_gradient(g, xf));
|
||||
n.appearance = match tp.stroke {
|
||||
|
||||
@@ -3178,6 +3178,43 @@ fn image_trace_document_library_links_fills_to_global_swatches() {
|
||||
assert!(!got.is_empty() && got.iter().all(|f| f.1.is_none()), "{got:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn image_trace_document_library_links_to_a_global_swatch_after_a_process_swatch_of_its_color() {
|
||||
let mut s = session();
|
||||
// A process swatch, then two global swatches, all of one color.
|
||||
s.execute("swatch.new", &json!({"name": "Red", "color": "#c82828"})).unwrap();
|
||||
s.execute("swatch.new", &json!({"name": "Ink", "color": "#c82828", "global": true})).unwrap();
|
||||
s.execute("swatch.new", &json!({"name": "Ink 2", "color": "#c82828", "global": true})).unwrap();
|
||||
s.execute("swatch.new", &json!({"name": "Leaf", "color": "#28a03c"})).unwrap();
|
||||
s.execute("swatch.new", &json!({"name": "Sky", "color": "#2846c8", "global": true})).unwrap();
|
||||
let [tr, tg, tb, _] = s.doc().unwrap().doc.tint_paint("Sky", 0.5).unwrap().color().unwrap().to_rgba8(1.0);
|
||||
let tint_hex = format!("#{tr:02x}{tg:02x}{tb:02x}");
|
||||
s.execute("swatch.new", &json!({"name": "Mist", "color": tint_hex})).unwrap();
|
||||
s.execute("swatch.new", &json!({"swatch": "Sky", "tint": 50})).unwrap();
|
||||
let r = vectorcraft_trace::Raster::from_fn(60, 60, |x, _| match x {
|
||||
0..20 => [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<Paint> = 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());
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user