use crate::svgtree::{self, AId};
use crate::{converter, Node, Options};
static FEATURES: &[&str] = &[
"http://www.w3.org/TR/SVG11/feature#SVGDOM-static",
"http://www.w3.org/TR/SVG11/feature#SVG-static",
"http://www.w3.org/TR/SVG11/feature#CoreAttribute", "http://www.w3.org/TR/SVG11/feature#Structure",
"http://www.w3.org/TR/SVG11/feature#BasicStructure",
"http://www.w3.org/TR/SVG11/feature#ContainerAttribute", "http://www.w3.org/TR/SVG11/feature#ConditionalProcessing",
"http://www.w3.org/TR/SVG11/feature#Image",
"http://www.w3.org/TR/SVG11/feature#Style",
"http://www.w3.org/TR/SVG11/feature#Shape",
"http://www.w3.org/TR/SVG11/feature#Text",
"http://www.w3.org/TR/SVG11/feature#BasicText",
"http://www.w3.org/TR/SVG11/feature#PaintAttribute", "http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute", "http://www.w3.org/TR/SVG11/feature#OpacityAttribute",
"http://www.w3.org/TR/SVG11/feature#GraphicsAttribute",
"http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute",
"http://www.w3.org/TR/SVG11/feature#Marker",
"http://www.w3.org/TR/SVG11/feature#Gradient",
"http://www.w3.org/TR/SVG11/feature#Pattern",
"http://www.w3.org/TR/SVG11/feature#Clip",
"http://www.w3.org/TR/SVG11/feature#BasicClip",
"http://www.w3.org/TR/SVG11/feature#Mask",
"http://www.w3.org/TR/SVG11/feature#Filter",
"http://www.w3.org/TR/SVG11/feature#BasicFilter",
"http://www.w3.org/TR/SVG11/feature#XlinkAttribute",
];
pub(crate) fn convert(
node: svgtree::Node,
state: &converter::State,
cache: &mut converter::Cache,
parent: &mut Node,
) -> Option<()> {
let child = node
.children()
.find(|n| is_condition_passed(*n, state.opt))?;
match converter::convert_group(node, state, false, cache, parent) {
converter::GroupKind::Create(ref mut g) => {
converter::convert_element(child, state, cache, g);
}
converter::GroupKind::Skip => {
converter::convert_element(child, state, cache, parent);
}
converter::GroupKind::Ignore => {}
}
Some(())
}
pub(crate) fn is_condition_passed(node: svgtree::Node, opt: &Options) -> bool {
if !node.is_element() {
return false;
}
if node.has_attribute(AId::RequiredExtensions) {
return false;
}
if let Some(features) = node.attribute::<&str>(AId::RequiredFeatures) {
for feature in features.split(' ') {
if !FEATURES.contains(&feature) {
return false;
}
}
}
if !is_valid_sys_lang(node, opt) {
return false;
}
true
}
fn is_valid_sys_lang(node: svgtree::Node, opt: &Options) -> bool {
if let Some(langs) = node.attribute::<&str>(AId::SystemLanguage) {
let mut has_match = false;
for lang in langs.split(',') {
let lang = lang.trim();
if opt.languages.iter().any(|v| v == lang) {
has_match = true;
break;
}
if let Some(idx) = lang.bytes().position(|c| c == b'-') {
let lang_prefix = &lang[..idx];
if opt.languages.iter().any(|v| v == lang_prefix) {
has_match = true;
break;
}
}
}
has_match
} else {
true
}
}