[librsvg] Split Length into LengthHorizontal/LengthVertical/LengthBoth
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] Split Length into LengthHorizontal/LengthVertical/LengthBoth
- Date: Tue, 22 Jan 2019 01:48:16 +0000 (UTC)
commit cab989b9f749ca71551ad1fb68411bb2e96d96b8
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Jan 21 18:14:39 2019 -0600
Split Length into LengthHorizontal/LengthVertical/LengthBoth
This will help remove the Data associated type from the Parse trait.
rsvg_internals/src/filters/bounds.rs | 18 ++---
rsvg_internals/src/filters/mod.rs | 54 ++++++++++-----
rsvg_internals/src/filters/node.rs | 65 +++++++++++-------
rsvg_internals/src/font_props.rs | 63 ++++++-----------
rsvg_internals/src/gradient.rs | 52 +++++++-------
rsvg_internals/src/image.rs | 30 ++++----
rsvg_internals/src/length.rs | 128 ++++++++++++++++++++++++++---------
rsvg_internals/src/marker.rs | 41 +++++------
rsvg_internals/src/mask.rs | 51 +++++---------
rsvg_internals/src/pattern.rs | 28 ++++----
rsvg_internals/src/properties.rs | 38 +++++------
rsvg_internals/src/shapes.rs | 119 ++++++++++++++++----------------
rsvg_internals/src/stop.rs | 8 +--
rsvg_internals/src/structure.rs | 60 ++++++++--------
rsvg_internals/src/text.rs | 96 ++++++++++++--------------
15 files changed, 446 insertions(+), 405 deletions(-)
---
diff --git a/rsvg_internals/src/filters/bounds.rs b/rsvg_internals/src/filters/bounds.rs
index 685fbeba..806b95c9 100644
--- a/rsvg_internals/src/filters/bounds.rs
+++ b/rsvg_internals/src/filters/bounds.rs
@@ -3,7 +3,7 @@ use cairo::{self, MatrixTrait};
use bbox::BoundingBox;
use drawing_ctx::DrawingCtx;
-use length::Length;
+use length::{LengthHorizontal, LengthVertical};
use rect::IRect;
use super::context::{FilterContext, FilterInput, FilterOutput};
@@ -21,10 +21,10 @@ pub struct BoundsBuilder<'a> {
standard_input_was_referenced: bool,
/// Filter primitive properties.
- x: Option<Length>,
- y: Option<Length>,
- width: Option<Length>,
- height: Option<Length>,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
+ width: Option<LengthHorizontal>,
+ height: Option<LengthVertical>,
}
impl<'a> BoundsBuilder<'a> {
@@ -32,10 +32,10 @@ impl<'a> BoundsBuilder<'a> {
#[inline]
pub fn new(
ctx: &'a FilterContext,
- x: Option<Length>,
- y: Option<Length>,
- width: Option<Length>,
- height: Option<Length>,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
+ width: Option<LengthHorizontal>,
+ height: Option<LengthVertical>,
) -> Self {
Self {
ctx,
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 9420ab34..486fe84e 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -9,7 +9,7 @@ use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::DrawingCtx;
use error::{RenderingError, ValueErrorKind};
-use length::{Length, LengthDir, LengthUnit};
+use length::{LengthHorizontal, LengthUnit, LengthVertical};
use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use parsers::{ParseError, ParseValue};
use properties::{ColorInterpolationFilters, ComputedValues};
@@ -70,10 +70,10 @@ trait Filter: NodeTrait {
/// The base filter primitive node containing common properties.
struct Primitive {
- x: Cell<Option<Length>>,
- y: Cell<Option<Length>>,
- width: Cell<Option<Length>>,
- height: Cell<Option<Length>>,
+ x: Cell<Option<LengthHorizontal>>,
+ y: Cell<Option<LengthVertical>>,
+ width: Cell<Option<LengthHorizontal>>,
+ height: Cell<Option<LengthVertical>>,
result: RefCell<Option<String>>,
}
@@ -124,42 +124,62 @@ impl NodeTrait for Primitive {
.unwrap_or(CoordUnits::UserSpaceOnUse);
let no_units_allowed = primitiveunits == CoordUnits::ObjectBoundingBox;
- let check_units = |length: Length| {
+
+ let check_units_horizontal = |length: LengthHorizontal| {
+ if !no_units_allowed {
+ return Ok(length);
+ }
+
+ match length.unit() {
+ LengthUnit::Default | LengthUnit::Percent => Ok(length),
+ _ => Err(ValueErrorKind::Parse(ParseError::new(
+ "unit identifiers are not allowed with primitiveUnits set to objectBoundingBox",
+ ))),
+ }
+ };
+
+ let check_units_vertical = |length: LengthVertical| {
if !no_units_allowed {
return Ok(length);
}
- match length.unit {
+ match length.unit() {
LengthUnit::Default | LengthUnit::Percent => Ok(length),
_ => Err(ValueErrorKind::Parse(ParseError::new(
"unit identifiers are not allowed with primitiveUnits set to objectBoundingBox",
))),
}
};
- let check_units_and_ensure_nonnegative =
- |length: Length| check_units(length).and_then(Length::check_nonnegative);
+
+ let check_units_horizontal_and_ensure_nonnegative = |length: LengthHorizontal| {
+ check_units_horizontal(length).and_then(LengthHorizontal::check_nonnegative)
+ };
+
+ let check_units_vertical_and_ensure_nonnegative = |length: LengthVertical| {
+ check_units_vertical(length).and_then(LengthVertical::check_nonnegative)
+ };
for (attr, value) in pbag.iter() {
match attr {
Attribute::X => self.x.set(Some(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- check_units,
+ (),
+ check_units_horizontal,
)?)),
Attribute::Y => self.y.set(Some(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- check_units,
+ (),
+ check_units_vertical,
)?)),
Attribute::Width => self.width.set(Some(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- check_units_and_ensure_nonnegative,
+ (),
+ check_units_horizontal_and_ensure_nonnegative,
)?)),
Attribute::Height => self.height.set(Some(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- check_units_and_ensure_nonnegative,
+ (),
+ check_units_vertical_and_ensure_nonnegative,
)?)),
Attribute::Result => *self.result.borrow_mut() = Some(value.to_string()),
_ => (),
diff --git a/rsvg_internals/src/filters/node.rs b/rsvg_internals/src/filters/node.rs
index e68c3d51..2889e7fa 100644
--- a/rsvg_internals/src/filters/node.rs
+++ b/rsvg_internals/src/filters/node.rs
@@ -4,17 +4,17 @@ use std::cell::Cell;
use attributes::Attribute;
use coord_units::CoordUnits;
use error::ValueErrorKind;
-use length::{Length, LengthDir, LengthUnit};
+use length::{LengthHorizontal, LengthUnit, LengthVertical};
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{Parse, ParseError, ParseValue};
use property_bag::PropertyBag;
/// The <filter> node.
pub struct NodeFilter {
- pub x: Cell<Length>,
- pub y: Cell<Length>,
- pub width: Cell<Length>,
- pub height: Cell<Length>,
+ pub x: Cell<LengthHorizontal>,
+ pub y: Cell<LengthVertical>,
+ pub width: Cell<LengthHorizontal>,
+ pub height: Cell<LengthVertical>,
pub filterunits: Cell<CoordUnits>,
pub primitiveunits: Cell<CoordUnits>,
}
@@ -24,10 +24,10 @@ impl NodeFilter {
#[inline]
pub fn new() -> Self {
Self {
- x: Cell::new(Length::parse_str("-10%", LengthDir::Horizontal).unwrap()),
- y: Cell::new(Length::parse_str("-10%", LengthDir::Vertical).unwrap()),
- width: Cell::new(Length::parse_str("120%", LengthDir::Horizontal).unwrap()),
- height: Cell::new(Length::parse_str("120%", LengthDir::Vertical).unwrap()),
+ x: Cell::new(LengthHorizontal::parse_str("-10%", ()).unwrap()),
+ y: Cell::new(LengthVertical::parse_str("-10%", ()).unwrap()),
+ width: Cell::new(LengthHorizontal::parse_str("120%", ()).unwrap()),
+ height: Cell::new(LengthVertical::parse_str("120%", ()).unwrap()),
filterunits: Cell::new(CoordUnits::ObjectBoundingBox),
primitiveunits: Cell::new(CoordUnits::UserSpaceOnUse),
}
@@ -46,42 +46,61 @@ impl NodeTrait for NodeFilter {
// With ObjectBoundingBox, only fractions and percents are allowed.
let no_units_allowed = self.filterunits.get() == CoordUnits::ObjectBoundingBox;
- let check_units = |length: Length| {
+
+ let check_units_horizontal = |length: LengthHorizontal| {
if !no_units_allowed {
return Ok(length);
}
- match length.unit {
+ match length.unit() {
LengthUnit::Default | LengthUnit::Percent => Ok(length),
_ => Err(ValueErrorKind::Parse(ParseError::new(
"unit identifiers are not allowed with filterUnits set to objectBoundingBox",
))),
}
};
- let check_units_and_ensure_nonnegative =
- |length: Length| check_units(length).and_then(Length::check_nonnegative);
+
+ let check_units_vertical = |length: LengthVertical| {
+ if !no_units_allowed {
+ return Ok(length);
+ }
+
+ match length.unit() {
+ LengthUnit::Default | LengthUnit::Percent => Ok(length),
+ _ => Err(ValueErrorKind::Parse(ParseError::new(
+ "unit identifiers are not allowed with filterUnits set to objectBoundingBox",
+ ))),
+ }
+ };
+
+ let check_units_horizontal_and_ensure_nonnegative = |length: LengthHorizontal| {
+ check_units_horizontal(length).and_then(LengthHorizontal::check_nonnegative)
+ };
+
+ let check_units_vertical_and_ensure_nonnegative = |length: LengthVertical| {
+ check_units_vertical(length).and_then(LengthVertical::check_nonnegative)
+ };
// Parse the rest of the attributes.
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X => self.x.set(attr.parse_and_validate(
- value,
- LengthDir::Horizontal,
- check_units,
- )?),
+ Attribute::X => {
+ self.x
+ .set(attr.parse_and_validate(value, (), check_units_horizontal)?)
+ }
Attribute::Y => {
self.y
- .set(attr.parse_and_validate(value, LengthDir::Vertical, check_units)?)
+ .set(attr.parse_and_validate(value, (), check_units_vertical)?)
}
Attribute::Width => self.width.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- check_units_and_ensure_nonnegative,
+ (),
+ check_units_horizontal_and_ensure_nonnegative,
)?),
Attribute::Height => self.height.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- check_units_and_ensure_nonnegative,
+ (),
+ check_units_vertical_and_ensure_nonnegative,
)?),
Attribute::PrimitiveUnits => self.primitiveunits.set(attr.parse(value, ())?),
_ => (),
diff --git a/rsvg_internals/src/font_props.rs b/rsvg_internals/src/font_props.rs
index ac9b5847..534bd94f 100644
--- a/rsvg_internals/src/font_props.rs
+++ b/rsvg_internals/src/font_props.rs
@@ -2,7 +2,7 @@ use cssparser::{BasicParseError, Parser, Token};
use drawing_ctx::ViewParams;
use error::*;
-use length::{Length, LengthDir, LengthUnit, POINTS_PER_INCH};
+use length::{LengthBoth, LengthHorizontal, LengthUnit, POINTS_PER_INCH};
use parsers::{Parse, ParseError};
use properties::ComputedValues;
@@ -18,11 +18,11 @@ pub enum FontSizeSpec {
Large,
XLarge,
XXLarge,
- Value(Length),
+ Value(LengthBoth),
}
impl FontSizeSpec {
- pub fn value(&self) -> Length {
+ pub fn value(&self) -> LengthBoth {
match self {
FontSizeSpec::Value(s) => s.clone(),
_ => unreachable!(),
@@ -35,31 +35,17 @@ impl FontSizeSpec {
let size = v.font_size.0.value();
let new_size = match self {
- FontSizeSpec::Smaller => Length::new(size.length / 1.2, size.unit, LengthDir::Both),
- FontSizeSpec::Larger => Length::new(size.length * 1.2, size.unit, LengthDir::Both),
- FontSizeSpec::XXSmall => {
- Length::new(compute_points(-3.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::XSmall => {
- Length::new(compute_points(-2.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::Small => {
- Length::new(compute_points(-1.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::Medium => {
- Length::new(compute_points(0.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::Large => {
- Length::new(compute_points(1.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::XLarge => {
- Length::new(compute_points(2.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::XXLarge => {
- Length::new(compute_points(3.0), LengthUnit::Inch, LengthDir::Both)
- }
- FontSizeSpec::Value(s) if s.unit == LengthUnit::Percent => {
- Length::new(size.length * s.length, size.unit, LengthDir::Both)
+ FontSizeSpec::Smaller => LengthBoth::new(size.length() / 1.2, size.unit()),
+ FontSizeSpec::Larger => LengthBoth::new(size.length() * 1.2, size.unit()),
+ FontSizeSpec::XXSmall => LengthBoth::new(compute_points(-3.0), LengthUnit::Inch),
+ FontSizeSpec::XSmall => LengthBoth::new(compute_points(-2.0), LengthUnit::Inch),
+ FontSizeSpec::Small => LengthBoth::new(compute_points(-1.0), LengthUnit::Inch),
+ FontSizeSpec::Medium => LengthBoth::new(compute_points(0.0), LengthUnit::Inch),
+ FontSizeSpec::Large => LengthBoth::new(compute_points(1.0), LengthUnit::Inch),
+ FontSizeSpec::XLarge => LengthBoth::new(compute_points(2.0), LengthUnit::Inch),
+ FontSizeSpec::XXLarge => LengthBoth::new(compute_points(3.0), LengthUnit::Inch),
+ FontSizeSpec::Value(s) if s.unit() == LengthUnit::Percent => {
+ LengthBoth::new(size.length() * s.length(), size.unit())
}
FontSizeSpec::Value(s) => s.clone(),
};
@@ -82,7 +68,7 @@ impl Parse for FontSizeSpec {
) -> Result<FontSizeSpec, ::error::ValueErrorKind> {
let parser_state = parser.state();
- Length::parse(parser, LengthDir::Both)
+ LengthBoth::parse(parser, ())
.and_then(|s| Ok(FontSizeSpec::Value(s)))
.or_else(|e| {
parser.reset(&parser_state);
@@ -184,11 +170,11 @@ impl Parse for FontWeightSpec {
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum LetterSpacingSpec {
Normal,
- Value(Length),
+ Value(LengthHorizontal),
}
impl LetterSpacingSpec {
- pub fn value(&self) -> Length {
+ pub fn value(&self) -> LengthHorizontal {
match self {
LetterSpacingSpec::Value(s) => s.clone(),
_ => unreachable!(),
@@ -197,9 +183,7 @@ impl LetterSpacingSpec {
pub fn compute(&self) -> Self {
let spacing = match self {
- LetterSpacingSpec::Normal => {
- Length::new(0.0, LengthUnit::Default, LengthDir::Horizontal)
- }
+ LetterSpacingSpec::Normal => LengthHorizontal::new(0.0, LengthUnit::Default),
LetterSpacingSpec::Value(s) => s.clone(),
};
@@ -221,7 +205,7 @@ impl Parse for LetterSpacingSpec {
) -> Result<LetterSpacingSpec, ::error::ValueErrorKind> {
let parser_state = parser.state();
- Length::parse(parser, LengthDir::Horizontal)
+ LengthHorizontal::parse(parser, ())
.and_then(|s| Ok(LetterSpacingSpec::Value(s)))
.or_else(|e| {
parser.reset(&parser_state);
@@ -323,10 +307,9 @@ mod tests {
);
assert_eq!(
<LetterSpacingSpec as Parse>::parse_str("10em", ()),
- Ok(LetterSpacingSpec::Value(Length::new(
+ Ok(LetterSpacingSpec::Value(LengthHorizontal::new(
10.0,
LengthUnit::FontEm,
- LengthDir::Horizontal
)))
);
}
@@ -335,18 +318,16 @@ mod tests {
fn computes_letter_spacing() {
assert_eq!(
<LetterSpacingSpec as Parse>::parse_str("normal", ()).map(|s| s.compute()),
- Ok(LetterSpacingSpec::Value(Length::new(
+ Ok(LetterSpacingSpec::Value(LengthHorizontal::new(
0.0,
LengthUnit::Default,
- LengthDir::Horizontal
)))
);
assert_eq!(
<LetterSpacingSpec as Parse>::parse_str("10em", ()).map(|s| s.compute()),
- Ok(LetterSpacingSpec::Value(Length::new(
+ Ok(LetterSpacingSpec::Value(LengthHorizontal::new(
10.0,
LengthUnit::FontEm,
- LengthDir::Horizontal
)))
);
}
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index 2edd2ae6..4e9fc893 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -91,18 +91,18 @@ pub struct GradientCommon {
#[derive(Copy, Clone)]
pub enum GradientVariant {
Linear {
- x1: Option<Length>,
- y1: Option<Length>,
- x2: Option<Length>,
- y2: Option<Length>,
+ x1: Option<LengthHorizontal>,
+ y1: Option<LengthVertical>,
+ x2: Option<LengthHorizontal>,
+ y2: Option<LengthVertical>,
},
Radial {
- cx: Option<Length>,
- cy: Option<Length>,
- r: Option<Length>,
- fx: Option<Length>,
- fy: Option<Length>,
+ cx: Option<LengthHorizontal>,
+ cy: Option<LengthVertical>,
+ r: Option<LengthBoth>,
+ fx: Option<LengthHorizontal>,
+ fy: Option<LengthVertical>,
},
}
@@ -256,10 +256,10 @@ impl GradientVariant {
// https://www.w3.org/TR/SVG/pservers.html#LinearGradients
GradientVariant::Linear {
- x1: Some(Length::parse_str("0%", LengthDir::Horizontal).unwrap()),
- y1: Some(Length::parse_str("0%", LengthDir::Vertical).unwrap()),
- x2: Some(Length::parse_str("100%", LengthDir::Horizontal).unwrap()),
- y2: Some(Length::parse_str("0%", LengthDir::Vertical).unwrap()),
+ x1: Some(LengthHorizontal::parse_str("0%", ()).unwrap()),
+ y1: Some(LengthVertical::parse_str("0%", ()).unwrap()),
+ x2: Some(LengthHorizontal::parse_str("100%", ()).unwrap()),
+ y2: Some(LengthVertical::parse_str("0%", ()).unwrap()),
}
}
@@ -267,9 +267,9 @@ impl GradientVariant {
// https://www.w3.org/TR/SVG/pservers.html#RadialGradients
GradientVariant::Radial {
- cx: Some(Length::parse_str("50%", LengthDir::Horizontal).unwrap()),
- cy: Some(Length::parse_str("50%", LengthDir::Vertical).unwrap()),
- r: Some(Length::parse_str("50%", LengthDir::Both).unwrap()),
+ cx: Some(LengthHorizontal::parse_str("50%", ()).unwrap()),
+ cy: Some(LengthVertical::parse_str("50%", ()).unwrap()),
+ r: Some(LengthBoth::parse_str("50%", ()).unwrap()),
fx: None,
fy: None,
@@ -684,16 +684,16 @@ impl NodeTrait for NodeGradient {
// Attributes specific to each gradient type. The defaults mandated by the spec
// are in GradientVariant::resolve_from_defaults()
- Attribute::X1 => x1 = Some(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y1 => y1 = Some(attr.parse(value, LengthDir::Vertical)?),
- Attribute::X2 => x2 = Some(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y2 => y2 = Some(attr.parse(value, LengthDir::Vertical)?),
-
- Attribute::Cx => cx = Some(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Cy => cy = Some(attr.parse(value, LengthDir::Vertical)?),
- Attribute::R => r = Some(attr.parse(value, LengthDir::Both)?),
- Attribute::Fx => fx = Some(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Fy => fy = Some(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::X1 => x1 = Some(attr.parse(value, ())?),
+ Attribute::Y1 => y1 = Some(attr.parse(value, ())?),
+ Attribute::X2 => x2 = Some(attr.parse(value, ())?),
+ Attribute::Y2 => y2 = Some(attr.parse(value, ())?),
+
+ Attribute::Cx => cx = Some(attr.parse(value, ())?),
+ Attribute::Cy => cy = Some(attr.parse(value, ())?),
+ Attribute::R => r = Some(attr.parse(value, ())?),
+ Attribute::Fx => fx = Some(attr.parse(value, ())?),
+ Attribute::Fy => fy = Some(attr.parse(value, ())?),
_ => (),
}
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 65f7620f..580baa7a 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -9,17 +9,17 @@ use bbox::BoundingBox;
use drawing_ctx::DrawingCtx;
use error::{NodeError, RenderingError};
use float_eq_cairo::ApproxEqCairo;
-use length::*;
+use length::{LengthHorizontal, LengthVertical};
use node::*;
use parsers::{ParseError, ParseValue};
use property_bag::PropertyBag;
pub struct NodeImage {
aspect: Cell<AspectRatio>,
- x: Cell<Length>,
- y: Cell<Length>,
- w: Cell<Length>,
- h: Cell<Length>,
+ x: Cell<LengthHorizontal>,
+ y: Cell<LengthVertical>,
+ w: Cell<LengthHorizontal>,
+ h: Cell<LengthVertical>,
href: RefCell<Option<Href>>,
}
@@ -27,10 +27,10 @@ impl NodeImage {
pub fn new() -> NodeImage {
NodeImage {
aspect: Cell::new(AspectRatio::default()),
- x: Cell::new(Length::default()),
- y: Cell::new(Length::default()),
- w: Cell::new(Length::default()),
- h: Cell::new(Length::default()),
+ x: Cell::new(Default::default()),
+ y: Cell::new(Default::default()),
+ w: Cell::new(Default::default()),
+ h: Cell::new(Default::default()),
href: RefCell::new(None),
}
}
@@ -44,17 +44,17 @@ impl NodeTrait for NodeImage {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X => self.x.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y => self.y.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::X => self.x.set(attr.parse(value, ())?),
+ Attribute::Y => self.y.set(attr.parse(value, ())?),
Attribute::Width => self.w.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?),
Attribute::Height => self.h.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?),
Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value, ())?),
diff --git a/rsvg_internals/src/length.rs b/rsvg_internals/src/length.rs
index 5dd5b65a..80e8fce1 100644
--- a/rsvg_internals/src/length.rs
+++ b/rsvg_internals/src/length.rs
@@ -17,29 +17,105 @@ pub enum LengthUnit {
}
#[derive(Debug, PartialEq, Copy, Clone)]
-pub enum LengthDir {
+enum LengthDir {
Horizontal,
Vertical,
Both,
}
+macro_rules! define_length_type {
+ ($name:ident, $dir:expr) => {
+ #[derive(Debug, PartialEq, Copy, Clone)]
+ pub struct $name(Length);
+
+ impl $name {
+ pub fn new(length: f64, unit: LengthUnit) -> Self {
+ $name(Length::new(length, unit, $dir))
+ }
+
+ pub fn length(&self) -> f64 {
+ self.0.length
+ }
+
+ pub fn unit(&self) -> LengthUnit {
+ self.0.unit
+ }
+
+ pub fn get_unitless(&self) -> f64 {
+ self.0.get_unitless()
+ }
+
+ pub fn check_nonnegative(self) -> Result<Self, ValueErrorKind> {
+ if self.length() >= 0.0 {
+ Ok(self)
+ } else {
+ Err(ValueErrorKind::Value(
+ "value must be non-negative".to_string(),
+ ))
+ }
+ }
+
+ pub fn normalize(&self, values: &ComputedValues, params: &ViewParams) -> f64 {
+ self.0.normalize(values, params)
+ }
+
+ pub fn hand_normalize(
+ &self,
+ pixels_per_inch: f64,
+ width_or_height: f64,
+ font_size: f64,
+ ) -> f64 {
+ self.0
+ .hand_normalize(pixels_per_inch, width_or_height, font_size)
+ }
+
+ pub fn from_cssparser(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
+ Ok($name(Length::from_cssparser(parser, $dir)?))
+ }
+ }
+
+ impl Default for $name {
+ fn default() -> Self {
+ $name(Length::new(0.0, LengthUnit::Default, $dir))
+ }
+ }
+
+ impl Parse for $name {
+ type Data = ();
+ type Err = ValueErrorKind;
+
+ fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<$name, ValueErrorKind> {
+ Ok($name(Length::parse(parser, $dir)?))
+ }
+ }
+ };
+}
+
+/// Horizontal length
+///
+/// When this is specified as a percent value, it will get resolved
+/// against the current viewport's width.
+define_length_type!(LengthHorizontal, LengthDir::Horizontal);
+
+/// Vertical length
+///
+/// When this is specified as a percent value, it will get resolved
+/// against the current viewport's height.
+define_length_type!(LengthVertical, LengthDir::Vertical);
+
+/// "Both" length
+///
+/// When this is specified as a percent value, it will get resolved
+/// against the current viewport's width and height.
+define_length_type!(LengthBoth, LengthDir::Both);
+
#[derive(Debug, PartialEq, Copy, Clone)]
-pub struct Length {
+struct Length {
pub length: f64,
pub unit: LengthUnit,
dir: LengthDir,
}
-impl Default for Length {
- fn default() -> Length {
- Length {
- length: 0.0,
- unit: LengthUnit::Default,
- dir: LengthDir::Both,
- }
- }
-}
-
pub const POINTS_PER_INCH: f64 = 72.0;
const CM_PER_INCH: f64 = 2.54;
const MM_PER_INCH: f64 = 25.4;
@@ -76,7 +152,7 @@ impl Parse for Length {
}
impl Length {
- pub fn new(l: f64, unit: LengthUnit, dir: LengthDir) -> Length {
+ fn new(l: f64, unit: LengthUnit, dir: LengthDir) -> Length {
Length {
length: l,
unit,
@@ -84,16 +160,6 @@ impl Length {
}
}
- pub fn check_nonnegative(self) -> Result<Length, ValueErrorKind> {
- if self.length >= 0.0 {
- Ok(self)
- } else {
- Err(ValueErrorKind::Value(
- "value must be non-negative".to_string(),
- ))
- }
- }
-
pub fn normalize(&self, values: &ComputedValues, params: &ViewParams) -> f64 {
match self.unit {
LengthUnit::Default => self.length,
@@ -236,7 +302,7 @@ fn font_size_from_inch(length: f64, dir: LengthDir, params: &ViewParams) -> f64
}
fn font_size_from_values(values: &ComputedValues, params: &ViewParams) -> f64 {
- let v = &values.font_size.0.value();
+ let v = &values.font_size.0.value().0;
match v.unit {
LengthUnit::Default => v.length,
@@ -263,7 +329,7 @@ fn viewport_percentage(x: f64, y: f64) -> f64 {
#[derive(Debug, PartialEq, Clone)]
pub enum Dasharray {
None,
- Array(Vec<Length>),
+ Array(Vec<LengthBoth>),
}
impl Default for Dasharray {
@@ -286,13 +352,11 @@ impl Parse for Dasharray {
}
// This does not handle "inherit" or "none" state, the caller is responsible for that.
-fn parse_dash_array(parser: &mut Parser<'_, '_>) -> Result<Vec<Length>, ValueErrorKind> {
+fn parse_dash_array(parser: &mut Parser<'_, '_>) -> Result<Vec<LengthBoth>, ValueErrorKind> {
let mut dasharray = Vec::new();
loop {
- dasharray.push(
- Length::from_cssparser(parser, LengthDir::Both).and_then(Length::check_nonnegative)?,
- );
+ dasharray.push(LengthBoth::from_cssparser(parser).and_then(LengthBoth::check_nonnegative)?);
if parser.is_exhausted() {
break;
@@ -398,10 +462,10 @@ mod tests {
#[test]
fn check_nonnegative_works() {
- assert!(Length::parse_str("0", LengthDir::Both)
+ assert!(LengthBoth::parse_str("0", ())
.and_then(|l| l.check_nonnegative())
.is_ok());
- assert!(Length::parse_str("-10", LengthDir::Both)
+ assert!(LengthBoth::parse_str("-10", ())
.and_then(|l| l.check_nonnegative())
.is_err());
}
@@ -478,7 +542,7 @@ mod tests {
#[test]
fn parses_dash_array() {
// helper to cut down boilderplate
- let length_parse = |s| Length::parse_str(s, LengthDir::Both).unwrap();
+ let length_parse = |s| LengthBoth::parse_str(s, ()).unwrap();
let expected = Dasharray::Array(vec![
length_parse("1"),
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index ba12cd44..9f6843a9 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -13,7 +13,7 @@ use drawing_ctx::DrawingCtx;
use error::*;
use float_eq_cairo::ApproxEqCairo;
use iri::IRI;
-use length::{Length, LengthDir};
+use length::{LengthHorizontal, LengthVertical};
use node::*;
use parsers::{Parse, ParseError, ParseValue};
use path_builder::*;
@@ -88,10 +88,10 @@ impl Parse for MarkerOrient {
pub struct NodeMarker {
units: Cell<MarkerUnits>,
- ref_x: Cell<Length>,
- ref_y: Cell<Length>,
- width: Cell<Length>,
- height: Cell<Length>,
+ ref_x: Cell<LengthHorizontal>,
+ ref_y: Cell<LengthVertical>,
+ width: Cell<LengthHorizontal>,
+ height: Cell<LengthVertical>,
orient: Cell<MarkerOrient>,
aspect: Cell<AspectRatio>,
vbox: Cell<Option<ViewBox>>,
@@ -101,26 +101,17 @@ impl NodeMarker {
pub fn new() -> NodeMarker {
NodeMarker {
units: Cell::new(MarkerUnits::default()),
- ref_x: Cell::new(Length::default()),
- ref_y: Cell::new(Length::default()),
- width: Cell::new(Self::default_width()),
- height: Cell::new(Self::default_height()),
+ ref_x: Cell::new(Default::default()),
+ ref_y: Cell::new(Default::default()),
+ // the following two are per the spec
+ width: Cell::new(LengthHorizontal::parse_str("3", ()).unwrap()),
+ height: Cell::new(LengthVertical::parse_str("3", ()).unwrap()),
orient: Cell::new(MarkerOrient::default()),
aspect: Cell::new(AspectRatio::default()),
vbox: Cell::new(None),
}
}
- fn default_width() -> Length {
- // per the spec
- Length::parse_str("3", LengthDir::Horizontal).unwrap()
- }
-
- fn default_height() -> Length {
- // per the spec
- Length::parse_str("3", LengthDir::Vertical).unwrap()
- }
-
fn render(
&self,
node: &RsvgNode,
@@ -220,20 +211,20 @@ impl NodeTrait for NodeMarker {
match attr {
Attribute::MarkerUnits => self.units.set(attr.parse(value, ())?),
- Attribute::RefX => self.ref_x.set(attr.parse(value, LengthDir::Horizontal)?),
+ Attribute::RefX => self.ref_x.set(attr.parse(value, ())?),
- Attribute::RefY => self.ref_y.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::RefY => self.ref_y.set(attr.parse(value, ())?),
Attribute::MarkerWidth => self.width.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?),
Attribute::MarkerHeight => self.height.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?),
Attribute::Orient => self.orient.set(attr.parse(value, ())?),
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index 86dda588..6f6ac58d 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -5,7 +5,7 @@ use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::DrawingCtx;
use error::RenderingError;
-use length::{Length, LengthDir};
+use length::{LengthHorizontal, LengthVertical};
use node::{NodeResult, NodeTrait, RsvgNode};
use parsers::{Parse, ParseValue};
use properties::Opacity;
@@ -23,10 +23,10 @@ coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);
pub struct NodeMask {
- x: Cell<Length>,
- y: Cell<Length>,
- width: Cell<Length>,
- height: Cell<Length>,
+ x: Cell<LengthHorizontal>,
+ y: Cell<LengthVertical>,
+ width: Cell<LengthHorizontal>,
+ height: Cell<LengthVertical>,
units: Cell<MaskUnits>,
content_units: Cell<MaskContentUnits>,
@@ -35,37 +35,18 @@ pub struct NodeMask {
impl NodeMask {
pub fn new() -> NodeMask {
NodeMask {
- x: Cell::new(Self::default_x()),
- y: Cell::new(Self::default_y()),
+ // these values are per the spec
+ x: Cell::new(LengthHorizontal::parse_str("-10%", ()).unwrap()),
+ y: Cell::new(LengthVertical::parse_str("-10%", ()).unwrap()),
- width: Cell::new(Self::default_width()),
- height: Cell::new(Self::default_height()),
+ width: Cell::new(LengthHorizontal::parse_str("120%", ()).unwrap()),
+ height: Cell::new(LengthVertical::parse_str("120%", ()).unwrap()),
units: Cell::new(MaskUnits::default()),
content_units: Cell::new(MaskContentUnits::default()),
}
}
- fn default_x() -> Length {
- // per the spec
- Length::parse_str("-10%", LengthDir::Horizontal).unwrap()
- }
-
- fn default_y() -> Length {
- // per the spec
- Length::parse_str("-10%", LengthDir::Vertical).unwrap()
- }
-
- fn default_width() -> Length {
- // per the spec
- Length::parse_str("120%", LengthDir::Horizontal).unwrap()
- }
-
- fn default_height() -> Length {
- // per the spec
- Length::parse_str("120%", LengthDir::Vertical).unwrap()
- }
-
pub fn generate_cairo_mask(
&self,
node: &RsvgNode,
@@ -207,17 +188,17 @@ impl NodeTrait for NodeMask {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X => self.x.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y => self.y.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::X => self.x.set(attr.parse(value, ())?),
+ Attribute::Y => self.y.set(attr.parse(value, ())?),
Attribute::Width => self.width.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?),
Attribute::Height => self.height.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?),
Attribute::MaskUnits => self.units.set(attr.parse(value, ())?),
Attribute::MaskContentUnits => self.content_units.set(attr.parse(value, ())?),
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 40afce76..36eb84eb 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -37,10 +37,10 @@ pub struct Pattern {
pub preserve_aspect_ratio: Option<AspectRatio>,
pub affine: Option<cairo::Matrix>,
pub fallback: Option<Fragment>,
- pub x: Option<Length>,
- pub y: Option<Length>,
- pub width: Option<Length>,
- pub height: Option<Length>,
+ pub x: Option<LengthHorizontal>,
+ pub y: Option<LengthVertical>,
+ pub width: Option<LengthHorizontal>,
+ pub height: Option<LengthVertical>,
// Point back to our corresponding node, or to the fallback node which has children.
// If the value is None, it means we are fully resolved and didn't find any children
@@ -59,10 +59,10 @@ impl Default for Pattern {
preserve_aspect_ratio: Some(AspectRatio::default()),
affine: Some(cairo::Matrix::identity()),
fallback: None,
- x: Some(Length::default()),
- y: Some(Length::default()),
- width: Some(Length::default()),
- height: Some(Length::default()),
+ x: Some(Default::default()),
+ y: Some(Default::default()),
+ width: Some(Default::default()),
+ height: Some(Default::default()),
node: None,
}
}
@@ -199,23 +199,23 @@ impl NodeTrait for NodePattern {
p.fallback = Some(Fragment::parse(value).attribute(Attribute::XlinkHref)?);
}
- Attribute::X => p.x = Some(attr.parse(value, LengthDir::Horizontal)?),
+ Attribute::X => p.x = Some(attr.parse(value, ())?),
- Attribute::Y => p.y = Some(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::Y => p.y = Some(attr.parse(value, ())?),
Attribute::Width => {
p.width = Some(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?)
}
Attribute::Height => {
p.height = Some(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?)
}
diff --git a/rsvg_internals/src/properties.rs b/rsvg_internals/src/properties.rs
index d00e49d9..baa5c3dc 100644
--- a/rsvg_internals/src/properties.rs
+++ b/rsvg_internals/src/properties.rs
@@ -6,7 +6,7 @@ use attributes::Attribute;
use error::*;
use font_props::{FontSizeSpec, FontWeightSpec, LetterSpacingSpec, SingleFontFamily};
use iri::IRI;
-use length::{Dasharray, Length, LengthDir, LengthUnit};
+use length::{Dasharray, LengthBoth, LengthUnit};
use paint_server::PaintServer;
use parsers::{Parse, ParseError};
use property_bag::PropertyBag;
@@ -407,7 +407,7 @@ impl SpecifiedValues {
}
Attribute::StrokeDashoffset => {
- self.stroke_dashoffset = parse_property(value, LengthDir::Both)?;
+ self.stroke_dashoffset = parse_property(value, ())?;
}
Attribute::StrokeLinecap => {
@@ -427,7 +427,7 @@ impl SpecifiedValues {
}
Attribute::StrokeWidth => {
- self.stroke_width = parse_property(value, LengthDir::Both)?;
+ self.stroke_width = parse_property(value, ())?;
}
Attribute::TextAnchor => {
@@ -593,8 +593,8 @@ where
make_property!(
ComputedValues,
BaselineShift,
- default: Length::parse_str("0.0", LengthDir::Both).unwrap(),
- newtype: Length,
+ default: LengthBoth::parse_str("0.0", ()).unwrap(),
+ newtype: LengthBoth,
property_impl: {
impl Property<ComputedValues> for BaselineShift {
fn inherits_automatically() -> bool {
@@ -608,11 +608,11 @@ make_property!(
// 1) we only handle 'percent' shifts, but it could also be an absolute offset
// 2) we should be able to normalize the lengths and add even if they have
// different units, but at the moment that requires access to the draw_ctx
- if self.0.unit != LengthUnit::Percent || v.baseline_shift.0.unit != font_size.unit {
- return BaselineShift(Length::new(v.baseline_shift.0.length, v.baseline_shift.0.unit,
LengthDir::Both));
+ if self.0.unit() != LengthUnit::Percent || v.baseline_shift.0.unit() != font_size.unit() {
+ return BaselineShift(LengthBoth::new(v.baseline_shift.0.length(),
v.baseline_shift.0.unit()));
}
- BaselineShift(Length::new(self.0.length * font_size.length + v.baseline_shift.0.length,
font_size.unit, LengthDir::Both))
+ BaselineShift(LengthBoth::new(self.0.length() * font_size.length() +
v.baseline_shift.0.length(), font_size.unit()))
}
}
},
@@ -634,15 +634,15 @@ make_property!(
if let Token::Ident(ref cow) = token {
match cow.as_ref() {
"baseline" => return Ok(BaselineShift(
- Length::new(0.0, LengthUnit::Percent, LengthDir::Both)
+ LengthBoth::new(0.0, LengthUnit::Percent)
)),
"sub" => return Ok(BaselineShift(
- Length::new(-0.2, LengthUnit::Percent, LengthDir::Both)
+ LengthBoth::new(-0.2, LengthUnit::Percent)
)),
"super" => return Ok(BaselineShift(
- Length::new(0.4, LengthUnit::Percent, LengthDir::Both),
+ LengthBoth::new(0.4, LengthUnit::Percent),
)),
_ => (),
@@ -652,7 +652,7 @@ make_property!(
parser.reset(&parser_state);
- Ok(BaselineShift(Length::from_cssparser(parser, LengthDir::Both)?))
+ Ok(BaselineShift(LengthBoth::from_cssparser(parser)?))
}
}
}
@@ -836,7 +836,7 @@ make_property!(
make_property!(
ComputedValues,
FontSize,
- default: FontSizeSpec::Value(Length::parse_str("12.0", LengthDir::Both).unwrap()),
+ default: FontSizeSpec::Value(LengthBoth::parse_str("12.0", ()).unwrap()),
newtype_parse: FontSizeSpec,
parse_data_type: (),
property_impl: {
@@ -1060,10 +1060,10 @@ make_property!(
make_property!(
ComputedValues,
StrokeDashoffset,
- default: Length::default(),
+ default: LengthBoth::default(),
inherits_automatically: true,
- newtype_parse: Length,
- parse_data_type: LengthDir
+ newtype_parse: LengthBoth,
+ parse_data_type: ()
);
// https://www.w3.org/TR/SVG/painting.html#StrokeLinecapProperty
@@ -1116,10 +1116,10 @@ make_property!(
make_property!(
ComputedValues,
StrokeWidth,
- default: Length::parse_str("1.0", LengthDir::Both).unwrap(),
+ default: LengthBoth::parse_str("1.0", ()).unwrap(),
inherits_automatically: true,
- newtype_parse: Length,
- parse_data_type: LengthDir
+ newtype_parse: LengthBoth,
+ parse_data_type: ()
);
// https://www.w3.org/TR/SVG/text.html#TextAnchorProperty
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index 9ce4c9d6..85161788 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -276,19 +276,19 @@ impl NodeTrait for NodePoly {
}
pub struct NodeLine {
- x1: Cell<Length>,
- y1: Cell<Length>,
- x2: Cell<Length>,
- y2: Cell<Length>,
+ x1: Cell<LengthHorizontal>,
+ y1: Cell<LengthVertical>,
+ x2: Cell<LengthHorizontal>,
+ y2: Cell<LengthVertical>,
}
impl NodeLine {
pub fn new() -> NodeLine {
NodeLine {
- x1: Cell::new(Length::default()),
- y1: Cell::new(Length::default()),
- x2: Cell::new(Length::default()),
- y2: Cell::new(Length::default()),
+ x1: Cell::new(Default::default()),
+ y1: Cell::new(Default::default()),
+ x2: Cell::new(Default::default()),
+ y2: Cell::new(Default::default()),
}
}
}
@@ -297,10 +297,10 @@ impl NodeTrait for NodeLine {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X1 => self.x1.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y1 => self.y1.set(attr.parse(value, LengthDir::Vertical)?),
- Attribute::X2 => self.x2.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y2 => self.y2.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::X1 => self.x1.set(attr.parse(value, ())?),
+ Attribute::Y1 => self.y1.set(attr.parse(value, ())?),
+ Attribute::X2 => self.x2.set(attr.parse(value, ())?),
+ Attribute::Y2 => self.y2.set(attr.parse(value, ())?),
_ => (),
}
}
@@ -335,23 +335,23 @@ impl NodeTrait for NodeLine {
pub struct NodeRect {
// x, y, width, height
- x: Cell<Length>,
- y: Cell<Length>,
- w: Cell<Length>,
- h: Cell<Length>,
+ x: Cell<LengthHorizontal>,
+ y: Cell<LengthVertical>,
+ w: Cell<LengthHorizontal>,
+ h: Cell<LengthVertical>,
// Radiuses for rounded corners
- rx: Cell<Option<Length>>,
- ry: Cell<Option<Length>>,
+ rx: Cell<Option<LengthHorizontal>>,
+ ry: Cell<Option<LengthVertical>>,
}
impl NodeRect {
pub fn new() -> NodeRect {
NodeRect {
- x: Cell::new(Length::default()),
- y: Cell::new(Length::default()),
- w: Cell::new(Length::default()),
- h: Cell::new(Length::default()),
+ x: Cell::new(Default::default()),
+ y: Cell::new(Default::default()),
+ w: Cell::new(Default::default()),
+ h: Cell::new(Default::default()),
rx: Cell::new(None),
ry: Cell::new(None),
@@ -363,28 +363,24 @@ impl NodeTrait for NodeRect {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X => self.x.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y => self.y.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::X => self.x.set(attr.parse(value, ())?),
+ Attribute::Y => self.y.set(attr.parse(value, ())?),
Attribute::Width => self.w.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?),
Attribute::Height => self.h.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?),
Attribute::Rx => self.rx.set(
- attr.parse_and_validate(
- value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
- )
- .map(Some)?,
+ attr.parse_and_validate(value, (), LengthHorizontal::check_nonnegative)
+ .map(Some)?,
),
Attribute::Ry => self.ry.set(
- attr.parse_and_validate(value, LengthDir::Vertical, Length::check_nonnegative)
+ attr.parse_and_validate(value, (), LengthVertical::check_nonnegative)
.map(Some)?,
),
@@ -544,17 +540,17 @@ impl NodeTrait for NodeRect {
}
pub struct NodeCircle {
- cx: Cell<Length>,
- cy: Cell<Length>,
- r: Cell<Length>,
+ cx: Cell<LengthHorizontal>,
+ cy: Cell<LengthVertical>,
+ r: Cell<LengthBoth>,
}
impl NodeCircle {
pub fn new() -> NodeCircle {
NodeCircle {
- cx: Cell::new(Length::default()),
- cy: Cell::new(Length::default()),
- r: Cell::new(Length::default()),
+ cx: Cell::new(Default::default()),
+ cy: Cell::new(Default::default()),
+ r: Cell::new(Default::default()),
}
}
}
@@ -563,13 +559,12 @@ impl NodeTrait for NodeCircle {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::Cx => self.cx.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Cy => self.cy.set(attr.parse(value, LengthDir::Vertical)?),
- Attribute::R => self.r.set(attr.parse_and_validate(
- value,
- LengthDir::Both,
- Length::check_nonnegative,
- )?),
+ Attribute::Cx => self.cx.set(attr.parse(value, ())?),
+ Attribute::Cy => self.cy.set(attr.parse(value, ())?),
+ Attribute::R => {
+ self.r
+ .set(attr.parse_and_validate(value, (), LengthBoth::check_nonnegative)?)
+ }
_ => (),
}
@@ -598,19 +593,19 @@ impl NodeTrait for NodeCircle {
}
pub struct NodeEllipse {
- cx: Cell<Length>,
- cy: Cell<Length>,
- rx: Cell<Length>,
- ry: Cell<Length>,
+ cx: Cell<LengthHorizontal>,
+ cy: Cell<LengthVertical>,
+ rx: Cell<LengthHorizontal>,
+ ry: Cell<LengthVertical>,
}
impl NodeEllipse {
pub fn new() -> NodeEllipse {
NodeEllipse {
- cx: Cell::new(Length::default()),
- cy: Cell::new(Length::default()),
- rx: Cell::new(Length::default()),
- ry: Cell::new(Length::default()),
+ cx: Cell::new(Default::default()),
+ cy: Cell::new(Default::default()),
+ rx: Cell::new(Default::default()),
+ ry: Cell::new(Default::default()),
}
}
}
@@ -619,17 +614,17 @@ impl NodeTrait for NodeEllipse {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::Cx => self.cx.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Cy => self.cy.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::Cx => self.cx.set(attr.parse(value, ())?),
+ Attribute::Cy => self.cy.set(attr.parse(value, ())?),
Attribute::Rx => self.rx.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?),
Attribute::Ry => self.ry.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?),
_ => (),
diff --git a/rsvg_internals/src/stop.rs b/rsvg_internals/src/stop.rs
index 8b549ba7..158e2e50 100644
--- a/rsvg_internals/src/stop.rs
+++ b/rsvg_internals/src/stop.rs
@@ -24,8 +24,8 @@ impl NodeStop {
}
}
-fn validate_offset(length: Length) -> Result<Length, ValueErrorKind> {
- match length.unit {
+fn validate_offset(length: LengthBoth) -> Result<LengthBoth, ValueErrorKind> {
+ match length.unit() {
LengthUnit::Default | LengthUnit::Percent => Ok(length),
_ => Err(ValueErrorKind::Value(
"stop offset must be in default or percent units".to_string(),
@@ -39,8 +39,8 @@ impl NodeTrait for NodeStop {
match attr {
Attribute::Offset => {
self.offset.set(
- attr.parse_and_validate(value, LengthDir::Both, validate_offset)
- .map(|l| UnitInterval::clamp(l.length))?,
+ attr.parse_and_validate(value, (), validate_offset)
+ .map(|l| UnitInterval::clamp(l.length()))?,
);
}
_ => (),
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index f12cddcb..641be301 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -97,10 +97,10 @@ impl NodeTrait for NodeSwitch {
pub struct NodeSvg {
preserve_aspect_ratio: Cell<AspectRatio>,
- x: Cell<Length>,
- y: Cell<Length>,
- w: Cell<Length>,
- h: Cell<Length>,
+ x: Cell<LengthHorizontal>,
+ y: Cell<LengthVertical>,
+ w: Cell<LengthHorizontal>,
+ h: Cell<LengthVertical>,
vbox: Cell<Option<ViewBox>>,
pbag: RefCell<Option<OwnedPropertyBag>>,
}
@@ -109,10 +109,10 @@ impl NodeSvg {
pub fn new() -> NodeSvg {
NodeSvg {
preserve_aspect_ratio: Cell::new(AspectRatio::default()),
- x: Cell::new(Length::parse_str("0", LengthDir::Horizontal).unwrap()),
- y: Cell::new(Length::parse_str("0", LengthDir::Vertical).unwrap()),
- w: Cell::new(Length::parse_str("100%", LengthDir::Horizontal).unwrap()),
- h: Cell::new(Length::parse_str("100%", LengthDir::Vertical).unwrap()),
+ x: Cell::new(LengthHorizontal::parse_str("0", ()).unwrap()),
+ y: Cell::new(LengthVertical::parse_str("0", ()).unwrap()),
+ w: Cell::new(LengthHorizontal::parse_str("100%", ()).unwrap()),
+ h: Cell::new(LengthVertical::parse_str("100%", ()).unwrap()),
vbox: Cell::new(None),
pbag: RefCell::new(None),
}
@@ -131,7 +131,7 @@ impl NodeSvg {
w.hand_normalize(dpi.x(), vbox.width, 12.0).round() as i32,
h.hand_normalize(dpi.y(), vbox.height, 12.0).round() as i32,
)),
- (w, h, None) if w.unit != LengthUnit::Percent && h.unit != LengthUnit::Percent => {
+ (w, h, None) if w.unit() != LengthUnit::Percent && h.unit() != LengthUnit::Percent => {
Some((
w.hand_normalize(dpi.x(), 0.0, 12.0).round() as i32,
h.hand_normalize(dpi.y(), 0.0, 12.0).round() as i32,
@@ -160,26 +160,26 @@ impl NodeTrait for NodeSvg {
Attribute::X => {
if is_inner_svg {
- self.x.set(attr.parse(value, LengthDir::Horizontal)?);
+ self.x.set(attr.parse(value, ())?);
}
}
Attribute::Y => {
if is_inner_svg {
- self.y.set(attr.parse(value, LengthDir::Vertical)?);
+ self.y.set(attr.parse(value, ())?);
}
}
Attribute::Width => self.w.set(attr.parse_and_validate(
value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
+ (),
+ LengthHorizontal::check_nonnegative,
)?),
Attribute::Height => self.h.set(attr.parse_and_validate(
value,
- LengthDir::Vertical,
- Length::check_nonnegative,
+ (),
+ LengthVertical::check_nonnegative,
)?),
Attribute::ViewBox => self.vbox.set(attr.parse(value, ()).map(Some)?),
@@ -237,18 +237,18 @@ impl NodeTrait for NodeSvg {
pub struct NodeUse {
link: RefCell<Option<Fragment>>,
- x: Cell<Length>,
- y: Cell<Length>,
- w: Cell<Option<Length>>,
- h: Cell<Option<Length>>,
+ x: Cell<LengthHorizontal>,
+ y: Cell<LengthVertical>,
+ w: Cell<Option<LengthHorizontal>>,
+ h: Cell<Option<LengthVertical>>,
}
impl NodeUse {
pub fn new() -> NodeUse {
NodeUse {
link: RefCell::new(None),
- x: Cell::new(Length::default()),
- y: Cell::new(Length::default()),
+ x: Cell::new(Default::default()),
+ y: Cell::new(Default::default()),
w: Cell::new(None),
h: Cell::new(None),
}
@@ -264,19 +264,15 @@ impl NodeTrait for NodeUse {
Some(Fragment::parse(value).attribute(Attribute::XlinkHref)?)
}
- Attribute::X => self.x.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y => self.y.set(attr.parse(value, LengthDir::Vertical)?),
+ Attribute::X => self.x.set(attr.parse(value, ())?),
+ Attribute::Y => self.y.set(attr.parse(value, ())?),
Attribute::Width => self.w.set(
- attr.parse_and_validate(
- value,
- LengthDir::Horizontal,
- Length::check_nonnegative,
- )
- .map(Some)?,
+ attr.parse_and_validate(value, (), LengthHorizontal::check_nonnegative)
+ .map(Some)?,
),
Attribute::Height => self.h.set(
- attr.parse_and_validate(value, LengthDir::Vertical, Length::check_nonnegative)
+ attr.parse_and_validate(value, (), LengthVertical::check_nonnegative)
.map(Some)?,
),
@@ -338,12 +334,12 @@ impl NodeTrait for NodeUse {
let nw = self
.w
.get()
- .unwrap_or_else(|| Length::parse_str("100%", LengthDir::Horizontal).unwrap())
+ .unwrap_or_else(|| LengthHorizontal::parse_str("100%", ()).unwrap())
.normalize(values, ¶ms);
let nh = self
.h
.get()
- .unwrap_or_else(|| Length::parse_str("100%", LengthDir::Vertical).unwrap())
+ .unwrap_or_else(|| LengthVertical::parse_str("100%", ()).unwrap())
.normalize(values, ¶ms);
// width or height set to 0 disables rendering of the element
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index 002c122c..ab729916 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -45,15 +45,15 @@ use space::{xml_space_normalize, NormalizeDefault, XmlSpaceNormalize};
/// [text chunk]: https://www.w3.org/TR/SVG11/text.html#TextLayoutIntroduction
struct Chunk {
values: ComputedValues,
- x: Option<Length>,
- y: Option<Length>,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
spans: Vec<Span>,
}
struct MeasuredChunk {
values: ComputedValues,
- x: Option<Length>,
- y: Option<Length>,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
advance: (f64, f64),
spans: Vec<MeasuredSpan>,
}
@@ -67,8 +67,8 @@ struct PositionedChunk {
struct Span {
values: ComputedValues,
text: String,
- dx: Option<Length>,
- dy: Option<Length>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
_depth: usize,
}
@@ -77,8 +77,8 @@ struct MeasuredSpan {
layout: pango::Layout,
_layout_size: (f64, f64),
advance: (f64, f64),
- dx: Option<Length>,
- dy: Option<Length>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
}
struct PositionedSpan {
@@ -89,7 +89,11 @@ struct PositionedSpan {
}
impl Chunk {
- fn new(values: &ComputedValues, x: Option<Length>, y: Option<Length>) -> Chunk {
+ fn new(
+ values: &ComputedValues,
+ x: Option<LengthHorizontal>,
+ y: Option<LengthVertical>,
+ ) -> Chunk {
Chunk {
values: values.clone(),
x,
@@ -182,8 +186,8 @@ impl Span {
fn new(
text: &str,
values: ComputedValues,
- dx: Option<Length>,
- dy: Option<Length>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
depth: usize,
) -> Span {
Span {
@@ -415,8 +419,8 @@ fn children_to_chunks(
node: &RsvgNode,
cascaded: &CascadedValues<'_>,
draw_ctx: &mut DrawingCtx,
- dx: Option<Length>,
- dy: Option<Length>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
depth: usize,
) {
for child in node.children() {
@@ -507,8 +511,8 @@ impl NodeChars {
&self,
node: &RsvgNode,
values: &ComputedValues,
- dx: Option<Length>,
- dy: Option<Length>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
depth: usize,
) -> Span {
self.ensure_normalized_string(node, values);
@@ -527,8 +531,8 @@ impl NodeChars {
node: &RsvgNode,
values: &ComputedValues,
chunks: &mut Vec<Chunk>,
- dx: Option<Length>,
- dy: Option<Length>,
+ dx: Option<LengthHorizontal>,
+ dy: Option<LengthVertical>,
depth: usize,
) {
let span = self.make_span(&node, values, dx, dy, depth);
@@ -547,17 +551,17 @@ impl NodeTrait for NodeChars {
}
pub struct NodeText {
- x: Cell<Length>,
- y: Cell<Length>,
- dx: Cell<Option<Length>>,
- dy: Cell<Option<Length>>,
+ x: Cell<LengthHorizontal>,
+ y: Cell<LengthVertical>,
+ dx: Cell<Option<LengthHorizontal>>,
+ dy: Cell<Option<LengthVertical>>,
}
impl NodeText {
pub fn new() -> NodeText {
NodeText {
- x: Cell::new(Length::default()),
- y: Cell::new(Length::default()),
+ x: Cell::new(Default::default()),
+ y: Cell::new(Default::default()),
dx: Cell::new(None),
dy: Cell::new(None),
}
@@ -587,14 +591,10 @@ impl NodeTrait for NodeText {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X => self.x.set(attr.parse(value, LengthDir::Horizontal)?),
- Attribute::Y => self.y.set(attr.parse(value, LengthDir::Vertical)?),
- Attribute::Dx => self
- .dx
- .set(attr.parse(value, LengthDir::Horizontal).map(Some)?),
- Attribute::Dy => self
- .dy
- .set(attr.parse(value, LengthDir::Vertical).map(Some)?),
+ Attribute::X => self.x.set(attr.parse(value, ())?),
+ Attribute::Y => self.y.set(attr.parse(value, ())?),
+ Attribute::Dx => self.dx.set(attr.parse(value, ()).map(Some)?),
+ Attribute::Dy => self.dy.set(attr.parse(value, ()).map(Some)?),
_ => (),
}
}
@@ -624,10 +624,12 @@ impl NodeTrait for NodeText {
let mut positioned_chunks = Vec::new();
for chunk in &measured_chunks {
- let normalize = |l: Length| l.normalize(&chunk.values, ¶ms);
-
- let chunk_x = chunk.x.map_or(x, normalize);
- let chunk_y = chunk.y.map_or(y, normalize);
+ let chunk_x = chunk
+ .x
+ .map_or_else(|| x, |l| l.normalize(&chunk.values, ¶ms));
+ let chunk_y = chunk
+ .y
+ .map_or_else(|| y, |l| l.normalize(&chunk.values, ¶ms));
let positioned = PositionedChunk::from_measured(&chunk, draw_ctx, chunk_x, chunk_y);
@@ -725,10 +727,10 @@ impl NodeTrait for NodeTRef {
}
pub struct NodeTSpan {
- x: Cell<Option<Length>>,
- y: Cell<Option<Length>>,
- dx: Cell<Option<Length>>,
- dy: Cell<Option<Length>>,
+ x: Cell<Option<LengthHorizontal>>,
+ y: Cell<Option<LengthVertical>>,
+ dx: Cell<Option<LengthHorizontal>>,
+ dy: Cell<Option<LengthVertical>>,
}
impl NodeTSpan {
@@ -768,18 +770,10 @@ impl NodeTrait for NodeTSpan {
fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
for (attr, value) in pbag.iter() {
match attr {
- Attribute::X => self
- .x
- .set(attr.parse(value, LengthDir::Horizontal).map(Some)?),
- Attribute::Y => self
- .y
- .set(attr.parse(value, LengthDir::Vertical).map(Some)?),
- Attribute::Dx => self
- .dx
- .set(attr.parse(value, LengthDir::Horizontal).map(Some)?),
- Attribute::Dy => self
- .dy
- .set(attr.parse(value, LengthDir::Vertical).map(Some)?),
+ Attribute::X => self.x.set(attr.parse(value, ()).map(Some)?),
+ Attribute::Y => self.y.set(attr.parse(value, ()).map(Some)?),
+ Attribute::Dx => self.dx.set(attr.parse(value, ()).map(Some)?),
+ Attribute::Dy => self.dy.set(attr.parse(value, ()).map(Some)?),
_ => (),
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]