style: Derive more stuff for clip rects.

I feel a bit weird for using LenghtPercentageOrAuto to implement LengthOrAuto,
but I don't think much other code will use it so it seemed a bit better to me.

Differential Revision: https://phabricator.services.mozilla.com/D21863
This commit is contained in:
Emilio Cobos Álvarez 2019-03-06 21:37:48 +00:00
parent e723a5b7d6
commit e0b3e5f691
8 changed files with 143 additions and 254 deletions

View file

@ -3748,6 +3748,7 @@ fn static_assert() {
#[allow(non_snake_case)]
pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
use crate::values::Either;
use crate::values::generics::length::LengthPercentageOrAuto::*;
match v {
Either::Second(_auto) => {
@ -3757,15 +3758,21 @@ fn static_assert() {
self.gecko.mImageRegion.height = 0;
}
Either::First(rect) => {
self.gecko.mImageRegion.x = rect.left.map(Au::from).unwrap_or(Au(0)).0;
self.gecko.mImageRegion.y = rect.top.map(Au::from).unwrap_or(Au(0)).0;
self.gecko.mImageRegion.x = match rect.left {
LengthPercentage(v) => v.to_i32_au(),
Auto => 0,
};
self.gecko.mImageRegion.y = match rect.top {
LengthPercentage(v) => v.to_i32_au(),
Auto => 0,
};
self.gecko.mImageRegion.height = match rect.bottom {
Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
None => 0,
LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
Auto => 0,
};
self.gecko.mImageRegion.width = match rect.right {
Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
None => 0,
LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
Auto => 0,
};
}
}
@ -3774,6 +3781,7 @@ fn static_assert() {
#[allow(non_snake_case)]
pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T {
use crate::values::{Auto, Either};
use crate::values::generics::length::LengthPercentageOrAuto::*;
use crate::values::computed::ClipRect;
// There is no ideal way to detect auto type for structs::nsRect and its components, so
@ -3786,10 +3794,10 @@ fn static_assert() {
}
Either::First(ClipRect {
top: Some(Au(self.gecko.mImageRegion.y).into()),
right: Some(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
bottom: Some(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
left: Some(Au(self.gecko.mImageRegion.x).into()),
top: LengthPercentage(Au(self.gecko.mImageRegion.y).into()),
right: LengthPercentage(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
bottom: LengthPercentage(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
left: LengthPercentage(Au(self.gecko.mImageRegion.x).into()),
})
}
@ -3846,38 +3854,43 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
use crate::values::generics::length::LengthPercentageOrAuto::*;
use crate::values::Either;
match v {
Either::First(rect) => {
self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8;
if let Some(left) = rect.left {
self.gecko.mClip.x = left.to_i32_au();
} else {
self.gecko.mClip.x = 0;
self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
}
self.gecko.mClip.x = match rect.left {
LengthPercentage(l) => l.to_i32_au(),
Auto => {
self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
0
}
};
if let Some(top) = rect.top {
self.gecko.mClip.y = top.to_i32_au();
} else {
self.gecko.mClip.y = 0;
self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
}
self.gecko.mClip.y = match rect.top {
LengthPercentage(l) => l.to_i32_au(),
Auto => {
self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
0
}
};
if let Some(bottom) = rect.bottom {
self.gecko.mClip.height = (Au::from(bottom) - Au(self.gecko.mClip.y)).0;
} else {
self.gecko.mClip.height = 1 << 30; // NS_MAXSIZE
self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
}
self.gecko.mClip.height = match rect.bottom {
LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.y)).0,
Auto => {
self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
1 << 30 // NS_MAXSIZE
}
};
if let Some(right) = rect.right {
self.gecko.mClip.width = (Au::from(right) - Au(self.gecko.mClip.x)).0;
} else {
self.gecko.mClip.width = 1 << 30; // NS_MAXSIZE
self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
}
self.gecko.mClip.width = match rect.right {
LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.x)).0,
Auto => {
self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
1 << 30 // NS_MAXSIZE
}
};
},
Either::Second(_auto) => {
self.gecko.mClipFlags = NS_STYLE_CLIP_AUTO as u8;
@ -3904,42 +3917,42 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO;
use crate::values::generics::length::LengthPercentageOrAuto::*;
use crate::values::computed::{ClipRect, ClipRectOrAuto};
use crate::values::Either;
if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 {
ClipRectOrAuto::auto()
} else {
let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.x, 0);
None
} else {
Some(Au(self.gecko.mClip.x).into())
};
let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.y, 0);
None
} else {
Some(Au(self.gecko.mClip.y).into())
};
let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.height, 1 << 30); // NS_MAXSIZE
None
} else {
Some(Au(self.gecko.mClip.y + self.gecko.mClip.height).into())
};
let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.width, 1 << 30); // NS_MAXSIZE
None
} else {
Some(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
};
Either::First(ClipRect { top, right, bottom, left })
return ClipRectOrAuto::auto()
}
let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.x, 0);
Auto
} else {
LengthPercentage(Au(self.gecko.mClip.x).into())
};
let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.y, 0);
Auto
} else {
LengthPercentage(Au(self.gecko.mClip.y).into())
};
let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.height, 1 << 30); // NS_MAXSIZE
Auto
} else {
LengthPercentage(Au(self.gecko.mClip.y + self.gecko.mClip.height).into())
};
let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 {
debug_assert_eq!(self.gecko.mClip.width, 1 << 30); // NS_MAXSIZE
Auto
} else {
LengthPercentage(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
};
Either::First(ClipRect { top, right, bottom, left })
}
<%

View file

@ -802,29 +802,29 @@ impl ToAnimatedZero for Visibility {
impl Animate for ClipRect {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
use crate::values::computed::Length;
let animate_component = |this: &Option<Length>, other: &Option<Length>| {
match (this.animate(other, procedure)?, procedure) {
(None, Procedure::Interpolate { .. }) => Ok(None),
(None, _) => Err(()),
(result, _) => Ok(result),
use crate::values::computed::LengthOrAuto;
let animate_component = |this: &LengthOrAuto, other: &LengthOrAuto| {
let result = this.animate(other, procedure)?;
if let Procedure::Interpolate { .. } = procedure {
return Ok(result);
}
if result.is_auto() {
// FIXME(emilio): Why? A couple SMIL tests fail without this,
// but it seems extremely fishy.
return Err(());
}
Ok(result)
};
Ok(ClipRect {
top: animate_component(&self.top, &other.top)?,
right: animate_component(&self.right, &other.right)?,
top: animate_component(&self.top, &other.top)?,
right: animate_component(&self.right, &other.right)?,
bottom: animate_component(&self.bottom, &other.bottom)?,
left: animate_component(&self.left, &other.left)?,
left: animate_component(&self.left, &other.left)?,
})
}
}
impl ToAnimatedZero for ClipRect {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
}
<%
FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale',
'HueRotate', 'Invert', 'Opacity', 'Saturate',

View file

@ -9,8 +9,8 @@
${helpers.predefined_type(
"column-width",
"length::NonNegativeLengthOrAuto",
"Either::Second(Auto)",
initial_specified_value="Either::Second(Auto)",
"computed::length::NonNegativeLengthOrAuto::auto()",
initial_specified_value="specified::length::NonNegativeLengthOrAuto::auto()",
extra_prefixes="moz",
animation_value_type="NonNegativeLengthOrAuto",
servo_pref="layout.columns.enabled",

View file

@ -15,7 +15,7 @@ use crate::values::generics::length::{
use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength;
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
use crate::values::{specified, Auto, CSSFloat, Either, Normal};
use crate::values::{specified, CSSFloat, Either, Normal};
use crate::Zero;
use app_units::Au;
use ordered_float::NotNan;
@ -701,7 +701,10 @@ impl From<Au> for CSSPixelLength {
pub type Length = CSSPixelLength;
/// Either a computed `<length>` or the `auto` keyword.
pub type LengthOrAuto = Either<Length, Auto>;
pub type LengthOrAuto = generics::GenericLengthPercentageOrAuto<Length>;
/// Either a non-negative `<length>` or the `auto` keyword.
pub type NonNegativeLengthOrAuto = generics::GenericLengthPercentageOrAuto<NonNegativeLength>;
/// Either a computed `<length>` or a `<number>` value.
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
@ -779,9 +782,6 @@ impl From<NonNegativeLength> for Au {
}
}
/// Either a computed NonNegativeLength or the `auto` keyword.
pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
/// Either a computed NonNegativeLength or the `normal` keyword.
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;

View file

@ -10,7 +10,7 @@ use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
use super::generics::transform::IsParallelTo;
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
use super::specified;
use super::{CSSFloat, CSSInteger};
use crate::context::QuirksMode;
@ -27,8 +27,6 @@ use euclid::Size2D;
use std::cell::RefCell;
use std::cmp;
use std::f32;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
#[cfg(feature = "gecko")]
pub use self::align::{AlignContent, AlignItems, JustifyContent, JustifyItems, SelfAlignment};
@ -62,7 +60,7 @@ pub use self::gecko::ScrollSnapPoint;
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage, NonNegativeLengthOrNumber};
pub use self::length::{LengthPercentageOrAuto, MaxSize, Size};
pub use self::length::{LengthOrAuto, LengthPercentageOrAuto, MaxSize, Size};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;
@ -637,52 +635,8 @@ impl From<CSSInteger> for PositiveInteger {
}
}
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
/// A computed cliprect for clip and image-region
pub struct ClipRect {
pub top: Option<Length>,
pub right: Option<Length>,
pub bottom: Option<Length>,
pub left: Option<Length>,
}
impl ToCss for ClipRect {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
dest.write_str("rect(")?;
if let Some(top) = self.top {
top.to_css(dest)?;
dest.write_str(", ")?;
} else {
dest.write_str("auto, ")?;
}
if let Some(right) = self.right {
right.to_css(dest)?;
dest.write_str(", ")?;
} else {
dest.write_str("auto, ")?;
}
if let Some(bottom) = self.bottom {
bottom.to_css(dest)?;
dest.write_str(", ")?;
} else {
dest.write_str("auto, ")?;
}
if let Some(left) = self.left {
left.to_css(dest)?;
} else {
dest.write_str("auto")?;
}
dest.write_str(")")
}
}
/// rect(...)
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
/// rect(...) | auto
pub type ClipRectOrAuto = Either<ClipRect, Auto>;

View file

@ -212,3 +212,14 @@ impl<T: Zero> Zero for NonNegative<T> {
ToCss,
)]
pub struct GreaterThanOrEqualToOne<T>(pub T);
/// A clip rect for clip and image-region
#[allow(missing_docs)]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
#[css(function = "rect", comma)]
pub struct ClipRect<LengthOrAuto> {
pub top: LengthOrAuto,
pub right: LengthOrAuto,
pub bottom: LengthOrAuto,
pub left: LengthOrAuto,
}

View file

@ -17,7 +17,7 @@ use crate::values::generics::length::{
use crate::values::generics::NonNegative;
use crate::values::specified::calc::CalcNode;
use crate::values::specified::NonNegativeNumber;
use crate::values::{Auto, CSSFloat, Either, Normal};
use crate::values::{CSSFloat, Either, Normal};
use crate::Zero;
use app_units::Au;
use cssparser::{Parser, Token};
@ -729,9 +729,6 @@ impl NonNegativeLength {
}
}
/// Either a NonNegativeLength or the `auto` keyword.
pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
/// A `<length-percentage>` value. This can be either a `<length>`, a
/// `<percentage>`, or a combination of both via `calc()`.
///
@ -997,7 +994,25 @@ impl NonNegativeLengthPercentage {
pub type LengthOrNormal = Either<Length, Normal>;
/// Either a `<length>` or the `auto` keyword.
pub type LengthOrAuto = Either<Length, Auto>;
pub type LengthOrAuto = generics::LengthPercentageOrAuto<Length>;
impl LengthOrAuto {
/// Parses a length, allowing the unitless length quirk.
/// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
#[inline]
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
Self::parse_with(context, input, |context, input| {
Length::parse_quirky(context, input, allow_quirks)
})
}
}
/// Either a non-negative `<length>` or the `auto` keyword.
pub type NonNegativeLengthOrAuto = generics::LengthPercentageOrAuto<NonNegativeLength>;
/// Either a `<length>` or a `<number>`.
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;

View file

@ -11,7 +11,7 @@ use super::computed::{Context, ToComputedValue};
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
use super::generics::transform::IsParallelTo;
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
use super::{Auto, CSSFloat, CSSInteger, Either};
use crate::context::QuirksMode;
use crate::parser::{Parse, ParserContext};
@ -60,7 +60,7 @@ pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber, NonNegativeLengthOrNumber};
pub use self::length::{LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{MaxSize, Size};
pub use self::length::{NoCalcLength, ViewportPercentageLength};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
@ -605,99 +605,8 @@ pub type GridLine = GenericGridLine<Integer>;
/// `<grid-template-rows> | <grid-template-columns>`
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
/// rect(<top>, <left>, <bottom>, <right>) used by clip and image-region
#[css(function = "rect")]
pub struct ClipRect {
/// <top> (<length> | <auto>)
pub top: Option<Length>,
/// <right> (<length> | <auto>)
pub right: Option<Length>,
/// <bottom> (<length> | <auto>)
pub bottom: Option<Length>,
/// <left> (<length> | <auto>)
pub left: Option<Length>,
}
impl ToCss for ClipRect {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
dest.write_str("rect(")?;
if let Some(ref top) = self.top {
top.to_css(dest)?;
dest.write_str(", ")?;
} else {
dest.write_str("auto, ")?;
}
if let Some(ref right) = self.right {
right.to_css(dest)?;
dest.write_str(", ")?;
} else {
dest.write_str("auto, ")?;
}
if let Some(ref bottom) = self.bottom {
bottom.to_css(dest)?;
dest.write_str(", ")?;
} else {
dest.write_str("auto, ")?;
}
if let Some(ref left) = self.left {
left.to_css(dest)?;
} else {
dest.write_str("auto")?;
}
dest.write_str(")")?;
Ok(())
}
}
impl ToComputedValue for ClipRect {
type ComputedValue = super::computed::ClipRect;
#[inline]
fn to_computed_value(&self, context: &Context) -> super::computed::ClipRect {
super::computed::ClipRect {
top: self.top.as_ref().map(|top| top.to_computed_value(context)),
right: self
.right
.as_ref()
.map(|right| right.to_computed_value(context)),
bottom: self
.bottom
.as_ref()
.map(|bottom| bottom.to_computed_value(context)),
left: self
.left
.as_ref()
.map(|left| left.to_computed_value(context)),
}
}
#[inline]
fn from_computed_value(computed: &super::computed::ClipRect) -> Self {
ClipRect {
top: computed
.top
.map(|top| ToComputedValue::from_computed_value(&top)),
right: computed
.right
.map(|right| ToComputedValue::from_computed_value(&right)),
bottom: computed
.bottom
.map(|bottom| ToComputedValue::from_computed_value(&bottom)),
left: computed
.left
.map(|left| ToComputedValue::from_computed_value(&left)),
}
}
}
/// rect(...)
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
impl Parse for ClipRect {
fn parse<'i, 't>(
@ -715,25 +624,16 @@ impl ClipRect {
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
use crate::values::specified::Length;
input.expect_function_matching("rect")?;
fn parse_argument<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Option<Length>, ParseError<'i>> {
if input
.try(|input| input.expect_ident_matching("auto"))
.is_ok()
{
Ok(None)
} else {
Length::parse_quirky(context, input, allow_quirks).map(Some)
}
) -> Result<LengthOrAuto, ParseError<'i>> {
LengthOrAuto::parse_quirky(context, input, allow_quirks)
}
input.expect_function_matching("rect")?;
input.parse_nested_block(|input| {
let top = parse_argument(context, input, allow_quirks)?;
let right;
@ -751,12 +651,8 @@ impl ClipRect {
bottom = parse_argument(context, input, allow_quirks)?;
left = parse_argument(context, input, allow_quirks)?;
}
Ok(ClipRect {
top: top,
right: right,
bottom: bottom,
left: left,
})
Ok(ClipRect { top, right, bottom, left })
})
}
}