Auto merge of #17036 - servo:derive-all-the-things, r=emilio

Use values::generics::rect::Rect some more

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17036)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-05-27 05:41:12 -05:00 committed by GitHub
commit 7275f65981
18 changed files with 253 additions and 410 deletions

View file

@ -2932,29 +2932,37 @@ fn static_assert() {
use gecko_bindings::structs::nsStyleImageLayers_Size_Dimension;
use gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType;
use gecko_bindings::structs::{nsStyleCoord_CalcValue, nsStyleImageLayers_Size};
use properties::longhands::background_size::single_value::computed_value::T;
use values::generics::background::BackgroundSize;
let mut width = nsStyleCoord_CalcValue::new();
let mut height = nsStyleCoord_CalcValue::new();
let (w_type, h_type) = match servo {
T::Explicit(size) => {
BackgroundSize::Explicit { width: explicit_width, height: explicit_height } => {
let mut w_type = nsStyleImageLayers_Size_DimensionType::eAuto;
let mut h_type = nsStyleImageLayers_Size_DimensionType::eAuto;
if let Some(w) = size.width.to_calc_value() {
if let Some(w) = explicit_width.to_calc_value() {
width = w;
w_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
}
if let Some(h) = size.height.to_calc_value() {
if let Some(h) = explicit_height.to_calc_value() {
height = h;
h_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
}
(w_type, h_type)
}
T::Cover => (nsStyleImageLayers_Size_DimensionType::eCover,
nsStyleImageLayers_Size_DimensionType::eCover),
T::Contain => (nsStyleImageLayers_Size_DimensionType::eContain,
nsStyleImageLayers_Size_DimensionType::eContain),
BackgroundSize::Cover => {
(
nsStyleImageLayers_Size_DimensionType::eCover,
nsStyleImageLayers_Size_DimensionType::eCover,
)
},
BackgroundSize::Contain => {
(
nsStyleImageLayers_Size_DimensionType::eContain,
nsStyleImageLayers_Size_DimensionType::eContain,
)
},
};
nsStyleImageLayers_Size {
@ -2968,8 +2976,8 @@ fn static_assert() {
pub fn clone_${shorthand}_size(&self) -> longhands::background_size::computed_value::T {
use gecko_bindings::structs::nsStyleCoord_CalcValue as CalcValue;
use gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType as DimensionType;
use properties::longhands::background_size::single_value::computed_value::{ExplicitSize, T};
use values::computed::LengthOrPercentageOrAuto;
use values::generics::background::BackgroundSize;
fn to_servo(value: CalcValue, ty: u8) -> LengthOrPercentageOrAuto {
if ty == DimensionType::eAuto as u8 {
@ -2984,17 +2992,16 @@ fn static_assert() {
self.gecko.${image_layers_field}.mLayers.iter().map(|ref layer| {
if DimensionType::eCover as u8 == layer.mSize.mWidthType {
debug_assert!(layer.mSize.mHeightType == DimensionType::eCover as u8);
return T::Cover
return BackgroundSize::Cover
}
if DimensionType::eContain as u8 == layer.mSize.mWidthType {
debug_assert!(layer.mSize.mHeightType == DimensionType::eContain as u8);
return T::Contain
return BackgroundSize::Contain
}
T::Explicit(ExplicitSize {
BackgroundSize::Explicit {
width: to_servo(layer.mSize.mWidth._base, layer.mSize.mWidthType),
height: to_servo(layer.mSize.mHeight._base, layer.mSize.mHeightType),
})
}
}).collect()
)
}
@ -3888,7 +3895,7 @@ fn static_assert() {
}
}
match servo_shape {
BasicShape::Inset(rect) => {
BasicShape::Inset(inset) => {
let mut shape = init_shape(${ident}, StyleBasicShapeType::Inset);
unsafe { shape.mCoordinates.set_len(4) };
@ -3900,15 +3907,15 @@ fn static_assert() {
// the garbage data without
// attempting to clean up.
shape.mCoordinates[0].leaky_set_null();
rect.top.to_gecko_style_coord(&mut shape.mCoordinates[0]);
inset.rect.top.to_gecko_style_coord(&mut shape.mCoordinates[0]);
shape.mCoordinates[1].leaky_set_null();
rect.right.to_gecko_style_coord(&mut shape.mCoordinates[1]);
inset.rect.right.to_gecko_style_coord(&mut shape.mCoordinates[1]);
shape.mCoordinates[2].leaky_set_null();
rect.bottom.to_gecko_style_coord(&mut shape.mCoordinates[2]);
inset.rect.bottom.to_gecko_style_coord(&mut shape.mCoordinates[2]);
shape.mCoordinates[3].leaky_set_null();
rect.left.to_gecko_style_coord(&mut shape.mCoordinates[3]);
inset.rect.left.to_gecko_style_coord(&mut shape.mCoordinates[3]);
set_corners_from_radius(rect.round, &mut shape.mRadius);
set_corners_from_radius(inset.round, &mut shape.mRadius);
}
BasicShape::Circle(circ) => {
let mut shape = init_shape(${ident}, StyleBasicShapeType::Circle);

View file

@ -887,35 +887,34 @@
<%call expr="self.shorthand(name, sub_properties=sub_properties, **kwargs)">
#[allow(unused_imports)]
use parser::Parse;
use super::parse_four_sides;
use values::generics::rect::Rect;
use values::specified;
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
let (top, right, bottom, left) =
let rect = Rect::parse_with(context, input, |_c, i| {
% if allow_quirks:
try!(parse_four_sides(input, |i| ${parser_function}_quirky(context, i, specified::AllowQuirks::Yes)));
${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
% elif needs_context:
try!(parse_four_sides(input, |i| ${parser_function}(context, i)));
${parser_function}(_c, i)
% else:
try!(parse_four_sides(input, ${parser_function}));
let _unused = context;
${parser_function}(i)
% endif
})?;
Ok(expanded! {
% for side in ["top", "right", "bottom", "left"]:
${to_rust_ident(sub_property_pattern % side)}: ${side},
${to_rust_ident(sub_property_pattern % side)}: rect.${side},
% endfor
})
}
impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
super::serialize_four_sides(
dest,
self.${to_rust_ident(sub_property_pattern % 'top')},
self.${to_rust_ident(sub_property_pattern % 'right')},
self.${to_rust_ident(sub_property_pattern % 'bottom')},
self.${to_rust_ident(sub_property_pattern % 'left')}
)
let rect = Rect::new(
% for side in ["top", "right", "bottom", "left"]:
&self.${to_rust_ident(sub_property_pattern % side)},
% endfor
);
rect.to_css(dest)
}
}
</%call>

View file

@ -160,188 +160,13 @@ ${helpers.single_keyword("background-origin",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
animation_value_type="none")}
<%helpers:vector_longhand name="background-size" animation_value_type="ComputedValue" extra_prefixes="webkit"
spec="https://drafts.csswg.org/css-backgrounds/#the-background-size">
use std::fmt;
use style_traits::ToCss;
#[allow(missing_docs)]
pub mod computed_value {
use values::computed::LengthOrPercentageOrAuto;
use properties::animated_properties::{Animatable, RepeatableListAnimatable};
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ExplicitSize {
pub width: LengthOrPercentageOrAuto,
pub height: LengthOrPercentageOrAuto,
}
#[derive(PartialEq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
Explicit(ExplicitSize),
Cover,
Contain,
}
impl RepeatableListAnimatable for T {}
impl Animatable for T {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
-> Result<Self, ()> {
use properties::longhands::background_size::single_value::computed_value::ExplicitSize;
match (self, other) {
(&T::Explicit(ref me), &T::Explicit(ref other)) => {
Ok(T::Explicit(ExplicitSize {
width: try!(me.width.add_weighted(&other.width,
self_portion, other_portion)),
height: try!(me.height.add_weighted(&other.height,
self_portion, other_portion)),
}))
}
_ => Err(()),
}
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt())
}
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
match (self, other) {
(&T::Explicit(ref me), &T::Explicit(ref other)) => {
Ok(try!(me.width.compute_squared_distance(&other.width)) +
try!(me.height.compute_squared_distance(&other.height)))
},
_ => Err(())
}
}
}
}
impl ToCss for computed_value::T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
computed_value::T::Explicit(ref size) => size.to_css(dest),
computed_value::T::Cover => dest.write_str("cover"),
computed_value::T::Contain => dest.write_str("contain"),
}
}
}
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct ExplicitSize {
pub width: specified::LengthOrPercentageOrAuto,
pub height: specified::LengthOrPercentageOrAuto,
}
impl ToCss for ExplicitSize {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(self.width.to_css(dest));
try!(dest.write_str(" "));
self.height.to_css(dest)
}
}
impl ToCss for computed_value::ExplicitSize {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(self.width.to_css(dest));
try!(dest.write_str(" "));
self.height.to_css(dest)
}
}
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
Explicit(ExplicitSize),
Cover,
Contain,
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
SpecifiedValue::Explicit(ref size) => size.to_css(dest),
SpecifiedValue::Cover => dest.write_str("cover"),
SpecifiedValue::Contain => dest.write_str("contain"),
}
}
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
match *self {
SpecifiedValue::Explicit(ref size) => {
computed_value::T::Explicit(computed_value::ExplicitSize {
width: size.width.to_computed_value(context),
height: size.height.to_computed_value(context),
})
}
SpecifiedValue::Cover => computed_value::T::Cover,
SpecifiedValue::Contain => computed_value::T::Contain,
}
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed {
computed_value::T::Explicit(ref size) => {
SpecifiedValue::Explicit(ExplicitSize {
width: ToComputedValue::from_computed_value(&size.width),
height: ToComputedValue::from_computed_value(&size.height),
})
}
computed_value::T::Cover => SpecifiedValue::Cover,
computed_value::T::Contain => SpecifiedValue::Contain,
}
}
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::Explicit(computed_value::ExplicitSize {
width: computed::LengthOrPercentageOrAuto::Auto,
height: computed::LengthOrPercentageOrAuto::Auto,
})
}
#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue::Explicit(ExplicitSize {
width: specified::LengthOrPercentageOrAuto::Auto,
height: specified::LengthOrPercentageOrAuto::Auto,
})
}
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
if input.try(|input| input.expect_ident_matching("cover")).is_ok() {
return Ok(SpecifiedValue::Cover);
}
if input.try(|input| input.expect_ident_matching("contain")).is_ok() {
return Ok(SpecifiedValue::Contain);
}
let width =
try!(specified::LengthOrPercentageOrAuto::parse_non_negative(context, input));
let height = input.try(|input| {
specified::LengthOrPercentageOrAuto::parse_non_negative(context, input)
}).unwrap_or(specified::LengthOrPercentageOrAuto::Auto);
Ok(SpecifiedValue::Explicit(ExplicitSize {
width: width,
height: height,
}))
}
</%helpers:vector_longhand>
${helpers.predefined_type("background-size", "BackgroundSize",
initial_value="computed::LengthOrPercentageOrAuto::Auto.into()",
initial_specified_value="specified::LengthOrPercentageOrAuto::Auto.into()",
spec="https://drafts.csswg.org/css-backgrounds/#the-background-size",
vector=True,
animation_value_type="ComputedValue",
extra_prefixes="webkit")}
// https://drafts.fxtf.org/compositing/#background-blend-mode
${helpers.single_keyword("background-blend-mode",

View file

@ -172,55 +172,6 @@ pub mod shorthands {
use parser::{Parse, ParserContext};
use values::specified;
/// Parses a property for four different sides per CSS syntax.
///
/// * Zero or more than four values is invalid.
/// * One value sets them all
/// * Two values set (top, bottom) and (left, right)
/// * Three values set top, (left, right) and bottom
/// * Four values set them in order
///
/// returns the values in (top, right, bottom, left) order.
pub fn parse_four_sides<F, T>(input: &mut Parser, parse_one: F) -> Result<(T, T, T, T), ()>
where F: Fn(&mut Parser) -> Result<T, ()>,
T: Clone,
{
let top = try!(parse_one(input));
let right;
let bottom;
let left;
match input.try(|i| parse_one(i)) {
Err(()) => {
right = top.clone();
bottom = top.clone();
left = top.clone();
}
Ok(value) => {
right = value;
match input.try(|i| parse_one(i)) {
Err(()) => {
bottom = top.clone();
left = right.clone();
}
Ok(value) => {
bottom = value;
match input.try(|i| parse_one(i)) {
Err(()) => {
left = right.clone();
}
Ok(value) => {
left = value;
}
}
}
}
}
}
Ok((top, right, bottom, left))
}
<%include file="/shorthand/serialize.mako.rs" />
<%include file="/shorthand/background.mako.rs" />
<%include file="/shorthand/border.mako.rs" />

View file

@ -17,27 +17,28 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
' '.join('border-%s-width' % side
for side in PHYSICAL_SIDES)}"
spec="https://drafts.csswg.org/css-backgrounds/#border-width">
use super::parse_four_sides;
use values::generics::rect::Rect;
use values::specified::{AllowQuirks, BorderWidth};
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
let (top, right, bottom, left) = try!(parse_four_sides(input, |i| {
let rect = Rect::parse_with(context, input, |_, i| {
BorderWidth::parse_quirky(context, i, AllowQuirks::Yes)
}));
})?;
Ok(expanded! {
% for side in PHYSICAL_SIDES:
${to_rust_ident('border-%s-width' % side)}: ${side},
${to_rust_ident('border-%s-width' % side)}: rect.${side},
% endfor
})
}
impl<'a> ToCss for LonghandsToSerialize<'a> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
% for side in PHYSICAL_SIDES:
let ${side} = self.border_${side}_width.clone();
% endfor
super::serialize_four_sides(dest, &top, &right, &bottom, &left)
let rect = Rect {
% for side in PHYSICAL_SIDES:
${side}: &self.border_${side}_width,
% endfor
};
rect.to_css(dest)
}
}
</%helpers:shorthand>

View file

@ -6,57 +6,6 @@ use style_traits::ToCss;
use values::specified::{BorderStyle, Color, CSSColor};
use std::fmt;
#[allow(missing_docs)]
pub fn serialize_four_sides<W, I>(dest: &mut W,
top: &I,
right: &I,
bottom: &I,
left: &I)
-> fmt::Result
where W: fmt::Write,
I: ToCss + PartialEq,
{
if left == right {
let horizontal_value = left;
if top == bottom {
let vertical_value = top;
if horizontal_value == vertical_value {
let single_value = horizontal_value;
try!(single_value.to_css(dest));
} else {
try!(vertical_value.to_css(dest));
try!(write!(dest, " "));
try!(horizontal_value.to_css(dest));
}
} else {
try!(top.to_css(dest));
try!(write!(dest, " "));
try!(horizontal_value.to_css(dest));
try!(write!(dest, " "));
try!(bottom.to_css(dest));
}
} else {
try!(top.to_css(dest));
try!(write!(dest, " "));
try!(right.to_css(dest));
try!(write!(dest, " "));
try!(bottom.to_css(dest));
try!(write!(dest, " "));
try!(left.to_css(dest));
}
Ok(())
}
fn serialize_directional_border<W, I,>(dest: &mut W,
width: &I,
style: &BorderStyle,