mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Split the Length type (introduce NoCalcLength)
This commit is contained in:
parent
556a46f537
commit
4035bbd738
4 changed files with 154 additions and 89 deletions
|
@ -17,6 +17,45 @@ pub use super::image::{EndingShape as GradientShape, Gradient, GradientKind, Ima
|
|||
pub use super::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||
pub use values::specified::{Angle, BorderStyle, Time, UrlOrNone};
|
||||
|
||||
impl ToComputedValue for specified::NoCalcLength {
|
||||
type ComputedValue = Au;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Au {
|
||||
match *self {
|
||||
specified::NoCalcLength::Absolute(length) => length,
|
||||
specified::NoCalcLength::FontRelative(length) =>
|
||||
length.to_computed_value(context, /* use inherited */ false),
|
||||
specified::NoCalcLength::ViewportPercentage(length) =>
|
||||
length.to_computed_value(context.viewport_size()),
|
||||
specified::NoCalcLength::ServoCharacterWidth(length) =>
|
||||
length.to_computed_value(context.style().get_font().clone_font_size())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Au) -> Self {
|
||||
specified::NoCalcLength::Absolute(*computed)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for specified::Length {
|
||||
type ComputedValue = Au;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Au {
|
||||
match *self {
|
||||
specified::Length::NoCalc(l) => l.to_computed_value(context),
|
||||
specified::Length::Calc(ref calc, range) => range.clamp(calc.to_computed_value(context).length()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Au) -> Self {
|
||||
specified::Length::NoCalc(specified::NoCalcLength::from_computed_value(computed))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
|
|
|
@ -121,30 +121,6 @@ impl ToComputedValue for specified::CSSColor {
|
|||
|
||||
impl ComputedValueAsSpecified for specified::BorderStyle {}
|
||||
|
||||
impl ToComputedValue for specified::Length {
|
||||
type ComputedValue = Au;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Au {
|
||||
match *self {
|
||||
specified::Length::Absolute(length) => length,
|
||||
specified::Length::Calc(ref calc, range) => range.clamp(calc.to_computed_value(context).length()),
|
||||
specified::Length::FontRelative(length) =>
|
||||
length.to_computed_value(context, /* use inherited */ false),
|
||||
specified::Length::ViewportPercentage(length) =>
|
||||
length.to_computed_value(context.viewport_size()),
|
||||
specified::Length::ServoCharacterWidth(length) =>
|
||||
length.to_computed_value(context.style().get_font().clone_font_size())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Au) -> Self {
|
||||
specified::Length::Absolute(*computed)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
|
|
|
@ -24,6 +24,14 @@ pub use super::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingSh
|
|||
pub use super::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||
pub use super::image::{SizeKeyword, VerticalDirection};
|
||||
|
||||
const AU_PER_PX: CSSFloat = 60.;
|
||||
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
|
||||
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
|
||||
const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
|
||||
const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
|
||||
const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
|
||||
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
||||
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
/// A font relative length.
|
||||
|
@ -205,12 +213,12 @@ impl CharacterWidth {
|
|||
}
|
||||
}
|
||||
|
||||
/// A length.
|
||||
/// A `<length>` without taking `calc` expressions into account
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values/#lengths
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum Length {
|
||||
pub enum NoCalcLength {
|
||||
/// An absolute length: https://drafts.csswg.org/css-values/#absolute-length
|
||||
Absolute(Au), // application units
|
||||
|
||||
|
@ -229,7 +237,96 @@ pub enum Length {
|
|||
/// This cannot be specified by the user directly and is only generated by
|
||||
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
|
||||
ServoCharacterWidth(CharacterWidth),
|
||||
}
|
||||
|
||||
impl HasViewportPercentage for NoCalcLength {
|
||||
fn has_viewport_percentage(&self) -> bool {
|
||||
match *self {
|
||||
NoCalcLength::ViewportPercentage(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for NoCalcLength {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
NoCalcLength::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
|
||||
NoCalcLength::FontRelative(length) => length.to_css(dest),
|
||||
NoCalcLength::ViewportPercentage(length) => length.to_css(dest),
|
||||
/* This should only be reached from style dumping code */
|
||||
NoCalcLength::ServoCharacterWidth(CharacterWidth(i)) => write!(dest, "CharWidth({})", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<CSSFloat> for NoCalcLength {
|
||||
type Output = NoCalcLength;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, scalar: CSSFloat) -> NoCalcLength {
|
||||
match self {
|
||||
NoCalcLength::Absolute(Au(v)) => NoCalcLength::Absolute(Au(((v as f32) * scalar) as i32)),
|
||||
NoCalcLength::FontRelative(v) => NoCalcLength::FontRelative(v * scalar),
|
||||
NoCalcLength::ViewportPercentage(v) => NoCalcLength::ViewportPercentage(v * scalar),
|
||||
NoCalcLength::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NoCalcLength {
|
||||
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
pub fn from_str(s: &str) -> Option<NoCalcLength> {
|
||||
Some(match_ignore_ascii_case! { s,
|
||||
"xx-small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
|
||||
"x-small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 4),
|
||||
"small" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 8 / 9),
|
||||
"medium" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX)),
|
||||
"large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 6 / 5),
|
||||
"x-large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 2),
|
||||
"xx-large" => NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX) * 2),
|
||||
|
||||
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
||||
"smaller" => NoCalcLength::FontRelative(FontRelativeLength::Em(0.85)),
|
||||
"larger" => NoCalcLength::FontRelative(FontRelativeLength::Em(1.2)),
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
"px" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PX) as i32))),
|
||||
"in" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_MM) as i32))),
|
||||
"q" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_Q) as i32))),
|
||||
"pt" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(NoCalcLength::Absolute(Au((value * AU_PER_PC) as i32))),
|
||||
// font-relative
|
||||
"em" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Em(value))),
|
||||
"ex" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Ex(value))),
|
||||
"ch" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Ch(value))),
|
||||
"rem" => Ok(NoCalcLength::FontRelative(FontRelativeLength::Rem(value))),
|
||||
// viewport percentages
|
||||
"vw" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vw(value))),
|
||||
"vh" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vh(value))),
|
||||
"vmin" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmin(value))),
|
||||
"vmax" => Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmax(value))),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension to `NoCalcLength` to parse `calc` expressions.
|
||||
/// This is commonly used for the `<length>` values.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values/#lengths
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum Length {
|
||||
/// The `NoCalcLength` type that cannot parse `calc`
|
||||
NoCalc(NoCalcLength),
|
||||
/// A calc expression.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values/#calc-notation
|
||||
|
@ -242,9 +339,8 @@ pub enum Length {
|
|||
impl HasViewportPercentage for Length {
|
||||
fn has_viewport_percentage(&self) -> bool {
|
||||
match *self {
|
||||
Length::ViewportPercentage(_) => true,
|
||||
Length::NoCalc(ref inner) => inner.has_viewport_percentage(),
|
||||
Length::Calc(ref calc, _) => calc.has_viewport_percentage(),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,12 +348,8 @@ impl HasViewportPercentage for Length {
|
|||
impl ToCss for Length {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
Length::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
|
||||
Length::FontRelative(length) => length.to_css(dest),
|
||||
Length::ViewportPercentage(length) => length.to_css(dest),
|
||||
Length::NoCalc(ref inner) => inner.to_css(dest),
|
||||
Length::Calc(ref calc, _) => calc.to_css(dest),
|
||||
/* This should only be reached from style dumping code */
|
||||
Length::ServoCharacterWidth(CharacterWidth(i)) => write!(dest, "CharWidth({})", i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,11 +360,8 @@ impl Mul<CSSFloat> for Length {
|
|||
#[inline]
|
||||
fn mul(self, scalar: CSSFloat) -> Length {
|
||||
match self {
|
||||
Length::Absolute(Au(v)) => Length::Absolute(Au(((v as f32) * scalar) as i32)),
|
||||
Length::FontRelative(v) => Length::FontRelative(v * scalar),
|
||||
Length::ViewportPercentage(v) => Length::ViewportPercentage(v * scalar),
|
||||
Length::NoCalc(inner) => Length::NoCalc(inner * scalar),
|
||||
Length::Calc(..) => panic!("Can't multiply Calc!"),
|
||||
Length::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,31 +394,15 @@ impl Mul<CSSFloat> for ViewportPercentageLength {
|
|||
}
|
||||
}
|
||||
|
||||
const AU_PER_PX: CSSFloat = 60.;
|
||||
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
|
||||
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
|
||||
const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
|
||||
const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
|
||||
const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
|
||||
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
||||
|
||||
impl Length {
|
||||
/// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
pub fn from_str(s: &str) -> Option<Length> {
|
||||
Some(match_ignore_ascii_case! { s,
|
||||
"xx-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 5),
|
||||
"x-small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 4),
|
||||
"small" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 8 / 9),
|
||||
"medium" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX)),
|
||||
"large" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 6 / 5),
|
||||
"x-large" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 3 / 2),
|
||||
"xx-large" => Length::Absolute(Au::from_px(FONT_MEDIUM_PX) * 2),
|
||||
NoCalcLength::from_str(s).map(Length::NoCalc)
|
||||
}
|
||||
|
||||
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
||||
"smaller" => Length::FontRelative(FontRelativeLength::Em(0.85)),
|
||||
"larger" => Length::FontRelative(FontRelativeLength::Em(1.2)),
|
||||
_ => return None
|
||||
})
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||
NoCalcLength::parse_dimension(value, unit).map(Length::NoCalc)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -352,34 +425,10 @@ impl Length {
|
|||
Length::parse_internal(input, AllowedNumericType::NonNegative)
|
||||
}
|
||||
|
||||
/// Parse a given absolute or relative dimension.
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
"px" => Ok(Length::from_px(value)),
|
||||
"in" => Ok(Length::Absolute(Au((value * AU_PER_IN) as i32))),
|
||||
"cm" => Ok(Length::Absolute(Au((value * AU_PER_CM) as i32))),
|
||||
"mm" => Ok(Length::Absolute(Au((value * AU_PER_MM) as i32))),
|
||||
"q" => Ok(Length::Absolute(Au((value * AU_PER_Q) as i32))),
|
||||
"pt" => Ok(Length::Absolute(Au((value * AU_PER_PT) as i32))),
|
||||
"pc" => Ok(Length::Absolute(Au((value * AU_PER_PC) as i32))),
|
||||
// font-relative
|
||||
"em" => Ok(Length::FontRelative(FontRelativeLength::Em(value))),
|
||||
"ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))),
|
||||
"ch" => Ok(Length::FontRelative(FontRelativeLength::Ch(value))),
|
||||
"rem" => Ok(Length::FontRelative(FontRelativeLength::Rem(value))),
|
||||
// viewport percentages
|
||||
"vw" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vw(value))),
|
||||
"vh" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vh(value))),
|
||||
"vmin" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmin(value))),
|
||||
"vmax" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmax(value))),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an absolute length from a px values.
|
||||
#[inline]
|
||||
pub fn from_px(px_value: CSSFloat) -> Length {
|
||||
Length::Absolute(Au((px_value * AU_PER_PX) as i32))
|
||||
Length::NoCalc(NoCalcLength::Absolute(Au((px_value * AU_PER_PX) as i32)))
|
||||
}
|
||||
|
||||
/// Extract inner length without a clone, replacing it with a 0 Au
|
||||
|
@ -648,9 +697,9 @@ impl CalcLengthOrPercentage {
|
|||
match value {
|
||||
SimplifiedValueNode::Percentage(p) =>
|
||||
percentage = Some(percentage.unwrap_or(0.) + p),
|
||||
SimplifiedValueNode::Length(Length::Absolute(Au(au))) =>
|
||||
SimplifiedValueNode::Length(NoCalcLength::Absolute(Au(au))) =>
|
||||
absolute = Some(absolute.unwrap_or(0) + au),
|
||||
SimplifiedValueNode::Length(Length::ViewportPercentage(v)) =>
|
||||
SimplifiedValueNode::Length(NoCalcLength::ViewportPercentage(v)) =>
|
||||
match v {
|
||||
ViewportPercentageLength::Vw(val) =>
|
||||
vw = Some(vw.unwrap_or(0.) + val),
|
||||
|
@ -661,7 +710,7 @@ impl CalcLengthOrPercentage {
|
|||
ViewportPercentageLength::Vmax(val) =>
|
||||
vmax = Some(vmax.unwrap_or(0.) + val),
|
||||
},
|
||||
SimplifiedValueNode::Length(Length::FontRelative(f)) =>
|
||||
SimplifiedValueNode::Length(NoCalcLength::FontRelative(f)) =>
|
||||
match f {
|
||||
FontRelativeLength::Em(val) =>
|
||||
em = Some(em.unwrap_or(0.) + val),
|
||||
|
|
|
@ -26,7 +26,7 @@ pub use self::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword,
|
|||
pub use self::image::{SizeKeyword, VerticalDirection};
|
||||
pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage};
|
||||
pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, CalcUnit};
|
||||
pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength, CalcUnit};
|
||||
|
||||
pub mod basic_shape;
|
||||
pub mod grid;
|
||||
|
@ -109,13 +109,14 @@ impl<'a> Mul<CSSFloat> for &'a SimplifiedSumNode {
|
|||
#[derive(Clone, Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum SimplifiedValueNode {
|
||||
Length(Length),
|
||||
Length(NoCalcLength),
|
||||
Angle(Angle),
|
||||
Time(Time),
|
||||
Percentage(CSSFloat),
|
||||
Number(CSSFloat),
|
||||
Sum(Box<SimplifiedSumNode>),
|
||||
}
|
||||
|
||||
impl<'a> Mul<CSSFloat> for &'a SimplifiedValueNode {
|
||||
type Output = SimplifiedValueNode;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue