diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index b0549cde28a..4ecbbd98cc2 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1424,10 +1424,10 @@ impl FragmentDisplayListBuilding for Fragment { details: BorderDetails::Image(ImageBorder { image: webrender_image, fill: border_style_struct.border_image_slice.fill, - slice: SideOffsets2D::new(corners.top.resolve(webrender_image.height), - corners.right.resolve(webrender_image.width), - corners.bottom.resolve(webrender_image.height), - corners.left.resolve(webrender_image.width)), + slice: SideOffsets2D::new(corners.0.resolve(webrender_image.height), + corners.1.resolve(webrender_image.width), + corners.2.resolve(webrender_image.height), + corners.3.resolve(webrender_image.width)), // TODO(gw): Support border-image-outset outset: SideOffsets2D::zero(), repeat_horizontal: convert_repeat_mode(border_style_struct.border_image_repeat.0), diff --git a/components/layout/model.rs b/components/layout/model.rs index a762c1d59c8..97fb5cbc43e 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -14,9 +14,8 @@ use std::fmt; use style::computed_values::transform::ComputedMatrix; use style::logical_geometry::{LogicalMargin, WritingMode}; use style::properties::ServoComputedValues; -use style::values::computed::{BorderRadiusSize, LengthOrPercentageOrAuto}; +use style::values::computed::{BorderCornerRadius, LengthOrPercentageOrAuto}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrNone}; -use style::values::generics; /// A collapsible margin. See CSS 2.1 ยง 8.3.1. #[derive(Copy, Clone, Debug)] @@ -472,13 +471,12 @@ pub fn style_length(style_length: LengthOrPercentageOrAuto, /// /// [1]: https://drafts.csswg.org/css-backgrounds-3/#border-radius pub fn specified_border_radius( - radius: BorderRadiusSize, + radius: BorderCornerRadius, containing_size: Size2D) -> Size2D { - let generics::BorderRadiusSize(size) = radius; - let w = size.width.to_used_value(containing_size.width); - let h = size.height.to_used_value(containing_size.height); + let w = radius.0.width.to_used_value(containing_size.width); + let h = radius.0.height.to_used_value(containing_size.height); Size2D::new(w, h) } diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 392ec9a1012..9f222690404 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -362,13 +362,14 @@ pub mod basic_shape { use gecko_bindings::structs::StyleGeometryBox; use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue}; use std::borrow::Borrow; - use values::computed::{BorderRadiusSize, LengthOrPercentage}; - use values::computed::basic_shape::{BasicShape, BorderRadius, ShapeRadius}; + use values::computed::basic_shape::{BasicShape, ShapeRadius}; + use values::computed::border::{BorderCornerRadius, BorderRadius}; + use values::computed::length::LengthOrPercentage; use values::computed::position; - use values::generics::BorderRadiusSize as GenericBorderRadiusSize; use values::generics::basic_shape::{BasicShape as GenericBasicShape, InsetRect, Polygon}; use values::generics::basic_shape::{Circle, Ellipse, FillRule}; use values::generics::basic_shape::{GeometryBox, ShapeBox}; + use values::generics::border::BorderRadius as GenericBorderRadius; use values::generics::rect::Rect; // using Borrow so that we can have a non-moving .into() @@ -435,14 +436,14 @@ pub mod basic_shape { fn from(other: T) -> Self { let other = other.borrow(); let get_corner = |index| { - GenericBorderRadiusSize::new( + BorderCornerRadius::new( LengthOrPercentage::from_gecko_style_coord(&other.data_at(index)) .expect(" should be a length, percentage, or calc value"), LengthOrPercentage::from_gecko_style_coord(&other.data_at(index + 1)) .expect(" should be a length, percentage, or calc value")) }; - BorderRadius { + GenericBorderRadius { top_left: get_corner(0), top_right: get_corner(2), bottom_right: get_corner(4), @@ -456,7 +457,7 @@ pub mod basic_shape { impl BorderRadius { /// Set this `BorderRadius` into a given `nsStyleCoord`. pub fn set_corners(&self, other: &mut nsStyleCorners) { - let mut set_corner = |field: &BorderRadiusSize, index| { + let mut set_corner = |field: &BorderCornerRadius, index| { field.0.width.to_gecko_style_coord(&mut other.data_at_mut(index)); field.0.height.to_gecko_style_coord(&mut other.data_at_mut(index + 1)); }; diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index eca4ba619e7..55d7cbe2dd9 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -558,14 +558,14 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { % if need_clone: #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use values::generics::BorderRadiusSize; + use values::computed::border::BorderCornerRadius; let width = GeckoStyleCoordConvertible::from_gecko_style_coord( &self.gecko.${gecko_ffi_name}.data_at(${x_index})) .expect("Failed to clone ${ident}"); let height = GeckoStyleCoordConvertible::from_gecko_style_coord( &self.gecko.${gecko_ffi_name}.data_at(${y_index})) .expect("Failed to clone ${ident}"); - BorderRadiusSize::new(width, height) + BorderCornerRadius::new(width, height) } % endif @@ -964,7 +964,7 @@ fn static_assert() { pub fn set_border_image_outset(&mut self, v: longhands::border_image_outset::computed_value::T) { % for side in SIDES: - v.${side.ident}.to_gecko_style_coord(&mut self.gecko.mBorderImageOutset.data_at_mut(${side.index})); + v.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageOutset.data_at_mut(${side.index})); % endfor } @@ -1001,7 +1001,7 @@ fn static_assert() { use values::generics::border::BorderImageWidthSide; % for side in SIDES: - match v.${side.ident} { + match v.${side.index} { BorderImageWidthSide::Auto => { self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::Auto) }, @@ -1026,7 +1026,7 @@ fn static_assert() { use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, NS_STYLE_BORDER_IMAGE_SLICE_FILL}; % for side in SIDES: - v.offsets.${side.ident}.to_gecko_style_coord(&mut self.gecko.mBorderImageSlice.data_at_mut(${side.index})); + v.offsets.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageSlice.data_at_mut(${side.index})); % endfor let fill = if v.fill { @@ -3967,13 +3967,13 @@ fn static_assert() { // the garbage data without // attempting to clean up. shape.mCoordinates[0].leaky_set_null(); - inset.rect.top.to_gecko_style_coord(&mut shape.mCoordinates[0]); + inset.rect.0.to_gecko_style_coord(&mut shape.mCoordinates[0]); shape.mCoordinates[1].leaky_set_null(); - inset.rect.right.to_gecko_style_coord(&mut shape.mCoordinates[1]); + inset.rect.1.to_gecko_style_coord(&mut shape.mCoordinates[1]); shape.mCoordinates[2].leaky_set_null(); - inset.rect.bottom.to_gecko_style_coord(&mut shape.mCoordinates[2]); + inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]); shape.mCoordinates[3].leaky_set_null(); - inset.rect.left.to_gecko_style_coord(&mut shape.mCoordinates[3]); + inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]); set_corners_from_radius(inset.round, &mut shape.mRadius); } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index e601f27c01e..f815dc6cc49 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -901,8 +901,8 @@ % endif })?; Ok(expanded! { - % for side in ["top", "right", "bottom", "left"]: - ${to_rust_ident(sub_property_pattern % side)}: rect.${side}, + % for index, side in enumerate(["top", "right", "bottom", "left"]): + ${to_rust_ident(sub_property_pattern % side)}: rect.${index}, % endfor }) } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 7c09b62c8af..267c33acf0a 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -37,12 +37,13 @@ use std::fmt; use style_traits::ToCss; use super::ComputedValues; use values::CSSFloat; -use values::{Auto, Either, generics}; +use values::{Auto, Either}; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; -use values::computed::{BorderRadiusSize, ClipRect}; +use values::computed::{BorderCornerRadius, ClipRect}; use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage}; use values::computed::{MaxLength, MozLength}; use values::computed::ToComputedValue; +use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::position as generic_position; @@ -874,10 +875,10 @@ impl Animatable for Point2D { } } -impl Animatable for BorderRadiusSize { +impl Animatable for BorderCornerRadius { #[inline] fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { - self.0.add_weighted(&other.0, self_portion, other_portion).map(generics::BorderRadiusSize) + self.0.add_weighted(&other.0, self_portion, other_portion).map(GenericBorderCornerRadius) } #[inline] diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index eb876c40d97..e2ad6c2c902 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -46,8 +46,8 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style', // FIXME(#4126): when gfx supports painting it, make this Size2D % for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]: - ${helpers.predefined_type("border-" + corner + "-radius", "BorderRadiusSize", - "computed::BorderRadiusSize::zero()", + ${helpers.predefined_type("border-" + corner + "-radius", "BorderCornerRadius", + "computed::LengthOrPercentage::zero().into()", "parse", extra_prefixes="webkit", spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner, boxed=True, diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index 3d0a22f08d4..e3896df6671 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -108,9 +108,9 @@ ${helpers.predefined_type("outline-color", "CSSColor", "computed::CSSColor::Curr // The -moz-outline-radius-* properties are non-standard and not on a standards track. // TODO: Should they animate? % for corner in ["topleft", "topright", "bottomright", "bottomleft"]: - ${helpers.predefined_type("-moz-outline-radius-" + corner, "BorderRadiusSize", - "computed::BorderRadiusSize::zero()", - "parse", products="gecko", + ${helpers.predefined_type("-moz-outline-radius-" + corner, "BorderCornerRadius", + "computed::LengthOrPercentage::zero().into()", + products="gecko", boxed=True, animation_value_type="none", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)")} diff --git a/components/style/properties/shorthand/border.mako.rs b/components/style/properties/shorthand/border.mako.rs index 67e807b824b..e2576891b06 100644 --- a/components/style/properties/shorthand/border.mako.rs +++ b/components/style/properties/shorthand/border.mako.rs @@ -25,20 +25,19 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style", BorderWidth::parse_quirky(context, i, AllowQuirks::Yes) })?; Ok(expanded! { - % for side in PHYSICAL_SIDES: - ${to_rust_ident('border-%s-width' % side)}: rect.${side}, - % endfor + border_top_width: rect.0, + border_right_width: rect.1, + border_bottom_width: rect.2, + border_left_width: rect.3, }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - let rect = Rect { - % for side in PHYSICAL_SIDES: - ${side}: &self.border_${side}_width, - % endfor - }; - rect.to_css(dest) + % for side in PHYSICAL_SIDES: + let ${side} = &self.border_${side}_width; + % endfor + Rect::new(top, right, bottom, left).to_css(dest) } } @@ -206,8 +205,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) 'border-%s-radius' % (corner) for corner in ['top-left', 'top-right', 'bottom-right', 'bottom-left'] )}" extra_prefixes="webkit" spec="https://drafts.csswg.org/css-backgrounds/#border-radius"> - use values::generics::serialize_radius_values; - use values::specified::basic_shape::BorderRadius; + use values::generics::rect::Rect; + use values::specified::border::BorderRadius; use parser::Parse; pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result { @@ -222,11 +221,17 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - serialize_radius_values(dest, - &self.border_top_left_radius.0, - &self.border_top_right_radius.0, - &self.border_bottom_right_radius.0, - &self.border_bottom_left_radius.0) + let LonghandsToSerialize { + border_top_left_radius: ref tl, + border_top_right_radius: ref tr, + border_bottom_right_radius: ref br, + border_bottom_left_radius: ref bl, + } = *self; + + let widths = Rect::new(&tl.0.width, &tr.0.width, &br.0.width, &bl.0.width); + let heights = Rect::new(&tl.0.height, &tr.0.height, &br.0.height, &bl.0.height); + + BorderRadius::serialize_rects(widths, heights, dest) } } diff --git a/components/style/properties/shorthand/outline.mako.rs b/components/style/properties/shorthand/outline.mako.rs index c609bd8a463..8a1ab5900da 100644 --- a/components/style/properties/shorthand/outline.mako.rs +++ b/components/style/properties/shorthand/outline.mako.rs @@ -67,28 +67,33 @@ '-moz-outline-radius-%s' % corner for corner in ['topleft', 'topright', 'bottomright', 'bottomleft'] )}" products="gecko" spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)"> - use properties::shorthands; - use values::generics::serialize_radius_values; + use values::generics::rect::Rect; + use values::specified::border::BorderRadius; + use parser::Parse; pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result { - // Re-use border-radius parsing. - shorthands::border_radius::parse_value(context, input).map(|longhands| { - expanded! { - % for corner in ["top_left", "top_right", "bottom_right", "bottom_left"]: - _moz_outline_radius_${corner.replace("_", "")}: longhands.border_${corner}_radius, - % endfor - } + let radii = try!(BorderRadius::parse(context, input)); + Ok(expanded! { + _moz_outline_radius_topleft: radii.top_left, + _moz_outline_radius_topright: radii.top_right, + _moz_outline_radius_bottomright: radii.bottom_right, + _moz_outline_radius_bottomleft: radii.bottom_left, }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - serialize_radius_values(dest, - &self._moz_outline_radius_topleft.0, - &self._moz_outline_radius_topright.0, - &self._moz_outline_radius_bottomright.0, - &self._moz_outline_radius_bottomleft.0, - ) + let LonghandsToSerialize { + _moz_outline_radius_topleft: ref tl, + _moz_outline_radius_topright: ref tr, + _moz_outline_radius_bottomright: ref br, + _moz_outline_radius_bottomleft: ref bl, + } = *self; + + let widths = Rect::new(&tl.0.width, &tr.0.width, &br.0.width, &bl.0.width); + let heights = Rect::new(&tl.0.height, &tr.0.height, &br.0.height, &bl.0.height); + + BorderRadius::serialize_rects(widths, heights, dest) } } diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs index 1e9ca6c5ff8..f46edcfae0a 100644 --- a/components/style/values/computed/basic_shape.rs +++ b/components/style/values/computed/basic_shape.rs @@ -10,7 +10,7 @@ use std::fmt; use style_traits::ToCss; use values::computed::LengthOrPercentage; -use values::generics::basic_shape::{BasicShape as GenericBasicShape, BorderRadius as GenericBorderRadius}; +use values::generics::basic_shape::{BasicShape as GenericBasicShape}; use values::generics::basic_shape::{Circle as GenericCircle, ClippingShape as GenericClippingShape}; use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape}; use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius}; @@ -27,9 +27,6 @@ pub type BasicShape = GenericBasicShape; -/// The computed value of `BorderRadius` -pub type BorderRadius = GenericBorderRadius; - /// A computed circle. pub type Circle = GenericCircle; diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs index e247f9a9cf4..00408b302eb 100644 --- a/components/style/values/computed/border.rs +++ b/components/style/values/computed/border.rs @@ -6,8 +6,10 @@ use values::computed::{Number, NumberOrPercentage}; use values::computed::length::LengthOrPercentage; +use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::border::BorderImageSlice as GenericBorderImageSlice; use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide; +use values::generics::border::BorderRadius as GenericBorderRadius; use values::generics::rect::Rect; /// A computed value for the `border-image-width` property. @@ -19,6 +21,12 @@ pub type BorderImageWidthSide = GenericBorderImageWidthSide; +/// A computed value for the `border-radius` property. +pub type BorderRadius = GenericBorderRadius; + +/// A computed value for the `border-*-radius` longhand properties. +pub type BorderCornerRadius = GenericBorderCornerRadius; + impl BorderImageWidthSide { /// Returns `1`. #[inline] diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 6085e00c39b..1a295217438 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -17,7 +17,6 @@ use std::f32::consts::PI; use std::fmt; use style_traits::ToCss; use super::{CSSFloat, CSSInteger, RGBA}; -use super::generics::BorderRadiusSize as GenericBorderRadiusSize; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::TrackList as GenericTrackList; use super::specified; @@ -26,6 +25,7 @@ pub use app_units::Au; pub use cssparser::Color as CSSColor; pub use self::background::BackgroundSize; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageWidthSide}; +pub use self::border::{BorderRadius, BorderCornerRadius}; pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect}; pub use self::rect::LengthOrNumberRect; pub use super::{Auto, Either, None_}; @@ -462,20 +462,6 @@ impl ComputedValueAsSpecified for specified::AlignJustifyContent {} impl ComputedValueAsSpecified for specified::AlignJustifySelf {} impl ComputedValueAsSpecified for specified::BorderStyle {} -/// The computed value of `BorderRadiusSize` -pub type BorderRadiusSize = GenericBorderRadiusSize; - -impl BorderRadiusSize { - /// Create a null value. - #[inline] - pub fn zero() -> BorderRadiusSize { - let zero = LengthOrPercentage::zero(); - GenericBorderRadiusSize(Size2D::new(zero.clone(), zero)) - } -} - -impl Copy for BorderRadiusSize {} - #[derive(Debug, PartialEq, Clone, Copy)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 688c9616d01..a507d15a4ec 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -5,11 +5,10 @@ //! CSS handling for the [`basic-shape`](https://drafts.csswg.org/css-shapes/#typedef-basic-shape) //! types that are generic over their `ToCss` implementations. -use euclid::size::Size2D; use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; use values::computed::ComputedValueAsSpecified; -use values::generics::BorderRadiusSize; +use values::generics::border::BorderRadius; use values::generics::position::Position; use values::generics::rect::Rect; use values::specified::url::SpecifiedUrl; @@ -71,22 +70,6 @@ pub struct InsetRect { pub round: Option>, } -/// A generic type used for `border-radius`, `outline-radius` and `inset()` values. -/// -/// https://drafts.csswg.org/css-backgrounds-3/#border-radius -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Debug, PartialEq, ToComputedValue)] -pub struct BorderRadius { - /// The top left radius. - pub top_left: BorderRadiusSize, - /// The top right radius. - pub top_right: BorderRadiusSize, - /// The bottom right radius. - pub bottom_right: BorderRadiusSize, - /// The bottom left radius. - pub bottom_left: BorderRadiusSize, -} - /// https://drafts.csswg.org/css-shapes/#funcdef-circle #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -201,33 +184,6 @@ impl ToCss for InsetRect } } -impl ToCss for BorderRadius { - #[inline] - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - serialize_radius_values(dest, &self.top_left.0, &self.top_right.0, - &self.bottom_right.0, &self.bottom_left.0) - } -} - -/// Serialization helper for types of longhands like `border-radius` and `outline-radius` -pub fn serialize_radius_values(dest: &mut W, top_left: &Size2D, - top_right: &Size2D, bottom_right: &Size2D, - bottom_left: &Size2D) -> fmt::Result - where L: ToCss + PartialEq, W: fmt::Write -{ - Rect::new(&top_left.width, &top_right.width, &bottom_right.width, &bottom_left.width).to_css(dest)?; - if - top_left.width != top_left.height || - top_right.width != top_right.height || - bottom_right.width != bottom_right.height || - bottom_left.width != bottom_left.height - { - dest.write_str(" / ")?; - Rect::new(&top_left.height, &top_right.height, &bottom_right.height, &bottom_left.height).to_css(dest)?; - } - Ok(()) -} - impl Default for ShapeRadius { #[inline] fn default() -> Self { ShapeRadius::ClosestSide } diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index 70e5812b401..6bfc5234b3d 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -4,6 +4,7 @@ //! Generic types for CSS values related to borders. +use euclid::Size2D; use std::fmt; use style_traits::ToCss; use values::generics::rect::Rect; @@ -30,6 +31,27 @@ pub struct BorderImageSlice { pub fill: bool, } +/// A generic value for `border-radius`, `outline-radius` and `inset()`. +/// +/// https://drafts.csswg.org/css-backgrounds-3/#border-radius +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +pub struct BorderRadius { + /// The top left radius. + pub top_left: BorderCornerRadius, + /// The top right radius. + pub top_right: BorderCornerRadius, + /// The bottom right radius. + pub bottom_right: BorderCornerRadius, + /// The bottom left radius. + pub bottom_left: BorderCornerRadius, +} + +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +/// A generic value for `border-*-radius` longhand properties. +pub struct BorderCornerRadius(pub Size2D); + impl ToCss for BorderImageWidthSide where L: ToCss, N: ToCss, { @@ -69,3 +91,81 @@ impl ToCss for BorderImageSlice Ok(()) } } + +impl BorderRadius { + /// Returns a new `BorderRadius`. + #[inline] + pub fn new(tl: BorderCornerRadius, + tr: BorderCornerRadius, + br: BorderCornerRadius, + bl: BorderCornerRadius) + -> Self { + BorderRadius { + top_left: tl, + top_right: tr, + bottom_right: br, + bottom_left: bl, + } + } +} + +impl BorderRadius + where L: PartialEq + ToCss +{ + /// Serialises two given rects following the syntax of the `border-radius`` + /// property. + pub fn serialize_rects(widths: Rect<&L>, heights: Rect<&L>, dest: &mut W) -> fmt::Result + where W: fmt::Write, + { + widths.to_css(dest)?; + if widths.0 != heights.0 || widths.1 != heights.1 || widths.2 != heights.2 || widths.3 != heights.3 { + dest.write_str(" / ")?; + heights.to_css(dest)?; + } + Ok(()) + } +} + +impl ToCss for BorderRadius + where L: PartialEq + ToCss +{ + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let BorderRadius { + top_left: ref tl, + top_right: ref tr, + bottom_right: ref br, + bottom_left: ref bl, + } = *self; + + let widths = Rect::new(&tl.0.width, &tr.0.width, &br.0.width, &bl.0.width); + let heights = Rect::new(&tl.0.height, &tr.0.height, &br.0.height, &bl.0.height); + + Self::serialize_rects(widths, heights, dest) + } +} + +impl BorderCornerRadius { + #[inline] + /// Create a new `BorderCornerRadius` for an area of given width and height. + pub fn new(width: L, height: L) -> BorderCornerRadius { + BorderCornerRadius(Size2D::new(width, height)) + } +} + +impl From for BorderCornerRadius { + fn from(radius: L) -> Self { + Self::new(radius.clone(), radius) + } +} + +impl ToCss for BorderCornerRadius + where L: ToCss, +{ + fn to_css(&self, dest: &mut W) -> fmt::Result + where W: fmt::Write + { + self.0.width.to_css(dest)?; + dest.write_str(" ")?; + self.0.height.to_css(dest) + } +} diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 0631038d67a..1d25f3b3845 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -7,14 +7,11 @@ use counter_style::{Symbols, parse_counter_style_name}; use cssparser::Parser; -use euclid::size::Size2D; use parser::{Parse, ParserContext}; use std::fmt; -use style_traits::{HasViewportPercentage, OneOrMoreCommaSeparated, ToCss}; +use style_traits::{OneOrMoreCommaSeparated, ToCss}; use super::CustomIdent; -pub use self::basic_shape::serialize_radius_values; - pub mod background; pub mod basic_shape; pub mod border; @@ -23,47 +20,6 @@ pub mod image; pub mod position; pub mod rect; -#[derive(Clone, Debug, PartialEq, ToComputedValue)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -/// A type for representing CSS `width` and `height` values. -pub struct BorderRadiusSize(pub Size2D); - -impl HasViewportPercentage for BorderRadiusSize { - #[inline] - fn has_viewport_percentage(&self) -> bool { false } -} - -impl From for BorderRadiusSize { - fn from(other: L) -> Self { - Self::new(other.clone(), other) - } -} - -impl BorderRadiusSize { - #[inline] - /// Create a new `BorderRadiusSize` for an area of given width and height. - pub fn new(width: L, height: L) -> BorderRadiusSize { - BorderRadiusSize(Size2D::new(width, height)) - } -} - -impl BorderRadiusSize { - #[inline] - /// Create a new `BorderRadiusSize` for a circle of given radius. - pub fn circle(radius: L) -> BorderRadiusSize { - BorderRadiusSize(Size2D::new(radius.clone(), radius)) - } -} - -impl ToCss for BorderRadiusSize { - #[inline] - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.0.width.to_css(dest)?; - dest.write_str(" ")?; - self.0.height.to_css(dest) - } -} - // https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type define_css_keyword_enum! { SymbolsType: "cyclic" => Cyclic, diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index 767ce2223e4..a0a63b7144e 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -9,29 +9,16 @@ use parser::{Parse, ParserContext}; use std::fmt; use style_traits::ToCss; -/// A CSS value made of four sides: top, right, bottom, and left. +/// A CSS value made of four components, where its `ToCss` impl will try to +/// serialize as few components as possible, like for example in `border-width`. #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub struct Rect { - /// Top - pub top: T, - /// Right. - pub right: T, - /// Bottom. - pub bottom: T, - /// Left. - pub left: T, -} +pub struct Rect(pub T, pub T, pub T, pub T); impl Rect { /// Returns a new `Rect` value. - pub fn new(top: T, right: T, bottom: T, left: T) -> Self { - Rect { - top: top, - right: right, - bottom: bottom, - left: left, - } + pub fn new(first: T, second: T, third: T, fourth: T) -> Self { + Rect(first, second, third, fourth) } } @@ -46,21 +33,21 @@ impl Rect -> Result where Parse: Fn(&ParserContext, &mut Parser) -> Result { - let top = parse(context, input)?; - let right = if let Ok(right) = input.try(|i| parse(context, i)) { right } else { - // - return Ok(Self::new(top.clone(), top.clone(), top.clone(), top)); + let first = parse(context, input)?; + let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else { + // + return Ok(Self::new(first.clone(), first.clone(), first.clone(), first)); }; - let bottom = if let Ok(bottom) = input.try(|i| parse(context, i)) { bottom } else { - // - return Ok(Self::new(top.clone(), right.clone(), top, right)); + let third = if let Ok(third) = input.try(|i| parse(context, i)) { third } else { + // + return Ok(Self::new(first.clone(), second.clone(), first, second)); }; - let left = if let Ok(left) = input.try(|i| parse(context, i)) { left } else { - // - return Ok(Self::new(top, right.clone(), bottom, right)); + let fourth = if let Ok(fourth) = input.try(|i| parse(context, i)) { fourth } else { + // + return Ok(Self::new(first, second.clone(), third, second)); }; - // - Ok(Self::new(top, right, bottom, left)) + // + Ok(Self::new(first, second, third, fourth)) } } @@ -88,23 +75,23 @@ impl ToCss for Rect fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write, { - self.top.to_css(dest)?; - let same_vertical = self.top == self.bottom; - let same_horizontal = self.right == self.left; - if same_vertical && same_horizontal && self.top == self.right { + self.0.to_css(dest)?; + let same_vertical = self.0 == self.2; + let same_horizontal = self.1 == self.3; + if same_vertical && same_horizontal && self.0 == self.1 { return Ok(()); } dest.write_str(" ")?; - self.right.to_css(dest)?; + self.1.to_css(dest)?; if same_vertical && same_horizontal { return Ok(()); } dest.write_str(" ")?; - self.bottom.to_css(dest)?; + self.2.to_css(dest)?; if same_horizontal { return Ok(()); } dest.write_str(" ")?; - self.left.to_css(dest) + self.3.to_css(dest) } } diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 5125ff9febd..237db2cd2a1 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -12,8 +12,7 @@ use parser::{Parse, ParserContext}; use std::borrow::Cow; use std::fmt; use style_traits::ToCss; -use values::generics::BorderRadiusSize; -use values::generics::basic_shape::{BorderRadius as GenericBorderRadius, Circle as GenericCircle}; +use values::generics::basic_shape::{Circle as GenericCircle}; use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse}; use values::generics::basic_shape::{FillRule, BasicShape as GenericBasicShape}; use values::generics::basic_shape::{FloatAreaShape as GenericFloatAreaShape, InsetRect as GenericInsetRect}; @@ -21,6 +20,7 @@ use values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource}; use values::generics::basic_shape::{Polygon as GenericPolygon, ShapeRadius as GenericShapeRadius}; use values::generics::rect::Rect; use values::specified::{LengthOrPercentage, Percentage}; +use values::specified::border::BorderRadius; use values::specified::position::{HorizontalPosition, Position, PositionComponent, Side, VerticalPosition}; use values::specified::url::SpecifiedUrl; @@ -36,9 +36,6 @@ pub type BasicShape = GenericBasicShape; -/// The specified value of `BorderRadius` -pub type BorderRadius = GenericBorderRadius; - /// A specified circle. pub type Circle = GenericCircle; @@ -140,49 +137,6 @@ impl InsetRect { } } -impl Parse for BorderRadius { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - let mut widths = parse_one_set_of_border_values(context, input)?; - let mut heights = if input.try(|input| input.expect_delim('/')).is_ok() { - parse_one_set_of_border_values(context, input)? - } else { - [widths[0].clone(), - widths[1].clone(), - widths[2].clone(), - widths[3].clone()] - }; - - Ok(BorderRadius { - top_left: BorderRadiusSize::new(widths[0].take(), heights[0].take()), - top_right: BorderRadiusSize::new(widths[1].take(), heights[1].take()), - bottom_right: BorderRadiusSize::new(widths[2].take(), heights[2].take()), - bottom_left: BorderRadiusSize::new(widths[3].take(), heights[3].take()), - }) - } -} - -fn parse_one_set_of_border_values(context: &ParserContext, mut input: &mut Parser) - -> Result<[LengthOrPercentage; 4], ()> { - let a = try!(LengthOrPercentage::parse_non_negative(context, input)); - let b = if let Ok(b) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { - b - } else { - return Ok([a.clone(), a.clone(), a.clone(), a]) - }; - - let c = if let Ok(c) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { - c - } else { - return Ok([a.clone(), b.clone(), a, b]) - }; - - if let Ok(d) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { - Ok([a, b, c, d]) - } else { - Ok([a, b.clone(), c, b]) - } -} - impl Parse for Circle { fn parse(context: &ParserContext, input: &mut Parser) -> Result { input.expect_function_matching("circle")?; diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs index c4b95c86865..26b7974732f 100644 --- a/components/style/values/specified/border.rs +++ b/components/style/values/specified/border.rs @@ -6,8 +6,10 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; +use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::border::BorderImageSlice as GenericBorderImageSlice; use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide; +use values::generics::border::BorderRadius as GenericBorderRadius; use values::generics::rect::Rect; use values::specified::{Number, NumberOrPercentage}; use values::specified::length::LengthOrPercentage; @@ -21,6 +23,12 @@ pub type BorderImageWidthSide = GenericBorderImageWidthSide; +/// A specified value for the `border-radius` property. +pub type BorderRadius = GenericBorderRadius; + +/// A specified value for the `border-*-radius` longhand properties. +pub type BorderCornerRadius = GenericBorderCornerRadius; + impl BorderImageWidthSide { /// Returns `1`. #[inline] @@ -57,3 +65,31 @@ impl Parse for BorderImageSlice { }) } } + +impl Parse for BorderRadius { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?; + let heights = if input.try(|i| i.expect_delim('/')).is_ok() { + Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)? + } else { + widths.clone() + }; + + Ok(GenericBorderRadius { + top_left: BorderCornerRadius::new(widths.0, heights.0), + top_right: BorderCornerRadius::new(widths.1, heights.1), + bottom_right: BorderCornerRadius::new(widths.2, heights.2), + bottom_left: BorderCornerRadius::new(widths.3, heights.3), + }) + } +} + +impl Parse for BorderCornerRadius { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + let first = LengthOrPercentage::parse_non_negative(context, input)?; + let second = input + .try(|i| LengthOrPercentage::parse_non_negative(context, i)) + .unwrap_or_else(|()| first.clone()); + Ok(Self::new(first, second)) + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index bf8033ed79a..c3356e8bab3 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -9,7 +9,6 @@ use app_units::Au; use context::QuirksMode; use cssparser::{self, Parser, Token}; -use euclid::size::Size2D; use itoa; use parser::{ParserContext, Parse}; use self::grid::TrackSizeOrRepeat; @@ -23,7 +22,6 @@ use style_traits::values::specified::AllowedNumericType; use super::{Auto, CSSFloat, CSSInteger, Either, None_}; use super::computed::{self, Context}; use super::computed::{Shadow as ComputedShadow, ToComputedValue}; -use super::generics::BorderRadiusSize as GenericBorderRadiusSize; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::TrackList as GenericTrackList; use values::specified::calc::CalcNode; @@ -31,7 +29,8 @@ use values::specified::calc::CalcNode; #[cfg(feature = "gecko")] pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems}; pub use self::background::BackgroundSize; -pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageWidthSide}; +pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; +pub use self::border::{BorderImageWidthSide, BorderRadius}; pub use self::color::Color; pub use self::rect::LengthOrNumberRect; pub use super::generics::grid::GridLine; @@ -281,19 +280,6 @@ pub fn parse_number_with_clamping_mode(context: &ParserContext, } } -/// The specified value of `BorderRadiusSize` -pub type BorderRadiusSize = GenericBorderRadiusSize; - -impl Parse for BorderRadiusSize { - #[inline] - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - let first = try!(LengthOrPercentage::parse_non_negative(context, input)); - let second = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) - .unwrap_or_else(|()| first.clone()); - Ok(GenericBorderRadiusSize(Size2D::new(first, second))) - } -} - #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] /// An angle consisting of a value and a unit. @@ -433,21 +419,6 @@ impl Angle { } } -#[allow(missing_docs)] -pub fn parse_border_radius(context: &ParserContext, input: &mut Parser) -> Result { - input.try(|i| BorderRadiusSize::parse(context, i)).or_else(|_| { - match_ignore_ascii_case! { &try!(input.expect_ident()), - "thin" => Ok(BorderRadiusSize::circle( - LengthOrPercentage::Length(NoCalcLength::from_px(1.)))), - "medium" => Ok(BorderRadiusSize::circle( - LengthOrPercentage::Length(NoCalcLength::from_px(3.)))), - "thick" => Ok(BorderRadiusSize::circle( - LengthOrPercentage::Length(NoCalcLength::from_px(5.)))), - _ => Err(()) - } - }) -} - #[allow(missing_docs)] pub fn parse_border_width(context: &ParserContext, input: &mut Parser) -> Result { input.try(|i| Length::parse_non_negative(context, i)).or_else(|()| { diff --git a/components/style_traits/viewport.rs b/components/style_traits/viewport.rs index 05e39f2b370..a2821cc5e35 100644 --- a/components/style_traits/viewport.rs +++ b/components/style_traits/viewport.rs @@ -56,6 +56,13 @@ impl HasViewportPercentage for Option { } } +impl HasViewportPercentage for TypedSize2D { + #[inline] + fn has_viewport_percentage(&self) -> bool { + self.width.has_viewport_percentage() || self.height.has_viewport_percentage() + } +} + impl HasViewportPercentage for Vec { #[inline] fn has_viewport_percentage(&self) -> bool { diff --git a/tests/unit/style/parsing/basic_shape.rs b/tests/unit/style/parsing/basic_shape.rs index 7364a24e923..e0afdbb001b 100644 --- a/tests/unit/style/parsing/basic_shape.rs +++ b/tests/unit/style/parsing/basic_shape.rs @@ -19,23 +19,6 @@ macro_rules! assert_roundtrip_basicshape { }; } -macro_rules! assert_border_radius_values { - ($input:expr; $tlw:expr, $trw:expr, $brw:expr, $blw:expr ; - $tlh:expr, $trh:expr, $brh:expr, $blh:expr) => { - let input = parse(BorderRadius::parse, $input) - .expect(&format!("Failed parsing {} as border radius", - $input)); - assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.width), $tlw); - assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.width), $trw); - assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.width), $brw); - assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.width), $blw); - assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.height), $tlh); - assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.height), $trh); - assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.height), $brh); - assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.height), $blh); - } -} - #[test] fn test_inset() { assert_roundtrip_basicshape!(InsetRect::parse, "inset(10px)"); @@ -46,47 +29,6 @@ fn test_inset() { assert_roundtrip_basicshape!(InsetRect::parse, "inset(10px round 10px 20px 30px 40px / 1px 2px 3px 4px)"); } -#[test] -fn test_border_radius() { - assert_border_radius_values!("10px"; - "10px", "10px", "10px", "10px" ; - "10px", "10px", "10px", "10px"); - assert_border_radius_values!("10px 20px"; - "10px", "20px", "10px", "20px" ; - "10px", "20px", "10px", "20px"); - assert_border_radius_values!("10px 20px 30px"; - "10px", "20px", "30px", "20px" ; - "10px", "20px", "30px", "20px"); - assert_border_radius_values!("10px 20px 30px 40px"; - "10px", "20px", "30px", "40px" ; - "10px", "20px", "30px", "40px"); - assert_border_radius_values!("10% / 20px"; - "10%", "10%", "10%", "10%" ; - "20px", "20px", "20px", "20px"); - assert_border_radius_values!("10px / 20px 30px"; - "10px", "10px", "10px", "10px" ; - "20px", "30px", "20px", "30px"); - assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; - "10px", "20px", "30px", "40px" ; - "1px", "2px", "3px", "4px"); - assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; - "10px", "20px", "30px", "40px" ; - "1px", "2px", "3px", "4px"); - assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; - "10px", "20px", "30px", "40px" ; - "1px", "2px", "3px", "4px"); - assert_border_radius_values!("10px -20px 30px 40px"; - "10px", "10px", "10px", "10px"; - "10px", "10px", "10px", "10px"); - assert_border_radius_values!("10px 20px -30px 40px"; - "10px", "20px", "10px", "20px"; - "10px", "20px", "10px", "20px"); - assert_border_radius_values!("10px 20px 30px -40px"; - "10px", "20px", "30px", "20px"; - "10px", "20px", "30px", "20px"); - assert!(parse(BorderRadius::parse, "-10px 20px 30px 40px").is_err()); -} - #[test] fn test_circle() { assert_roundtrip_basicshape!(Circle::parse, "circle(at center)", "circle(at 50% 50%)"); diff --git a/tests/unit/style/parsing/border.rs b/tests/unit/style/parsing/border.rs index d9588f116db..92e0cb22331 100644 --- a/tests/unit/style/parsing/border.rs +++ b/tests/unit/style/parsing/border.rs @@ -8,6 +8,7 @@ use style::properties::MaybeBoxed; use style::properties::longhands::{border_image_outset, border_image_repeat, border_image_slice}; use style::properties::longhands::{border_image_source, border_image_width}; use style::properties::shorthands::border_image; +use style::values::specified::BorderRadius; use style_traits::ToCss; macro_rules! assert_longhand { @@ -22,6 +23,64 @@ macro_rules! assert_initial { } } +macro_rules! assert_border_radius_values { + ($input:expr; $tlw:expr, $trw:expr, $brw:expr, $blw:expr ; + $tlh:expr, $trh:expr, $brh:expr, $blh:expr) => { + let input = parse(BorderRadius::parse, $input) + .expect(&format!("Failed parsing {} as border radius", + $input)); + assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.width), $tlw); + assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.width), $trw); + assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.width), $brw); + assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.width), $blw); + assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.height), $tlh); + assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.height), $trh); + assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.height), $brh); + assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.height), $blh); + } +} + +#[test] +fn test_border_radius() { + assert_border_radius_values!("10px"; + "10px", "10px", "10px", "10px" ; + "10px", "10px", "10px", "10px"); + assert_border_radius_values!("10px 20px"; + "10px", "20px", "10px", "20px" ; + "10px", "20px", "10px", "20px"); + assert_border_radius_values!("10px 20px 30px"; + "10px", "20px", "30px", "20px" ; + "10px", "20px", "30px", "20px"); + assert_border_radius_values!("10px 20px 30px 40px"; + "10px", "20px", "30px", "40px" ; + "10px", "20px", "30px", "40px"); + assert_border_radius_values!("10% / 20px"; + "10%", "10%", "10%", "10%" ; + "20px", "20px", "20px", "20px"); + assert_border_radius_values!("10px / 20px 30px"; + "10px", "10px", "10px", "10px" ; + "20px", "30px", "20px", "30px"); + assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; + "10px", "20px", "30px", "40px" ; + "1px", "2px", "3px", "4px"); + assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; + "10px", "20px", "30px", "40px" ; + "1px", "2px", "3px", "4px"); + assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; + "10px", "20px", "30px", "40px" ; + "1px", "2px", "3px", "4px"); + assert_border_radius_values!("10px -20px 30px 40px"; + "10px", "10px", "10px", "10px"; + "10px", "10px", "10px", "10px"); + assert_border_radius_values!("10px 20px -30px 40px"; + "10px", "20px", "10px", "20px"; + "10px", "20px", "10px", "20px"); + assert_border_radius_values!("10px 20px 30px -40px"; + "10px", "20px", "30px", "20px"; + "10px", "20px", "30px", "20px"); + assert!(parse(BorderRadius::parse, "-10px 20px 30px 40px").is_err()); +} + #[test] fn border_image_shorthand_should_parse_when_all_properties_specified() { let input = "linear-gradient(red, blue) 30 30% 45 fill / 20px 40px / 10px round stretch"; diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index 46570f870a0..cee52e5385f 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -368,22 +368,22 @@ mod shorthand_serialization { assert_eq!(serialization, "border-style: solid dotted;"); } - use style::values::specified::BorderRadiusSize; + use style::values::specified::BorderCornerRadius; use style::values::specified::length::Percentage; #[test] fn border_radius_should_serialize_correctly() { let mut properties = Vec::new(); - properties.push(PropertyDeclaration::BorderTopLeftRadius(Box::new(BorderRadiusSize::new( + properties.push(PropertyDeclaration::BorderTopLeftRadius(Box::new(BorderCornerRadius::new( Percentage(0.01).into(), Percentage(0.05).into() )))); - properties.push(PropertyDeclaration::BorderTopRightRadius(Box::new(BorderRadiusSize::new( + properties.push(PropertyDeclaration::BorderTopRightRadius(Box::new(BorderCornerRadius::new( Percentage(0.02).into(), Percentage(0.06).into() )))); - properties.push(PropertyDeclaration::BorderBottomRightRadius(Box::new(BorderRadiusSize::new( + properties.push(PropertyDeclaration::BorderBottomRightRadius(Box::new(BorderCornerRadius::new( Percentage(0.03).into(), Percentage(0.07).into() )))); - properties.push(PropertyDeclaration::BorderBottomLeftRadius(Box::new(BorderRadiusSize::new( + properties.push(PropertyDeclaration::BorderBottomLeftRadius(Box::new(BorderCornerRadius::new( Percentage(0.04).into(), Percentage(0.08).into() ))));