mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-29 04:46:50 -06:00
Keep a styled layer's fill variable through .fig round trips
Fixes #399 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
102404e8c3
commit
f6437548ba
@@ -450,6 +450,38 @@ fn shared_styles_and_their_links_round_trip() {
|
||||
assert_eq!(named(&nodes, "Title")["styleIdForText"]["guid"], named(&nodes, "Heading")["guid"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_styled_layers_fill_variable_survives_a_round_trip() {
|
||||
let mut doc = Document::new("Overlap");
|
||||
let page = doc.first_page().unwrap();
|
||||
let mode = |id: &str, name: &str| Mode { id: id.into(), name: name.into() };
|
||||
doc.variables.collections =
|
||||
vec![Collection { id: "c-theme".into(), name: "Theme".into(), modes: vec![mode("m-light", "Light"), mode("m-dark", "Dark")], extends: None }];
|
||||
let light = Color::new(0.1, 0.3, 0.7, 1.0);
|
||||
let dark = VariableValue::Color(Color::new(0.8, 0.9, 1.0, 1.0));
|
||||
doc.variables.variables =
|
||||
vec![var("v-accent", "Accent color", "c-theme", VariableType::Color, &[("m-light", VariableValue::Color(light)), ("m-dark", dark)])];
|
||||
doc.styles = vec![Style {
|
||||
id: "s-accent".into(),
|
||||
name: "Accent".into(),
|
||||
description: String::new(),
|
||||
kind: StyleKind::Paint { paints: vec![Paint::solid(light)] },
|
||||
bound: Default::default(),
|
||||
}];
|
||||
add(&mut doc, page, NodeKind::Rectangle, "Swatch", (0.0, 0.0), (120.0, 80.0), &|n| {
|
||||
n.fills = vec![Paint::solid(light)];
|
||||
n.styles.fill = Some("s-accent".into());
|
||||
n.bound.insert("fill".into(), "v-accent".into());
|
||||
});
|
||||
let (back, _) = import(&export(&doc, None).unwrap().0, "x").unwrap();
|
||||
let var = back.variables.variables.iter().find(|v| v.name == "Accent color").unwrap().id.clone();
|
||||
let swatch = back.nodes().find(|n| n.name == "Swatch").unwrap();
|
||||
let on_layer = swatch.bound.get("fill") == Some(&var) || swatch.bound.get("fills/0/color") == Some(&var);
|
||||
let style = back.styles.iter().find(|s| Some(&s.id) == swatch.styles.fill.as_ref()).unwrap();
|
||||
let on_style = style.bound.get("fills/0/color") == Some(&var);
|
||||
assert!(on_layer || on_style, "the fill binding was lost: layer {:?}, style {:?}", swatch.bound, style.bound);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_styles_on_part_of_a_text_are_written_as_values() {
|
||||
let mut doc = styled();
|
||||
|
||||
@@ -492,13 +492,17 @@ impl<'a> Mapper<'a> {
|
||||
}
|
||||
let t = v.get("transform").and_then(matrix).unwrap_or_default();
|
||||
o.insert("relativeTransform".into(), rows(space * t));
|
||||
// Paints, from the shared style when one is linked (the layer's own copy can be stale).
|
||||
// Paints, from the shared style when one is linked (the layer's own copy can be stale),
|
||||
// unless the layer's own paints are bound to variables: those bindings must not be lost.
|
||||
let mut styles = Obj::new();
|
||||
let own = |k: &str| Some(v.list(k)).filter(|l| l.iter().any(paint_bound));
|
||||
let fill_style = self.style(v, "styleIdForFill", "inheritFillStyleID", "fill", &mut styles);
|
||||
let fills = fill_style.map_or_else(|| v.list("fillPaints"), |s| s.get("fillPaints").map(Kv::list).unwrap_or_default());
|
||||
let fills = own("fillPaints")
|
||||
.unwrap_or_else(|| fill_style.map_or_else(|| v.list("fillPaints"), |s| s.get("fillPaints").map(Kv::list).unwrap_or_default()));
|
||||
o.insert("fills".into(), Value::Array(fills.iter().filter_map(paint).collect()));
|
||||
let stroke_style = self.style(v, "styleIdForStrokeFill", "inheritFillStyleIDForStroke", "stroke", &mut styles);
|
||||
let strokes = stroke_style.map_or_else(|| v.list("strokePaints"), |s| s.get("fillPaints").map(Kv::list).unwrap_or_default());
|
||||
let strokes = own("strokePaints")
|
||||
.unwrap_or_else(|| stroke_style.map_or_else(|| v.list("strokePaints"), |s| s.get("fillPaints").map(Kv::list).unwrap_or_default()));
|
||||
o.insert("strokes".into(), Value::Array(strokes.iter().filter_map(paint).collect()));
|
||||
let effect_style = self.style(v, "styleIdForEffect", "inheritEffectStyleID", "effect", &mut styles);
|
||||
let effects = effect_style.map_or_else(|| v.list("effects"), |s| s.get("effects").map(Kv::list).unwrap_or_default());
|
||||
@@ -1387,6 +1391,11 @@ fn child_layout(o: &mut Obj, v: &View, parent: Option<&View>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a paint's colour or one of its gradient stops is bound to a variable.
|
||||
fn paint_bound(p: &Kv) -> bool {
|
||||
alias(p.get("colorVar")).is_some() || p.get("stopsVar").map(Kv::list).unwrap_or_default().iter().any(|s| alias(s.get("colorVar")).is_some())
|
||||
}
|
||||
|
||||
fn paint(p: &Kv) -> Option<Value> {
|
||||
let ty = p.get("type").and_then(Kv::str)?;
|
||||
let mut o = Obj::new();
|
||||
|
||||
Reference in New Issue
Block a user