[librsvg: 1/4] marker: impl Parse for Angle
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/4] marker: impl Parse for Angle
- Date: Tue, 11 Dec 2018 00:39:51 +0000 (UTC)
commit 7df8225fe6979b8c380a4d99f627eaee8c104b78
Author: Paolo Borelli <pborelli gnome org>
Date: Mon Dec 10 22:29:37 2018 +0100
marker: impl Parse for Angle
Now that we have a struct, we can move the parsing code to it.
Also change the MarkerOrient enum to hold Angle directly.
rsvg_internals/src/marker.rs | 78 ++++++++++++++++++++++++++++++++++++-------
rsvg_internals/src/parsers.rs | 61 ---------------------------------
2 files changed, 66 insertions(+), 73 deletions(-)
---
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 88faa874..be28eb9f 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -14,7 +14,6 @@ use handle::RsvgHandle;
use iri::IRI;
use length::{Length, LengthDir};
use node::*;
-use parsers;
use parsers::ParseError;
use parsers::{parse, parse_and_validate, Parse};
use path_builder::*;
@@ -65,12 +64,12 @@ impl Parse for MarkerUnits {
#[derive(Debug, Copy, Clone, PartialEq)]
enum MarkerOrient {
Auto,
- Degrees(f64),
+ Angle(Angle),
}
impl Default for MarkerOrient {
fn default() -> MarkerOrient {
- MarkerOrient::Degrees(0.0)
+ MarkerOrient::Angle(Angle::new(0.0))
}
}
@@ -82,9 +81,8 @@ impl Parse for MarkerOrient {
if parser.try(|p| p.expect_ident_matching("auto")).is_ok() {
Ok(MarkerOrient::Auto)
} else {
- parsers::angle_degrees(parser)
- .map(MarkerOrient::Degrees)
- .map_err(ValueErrorKind::Parse)
+ Angle::parse(parser, ())
+ .map(MarkerOrient::Angle)
}
}
}
@@ -151,7 +149,7 @@ impl NodeMarker {
let rotation = match self.orient.get() {
MarkerOrient::Auto => computed_angle,
- MarkerOrient::Degrees(d) => Angle::from_degrees(d),
+ MarkerOrient::Angle(a) => a,
};
affine.rotate(rotation.radians());
@@ -635,6 +633,49 @@ impl Angle {
}
}
+// angle:
+// https://www.w3.org/TR/SVG/types.html#DataTypeAngle
+//
+// angle ::= number ("deg" | "grad" | "rad")?
+//
+impl Parse for Angle {
+ type Data = ();
+ type Err = ValueErrorKind;
+
+ fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<Angle, ValueErrorKind> {
+ let angle = {
+ let token = parser
+ .next()
+ .map_err(|_| ParseError::new("expected angle"))?;
+
+ match *token {
+ Token::Number { value, .. } => Angle::from_degrees(value as f64),
+
+ Token::Dimension {
+ value, ref unit, ..
+ } => {
+ let value = f64::from(value);
+
+ match unit.as_ref() {
+ "deg" => Angle::from_degrees(value),
+ "grad" => Angle::from_degrees(value * 360.0 / 400.0),
+ "rad" => Angle::new(value),
+ _ => return Err(ValueErrorKind::Parse(ParseError::new("expected 'deg' | 'grad' |
'rad'"))),
+ }
+ }
+
+ _ => return Err(ValueErrorKind::Parse(ParseError::new("expected angle"))),
+ }
+ };
+
+ parser
+ .expect_exhausted()
+ .map_err(|_| ValueErrorKind::Parse(ParseError::new("expected angle")))?;
+
+ Ok(angle)
+ }
+}
+
// From SVG's marker-start, marker-mid, marker-end properties
#[derive(Debug, Copy, Clone, PartialEq)]
enum MarkerType {
@@ -877,6 +918,19 @@ where
mod parser_tests {
use super::*;
+ #[test]
+ fn parses_angle() {
+ assert_eq!(Angle::parse_str("0", ()), Ok(Angle::new(0.0)));
+ assert_eq!(Angle::parse_str("15", ()), Ok(Angle::from_degrees(15.0)));
+ assert_eq!(Angle::parse_str("180.5deg", ()), Ok(Angle::from_degrees(180.5)));
+ assert_eq!(Angle::parse_str("1rad", ()), Ok(Angle::new(1.0)));
+ assert_eq!(Angle::parse_str("-400grad", ()), Ok(Angle::from_degrees(-360.0)));
+
+ assert!(Angle::parse_str("", ()).is_err());
+ assert!(Angle::parse_str("foo", ()).is_err());
+ assert!(Angle::parse_str("300foo", ()).is_err());
+ }
+
#[test]
fn parsing_invalid_marker_units_yields_error() {
assert!(is_parse_error(
@@ -918,23 +972,23 @@ mod parser_tests {
assert_eq!(
MarkerOrient::parse_str("0", ()),
- Ok(MarkerOrient::Degrees(0.0))
+ Ok(MarkerOrient::Angle(Angle::new(0.0)))
);
assert_eq!(
MarkerOrient::parse_str("180", ()),
- Ok(MarkerOrient::Degrees(180.0))
+ Ok(MarkerOrient::Angle(Angle::from_degrees(180.0)))
);
assert_eq!(
MarkerOrient::parse_str("180deg", ()),
- Ok(MarkerOrient::Degrees(180.0))
+ Ok(MarkerOrient::Angle(Angle::from_degrees(180.0)))
);
assert_eq!(
MarkerOrient::parse_str("-400grad", ()),
- Ok(MarkerOrient::Degrees(-360.0))
+ Ok(MarkerOrient::Angle(Angle::from_degrees(-360.0)))
);
assert_eq!(
MarkerOrient::parse_str("1rad", ()),
- Ok(MarkerOrient::Degrees(180.0 / PI))
+ Ok(MarkerOrient::Angle(Angle::new(1.0)))
);
}
}
diff --git a/rsvg_internals/src/parsers.rs b/rsvg_internals/src/parsers.rs
index 5eae2591..e87e373b 100644
--- a/rsvg_internals/src/parsers.rs
+++ b/rsvg_internals/src/parsers.rs
@@ -1,6 +1,5 @@
use cssparser::{BasicParseError, Parser, ParserInput, Token};
-use std::f64::consts::*;
use std::str::{self, FromStr};
use attributes::Attribute;
@@ -116,46 +115,6 @@ where
.map_err(|e| NodeError::attribute_error(Attribute::from_str(key).unwrap(), e))
}
-// angle:
-// https://www.w3.org/TR/SVG/types.html#DataTypeAngle
-//
-// angle ::= number ("deg" | "grad" | "rad")?
-//
-// Returns an f64 angle in degrees
-
-pub fn angle_degrees(parser: &mut Parser<'_, '_>) -> Result<f64, ParseError> {
- let angle = {
- let token = parser
- .next()
- .map_err(|_| ParseError::new("expected angle"))?;
-
- match *token {
- Token::Number { value, .. } => f64::from(value),
-
- Token::Dimension {
- value, ref unit, ..
- } => {
- let value = f64::from(value);
-
- match unit.as_ref() {
- "deg" => value,
- "grad" => value * 360.0 / 400.0,
- "rad" => value * 180.0 / PI,
- _ => return Err(ParseError::new("expected 'deg' | 'grad' | 'rad'")),
- }
- }
-
- _ => return Err(ParseError::new("expected angle")),
- }
- };
-
- parser
- .expect_exhausted()
- .map_err(|_| ParseError::new("expected angle"))?;
-
- Ok(angle)
-}
-
pub fn optional_comma(parser: &mut Parser<'_, '_>) {
let _ = parser.try(|p| p.expect_comma());
}
@@ -391,26 +350,6 @@ mod tests {
assert!(list_of_points("1 2-3,-4").is_err());
}
- fn angle_degrees_str(s: &str) -> Result<f64, ParseError> {
- let mut input = ParserInput::new(s);
- let mut parser = Parser::new(&mut input);
-
- angle_degrees(&mut parser)
- }
-
- #[test]
- fn parses_angle() {
- assert_eq!(angle_degrees_str("0"), Ok(0.0));
- assert_eq!(angle_degrees_str("15"), Ok(15.0));
- assert_eq!(angle_degrees_str("180.5deg"), Ok(180.5));
- assert_eq!(angle_degrees_str("1rad"), Ok(180.0 / PI));
- assert_eq!(angle_degrees_str("-400grad"), Ok(-360.0));
-
- assert!(angle_degrees_str("").is_err());
- assert!(angle_degrees_str("foo").is_err());
- assert!(angle_degrees_str("300foo").is_err());
- }
-
#[test]
fn parses_number_list() {
assert_eq!(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]