style: Add a Zero trait that doesn't require Add, and use it in place of num_traits and IsZeroLength.

Use it to be consistent in InsetRect serialization and storage between Servo and
Gecko.

Differential Revision: https://phabricator.services.mozilla.com/D21493
This commit is contained in:
Emilio Cobos Álvarez 2019-02-28 19:03:03 +00:00
parent 4496411edc
commit 7d01114cbf
29 changed files with 179 additions and 186 deletions

View file

@ -27,6 +27,7 @@ use crate::values::generics::box_::VerticalAlign;
use crate::values::generics::grid::{TrackListValue, TrackSize}; use crate::values::generics::grid::{TrackListValue, TrackSize};
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage}; use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage};
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::Zero;
use app_units::Au; use app_units::Au;
use std::f32::consts::PI; use std::f32::consts::PI;
use style_traits::values::specified::AllowedNumericType; use style_traits::values::specified::AllowedNumericType;
@ -703,7 +704,6 @@ pub mod basic_shape {
let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]); let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]); let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
let round = other.mRadius; let round = other.mRadius;
let round = if round.all_zero() { None } else { Some(round) };
let rect = Rect::new( let rect = Rect::new(
t.expect("inset() offset should be a length, percentage, or calc value"), t.expect("inset() offset should be a length, percentage, or calc value"),
r.expect("inset() offset should be a length, percentage, or calc value"), r.expect("inset() offset should be a length, percentage, or calc value"),

View file

@ -19,7 +19,7 @@ use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::LengthPercentageOrAuto; use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative}; use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal}; use crate::values::{Auto, Either, None_, Normal};
use crate::Atom; use crate::{Atom, Zero};
use app_units::Au; use app_units::Au;
use cssparser::RGBA; use cssparser::RGBA;
use nsstring::{nsACString, nsCStr}; use nsstring::{nsACString, nsCStr};

View file

@ -10,6 +10,7 @@ use crate::gecko_bindings::structs::{nsCSSUnit, nsCSSValue};
use crate::gecko_bindings::structs::{nsCSSValueList, nsCSSValue_Array}; use crate::gecko_bindings::structs::{nsCSSValueList, nsCSSValue_Array};
use crate::gecko_string_cache::Atom; use crate::gecko_string_cache::Atom;
use crate::values::computed::{Angle, Length, LengthPercentage, Percentage}; use crate::values::computed::{Angle, Length, LengthPercentage, Percentage};
use crate::Zero;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};

View file

@ -244,3 +244,26 @@ impl CaseSensitivityExt for selectors::attr::CaseSensitivity {
} }
} }
} }
/// A trait pretty much similar to num_traits::Zero, but without the need of
/// implementing `Add`.
pub trait Zero {
/// Returns the zero value.
fn zero() -> Self;
/// Returns whether this value is zero.
fn is_zero(&self) -> bool;
}
impl<T> Zero for T
where
T: num_traits::Zero,
{
fn zero() -> Self {
<Self as num_traits::Zero>::zero()
}
fn is_zero(&self) -> bool {
<Self as num_traits::Zero>::is_zero(self)
}
}

View file

@ -21,9 +21,8 @@ use crate::stylesheets::Origin;
use crate::values::computed::{self, ToComputedValue}; use crate::values::computed::{self, ToComputedValue};
use crate::values::specified::{Integer, Length, Number, Resolution}; use crate::values::specified::{Integer, Length, Number, Resolution};
use crate::values::{serialize_atom_identifier, CSSFloat}; use crate::values::{serialize_atom_identifier, CSSFloat};
use crate::Atom; use crate::{Atom, Zero};
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use num_traits::Zero;
use std::cmp::{Ordering, PartialOrd}; use std::cmp::{Ordering, PartialOrd};
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};

View file

@ -4629,10 +4629,7 @@ fn set_style_svg_path(
inset.rect.2.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.3.to_gecko_style_coord(&mut shape.mCoordinates[3]); inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
shape.mRadius = match inset.round { shape.mRadius = inset.round;
Some(radius) => radius,
None => crate::values::computed::BorderRadius::zero(),
};
} }
BasicShape::Circle(circ) => { BasicShape::Circle(circ) => {
let shape = init_shape(${ident}, StyleBasicShapeType::Circle); let shape = init_shape(${ident}, StyleBasicShapeType::Circle);

View file

@ -19,6 +19,8 @@
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::values::specified::AllowQuirks; use crate::values::specified::AllowQuirks;
#[allow(unused_imports)] #[allow(unused_imports)]
use crate::Zero;
#[allow(unused_imports)]
use smallvec::SmallVec; use smallvec::SmallVec;
pub use crate::values::specified::${type} as SpecifiedValue; pub use crate::values::specified::${type} as SpecifiedValue;
pub mod computed_value { pub mod computed_value {

View file

@ -42,6 +42,7 @@ use crate::values::computed;
use crate::values::computed::NonNegativeLength; use crate::values::computed::NonNegativeLength;
use crate::values::serialize_atom_name; use crate::values::serialize_atom_name;
use crate::rule_tree::StrongRuleNode; use crate::rule_tree::StrongRuleNode;
use crate::Zero;
use self::computed_value_flags::*; use self::computed_value_flags::*;
use crate::str::{CssString, CssStringBorrow, CssStringWriter}; use crate::str::{CssString, CssStringBorrow, CssStringWriter};
@ -2585,7 +2586,7 @@ pub mod style_structs {
/// Whether the border-${side} property has nonzero width. /// Whether the border-${side} property has nonzero width.
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn border_${side}_has_nonzero_width(&self) -> bool { pub fn border_${side}_has_nonzero_width(&self) -> bool {
self.border_${side}_width != NonNegativeLength::zero() !self.border_${side}_width.is_zero()
} }
% endfor % endfor
% elif style_struct.name == "Font": % elif style_struct.name == "Font":
@ -2624,7 +2625,7 @@ pub mod style_structs {
/// Whether the outline-width property is non-zero. /// Whether the outline-width property is non-zero.
#[inline] #[inline]
pub fn outline_has_nonzero_width(&self) -> bool { pub fn outline_has_nonzero_width(&self) -> bool {
self.outline_width != NonNegativeLength::zero() !self.outline_width.is_zero()
} }
% elif style_struct.name == "Text": % elif style_struct.name == "Text":
/// Whether the text decoration has an underline. /// Whether the text decoration has an underline.

View file

@ -22,7 +22,7 @@ use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::transform::{self, Transform, TransformOperation}; use crate::values::generics::transform::{self, Transform, TransformOperation};
use crate::values::generics::transform::{Rotate, Scale, Translate}; use crate::values::generics::transform::{Rotate, Scale, Translate};
use crate::values::CSSFloat; use crate::values::CSSFloat;
use num_traits::Zero; use crate::Zero;
use std::cmp; use std::cmp;
// ------------------------------------ // ------------------------------------

View file

@ -6,7 +6,7 @@
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::CSSFloat; use crate::values::CSSFloat;
use num_traits::Zero; use crate::Zero;
use std::f64::consts::PI; use std::f64::consts::PI;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::{f32, f64}; use std::{f32, f64};

View file

@ -14,6 +14,7 @@ use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::values::generics::size::Size2D; use crate::values::generics::size::Size2D;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::Zero;
use app_units::Au; use app_units::Au;
pub use crate::values::specified::border::BorderImageRepeat; pub use crate::values::specified::border::BorderImageRepeat;
@ -75,39 +76,3 @@ impl BorderSpacing {
Au::from(*self.0.height()) Au::from(*self.0.height())
} }
} }
impl BorderCornerRadius {
/// Returns `0 0`.
pub fn zero() -> Self {
GenericBorderCornerRadius(Size2D::new(
NonNegativeLengthPercentage::zero(),
NonNegativeLengthPercentage::zero(),
))
}
}
impl BorderRadius {
/// Returns a `0` border radius.
pub fn zero() -> Self {
Self {
top_left: BorderCornerRadius::zero(),
top_right: BorderCornerRadius::zero(),
bottom_right: BorderCornerRadius::zero(),
bottom_left: BorderCornerRadius::zero(),
}
}
/// Returns whether all the values are `0px`.
pub fn all_zero(&self) -> bool {
fn all(corner: &BorderCornerRadius) -> bool {
fn is_zero(l: &NonNegativeLengthPercentage) -> bool {
*l == NonNegativeLengthPercentage::zero()
}
is_zero(corner.0.width()) && is_zero(corner.0.height())
}
all(&self.top_left) &&
all(&self.top_right) &&
all(&self.bottom_left) &&
all(&self.bottom_right)
}
}

View file

@ -12,11 +12,11 @@ use crate::values::generics::length as generics;
use crate::values::generics::length::{ use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize, GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
}; };
use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength; use crate::values::specified::length::ViewportPercentageLength;
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
use crate::values::{specified, Auto, CSSFloat, Either, Normal}; use crate::values::{specified, Auto, CSSFloat, Either, Normal};
use crate::Zero;
use app_units::Au; use app_units::Au;
use ordered_float::NotNan; use ordered_float::NotNan;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
@ -342,12 +342,6 @@ impl ToComputedValue for specified::CalcLengthPercentage {
} }
impl LengthPercentage { impl LengthPercentage {
#[inline]
#[allow(missing_docs)]
pub fn zero() -> LengthPercentage {
LengthPercentage::new(Length::new(0.), None)
}
/// 1px length value for SVG defaults /// 1px length value for SVG defaults
#[inline] #[inline]
pub fn one() -> LengthPercentage { pub fn one() -> LengthPercentage {
@ -442,9 +436,13 @@ impl ToComputedValue for specified::LengthPercentage {
} }
} }
impl IsZeroLength for LengthPercentage { impl Zero for LengthPercentage {
fn zero() -> Self {
LengthPercentage::new(Length::zero(), None)
}
#[inline] #[inline]
fn is_zero_length(&self) -> bool { fn is_zero(&self) -> bool {
self.is_definitely_zero() self.is_definitely_zero()
} }
} }
@ -453,12 +451,6 @@ impl IsZeroLength for LengthPercentage {
/// length-percentage or auto. /// length-percentage or auto.
macro_rules! computed_length_percentage_or_auto { macro_rules! computed_length_percentage_or_auto {
($inner:ty) => { ($inner:ty) => {
/// Returns the `0` value.
#[inline]
pub fn zero() -> Self {
generics::LengthPercentageOrAuto::LengthPercentage(<$inner>::zero())
}
/// Returns the used value. /// Returns the used value.
#[inline] #[inline]
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> { pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
@ -547,12 +539,6 @@ impl From<Au> for LengthPercentage {
} }
impl NonNegativeLengthPercentage { impl NonNegativeLengthPercentage {
/// Get zero value.
#[inline]
pub fn zero() -> Self {
NonNegative(LengthPercentage::zero())
}
/// Returns true if the computed value is absolute 0 or 0%. /// Returns true if the computed value is absolute 0 or 0%.
#[inline] #[inline]
pub fn is_definitely_zero(&self) -> bool { pub fn is_definitely_zero(&self) -> bool {
@ -656,12 +642,16 @@ impl CSSPixelLength {
pub fn clamp_to_non_negative(self) -> Self { pub fn clamp_to_non_negative(self) -> Self {
CSSPixelLength::new(self.0.max(0.)) CSSPixelLength::new(self.0.max(0.))
} }
}
/// Zero value impl Zero for CSSPixelLength {
#[inline] fn zero() -> Self {
pub fn zero() -> Self {
CSSPixelLength::new(0.) CSSPixelLength::new(0.)
} }
fn is_zero(&self) -> bool {
self.px() == 0.
}
} }
impl ToCss for CSSPixelLength { impl ToCss for CSSPixelLength {
@ -743,12 +733,6 @@ impl NonNegativeLength {
NonNegative(Length::new(px.max(0.))) NonNegative(Length::new(px.max(0.)))
} }
/// Return a zero value.
#[inline]
pub fn zero() -> Self {
Self::new(0.)
}
/// Return the pixel value of |NonNegativeLength|. /// Return the pixel value of |NonNegativeLength|.
#[inline] #[inline]
pub fn px(&self) -> CSSFloat { pub fn px(&self) -> CSSFloat {

View file

@ -7,6 +7,7 @@
use crate::values::animated::ToAnimatedValue; use crate::values::animated::ToAnimatedValue;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::values::{serialize_percentage, CSSFloat}; use crate::values::{serialize_percentage, CSSFloat};
use crate::Zero;
use std::fmt; use std::fmt;
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
@ -31,12 +32,6 @@ use style_traits::{CssWriter, ToCss};
pub struct Percentage(pub CSSFloat); pub struct Percentage(pub CSSFloat);
impl Percentage { impl Percentage {
/// 0%
#[inline]
pub fn zero() -> Self {
Percentage(0.)
}
/// 100% /// 100%
#[inline] #[inline]
pub fn hundred() -> Self { pub fn hundred() -> Self {
@ -56,6 +51,16 @@ impl Percentage {
} }
} }
impl Zero for Percentage {
fn zero() -> Self {
Percentage(0.)
}
fn is_zero(&self) -> bool {
self.0 == 0.
}
}
impl ToCss for Percentage { impl ToCss for Percentage {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
@ -69,12 +74,6 @@ impl ToCss for Percentage {
pub type NonNegativePercentage = NonNegative<Percentage>; pub type NonNegativePercentage = NonNegative<Percentage>;
impl NonNegativePercentage { impl NonNegativePercentage {
/// 0%
#[inline]
pub fn zero() -> Self {
NonNegative(Percentage::zero())
}
/// 100% /// 100%
#[inline] #[inline]
pub fn hundred() -> Self { pub fn hundred() -> Self {

View file

@ -11,6 +11,7 @@ use crate::values::computed::{Integer, LengthPercentage, Percentage};
use crate::values::generics::position::Position as GenericPosition; use crate::values::generics::position::Position as GenericPosition;
use crate::values::generics::position::ZIndex as GenericZIndex; use crate::values::generics::position::ZIndex as GenericZIndex;
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas}; pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas};
use crate::Zero;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};

View file

@ -10,6 +10,7 @@ use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage};
use crate::values::computed::{NonNegativeNumber, Number, Opacity}; use crate::values::computed::{NonNegativeNumber, Number, Opacity};
use crate::values::generics::svg as generic; use crate::values::generics::svg as generic;
use crate::values::RGBA; use crate::values::RGBA;
use crate::Zero;
pub use crate::values::specified::SVGPaintOrder; pub use crate::values::specified::SVGPaintOrder;

View file

@ -9,8 +9,8 @@ use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
use crate::values::animated::ToAnimatedZero; use crate::values::animated::ToAnimatedZero;
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage}; use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
use crate::values::generics::transform as generic; use crate::values::generics::transform as generic;
use crate::Zero;
use euclid::{Transform3D, Vector3D}; use euclid::{Transform3D, Vector3D};
use num_traits::Zero;
pub use crate::values::generics::transform::TransformStyle; pub use crate::values::generics::transform::TransformStyle;

View file

@ -11,6 +11,7 @@ use crate::values::generics::border::BorderRadius;
use crate::values::generics::position::Position; use crate::values::generics::position::Position;
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::values::specified::SVGPathData; use crate::values::specified::SVGPathData;
use crate::Zero;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
@ -127,7 +128,7 @@ pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
)] )]
pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> { pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
pub rect: Rect<LengthPercentage>, pub rect: Rect<LengthPercentage>,
pub round: Option<BorderRadius<NonNegativeLengthPercentage>>, pub round: BorderRadius<NonNegativeLengthPercentage>,
} }
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle> /// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
@ -311,7 +312,7 @@ impl<B, T, U> ToAnimatedZero for ShapeSource<B, T, U> {
impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength> impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength>
where where
Length: ToCss + PartialEq, Length: ToCss + PartialEq,
NonNegativeLength: ToCss + PartialEq, NonNegativeLength: ToCss + PartialEq + Zero,
{ {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
@ -319,9 +320,9 @@ where
{ {
dest.write_str("inset(")?; dest.write_str("inset(")?;
self.rect.to_css(dest)?; self.rect.to_css(dest)?;
if let Some(ref radius) = self.round { if !self.round.is_zero() {
dest.write_str(" round ")?; dest.write_str(" round ")?;
radius.to_css(dest)?; self.round.to_css(dest)?;
} }
dest.write_str(")") dest.write_str(")")
} }

View file

@ -6,6 +6,7 @@
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::values::generics::size::Size2D; use crate::values::generics::size::Size2D;
use crate::Zero;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
@ -65,6 +66,16 @@ impl<L> BorderCornerRadius<L> {
} }
} }
impl<L: Zero> Zero for BorderCornerRadius<L> {
fn zero() -> Self {
BorderCornerRadius(Size2D::zero())
}
fn is_zero(&self) -> bool {
self.0.is_zero()
}
}
/// A generic value for the `border-spacing` property. /// A generic value for the `border-spacing` property.
#[derive( #[derive(
Animate, Animate,
@ -135,12 +146,7 @@ impl<L> BorderRadius<L> {
bottom_left: bl, bottom_left: bl,
} }
} }
}
impl<L> BorderRadius<L>
where
L: PartialEq + ToCss,
{
/// Serialises two given rects following the syntax of the `border-radius`` /// Serialises two given rects following the syntax of the `border-radius``
/// property. /// property.
pub fn serialize_rects<W>( pub fn serialize_rects<W>(
@ -149,6 +155,7 @@ where
dest: &mut CssWriter<W>, dest: &mut CssWriter<W>,
) -> fmt::Result ) -> fmt::Result
where where
L: PartialEq + ToCss,
W: Write, W: Write,
{ {
widths.to_css(dest)?; widths.to_css(dest)?;
@ -160,6 +167,24 @@ where
} }
} }
impl<L: Zero> Zero for BorderRadius<L> {
fn zero() -> Self {
Self::new(
BorderCornerRadius::<L>::zero(),
BorderCornerRadius::<L>::zero(),
BorderCornerRadius::<L>::zero(),
BorderCornerRadius::<L>::zero(),
)
}
fn is_zero(&self) -> bool {
self.top_left.is_zero() &&
self.top_right.is_zero() &&
self.bottom_right.is_zero() &&
self.bottom_left.is_zero()
}
}
impl<L> ToCss for BorderRadius<L> impl<L> ToCss for BorderRadius<L>
where where
L: PartialEq + ToCss, L: PartialEq + ToCss,

View file

@ -7,8 +7,8 @@
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use crate::values::computed::ExtremumLength; use crate::values::computed::ExtremumLength;
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use num_traits::Zero;
use style_traits::ParseError; use style_traits::ParseError;
/// A `<length-percentage> | auto` value. /// A `<length-percentage> | auto` value.
@ -67,6 +67,19 @@ impl<LengthPercentage> LengthPercentageOrAuto<LengthPercentage> {
} }
} }
impl<LengthPercentage: Zero> Zero for LengthPercentageOrAuto<LengthPercentage> {
fn zero() -> Self {
LengthPercentageOrAuto::LengthPercentage(Zero::zero())
}
fn is_zero(&self) -> bool {
match *self {
LengthPercentageOrAuto::LengthPercentage(ref l) => l.is_zero(),
LengthPercentageOrAuto::Auto => false,
}
}
}
impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage> { impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage> {
fn parse<'i, 't>( fn parse<'i, 't>(
context: &ParserContext, context: &ParserContext,
@ -186,12 +199,15 @@ pub enum GenericLengthOrNumber<L, N> {
pub use self::GenericLengthOrNumber as LengthOrNumber; pub use self::GenericLengthOrNumber as LengthOrNumber;
impl<L, N> LengthOrNumber<L, N> { impl<L, N: Zero> Zero for LengthOrNumber<L, N> {
/// Returns `0`. fn zero() -> Self {
pub fn zero() -> Self LengthOrNumber::Number(Zero::zero())
where }
N: Zero,
{ fn is_zero(&self) -> bool {
LengthOrNumber::Number(num_traits::Zero::zero()) match *self {
LengthOrNumber::Number(ref n) => n.is_zero(),
LengthOrNumber::Length(..) => false,
}
} }
} }

View file

@ -8,8 +8,8 @@
use super::CustomIdent; use super::CustomIdent;
use crate::counter_style::{parse_counter_style_name, Symbols}; use crate::counter_style::{parse_counter_style_name, Symbols};
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use num_traits::Zero;
use std::ops::Add; use std::ops::Add;
use style_traits::{KeywordsCollectFn, ParseError}; use style_traits::{KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};

View file

@ -5,6 +5,7 @@
//! Generic type for CSS properties that are composed by two dimensions. //! Generic type for CSS properties that are composed by two dimensions.
use crate::parser::ParserContext; use crate::parser::ParserContext;
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
@ -84,3 +85,13 @@ where
Ok(()) Ok(())
} }
} }
impl<L: Zero> Zero for Size2D<L> {
fn zero() -> Self {
Self::new(L::zero(), L::zero())
}
fn is_zero(&self) -> bool {
self.width.is_zero() && self.height.is_zero()
}
}

View file

@ -10,9 +10,9 @@ use crate::values::specified::angle::Angle as SpecifiedAngle;
use crate::values::specified::length::Length as SpecifiedLength; use crate::values::specified::length::Length as SpecifiedLength;
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage; use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
use crate::values::{computed, CSSFloat}; use crate::values::{computed, CSSFloat};
use crate::Zero;
use app_units::Au; use app_units::Au;
use euclid::{self, Rect, Transform3D}; use euclid::{self, Rect, Transform3D};
use num_traits::Zero;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
@ -643,16 +643,7 @@ pub enum Translate<LengthPercentage, Length> {
Translate3D(LengthPercentage, LengthPercentage, Length), Translate3D(LengthPercentage, LengthPercentage, Length),
} }
/// A trait to check if this is a zero length. impl<LoP: ToCss + Zero, L: ToCss> ToCss for Translate<LoP, L> {
/// An alternative way is use num_traits::Zero. However, in order to implement num_traits::Zero,
/// we also have to implement Add, which may be complicated for LengthPercentage::Calc.
/// We could do this if other types also need it. If so, we could drop this trait.
pub trait IsZeroLength {
/// Returns true if this is a zero length.
fn is_zero_length(&self) -> bool;
}
impl<LoP: ToCss + IsZeroLength, L: ToCss> ToCss for Translate<LoP, L> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
W: fmt::Write, W: fmt::Write,
@ -670,7 +661,7 @@ impl<LoP: ToCss + IsZeroLength, L: ToCss> ToCss for Translate<LoP, L> {
Translate::None => dest.write_str("none"), Translate::None => dest.write_str("none"),
Translate::Translate(ref x, ref y) => { Translate::Translate(ref x, ref y) => {
x.to_css(dest)?; x.to_css(dest)?;
if !y.is_zero_length() { if !y.is_zero() {
dest.write_char(' ')?; dest.write_char(' ')?;
y.to_css(dest)?; y.to_css(dest)?;
} }

View file

@ -101,6 +101,11 @@ impl Angle {
} }
} }
/// Return `0deg`.
pub fn zero() -> Self {
Self::from_degrees(0.0, false)
}
/// Returns the value of the angle in degrees, mostly for `calc()`. /// Returns the value of the angle in degrees, mostly for `calc()`.
#[inline] #[inline]
pub fn degrees(&self) -> CSSFloat { pub fn degrees(&self) -> CSSFloat {
@ -113,12 +118,6 @@ impl Angle {
self.was_calc self.was_calc
} }
/// Returns `0deg`.
#[inline]
pub fn zero() -> Self {
Self::from_degrees(0.0, false)
}
/// Returns an `Angle` parsed from a `calc()` expression. /// Returns an `Angle` parsed from a `calc()` expression.
pub fn from_calc(degrees: CSSFloat) -> Self { pub fn from_calc(degrees: CSSFloat) -> Self {
Angle { Angle {

View file

@ -18,6 +18,7 @@ use crate::values::specified::position::{HorizontalPosition, Position, VerticalP
use crate::values::specified::url::SpecifiedUrl; use crate::values::specified::url::SpecifiedUrl;
use crate::values::specified::SVGPathData; use crate::values::specified::SVGPathData;
use crate::values::specified::{LengthPercentage, NonNegativeLengthPercentage}; use crate::values::specified::{LengthPercentage, NonNegativeLengthPercentage};
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
@ -202,9 +203,9 @@ impl InsetRect {
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, LengthPercentage::parse)?; let rect = Rect::parse_with(context, input, LengthPercentage::parse)?;
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() { let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
Some(BorderRadius::parse(context, input)?) BorderRadius::parse(context, input)?
} else { } else {
None BorderRadius::zero()
}; };
Ok(generic::InsetRect { rect, round }) Ok(generic::InsetRect { rect, round })
} }

View file

@ -15,6 +15,7 @@ use crate::values::generics::rect::Rect;
use crate::values::generics::size::Size2D; use crate::values::generics::size::Size2D;
use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthPercentage}; use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthPercentage};
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage}; use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};

View file

@ -20,6 +20,7 @@ use crate::values::specified::url::SpecifiedUrl;
use crate::values::specified::{Angle, NumberOrPercentage}; use crate::values::specified::{Angle, NumberOrPercentage};
#[cfg(not(feature = "gecko"))] #[cfg(not(feature = "gecko"))]
use crate::values::Impossible; use crate::values::Impossible;
use crate::Zero;
use cssparser::{self, BasicParseErrorKind, Parser, Token}; use cssparser::{self, BasicParseErrorKind, Parser, Token};
use style_traits::{ParseError, StyleParseErrorKind, ValueParseErrorKind}; use style_traits::{ParseError, StyleParseErrorKind, ValueParseErrorKind};

View file

@ -14,11 +14,11 @@ use crate::values::generics::length as generics;
use crate::values::generics::length::{ use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize, GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
}; };
use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::values::specified::calc::CalcNode; use crate::values::specified::calc::CalcNode;
use crate::values::specified::NonNegativeNumber; use crate::values::specified::NonNegativeNumber;
use crate::values::{Auto, CSSFloat, Either, Normal}; use crate::values::{Auto, CSSFloat, Either, Normal};
use crate::Zero;
use app_units::Au; use app_units::Au;
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use euclid::Size2D; use euclid::Size2D;
@ -477,21 +477,6 @@ impl NoCalcLength {
}) })
} }
#[inline]
/// Returns a `zero` length.
pub fn zero() -> NoCalcLength {
NoCalcLength::Absolute(AbsoluteLength::Px(0.))
}
#[inline]
/// Checks whether the length value is zero.
pub fn is_zero(&self) -> bool {
match *self {
NoCalcLength::Absolute(length) => length.is_zero(),
_ => false,
}
}
/// Get a px value without context. /// Get a px value without context.
#[inline] #[inline]
pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> { pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> {
@ -510,9 +495,12 @@ impl NoCalcLength {
impl SpecifiedValueInfo for NoCalcLength {} impl SpecifiedValueInfo for NoCalcLength {}
impl IsZeroLength for NoCalcLength { impl Zero for NoCalcLength {
#[inline] fn zero() -> Self {
fn is_zero_length(&self) -> bool { NoCalcLength::Absolute(AbsoluteLength::Px(0.))
}
fn is_zero(&self) -> bool {
match *self { match *self {
NoCalcLength::Absolute(v) => v.is_zero(), NoCalcLength::Absolute(v) => v.is_zero(),
NoCalcLength::FontRelative(v) => v.is_zero(), NoCalcLength::FontRelative(v) => v.is_zero(),
@ -584,12 +572,6 @@ impl Mul<CSSFloat> for ViewportPercentageLength {
} }
impl Length { impl Length {
#[inline]
/// Returns a `zero` length.
pub fn zero() -> Length {
Length::NoCalc(NoCalcLength::zero())
}
#[inline] #[inline]
fn parse_internal<'i, 't>( fn parse_internal<'i, 't>(
context: &ParserContext, context: &ParserContext,
@ -672,6 +654,21 @@ impl Parse for Length {
} }
} }
impl Zero for Length {
fn zero() -> Self {
Length::NoCalc(NoCalcLength::zero())
}
fn is_zero(&self) -> bool {
// FIXME(emilio): Seems a bit weird to treat calc() unconditionally as
// non-zero here?
match *self {
Length::NoCalc(ref l) => l.is_zero(),
Length::Calc(..) => false,
}
}
}
impl Length { impl Length {
/// Parses a length, with quirks. /// Parses a length, with quirks.
pub fn parse_quirky<'i, 't>( pub fn parse_quirky<'i, 't>(
@ -711,12 +708,6 @@ impl From<Length> for NonNegativeLength {
} }
impl NonNegativeLength { impl NonNegativeLength {
/// Returns a `zero` length.
#[inline]
pub fn zero() -> Self {
Length::zero().into()
}
/// Get an absolute length from a px value. /// Get an absolute length from a px value.
#[inline] #[inline]
pub fn from_px(px_value: CSSFloat) -> Self { pub fn from_px(px_value: CSSFloat) -> Self {
@ -801,12 +792,6 @@ impl Parse for LengthPercentage {
} }
impl LengthPercentage { impl LengthPercentage {
#[inline]
/// Returns a `zero` length.
pub fn zero() -> LengthPercentage {
LengthPercentage::Length(NoCalcLength::zero())
}
#[inline] #[inline]
/// Returns a `0%` value. /// Returns a `0%` value.
pub fn zero_percent() -> LengthPercentage { pub fn zero_percent() -> LengthPercentage {
@ -898,11 +883,14 @@ impl LengthPercentage {
} }
} }
impl IsZeroLength for LengthPercentage { impl Zero for LengthPercentage {
#[inline] fn zero() -> Self {
fn is_zero_length(&self) -> bool { LengthPercentage::Length(NoCalcLength::zero())
}
fn is_zero(&self) -> bool {
match *self { match *self {
LengthPercentage::Length(l) => l.is_zero_length(), LengthPercentage::Length(l) => l.is_zero(),
LengthPercentage::Percentage(p) => p.0 == 0.0, LengthPercentage::Percentage(p) => p.0 == 0.0,
LengthPercentage::Calc(_) => false, LengthPercentage::Calc(_) => false,
} }
@ -913,11 +901,6 @@ impl IsZeroLength for LengthPercentage {
pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>; pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>;
impl LengthPercentageOrAuto { impl LengthPercentageOrAuto {
/// Returns a value representing a `0` length.
pub fn zero() -> Self {
generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero())
}
/// Returns a value representing `0%`. /// Returns a value representing `0%`.
#[inline] #[inline]
pub fn zero_percent() -> Self { pub fn zero_percent() -> Self {
@ -943,11 +926,6 @@ pub type NonNegativeLengthPercentageOrAuto =
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>; generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
impl NonNegativeLengthPercentageOrAuto { impl NonNegativeLengthPercentageOrAuto {
/// Returns a value representing a `0` length.
pub fn zero() -> Self {
generics::LengthPercentageOrAuto::LengthPercentage(NonNegativeLengthPercentage::zero())
}
/// Returns a value representing `0%`. /// Returns a value representing `0%`.
#[inline] #[inline]
pub fn zero_percent() -> Self { pub fn zero_percent() -> Self {
@ -997,12 +975,6 @@ impl Parse for NonNegativeLengthPercentage {
} }
impl NonNegativeLengthPercentage { impl NonNegativeLengthPercentage {
#[inline]
/// Returns a `zero` length.
pub fn zero() -> Self {
NonNegative(LengthPercentage::zero())
}
#[inline] #[inline]
/// Returns a `0%` value. /// Returns a `0%` value.
pub fn zero_percent() -> Self { pub fn zero_percent() -> Self {

View file

@ -17,6 +17,7 @@ use crate::values::generics::position::ZIndex as GenericZIndex;
use crate::values::specified::transform::OriginComponent; use crate::values::specified::transform::OriginComponent;
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage}; use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
use crate::values::{Either, None_}; use crate::values::{Either, None_};
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use servo_arc::Arc; use servo_arc::Arc;

View file

@ -11,6 +11,7 @@ use crate::values::generics::transform as generic;
use crate::values::generics::transform::{Matrix, Matrix3D}; use crate::values::generics::transform::{Matrix, Matrix3D};
use crate::values::specified::position::{Side, X, Y}; use crate::values::specified::position::{Side, X, Y};
use crate::values::specified::{self, Angle, Integer, Length, LengthPercentage, Number}; use crate::values::specified::{self, Angle, Integer, Length, LengthPercentage, Number};
use crate::Zero;
use cssparser::Parser; use cssparser::Parser;
use style_traits::{ParseError, StyleParseErrorKind}; use style_traits::{ParseError, StyleParseErrorKind};