Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: Make numbers keep track of whether they were specified as calc(). #16144

Merged
merged 13 commits into from Mar 27, 2017
Next

style: Make numbers keep track of whether they were specified as calc().

  • Loading branch information
emilio committed Mar 27, 2017
commit c7ce2ff4835f5d08eb3bbab8516356baf7537f2c
@@ -65,7 +65,8 @@ impl From<SpecifiedTimingFunction> for nsTimingFunction {
tf.set_as_step(nsTimingFunction_Type::StepEnd, steps);
},
SpecifiedTimingFunction::CubicBezier(p1, p2) => {
tf.set_as_cubic_bezier(p1, p2);
tf.set_as_cubic_bezier(Point2D::new(p1.x.value, p1.y.value),
Point2D::new(p2.x.value, p2.y.value));
},
SpecifiedTimingFunction::Keyword(keyword) => {
match keyword {
@@ -1283,7 +1283,7 @@ fn static_assert() {
use properties::longhands::font_size_adjust::computed_value::T;
match v {
T::None => self.gecko.mFont.sizeAdjust = -1.0 as f32,
T::Number(n) => self.gecko.mFont.sizeAdjust = n.0 as f32,
T::Number(n) => self.gecko.mFont.sizeAdjust = n,
}
}

@@ -1293,11 +1293,10 @@ fn static_assert() {

pub fn clone_font_size_adjust(&self) -> longhands::font_size_adjust::computed_value::T {
use properties::longhands::font_size_adjust::computed_value::T;
use values::specified::Number;

match self.gecko.mFont.sizeAdjust {
-1.0 => T::None,
_ => T::Number(Number(self.gecko.mFont.sizeAdjust)),
_ => T::Number(self.gecko.mFont.sizeAdjust),
}
}

@@ -223,7 +223,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",

#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(vec![Either::Second(Number(0.0))])
SpecifiedValue(vec![Either::Second(Number::new(0.0))])
}

impl ToComputedValue for SpecifiedValue {
@@ -486,7 +486,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",

#[inline]
pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(vec![SingleSpecifiedValue::Number(Number(1.0))])
SpecifiedValue(vec![SingleSpecifiedValue::Number(Number::new(1.0))])
}

impl ToComputedValue for SpecifiedValue {

Large diffs are not rendered by default.

@@ -655,30 +655,65 @@ ${helpers.single_keyword("font-variant-caps",

<%helpers:longhand products="gecko" name="font-size-adjust" animatable="True"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
use values::specified::Number;

impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue);

#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue {
None,
Number(Number),
Number(specified::Number),
}

impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self {
SpecifiedValue::None => dest.write_str("none"),
SpecifiedValue::Number(number) => number.to_css(dest),
}
}
}

impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;

fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
SpecifiedValue::None => computed_value::T::None,
SpecifiedValue::Number(ref n) => computed_value::T::Number(n.to_computed_value(context)),
}
}

fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed {
computed_value::T::None => SpecifiedValue::None,
computed_value::T::Number(ref v) => SpecifiedValue::Number(specified::Number::from_computed_value(v)),
}
}
}

pub mod computed_value {
use style_traits::ToCss;
use std::fmt;
use properties::animated_properties::Interpolate;
use values::specified::Number;
use std::fmt;
use style_traits::ToCss;
use values::CSSFloat;

pub use super::SpecifiedValue as T;
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
None,
Number(CSSFloat),
}

impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self {
T::None => dest.write_str("none"),
T::Number(number) => number.to_css(dest),
@@ -690,14 +725,15 @@ ${helpers.single_keyword("font-variant-caps",
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
match (*self, *other) {
(T::Number(ref number), T::Number(ref other)) =>
Ok(T::Number(Number(try!(number.0.interpolate(&other.0, time))))),
Ok(T::Number(try!(number.interpolate(other, time)))),
_ => Err(()),
}
}
}
}

#[inline] pub fn get_initial_value() -> computed_value::T {
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::None
}

@@ -10,7 +10,7 @@
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height">
use std::fmt;
use style_traits::ToCss;
use values::{CSSFloat, HasViewportPercentage};
use values::HasViewportPercentage;

impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool {
@@ -28,7 +28,7 @@
% if product == "gecko":
MozBlockHeight,
% endif
Number(CSSFloat),
Number(specified::Number),
LengthOrPercentage(specified::LengthOrPercentage),
}

@@ -40,7 +40,7 @@
SpecifiedValue::MozBlockHeight => dest.write_str("-moz-block-height"),
% endif
SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest),
SpecifiedValue::Number(number) => write!(dest, "{}", number),
SpecifiedValue::Number(number) => number.to_css(dest),
}
}
}
@@ -52,24 +52,24 @@
// parsed as a plain Number rather than a Length (0px); this matches the behaviour
// of all major browsers
input.try(specified::Number::parse_non_negative)
.map(|n| SpecifiedValue::Number(n.0))
.or_else(|()| {
input.try(specified::LengthOrPercentage::parse_non_negative)
.map(SpecifiedValue::LengthOrPercentage)
.map(SpecifiedValue::Number)
.or_else(|()| {
match try!(input.next()) {
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
Ok(SpecifiedValue::Normal)
}
% if product == "gecko":
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
Ok(SpecifiedValue::MozBlockHeight)
input.try(specified::LengthOrPercentage::parse_non_negative)
.map(SpecifiedValue::LengthOrPercentage)
.or_else(|()| {
match try!(input.next()) {
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
Ok(SpecifiedValue::Normal)
}
% if product == "gecko":
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
Ok(SpecifiedValue::MozBlockHeight)
}
% endif
_ => Err(()),
}
% endif
_ => Err(()),
}
})
})
})
}
pub mod computed_value {
use app_units::Au;
@@ -116,7 +116,7 @@
% if product == "gecko":
SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight,
% endif
SpecifiedValue::Number(value) => computed_value::T::Number(value),
SpecifiedValue::Number(value) => computed_value::T::Number(value.to_computed_value(context)),
SpecifiedValue::LengthOrPercentage(ref value) => {
match *value {
specified::LengthOrPercentage::Length(ref value) =>
@@ -144,7 +144,9 @@
% if product == "gecko":
computed_value::T::MozBlockHeight => SpecifiedValue::MozBlockHeight,
% endif
computed_value::T::Number(value) => SpecifiedValue::Number(value),
computed_value::T::Number(ref value) => {
SpecifiedValue::Number(specified::Number::from_computed_value(value))
},
computed_value::T::Length(au) => {
SpecifiedValue::LengthOrPercentage(specified::LengthOrPercentage::Length(
ToComputedValue::from_computed_value(&au)
@@ -70,8 +70,8 @@

if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(Longhands {
flex_grow: Number(0.0),
flex_shrink: Number(0.0),
flex_grow: Number::new(0.0),
flex_shrink: Number::new(0.0),
% if product == "gecko":
flex_basis: LengthOrPercentageOrAuto::Auto
% else:
@@ -105,8 +105,8 @@
return Err(())
}
Ok(Longhands {
flex_grow: grow.unwrap_or(Number(1.0)),
flex_shrink: shrink.unwrap_or(Number(1.0)),
flex_grow: grow.unwrap_or(Number::new(1.0)),
flex_shrink: shrink.unwrap_or(Number::new(1.0)),
% if product == "gecko":
flex_basis: basis.unwrap_or(LengthOrPercentageOrAuto::Length(NoCalcLength::zero()))
% else:
@@ -219,17 +219,15 @@ pub fn parse_integer(input: &mut Parser) -> Result<CSSInteger, ()> {
}

#[allow(missing_docs)]
pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
pub fn parse_number(input: &mut Parser) -> Result<Number, ()> {
use std::f32;

match try!(input.next()) {
Token::Number(ref value) => {
use std::f32;
if value.value.is_finite() {
Ok(value.value)
} else if value.value.is_sign_positive() {
Ok(f32::MAX)
} else {
Ok(f32::MIN)
}
Ok(Number {
value: value.value.min(f32::MAX).max(f32::MIN),
was_calc: false,
})
},
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
let ast = try!(input.parse_nested_block(|i| CalcLengthOrPercentage::parse_sum(i, CalcUnit::Number)));
@@ -245,7 +243,12 @@ pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
}

match result {
Some(result) => Ok(result),
Some(result) => {
Ok(Number {
value: result.min(f32::MAX).max(f32::MIN),
was_calc: true,
})
},
_ => Err(())
}
}
@@ -525,24 +528,39 @@ impl ToCss for Time {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Number(pub CSSFloat);
pub struct Number {
/// The numeric value itself.
pub value: CSSFloat,
/// Whether this came from a `calc()` expression. This is needed for
/// serialization purposes, since `calc(1)` should still serialize to
/// `calc(1)`, not just `1`.
was_calc: bool,
}

no_viewport_percentage!(Number);

impl Parse for Number {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
parse_number(input).map(Number)
parse_number(input)
}
}

impl Number {
fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result<Number, ()> {
match parse_number(input) {
Ok(value) if value >= min => Ok(Number(value)),
Ok(value) if value.value >= min => Ok(value),
_ => Err(()),
}
}

/// Returns a new number with the value `val`.
pub fn new(val: CSSFloat) -> Self {
Number {
value: val,
was_calc: false,
}
}

#[allow(missing_docs)]
pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
Number::parse_with_minimum(input, 0.0)
@@ -558,17 +576,27 @@ impl ToComputedValue for Number {
type ComputedValue = CSSFloat;

#[inline]
fn to_computed_value(&self, _: &Context) -> CSSFloat { self.0 }
fn to_computed_value(&self, _: &Context) -> CSSFloat { self.value }

#[inline]
fn from_computed_value(computed: &CSSFloat) -> Self {
Number(*computed)
Number {
value: *computed,
was_calc: false,
}
}
}

impl ToCss for Number {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.0.to_css(dest)
if self.was_calc {
dest.write_str("calc(")?;
}
self.value.to_css(dest)?;
if self.was_calc {
dest.write_str(")")?;
}
Ok(())
}
}

@@ -606,7 +634,7 @@ impl ToCss for NumberOrPercentage {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub struct Opacity(pub CSSFloat);
pub struct Opacity(Number);

no_viewport_percentage!(Opacity);

@@ -620,19 +648,13 @@ impl ToComputedValue for Opacity {
type ComputedValue = CSSFloat;

#[inline]
fn to_computed_value(&self, _: &Context) -> CSSFloat {
if self.0 < 0.0 {
0.0
} else if self.0 > 1.0 {
1.0
} else {
self.0
}
fn to_computed_value(&self, context: &Context) -> CSSFloat {
self.0.to_computed_value(context).min(1.0).max(0.0)
}

#[inline]
fn from_computed_value(computed: &CSSFloat) -> Self {
Opacity(*computed)
Opacity(Number::from_computed_value(computed))
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.