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

Use generics for the vertical-align property

<!-- 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/18301)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-08-31 09:41:50 -05:00 committed by GitHub
commit 174c37fddd
13 changed files with 202 additions and 178 deletions

View file

@ -12,13 +12,14 @@ use app_units::Au;
use gecko::values::{convert_rgba_to_nscolor, GeckoStyleCoordConvertible};
use gecko_bindings::bindings::{Gecko_CreateGradient, Gecko_SetGradientImageValue, Gecko_SetLayerImageImageValue};
use gecko_bindings::bindings::{Gecko_InitializeImageCropRect, Gecko_SetImageElement};
use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage};
use gecko_bindings::structs::{nsresult, SheetType};
use gecko_bindings::structs::{self, nsCSSUnit, nsStyleCoord_CalcValue};
use gecko_bindings::structs::{nsStyleImage, nsresult, SheetType};
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use std::f32::consts::PI;
use stylesheets::{Origin, RulesMutateError};
use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, Percentage};
use values::generics::box_::VerticalAlign;
use values::generics::grid::TrackSize;
use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
use values::generics::rect::Rect;
@ -920,6 +921,26 @@ impl<T> Rect<T> where T: GeckoStyleCoordConvertible {
}
}
impl<L> VerticalAlign<L> {
/// Converts an enumerated value coming from Gecko to a `VerticalAlign<L>`.
pub fn from_gecko_keyword(value: u32) -> Self {
match value {
structs::NS_STYLE_VERTICAL_ALIGN_BASELINE => VerticalAlign::Baseline,
structs::NS_STYLE_VERTICAL_ALIGN_SUB => VerticalAlign::Sub,
structs::NS_STYLE_VERTICAL_ALIGN_SUPER => VerticalAlign::Super,
structs::NS_STYLE_VERTICAL_ALIGN_TOP => VerticalAlign::Top,
structs::NS_STYLE_VERTICAL_ALIGN_TEXT_TOP => VerticalAlign::TextTop,
structs::NS_STYLE_VERTICAL_ALIGN_MIDDLE => VerticalAlign::Middle,
structs::NS_STYLE_VERTICAL_ALIGN_BOTTOM => VerticalAlign::Bottom,
structs::NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM => VerticalAlign::TextBottom,
structs::NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE => {
VerticalAlign::MozMiddleWithBaseline
},
_ => panic!("unexpected enumerated value for vertical-align"),
}
}
}
/// Convert to String from given chars pointer.
pub unsafe fn string_from_chars_pointer(p: *const u16) -> String {
use std::slice;

View file

@ -2904,33 +2904,41 @@ fn static_assert() {
}
pub fn set_vertical_align(&mut self, v: longhands::vertical_align::computed_value::T) {
<% keyword = data.longhands_by_name["vertical-align"].keyword %>
use properties::longhands::vertical_align::computed_value::T;
// FIXME: Align binary representations and ditch |match| for cast + static_asserts
match v {
% for value in keyword.values_for('gecko'):
T::${to_rust_ident(value)} =>
self.gecko.mVerticalAlign.set_value(
CoordDataValue::Enumerated(structs::${keyword.gecko_constant(value)})),
% endfor
T::LengthOrPercentage(v) => self.gecko.mVerticalAlign.set(v),
}
use values::generics::box_::VerticalAlign;
let value = match v {
VerticalAlign::Baseline => structs::NS_STYLE_VERTICAL_ALIGN_BASELINE,
VerticalAlign::Sub => structs::NS_STYLE_VERTICAL_ALIGN_SUB,
VerticalAlign::Super => structs::NS_STYLE_VERTICAL_ALIGN_SUPER,
VerticalAlign::Top => structs::NS_STYLE_VERTICAL_ALIGN_TOP,
VerticalAlign::TextTop => structs::NS_STYLE_VERTICAL_ALIGN_TEXT_TOP,
VerticalAlign::Middle => structs::NS_STYLE_VERTICAL_ALIGN_MIDDLE,
VerticalAlign::Bottom => structs::NS_STYLE_VERTICAL_ALIGN_BOTTOM,
VerticalAlign::TextBottom => structs::NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM,
VerticalAlign::MozMiddleWithBaseline => {
structs::NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
},
VerticalAlign::Length(length) => {
self.gecko.mVerticalAlign.set(length);
return;
},
};
self.gecko.mVerticalAlign.set_value(CoordDataValue::Enumerated(value));
}
pub fn clone_vertical_align(&self) -> longhands::vertical_align::computed_value::T {
use properties::longhands::vertical_align::computed_value::T;
use values::computed::LengthOrPercentage;
use values::generics::box_::VerticalAlign;
match self.gecko.mVerticalAlign.as_value() {
% for value in keyword.values_for('gecko'):
CoordDataValue::Enumerated(structs::${keyword.gecko_constant(value)}) => T::${to_rust_ident(value)},
% endfor
CoordDataValue::Enumerated(_) => panic!("Unexpected enum variant for vertical-align"),
_ => {
let v = LengthOrPercentage::from_gecko_style_coord(&self.gecko.mVerticalAlign)
.expect("Expected length or percentage for vertical-align");
T::LengthOrPercentage(v)
}
let gecko = &self.gecko.mVerticalAlign;
match gecko.as_value() {
CoordDataValue::Enumerated(value) => VerticalAlign::from_gecko_keyword(value),
_ => {
VerticalAlign::Length(
LengthOrPercentage::from_gecko_style_coord(gecko).expect(
"expected <length-percentage> for vertical-align",
),
)
},
}
}

View file

@ -24,7 +24,6 @@ use properties::longhands::line_height::computed_value::T as LineHeight;
use properties::longhands::transform::computed_value::ComputedMatrix;
use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
use properties::longhands::transform::computed_value::T as TransformList;
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
use properties::longhands::visibility::computed_value::T as Visibility;
#[cfg(feature = "gecko")] use properties::{PropertyId, PropertyDeclarationId, LonghandId};
#[cfg(feature = "gecko")] use properties::{ShorthandId};
@ -787,11 +786,6 @@ impl ToAnimatedZero for Visibility {
}
}
impl ToAnimatedZero for VerticalAlign {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
impl Animate for CalcLengthOrPercentage {
#[inline]

View file

@ -307,125 +307,15 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
</%helpers:longhand>
<%helpers:longhand name="vertical-align" animation_value_type="ComputedValue"
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align">
use std::fmt;
use style_traits::ToCss;
use values::specified::AllowQuirks;
<% vertical_align = data.longhands_by_name["vertical-align"] %>
<% vertical_align.keyword = Keyword("vertical-align",
"baseline sub super top text-top middle bottom text-bottom",
extra_gecko_values="-moz-middle-with-baseline") %>
<% vertical_align_keywords = vertical_align.keyword.values_for(product) %>
${helpers.gecko_keyword_conversion(vertical_align.keyword)}
/// The `vertical-align` value.
#[allow(non_camel_case_types)]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
% for keyword in vertical_align_keywords:
${to_rust_ident(keyword)},
% endfor
LengthOrPercentage(specified::LengthOrPercentage),
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
% for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
% endfor
SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest),
}
}
}
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
/// | <percentage> | <length>
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
if let Ok(lop) = input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes)) {
return Ok(SpecifiedValue::LengthOrPercentage(lop));
}
try_match_ident_ignore_ascii_case! { input.expect_ident()?,
% for keyword in vertical_align_keywords:
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
% endfor
}
}
/// The computed value for `vertical-align`.
pub mod computed_value {
use std::fmt;
use style_traits::ToCss;
use values::computed;
/// The keywords are the same, and the `LengthOrPercentage` is computed
/// here.
#[allow(non_camel_case_types)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
pub enum T {
% for keyword in vertical_align_keywords:
#[animation(error)] // only animatable as a length
${to_rust_ident(keyword)},
% endfor
LengthOrPercentage(computed::LengthOrPercentage),
}
impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
% for keyword in vertical_align_keywords:
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
% endfor
T::LengthOrPercentage(ref value) => value.to_css(dest),
}
}
}
}
/// The initial computed value for `vertical-align`.
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::baseline
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
match *self {
% for keyword in vertical_align_keywords:
SpecifiedValue::${to_rust_ident(keyword)} => {
computed_value::T::${to_rust_ident(keyword)}
}
% endfor
SpecifiedValue::LengthOrPercentage(ref value) =>
computed_value::T::LengthOrPercentage(value.to_computed_value(context)),
}
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed {
% for keyword in vertical_align_keywords:
computed_value::T::${to_rust_ident(keyword)} => {
SpecifiedValue::${to_rust_ident(keyword)}
}
% endfor
computed_value::T::LengthOrPercentage(value) =>
SpecifiedValue::LengthOrPercentage(
ToComputedValue::from_computed_value(&value)
),
}
}
}
</%helpers:longhand>
${helpers.predefined_type(
"vertical-align",
"VerticalAlign",
"computed::VerticalAlign::baseline()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align",
)}
// CSS 2.1, Section 11 - Visual effects

View file

@ -0,0 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Computed types for box properties.
use values::computed::length::LengthOrPercentage;
use values::generics::box_::VerticalAlign as GenericVerticalAlign;
/// A computed value for the `vertical-align` property.
pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>;

View file

@ -34,6 +34,7 @@ pub use self::angle::Angle;
pub use self::background::BackgroundSize;
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
pub use self::border::{BorderRadius, BorderCornerRadius};
pub use self::box_::VerticalAlign;
pub use self::color::{Color, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
pub use self::flex::FlexBasis;
@ -60,6 +61,8 @@ pub mod angle;
pub mod background;
pub mod basic_shape;
pub mod border;
#[path = "box.rs"]
pub mod box_;
pub mod color;
pub mod effects;
pub mod flex;

View file

@ -0,0 +1,49 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Generic types for box properties.
use values::animated::ToAnimatedZero;
/// A generic value for the `vertical-align` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
#[derive(ToComputedValue, ToCss)]
pub enum VerticalAlign<LengthOrPercentage> {
/// `baseline`
Baseline,
/// `sub`
Sub,
/// `super`
Super,
/// `top`
Top,
/// `text-top`
TextTop,
/// `middle`
Middle,
/// `bottom`
Bottom,
/// `text-bottom`
TextBottom,
/// `-moz-middle-with-baseline`
#[cfg(feature = "gecko")]
MozMiddleWithBaseline,
/// `<length-percentage>`
Length(LengthOrPercentage),
}
impl<L> VerticalAlign<L> {
/// Returns `baseline`.
#[inline]
pub fn baseline() -> Self {
VerticalAlign::Baseline
}
}
impl<L> ToAnimatedZero for VerticalAlign<L> {
fn to_animated_zero(&self) -> Result<Self, ()> {
Err(())
}
}

View file

@ -15,6 +15,8 @@ use super::CustomIdent;
pub mod background;
pub mod basic_shape;
pub mod border;
#[path = "box.rs"]
pub mod box_;
pub mod effects;
pub mod flex;
#[cfg(feature = "gecko")]

View file

@ -0,0 +1,41 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Specified types for box properties.
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::ParseError;
use values::generics::box_::VerticalAlign as GenericVerticalAlign;
use values::specified::AllowQuirks;
use values::specified::length::LengthOrPercentage;
/// A specified value for the `vertical-align` property.
pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>;
impl Parse for VerticalAlign {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes)) {
return Ok(GenericVerticalAlign::Length(lop));
}
try_match_ident_ignore_ascii_case! { input.expect_ident()?,
"baseline" => Ok(GenericVerticalAlign::Baseline),
"sub" => Ok(GenericVerticalAlign::Sub),
"super" => Ok(GenericVerticalAlign::Super),
"top" => Ok(GenericVerticalAlign::Top),
"text-top" => Ok(GenericVerticalAlign::TextTop),
"middle" => Ok(GenericVerticalAlign::Middle),
"bottom" => Ok(GenericVerticalAlign::Bottom),
"text-bottom" => Ok(GenericVerticalAlign::TextBottom),
#[cfg(feature = "gecko")]
"-moz-middle-with-baseline" => {
Ok(GenericVerticalAlign::MozMiddleWithBaseline)
},
}
}
}

View file

@ -31,6 +31,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify
pub use self::background::BackgroundSize;
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
pub use self::box_::VerticalAlign;
pub use self::color::{Color, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
pub use self::flex::FlexBasis;
@ -60,6 +61,8 @@ pub mod angle;
pub mod background;
pub mod basic_shape;
pub mod border;
#[path = "box.rs"]
pub mod box_;
pub mod calc;
pub mod color;
pub mod effects;