[librsvg/librsvg-2.50] (#483): Support attribute matching selectors
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/librsvg-2.50] (#483): Support attribute matching selectors
- Date: Fri, 2 Oct 2020 19:24:35 +0000 (UTC)
commit f140d29807cdaf95fe917d08dcff2654771aa0c2
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Sep 7 17:35:36 2020 -0500
(#483): Support attribute matching selectors
This implements selectors::Element::attr_matches().
Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/483
rsvg_internals/src/css.rs | 26 ++++++++++++++----
rsvg_internals/src/element.rs | 30 ++++++++++++++-------
.../reftests/483-attribute-selectors-ref.png | Bin 0 -> 334 bytes
.../fixtures/reftests/483-attribute-selectors.svg | 23 ++++++++++++++++
4 files changed, 64 insertions(+), 15 deletions(-)
---
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index da32460e..f1c91e35 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -464,12 +464,28 @@ impl selectors::Element for RsvgElement {
fn attr_matches(
&self,
- _ns: &NamespaceConstraint<&Namespace>,
- _local_name: &LocalName,
- _operation: &AttrSelectorOperation<&String>,
+ ns: &NamespaceConstraint<&Namespace>,
+ local_name: &LocalName,
+ operation: &AttrSelectorOperation<&String>,
) -> bool {
- // unsupported
- false
+ self.0
+ .borrow_element()
+ .get_attributes()
+ .iter()
+ .find(|(attr, _)| {
+ // do we have an attribute that matches the namespace and local_name?
+ match *ns {
+ NamespaceConstraint::Any => *local_name == attr.local,
+ NamespaceConstraint::Specific(ns) => {
+ QualName::new(None, ns.clone(), local_name.clone()) == *attr
+ }
+ }
+ })
+ .map(|(_, value)| {
+ // we have one; does the attribute's value match the expected operation?
+ operation.eval_str(value)
+ })
+ .unwrap_or(false)
}
fn match_non_ts_pseudo_class<F>(
diff --git a/rsvg_internals/src/element.rs b/rsvg_internals/src/element.rs
index aa7e6e8f..20f467ea 100644
--- a/rsvg_internals/src/element.rs
+++ b/rsvg_internals/src/element.rs
@@ -192,17 +192,16 @@ impl<T: SetAttributes + Draw> ElementInner<T> {
.iter()
.find(|(attr, _)| attr.expanded() == expanded_name!("", "style"))
.map(|(_, value)| value)
- .unwrap_or("")
+ .unwrap_or(""),
);
}
fn set_transform_attribute(&mut self) -> Result<(), ElementError> {
- self.transform = self.attributes
+ self.transform = self
+ .attributes
.iter()
.find(|(attr, _)| attr.expanded() == expanded_name!("", "transform"))
- .map(|(attr, value)| {
- Transform::parse_str(value).attribute(attr)
- })
+ .map(|(attr, value)| Transform::parse_str(value).attribute(attr))
.unwrap_or_else(|| Ok(Transform::default()))?;
Ok(())
@@ -215,17 +214,20 @@ impl<T: SetAttributes + Draw> ElementInner<T> {
match attr.expanded() {
expanded_name!("", "requiredExtensions") if cond => {
cond = RequiredExtensions::from_attribute(value)
- .map(|RequiredExtensions(res)| res).attribute(attr)?;
+ .map(|RequiredExtensions(res)| res)
+ .attribute(attr)?;
}
expanded_name!("", "requiredFeatures") if cond => {
cond = RequiredFeatures::from_attribute(value)
- .map(|RequiredFeatures(res)| res).attribute(attr)?;
+ .map(|RequiredFeatures(res)| res)
+ .attribute(attr)?;
}
expanded_name!("", "systemLanguage") if cond => {
cond = SystemLanguage::from_attribute(value, &LOCALE)
- .map(|SystemLanguage(res)| res).attribute(attr)?;
+ .map(|SystemLanguage(res)| res)
+ .attribute(attr)?;
}
_ => {}
@@ -239,7 +241,10 @@ impl<T: SetAttributes + Draw> ElementInner<T> {
/// Hands the `attrs` to the node's state, to apply the presentation attributes.
fn set_presentation_attributes(&mut self) -> Result<(), ElementError> {
- match self.specified_values.parse_presentation_attributes(&self.attributes) {
+ match self
+ .specified_values
+ .parse_presentation_attributes(&self.attributes)
+ {
Ok(_) => Ok(()),
Err(e) => {
// FIXME: we'll ignore errors here for now.
@@ -638,7 +643,12 @@ impl fmt::Display for Element {
macro_rules! e {
($name:ident, $element_type:ident) => {
- pub fn $name(element_name: &QualName, attributes: Attributes, id: Option<String>, class:
Option<String>) -> Element {
+ pub fn $name(
+ element_name: &QualName,
+ attributes: Attributes,
+ id: Option<String>,
+ class: Option<String>,
+ ) -> Element {
let mut element_impl = <$element_type>::default();
let result = element_impl.set_attributes(&attributes);
diff --git a/tests/fixtures/reftests/483-attribute-selectors-ref.png
b/tests/fixtures/reftests/483-attribute-selectors-ref.png
new file mode 100644
index 00000000..63f8a370
Binary files /dev/null and b/tests/fixtures/reftests/483-attribute-selectors-ref.png differ
diff --git a/tests/fixtures/reftests/483-attribute-selectors.svg
b/tests/fixtures/reftests/483-attribute-selectors.svg
new file mode 100644
index 00000000..5b3230c9
--- /dev/null
+++ b/tests/fixtures/reftests/483-attribute-selectors.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="150" height="100">
+ <style type="text/css">
+ rect[id] { fill: blue; }
+
+ rect[id="rojo"] { fill: red; }
+ rect[id|="rojo"] { fill: red; }
+
+ rect[id^="verde"] { fill: lime; }
+ rect[id$="verde"] { fill: lime; }
+
+ rect[id*="azul"] { fill: blue; }
+ </style>
+
+ <rect x="0" y="0" width="50" height="50" id="rojo"/>
+ <rect x="0" y="50" width="50" height="50" id="rojo-jojojo"/>
+
+ <rect x="50" y="0" width="50" height="50" id="verdecito"/>
+ <rect x="50" y="50" width="50" height="50" id="superverde"/>
+
+ <rect x="100" y="0" width="50" height="50" id="cualquier_cosa"/>
+ <rect x="100" y="50" width="50" height="50" id="superazulito"/>
+</svg>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]