--- a/servo/components/style/gecko/values.rs
+++ b/servo/components/style/gecko/values.rs
@@ -12,19 +12,19 @@ use cssparser::RGBA;
use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord};
use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use media_queries::Device;
use nsstring::{nsACString, nsCString};
use std::cmp::max;
use values::{Auto, Either, ExtremumLength, None_, Normal};
use values::computed::{Angle, LengthOrPercentage, LengthOrPercentageOrAuto};
-use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage, NonNegativeAu};
+use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage};
use values::computed::{MaxLength, MozLength, Percentage};
-use values::computed::NonNegativeLengthOrPercentage;
+use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentage, NonNegativeNumber};
use values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
use values::generics::CounterStyleOrNone;
use values::generics::basic_shape::ShapeRadius;
use values::generics::gecko::ScrollSnapPoint;
use values::generics::grid::{TrackBreadth, TrackKeyword};
/// A trait that defines an interface to convert from and to `nsStyleCoord`s.
pub trait GeckoStyleCoordConvertible : Sized {
@@ -150,16 +150,26 @@ impl GeckoStyleCoordConvertible for NonN
self.0.to_gecko_style_coord(coord);
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
Au::from_gecko_style_coord(coord).map(NonNegativeAu)
}
}
+impl GeckoStyleCoordConvertible for NonNegativeNumber {
+ fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
+ self.0.to_gecko_style_coord(coord);
+ }
+
+ fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
+ Number::from_gecko_style_coord(coord).map(NonNegativeNumber)
+ }
+}
+
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
let value = match *self {
LengthOrPercentageOrAuto::Length(au) => CoordDataValue::Coord(au.0),
LengthOrPercentageOrAuto::Percentage(p) => CoordDataValue::Percent(p.0),
LengthOrPercentageOrAuto::Auto => CoordDataValue::Auto,
LengthOrPercentageOrAuto::Calc(calc) => CoordDataValue::Calc(calc.into()),
};
--- a/servo/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
@@ -2,17 +2,17 @@
* 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/. */
//! Rust helpers for Gecko's `nsCSSShadowItem`.
use app_units::Au;
use gecko::values::{convert_rgba_to_nscolor, convert_nscolor_to_rgba};
use gecko_bindings::structs::nsCSSShadowItem;
-use values::computed::Color;
+use values::computed::{Color, NonNegativeAu};
use values::computed::effects::{BoxShadow, SimpleShadow};
impl nsCSSShadowItem {
/// Sets this item from the given box shadow.
#[inline]
pub fn set_from_box_shadow(&mut self, shadow: BoxShadow) {
self.set_from_simple_shadow(shadow.base);
self.mSpread = shadow.spread.0;
@@ -22,29 +22,29 @@ impl nsCSSShadowItem {
/// Returns this item as a box shadow.
#[inline]
pub fn to_box_shadow(&self) -> BoxShadow {
BoxShadow {
base: SimpleShadow {
color: Color::rgba(convert_nscolor_to_rgba(self.mColor)),
horizontal: Au(self.mXOffset),
vertical: Au(self.mYOffset),
- blur: Au(self.mRadius),
+ blur: NonNegativeAu(Au(self.mRadius)),
},
spread: Au(self.mSpread),
inset: self.mInset,
}
}
/// Sets this item from the given simple shadow.
#[inline]
pub fn set_from_simple_shadow(&mut self, shadow: SimpleShadow) {
self.mXOffset = shadow.horizontal.0;
self.mYOffset = shadow.vertical.0;
- self.mRadius = shadow.blur.0;
+ self.mRadius = shadow.blur.value();
self.mSpread = 0;
self.mInset = false;
if shadow.color.is_currentcolor() {
// TODO handle currentColor
// https://bugzilla.mozilla.org/show_bug.cgi?id=760345
self.mHasColor = false;
self.mColor = 0;
} else {
@@ -57,12 +57,12 @@ impl nsCSSShadowItem {
#[inline]
pub fn to_simple_shadow(&self) -> SimpleShadow {
debug_assert_eq!(self.mSpread, 0);
debug_assert_eq!(self.mInset, false);
SimpleShadow {
color: Color::rgba(convert_nscolor_to_rgba(self.mColor)),
horizontal: Au(self.mXOffset),
vertical: Au(self.mYOffset),
- blur: Au(self.mRadius),
+ blur: NonNegativeAu(Au(self.mRadius)),
}
}
}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -3863,21 +3863,21 @@ fn static_assert() {
Gecko_ResetFilters(&mut self.gecko, v.len());
}
debug_assert_eq!(v.len(), self.gecko.mFilters.len());
for (servo, gecko_filter) in v.zip(self.gecko.mFilters.iter_mut()) {
match servo {
% for func in FILTER_FUNCTIONS:
${func}(factor) => fill_filter(NS_STYLE_FILTER_${func.upper()},
- CoordDataValue::Factor(factor),
+ CoordDataValue::Factor(factor.0),
gecko_filter),
% endfor
Blur(length) => fill_filter(NS_STYLE_FILTER_BLUR,
- CoordDataValue::Coord(length.0),
+ CoordDataValue::Coord(length.value()),
gecko_filter),
HueRotate(angle) => fill_filter(NS_STYLE_FILTER_HUE_ROTATE,
CoordDataValue::from(angle),
gecko_filter),
DropShadow(shadow) => {
gecko_filter.mType = NS_STYLE_FILTER_DROP_SHADOW;
@@ -3931,17 +3931,17 @@ fn static_assert() {
% for func in FILTER_FUNCTIONS:
NS_STYLE_FILTER_${func.upper()} => {
filters.push(Filter::${func}(
GeckoStyleCoordConvertible::from_gecko_style_coord(
&filter.mFilterParameter).unwrap()));
},
% endfor
NS_STYLE_FILTER_BLUR => {
- filters.push(Filter::Blur(Au::from_gecko_style_coord(
+ filters.push(Filter::Blur(NonNegativeAu::from_gecko_style_coord(
&filter.mFilterParameter).unwrap()));
},
NS_STYLE_FILTER_HUE_ROTATE => {
filters.push(Filter::HueRotate(
GeckoStyleCoordConvertible::from_gecko_style_coord(
&filter.mFilterParameter).unwrap()));
},
NS_STYLE_FILTER_DROP_SHADOW => {
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -3140,28 +3140,28 @@ fn add_weighted_filter_function_impl(fro
% endfor
% for func in [ 'Grayscale', 'Invert', 'Sepia' ]:
(&Filter::${func}(from_value), &Filter::${func}(to_value)) => {
Ok(Filter::${func}(add_weighted_with_initial_val(
&from_value,
&to_value,
self_portion,
other_portion,
- &0.0,
+ &NonNegativeNumber(0.0),
)?))
},
% endfor
% for func in [ 'Brightness', 'Contrast', 'Opacity', 'Saturate' ]:
(&Filter::${func}(from_value), &Filter::${func}(to_value)) => {
Ok(Filter::${func}(add_weighted_with_initial_val(
&from_value,
&to_value,
self_portion,
other_portion,
- &1.0,
+ &NonNegativeNumber(1.0),
)?))
},
% endfor
% if product == "gecko":
(&Filter::DropShadow(ref from_value), &Filter::DropShadow(ref to_value)) => {
Ok(Filter::DropShadow(from_value.add_weighted(
&to_value,
self_portion,
--- a/servo/components/style/values/animated/effects.rs
+++ b/servo/components/style/values/animated/effects.rs
@@ -7,18 +7,18 @@
use properties::animated_properties::{Animatable, IntermediateColor};
use properties::longhands::box_shadow::computed_value::T as ComputedBoxShadowList;
use properties::longhands::filter::computed_value::T as ComputedFilterList;
use properties::longhands::text_shadow::computed_value::T as ComputedTextShadowList;
use std::cmp;
#[cfg(not(feature = "gecko"))]
use values::Impossible;
use values::animated::{ToAnimatedValue, ToAnimatedZero};
-use values::computed::{Angle, Number};
-use values::computed::length::Length;
+use values::computed::{Angle, NonNegativeNumber};
+use values::computed::length::{Length, NonNegativeLength};
use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter;
use values::generics::effects::SimpleShadow as GenericSimpleShadow;
/// An animated value for the `box-shadow` property.
pub type BoxShadowList = ShadowList<BoxShadow>;
/// An animated value for the `text-shadow` property.
@@ -27,33 +27,33 @@ pub type TextShadowList = ShadowList<Sim
/// An animated value for shadow lists.
///
/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct ShadowList<Shadow>(Vec<Shadow>);
/// An animated value for a single `box-shadow`.
-pub type BoxShadow = GenericBoxShadow<IntermediateColor, Length, Length>;
+pub type BoxShadow = GenericBoxShadow<IntermediateColor, Length, NonNegativeLength, Length>;
/// An animated value for the `filter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct FilterList(pub Vec<Filter>);
/// An animated value for a single `filter`.
#[cfg(feature = "gecko")]
-pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow>;
+pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;
/// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))]
-pub type Filter = GenericFilter<Angle, Number, Length, Impossible>;
+pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;
/// An animated value for the `drop-shadow()` filter.
-pub type SimpleShadow = GenericSimpleShadow<IntermediateColor, Length, Length>;
+pub type SimpleShadow = GenericSimpleShadow<IntermediateColor, Length, NonNegativeLength>;
impl ToAnimatedValue for ComputedBoxShadowList {
type AnimatedValue = BoxShadowList;
#[inline]
fn to_animated_value(self) -> Self::AnimatedValue {
ShadowList(self.0.to_animated_value())
}
--- a/servo/components/style/values/computed/effects.rs
+++ b/servo/components/style/values/computed/effects.rs
@@ -1,28 +1,28 @@
/* 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 CSS values related to effects.
#[cfg(not(feature = "gecko"))]
use values::Impossible;
-use values::computed::{Angle, Number};
+use values::computed::{Angle, NonNegativeNumber};
use values::computed::color::Color;
-use values::computed::length::Length;
+use values::computed::length::{Length, NonNegativeLength};
use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter;
use values::generics::effects::SimpleShadow as GenericSimpleShadow;
/// A computed value for a single shadow of the `box-shadow` property.
-pub type BoxShadow = GenericBoxShadow<Color, Length, Length>;
+pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>;
/// A computed value for a single `filter`.
#[cfg(feature = "gecko")]
-pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow>;
+pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;
/// A computed value for a single `filter`.
#[cfg(not(feature = "gecko"))]
-pub type Filter = GenericFilter<Angle, Number, Length, Impossible>;
+pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;
/// A computed value for the `drop-shadow()` filter.
-pub type SimpleShadow = GenericSimpleShadow<Color, Length, Length>;
+pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>;
--- a/servo/components/style/values/generics/effects.rs
+++ b/servo/components/style/values/generics/effects.rs
@@ -7,19 +7,19 @@
use std::fmt;
use style_traits::values::{SequenceWriter, ToCss};
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedUrl;
/// A generic value for a single `box-shadow`.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue)]
-pub struct BoxShadow<Color, SizeLength, ShapeLength> {
+pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
/// The base shadow.
- pub base: SimpleShadow<Color, SizeLength, ShapeLength>,
+ pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
/// The spread radius.
pub spread: ShapeLength,
/// Whether this is an inset box shadow.
pub inset: bool,
}
/// A generic value for a single `filter`.
#[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))]
@@ -72,20 +72,24 @@ pub struct SimpleShadow<Color, SizeLengt
/// Horizontal radius.
pub horizontal: SizeLength,
/// Vertical radius.
pub vertical: SizeLength,
/// Blur radius.
pub blur: ShapeLength,
}
-impl<Color, SizeLength, ShapeLength> ToCss for BoxShadow<Color, SizeLength, ShapeLength>
+impl<Color, SizeLength, BlurShapeLength, ShapeLength> ToCss for BoxShadow<Color,
+ SizeLength,
+ BlurShapeLength,
+ ShapeLength>
where
Color: ToCss,
SizeLength: ToCss,
+ BlurShapeLength: ToCss,
ShapeLength: ToCss,
{
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
{
{
let mut writer = SequenceWriter::new(&mut *dest, " ");
--- a/servo/components/style/values/specified/effects.rs
+++ b/servo/components/style/values/specified/effects.rs
@@ -4,38 +4,38 @@
//! Specified types for CSS values related to effects.
use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseError};
#[cfg(not(feature = "gecko"))]
use values::Impossible;
-use values::computed::{Context, Number as ComputedNumber, ToComputedValue};
+use values::computed::{Context, NonNegativeNumber as ComputedNonNegativeNumber, ToComputedValue};
use values::computed::effects::BoxShadow as ComputedBoxShadow;
use values::computed::effects::SimpleShadow as ComputedSimpleShadow;
use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter;
use values::generics::effects::SimpleShadow as GenericSimpleShadow;
use values::specified::{Angle, NumberOrPercentage};
use values::specified::color::Color;
-use values::specified::length::Length;
+use values::specified::length::{Length, NonNegativeLength};
#[cfg(feature = "gecko")]
use values::specified::url::SpecifiedUrl;
/// A specified value for a single shadow of the `box-shadow` property.
-pub type BoxShadow = GenericBoxShadow<Option<Color>, Length, Option<Length>>;
+pub type BoxShadow = GenericBoxShadow<Option<Color>, Length, Option<NonNegativeLength>, Option<Length>>;
/// A specified value for a single `filter`.
#[cfg(feature = "gecko")]
-pub type Filter = GenericFilter<Angle, Factor, Length, SimpleShadow>;
+pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow>;
/// A specified value for a single `filter`.
#[cfg(not(feature = "gecko"))]
-pub type Filter = GenericFilter<Angle, Factor, Length, Impossible>;
+pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible>;
/// A value for the `<factor>` parts in `Filter`.
#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Factor(NumberOrPercentage);
impl Parse for Factor {
#[inline]
@@ -43,35 +43,35 @@ impl Parse for Factor {
context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<Self, ParseError<'i>> {
NumberOrPercentage::parse_non_negative(context, input).map(Factor)
}
}
impl ToComputedValue for Factor {
- type ComputedValue = ComputedNumber;
+ type ComputedValue = ComputedNonNegativeNumber;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
use values::computed::NumberOrPercentage;
match self.0.to_computed_value(context) {
- NumberOrPercentage::Number(n) => n,
- NumberOrPercentage::Percentage(p) => p.0,
+ NumberOrPercentage::Number(n) => ComputedNonNegativeNumber(n),
+ NumberOrPercentage::Percentage(p) => ComputedNonNegativeNumber(p.0),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- Factor(NumberOrPercentage::Number(ToComputedValue::from_computed_value(computed)))
+ Factor(NumberOrPercentage::Number(ToComputedValue::from_computed_value(&computed.0)))
}
}
/// A specified value for the `drop-shadow()` filter.
-pub type SimpleShadow = GenericSimpleShadow<Option<Color>, Length, Option<Length>>;
+pub type SimpleShadow = GenericSimpleShadow<Option<Color>, Length, Option<NonNegativeLength>>;
impl Parse for BoxShadow {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut lengths = None;
let mut color = None;
@@ -86,17 +86,17 @@ impl Parse for BoxShadow {
}
if lengths.is_none() {
let value = input.try::<_, _, ParseError>(|i| {
let horizontal = Length::parse(context, i)?;
let vertical = Length::parse(context, i)?;
let (blur, spread) = match i.try::<_, _, ParseError>(|i| Length::parse_non_negative(context, i)) {
Ok(blur) => {
let spread = i.try(|i| Length::parse(context, i)).ok();
- (Some(blur), spread)
+ (Some(NonNegativeLength(blur)), spread)
},
Err(_) => (None, None),
};
Ok((horizontal, vertical, blur, spread))
});
if let Ok(value) = value {
lengths = Some(value);
continue;
@@ -157,17 +157,17 @@ impl Parse for Filter {
{
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
return Ok(GenericFilter::Url(url));
}
}
let function = input.expect_function()?;
input.parse_nested_block(|i| {
try_match_ident_ignore_ascii_case! { function,
- "blur" => Ok(GenericFilter::Blur(Length::parse_non_negative(context, i)?)),
+ "blur" => Ok(GenericFilter::Blur(NonNegativeLength(Length::parse_non_negative(context, i)?))),
"brightness" => Ok(GenericFilter::Brightness(Factor::parse(context, i)?)),
"contrast" => Ok(GenericFilter::Contrast(Factor::parse(context, i)?)),
"grayscale" => Ok(GenericFilter::Grayscale(Factor::parse(context, i)?)),
"hue-rotate" => Ok(GenericFilter::HueRotate(Angle::parse(context, i)?)),
"invert" => Ok(GenericFilter::Invert(Factor::parse(context, i)?)),
"opacity" => Ok(GenericFilter::Opacity(Factor::parse(context, i)?)),
"saturate" => Ok(GenericFilter::Saturate(Factor::parse(context, i)?)),
"sepia" => Ok(GenericFilter::Sepia(Factor::parse(context, i)?)),
@@ -187,33 +187,33 @@ impl Parse for SimpleShadow {
let horizontal = Length::parse(context, input)?;
let vertical = Length::parse(context, input)?;
let blur = input.try(|i| Length::parse_non_negative(context, i)).ok();
let color = color.or_else(|| input.try(|i| Color::parse(context, i)).ok());
Ok(SimpleShadow {
color: color,
horizontal: horizontal,
vertical: vertical,
- blur: blur,
+ blur: blur.map(NonNegativeLength),
})
}
}
impl ToComputedValue for SimpleShadow {
type ComputedValue = ComputedSimpleShadow;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
ComputedSimpleShadow {
color:
self.color.as_ref().unwrap_or(&Color::CurrentColor).to_computed_value(context),
horizontal: self.horizontal.to_computed_value(context),
vertical: self.vertical.to_computed_value(context),
blur:
- self.blur.as_ref().unwrap_or(&Length::zero()).to_computed_value(context),
+ self.blur.as_ref().unwrap_or(&NonNegativeLength::zero()).to_computed_value(context),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
SimpleShadow {
color: Some(ToComputedValue::from_computed_value(&computed.color)),
horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -719,16 +719,24 @@ impl<T: Parse> Parse for Either<NonNegat
if let Ok(v) = input.try(|input| T::parse(context, input)) {
return Ok(Either::Second(v));
}
Length::parse_internal(context, input, AllowedLengthType::NonNegative, AllowQuirks::No)
.map(NonNegativeLength).map(Either::First)
}
}
+impl NonNegativeLength {
+ /// Returns a `zero` length.
+ #[inline]
+ pub fn zero() -> Self {
+ NonNegativeLength(Length::zero())
+ }
+}
+
/// Either a NonNegativeLength or the `normal` keyword.
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
/// Either a NonNegativeLength or the `auto` keyword.
pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
/// Either a NonNegativeLength or a NonNegativeNumber value.
pub type NonNegativeLengthOrNumber = Either<NonNegativeLength, NonNegativeNumber>;