Commit e6efe102 authored by RazrFalcon's avatar RazrFalcon

Fixed coordinates resolving when units are 'userSpaceOnUse'.

parent 9f3d271e
......@@ -21,6 +21,7 @@ This changelog also contains important changes in dependencies.
- (usvg) `rotate` attribute resolving.
- (usvg) Paths without stroke and fill will no longer be removed.
Required for a proper bbox resolving.
- (usvg) Coordinates resolving when units are `userSpaceOnUse`.
- (svgdom) `stroke-miterlimit` attribute parsing.
- (svgdom) `length` and `number` attribute types parsing.
- (svgdom) `offset` attribute parsing.
......
e-use-023.svg
e-filter-057.svg
e-linearGradient-006.svg
e-linearGradient-029.svg
e-linearGradient-031.svg
e-pattern-027.svg
e-radialGradient-006.svg
e-radialGradient-039.svg
e-use-023.svg
e-filter-057.svg
e-linearGradient-006.svg
e-linearGradient-029.svg
e-linearGradient-031.svg
e-pattern-027.svg
e-radialGradient-006.svg
e-radialGradient-039.svg
......@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Ungrouping of groups with non-inheritable attributes.
- `rotate` attribute resolving.
- `color` on `use` resolving.
- Coordinates resolving when units are `userSpaceOnUse`.
### Removed
- `Rect::transform`.
......
......@@ -145,8 +145,19 @@ pub fn prepare_doc(doc: &mut svgdom::Document, opt: &Options) {
resolve_use_attributes(doc);
resolve_svg_attributes(doc);
resolve_linear_gradient_attributes(doc);
resolve_radial_gradient_attributes(doc);
resolve_pattern_attributes(doc);
resolve_pattern_children(doc);
resolve_filter_attributes(doc);
resolve_filter_children(doc);
convert_units(svg, opt);
fix_radial_gradient_attributes(doc);
// `use` should be resolved before style attributes,
// because `use` can propagate own style.
resolve_use(doc, opt);
......@@ -158,17 +169,9 @@ pub fn prepare_doc(doc: &mut svgdom::Document, opt: &Options) {
group_defs(doc, svg);
resolve_linear_gradient_attributes(doc);
resolve_radial_gradient_attributes(doc);
resolve_gradient_stops(doc);
fix_gradient_stops(doc);
resolve_pattern_attributes(doc);
resolve_pattern_children(doc);
resolve_filter_attributes(doc);
resolve_filter_children(doc);
resolve_clip_path_attributes(doc);
fix_recursive_links(doc);
......
......@@ -4,6 +4,7 @@
use svgdom::{
AspectRatio,
Length,
};
use super::prelude::*;
......@@ -16,9 +17,11 @@ pub fn resolve_linear_gradient_attributes(doc: &Document) {
resolve_attr(node, AId::SpreadMethod, Some(AValue::from("pad")));
resolve_attr(node, AId::X1, Some(AValue::from(0.0)));
resolve_attr(node, AId::Y1, Some(AValue::from(0.0)));
resolve_attr(node, AId::X2, Some(AValue::from(1.0)));
resolve_attr(node, AId::X2, Some(AValue::from(Length::new(100.0, Unit::Percent))));
resolve_attr(node, AId::Y2, Some(AValue::from(0.0)));
resolve_attr(node, AId::GradientTransform, None);
fix_units(node, AId::GradientUnits, "objectBoundingBox");
}
}
......@@ -27,31 +30,37 @@ pub fn resolve_radial_gradient_attributes(doc: &Document) {
for node in &mut gen_order(doc, EId::RadialGradient) {
resolve_attr(node, AId::GradientUnits, Some(AValue::from("objectBoundingBox")));
resolve_attr(node, AId::SpreadMethod, Some(AValue::from("pad")));
resolve_attr(node, AId::Cx, Some(AValue::from(0.5)));
resolve_attr(node, AId::Cy, Some(AValue::from(0.5)));
resolve_attr(node, AId::R, Some(AValue::from(0.5)));
resolve_attr(node, AId::Cx, Some(AValue::from(Length::new(50.0, Unit::Percent))));
resolve_attr(node, AId::Cy, Some(AValue::from(Length::new(50.0, Unit::Percent))));
resolve_attr(node, AId::R, Some(AValue::from(Length::new(50.0, Unit::Percent))));
resolve_attr(node, AId::GradientTransform, None);
// If `fx` is not found then set it to `cx`.
let cx = node.attributes().get_value(AId::Cx).cloned();
resolve_attr(node, AId::Fx, cx);
// If `fy` is not found then set it to `cy`.
let cy = node.attributes().get_value(AId::Cy).cloned();
resolve_attr(node, AId::Fy, cy);
fix_units(node, AId::GradientUnits, "objectBoundingBox");
}
}
// Should be done after `convert_units`.
pub fn fix_radial_gradient_attributes(doc: &Document) {
for node in &mut gen_order(doc, EId::RadialGradient) {
// Replace negative `r` with zero
// otherwise `fx` and `fy` may became NaN.
//
// Note: negative `r` is an error and UB, so we can resolve it
// in whatever way we want.
// By replacing it with zero we will get the same behavior as Chrome.
// By replacing it with zero we will get the same behavior as in Chrome.
let r = node.attributes().get_number(AId::R).unwrap();
if r < 0.0 {
node.set_attribute((AId::R, 0.0));
}
// If `fx` is not found then set it to `cx`.
let cx = node.attributes().get_value(AId::Cx).cloned();
resolve_attr(node, AId::Fx, cx);
// If `fy` is not found then set it to `cy`.
let cy = node.attributes().get_value(AId::Cy).cloned();
resolve_attr(node, AId::Fy, cy);
prepare_focal(node);
}
}
......@@ -68,6 +77,9 @@ pub fn resolve_pattern_attributes(doc: &Document) {
resolve_attr(node, AId::Height, Some(AValue::from(0.0)));
resolve_attr(node, AId::PreserveAspectRatio, Some(AValue::from(AspectRatio::default())));
resolve_attr(node, AId::ViewBox, None);
fix_units(node, AId::PatternUnits, "objectBoundingBox");
fix_units(node, AId::PatternContentUnits, "userSpaceOnUse");
}
}
......@@ -76,21 +88,25 @@ pub fn resolve_filter_attributes(doc: &Document) {
for node in &mut gen_order(doc, EId::Filter) {
resolve_attr(node, AId::FilterUnits, Some(AValue::from("objectBoundingBox")));
resolve_attr(node, AId::PrimitiveUnits, Some(AValue::from("userSpaceOnUse")));
resolve_attr(node, AId::X, Some(AValue::from(-0.1)));
resolve_attr(node, AId::Y, Some(AValue::from(-0.1)));
resolve_attr(node, AId::Width, Some(AValue::from(1.2)));
resolve_attr(node, AId::Height, Some(AValue::from(1.2)));
// TODO: do this for other elements
let is_valid_filter_units = {
let attrs = node.attributes();
let filter_units = attrs.get_str_or(AId::FilterUnits, "");
filter_units == "objectBoundingBox" || filter_units == "userSpaceOnUse"
};
if !is_valid_filter_units {
node.set_attribute((AId::FilterUnits, "objectBoundingBox"));
}
resolve_attr(node, AId::X, Some(AValue::from(Length::new(-10.0, Unit::Percent))));
resolve_attr(node, AId::Y, Some(AValue::from(Length::new(-10.0, Unit::Percent))));
resolve_attr(node, AId::Width, Some(AValue::from(Length::new(120.0, Unit::Percent))));
resolve_attr(node, AId::Height, Some(AValue::from(Length::new(120.0, Unit::Percent))));
fix_units(node, AId::FilterUnits, "objectBoundingBox");
fix_units(node, AId::PrimitiveUnits, "userSpaceOnUse");
}
}
fn fix_units(node: &mut Node, aid: AId, default: &str) {
let is_valid_filter_units = {
let attrs = node.attributes();
let filter_units = attrs.get_str_or(aid, "");
filter_units == "objectBoundingBox" || filter_units == "userSpaceOnUse"
};
if !is_valid_filter_units {
node.set_attribute((aid, default));
}
}
......
......@@ -126,6 +126,7 @@ e-pattern-022,174
e-pattern-023,174
e-pattern-024,174
e-pattern-026,19086,bug
e-pattern-027,171
e-radialGradient-031,38237,fixes chrome bug
e-rect-004,96
e-rect-005,106
......
......@@ -342,8 +342,8 @@ e-feImage-008,53820d08
e-feImage-009,5fab46e6
e-feImage-010,da6f1fb1
e-feImage-011,df29e4e7
e-feMerge-001,9c2179ad
e-feMerge-002,3a7a0cef
e-feMerge-001,6201ebfe
e-feMerge-002,6821d1e7
e-feOffset-001,8a5594e2
e-feOffset-002,8e4d17ef
e-feOffset-003,8ffab3d0
......@@ -461,7 +461,7 @@ e-linearGradient-002,f333c639
e-linearGradient-003,b090e2e6
e-linearGradient-004,6153c036
e-linearGradient-005,f333c639
e-linearGradient-006,21ddd0e3
e-linearGradient-006,5733e899
e-linearGradient-007,b4355cce
e-linearGradient-008,d4f15dbe
e-linearGradient-009,669371f5
......@@ -484,7 +484,7 @@ e-linearGradient-025,3f79d317
e-linearGradient-026,d35ddf9b
e-linearGradient-027,14d5b02d
e-linearGradient-028,2c0481ec
e-linearGradient-029,a6794538
e-linearGradient-029,1abb06ee
e-linearGradient-030,10fb99ae
e-mask-001,07db0d65
e-mask-002,80a2b74c
......@@ -598,7 +598,7 @@ e-radialGradient-002,9728d6a9
e-radialGradient-003,13efda6a
e-radialGradient-004,b4a20272
e-radialGradient-005,9728d6a9
e-radialGradient-006,ca610e24
e-radialGradient-006,41752492
e-radialGradient-007,10b899b4
e-radialGradient-008,1659756f
e-radialGradient-009,dd98bb2c
......@@ -929,3 +929,7 @@ e-marker-055,92588210
e-marker-056,1aa62c2b
e-tspan-018,2ddc5037
e-use-023,967b9e79
e-filter-057,a2b786f1
e-linearGradient-031,3fd79268
e-pattern-027,f3fbe960
e-radialGradient-039,f0ad4b80
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment