servo: Merge #17071 - Reuse Rect<T> some more (from servo:derive-all-the-things); r=emilio

Source-Repo: https://github.com/servo/servo
Source-Revision: 433d68955b276266d620f788ad509678edc35071

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : adcf447653e4fb82c9ba5fa736085e418722118d
This commit is contained in:
Anthony Ramine 2017-05-30 05:11:28 -05:00
Родитель ec25d40fbf
Коммит f7c6cee7a6
24 изменённых файлов: 324 добавлений и 355 удалений

Просмотреть файл

@ -1424,10 +1424,10 @@ impl FragmentDisplayListBuilding for Fragment {
details: BorderDetails::Image(ImageBorder { details: BorderDetails::Image(ImageBorder {
image: webrender_image, image: webrender_image,
fill: border_style_struct.border_image_slice.fill, fill: border_style_struct.border_image_slice.fill,
slice: SideOffsets2D::new(corners.top.resolve(webrender_image.height), slice: SideOffsets2D::new(corners.0.resolve(webrender_image.height),
corners.right.resolve(webrender_image.width), corners.1.resolve(webrender_image.width),
corners.bottom.resolve(webrender_image.height), corners.2.resolve(webrender_image.height),
corners.left.resolve(webrender_image.width)), corners.3.resolve(webrender_image.width)),
// TODO(gw): Support border-image-outset // TODO(gw): Support border-image-outset
outset: SideOffsets2D::zero(), outset: SideOffsets2D::zero(),
repeat_horizontal: convert_repeat_mode(border_style_struct.border_image_repeat.0), repeat_horizontal: convert_repeat_mode(border_style_struct.border_image_repeat.0),

Просмотреть файл

@ -14,9 +14,8 @@ use std::fmt;
use style::computed_values::transform::ComputedMatrix; use style::computed_values::transform::ComputedMatrix;
use style::logical_geometry::{LogicalMargin, WritingMode}; use style::logical_geometry::{LogicalMargin, WritingMode};
use style::properties::ServoComputedValues; 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::computed::{LengthOrPercentage, LengthOrPercentageOrNone};
use style::values::generics;
/// A collapsible margin. See CSS 2.1 § 8.3.1. /// A collapsible margin. See CSS 2.1 § 8.3.1.
#[derive(Copy, Clone, Debug)] #[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 /// [1]: https://drafts.csswg.org/css-backgrounds-3/#border-radius
pub fn specified_border_radius( pub fn specified_border_radius(
radius: BorderRadiusSize, radius: BorderCornerRadius,
containing_size: Size2D<Au>) containing_size: Size2D<Au>)
-> Size2D<Au> -> Size2D<Au>
{ {
let generics::BorderRadiusSize(size) = radius; let w = radius.0.width.to_used_value(containing_size.width);
let w = size.width.to_used_value(containing_size.width); let h = radius.0.height.to_used_value(containing_size.height);
let h = size.height.to_used_value(containing_size.height);
Size2D::new(w, h) Size2D::new(w, h)
} }

Просмотреть файл

@ -362,13 +362,14 @@ pub mod basic_shape {
use gecko_bindings::structs::StyleGeometryBox; use gecko_bindings::structs::StyleGeometryBox;
use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue}; use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
use std::borrow::Borrow; use std::borrow::Borrow;
use values::computed::{BorderRadiusSize, LengthOrPercentage}; use values::computed::basic_shape::{BasicShape, ShapeRadius};
use values::computed::basic_shape::{BasicShape, BorderRadius, ShapeRadius}; use values::computed::border::{BorderCornerRadius, BorderRadius};
use values::computed::length::LengthOrPercentage;
use values::computed::position; 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::{BasicShape as GenericBasicShape, InsetRect, Polygon};
use values::generics::basic_shape::{Circle, Ellipse, FillRule}; use values::generics::basic_shape::{Circle, Ellipse, FillRule};
use values::generics::basic_shape::{GeometryBox, ShapeBox}; use values::generics::basic_shape::{GeometryBox, ShapeBox};
use values::generics::border::BorderRadius as GenericBorderRadius;
use values::generics::rect::Rect; use values::generics::rect::Rect;
// using Borrow so that we can have a non-moving .into() // using Borrow so that we can have a non-moving .into()
@ -435,14 +436,14 @@ pub mod basic_shape {
fn from(other: T) -> Self { fn from(other: T) -> Self {
let other = other.borrow(); let other = other.borrow();
let get_corner = |index| { let get_corner = |index| {
GenericBorderRadiusSize::new( BorderCornerRadius::new(
LengthOrPercentage::from_gecko_style_coord(&other.data_at(index)) LengthOrPercentage::from_gecko_style_coord(&other.data_at(index))
.expect("<border-radius> should be a length, percentage, or calc value"), .expect("<border-radius> should be a length, percentage, or calc value"),
LengthOrPercentage::from_gecko_style_coord(&other.data_at(index + 1)) LengthOrPercentage::from_gecko_style_coord(&other.data_at(index + 1))
.expect("<border-radius> should be a length, percentage, or calc value")) .expect("<border-radius> should be a length, percentage, or calc value"))
}; };
BorderRadius { GenericBorderRadius {
top_left: get_corner(0), top_left: get_corner(0),
top_right: get_corner(2), top_right: get_corner(2),
bottom_right: get_corner(4), bottom_right: get_corner(4),
@ -456,7 +457,7 @@ pub mod basic_shape {
impl BorderRadius { impl BorderRadius {
/// Set this `BorderRadius` into a given `nsStyleCoord`. /// Set this `BorderRadius` into a given `nsStyleCoord`.
pub fn set_corners(&self, other: &mut nsStyleCorners) { 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.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)); field.0.height.to_gecko_style_coord(&mut other.data_at_mut(index + 1));
}; };

Просмотреть файл

@ -558,14 +558,14 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor {
% if need_clone: % if need_clone:
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { 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( let width = GeckoStyleCoordConvertible::from_gecko_style_coord(
&self.gecko.${gecko_ffi_name}.data_at(${x_index})) &self.gecko.${gecko_ffi_name}.data_at(${x_index}))
.expect("Failed to clone ${ident}"); .expect("Failed to clone ${ident}");
let height = GeckoStyleCoordConvertible::from_gecko_style_coord( let height = GeckoStyleCoordConvertible::from_gecko_style_coord(
&self.gecko.${gecko_ffi_name}.data_at(${y_index})) &self.gecko.${gecko_ffi_name}.data_at(${y_index}))
.expect("Failed to clone ${ident}"); .expect("Failed to clone ${ident}");
BorderRadiusSize::new(width, height) BorderCornerRadius::new(width, height)
} }
% endif % endif
</%def> </%def>
@ -964,7 +964,7 @@ fn static_assert() {
pub fn set_border_image_outset(&mut self, v: longhands::border_image_outset::computed_value::T) { pub fn set_border_image_outset(&mut self, v: longhands::border_image_outset::computed_value::T) {
% for side in SIDES: % 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 % endfor
} }
@ -1001,7 +1001,7 @@ fn static_assert() {
use values::generics::border::BorderImageWidthSide; use values::generics::border::BorderImageWidthSide;
% for side in SIDES: % for side in SIDES:
match v.${side.ident} { match v.${side.index} {
BorderImageWidthSide::Auto => { BorderImageWidthSide::Auto => {
self.gecko.mBorderImageWidth.data_at_mut(${side.index}).set_value(CoordDataValue::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}; use gecko_bindings::structs::{NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, NS_STYLE_BORDER_IMAGE_SLICE_FILL};
% for side in SIDES: % 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 % endfor
let fill = if v.fill { let fill = if v.fill {
@ -3967,13 +3967,13 @@ fn static_assert() {
// the garbage data without // the garbage data without
// attempting to clean up. // attempting to clean up.
shape.mCoordinates[0].leaky_set_null(); 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(); 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(); 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(); 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); set_corners_from_radius(inset.round, &mut shape.mRadius);
} }

Просмотреть файл

@ -901,8 +901,8 @@
% endif % endif
})?; })?;
Ok(expanded! { Ok(expanded! {
% for side in ["top", "right", "bottom", "left"]: % for index, side in enumerate(["top", "right", "bottom", "left"]):
${to_rust_ident(sub_property_pattern % side)}: rect.${side}, ${to_rust_ident(sub_property_pattern % side)}: rect.${index},
% endfor % endfor
}) })
} }

Просмотреть файл

@ -37,12 +37,13 @@ use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use super::ComputedValues; use super::ComputedValues;
use values::CSSFloat; use values::CSSFloat;
use values::{Auto, Either, generics}; use values::{Auto, Either};
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; 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::{CalcLengthOrPercentage, Context, LengthOrPercentage};
use values::computed::{MaxLength, MozLength}; use values::computed::{MaxLength, MozLength};
use values::computed::ToComputedValue; use values::computed::ToComputedValue;
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::position as generic_position; use values::generics::position as generic_position;
@ -874,10 +875,10 @@ impl<T: Animatable + Copy> Animatable for Point2D<T> {
} }
} }
impl Animatable for BorderRadiusSize { impl Animatable for BorderCornerRadius {
#[inline] #[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
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] #[inline]

Просмотреть файл

@ -46,8 +46,8 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
// FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage> // FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage>
% for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]: % for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]:
${helpers.predefined_type("border-" + corner + "-radius", "BorderRadiusSize", ${helpers.predefined_type("border-" + corner + "-radius", "BorderCornerRadius",
"computed::BorderRadiusSize::zero()", "computed::LengthOrPercentage::zero().into()",
"parse", extra_prefixes="webkit", "parse", extra_prefixes="webkit",
spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner, spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner,
boxed=True, boxed=True,

Просмотреть файл

@ -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. // The -moz-outline-radius-* properties are non-standard and not on a standards track.
// TODO: Should they animate? // TODO: Should they animate?
% for corner in ["topleft", "topright", "bottomright", "bottomleft"]: % for corner in ["topleft", "topright", "bottomright", "bottomleft"]:
${helpers.predefined_type("-moz-outline-radius-" + corner, "BorderRadiusSize", ${helpers.predefined_type("-moz-outline-radius-" + corner, "BorderCornerRadius",
"computed::BorderRadiusSize::zero()", "computed::LengthOrPercentage::zero().into()",
"parse", products="gecko", products="gecko",
boxed=True, boxed=True,
animation_value_type="none", animation_value_type="none",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)")} spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)")}

Просмотреть файл

@ -25,20 +25,19 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
BorderWidth::parse_quirky(context, i, AllowQuirks::Yes) BorderWidth::parse_quirky(context, i, AllowQuirks::Yes)
})?; })?;
Ok(expanded! { Ok(expanded! {
% for side in PHYSICAL_SIDES: border_top_width: rect.0,
${to_rust_ident('border-%s-width' % side)}: rect.${side}, border_right_width: rect.1,
% endfor border_bottom_width: rect.2,
border_left_width: rect.3,
}) })
} }
impl<'a> ToCss for LonghandsToSerialize<'a> { impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
let rect = Rect { % for side in PHYSICAL_SIDES:
% for side in PHYSICAL_SIDES: let ${side} = &self.border_${side}_width;
${side}: &self.border_${side}_width, % endfor
% endfor Rect::new(top, right, bottom, left).to_css(dest)
};
rect.to_css(dest)
} }
} }
</%helpers:shorthand> </%helpers:shorthand>
@ -206,8 +205,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
'border-%s-radius' % (corner) 'border-%s-radius' % (corner)
for corner in ['top-left', 'top-right', 'bottom-right', 'bottom-left'] for corner in ['top-left', 'top-right', 'bottom-right', 'bottom-left']
)}" extra_prefixes="webkit" spec="https://drafts.csswg.org/css-backgrounds/#border-radius"> )}" extra_prefixes="webkit" spec="https://drafts.csswg.org/css-backgrounds/#border-radius">
use values::generics::serialize_radius_values; use values::generics::rect::Rect;
use values::specified::basic_shape::BorderRadius; use values::specified::border::BorderRadius;
use parser::Parse; use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> { pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
@ -222,11 +221,17 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
impl<'a> ToCss for LonghandsToSerialize<'a> { impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
serialize_radius_values(dest, let LonghandsToSerialize {
&self.border_top_left_radius.0, border_top_left_radius: ref tl,
&self.border_top_right_radius.0, border_top_right_radius: ref tr,
&self.border_bottom_right_radius.0, border_bottom_right_radius: ref br,
&self.border_bottom_left_radius.0) 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)
} }
} }
</%helpers:shorthand> </%helpers:shorthand>

Просмотреть файл

@ -67,28 +67,33 @@
'-moz-outline-radius-%s' % corner '-moz-outline-radius-%s' % corner
for corner in ['topleft', 'topright', 'bottomright', 'bottomleft'] for corner in ['topleft', 'topright', 'bottomright', 'bottomleft']
)}" products="gecko" spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)"> )}" products="gecko" spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)">
use properties::shorthands; use values::generics::rect::Rect;
use values::generics::serialize_radius_values; use values::specified::border::BorderRadius;
use parser::Parse;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> { pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
// Re-use border-radius parsing. let radii = try!(BorderRadius::parse(context, input));
shorthands::border_radius::parse_value(context, input).map(|longhands| { Ok(expanded! {
expanded! { _moz_outline_radius_topleft: radii.top_left,
% for corner in ["top_left", "top_right", "bottom_right", "bottom_left"]: _moz_outline_radius_topright: radii.top_right,
_moz_outline_radius_${corner.replace("_", "")}: longhands.border_${corner}_radius, _moz_outline_radius_bottomright: radii.bottom_right,
% endfor _moz_outline_radius_bottomleft: radii.bottom_left,
}
}) })
} }
impl<'a> ToCss for LonghandsToSerialize<'a> { impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
serialize_radius_values(dest, let LonghandsToSerialize {
&self._moz_outline_radius_topleft.0, _moz_outline_radius_topleft: ref tl,
&self._moz_outline_radius_topright.0, _moz_outline_radius_topright: ref tr,
&self._moz_outline_radius_bottomright.0, _moz_outline_radius_bottomright: ref br,
&self._moz_outline_radius_bottomleft.0, _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)
} }
} }
</%helpers:shorthand> </%helpers:shorthand>

Просмотреть файл

@ -10,7 +10,7 @@
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::LengthOrPercentage; 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::{Circle as GenericCircle, ClippingShape as GenericClippingShape};
use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape}; use values::generics::basic_shape::{Ellipse as GenericEllipse, FloatAreaShape as GenericFloatAreaShape};
use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius}; use values::generics::basic_shape::{InsetRect as GenericInsetRect, ShapeRadius as GenericShapeRadius};
@ -27,9 +27,6 @@ pub type BasicShape = GenericBasicShape<LengthOrPercentage, LengthOrPercentage,
/// The computed value of `inset()` /// The computed value of `inset()`
pub type InsetRect = GenericInsetRect<LengthOrPercentage>; pub type InsetRect = GenericInsetRect<LengthOrPercentage>;
/// The computed value of `BorderRadius`
pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
/// A computed circle. /// A computed circle.
pub type Circle = GenericCircle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>; pub type Circle = GenericCircle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;

Просмотреть файл

@ -6,8 +6,10 @@
use values::computed::{Number, NumberOrPercentage}; use values::computed::{Number, NumberOrPercentage};
use values::computed::length::LengthOrPercentage; use values::computed::length::LengthOrPercentage;
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::border::BorderImageSlice as GenericBorderImageSlice; use values::generics::border::BorderImageSlice as GenericBorderImageSlice;
use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide; use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide;
use values::generics::border::BorderRadius as GenericBorderRadius;
use values::generics::rect::Rect; use values::generics::rect::Rect;
/// A computed value for the `border-image-width` property. /// A computed value for the `border-image-width` property.
@ -19,6 +21,12 @@ pub type BorderImageWidthSide = GenericBorderImageWidthSide<LengthOrPercentage,
/// A computed value for the `border-image-slice` property. /// A computed value for the `border-image-slice` property.
pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>; pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>;
/// A computed value for the `border-radius` property.
pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
/// A computed value for the `border-*-radius` longhand properties.
pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
impl BorderImageWidthSide { impl BorderImageWidthSide {
/// Returns `1`. /// Returns `1`.
#[inline] #[inline]

Просмотреть файл

@ -17,7 +17,6 @@ use std::f32::consts::PI;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use super::{CSSFloat, CSSInteger, RGBA}; 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::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
use super::generics::grid::TrackList as GenericTrackList; use super::generics::grid::TrackList as GenericTrackList;
use super::specified; use super::specified;
@ -26,6 +25,7 @@ pub use app_units::Au;
pub use cssparser::Color as CSSColor; pub use cssparser::Color as CSSColor;
pub use self::background::BackgroundSize; pub use self::background::BackgroundSize;
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageWidthSide}; 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::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use super::{Auto, Either, None_}; pub use super::{Auto, Either, None_};
@ -462,20 +462,6 @@ impl ComputedValueAsSpecified for specified::AlignJustifyContent {}
impl ComputedValueAsSpecified for specified::AlignJustifySelf {} impl ComputedValueAsSpecified for specified::AlignJustifySelf {}
impl ComputedValueAsSpecified for specified::BorderStyle {} impl ComputedValueAsSpecified for specified::BorderStyle {}
/// The computed value of `BorderRadiusSize`
pub type BorderRadiusSize = GenericBorderRadiusSize<LengthOrPercentage>;
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)] #[derive(Debug, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]

Просмотреть файл

@ -5,11 +5,10 @@
//! CSS handling for the [`basic-shape`](https://drafts.csswg.org/css-shapes/#typedef-basic-shape) //! CSS handling for the [`basic-shape`](https://drafts.csswg.org/css-shapes/#typedef-basic-shape)
//! types that are generic over their `ToCss` implementations. //! types that are generic over their `ToCss` implementations.
use euclid::size::Size2D;
use std::fmt; use std::fmt;
use style_traits::{HasViewportPercentage, ToCss}; use style_traits::{HasViewportPercentage, ToCss};
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::generics::BorderRadiusSize; use values::generics::border::BorderRadius;
use values::generics::position::Position; use values::generics::position::Position;
use values::generics::rect::Rect; use values::generics::rect::Rect;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
@ -71,22 +70,6 @@ pub struct InsetRect<LengthOrPercentage> {
pub round: Option<BorderRadius<LengthOrPercentage>>, pub round: Option<BorderRadius<LengthOrPercentage>>,
} }
/// 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<LengthOrPercentage> {
/// The top left radius.
pub top_left: BorderRadiusSize<LengthOrPercentage>,
/// The top right radius.
pub top_right: BorderRadiusSize<LengthOrPercentage>,
/// The bottom right radius.
pub bottom_right: BorderRadiusSize<LengthOrPercentage>,
/// The bottom left radius.
pub bottom_left: BorderRadiusSize<LengthOrPercentage>,
}
/// https://drafts.csswg.org/css-shapes/#funcdef-circle /// https://drafts.csswg.org/css-shapes/#funcdef-circle
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -201,33 +184,6 @@ impl<L> ToCss for InsetRect<L>
} }
} }
impl<L: ToCss + PartialEq> ToCss for BorderRadius<L> {
#[inline]
fn to_css<W>(&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<L, W>(dest: &mut W, top_left: &Size2D<L>,
top_right: &Size2D<L>, bottom_right: &Size2D<L>,
bottom_left: &Size2D<L>) -> 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<L> Default for ShapeRadius<L> { impl<L> Default for ShapeRadius<L> {
#[inline] #[inline]
fn default() -> Self { ShapeRadius::ClosestSide } fn default() -> Self { ShapeRadius::ClosestSide }

Просмотреть файл

@ -4,6 +4,7 @@
//! Generic types for CSS values related to borders. //! Generic types for CSS values related to borders.
use euclid::Size2D;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::generics::rect::Rect; use values::generics::rect::Rect;
@ -30,6 +31,27 @@ pub struct BorderImageSlice<NumberOrPercentage> {
pub fill: bool, 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<LengthOrPercentage> {
/// The top left radius.
pub top_left: BorderCornerRadius<LengthOrPercentage>,
/// The top right radius.
pub top_right: BorderCornerRadius<LengthOrPercentage>,
/// The bottom right radius.
pub bottom_right: BorderCornerRadius<LengthOrPercentage>,
/// The bottom left radius.
pub bottom_left: BorderCornerRadius<LengthOrPercentage>,
}
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
/// A generic value for `border-*-radius` longhand properties.
pub struct BorderCornerRadius<L>(pub Size2D<L>);
impl<L, N> ToCss for BorderImageWidthSide<L, N> impl<L, N> ToCss for BorderImageWidthSide<L, N>
where L: ToCss, N: ToCss, where L: ToCss, N: ToCss,
{ {
@ -69,3 +91,81 @@ impl<N> ToCss for BorderImageSlice<N>
Ok(()) Ok(())
} }
} }
impl<L> BorderRadius<L> {
/// Returns a new `BorderRadius<L>`.
#[inline]
pub fn new(tl: BorderCornerRadius<L>,
tr: BorderCornerRadius<L>,
br: BorderCornerRadius<L>,
bl: BorderCornerRadius<L>)
-> Self {
BorderRadius {
top_left: tl,
top_right: tr,
bottom_right: br,
bottom_left: bl,
}
}
}
impl<L> BorderRadius<L>
where L: PartialEq + ToCss
{
/// Serialises two given rects following the syntax of the `border-radius``
/// property.
pub fn serialize_rects<W>(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<L> ToCss for BorderRadius<L>
where L: PartialEq + ToCss
{
fn to_css<W>(&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<L> BorderCornerRadius<L> {
#[inline]
/// Create a new `BorderCornerRadius` for an area of given width and height.
pub fn new(width: L, height: L) -> BorderCornerRadius<L> {
BorderCornerRadius(Size2D::new(width, height))
}
}
impl<L: Clone> From<L> for BorderCornerRadius<L> {
fn from(radius: L) -> Self {
Self::new(radius.clone(), radius)
}
}
impl<L> ToCss for BorderCornerRadius<L>
where L: ToCss,
{
fn to_css<W>(&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)
}
}

Просмотреть файл

@ -7,14 +7,11 @@
use counter_style::{Symbols, parse_counter_style_name}; use counter_style::{Symbols, parse_counter_style_name};
use cssparser::Parser; use cssparser::Parser;
use euclid::size::Size2D;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::fmt; use std::fmt;
use style_traits::{HasViewportPercentage, OneOrMoreCommaSeparated, ToCss}; use style_traits::{OneOrMoreCommaSeparated, ToCss};
use super::CustomIdent; use super::CustomIdent;
pub use self::basic_shape::serialize_radius_values;
pub mod background; pub mod background;
pub mod basic_shape; pub mod basic_shape;
pub mod border; pub mod border;
@ -23,47 +20,6 @@ pub mod image;
pub mod position; pub mod position;
pub mod rect; 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<L>(pub Size2D<L>);
impl<L> HasViewportPercentage for BorderRadiusSize<L> {
#[inline]
fn has_viewport_percentage(&self) -> bool { false }
}
impl<L: Clone> From<L> for BorderRadiusSize<L> {
fn from(other: L) -> Self {
Self::new(other.clone(), other)
}
}
impl<L> BorderRadiusSize<L> {
#[inline]
/// Create a new `BorderRadiusSize` for an area of given width and height.
pub fn new(width: L, height: L) -> BorderRadiusSize<L> {
BorderRadiusSize(Size2D::new(width, height))
}
}
impl<L: Clone> BorderRadiusSize<L> {
#[inline]
/// Create a new `BorderRadiusSize` for a circle of given radius.
pub fn circle(radius: L) -> BorderRadiusSize<L> {
BorderRadiusSize(Size2D::new(radius.clone(), radius))
}
}
impl<L: ToCss> ToCss for BorderRadiusSize<L> {
#[inline]
fn to_css<W>(&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 // https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
define_css_keyword_enum! { SymbolsType: define_css_keyword_enum! { SymbolsType:
"cyclic" => Cyclic, "cyclic" => Cyclic,

Просмотреть файл

@ -9,29 +9,16 @@ use parser::{Parse, ParserContext};
use std::fmt; use std::fmt;
use style_traits::ToCss; 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)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Rect<T> { pub struct Rect<T>(pub T, pub T, pub T, pub T);
/// Top
pub top: T,
/// Right.
pub right: T,
/// Bottom.
pub bottom: T,
/// Left.
pub left: T,
}
impl<T> Rect<T> { impl<T> Rect<T> {
/// Returns a new `Rect<T>` value. /// Returns a new `Rect<T>` value.
pub fn new(top: T, right: T, bottom: T, left: T) -> Self { pub fn new(first: T, second: T, third: T, fourth: T) -> Self {
Rect { Rect(first, second, third, fourth)
top: top,
right: right,
bottom: bottom,
left: left,
}
} }
} }
@ -46,21 +33,21 @@ impl<T> Rect<T>
-> Result<Self, ()> -> Result<Self, ()>
where Parse: Fn(&ParserContext, &mut Parser) -> Result<T, ()> where Parse: Fn(&ParserContext, &mut Parser) -> Result<T, ()>
{ {
let top = parse(context, input)?; let first = parse(context, input)?;
let right = if let Ok(right) = input.try(|i| parse(context, i)) { right } else { let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else {
// <top> // <first>
return Ok(Self::new(top.clone(), top.clone(), top.clone(), top)); 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 { let third = if let Ok(third) = input.try(|i| parse(context, i)) { third } else {
// <top> <right> // <first> <second>
return Ok(Self::new(top.clone(), right.clone(), top, right)); return Ok(Self::new(first.clone(), second.clone(), first, second));
}; };
let left = if let Ok(left) = input.try(|i| parse(context, i)) { left } else { let fourth = if let Ok(fourth) = input.try(|i| parse(context, i)) { fourth } else {
// <top> <right> <bottom> // <first> <second> <third>
return Ok(Self::new(top, right.clone(), bottom, right)); return Ok(Self::new(first, second.clone(), third, second));
}; };
// <top> <right> <bottom> <left> // <first> <second> <third> <fourth>
Ok(Self::new(top, right, bottom, left)) Ok(Self::new(first, second, third, fourth))
} }
} }
@ -88,23 +75,23 @@ impl<T> ToCss for Rect<T>
fn to_css<W>(&self, dest: &mut W) -> fmt::Result fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write, where W: fmt::Write,
{ {
self.top.to_css(dest)?; self.0.to_css(dest)?;
let same_vertical = self.top == self.bottom; let same_vertical = self.0 == self.2;
let same_horizontal = self.right == self.left; let same_horizontal = self.1 == self.3;
if same_vertical && same_horizontal && self.top == self.right { if same_vertical && same_horizontal && self.0 == self.1 {
return Ok(()); return Ok(());
} }
dest.write_str(" ")?; dest.write_str(" ")?;
self.right.to_css(dest)?; self.1.to_css(dest)?;
if same_vertical && same_horizontal { if same_vertical && same_horizontal {
return Ok(()); return Ok(());
} }
dest.write_str(" ")?; dest.write_str(" ")?;
self.bottom.to_css(dest)?; self.2.to_css(dest)?;
if same_horizontal { if same_horizontal {
return Ok(()); return Ok(());
} }
dest.write_str(" ")?; dest.write_str(" ")?;
self.left.to_css(dest) self.3.to_css(dest)
} }
} }

Просмотреть файл

@ -12,8 +12,7 @@ use parser::{Parse, ParserContext};
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::generics::BorderRadiusSize; use values::generics::basic_shape::{Circle as GenericCircle};
use values::generics::basic_shape::{BorderRadius as GenericBorderRadius, Circle as GenericCircle};
use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse}; 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::{FillRule, BasicShape as GenericBasicShape};
use values::generics::basic_shape::{FloatAreaShape as GenericFloatAreaShape, InsetRect as GenericInsetRect}; 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::basic_shape::{Polygon as GenericPolygon, ShapeRadius as GenericShapeRadius};
use values::generics::rect::Rect; use values::generics::rect::Rect;
use values::specified::{LengthOrPercentage, Percentage}; use values::specified::{LengthOrPercentage, Percentage};
use values::specified::border::BorderRadius;
use values::specified::position::{HorizontalPosition, Position, PositionComponent, Side, VerticalPosition}; use values::specified::position::{HorizontalPosition, Position, PositionComponent, Side, VerticalPosition};
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
@ -36,9 +36,6 @@ pub type BasicShape = GenericBasicShape<HorizontalPosition, VerticalPosition, Le
/// The specified value of `inset()` /// The specified value of `inset()`
pub type InsetRect = GenericInsetRect<LengthOrPercentage>; pub type InsetRect = GenericInsetRect<LengthOrPercentage>;
/// The specified value of `BorderRadius`
pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
/// A specified circle. /// A specified circle.
pub type Circle = GenericCircle<HorizontalPosition, VerticalPosition, LengthOrPercentage>; pub type Circle = GenericCircle<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
@ -140,49 +137,6 @@ impl InsetRect {
} }
} }
impl Parse for BorderRadius {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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 { impl Parse for Circle {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
input.expect_function_matching("circle")?; input.expect_function_matching("circle")?;

Просмотреть файл

@ -6,8 +6,10 @@
use cssparser::Parser; use cssparser::Parser;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::border::BorderImageSlice as GenericBorderImageSlice; use values::generics::border::BorderImageSlice as GenericBorderImageSlice;
use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide; use values::generics::border::BorderImageWidthSide as GenericBorderImageWidthSide;
use values::generics::border::BorderRadius as GenericBorderRadius;
use values::generics::rect::Rect; use values::generics::rect::Rect;
use values::specified::{Number, NumberOrPercentage}; use values::specified::{Number, NumberOrPercentage};
use values::specified::length::LengthOrPercentage; use values::specified::length::LengthOrPercentage;
@ -21,6 +23,12 @@ pub type BorderImageWidthSide = GenericBorderImageWidthSide<LengthOrPercentage,
/// A specified value for the `border-image-slice` property. /// A specified value for the `border-image-slice` property.
pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>; pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>;
/// A specified value for the `border-radius` property.
pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
/// A specified value for the `border-*-radius` longhand properties.
pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
impl BorderImageWidthSide { impl BorderImageWidthSide {
/// Returns `1`. /// Returns `1`.
#[inline] #[inline]
@ -57,3 +65,31 @@ impl Parse for BorderImageSlice {
}) })
} }
} }
impl Parse for BorderRadius {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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<Self, ()> {
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))
}
}

Просмотреть файл

@ -9,7 +9,6 @@
use app_units::Au; use app_units::Au;
use context::QuirksMode; use context::QuirksMode;
use cssparser::{self, Parser, Token}; use cssparser::{self, Parser, Token};
use euclid::size::Size2D;
use itoa; use itoa;
use parser::{ParserContext, Parse}; use parser::{ParserContext, Parse};
use self::grid::TrackSizeOrRepeat; use self::grid::TrackSizeOrRepeat;
@ -23,7 +22,6 @@ use style_traits::values::specified::AllowedNumericType;
use super::{Auto, CSSFloat, CSSInteger, Either, None_}; use super::{Auto, CSSFloat, CSSInteger, Either, None_};
use super::computed::{self, Context}; use super::computed::{self, Context};
use super::computed::{Shadow as ComputedShadow, ToComputedValue}; 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::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize};
use super::generics::grid::TrackList as GenericTrackList; use super::generics::grid::TrackList as GenericTrackList;
use values::specified::calc::CalcNode; use values::specified::calc::CalcNode;
@ -31,7 +29,8 @@ use values::specified::calc::CalcNode;
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems}; pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
pub use self::background::BackgroundSize; 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::color::Color;
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use super::generics::grid::GridLine; 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<LengthOrPercentage>;
impl Parse for BorderRadiusSize {
#[inline]
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
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)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
/// An angle consisting of a value and a unit. /// 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<BorderRadiusSize, ()> {
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)] #[allow(missing_docs)]
pub fn parse_border_width(context: &ParserContext, input: &mut Parser) -> Result<Length, ()> { pub fn parse_border_width(context: &ParserContext, input: &mut Parser) -> Result<Length, ()> {
input.try(|i| Length::parse_non_negative(context, i)).or_else(|()| { input.try(|i| Length::parse_non_negative(context, i)).or_else(|()| {

Просмотреть файл

@ -56,6 +56,13 @@ impl<T: HasViewportPercentage> HasViewportPercentage for Option<T> {
} }
} }
impl<T: HasViewportPercentage, U> HasViewportPercentage for TypedSize2D<T, U> {
#[inline]
fn has_viewport_percentage(&self) -> bool {
self.width.has_viewport_percentage() || self.height.has_viewport_percentage()
}
}
impl<T: HasViewportPercentage> HasViewportPercentage for Vec<T> { impl<T: HasViewportPercentage> HasViewportPercentage for Vec<T> {
#[inline] #[inline]
fn has_viewport_percentage(&self) -> bool { fn has_viewport_percentage(&self) -> bool {

Просмотреть файл

@ -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] #[test]
fn test_inset() { fn test_inset() {
assert_roundtrip_basicshape!(InsetRect::parse, "inset(10px)"); 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)"); 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] #[test]
fn test_circle() { fn test_circle() {
assert_roundtrip_basicshape!(Circle::parse, "circle(at center)", "circle(at 50% 50%)"); assert_roundtrip_basicshape!(Circle::parse, "circle(at center)", "circle(at 50% 50%)");

Просмотреть файл

@ -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_outset, border_image_repeat, border_image_slice};
use style::properties::longhands::{border_image_source, border_image_width}; use style::properties::longhands::{border_image_source, border_image_width};
use style::properties::shorthands::border_image; use style::properties::shorthands::border_image;
use style::values::specified::BorderRadius;
use style_traits::ToCss; use style_traits::ToCss;
macro_rules! assert_longhand { 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] #[test]
fn border_image_shorthand_should_parse_when_all_properties_specified() { 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"; let input = "linear-gradient(red, blue) 30 30% 45 fill / 20px 40px / 10px round stretch";

Просмотреть файл

@ -368,22 +368,22 @@ mod shorthand_serialization {
assert_eq!(serialization, "border-style: solid dotted;"); assert_eq!(serialization, "border-style: solid dotted;");
} }
use style::values::specified::BorderRadiusSize; use style::values::specified::BorderCornerRadius;
use style::values::specified::length::Percentage; use style::values::specified::length::Percentage;
#[test] #[test]
fn border_radius_should_serialize_correctly() { fn border_radius_should_serialize_correctly() {
let mut properties = Vec::new(); 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() 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() 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() 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() Percentage(0.04).into(), Percentage(0.08).into()
)))); ))));