[librsvg: 5/10] Parse the blur() filter function




commit d40e3b920d5afb45c78071f0ad0a3ceac4c388cf
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Apr 28 14:36:05 2021 -0500

    Parse the blur() filter function

 src/filter.rs      | 15 ++++++++---
 src/filter_func.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 4 deletions(-)
---
diff --git a/src/filter.rs b/src/filter.rs
index 8a26e416..f626b4f2 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -202,10 +202,17 @@ impl Parse for FilterValueList {
         loop {
             let loc = parser.current_source_location();
 
-            let url = parser.expect_url()?;
-            let node_id =
-                NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;
-            result.0.push(FilterValue::Url(node_id));
+            let filter_value = if let Ok(func) = parser.try_parse(|p| FilterFunction::parse(p)) {
+                FilterValue::Function(func)
+            } else {
+                let url = parser.expect_url()?;
+                let node_id = NodeId::parse(&url)
+                    .map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;
+
+                FilterValue::Url(node_id)
+            };
+
+            result.0.push(filter_value);
 
             if parser.is_exhausted() {
                 break;
diff --git a/src/filter_func.rs b/src/filter_func.rs
index 5b664aff..eb84fff8 100644
--- a/src/filter_func.rs
+++ b/src/filter_func.rs
@@ -1,10 +1,60 @@
+use cssparser::Parser;
+
+use crate::error::*;
 use crate::filters::{FilterResolveError, FilterSpec};
+use crate::length::*;
+use crate::parsers::Parse;
 
 /// CSS Filter functions from the Filter Effects Module Level 1
 ///
 /// https://www.w3.org/TR/filter-effects/#filter-functions
 #[derive(Debug, Clone, PartialEq)]
 pub enum FilterFunction {
+    Blur(Blur),
+}
+
+/// Parameters for the `blur()` filter function
+///
+/// https://www.w3.org/TR/filter-effects/#funcdef-filter-blur
+#[derive(Debug, Clone, PartialEq)]
+pub struct Blur {
+    std_deviation: Option<Length<Both>>,
+}
+
+fn parse_function<'i, F>(
+    parser: &mut Parser<'i, '_>,
+    name: &str,
+    f: F,
+) -> Result<FilterFunction, ParseError<'i>>
+where
+    F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result<FilterFunction, ParseError<'i>>,
+{
+    parser.expect_function_matching(name)?;
+    parser.parse_nested_block(f)
+}
+
+fn parse_blur<'i>(parser: &mut Parser<'i, '_>) -> Result<FilterFunction, ParseError<'i>> {
+    let length = if let Ok(length) = parser.try_parse(|p| Length::parse(p)) {
+        Some(length)
+    } else {
+        None
+    };
+
+    Ok(FilterFunction::Blur(Blur {
+        std_deviation: length,
+    }))
+}
+
+impl Parse for FilterFunction {
+    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, crate::error::ParseError<'i>> {
+        let loc = parser.current_source_location();
+
+        parser
+            .try_parse(|p| parse_function(p, "blur", parse_blur))
+            .or_else(|_| {
+                Err(loc.new_custom_error(ValueErrorKind::parse_error("expected filter function")))
+            })
+    }
 }
 
 impl FilterFunction {
@@ -12,3 +62,31 @@ impl FilterFunction {
         unimplemented!()
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn parses_blur() {
+        assert_eq!(
+            FilterFunction::parse_str("blur()").unwrap(),
+            FilterFunction::Blur(Blur {
+                std_deviation: None
+            })
+        );
+
+        assert_eq!(
+            FilterFunction::parse_str("blur(5px)").unwrap(),
+            FilterFunction::Blur(Blur {
+                std_deviation: Some(Length::new(5.0, LengthUnit::Px))
+            })
+        );
+    }
+
+    #[test]
+    fn invalid_blur_yields_error() {
+        assert!(FilterFunction::parse_str("blur(foo)").is_err());
+        assert!(FilterFunction::parse_str("blur(42 43)").is_err());
+    }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]