mirror of
https://github.com/servo/servo.git
synced 2025-08-07 22:45:34 +01:00
style: Add computed value ZeroToOneNumber.
Correctly handle clamping to 1 behavior of grayscale(), invert(), opacity() and sepia(). Differential Revision: https://phabricator.services.mozilla.com/D35509
This commit is contained in:
parent
9939c1ee07
commit
2fba62aba9
6 changed files with 132 additions and 73 deletions
|
@ -7,6 +7,7 @@
|
|||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::computed::effects::BoxShadow as ComputedBoxShadow;
|
||||
use crate::values::computed::effects::SimpleShadow as ComputedSimpleShadow;
|
||||
use crate::values::computed::ZeroToOneNumber as ComputedZeroToOneNumber;
|
||||
use crate::values::computed::NonNegativeNumber as ComputedNonNegativeNumber;
|
||||
use crate::values::computed::{Context, ToComputedValue};
|
||||
use crate::values::generics::effects::BoxShadow as GenericBoxShadow;
|
||||
|
@ -31,73 +32,85 @@ pub type BoxShadow =
|
|||
/// A specified value for a single `filter`.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub type SpecifiedFilter =
|
||||
GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow, SpecifiedUrl>;
|
||||
GenericFilter<Angle, NonNegativeFactor, ZeroToOneFactor, NonNegativeLength, SimpleShadow, SpecifiedUrl>;
|
||||
|
||||
/// A specified value for a single `filter`.
|
||||
#[cfg(feature = "servo")]
|
||||
pub type SpecifiedFilter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible, Impossible>;
|
||||
pub type SpecifiedFilter =
|
||||
GenericFilter<Angle, NonNegativeFactor, ZeroToOneFactor, NonNegativeLength, Impossible, Impossible>;
|
||||
|
||||
pub use self::SpecifiedFilter as Filter;
|
||||
|
||||
/// A value for the `<factor>` parts in `Filter`.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||
pub struct Factor(NumberOrPercentage);
|
||||
pub struct NonNegativeFactor(NumberOrPercentage);
|
||||
|
||||
impl Factor {
|
||||
/// Parse this factor but clamp to one if the value is over 100%.
|
||||
#[inline]
|
||||
pub fn parse_with_clamping_to_one<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Factor::parse(context, input).map(|v| v.clamp_to_one())
|
||||
}
|
||||
/// A value for the `<factor>` parts in `Filter` which clamps to one.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||
pub struct ZeroToOneFactor(NumberOrPercentage);
|
||||
|
||||
/// Clamp the value to 1 if the value is over 100%.
|
||||
#[inline]
|
||||
fn clamp_to_one(self) -> Self {
|
||||
match self.0 {
|
||||
NumberOrPercentage::Percentage(percent) => {
|
||||
Factor(NumberOrPercentage::Percentage(percent.clamp_to_hundred()))
|
||||
},
|
||||
NumberOrPercentage::Number(number) => {
|
||||
Factor(NumberOrPercentage::Number(number.clamp_to_one()))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Factor(NumberOrPercentage::Number(Number::new(1.0)))
|
||||
/// Clamp the value to 1 if the value is over 100%.
|
||||
#[inline]
|
||||
fn clamp_to_one(number: NumberOrPercentage) -> NumberOrPercentage {
|
||||
match number {
|
||||
NumberOrPercentage::Percentage(percent) => {
|
||||
NumberOrPercentage::Percentage(percent.clamp_to_hundred())
|
||||
},
|
||||
NumberOrPercentage::Number(number) => NumberOrPercentage::Number(number.clamp_to_one()),
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Factor {
|
||||
macro_rules! factor_impl_common {
|
||||
($ty:ty, $computed_ty:ty) => {
|
||||
impl $ty {
|
||||
fn one() -> Self {
|
||||
Self(NumberOrPercentage::Number(Number::new(1.)))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for $ty {
|
||||
type ComputedValue = $computed_ty;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
use crate::values::computed::NumberOrPercentage;
|
||||
match self.0.to_computed_value(context) {
|
||||
NumberOrPercentage::Number(n) => n.into(),
|
||||
NumberOrPercentage::Percentage(p) => p.0.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
Self(NumberOrPercentage::Number(
|
||||
ToComputedValue::from_computed_value(&computed.0),
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
factor_impl_common!(NonNegativeFactor, ComputedNonNegativeNumber);
|
||||
factor_impl_common!(ZeroToOneFactor, ComputedZeroToOneNumber);
|
||||
|
||||
impl Parse for NonNegativeFactor {
|
||||
#[inline]
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
NumberOrPercentage::parse_non_negative(context, input).map(Factor)
|
||||
NumberOrPercentage::parse_non_negative(context, input).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for Factor {
|
||||
type ComputedValue = ComputedNonNegativeNumber;
|
||||
|
||||
impl Parse for ZeroToOneFactor {
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
use crate::values::computed::NumberOrPercentage;
|
||||
match self.0.to_computed_value(context) {
|
||||
NumberOrPercentage::Number(n) => n.into(),
|
||||
NumberOrPercentage::Percentage(p) => p.0.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
Factor(NumberOrPercentage::Number(
|
||||
ToComputedValue::from_computed_value(&computed.0),
|
||||
))
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
NumberOrPercentage::parse_non_negative(context, input)
|
||||
.map(clamp_to_one)
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,19 +234,19 @@ impl Parse for Filter {
|
|||
.unwrap_or(Zero::zero()),
|
||||
)),
|
||||
"brightness" => Ok(GenericFilter::Brightness(
|
||||
i.try(|i| Factor::parse(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| NonNegativeFactor::parse(context, i))
|
||||
.unwrap_or(NonNegativeFactor::one()),
|
||||
)),
|
||||
"contrast" => Ok(GenericFilter::Contrast(
|
||||
i.try(|i| Factor::parse(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| NonNegativeFactor::parse(context, i))
|
||||
.unwrap_or(NonNegativeFactor::one()),
|
||||
)),
|
||||
"grayscale" => {
|
||||
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
|
||||
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-grayscale
|
||||
Ok(GenericFilter::Grayscale(
|
||||
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| ZeroToOneFactor::parse(context, i))
|
||||
.unwrap_or(ZeroToOneFactor::one()),
|
||||
))
|
||||
},
|
||||
"hue-rotate" => {
|
||||
|
@ -248,28 +261,28 @@ impl Parse for Filter {
|
|||
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
|
||||
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-invert
|
||||
Ok(GenericFilter::Invert(
|
||||
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| ZeroToOneFactor::parse(context, i))
|
||||
.unwrap_or(ZeroToOneFactor::one()),
|
||||
))
|
||||
},
|
||||
"opacity" => {
|
||||
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
|
||||
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-opacity
|
||||
Ok(GenericFilter::Opacity(
|
||||
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| ZeroToOneFactor::parse(context, i))
|
||||
.unwrap_or(ZeroToOneFactor::one()),
|
||||
))
|
||||
},
|
||||
"saturate" => Ok(GenericFilter::Saturate(
|
||||
i.try(|i| Factor::parse(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| NonNegativeFactor::parse(context, i))
|
||||
.unwrap_or(NonNegativeFactor::one()),
|
||||
)),
|
||||
"sepia" => {
|
||||
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
|
||||
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-sepia
|
||||
Ok(GenericFilter::Sepia(
|
||||
i.try(|i| Factor::parse_with_clamping_to_one(context, i))
|
||||
.unwrap_or(Factor::one()),
|
||||
i.try(|i| ZeroToOneFactor::parse(context, i))
|
||||
.unwrap_or(ZeroToOneFactor::one()),
|
||||
))
|
||||
},
|
||||
"drop-shadow" => Ok(GenericFilter::DropShadow(Parse::parse(context, i)?)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue