mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Respect calc for percentages.
This commit is contained in:
parent
465e6f14fe
commit
310be02ba8
28 changed files with 308 additions and 176 deletions
|
@ -14,9 +14,9 @@ use std::fmt;
|
|||
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
|
||||
use style_traits::values::specified::AllowedLengthType;
|
||||
use values::{CSSInteger, CSSFloat};
|
||||
use values::computed;
|
||||
use values::specified::{Angle, Time};
|
||||
use values::specified::length::{FontRelativeLength, NoCalcLength};
|
||||
use values::specified::length::{Percentage, ViewportPercentageLength};
|
||||
use values::specified::length::{FontRelativeLength, NoCalcLength, ViewportPercentageLength};
|
||||
|
||||
/// A node inside a `Calc` expression's AST.
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -52,6 +52,8 @@ pub enum CalcUnit {
|
|||
Integer,
|
||||
/// `<length>`
|
||||
Length,
|
||||
/// `<percentage>`
|
||||
Percentage,
|
||||
/// `<length> | <percentage>`
|
||||
LengthOrPercentage,
|
||||
/// `<angle>`
|
||||
|
@ -75,7 +77,7 @@ pub struct CalcLengthOrPercentage {
|
|||
pub ex: Option<CSSFloat>,
|
||||
pub ch: Option<CSSFloat>,
|
||||
pub rem: Option<CSSFloat>,
|
||||
pub percentage: Option<Percentage>,
|
||||
pub percentage: Option<computed::Percentage>,
|
||||
#[cfg(feature = "gecko")]
|
||||
pub mozmm: Option<CSSFloat>,
|
||||
}
|
||||
|
@ -146,9 +148,8 @@ impl CalcNode {
|
|||
fn parse_one<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
expected_unit: CalcUnit)
|
||||
-> Result<Self, ParseError<'i>>
|
||||
{
|
||||
expected_unit: CalcUnit
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
match (input.next()?, expected_unit) {
|
||||
(Token::Number { value, .. }, _) => Ok(CalcNode::Number(value)),
|
||||
(Token::Dimension { value, ref unit, .. }, CalcUnit::Length) |
|
||||
|
@ -167,7 +168,8 @@ impl CalcNode {
|
|||
.map(CalcNode::Time)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
(Token::Percentage { unit_value, .. }, CalcUnit::LengthOrPercentage) => {
|
||||
(Token::Percentage { unit_value, .. }, CalcUnit::LengthOrPercentage) |
|
||||
(Token::Percentage { unit_value, .. }, CalcUnit::Percentage) => {
|
||||
Ok(CalcNode::Percentage(unit_value))
|
||||
}
|
||||
(Token::ParenthesisBlock, _) => {
|
||||
|
@ -283,6 +285,44 @@ impl CalcNode {
|
|||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Tries to simplify this expression into a `<percentage>` value.
|
||||
fn to_percentage(&self) -> Result<CSSFloat, ()> {
|
||||
Ok(match *self {
|
||||
CalcNode::Percentage(percentage) => percentage,
|
||||
CalcNode::Sub(ref a, ref b) => {
|
||||
a.to_percentage()? - b.to_percentage()?
|
||||
}
|
||||
CalcNode::Sum(ref a, ref b) => {
|
||||
a.to_percentage()? + b.to_percentage()?
|
||||
}
|
||||
CalcNode::Mul(ref a, ref b) => {
|
||||
match a.to_percentage() {
|
||||
Ok(lhs) => {
|
||||
let rhs = b.to_number()?;
|
||||
lhs * rhs
|
||||
}
|
||||
Err(..) => {
|
||||
let lhs = a.to_number()?;
|
||||
let rhs = b.to_percentage()?;
|
||||
lhs * rhs
|
||||
}
|
||||
}
|
||||
}
|
||||
CalcNode::Div(ref a, ref b) => {
|
||||
let lhs = a.to_percentage()?;
|
||||
let rhs = b.to_number()?;
|
||||
if rhs == 0. {
|
||||
return Err(())
|
||||
}
|
||||
lhs / rhs
|
||||
}
|
||||
CalcNode::Number(..) |
|
||||
CalcNode::Length(..) |
|
||||
CalcNode::Angle(..) |
|
||||
CalcNode::Time(..) => return Err(()),
|
||||
})
|
||||
}
|
||||
|
||||
/// Puts this `<length>` or `<percentage>` into `ret`, or error.
|
||||
///
|
||||
/// `factor` is the sign or multiplicative factor to account for the sign
|
||||
|
@ -295,7 +335,7 @@ impl CalcNode {
|
|||
{
|
||||
match *self {
|
||||
CalcNode::Percentage(pct) => {
|
||||
ret.percentage = Some(Percentage(
|
||||
ret.percentage = Some(computed::Percentage(
|
||||
ret.percentage.map_or(0., |p| p.0) + pct * factor,
|
||||
));
|
||||
}
|
||||
|
@ -495,9 +535,8 @@ impl CalcNode {
|
|||
/// Convenience parsing function for integers.
|
||||
pub fn parse_integer<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<CSSInteger, ParseError<'i>>
|
||||
{
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<CSSInteger, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::Integer)?
|
||||
.to_number()
|
||||
.map(|n| n as CSSInteger)
|
||||
|
@ -508,21 +547,29 @@ impl CalcNode {
|
|||
pub fn parse_length_or_percentage<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
clamping_mode: AllowedLengthType)
|
||||
-> Result<CalcLengthOrPercentage, ParseError<'i>>
|
||||
{
|
||||
clamping_mode: AllowedLengthType
|
||||
) -> Result<CalcLengthOrPercentage, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::LengthOrPercentage)?
|
||||
.to_length_or_percentage(clamping_mode)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for percentages.
|
||||
pub fn parse_percentage<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<CSSFloat, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::Percentage)?
|
||||
.to_percentage()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
}
|
||||
|
||||
/// Convenience parsing function for `<length>`.
|
||||
pub fn parse_length<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
clamping_mode: AllowedLengthType)
|
||||
-> Result<CalcLengthOrPercentage, ParseError<'i>>
|
||||
{
|
||||
clamping_mode: AllowedLengthType
|
||||
) -> Result<CalcLengthOrPercentage, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::Length)?
|
||||
.to_length_or_percentage(clamping_mode)
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
|
@ -531,9 +578,8 @@ impl CalcNode {
|
|||
/// Convenience parsing function for `<number>`.
|
||||
pub fn parse_number<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<CSSFloat, ParseError<'i>>
|
||||
{
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<CSSFloat, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::Number)?
|
||||
.to_number()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
|
@ -542,9 +588,8 @@ impl CalcNode {
|
|||
/// Convenience parsing function for `<angle>`.
|
||||
pub fn parse_angle<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<Angle, ParseError<'i>>
|
||||
{
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<Angle, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::Angle)?
|
||||
.to_angle()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
|
@ -553,9 +598,8 @@ impl CalcNode {
|
|||
/// Convenience parsing function for `<time>`.
|
||||
pub fn parse_time<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<Time, ParseError<'i>>
|
||||
{
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<Time, ParseError<'i>> {
|
||||
Self::parse(context, input, CalcUnit::Time)?
|
||||
.to_time()
|
||||
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue