diff --git a/moli-svg/src/lib.rs b/moli-svg/src/lib.rs index 365e72855a..643c081fc7 100644 --- a/moli-svg/src/lib.rs +++ b/moli-svg/src/lib.rs @@ -23,12 +23,13 @@ pub use transform::{ #[cfg(test)] mod tests { use crate::{ - SvgGeometryElement, SvgGeometryPoint, SvgGeometrySegment, SvgLengthUnit, + SvgFillRule, SvgGeometryElement, SvgGeometryPoint, SvgGeometrySegment, SvgLengthUnit, SvgMatrixComponents, SvgTransform, SvgTransformKind, bounding_box_for_element, bounding_box_for_segments, bounding_box_for_transformed_element, - consolidate_transform_matrices, is_point_in_fill, parse_length, parse_length_list, - parse_number, parse_number_list, parse_point_list, parse_transform_attribute, - point_at_length, segments_for_element, serialize_number, serialize_transform_list, + consolidate_transform_matrices, is_point_in_fill, is_point_in_fill_with_rule, parse_length, + parse_length_list, parse_number, parse_number_list, parse_point_list, + parse_transform_attribute, point_at_length, segments_for_element, serialize_number, + serialize_transform_list, }; #[test] @@ -537,6 +538,51 @@ mod tests { )); } + #[test] + fn fill_containment_rejects_nonfinite_coordinates() { + let circle = SvgGeometryElement::Circle { + cx: 0.0, + cy: 0.0, + r: 10.0, + }; + for value in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { + for point in [ + SvgGeometryPoint::new(value, 0.0), + SvgGeometryPoint::new(0.0, value), + ] { + for rule in [SvgFillRule::NonZero, SvgFillRule::EvenOdd] { + assert!(!is_point_in_fill_with_rule(&circle, point, rule)); + } + } + } + } + + #[test] + fn evenodd_fill_excludes_nested_interiors_but_includes_boundaries() { + let rings = SvgGeometryElement::Path { + d: "M0 0H10V10H0Z M2 2H8V8H2Z".to_owned(), + }; + let center = SvgGeometryPoint::new(5.0, 5.0); + assert!(is_point_in_fill(&rings, center)); + assert!(!is_point_in_fill_with_rule( + &rings, + center, + SvgFillRule::EvenOdd + )); + for point in [ + SvgGeometryPoint::new(1.0, 5.0), + SvgGeometryPoint::new(2.0, 5.0), + SvgGeometryPoint::new(8.0, 5.0), + SvgGeometryPoint::new(10.0, 5.0), + ] { + assert!(is_point_in_fill_with_rule( + &rings, + point, + SvgFillRule::EvenOdd + )); + } + } + #[test] fn curve_bounding_box_uses_bezier_extrema() { let path = path_segments("M0 0 C100 100 100-100 200 0");