diff --git a/crates/format/src/fig/export/shape.rs b/crates/format/src/fig/export/shape.rs index 6b70b6c62..9ef7b2077 100644 --- a/crates/format/src/fig/export/shape.rs +++ b/crates/format/src/fig/export/shape.rs @@ -381,7 +381,11 @@ impl<'d> Exporter<'d> { if let Some(main) = main { let main_ok = matches!(&main.kind, NodeKind::Text(m) if text_path_net(m, main.width, main.height).is_ok()); if main_ok != own.is_ok() { - self.warn(TEXT_PATH_INSTANCE); + // An override can't take its layer off the main's path. So an instance text of + // more than one line, on a main that is on a path, stays on that path in the file: + // say so rather than the general mismatch (FigCraft's import reads it as plain text). + let lines = main_ok && matches!(own, Err(TEXT_PATH_LINES)); + self.warn(if lines { TEXT_PATH_INSTANCE_LINES } else { TEXT_PATH_INSTANCE }); return None; } } @@ -414,6 +418,8 @@ const TEXT_PATH_CANT: &str = "text on a path the format can't hold was written a const TEXT_PATH_PARTS: &str = "the parts of a text's path after the first were left out"; const TEXT_PATH_INSTANCE: &str = "text on a path in an instance but not in its main component, or the other way round, was written as the main has it"; +const TEXT_PATH_INSTANCE_LINES: &str = + "an instance's text of more than one line stays on its main component's text path in the file, as an override can't take it off"; /// A text's path as the format holds it: one chain (or cycle) of a vector network with the /// segment the text starts on marked, and the start as that segment's own parameter. diff --git a/crates/format/src/fig/text_path_tests.rs b/crates/format/src/fig/text_path_tests.rs index 154b9015d..ec1e20bdd 100644 --- a/crates/format/src/fig/text_path_tests.rs +++ b/crates/format/src/fig/text_path_tests.rs @@ -275,6 +275,8 @@ const W1: &str = "text on a path with more than one line was written as plain te const W2: &str = "text on a path the format can't hold was written as plain text"; const W3: &str = "the parts of a text's path after the first were left out"; const W4: &str = "text on a path in an instance but not in its main component, or the other way round, was written as the main has it"; +const W4_LINES: &str = + "an instance's text of more than one line stays on its main component's text path in the file, as an override can't take it off"; const MARK: u32 = 0x01ff_ffff; /// What an export wrote: its warnings, the layer records and the blobs. @@ -557,6 +559,15 @@ fn an_instance_layer_on_a_path_survives_a_fig_export() { let (back, _) = super::import(&bytes, "Back").unwrap(); assert_eq!(path_of(&back, "Half").as_deref(), Some("M0,0 L50,0")); + // An instance's text of two lines on a main that is on a path: the override can't leave the + // path, so the warning names that case, not the general mismatch. + let mut two = doc.clone(); + let id: NodeId = two.nodes().find(|n| n.name == "Half").unwrap().children[0]; + two.node_mut(id).unwrap().kind.text_mut().unwrap().characters = "al\npha".into(); + let (_, w) = Written::of(&two); + assert!(w.warned(W4_LINES), "{:?}", w.warnings); + assert!(!w.warned(W4), "{:?}", w.warnings); + // The other way round: the main's layer is plain text, and so is the instance's. let (bytes, w) = Written::of(&off("Main")); assert!(w.warned(W4), "{:?}", w.warnings); diff --git a/docs/file-format-parity.md b/docs/file-format-parity.md index 47bab36b7..2dc0e240b 100644 --- a/docs/file-format-parity.md +++ b/docs/file-format-parity.md @@ -141,7 +141,7 @@ scales and empty-style clears; they have not been checked in other software. with the width on both sides when the shape has a fill too), pattern fills, WebP export settings (written as PNG), image adjustments, glass settings other than frost, springs other than Gentle (written as ease out), set-variable, set-variable-mode and conditional actions, scroll-to offsets, text decoration - looks, variable font axes, text on a path with more than one line or on a path the format can't hold (written as plain text), the parts of a text's path after the first, text on a path in an instance but not in its main or the other way round (written as the main has it), nested list levels, OpenType features, per-layer operations inside boolean groups, different stroke ends + looks, variable font axes, text on a path with more than one line or on a path the format can't hold (written as plain text), the parts of a text's path after the first, text on a path in an instance but not in its main or the other way round (written as the main has it), an instance's text of more than one line on a main on a path (it stays on that path, as an override can't take it off), nested list levels, OpenType features, per-layer operations inside boolean groups, different stroke ends on lines, the Dash cap (no public name for it). Not written at all: stroke outlines of dashed and per-side strokes and of inside or outside strokes on polygons, stars and vectors, glyph outlines of text (a reader lays text out with its own fonts), version history and branches.