mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
style: Simplify computed::LengthOrPercentage and friends.
This is a first step to share LengthOrPercentage representation between Rust and Gecko. We need to preserve whether the value came from a calc() expression, for now at least, since we do different things depending on whether we're calc or not right now. See https://github.com/w3c/csswg-drafts/issues/3482 and dependent bugs for example. That means that the gecko conversion code needs to handle calc() in a bit of an awkward way until I change it to not be needed (patches for that incoming in the next few weeks I hope). I need to add a hack to exclude other things from the PartialEq implementation because the new conversion code is less lossy than the old one, and we relied on the lousiness in AnimationValue comparison (in order to start transitions and such, in [1] for example). I expect to remove that manual PartialEq implementation as soon as I'm done with the conversion. The less lossy conversion does fix a few serialization bugs for animation values though, like not loosing 0% values in calc() when interpolating lengths and percentages, see the two modified tests: * property-types.js * test_animation_properties.html Differential Revision: https://phabricator.services.mozilla.com/D15793
This commit is contained in:
parent
bffe2a699e
commit
ca503b4908
22 changed files with 338 additions and 644 deletions
|
@ -4,15 +4,14 @@
|
|||
|
||||
//! Animation implementation for various length-related types.
|
||||
|
||||
use super::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use crate::values::computed::length::{CalcLengthOrPercentage, Length};
|
||||
use crate::values::computed::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||
use super::{Animate, Procedure, ToAnimatedValue};
|
||||
use crate::values::computed::length::LengthOrPercentage;
|
||||
use crate::values::computed::MaxLength as ComputedMaxLength;
|
||||
use crate::values::computed::MozLength as ComputedMozLength;
|
||||
use crate::values::computed::Percentage;
|
||||
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
||||
impl Animate for CalcLengthOrPercentage {
|
||||
impl Animate for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
let animate_percentage_half = |this: Option<Percentage>, other: Option<Percentage>| {
|
||||
|
@ -28,42 +27,17 @@ impl Animate for CalcLengthOrPercentage {
|
|||
.unclamped_length()
|
||||
.animate(&other.unclamped_length(), procedure)?;
|
||||
let percentage = animate_percentage_half(self.percentage, other.percentage)?;
|
||||
Ok(CalcLengthOrPercentage::with_clamping_mode(
|
||||
let is_calc = self.was_calc || other.was_calc || self.percentage.is_some() != other.percentage.is_some();
|
||||
Ok(Self::with_clamping_mode(
|
||||
length,
|
||||
percentage,
|
||||
self.clamping_mode,
|
||||
is_calc,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for LengthOrPercentageOrAuto {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
match *self {
|
||||
LengthOrPercentageOrAuto::Length(_) |
|
||||
LengthOrPercentageOrAuto::Percentage(_) |
|
||||
LengthOrPercentageOrAuto::Calc(_) => {
|
||||
Ok(LengthOrPercentageOrAuto::Length(Length::new(0.)))
|
||||
},
|
||||
LengthOrPercentageOrAuto::Auto => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for LengthOrPercentageOrNone {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
match *self {
|
||||
LengthOrPercentageOrNone::Length(_) |
|
||||
LengthOrPercentageOrNone::Percentage(_) |
|
||||
LengthOrPercentageOrNone::Calc(_) => {
|
||||
Ok(LengthOrPercentageOrNone::Length(Length::new(0.)))
|
||||
},
|
||||
LengthOrPercentageOrNone::None => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(emilio): These should use NonNegative<> instead.
|
||||
impl ToAnimatedValue for ComputedMaxLength {
|
||||
type AnimatedValue = Self;
|
||||
|
||||
|
@ -74,18 +48,15 @@ impl ToAnimatedValue for ComputedMaxLength {
|
|||
|
||||
#[inline]
|
||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||
use crate::values::computed::{Length, LengthOrPercentageOrNone, Percentage};
|
||||
use crate::values::computed::LengthOrPercentageOrNone;
|
||||
use crate::values::generics::length::MaxLength as GenericMaxLength;
|
||||
match animated {
|
||||
GenericMaxLength::LengthOrPercentageOrNone(lopn) => {
|
||||
let result = match lopn {
|
||||
LengthOrPercentageOrNone::Length(px) => {
|
||||
LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
|
||||
LengthOrPercentageOrNone::LengthOrPercentage(len) => {
|
||||
LengthOrPercentageOrNone::LengthOrPercentage(len.clamp_to_non_negative())
|
||||
},
|
||||
LengthOrPercentageOrNone::Percentage(percentage) => {
|
||||
LengthOrPercentageOrNone::Percentage(Percentage(percentage.0.max(0.)))
|
||||
},
|
||||
_ => lopn,
|
||||
LengthOrPercentageOrNone::None => lopn,
|
||||
};
|
||||
GenericMaxLength::LengthOrPercentageOrNone(result)
|
||||
},
|
||||
|
@ -104,20 +75,10 @@ impl ToAnimatedValue for ComputedMozLength {
|
|||
|
||||
#[inline]
|
||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||
use crate::values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
|
||||
use crate::values::generics::length::MozLength as GenericMozLength;
|
||||
match animated {
|
||||
GenericMozLength::LengthOrPercentageOrAuto(lopa) => {
|
||||
let result = match lopa {
|
||||
LengthOrPercentageOrAuto::Length(px) => {
|
||||
LengthOrPercentageOrAuto::Length(Length::new(px.px().max(0.)))
|
||||
},
|
||||
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
||||
LengthOrPercentageOrAuto::Percentage(Percentage(percentage.0.max(0.)))
|
||||
},
|
||||
_ => lopa,
|
||||
};
|
||||
GenericMozLength::LengthOrPercentageOrAuto(result)
|
||||
GenericMozLength::LengthOrPercentageOrAuto(lopa.clamp_to_non_negative())
|
||||
},
|
||||
_ => animated,
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
//! module's raison d'être is to ultimately contain all these types.
|
||||
|
||||
use crate::properties::PropertyId;
|
||||
use crate::values::computed::length::CalcLengthOrPercentage;
|
||||
use crate::values::computed::length::LengthOrPercentage;
|
||||
use crate::values::computed::url::ComputedUrl;
|
||||
use crate::values::computed::Angle as ComputedAngle;
|
||||
use crate::values::computed::Image;
|
||||
|
@ -335,7 +335,7 @@ macro_rules! trivial_to_animated_value {
|
|||
}
|
||||
|
||||
trivial_to_animated_value!(Au);
|
||||
trivial_to_animated_value!(CalcLengthOrPercentage);
|
||||
trivial_to_animated_value!(LengthOrPercentage);
|
||||
trivial_to_animated_value!(ComputedAngle);
|
||||
trivial_to_animated_value!(ComputedUrl);
|
||||
trivial_to_animated_value!(bool);
|
||||
|
|
|
@ -32,10 +32,16 @@ fn to_number_or_percentage(
|
|||
value: &SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number>,
|
||||
) -> Result<NumberOrPercentage, ()> {
|
||||
Ok(match *value {
|
||||
SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref l) => match *l {
|
||||
LengthOrPercentage::Length(ref l) => NumberOrPercentage::Number(l.px()),
|
||||
LengthOrPercentage::Percentage(ref p) => NumberOrPercentage::Percentage(*p),
|
||||
LengthOrPercentage::Calc(..) => return Err(()),
|
||||
SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref l) => {
|
||||
match l.percentage {
|
||||
Some(p) => {
|
||||
if l.unclamped_length().px() != 0. {
|
||||
return Err(());
|
||||
}
|
||||
NumberOrPercentage::Percentage(p)
|
||||
}
|
||||
None => NumberOrPercentage::Number(l.length().px())
|
||||
}
|
||||
},
|
||||
SvgLengthOrPercentageOrNumber::Number(ref n) => NumberOrPercentage::Number(*n),
|
||||
})
|
||||
|
@ -55,7 +61,7 @@ impl Animate for SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> {
|
|||
NumberOrPercentage::Percentage(ref this),
|
||||
NumberOrPercentage::Percentage(ref other),
|
||||
) => Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||
LengthOrPercentage::Percentage(this.animate(other, procedure)?),
|
||||
LengthOrPercentage::new_percent(this.animate(other, procedure)?),
|
||||
)),
|
||||
_ => Err(()),
|
||||
}
|
||||
|
|
|
@ -1167,17 +1167,6 @@ impl Animate for ComputedTransformOperation {
|
|||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1318591#c0.
|
||||
impl ComputeSquaredDistance for ComputedTransformOperation {
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
// For translate, We don't want to require doing layout in order to calculate the result, so
|
||||
// drop the percentage part. However, dropping percentage makes us impossible to
|
||||
// compute the distance for the percentage-percentage case, but Gecko uses the
|
||||
// same formula, so it's fine for now.
|
||||
// Note: We use pixel value to compute the distance for translate, so we have to
|
||||
// convert Au into px.
|
||||
let extract_pixel_length = |lop: &LengthOrPercentage| match *lop {
|
||||
LengthOrPercentage::Length(px) => px.px(),
|
||||
LengthOrPercentage::Percentage(_) => 0.,
|
||||
LengthOrPercentage::Calc(calc) => calc.length().px(),
|
||||
};
|
||||
match (self, other) {
|
||||
(&TransformOperation::Matrix3D(ref this), &TransformOperation::Matrix3D(ref other)) => {
|
||||
this.compute_squared_distance(other)
|
||||
|
@ -1199,10 +1188,16 @@ impl ComputeSquaredDistance for ComputedTransformOperation {
|
|||
&TransformOperation::Translate3D(ref fx, ref fy, ref fz),
|
||||
&TransformOperation::Translate3D(ref tx, ref ty, ref tz),
|
||||
) => {
|
||||
let fx = extract_pixel_length(&fx);
|
||||
let fy = extract_pixel_length(&fy);
|
||||
let tx = extract_pixel_length(&tx);
|
||||
let ty = extract_pixel_length(&ty);
|
||||
// For translate, We don't want to require doing layout in order
|
||||
// to calculate the result, so drop the percentage part.
|
||||
//
|
||||
// However, dropping percentage makes us impossible to compute
|
||||
// the distance for the percentage-percentage case, but Gecko
|
||||
// uses the same formula, so it's fine for now.
|
||||
let fx = fx.length_component().px();
|
||||
let fy = fy.length_component().px();
|
||||
let tx = tx.length_component().px();
|
||||
let ty = ty.length_component().px();
|
||||
|
||||
Ok(fx.compute_squared_distance(&tx)? +
|
||||
fy.compute_squared_distance(&ty)? +
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
use crate::values::computed::position::Position;
|
||||
use crate::values::computed::url::ComputedImageUrl;
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::values::computed::Percentage;
|
||||
use crate::values::computed::{Angle, Color, Context};
|
||||
use crate::values::computed::{Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
||||
use crate::values::generics::image::{self as generic, CompatMode};
|
||||
|
@ -73,15 +71,10 @@ impl generic::LineDirection for LineDirection {
|
|||
LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
|
||||
LineDirection::Corner(..) => false,
|
||||
#[cfg(feature = "gecko")]
|
||||
LineDirection::MozPosition(
|
||||
Some(Position {
|
||||
horizontal: LengthOrPercentage::Percentage(Percentage(x)),
|
||||
vertical: LengthOrPercentage::Percentage(Percentage(y)),
|
||||
}),
|
||||
None,
|
||||
) => {
|
||||
LineDirection::MozPosition(Some(Position { ref vertical, ref horizontal }), None) => {
|
||||
// `50% 0%` is the default value for line direction.
|
||||
x == 0.5 && y == 0.0
|
||||
horizontal.as_percentage().map_or(false, |p| p.0 == 0.5) &&
|
||||
vertical.as_percentage().map_or(false, |p| p.0 == 0.0)
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! `<length>` computed values, and related ones.
|
||||
|
||||
use super::{Context, Number, Percentage, ToComputedValue};
|
||||
use crate::values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||
use crate::values::animated::{ToAnimatedValue};
|
||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use crate::values::generics::length::MaxLength as GenericMaxLength;
|
||||
use crate::values::generics::length::MozLength as GenericMozLength;
|
||||
|
@ -68,15 +68,38 @@ impl ToComputedValue for specified::Length {
|
|||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedZero)]
|
||||
pub struct CalcLengthOrPercentage {
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero)]
|
||||
pub struct LengthOrPercentage {
|
||||
#[animation(constant)]
|
||||
pub clamping_mode: AllowedNumericType,
|
||||
length: Length,
|
||||
pub percentage: Option<Percentage>,
|
||||
/// Whether this was from a calc() expression. This is needed because right
|
||||
/// now we don't treat calc() the same way as non-calc everywhere, but
|
||||
/// that's a bug in most cases.
|
||||
///
|
||||
/// Please don't add new uses of this that aren't for converting to Gecko's
|
||||
/// representation, or to interpolate values.
|
||||
///
|
||||
/// See https://github.com/w3c/csswg-drafts/issues/3482.
|
||||
#[animation(constant)]
|
||||
pub was_calc: bool,
|
||||
}
|
||||
|
||||
impl ComputeSquaredDistance for CalcLengthOrPercentage {
|
||||
// FIXME(emilio): This is a bit of a hack that can disappear as soon as we share
|
||||
// representation of LengthOrPercentage with Gecko. The issue here is that Gecko
|
||||
// uses CalcValue to represent position components, so they always come back as
|
||||
// was_calc == true, and we mess up in the transitions code.
|
||||
//
|
||||
// This was a pre-existing bug, though arguably so only in pretty obscure cases
|
||||
// like calc(0px + 5%) and such.
|
||||
impl PartialEq for LengthOrPercentage {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.length == other.length && self.percentage == other.percentage
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputeSquaredDistance for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
// FIXME(nox): This looks incorrect to me, to add a distance between lengths
|
||||
|
@ -89,24 +112,36 @@ impl ComputeSquaredDistance for CalcLengthOrPercentage {
|
|||
}
|
||||
}
|
||||
|
||||
impl CalcLengthOrPercentage {
|
||||
/// Returns a new `CalcLengthOrPercentage`.
|
||||
impl LengthOrPercentage {
|
||||
/// Returns a new `LengthOrPercentage`.
|
||||
#[inline]
|
||||
pub fn new(length: Length, percentage: Option<Percentage>) -> Self {
|
||||
Self::with_clamping_mode(length, percentage, AllowedNumericType::All)
|
||||
Self::with_clamping_mode(
|
||||
length,
|
||||
percentage,
|
||||
AllowedNumericType::All,
|
||||
/* was_calc = */ false,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a new `CalcLengthOrPercentage` with a specific clamping mode.
|
||||
/// Returns a new `LengthOrPercentage` with zero length and some percentage.
|
||||
pub fn new_percent(percentage: Percentage) -> Self {
|
||||
Self::new(Length::zero(), Some(percentage))
|
||||
}
|
||||
|
||||
/// Returns a new `LengthOrPercentage` with a specific clamping mode.
|
||||
#[inline]
|
||||
pub fn with_clamping_mode(
|
||||
length: Length,
|
||||
percentage: Option<Percentage>,
|
||||
clamping_mode: AllowedNumericType,
|
||||
was_calc: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
clamping_mode,
|
||||
length,
|
||||
percentage,
|
||||
was_calc,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,22 +166,38 @@ impl CalcLengthOrPercentage {
|
|||
self.length
|
||||
}
|
||||
|
||||
|
||||
/// Return the percentage value as CSSFloat.
|
||||
#[inline]
|
||||
pub fn percentage(&self) -> CSSFloat {
|
||||
self.percentage.map_or(0., |p| p.0)
|
||||
}
|
||||
|
||||
/// Returns the percentage component if this could be represented as a
|
||||
/// non-calc percentage.
|
||||
pub fn as_percentage(&self) -> Option<Percentage> {
|
||||
if self.length.px() != 0. {
|
||||
return None;
|
||||
}
|
||||
|
||||
let p = self.percentage?;
|
||||
if self.clamping_mode.clamp(p.0) != p.0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(p)
|
||||
}
|
||||
|
||||
/// Convert the computed value into used value.
|
||||
#[inline]
|
||||
pub fn to_used_value(&self, container_len: Option<Au>) -> Option<Au> {
|
||||
self.to_pixel_length(container_len).map(Au::from)
|
||||
pub fn maybe_to_used_value(&self, container_len: Option<Au>) -> Option<Au> {
|
||||
self.maybe_to_pixel_length(container_len).map(Au::from)
|
||||
}
|
||||
|
||||
/// If there are special rules for computing percentages in a value (e.g.
|
||||
/// the height property), they apply whenever a calc() expression contains
|
||||
/// percentages.
|
||||
pub fn to_pixel_length(&self, container_len: Option<Au>) -> Option<Length> {
|
||||
pub fn maybe_to_pixel_length(&self, container_len: Option<Au>) -> Option<Length> {
|
||||
match (container_len, self.percentage) {
|
||||
(Some(len), Some(percent)) => {
|
||||
let pixel = self.length.px() + len.scale_by(percent.0).to_f32_px();
|
||||
|
@ -158,81 +209,12 @@ impl CalcLengthOrPercentage {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<LengthOrPercentage> for CalcLengthOrPercentage {
|
||||
fn from(len: LengthOrPercentage) -> CalcLengthOrPercentage {
|
||||
match len {
|
||||
LengthOrPercentage::Percentage(this) => {
|
||||
CalcLengthOrPercentage::new(Length::new(0.), Some(this))
|
||||
},
|
||||
LengthOrPercentage::Length(this) => CalcLengthOrPercentage::new(this, None),
|
||||
LengthOrPercentage::Calc(this) => this,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LengthOrPercentageOrAuto> for Option<CalcLengthOrPercentage> {
|
||||
fn from(len: LengthOrPercentageOrAuto) -> Option<CalcLengthOrPercentage> {
|
||||
match len {
|
||||
LengthOrPercentageOrAuto::Percentage(this) => {
|
||||
Some(CalcLengthOrPercentage::new(Length::new(0.), Some(this)))
|
||||
},
|
||||
LengthOrPercentageOrAuto::Length(this) => Some(CalcLengthOrPercentage::new(this, None)),
|
||||
LengthOrPercentageOrAuto::Calc(this) => Some(this),
|
||||
LengthOrPercentageOrAuto::Auto => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LengthOrPercentageOrNone> for Option<CalcLengthOrPercentage> {
|
||||
fn from(len: LengthOrPercentageOrNone) -> Option<CalcLengthOrPercentage> {
|
||||
match len {
|
||||
LengthOrPercentageOrNone::Percentage(this) => {
|
||||
Some(CalcLengthOrPercentage::new(Length::new(0.), Some(this)))
|
||||
},
|
||||
LengthOrPercentageOrNone::Length(this) => Some(CalcLengthOrPercentage::new(this, None)),
|
||||
LengthOrPercentageOrNone::Calc(this) => Some(this),
|
||||
LengthOrPercentageOrNone::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for CalcLengthOrPercentage {
|
||||
impl ToCss for LengthOrPercentage {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
use num_traits::Zero;
|
||||
|
||||
let length = self.unclamped_length();
|
||||
match self.percentage {
|
||||
Some(p) => {
|
||||
if length.px() == 0. && self.clamping_mode.clamp(p.0) == p.0 {
|
||||
return p.to_css(dest);
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if self.clamping_mode.clamp(length.px()) == length.px() {
|
||||
return length.to_css(dest);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
dest.write_str("calc(")?;
|
||||
if let Some(percentage) = self.percentage {
|
||||
percentage.to_css(dest)?;
|
||||
if length.px() != 0. {
|
||||
dest.write_str(if length.px() < Zero::zero() {
|
||||
" - "
|
||||
} else {
|
||||
" + "
|
||||
})?;
|
||||
length.abs().to_css(dest)?;
|
||||
}
|
||||
} else {
|
||||
length.to_css(dest)?;
|
||||
}
|
||||
|
||||
dest.write_str(")")
|
||||
specified::LengthOrPercentage::from_computed_value(self).to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,7 +225,7 @@ impl specified::CalcLengthOrPercentage {
|
|||
context: &Context,
|
||||
zoom_fn: F,
|
||||
base_size: FontBaseSize,
|
||||
) -> CalcLengthOrPercentage
|
||||
) -> LengthOrPercentage
|
||||
where
|
||||
F: Fn(Length) -> Length,
|
||||
{
|
||||
|
@ -277,10 +259,11 @@ impl specified::CalcLengthOrPercentage {
|
|||
}
|
||||
}
|
||||
|
||||
CalcLengthOrPercentage {
|
||||
LengthOrPercentage {
|
||||
clamping_mode: self.clamping_mode,
|
||||
length: Length::new(length.min(f32::MAX).max(f32::MIN)),
|
||||
percentage: self.percentage,
|
||||
was_calc: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,7 +272,7 @@ impl specified::CalcLengthOrPercentage {
|
|||
&self,
|
||||
context: &Context,
|
||||
base_size: FontBaseSize,
|
||||
) -> CalcLengthOrPercentage {
|
||||
) -> LengthOrPercentage {
|
||||
self.to_computed_value_with_zoom(
|
||||
context,
|
||||
|abs| context.maybe_zoom_text(abs.into()).0,
|
||||
|
@ -324,15 +307,15 @@ impl specified::CalcLengthOrPercentage {
|
|||
}
|
||||
|
||||
impl ToComputedValue for specified::CalcLengthOrPercentage {
|
||||
type ComputedValue = CalcLengthOrPercentage;
|
||||
type ComputedValue = LengthOrPercentage;
|
||||
|
||||
fn to_computed_value(&self, context: &Context) -> CalcLengthOrPercentage {
|
||||
fn to_computed_value(&self, context: &Context) -> LengthOrPercentage {
|
||||
// normal properties don't zoom, and compute em units against the current style's font-size
|
||||
self.to_computed_value_with_zoom(context, |abs| abs, FontBaseSize::CurrentStyle)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &CalcLengthOrPercentage) -> Self {
|
||||
fn from_computed_value(computed: &LengthOrPercentage) -> Self {
|
||||
specified::CalcLengthOrPercentage {
|
||||
clamping_mode: computed.clamping_mode,
|
||||
absolute: Some(AbsoluteLength::from_computed_value(&computed.length)),
|
||||
|
@ -342,95 +325,33 @@ impl ToComputedValue for specified::CalcLengthOrPercentage {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[animate(fallback = "Self::animate_fallback")]
|
||||
#[css(derive_debug)]
|
||||
#[derive(
|
||||
Animate,
|
||||
Clone,
|
||||
ComputeSquaredDistance,
|
||||
Copy,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
ToAnimatedValue,
|
||||
ToAnimatedZero,
|
||||
ToCss,
|
||||
)]
|
||||
#[distance(fallback = "Self::compute_squared_distance_fallback")]
|
||||
pub enum LengthOrPercentage {
|
||||
Length(Length),
|
||||
Percentage(Percentage),
|
||||
Calc(CalcLengthOrPercentage),
|
||||
}
|
||||
|
||||
impl LengthOrPercentage {
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
||||
fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
// Special handling for zero values since these should not require calc().
|
||||
if self.is_definitely_zero() {
|
||||
return other.to_animated_zero()?.animate(other, procedure);
|
||||
}
|
||||
if other.is_definitely_zero() {
|
||||
return self.animate(&self.to_animated_zero()?, procedure);
|
||||
}
|
||||
|
||||
let this = CalcLengthOrPercentage::from(*self);
|
||||
let other = CalcLengthOrPercentage::from(*other);
|
||||
Ok(LengthOrPercentage::Calc(this.animate(&other, procedure)?))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compute_squared_distance_fallback(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
CalcLengthOrPercentage::compute_squared_distance(&(*self).into(), &(*other).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Au> for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn from(length: Au) -> Self {
|
||||
LengthOrPercentage::Length(length.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl LengthOrPercentage {
|
||||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
pub fn zero() -> LengthOrPercentage {
|
||||
LengthOrPercentage::Length(Length::new(0.))
|
||||
LengthOrPercentage::new(Length::new(0.), None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// 1px length value for SVG defaults
|
||||
#[inline]
|
||||
pub fn one() -> LengthOrPercentage {
|
||||
LengthOrPercentage::Length(Length::new(1.))
|
||||
LengthOrPercentage::new(Length::new(1.), None)
|
||||
}
|
||||
|
||||
/// Returns true if the computed value is absolute 0 or 0%.
|
||||
///
|
||||
/// (Returns false for calc() values, even if ones that may resolve to zero.)
|
||||
#[inline]
|
||||
pub fn is_definitely_zero(&self) -> bool {
|
||||
use self::LengthOrPercentage::*;
|
||||
match *self {
|
||||
Length(l) => l.px() == 0.0,
|
||||
Percentage(p) => p.0 == 0.0,
|
||||
Calc(_) => false,
|
||||
}
|
||||
self.unclamped_length().px() == 0.0 && self.percentage.map_or(true, |p| p.0 == 0.0)
|
||||
}
|
||||
|
||||
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the
|
||||
// hash key.
|
||||
#[allow(missing_docs)]
|
||||
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
|
||||
use self::LengthOrPercentage::*;
|
||||
match *self {
|
||||
Length(l) => (Au::from(l), NotNan::new(0.0).unwrap()),
|
||||
Percentage(p) => (Au(0), NotNan::new(p.0).unwrap()),
|
||||
Calc(c) => (
|
||||
Au::from(c.unclamped_length()),
|
||||
NotNan::new(c.percentage()).unwrap(),
|
||||
),
|
||||
}
|
||||
(
|
||||
Au::from(self.unclamped_length()),
|
||||
NotNan::new(self.percentage()).unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the used value.
|
||||
|
@ -440,27 +361,40 @@ impl LengthOrPercentage {
|
|||
|
||||
/// Returns the used value as CSSPixelLength.
|
||||
pub fn to_pixel_length(&self, containing_length: Au) -> Length {
|
||||
match *self {
|
||||
LengthOrPercentage::Length(length) => length,
|
||||
LengthOrPercentage::Percentage(p) => containing_length.scale_by(p.0).into(),
|
||||
LengthOrPercentage::Calc(ref calc) => {
|
||||
calc.to_pixel_length(Some(containing_length)).unwrap()
|
||||
},
|
||||
}
|
||||
self.maybe_to_pixel_length(Some(containing_length)).unwrap()
|
||||
}
|
||||
|
||||
/// Returns the clamped non-negative values.
|
||||
///
|
||||
/// TODO(emilio): It's a bit unfortunate that this depends on whether the
|
||||
/// value was a `calc()` value or not. Should it?
|
||||
#[inline]
|
||||
pub fn clamp_to_non_negative(self) -> Self {
|
||||
match self {
|
||||
LengthOrPercentage::Length(length) => {
|
||||
LengthOrPercentage::Length(length.clamp_to_non_negative())
|
||||
},
|
||||
LengthOrPercentage::Percentage(percentage) => {
|
||||
LengthOrPercentage::Percentage(percentage.clamp_to_non_negative())
|
||||
},
|
||||
_ => self,
|
||||
if self.was_calc {
|
||||
return Self::with_clamping_mode(
|
||||
self.length,
|
||||
self.percentage,
|
||||
AllowedNumericType::NonNegative,
|
||||
self.was_calc,
|
||||
)
|
||||
}
|
||||
|
||||
debug_assert!(self.percentage.is_none() || self.unclamped_length() == Length::zero());
|
||||
if let Some(p) = self.percentage {
|
||||
return Self::with_clamping_mode(
|
||||
Length::zero(),
|
||||
Some(p.clamp_to_non_negative()),
|
||||
AllowedNumericType::NonNegative,
|
||||
self.was_calc,
|
||||
);
|
||||
}
|
||||
|
||||
Self::with_clamping_mode(
|
||||
self.length.clamp_to_non_negative(),
|
||||
None,
|
||||
AllowedNumericType::NonNegative,
|
||||
self.was_calc,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,71 +404,57 @@ impl ToComputedValue for specified::LengthOrPercentage {
|
|||
fn to_computed_value(&self, context: &Context) -> LengthOrPercentage {
|
||||
match *self {
|
||||
specified::LengthOrPercentage::Length(ref value) => {
|
||||
LengthOrPercentage::Length(value.to_computed_value(context))
|
||||
LengthOrPercentage::new(value.to_computed_value(context), None)
|
||||
},
|
||||
specified::LengthOrPercentage::Percentage(value) => {
|
||||
LengthOrPercentage::Percentage(value)
|
||||
LengthOrPercentage::new_percent(value)
|
||||
},
|
||||
specified::LengthOrPercentage::Calc(ref calc) => {
|
||||
LengthOrPercentage::Calc((**calc).to_computed_value(context))
|
||||
(**calc).to_computed_value(context)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &LengthOrPercentage) -> Self {
|
||||
match *computed {
|
||||
LengthOrPercentage::Length(value) => {
|
||||
specified::LengthOrPercentage::Length(ToComputedValue::from_computed_value(&value))
|
||||
},
|
||||
LengthOrPercentage::Percentage(value) => {
|
||||
specified::LengthOrPercentage::Percentage(value)
|
||||
},
|
||||
LengthOrPercentage::Calc(ref calc) => specified::LengthOrPercentage::Calc(Box::new(
|
||||
ToComputedValue::from_computed_value(calc),
|
||||
)),
|
||||
let length = computed.unclamped_length();
|
||||
if let Some(p) = computed.as_percentage() {
|
||||
return specified::LengthOrPercentage::Percentage(p)
|
||||
}
|
||||
|
||||
let percentage = computed.percentage;
|
||||
if percentage.is_none() &&
|
||||
computed.clamping_mode.clamp(length.px()) == length.px() {
|
||||
return specified::LengthOrPercentage::Length(
|
||||
ToComputedValue::from_computed_value(&length)
|
||||
)
|
||||
}
|
||||
|
||||
specified::LengthOrPercentage::Calc(Box::new(
|
||||
ToComputedValue::from_computed_value(computed),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl IsZeroLength for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn is_zero_length(&self) -> bool {
|
||||
match *self {
|
||||
LengthOrPercentage::Length(l) => l.0 == 0.0,
|
||||
LengthOrPercentage::Percentage(p) => p.0 == 0.0,
|
||||
LengthOrPercentage::Calc(c) => c.unclamped_length().0 == 0.0 && c.percentage() == 0.0,
|
||||
}
|
||||
self.is_definitely_zero()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[animate(fallback = "Self::animate_fallback")]
|
||||
#[css(derive_debug)]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToCss)]
|
||||
#[distance(fallback = "Self::compute_squared_distance_fallback")]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss)]
|
||||
pub enum LengthOrPercentageOrAuto {
|
||||
Length(Length),
|
||||
Percentage(Percentage),
|
||||
LengthOrPercentage(LengthOrPercentage),
|
||||
Auto,
|
||||
Calc(CalcLengthOrPercentage),
|
||||
}
|
||||
|
||||
impl LengthOrPercentageOrAuto {
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
||||
fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
let this = <Option<CalcLengthOrPercentage>>::from(*self);
|
||||
let other = <Option<CalcLengthOrPercentage>>::from(*other);
|
||||
Ok(LengthOrPercentageOrAuto::Calc(
|
||||
this.animate(&other, procedure)?.ok_or(())?,
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns the `0` value.
|
||||
#[inline]
|
||||
fn compute_squared_distance_fallback(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
<Option<CalcLengthOrPercentage>>::compute_squared_distance(
|
||||
&(*self).into(),
|
||||
&(*other).into(),
|
||||
)
|
||||
pub fn zero() -> Self {
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::zero())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,24 +492,21 @@ impl ToAnimatedValue for NonNegativeLengthOrPercentageOrAuto {
|
|||
|
||||
impl LengthOrPercentageOrAuto {
|
||||
/// Returns true if the computed value is absolute 0 or 0%.
|
||||
///
|
||||
/// (Returns false for calc() values, even if ones that may resolve to zero.)
|
||||
#[inline]
|
||||
pub fn is_definitely_zero(&self) -> bool {
|
||||
use self::LengthOrPercentageOrAuto::*;
|
||||
match *self {
|
||||
Length(l) => l.px() == 0.0,
|
||||
Percentage(p) => p.0 == 0.0,
|
||||
Calc(_) | Auto => false,
|
||||
LengthOrPercentage(ref l) => l.is_definitely_zero(),
|
||||
Auto => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn clamp_to_non_negative(self) -> Self {
|
||||
/// Clamps the value to a non-negative value.
|
||||
pub fn clamp_to_non_negative(self) -> Self {
|
||||
use self::LengthOrPercentageOrAuto::*;
|
||||
match self {
|
||||
Length(l) => Length(l.clamp_to_non_negative()),
|
||||
Percentage(p) => Percentage(p.clamp_to_non_negative()),
|
||||
_ => self,
|
||||
LengthOrPercentage(l) => LengthOrPercentage(l.clamp_to_non_negative()),
|
||||
Auto => Auto,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -600,16 +517,12 @@ impl ToComputedValue for specified::LengthOrPercentageOrAuto {
|
|||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAuto {
|
||||
match *self {
|
||||
specified::LengthOrPercentageOrAuto::Length(ref value) => {
|
||||
LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
|
||||
},
|
||||
specified::LengthOrPercentageOrAuto::Percentage(value) => {
|
||||
LengthOrPercentageOrAuto::Percentage(value)
|
||||
specified::LengthOrPercentageOrAuto::LengthOrPercentage(ref value) => {
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(
|
||||
value.to_computed_value(context),
|
||||
)
|
||||
},
|
||||
specified::LengthOrPercentageOrAuto::Auto => LengthOrPercentageOrAuto::Auto,
|
||||
specified::LengthOrPercentageOrAuto::Calc(ref calc) => {
|
||||
LengthOrPercentageOrAuto::Calc((**calc).to_computed_value(context))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,78 +530,44 @@ impl ToComputedValue for specified::LengthOrPercentageOrAuto {
|
|||
fn from_computed_value(computed: &LengthOrPercentageOrAuto) -> Self {
|
||||
match *computed {
|
||||
LengthOrPercentageOrAuto::Auto => specified::LengthOrPercentageOrAuto::Auto,
|
||||
LengthOrPercentageOrAuto::Length(value) => specified::LengthOrPercentageOrAuto::Length(
|
||||
ToComputedValue::from_computed_value(&value),
|
||||
),
|
||||
LengthOrPercentageOrAuto::Percentage(value) => {
|
||||
specified::LengthOrPercentageOrAuto::Percentage(value)
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(ref value) => {
|
||||
specified::LengthOrPercentageOrAuto::LengthOrPercentage(
|
||||
ToComputedValue::from_computed_value(value),
|
||||
)
|
||||
},
|
||||
LengthOrPercentageOrAuto::Calc(calc) => specified::LengthOrPercentageOrAuto::Calc(
|
||||
Box::new(ToComputedValue::from_computed_value(&calc)),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[animate(fallback = "Self::animate_fallback")]
|
||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||
#[css(derive_debug)]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)]
|
||||
#[distance(fallback = "Self::compute_squared_distance_fallback")]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss)]
|
||||
pub enum LengthOrPercentageOrNone {
|
||||
Length(Length),
|
||||
Percentage(Percentage),
|
||||
Calc(CalcLengthOrPercentage),
|
||||
LengthOrPercentage(LengthOrPercentage),
|
||||
None,
|
||||
}
|
||||
|
||||
impl LengthOrPercentageOrNone {
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
||||
fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
let this = <Option<CalcLengthOrPercentage>>::from(*self);
|
||||
let other = <Option<CalcLengthOrPercentage>>::from(*other);
|
||||
Ok(LengthOrPercentageOrNone::Calc(
|
||||
this.animate(&other, procedure)?.ok_or(())?,
|
||||
))
|
||||
}
|
||||
|
||||
fn compute_squared_distance_fallback(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
<Option<CalcLengthOrPercentage>>::compute_squared_distance(
|
||||
&(*self).into(),
|
||||
&(*other).into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl LengthOrPercentageOrNone {
|
||||
/// Returns the used value.
|
||||
pub fn to_used_value(&self, containing_length: Au) -> Option<Au> {
|
||||
match *self {
|
||||
LengthOrPercentageOrNone::None => None,
|
||||
LengthOrPercentageOrNone::Length(length) => Some(Au::from(length)),
|
||||
LengthOrPercentageOrNone::Percentage(percent) => {
|
||||
Some(containing_length.scale_by(percent.0))
|
||||
LengthOrPercentageOrNone::LengthOrPercentage(ref lop) => {
|
||||
Some(lop.to_used_value(containing_length))
|
||||
},
|
||||
LengthOrPercentageOrNone::Calc(ref calc) => calc.to_used_value(Some(containing_length)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(emilio): Derive this.
|
||||
impl ToComputedValue for specified::LengthOrPercentageOrNone {
|
||||
type ComputedValue = LengthOrPercentageOrNone;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrNone {
|
||||
match *self {
|
||||
specified::LengthOrPercentageOrNone::Length(ref value) => {
|
||||
LengthOrPercentageOrNone::Length(value.to_computed_value(context))
|
||||
},
|
||||
specified::LengthOrPercentageOrNone::Percentage(value) => {
|
||||
LengthOrPercentageOrNone::Percentage(value)
|
||||
},
|
||||
specified::LengthOrPercentageOrNone::Calc(ref calc) => {
|
||||
LengthOrPercentageOrNone::Calc((**calc).to_computed_value(context))
|
||||
specified::LengthOrPercentageOrNone::LengthOrPercentage(ref value) => {
|
||||
LengthOrPercentageOrNone::LengthOrPercentage(value.to_computed_value(context))
|
||||
},
|
||||
specified::LengthOrPercentageOrNone::None => LengthOrPercentageOrNone::None,
|
||||
}
|
||||
|
@ -698,15 +577,11 @@ impl ToComputedValue for specified::LengthOrPercentageOrNone {
|
|||
fn from_computed_value(computed: &LengthOrPercentageOrNone) -> Self {
|
||||
match *computed {
|
||||
LengthOrPercentageOrNone::None => specified::LengthOrPercentageOrNone::None,
|
||||
LengthOrPercentageOrNone::Length(value) => specified::LengthOrPercentageOrNone::Length(
|
||||
ToComputedValue::from_computed_value(&value),
|
||||
),
|
||||
LengthOrPercentageOrNone::Percentage(value) => {
|
||||
specified::LengthOrPercentageOrNone::Percentage(value)
|
||||
LengthOrPercentageOrNone::LengthOrPercentage(value) => {
|
||||
specified::LengthOrPercentageOrNone::LengthOrPercentage(
|
||||
ToComputedValue::from_computed_value(&value),
|
||||
)
|
||||
},
|
||||
LengthOrPercentageOrNone::Calc(calc) => specified::LengthOrPercentageOrNone::Calc(
|
||||
Box::new(ToComputedValue::from_computed_value(&calc)),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -719,19 +594,19 @@ impl ToAnimatedValue for NonNegativeLengthOrPercentage {
|
|||
|
||||
#[inline]
|
||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||
self.into()
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||
animated.clamp_to_non_negative().into()
|
||||
NonNegative(animated.clamp_to_non_negative())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NonNegativeLength> for NonNegativeLengthOrPercentage {
|
||||
#[inline]
|
||||
fn from(length: NonNegativeLength) -> Self {
|
||||
LengthOrPercentage::Length(length.0).into()
|
||||
LengthOrPercentage::new(length.0, None).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -749,6 +624,15 @@ impl From<NonNegativeLengthOrPercentage> for LengthOrPercentage {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(emilio): This is a really generic impl which is only needed to implement
|
||||
// Animated and co for Spacing<>. Get rid of this, probably?
|
||||
impl From<Au> for LengthOrPercentage {
|
||||
#[inline]
|
||||
fn from(length: Au) -> Self {
|
||||
LengthOrPercentage::new(length.into(), None)
|
||||
}
|
||||
}
|
||||
|
||||
impl NonNegativeLengthOrPercentage {
|
||||
/// Get zero value.
|
||||
#[inline]
|
||||
|
@ -798,11 +682,6 @@ impl CSSPixelLength {
|
|||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clamp_to_non_negative(self) -> Self {
|
||||
Self::new(self.px().max(0.))
|
||||
}
|
||||
|
||||
/// Return the length with app_unit i32 type.
|
||||
#[inline]
|
||||
pub fn to_i32_au(&self) -> i32 {
|
||||
|
@ -810,11 +689,19 @@ impl CSSPixelLength {
|
|||
}
|
||||
|
||||
/// Return the absolute value of this length.
|
||||
#[inline]
|
||||
pub fn abs(self) -> Self {
|
||||
CSSPixelLength::new(self.0.abs())
|
||||
}
|
||||
|
||||
/// Return the clamped value of this length.
|
||||
#[inline]
|
||||
pub fn clamp_to_non_negative(self) -> Self {
|
||||
CSSPixelLength::new(self.0.max(0.))
|
||||
}
|
||||
|
||||
/// Zero value
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
CSSPixelLength::new(0.)
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier,
|
|||
pub use self::gecko::ScrollSnapPoint;
|
||||
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
|
||||
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
|
||||
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage};
|
||||
pub use self::length::{Length, LengthOrNumber, LengthOrPercentage};
|
||||
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
|
||||
pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto};
|
||||
#[cfg(feature = "gecko")]
|
||||
|
|
|
@ -28,8 +28,8 @@ impl Position {
|
|||
#[inline]
|
||||
pub fn center() -> Self {
|
||||
Self::new(
|
||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ impl TransformOrigin {
|
|||
#[inline]
|
||||
pub fn initial_value() -> Self {
|
||||
Self::new(
|
||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||
Length::new(0.),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -103,10 +103,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> ToAnimatedZero for Spacing<V>
|
||||
where
|
||||
V: From<Au>,
|
||||
{
|
||||
impl<V> ToAnimatedZero for Spacing<V> {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
Err(())
|
||||
|
|
|
@ -288,18 +288,14 @@ impl ToAbsoluteLength for ComputedLength {
|
|||
impl ToAbsoluteLength for ComputedLengthOrPercentage {
|
||||
#[inline]
|
||||
fn to_pixel_length(&self, containing_len: Option<Au>) -> Result<CSSFloat, ()> {
|
||||
let extract_pixel_length = |lop: &ComputedLengthOrPercentage| match *lop {
|
||||
ComputedLengthOrPercentage::Length(px) => px.px(),
|
||||
ComputedLengthOrPercentage::Percentage(_) => 0.,
|
||||
ComputedLengthOrPercentage::Calc(calc) => calc.length().px(),
|
||||
};
|
||||
|
||||
match containing_len {
|
||||
Some(relative_len) => Ok(self.to_pixel_length(relative_len).px()),
|
||||
// If we don't have reference box, we cannot resolve the used value,
|
||||
// so only retrieve the length part. This will be used for computing
|
||||
// distance without any layout info.
|
||||
None => Ok(extract_pixel_length(self)),
|
||||
//
|
||||
// FIXME(emilio): This looks wrong.
|
||||
None => Ok(self.length_component().px()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -916,9 +916,7 @@ impl FontSize {
|
|||
info = parent.keyword_info.map(|i| i.compose(ratio, abs.into()));
|
||||
}
|
||||
let calc = calc.to_computed_value_zoomed(context, base_size);
|
||||
calc.to_used_value(Some(base_size.resolve(context)))
|
||||
.unwrap()
|
||||
.into()
|
||||
calc.to_used_value(base_size.resolve(context)).into()
|
||||
},
|
||||
FontSize::Keyword(i) => {
|
||||
// As a specified keyword, this is keyword derived
|
||||
|
|
|
@ -789,6 +789,12 @@ impl LengthOrPercentage {
|
|||
LengthOrPercentage::Length(NoCalcLength::zero())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns a `0%` value.
|
||||
pub fn zero_percent() -> LengthOrPercentage {
|
||||
LengthOrPercentage::Percentage(computed::Percentage::zero())
|
||||
}
|
||||
|
||||
fn parse_internal<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
|
@ -898,24 +904,8 @@ impl IsZeroLength for LengthOrPercentage {
|
|||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||
pub enum LengthOrPercentageOrAuto {
|
||||
Length(NoCalcLength),
|
||||
Percentage(computed::Percentage),
|
||||
LengthOrPercentage(LengthOrPercentage),
|
||||
Auto,
|
||||
Calc(Box<CalcLengthOrPercentage>),
|
||||
}
|
||||
|
||||
impl From<NoCalcLength> for LengthOrPercentageOrAuto {
|
||||
#[inline]
|
||||
fn from(len: NoCalcLength) -> Self {
|
||||
LengthOrPercentageOrAuto::Length(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<computed::Percentage> for LengthOrPercentageOrAuto {
|
||||
#[inline]
|
||||
fn from(pc: computed::Percentage) -> Self {
|
||||
LengthOrPercentageOrAuto::Percentage(pc)
|
||||
}
|
||||
}
|
||||
|
||||
impl LengthOrPercentageOrAuto {
|
||||
|
@ -925,48 +915,16 @@ impl LengthOrPercentageOrAuto {
|
|||
num_context: AllowedNumericType,
|
||||
allow_quirks: AllowQuirks,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
// FIXME: remove early returns when lifetimes are non-lexical
|
||||
{
|
||||
let location = input.current_source_location();
|
||||
let token = input.next()?;
|
||||
match *token {
|
||||
Token::Dimension {
|
||||
value, ref unit, ..
|
||||
} if num_context.is_ok(context.parsing_mode, value) => {
|
||||
return NoCalcLength::parse_dimension(context, value, unit)
|
||||
.map(LengthOrPercentageOrAuto::Length)
|
||||
.map_err(|()| location.new_unexpected_token_error(token.clone()));
|
||||
},
|
||||
Token::Percentage { unit_value, .. }
|
||||
if num_context.is_ok(context.parsing_mode, unit_value) =>
|
||||
{
|
||||
return Ok(LengthOrPercentageOrAuto::Percentage(computed::Percentage(
|
||||
unit_value,
|
||||
)));
|
||||
}
|
||||
Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
|
||||
if value != 0. &&
|
||||
!context.parsing_mode.allows_unitless_lengths() &&
|
||||
!allow_quirks.allowed(context.quirks_mode)
|
||||
{
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
return Ok(LengthOrPercentageOrAuto::Length(NoCalcLength::Absolute(
|
||||
AbsoluteLength::Px(value),
|
||||
)));
|
||||
},
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => {
|
||||
return Ok(LengthOrPercentageOrAuto::Auto);
|
||||
},
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {},
|
||||
_ => return Err(location.new_unexpected_token_error(token.clone())),
|
||||
}
|
||||
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||
return Ok(LengthOrPercentageOrAuto::Auto);
|
||||
}
|
||||
|
||||
let calc = input.parse_nested_block(|i| {
|
||||
CalcNode::parse_length_or_percentage(context, i, num_context)
|
||||
})?;
|
||||
Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
|
||||
Ok(LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::parse_internal(
|
||||
context,
|
||||
input,
|
||||
num_context,
|
||||
allow_quirks,
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Parse a non-negative length, percentage, or auto.
|
||||
|
@ -1000,13 +958,13 @@ impl LengthOrPercentageOrAuto {
|
|||
|
||||
/// Returns a value representing a `0` length.
|
||||
pub fn zero() -> Self {
|
||||
LengthOrPercentageOrAuto::Length(NoCalcLength::zero())
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::zero())
|
||||
}
|
||||
|
||||
/// Returns a value representing `0%`.
|
||||
#[inline]
|
||||
pub fn zero_percent() -> Self {
|
||||
LengthOrPercentageOrAuto::Percentage(computed::Percentage::zero())
|
||||
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::zero_percent())
|
||||
}
|
||||
|
||||
/// Parses, with quirks.
|
||||
|
@ -1076,9 +1034,7 @@ impl Parse for NonNegativeLengthOrPercentageOrAuto {
|
|||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum LengthOrPercentageOrNone {
|
||||
Length(NoCalcLength),
|
||||
Percentage(computed::Percentage),
|
||||
Calc(Box<CalcLengthOrPercentage>),
|
||||
LengthOrPercentage(LengthOrPercentage),
|
||||
None,
|
||||
}
|
||||
|
||||
|
@ -1089,48 +1045,16 @@ impl LengthOrPercentageOrNone {
|
|||
num_context: AllowedNumericType,
|
||||
allow_quirks: AllowQuirks,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
// FIXME: remove early returns when lifetimes are non-lexical
|
||||
{
|
||||
let location = input.current_source_location();
|
||||
let token = input.next()?;
|
||||
match *token {
|
||||
Token::Dimension {
|
||||
value, ref unit, ..
|
||||
} if num_context.is_ok(context.parsing_mode, value) => {
|
||||
return NoCalcLength::parse_dimension(context, value, unit)
|
||||
.map(LengthOrPercentageOrNone::Length)
|
||||
.map_err(|()| location.new_unexpected_token_error(token.clone()));
|
||||
},
|
||||
Token::Percentage { unit_value, .. }
|
||||
if num_context.is_ok(context.parsing_mode, unit_value) =>
|
||||
{
|
||||
return Ok(LengthOrPercentageOrNone::Percentage(computed::Percentage(
|
||||
unit_value,
|
||||
)));
|
||||
}
|
||||
Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => {
|
||||
if value != 0. &&
|
||||
!context.parsing_mode.allows_unitless_lengths() &&
|
||||
!allow_quirks.allowed(context.quirks_mode)
|
||||
{
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
return Ok(LengthOrPercentageOrNone::Length(NoCalcLength::Absolute(
|
||||
AbsoluteLength::Px(value),
|
||||
)));
|
||||
},
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {},
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => {
|
||||
return Ok(LengthOrPercentageOrNone::None);
|
||||
},
|
||||
_ => return Err(location.new_unexpected_token_error(token.clone())),
|
||||
}
|
||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(LengthOrPercentageOrNone::None);
|
||||
}
|
||||
|
||||
let calc = input.parse_nested_block(|i| {
|
||||
CalcNode::parse_length_or_percentage(context, i, num_context)
|
||||
})?;
|
||||
Ok(LengthOrPercentageOrNone::Calc(Box::new(calc)))
|
||||
Ok(LengthOrPercentageOrNone::LengthOrPercentage(LengthOrPercentage::parse_internal(
|
||||
context,
|
||||
input,
|
||||
num_context,
|
||||
allow_quirks,
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Parse a non-negative LengthOrPercentageOrNone.
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
use crate::hash::FxHashMap;
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::str::HTML_SPACE_CHARACTERS;
|
||||
use crate::values::computed::CalcLengthOrPercentage;
|
||||
use crate::values::computed::LengthOrPercentage as ComputedLengthOrPercentage;
|
||||
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
||||
use crate::values::generics::position::Position as GenericPosition;
|
||||
|
@ -255,25 +254,21 @@ impl<S: Side> ToComputedValue for PositionComponent<S> {
|
|||
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
PositionComponent::Center => ComputedLengthOrPercentage::Percentage(Percentage(0.5)),
|
||||
PositionComponent::Center => ComputedLengthOrPercentage::new_percent(Percentage(0.5)),
|
||||
PositionComponent::Side(ref keyword, None) => {
|
||||
let p = Percentage(if keyword.is_start() { 0. } else { 1. });
|
||||
ComputedLengthOrPercentage::Percentage(p)
|
||||
ComputedLengthOrPercentage::new_percent(p)
|
||||
},
|
||||
PositionComponent::Side(ref keyword, Some(ref length)) if !keyword.is_start() => {
|
||||
match length.to_computed_value(context) {
|
||||
ComputedLengthOrPercentage::Length(length) => ComputedLengthOrPercentage::Calc(
|
||||
CalcLengthOrPercentage::new(-length, Some(Percentage::hundred())),
|
||||
),
|
||||
ComputedLengthOrPercentage::Percentage(p) => {
|
||||
ComputedLengthOrPercentage::Percentage(Percentage(1.0 - p.0))
|
||||
},
|
||||
ComputedLengthOrPercentage::Calc(calc) => {
|
||||
let p = Percentage(1. - calc.percentage.map_or(0., |p| p.0));
|
||||
let l = -calc.unclamped_length();
|
||||
ComputedLengthOrPercentage::Calc(CalcLengthOrPercentage::new(l, Some(p)))
|
||||
},
|
||||
}
|
||||
let length = length.to_computed_value(context);
|
||||
let p = Percentage(1. - length.percentage());
|
||||
let l = -length.unclamped_length();
|
||||
ComputedLengthOrPercentage::with_clamping_mode(
|
||||
l,
|
||||
Some(p),
|
||||
length.clamping_mode,
|
||||
length.was_calc,
|
||||
)
|
||||
},
|
||||
PositionComponent::Side(_, Some(ref length)) |
|
||||
PositionComponent::Length(ref length) => length.to_computed_value(context),
|
||||
|
|
|
@ -323,12 +323,12 @@ where
|
|||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
OriginComponent::Center => {
|
||||
ComputedLengthOrPercentage::Percentage(ComputedPercentage(0.5))
|
||||
ComputedLengthOrPercentage::new_percent(ComputedPercentage(0.5))
|
||||
},
|
||||
OriginComponent::Length(ref length) => length.to_computed_value(context),
|
||||
OriginComponent::Side(ref keyword) => {
|
||||
let p = ComputedPercentage(if keyword.is_start() { 0. } else { 1. });
|
||||
ComputedLengthOrPercentage::Percentage(p)
|
||||
ComputedLengthOrPercentage::new_percent(p)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue