fix(svg): reject nonfinite fill points and support fill rules

This commit is contained in:
ldm0
2026-10-11 18:06:48 +08:00
parent 199b8ee144
commit 361af4f1a7
+50 -4
View File
@@ -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");