mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 15:51:56 +00:00
Preserve SVG styles with encoded attribute selectors
This commit is contained in:
@@ -149,7 +149,7 @@ fn named_made_up_ids(xml: &roxmltree::Document) -> HashSet<usize> {
|
||||
/// * so do objects with attributes in other applications' namespaces ([`foreign`]);
|
||||
/// * so do `<circle>` and `<ellipse>` elements, recorded: usvg makes their arcs into a varying
|
||||
/// number of curves, and they come back as the ellipse VectorCraft draws (not in a file whose
|
||||
/// style sheet has an `[id` selector);
|
||||
/// style sheet has an attribute selector);
|
||||
/// * linked files are read ([`files`]);
|
||||
/// * percentage lengths in a `<symbol>` with a `viewBox` become numbers ([`symbol_units`]);
|
||||
/// * what style sheet rules with a `:not()` set goes in `style` attributes ([`not_rules`]).
|
||||
@@ -164,8 +164,9 @@ pub(super) fn prepass<'s>(svg: &'s str, markers: &str, xml: &roxmltree::Document
|
||||
let not = markers.contains(":not(");
|
||||
let events = SVG_EVENTS.iter().any(|e| markers.contains(e));
|
||||
let foreign_attrs = markers.contains("xmlns:") && has_foreign_attributes(xml);
|
||||
// An id would change what a style sheet's `[id]` selector matches: such files keep usvg's curves.
|
||||
let ellipses = !markers.contains("[id") && ["<circle", ":circle", "<ellipse", ":ellipse"].iter().any(|t| markers.contains(t));
|
||||
let attribute_selectors =
|
||||
xml.descendants().filter(|n| n.is_element() && n.tag_name().name() == "style").filter_map(|n| n.text()).any(|text| text.contains('['));
|
||||
let ellipses = !attribute_selectors && ["<circle", ":circle", "<ellipse", ":ellipse"].iter().any(|t| markers.contains(t));
|
||||
if !css_transform
|
||||
&& !not
|
||||
&& !events
|
||||
|
||||
@@ -20,6 +20,23 @@ fn open(body: &str) -> (Document, Vec<String>) {
|
||||
import_with_report(&svg(body)).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decoded_id_selectors_do_not_recolor_bare_ellipses() {
|
||||
for selector in ["circle[id]", "ellipse[id]", "circle[id]", "ellipse[id]", "circle[ id ]", r"ellipse[\69 d]"] {
|
||||
let source = svg(&format!(
|
||||
"<style>{selector} {{ fill: red }}</style><circle cx=\"40\" cy=\"50\" r=\"20\"/><ellipse cx=\"100\" cy=\"50\" rx=\"20\" ry=\"10\"/><circle id=\"c\" cx=\"40\" cy=\"100\" r=\"8\"/><ellipse id=\"e\" cx=\"100\" cy=\"100\" rx=\"12\" ry=\"8\"/>"
|
||||
));
|
||||
let doc = import(&source).unwrap();
|
||||
let actual = render_artboard(&doc);
|
||||
let expected = resvg_render(&source, 200, 120);
|
||||
assert_eq!((actual.width, actual.height), (expected.width, expected.height));
|
||||
for (x, y) in [(40, 50), (100, 50), (40, 100), (100, 100)] {
|
||||
let at = 4 * (y * actual.width + x) as usize;
|
||||
assert_eq!(&actual.rgba[at..at + 4], &expected.rgba[at..at + 4], "{selector}: ({x}, {y})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// All non-layer nodes in paint order.
|
||||
fn art(d: &Document) -> Vec<&Node> {
|
||||
let mut v = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user