//! Live effects in SVG export: a fill or stroke's own raster effects become filters on that item's //! element, and geometry effects on type are baked through its outlines. // Integration tests: unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness). #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] use serde_json::json; use vectorcraft_color::{Color, Paint}; use vectorcraft_doc::{Appearance, CharStyle, Document, Effect, Node, NodeId, NodeKind, TextObject}; use vectorcraft_geom::{Point, Rect, shapes}; use vectorcraft_svg::{ExportOptions, export}; fn doc_with(mut n: Node) -> Document { let mut d = Document::new(200.0, 200.0); n.id = d.alloc_id(); let l = d.layers[0].id; d.insert(Some(l), 0, n).unwrap(); d } fn fx(id: &str) -> Effect { Effect { id: id.into(), params: json!({}), visible: true } } #[test] fn a_strokes_own_glow_filters_the_stroke_element_only() { let mut n = Node::path( NodeId(0), shapes::rectangle(Rect::new(20.0, 20.0, 80.0, 80.0)), Appearance::basic(Paint::solid(Color::WHITE), Paint::solid(Color::BLACK), 2.0), ); n.appearance.items[1].effects_mut().push(fx("stylize.outerGlow")); let svg = export(&doc_with(n), &ExportOptions::default()); assert_eq!(svg.matches("").map(|i| open + i).unwrap()]; assert!(inside.contains("stroke=\"#000000\"") && !inside.contains("fill=\"#ffffff\""), "{inside}"); assert!(svg[..open].contains("fill=\"#ffffff\""), "{svg}"); // A hidden effect exports nothing. let mut n = Node::path( NodeId(0), shapes::rectangle(Rect::new(20.0, 20.0, 80.0, 80.0)), Appearance::basic(Paint::solid(Color::WHITE), Paint::solid(Color::BLACK), 2.0), ); n.appearance.items[1].effects_mut().push(Effect { visible: false, ..fx("stylize.outerGlow") }); assert!(!export(&doc_with(n), &ExportOptions::default()).contains("