[librsvg: 2/3] DropShadow filter: allow parameters in arbitrary order
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 2/3] DropShadow filter: allow parameters in arbitrary order
- Date: Sat, 29 May 2021 00:23:04 +0000 (UTC)
commit d2d35f77590c9cf015306e065ea69bb272229f60
Author: John Ledbetter <john ledbetter gmail com>
Date: Fri May 28 13:42:50 2021 -0400
DropShadow filter: allow parameters in arbitrary order
drop-shadow() accepts two sets of arguments:
* an optional color
* 2 or 3 lengths, describing dx, dy, and blur std_dev
These sets can be provided in any order, but cannot be intermixed;
`blue 2px 2px 3px` is valid, as is `2px 2px blue`. However,
`2px blue 2px` is invalid.
src/filter_func.rs | 82 +++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 65 insertions(+), 17 deletions(-)
---
diff --git a/src/filter_func.rs b/src/filter_func.rs
index 3365b5ac..15ddd24e 100644
--- a/src/filter_func.rs
+++ b/src/filter_func.rs
@@ -163,20 +163,40 @@ fn parse_contrast<'i>(parser: &mut Parser<'i, '_>) -> Result<FilterFunction, Par
Ok(FilterFunction::Contrast(Contrast { proportion }))
}
-
#[allow(clippy::unnecessary_wraps)]
fn parse_dropshadow<'i>(parser: &mut Parser<'i, '_>) -> Result<FilterFunction, ParseError<'i>> {
- let color = parser.try_parse(|p| Color::parse(p)).ok();
- let dx = parser.try_parse(|p| Length::parse(p)).ok();
- let dy = parser.try_parse(|p| Length::parse(p)).ok();
- let std_deviation = parser.try_parse(|p| ULength::parse(p)).ok();
-
- Ok(FilterFunction::DropShadow(DropShadow {
- color,
- dx,
- dy,
- std_deviation,
- }))
+ let mut result = DropShadow {
+ color: None,
+ dx: None,
+ dy: None,
+ std_deviation: None,
+ };
+
+ result.color = parser.try_parse(|p| Color::parse(p)).ok();
+
+ // if dx is provided, dy must follow and an optional std_dev must follow that.
+ if let Ok(dx) = parser.try_parse(|p| Length::parse(p)) {
+ result.dx = Some(dx);
+ result.dy = Some(parser.try_parse(|p| Length::parse(p))?);
+ result.std_deviation = parser.try_parse(|p| ULength::parse(p)).ok();
+ }
+
+ let loc = parser.current_source_location();
+
+ // because the color and length arguments can be provided in either order,
+ // check again after potentially parsing lengths if the color is now provided.
+ // if a color is provided both before and after, that is an error.
+ if let Ok(c) = parser.try_parse(|p| Color::parse(p)) {
+ if result.color.is_some() {
+ return Err(
+ loc.new_custom_error(ValueErrorKind::Value("color already specified".to_string()))
+ );
+ } else {
+ result.color = Some(c);
+ }
+ }
+
+ Ok(FilterFunction::DropShadow(result))
}
#[allow(clippy::unnecessary_wraps)]
@@ -669,19 +689,39 @@ mod tests {
);
assert_eq!(
- FilterFunction::parse_str("drop-shadow(#ff0000)").unwrap(),
+ FilterFunction::parse_str("drop-shadow(1px 2px blue)").unwrap(),
FilterFunction::DropShadow(DropShadow {
color: Some(Color::RGBA(RGBA {
- red: 255,
+ red: 0,
green: 0,
- blue: 0,
+ blue: 255,
alpha: 255
})),
- dx: None,
- dy: None,
+ dx: Some(Length::new(1.0, LengthUnit::Px)),
+ dy: Some(Length::new(2.0, LengthUnit::Px)),
std_deviation: None,
})
);
+
+ assert_eq!(
+ FilterFunction::parse_str("drop-shadow(1px 2px 3px currentColor)").unwrap(),
+ FilterFunction::DropShadow(DropShadow {
+ color: Some(Color::CurrentColor),
+ dx: Some(Length::new(1.0, LengthUnit::Px)),
+ dy: Some(Length::new(2.0, LengthUnit::Px)),
+ std_deviation: Some(ULength::new(3.0, LengthUnit::Px)),
+ })
+ );
+
+ assert_eq!(
+ FilterFunction::parse_str("drop-shadow(1 2 3)").unwrap(),
+ FilterFunction::DropShadow(DropShadow {
+ color: None,
+ dx: Some(Length::new(1.0, LengthUnit::Px)),
+ dy: Some(Length::new(2.0, LengthUnit::Px)),
+ std_deviation: Some(ULength::new(3.0, LengthUnit::Px)),
+ })
+ );
}
#[test]
@@ -796,6 +836,14 @@ mod tests {
assert!(FilterFunction::parse_str("contrast(foo)").is_err());
}
+ #[test]
+ fn invalid_dropshadow_yields_error() {
+ assert!(FilterFunction::parse_str("drop-shadow(blue 5px green)").is_err());
+ assert!(FilterFunction::parse_str("drop-shadow(blue 5px 5px green)").is_err());
+ assert!(FilterFunction::parse_str("drop-shadow(blue 1px)").is_err());
+ assert!(FilterFunction::parse_str("drop-shadow(1 2 3 4 blue)").is_err());
+ }
+
#[test]
fn invalid_grayscale_yields_error() {
assert!(FilterFunction::parse_str("grayscale(foo)").is_err());
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]