[librsvg: 1/7] Implement geometry properties
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/7] Implement geometry properties
- Date: Sat, 5 Mar 2022 03:35:30 +0000 (UTC)
commit c9571ccb8b98fc8d9c1cde568e95d1f4fcbefaaf
Author: Jeremias Ortega <jeremias ortega tech>
Date: Sun Feb 27 22:22:50 2022 -0600
Implement geometry properties
Closes https://gitlab.gnome.org/GNOME/librsvg/-/issues/772
https://gitlab.gnome.org/GNOME/librsvg/-/issues/773 https://gitlab.gnome.org/GNOME/librsvg/-/issues/774
https://gitlab.gnome.org/GNOME/librsvg/-/issues/775 https://gitlab.gnome.org/GNOME/librsvg/-/issues/776
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/670>
src/api.rs | 22 ++---
src/c_api/handle.rs | 4 +-
src/c_api/sizing.rs | 6 +-
src/handle.rs | 14 ++--
src/image.rs | 16 +---
src/properties.rs | 27 ++++---
src/property_defs.rs | 90 +++++++++++++++++++++
src/shapes.rs | 164 +++++++++++++++-----------------------
src/structure.rs | 66 +++++++--------
tests/src/intrinsic_dimensions.rs | 8 +-
tests/src/predicates/svg.rs | 2 +-
tests/src/reference.rs | 20 ++---
12 files changed, 239 insertions(+), 200 deletions(-)
---
diff --git a/src/api.rs b/src/api.rs
index 8316b2907..16175f60c 100644
--- a/src/api.rs
+++ b/src/api.rs
@@ -268,11 +268,11 @@ const DEFAULT_DPI_Y: f64 = 96.0;
/// ```
/// In this case, the length fields will be set to `Some()`, and `vbox` to `None`.
pub struct IntrinsicDimensions {
- /// `width` attribute of the `<svg>`, if present
- pub width: Option<Length>,
+ /// `width` attribute of the `<svg>`
+ pub width: Length,
- /// `height` attribute of the `<svg>`, if present
- pub height: Option<Length>,
+ /// `height` attribute of the `<svg>`
+ pub height: Length,
/// `viewBox` attribute of the `<svg>`, if present
pub vbox: Option<cairo::Rectangle>,
@@ -343,8 +343,8 @@ impl<'a> CairoRenderer<'a> {
let d = self.handle.0.get_intrinsic_dimensions();
IntrinsicDimensions {
- width: d.width.map(Into::into),
- height: d.height.map(Into::into),
+ width: Into::into(d.width),
+ height: Into::into(d.height),
vbox: d.vbox.map(|v| cairo::Rectangle::from(*v)),
}
}
@@ -366,14 +366,8 @@ impl<'a> CairoRenderer<'a> {
/// application can use a viewport size to scale percentage-based dimensions.
pub fn intrinsic_size_in_pixels(&self) -> Option<(f64, f64)> {
let dim = self.intrinsic_dimensions();
-
- // missing width/height default to "auto", which compute to "100%"
- let width = dim
- .width
- .unwrap_or_else(|| Length::new(1.0, LengthUnit::Percent));
- let height = dim
- .height
- .unwrap_or_else(|| Length::new(1.0, LengthUnit::Percent));
+ let width = dim.width;
+ let height = dim.height;
if width.unit == LengthUnit::Percent || height.unit == LengthUnit::Percent {
return None;
diff --git a/src/c_api/handle.rs b/src/c_api/handle.rs
index 0619325c0..9106f9da8 100644
--- a/src/c_api/handle.rs
+++ b/src/c_api/handle.rs
@@ -1736,8 +1736,8 @@ pub unsafe extern "C" fn rsvg_handle_get_intrinsic_dimensions(
let h = d.height;
let r = d.vbox.map(RsvgRectangle::from);
- set_out_param(out_has_width, out_width, &w.map(Into::into));
- set_out_param(out_has_height, out_height, &h.map(Into::into));
+ set_out_param(out_has_width, out_width, &Into::into(w));
+ set_out_param(out_has_height, out_height, &Into::into(h));
set_out_param(out_has_viewbox, out_viewbox, &r);
}
diff --git a/src/c_api/sizing.rs b/src/c_api/sizing.rs
index b475d4281..902c188f7 100644
--- a/src/c_api/sizing.rs
+++ b/src/c_api/sizing.rs
@@ -12,7 +12,7 @@
use float_cmp::approx_eq;
-use crate::api::{CairoRenderer, IntrinsicDimensions, Length, RenderingError};
+use crate::api::{CairoRenderer, IntrinsicDimensions, RenderingError};
use crate::dpi::Dpi;
use crate::handle::Handle;
use crate::length::*;
@@ -101,10 +101,6 @@ fn size_in_pixels_from_percentage_width_and_height(
let (w, h) = handle.width_height_to_user(dpi);
- // missing width/height default to "auto", which compute to "100%"
- let width = width.unwrap_or_else(|| Length::new(1.0, Percent));
- let height = height.unwrap_or_else(|| Length::new(1.0, Percent));
-
// Avoid division by zero below. If the viewBox is zero-sized, there's
// not much we can do.
if approx_eq!(f64, vbox.width, 0.0) || approx_eq!(f64, vbox.height, 0.0) {
diff --git a/src/handle.rs b/src/handle.rs
index 4c8ea852b..2480eb9a8 100644
--- a/src/handle.rs
+++ b/src/handle.rs
@@ -116,13 +116,8 @@ impl Handle {
pub fn width_height_to_user(&self, dpi: Dpi) -> (f64, f64) {
let dimensions = self.get_intrinsic_dimensions();
- // missing width/height default to "auto", which compute to "100%"
- let width = dimensions
- .width
- .unwrap_or_else(|| ULength::new(1.0, LengthUnit::Percent));
- let height = dimensions
- .height
- .unwrap_or_else(|| ULength::new(1.0, LengthUnit::Percent));
+ let width = dimensions.width;
+ let height = dimensions.height;
let view_params = ViewParams::new(dpi, 0.0, 0.0);
let root = self.document.root();
@@ -360,7 +355,10 @@ impl Handle {
}
pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
- borrow_element_as!(self.document.root(), Svg).get_intrinsic_dimensions()
+ let root = self.document.root();
+ let cascaded = CascadedValues::new_from_node(&root);
+ let values = cascaded.get();
+ borrow_element_as!(self.document.root(), Svg).get_intrinsic_dimensions(values)
}
pub fn set_stylesheet(&mut self, css: &str) -> Result<(), LoadingError> {
diff --git a/src/image.rs b/src/image.rs
index 95e48a242..d2f8c7155 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -18,10 +18,6 @@ use crate::xml::Attributes;
#[derive(Default)]
pub struct Image {
- x: Length<Horizontal>,
- y: Length<Vertical>,
- width: LengthOrAuto<Horizontal>,
- height: LengthOrAuto<Vertical>,
aspect: AspectRatio,
href: Option<String>,
}
@@ -30,10 +26,6 @@ impl SetAttributes for Image {
fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
for (attr, value) in attrs.iter() {
match attr.expanded() {
- expanded_name!("", "x") => self.x = attr.parse(value)?,
- expanded_name!("", "y") => self.y = attr.parse(value)?,
- expanded_name!("", "width") => self.width = attr.parse(value)?,
- expanded_name!("", "height") => self.height = attr.parse(value)?,
expanded_name!("", "preserveAspectRatio") => self.aspect = attr.parse(value)?,
// "path" is used by some older Adobe Illustrator versions
@@ -74,14 +66,14 @@ impl Draw for Image {
let view_params = draw_ctx.get_view_params();
let params = NormalizeParams::new(values, &view_params);
- let x = self.x.to_user(¶ms);
- let y = self.y.to_user(¶ms);
+ let x = values.x().0.to_user(¶ms);
+ let y = values.y().0.to_user(¶ms);
- let w = match self.width {
+ let w = match values.width().0 {
LengthOrAuto::Length(l) => l.to_user(¶ms),
LengthOrAuto::Auto => surface.width() as f64,
};
- let h = match self.height {
+ let h = match values.height().0 {
LengthOrAuto::Length(l) => l.to_user(¶ms),
LengthOrAuto::Auto => surface.height() as f64,
};
diff --git a/src/properties.rs b/src/properties.rs
index 071646e34..eb5fc24c6 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -397,15 +397,6 @@ make_properties! {
}
// longhands that are presentation attributes right now, but need to be turned into properties:
- // "cx" - applies only to circle, ellipse
- // "cy" - applies only to circle, ellipse
- // "height" - applies only to foreignObject, image, rect, svg, symbol, use
- // "width" - applies only to foreignObject, image, rect, svg, symbol, use
- // "x" - applies only to foreignObject, image, rect, svg, symbol, use
- // "y" - applies only to foreignObject, image, rect, svg, symbol, use
- // "r" - applies only to circle
- // "rx" - applies only to ellipse, rect
- // "ry" - applies only to ellipse, rect
// "d" - applies only to path
longhands: {
@@ -417,6 +408,8 @@ make_properties! {
// "color-interpolation" => (PresentationAttr::Yes, unimplemented),
"color-interpolation-filters" => (PresentationAttr::Yes, color_interpolation_filters :
ColorInterpolationFilters),
// "cursor" => (PresentationAttr::Yes, unimplemented),
+ "cx" => (PresentationAttr::Yes, cx: CX),
+ "cy" => (PresentationAttr::Yes, cy: CY),
"direction" => (PresentationAttr::Yes, direction : Direction),
"display" => (PresentationAttr::Yes, display : Display),
// "dominant-baseline" => (PresentationAttr::Yes, unimplemented),
@@ -450,6 +443,7 @@ make_properties! {
// So, we put the property here, not in the shorthands, and deal with it as a
// special case in the text handling code.
"glyph-orientation-vertical" => (PresentationAttr::Yes, glyph_orientation_vertical :
GlyphOrientationVertical),
+ "height" => (PresentationAttr::Yes, height: Height),
// "image-rendering" => (PresentationAttr::Yes, unimplemented),
"letter-spacing" => (PresentationAttr::Yes, letter_spacing :
LetterSpacing),
@@ -461,6 +455,9 @@ make_properties! {
"opacity" => (PresentationAttr::Yes, opacity : Opacity),
"overflow" => (PresentationAttr::Yes, overflow : Overflow),
// "pointer-events" => (PresentationAttr::Yes, unimplemented),
+ "r" => (PresentationAttr::Yes, r: R),
+ "rx" => (PresentationAttr::Yes, rx: RX),
+ "ry" => (PresentationAttr::Yes, ry: RY),
"shape-rendering" => (PresentationAttr::Yes, shape_rendering :
ShapeRendering),
"stop-color" => (PresentationAttr::Yes, stop_color : StopColor),
"stop-opacity" => (PresentationAttr::Yes, stop_opacity : StopOpacity),
@@ -490,7 +487,10 @@ make_properties! {
"visibility" => (PresentationAttr::Yes, visibility : Visibility),
// "white-space" => (PresentationAttr::Yes, unimplemented),
// "word-spacing" => (PresentationAttr::Yes, unimplemented),
+ "width" => (PresentationAttr::Yes, width: Width),
"writing-mode" => (PresentationAttr::Yes, writing_mode : WritingMode),
+ "x" => (PresentationAttr::Yes, x: X),
+ "y" => (PresentationAttr::Yes, y: Y),
}
longhands_not_supported_by_markup5ever: {
@@ -699,6 +699,8 @@ impl SpecifiedValues {
compute!(ClipRule, clip_rule);
compute!(Color, color);
compute!(ColorInterpolationFilters, color_interpolation_filters);
+ compute!(CX, cx);
+ compute!(CY, cy);
compute!(Direction, direction);
compute!(Display, display);
compute!(EnableBackground, enable_background);
@@ -714,6 +716,7 @@ impl SpecifiedValues {
compute!(FontVariant, font_variant);
compute!(FontWeight, font_weight);
compute!(GlyphOrientationVertical, glyph_orientation_vertical);
+ compute!(Height, height);
compute!(Isolation, isolation);
compute!(LetterSpacing, letter_spacing);
compute!(LightingColor, lighting_color);
@@ -726,6 +729,9 @@ impl SpecifiedValues {
compute!(Opacity, opacity);
compute!(Overflow, overflow);
compute!(PaintOrder, paint_order);
+ compute!(R, r);
+ compute!(RX, rx);
+ compute!(RY, ry);
compute!(ShapeRendering, shape_rendering);
compute!(StopColor, stop_color);
compute!(StopOpacity, stop_opacity);
@@ -744,9 +750,12 @@ impl SpecifiedValues {
compute!(TransformProperty, transform_property);
compute!(UnicodeBidi, unicode_bidi);
compute!(Visibility, visibility);
+ compute!(Width, width);
compute!(WritingMode, writing_mode);
+ compute!(X, x);
compute!(XmlSpace, xml_space);
compute!(XmlLang, xml_lang);
+ compute!(Y, y);
computed.transform = self.transform.unwrap_or_else(|| {
match self.get_property(PropertyId::TransformProperty) {
diff --git a/src/property_defs.rs b/src/property_defs.rs
index b4699b04a..1ffd6e029 100644
--- a/src/property_defs.rs
+++ b/src/property_defs.rs
@@ -181,6 +181,26 @@ make_property!(
"sRGB" => Srgb,
);
+make_property!(
+ /// `cx` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#CX
+ CX,
+ default: Length::<Horizontal>::parse_str("0").unwrap(),
+ inherits_automatically: false,
+ newtype_parse: Length<Horizontal>,
+);
+
+make_property!(
+ /// `cy` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#CY
+ CY,
+ default: Length::<Vertical>::parse_str("0").unwrap(),
+ inherits_automatically: false,
+ newtype_parse: Length<Vertical>,
+);
+
make_property!(
/// `direction` property.
///
@@ -510,6 +530,16 @@ make_property!(
inherits_automatically: false,
);
+make_property!(
+ /// `height` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#Sizing
+ Height,
+ default: LengthOrAuto::<Vertical>::Auto,
+ inherits_automatically: false,
+ newtype_parse: LengthOrAuto<Vertical>,
+);
+
make_property!(
/// `isolation` property.
///
@@ -774,6 +804,36 @@ fn parses_paint_order() {
assert!(PaintOrder::parse_str("markers stroke fill hello").is_err());
}
+make_property!(
+ /// `r` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#R
+ R,
+ default: Length::<Both>::parse_str("0").unwrap(),
+ inherits_automatically: false,
+ newtype_parse: Length<Both>,
+);
+
+make_property!(
+ /// `rx` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#RX
+ RX,
+ default: LengthOrAuto::<Horizontal>::Auto,
+ inherits_automatically: false,
+ newtype_parse: LengthOrAuto<Horizontal>,
+);
+
+make_property!(
+ /// `ry` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#RY
+ RY,
+ default: LengthOrAuto::<Vertical>::Auto,
+ inherits_automatically: false,
+ newtype_parse: LengthOrAuto<Vertical>,
+);
+
make_property!(
/// `shape-rendering` property.
///
@@ -1097,6 +1157,16 @@ make_property!(
"collapse" => Collapse,
);
+make_property!(
+ /// `width` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#Sizing
+ Width,
+ default: LengthOrAuto::<Horizontal>::Auto,
+ inherits_automatically: false,
+ newtype_parse: LengthOrAuto<Horizontal>,
+);
+
make_property!(
/// `writing-mode` property.
///
@@ -1147,6 +1217,16 @@ impl WritingMode {
}
}
+make_property!(
+ /// `x` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#X
+ X,
+ default: Length::<Horizontal>::parse_str("0").unwrap(),
+ inherits_automatically: false,
+ newtype_parse: Length<Horizontal>,
+);
+
make_property!(
/// `xml:lang` attribute.
///
@@ -1204,3 +1284,13 @@ make_property!(
"default" => Default,
"preserve" => Preserve,
);
+
+make_property!(
+ /// `y` attribute.
+ ///
+ /// https://www.w3.org/TR/SVG2/geometry.html#Y
+ Y,
+ default: Length::<Vertical>::parse_str("0").unwrap(),
+ inherits_automatically: false,
+ newtype_parse: Length<Vertical>,
+);
diff --git a/src/shapes.rs b/src/shapes.rs
index b8f0f6f3a..f9d0d35d7 100644
--- a/src/shapes.rs
+++ b/src/shapes.rs
@@ -17,6 +17,7 @@ use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
use crate::parsers::{optional_comma, Parse, ParseValue};
use crate::path_builder::{LargeArc, Path as SvgPath, PathBuilder, Sweep};
+use crate::properties::ComputedValues;
use crate::xml::Attributes;
#[derive(PartialEq)]
@@ -37,7 +38,7 @@ impl ShapeDef {
}
trait BasicShape {
- fn make_shape(&self, params: &NormalizeParams) -> ShapeDef;
+ fn make_shape(&self, params: &NormalizeParams, values: &ComputedValues) -> ShapeDef;
}
macro_rules! impl_draw {
@@ -54,7 +55,7 @@ macro_rules! impl_draw {
let values = cascaded.get();
let view_params = draw_ctx.get_view_params();
let params = NormalizeParams::new(values, &view_params);
- let shape_def = self.make_shape(¶ms);
+ let shape_def = self.make_shape(¶ms, values);
let is_visible = values.is_visible();
let paint_order = values.paint_order();
@@ -249,7 +250,7 @@ impl SetAttributes for Path {
}
impl BasicShape for Path {
- fn make_shape(&self, _params: &NormalizeParams) -> ShapeDef {
+ fn make_shape(&self, _params: &NormalizeParams, _values: &ComputedValues) -> ShapeDef {
ShapeDef::new(self.path.clone(), Markers::Yes)
}
}
@@ -330,7 +331,7 @@ impl SetAttributes for Polygon {
}
impl BasicShape for Polygon {
- fn make_shape(&self, _params: &NormalizeParams) -> ShapeDef {
+ fn make_shape(&self, _params: &NormalizeParams, _values: &ComputedValues) -> ShapeDef {
ShapeDef::new(Rc::new(make_poly(&self.points, true)), Markers::Yes)
}
}
@@ -355,7 +356,7 @@ impl SetAttributes for Polyline {
}
impl BasicShape for Polyline {
- fn make_shape(&self, _params: &NormalizeParams) -> ShapeDef {
+ fn make_shape(&self, _params: &NormalizeParams, _values: &ComputedValues) -> ShapeDef {
ShapeDef::new(Rc::new(make_poly(&self.points, false)), Markers::Yes)
}
}
@@ -387,7 +388,7 @@ impl SetAttributes for Line {
}
impl BasicShape for Line {
- fn make_shape(&self, params: &NormalizeParams) -> ShapeDef {
+ fn make_shape(&self, params: &NormalizeParams, _values: &ComputedValues) -> ShapeDef {
let mut builder = PathBuilder::default();
let x1 = self.x1.to_user(params);
@@ -403,65 +404,35 @@ impl BasicShape for Line {
}
#[derive(Default)]
-pub struct Rect {
- x: Length<Horizontal>,
- y: Length<Vertical>,
- width: LengthOrAuto<Horizontal>,
- height: LengthOrAuto<Vertical>,
-
- // Radiuses for rounded corners
- rx: Option<Length<Horizontal>>,
- ry: Option<Length<Vertical>>,
-}
+pub struct Rect {}
impl_draw!(Rect);
-impl SetAttributes for Rect {
- fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
- for (attr, value) in attrs.iter() {
- match attr.expanded() {
- expanded_name!("", "x") => self.x = attr.parse(value)?,
- expanded_name!("", "y") => self.y = attr.parse(value)?,
- expanded_name!("", "width") => self.width = attr.parse(value)?,
- expanded_name!("", "height") => self.height = attr.parse(value)?,
- expanded_name!("", "rx") => self.rx = attr.parse(value)?,
- expanded_name!("", "ry") => self.ry = attr.parse(value)?,
- _ => (),
- }
- }
-
- Ok(())
- }
-}
+impl SetAttributes for Rect {}
impl BasicShape for Rect {
#[allow(clippy::many_single_char_names)]
- fn make_shape(&self, params: &NormalizeParams) -> ShapeDef {
- let x = self.x.to_user(params);
- let y = self.y.to_user(params);
+ fn make_shape(&self, params: &NormalizeParams, values: &ComputedValues) -> ShapeDef {
+ let x = values.x().0.to_user(params);
+ let y = values.y().0.to_user(params);
- let w = match self.width {
+ let w = match values.width().0 {
LengthOrAuto::Length(l) => l.to_user(params),
LengthOrAuto::Auto => 0.0,
};
- let h = match self.height {
+ let h = match values.height().0 {
LengthOrAuto::Length(l) => l.to_user(params),
LengthOrAuto::Auto => 0.0,
};
- let specified_rx = self.rx.map(|l| l.to_user(params));
- let specified_ry = self.ry.map(|l| l.to_user(params));
-
- fn nonnegative_or_none(l: f64) -> Option<f64> {
- if l < 0.0 {
- None
- } else {
- Some(l)
- }
- }
-
- let norm_rx = specified_rx.and_then(nonnegative_or_none);
- let norm_ry = specified_ry.and_then(nonnegative_or_none);
+ let norm_rx = match values.rx().0 {
+ LengthOrAuto::Length(l) => Some(l.to_user(params)),
+ LengthOrAuto::Auto => None,
+ };
+ let norm_ry = match values.ry().0 {
+ LengthOrAuto::Length(l) => Some(l.to_user(params)),
+ LengthOrAuto::Auto => None,
+ };
let mut rx;
let mut ry;
@@ -622,71 +593,66 @@ impl BasicShape for Rect {
}
#[derive(Default)]
-pub struct Circle {
- cx: Length<Horizontal>,
- cy: Length<Vertical>,
- r: ULength<Both>,
-}
+pub struct Circle {}
impl_draw!(Circle);
-impl SetAttributes for Circle {
- fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
- for (attr, value) in attrs.iter() {
- match attr.expanded() {
- expanded_name!("", "cx") => self.cx = attr.parse(value)?,
- expanded_name!("", "cy") => self.cy = attr.parse(value)?,
- expanded_name!("", "r") => self.r = attr.parse(value)?,
- _ => (),
- }
- }
-
- Ok(())
- }
-}
+impl SetAttributes for Circle {}
impl BasicShape for Circle {
- fn make_shape(&self, params: &NormalizeParams) -> ShapeDef {
- let cx = self.cx.to_user(params);
- let cy = self.cy.to_user(params);
- let r = self.r.to_user(params);
+ fn make_shape(&self, params: &NormalizeParams, values: &ComputedValues) -> ShapeDef {
+ let cx = values.cx().0.to_user(params);
+ let cy = values.cy().0.to_user(params);
+ let r = values.r().0.to_user(params);
ShapeDef::new(Rc::new(make_ellipse(cx, cy, r, r)), Markers::No)
}
}
#[derive(Default)]
-pub struct Ellipse {
- cx: Length<Horizontal>,
- cy: Length<Vertical>,
- rx: ULength<Horizontal>,
- ry: ULength<Vertical>,
-}
+pub struct Ellipse {}
impl_draw!(Ellipse);
-impl SetAttributes for Ellipse {
- fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
- for (attr, value) in attrs.iter() {
- match attr.expanded() {
- expanded_name!("", "cx") => self.cx = attr.parse(value)?,
- expanded_name!("", "cy") => self.cy = attr.parse(value)?,
- expanded_name!("", "rx") => self.rx = attr.parse(value)?,
- expanded_name!("", "ry") => self.ry = attr.parse(value)?,
- _ => (),
+impl SetAttributes for Ellipse {}
+
+impl BasicShape for Ellipse {
+ fn make_shape(&self, params: &NormalizeParams, values: &ComputedValues) -> ShapeDef {
+ let cx = values.cx().0.to_user(params);
+ let cy = values.cy().0.to_user(params);
+ let norm_rx = match values.rx().0 {
+ LengthOrAuto::Length(l) => Some(l.to_user(params)),
+ LengthOrAuto::Auto => None,
+ };
+ let norm_ry = match values.ry().0 {
+ LengthOrAuto::Length(l) => Some(l.to_user(params)),
+ LengthOrAuto::Auto => None,
+ };
+
+ let rx;
+ let ry;
+
+ match (norm_rx, norm_ry) {
+ (None, None) => {
+ rx = 0.0;
+ ry = 0.0;
}
- }
- Ok(())
- }
-}
+ (Some(_rx), None) => {
+ rx = _rx;
+ ry = _rx;
+ }
-impl BasicShape for Ellipse {
- fn make_shape(&self, params: &NormalizeParams) -> ShapeDef {
- let cx = self.cx.to_user(params);
- let cy = self.cy.to_user(params);
- let rx = self.rx.to_user(params);
- let ry = self.ry.to_user(params);
+ (None, Some(_ry)) => {
+ rx = _ry;
+ ry = _ry;
+ }
+
+ (Some(_rx), Some(_ry)) => {
+ rx = _rx;
+ ry = _ry;
+ }
+ }
ShapeDef::new(Rc::new(make_ellipse(cx, cy, rx, ry)), Markers::No)
}
diff --git a/src/structure.rs b/src/structure.rs
index 257b04ebd..459d66d7b 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -14,6 +14,7 @@ use crate::layout::StackingContext;
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow, NodeDraw};
use crate::parsers::{Parse, ParseValue};
+use crate::properties::ComputedValues;
use crate::rect::Rect;
use crate::viewbox::*;
use crate::xml::Attributes;
@@ -111,10 +112,10 @@ impl Draw for Switch {
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct IntrinsicDimensions {
/// Contents of the `width` attribute.
- pub width: Option<ULength<Horizontal>>,
+ pub width: ULength<Horizontal>,
/// Contents of the `height` attribute.
- pub height: Option<ULength<Vertical>>,
+ pub height: ULength<Vertical>,
/// Contents of the `viewBox` attribute.
pub vbox: Option<ViewBox>,
@@ -123,24 +124,20 @@ pub struct IntrinsicDimensions {
#[derive(Default)]
pub struct Svg {
preserve_aspect_ratio: AspectRatio,
- x: Option<Length<Horizontal>>,
- y: Option<Length<Vertical>>,
- width: Option<LengthOrAuto<Horizontal>>,
- height: Option<LengthOrAuto<Vertical>>,
vbox: Option<ViewBox>,
}
impl Svg {
- pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
- let w = self.width.map(|length_or_auto| match length_or_auto {
+ pub fn get_intrinsic_dimensions(&self, values: &ComputedValues) -> IntrinsicDimensions {
+ let w = match values.width().0 {
LengthOrAuto::Auto => ULength::<Horizontal>::parse_str("100%").unwrap(),
LengthOrAuto::Length(l) => l,
- });
+ };
- let h = self.height.map(|length_or_auto| match length_or_auto {
+ let h = match values.height().0 {
LengthOrAuto::Auto => ULength::<Vertical>::parse_str("100%").unwrap(),
LengthOrAuto::Length(l) => l,
- });
+ };
IntrinsicDimensions {
width: w,
@@ -149,42 +146,49 @@ impl Svg {
}
}
- fn get_unnormalized_offset(&self) -> (Length<Horizontal>, Length<Vertical>) {
+ fn get_unnormalized_offset(
+ &self,
+ values: &ComputedValues,
+ ) -> (Length<Horizontal>, Length<Vertical>) {
// these defaults are per the spec
- let x = self
- .x
- .unwrap_or_else(|| Length::<Horizontal>::parse_str("0").unwrap());
- let y = self
- .y
- .unwrap_or_else(|| Length::<Vertical>::parse_str("0").unwrap());
+ let x = values.x().0;
+ let y = values.y().0;
(x, y)
}
- fn get_unnormalized_size(&self) -> (ULength<Horizontal>, ULength<Vertical>) {
+ fn get_unnormalized_size(
+ &self,
+ values: &ComputedValues,
+ ) -> (ULength<Horizontal>, ULength<Vertical>) {
// these defaults are per the spec
- let w = match self.width {
- None | Some(LengthOrAuto::Auto) => ULength::<Horizontal>::parse_str("100%").unwrap(),
- Some(LengthOrAuto::Length(l)) => l,
+ let w = match values.width().0 {
+ LengthOrAuto::Auto => ULength::<Horizontal>::parse_str("100%").unwrap(),
+ LengthOrAuto::Length(l) => l,
};
- let h = match self.height {
- None | Some(LengthOrAuto::Auto) => ULength::<Vertical>::parse_str("100%").unwrap(),
- Some(LengthOrAuto::Length(l)) => l,
+ let h = match values.height().0 {
+ LengthOrAuto::Auto => ULength::<Vertical>::parse_str("100%").unwrap(),
+ LengthOrAuto::Length(l) => l,
};
(w, h)
}
- fn get_viewport(&self, params: &NormalizeParams, outermost: bool) -> Rect {
+ fn get_viewport(
+ &self,
+ params: &NormalizeParams,
+ values: &ComputedValues,
+ outermost: bool,
+ ) -> Rect {
// x & y attributes have no effect on outermost svg
// http://www.w3.org/TR/SVG/struct.html#SVGElement
let (nx, ny) = if outermost {
(0.0, 0.0)
} else {
- let (x, y) = self.get_unnormalized_offset();
+ let (x, y) = self.get_unnormalized_offset(values);
(x.to_user(params), y.to_user(params))
};
- let (w, h) = self.get_unnormalized_size();
+ let (w, h) = self.get_unnormalized_size(values);
let (nw, nh) = (w.to_user(params), h.to_user(params));
Rect::new(nx, ny, nx + nw, ny + nh)
@@ -209,7 +213,7 @@ impl Svg {
None
};
- let svg_viewport = self.get_viewport(¶ms, !has_parent);
+ let svg_viewport = self.get_viewport(¶ms, values, !has_parent);
let is_measuring_toplevel_svg = !has_parent && draw_ctx.is_measuring();
@@ -248,10 +252,6 @@ impl SetAttributes for Svg {
expanded_name!("", "preserveAspectRatio") => {
self.preserve_aspect_ratio = attr.parse(value)?
}
- expanded_name!("", "x") => self.x = attr.parse(value)?,
- expanded_name!("", "y") => self.y = attr.parse(value)?,
- expanded_name!("", "width") => self.width = attr.parse(value)?,
- expanded_name!("", "height") => self.height = attr.parse(value)?,
expanded_name!("", "viewBox") => self.vbox = attr.parse(value)?,
_ => (),
}
diff --git a/tests/src/intrinsic_dimensions.rs b/tests/src/intrinsic_dimensions.rs
index ac9bd6d55..01f0704a1 100644
--- a/tests/src/intrinsic_dimensions.rs
+++ b/tests/src/intrinsic_dimensions.rs
@@ -17,8 +17,8 @@ fn no_intrinsic_dimensions() {
assert_eq!(
CairoRenderer::new(&svg).intrinsic_dimensions(),
IntrinsicDimensions {
- width: None,
- height: None,
+ width: Length::new(1.0, LengthUnit::Percent),
+ height: Length::new(1.0, LengthUnit::Percent),
vbox: None,
}
);
@@ -36,8 +36,8 @@ fn has_intrinsic_dimensions() {
assert_eq!(
CairoRenderer::new(&svg).intrinsic_dimensions(),
IntrinsicDimensions {
- width: Some(Length::new(10.0, LengthUnit::Cm)),
- height: Some(Length::new(20.0, LengthUnit::Px)),
+ width: Length::new(10.0, LengthUnit::Cm),
+ height: Length::new(20.0, LengthUnit::Px),
vbox: Some(cairo::Rectangle {
x: 0.0,
y: 0.0,
diff --git a/tests/src/predicates/svg.rs b/tests/src/predicates/svg.rs
index f4499e788..d70cb2d9d 100644
--- a/tests/src/predicates/svg.rs
+++ b/tests/src/predicates/svg.rs
@@ -114,7 +114,7 @@ impl DetailPredicate<SvgPredicate> {
Detail::Size(d) => {
let renderer = CairoRenderer::new(handle);
let dimensions = renderer.intrinsic_dimensions();
- (dimensions.width, dimensions.height) == (Some(d.w), Some(d.h))
+ (dimensions.width, dimensions.height) == (d.w, d.h)
}
}
}
diff --git a/tests/src/reference.rs b/tests/src/reference.rs
index d04b4fb62..1eb088a01 100644
--- a/tests/src/reference.rs
+++ b/tests/src/reference.rs
@@ -132,16 +132,14 @@ fn image_size(dim: IntrinsicDimensions, dpi: f64) -> (i32, i32) {
use librsvg::LengthUnit::*;
- if let (Some(width), Some(height)) = (width, height) {
- if !(has_supported_unit(&width) && has_supported_unit(&height)) {
- panic!("SVG has unsupported unit type in width or height");
- }
+ if !(has_supported_unit(&width) && has_supported_unit(&height)) {
+ panic!("SVG has unsupported unit type in width or height");
}
#[rustfmt::skip]
let (width, height) = match (width, height, vbox) {
- (Some(Length { length: w, unit: Percent }),
- Some(Length { length: h, unit: Percent }), vbox) if w == 1.0 && h == 1.0 => {
+ (Length { length: w, unit: Percent },
+ Length { length: h, unit: Percent }, vbox) if w == 1.0 && h == 1.0 => {
if let Some(vbox) = vbox {
(vbox.width, vbox.height)
} else {
@@ -149,18 +147,14 @@ fn image_size(dim: IntrinsicDimensions, dpi: f64) -> (i32, i32) {
}
}
- (Some(Length { length: _, unit: Percent }),
- Some(Length { length: _, unit: Percent }), _) => {
+ (Length { length: _, unit: Percent },
+ Length { length: _, unit: Percent }, _) => {
panic!("Test suite only supports percentage width/height at 100%");
}
- (Some(w), Some(h), _) => {
+ (w, h, _) => {
(normalize(&w, dpi), normalize(&h, dpi))
}
-
- (None, None, Some(vbox)) => (vbox.width, vbox.height),
-
- (_, _, _) => panic!("Test suite does not support the dimensions of this file"),
};
// Keep in sync with c_api.rs
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]