mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 19:22:48 +00:00
Expand Appearance: tinted symbols keep their colors under a color adjustment
Expand Appearance on a symbol instance with a fill tint and a color adjustment applied the adjustment to the untinted art, so the expanded colors differed from the canvas. The expand path now passes the tinted instance art to adjust_in_document.
This commit is contained in:
@@ -468,12 +468,14 @@ pub fn adjust(n: &Node, outer: Option<&ColorMap>, swatches: &SwatchKinds, images
|
||||
}
|
||||
|
||||
/// [`adjust`] for export and Expand Appearance: recoloured embedded images become new images in
|
||||
/// `d` (named by their content), and a symbol instance stands for its symbol's art.
|
||||
pub fn adjust_in_document(d: &mut Document, n: &Node) -> Option<Node> {
|
||||
/// `d` (named by their content), and a symbol instance stands for its symbol's art: `symbol_art`
|
||||
/// when given, otherwise the symbol's art with the instance's own appearance changes.
|
||||
pub fn adjust_in_document(d: &mut Document, n: &Node, symbol_art: Option<Node>) -> Option<Node> {
|
||||
let art;
|
||||
let src = match &n.kind {
|
||||
NodeKind::SymbolInstance { symbol, .. } if has_adjustment(n) => {
|
||||
let symbol = d.symbols.iter().find(|s| s.name == *symbol).map(|s| vectorcraft_doc::symbol_overrides::dynamic_art(&s.art, n));
|
||||
let symbol = symbol_art
|
||||
.or_else(|| d.symbols.iter().find(|s| s.name == *symbol).map(|s| vectorcraft_doc::symbol_overrides::dynamic_art(&s.art, n)));
|
||||
art = crate::reshape::as_art(Some(d), n, symbol.as_ref())?;
|
||||
&art
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ fn bake_node(d: &mut Document, n: &Node) -> Option<Node> {
|
||||
}
|
||||
// Colour adjustments: the object recoloured (inside it too), then baked as it is.
|
||||
if has_adjustment(n)
|
||||
&& let Some(m) = adjust_in_document(d, n)
|
||||
&& let Some(m) = adjust_in_document(d, n, None)
|
||||
{
|
||||
return Some(bake_node(d, &m).unwrap_or(m));
|
||||
}
|
||||
|
||||
@@ -814,8 +814,15 @@ fn expanded_node(d: &mut Document, mut n: Node, brushes: &[vectorcraft_brush::Br
|
||||
let mut changed = false;
|
||||
// Is `n` in `out` yet?
|
||||
let mut listed_n = false;
|
||||
// A symbol instance's fill tints its art before the adjustment, as the canvas draws it.
|
||||
let symbol_art = match &n.kind {
|
||||
NodeKind::SymbolInstance { symbol, .. } if effects::has_adjustment(&n) => {
|
||||
d.symbols.iter().find(|s| s.name == *symbol).map(|s| vectorcraft_render::instance_art(&s.art, &n))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
if effects::has_adjustment(&n)
|
||||
&& let Some(m) = effects::adjust_in_document(d, &n)
|
||||
&& let Some(m) = effects::adjust_in_document(d, &n, symbol_art)
|
||||
{
|
||||
out.push((id, 0));
|
||||
listed_n = true;
|
||||
|
||||
@@ -75,6 +75,29 @@ fn symbol_instance_tint_survives_expanding_an_object_effect() {
|
||||
assert!(differing(&before, &after, 8) < 200, "expanding changed {} pixels", differing(&before, &after, 8));
|
||||
}
|
||||
|
||||
/// The canvas tints a symbol's art with the instance fill before the instance's color adjustment,
|
||||
/// and expanding gives the same colors.
|
||||
#[test]
|
||||
fn symbol_instance_tint_comes_before_a_color_adjustment_when_expanded() {
|
||||
let mut s = session();
|
||||
square(&mut s);
|
||||
let id = NodeId(run(&mut s, "symbol.new", json!({"name": "Tinted Square"}))["id"].as_u64().unwrap());
|
||||
run(&mut s, "appearance.addFill", json!({"ids": [id.0]}));
|
||||
let fill = node(&s, id).appearance.items.len() - 1;
|
||||
run(&mut s, "appearance.setItem", json!({"ids": [id.0], "index": fill, "color": "#00ff00", "opacity": 50}));
|
||||
run(&mut s, "effect.apply", json!({"ids": [id.0], "item": null, "effect": "adjust.hueSaturation", "params": {"hue": 120}}));
|
||||
let before = render(&s);
|
||||
assert_ne!(before.pixel(100, 100), [255, 255, 255, 255], "the symbol is visible");
|
||||
assert!(expandable(&s));
|
||||
|
||||
run(&mut s, "effect.expandAppearance", json!({}));
|
||||
assert!(!matches!(node(&s, id).kind, NodeKind::SymbolInstance { .. }));
|
||||
let after = render(&s);
|
||||
let (b, a) = (before.pixel(100, 100), after.pixel(100, 100));
|
||||
assert!(b.iter().zip(a.iter()).all(|(x, y)| x.abs_diff(*y) <= 8), "expanding changed the color from {b:?} to {a:?}");
|
||||
assert!(differing(&before, &after, 8) < 200, "expanding changed {} pixels", differing(&before, &after, 8));
|
||||
}
|
||||
|
||||
/// An instance fill with an opacity of 0 does not tint the symbol's art, so expanding keeps the
|
||||
/// art's global swatch link.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user