mirror of
https://github.com/servo/servo.git
synced 2025-09-20 03:40:09 +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
|
@ -20,7 +20,7 @@ use crate::stylesheets::{Origin, RulesMutateError};
|
||||||
use crate::values::computed::image::LineDirection;
|
use crate::values::computed::image::LineDirection;
|
||||||
use crate::values::computed::transform::Matrix3D;
|
use crate::values::computed::transform::Matrix3D;
|
||||||
use crate::values::computed::url::ComputedImageUrl;
|
use crate::values::computed::url::ComputedImageUrl;
|
||||||
use crate::values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
|
use crate::values::computed::{Angle, Gradient, Image};
|
||||||
use crate::values::computed::{Integer, LengthOrPercentage};
|
use crate::values::computed::{Integer, LengthOrPercentage};
|
||||||
use crate::values::computed::{LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto};
|
use crate::values::computed::{LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto};
|
||||||
use crate::values::computed::{Percentage, TextAlign};
|
use crate::values::computed::{Percentage, TextAlign};
|
||||||
|
@ -31,9 +31,10 @@ use crate::values::generics::rect::Rect;
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
|
|
||||||
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||||
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
|
fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
|
||||||
let has_percentage = other.percentage.is_some();
|
let has_percentage = other.percentage.is_some();
|
||||||
nsStyleCoord_CalcValue {
|
nsStyleCoord_CalcValue {
|
||||||
mLength: other.unclamped_length().to_i32_au(),
|
mLength: other.unclamped_length().to_i32_au(),
|
||||||
|
@ -43,32 +44,19 @@ impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<nsStyleCoord_CalcValue> for CalcLengthOrPercentage {
|
impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
|
||||||
fn from(other: nsStyleCoord_CalcValue) -> CalcLengthOrPercentage {
|
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
|
||||||
let percentage = if other.mHasPercent {
|
let percentage = if other.mHasPercent {
|
||||||
Some(Percentage(other.mPercent))
|
Some(Percentage(other.mPercent))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Self::new(Au(other.mLength).into(), percentage)
|
Self::with_clamping_mode(
|
||||||
}
|
Au(other.mLength).into(),
|
||||||
}
|
percentage,
|
||||||
|
AllowedNumericType::All,
|
||||||
impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
|
/* was_calc = */ true,
|
||||||
fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
|
)
|
||||||
match other {
|
|
||||||
LengthOrPercentage::Length(px) => nsStyleCoord_CalcValue {
|
|
||||||
mLength: px.to_i32_au(),
|
|
||||||
mPercent: 0.0,
|
|
||||||
mHasPercent: false,
|
|
||||||
},
|
|
||||||
LengthOrPercentage::Percentage(pc) => nsStyleCoord_CalcValue {
|
|
||||||
mLength: 0,
|
|
||||||
mPercent: pc.0,
|
|
||||||
mHasPercent: true,
|
|
||||||
},
|
|
||||||
LengthOrPercentage::Calc(calc) => calc.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,39 +64,15 @@ impl LengthOrPercentageOrAuto {
|
||||||
/// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
|
/// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
|
||||||
pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
|
pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
|
||||||
match *self {
|
match *self {
|
||||||
LengthOrPercentageOrAuto::Length(px) => Some(nsStyleCoord_CalcValue {
|
LengthOrPercentageOrAuto::LengthOrPercentage(len) => Some(From::from(len)),
|
||||||
mLength: px.to_i32_au(),
|
|
||||||
mPercent: 0.0,
|
|
||||||
mHasPercent: false,
|
|
||||||
}),
|
|
||||||
LengthOrPercentageOrAuto::Percentage(pc) => Some(nsStyleCoord_CalcValue {
|
|
||||||
mLength: 0,
|
|
||||||
mPercent: pc.0,
|
|
||||||
mHasPercent: true,
|
|
||||||
}),
|
|
||||||
LengthOrPercentageOrAuto::Calc(calc) => Some(calc.into()),
|
|
||||||
LengthOrPercentageOrAuto::Auto => None,
|
LengthOrPercentageOrAuto::Auto => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
|
|
||||||
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
|
|
||||||
match (other.mHasPercent, other.mLength) {
|
|
||||||
(false, _) => LengthOrPercentage::Length(Au(other.mLength).into()),
|
|
||||||
(true, 0) => LengthOrPercentage::Percentage(Percentage(other.mPercent)),
|
|
||||||
_ => LengthOrPercentage::Calc(other.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
|
impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
|
||||||
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentageOrAuto {
|
fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentageOrAuto {
|
||||||
match (other.mHasPercent, other.mLength) {
|
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::from(other))
|
||||||
(false, _) => LengthOrPercentageOrAuto::Length(Au(other.mLength).into()),
|
|
||||||
(true, 0) => LengthOrPercentageOrAuto::Percentage(Percentage(other.mPercent)),
|
|
||||||
_ => LengthOrPercentageOrAuto::Calc(other.into()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,9 +80,8 @@ impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
|
||||||
// disappear as we move more stuff to cbindgen.
|
// disappear as we move more stuff to cbindgen.
|
||||||
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
|
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
|
||||||
fn from(other: nsStyleCoord_CalcValue) -> Self {
|
fn from(other: nsStyleCoord_CalcValue) -> Self {
|
||||||
use style_traits::values::specified::AllowedNumericType;
|
NonNegative(
|
||||||
NonNegative(if other.mLength < 0 || other.mPercent < 0. {
|
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::with_clamping_mode(
|
||||||
LengthOrPercentageOrAuto::Calc(CalcLengthOrPercentage::with_clamping_mode(
|
|
||||||
Au(other.mLength).into(),
|
Au(other.mLength).into(),
|
||||||
if other.mHasPercent {
|
if other.mHasPercent {
|
||||||
Some(Percentage(other.mPercent))
|
Some(Percentage(other.mPercent))
|
||||||
|
@ -126,10 +89,9 @@ impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
AllowedNumericType::NonNegative,
|
AllowedNumericType::NonNegative,
|
||||||
|
/* was_calc = */ true,
|
||||||
))
|
))
|
||||||
} else {
|
)
|
||||||
other.into()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,20 +105,13 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
|
||||||
use crate::values::computed::position::Position;
|
use crate::values::computed::position::Position;
|
||||||
use crate::values::specified::position::{X, Y};
|
use crate::values::specified::position::{X, Y};
|
||||||
|
|
||||||
let horizontal_percentage = match horizontal {
|
let horizontal_percentage = horizontal.as_percentage();
|
||||||
LengthOrPercentage::Percentage(percentage) => Some(percentage.0),
|
let vertical_percentage = vertical.as_percentage();
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let vertical_percentage = match vertical {
|
|
||||||
LengthOrPercentage::Percentage(percentage) => Some(percentage.0),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let horizontal_as_corner = horizontal_percentage.and_then(|percentage| {
|
let horizontal_as_corner = horizontal_percentage.and_then(|percentage| {
|
||||||
if percentage == 0.0 {
|
if percentage.0 == 0.0 {
|
||||||
Some(X::Left)
|
Some(X::Left)
|
||||||
} else if percentage == 1.0 {
|
} else if percentage.0 == 1.0 {
|
||||||
Some(X::Right)
|
Some(X::Right)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -164,9 +119,9 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
|
||||||
});
|
});
|
||||||
|
|
||||||
let vertical_as_corner = vertical_percentage.and_then(|percentage| {
|
let vertical_as_corner = vertical_percentage.and_then(|percentage| {
|
||||||
if percentage == 0.0 {
|
if percentage.0 == 0.0 {
|
||||||
Some(Y::Top)
|
Some(Y::Top)
|
||||||
} else if percentage == 1.0 {
|
} else if percentage.0 == 1.0 {
|
||||||
Some(Y::Bottom)
|
Some(Y::Bottom)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -178,13 +133,13 @@ fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(hc) = horizontal_as_corner {
|
if let Some(hc) = horizontal_as_corner {
|
||||||
if vertical_percentage == Some(0.5) {
|
if vertical_percentage == Some(Percentage(0.5)) {
|
||||||
return LineDirection::Horizontal(hc);
|
return LineDirection::Horizontal(hc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(vc) = vertical_as_corner {
|
if let Some(vc) = vertical_as_corner {
|
||||||
if horizontal_percentage == Some(0.5) {
|
if horizontal_percentage == Some(Percentage(0.5)) {
|
||||||
return LineDirection::Vertical(vc);
|
return LineDirection::Vertical(vc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,19 +148,21 @@ impl GeckoStyleCoordConvertible for NumberOrPercentage {
|
||||||
|
|
||||||
impl GeckoStyleCoordConvertible for LengthOrPercentage {
|
impl GeckoStyleCoordConvertible for LengthOrPercentage {
|
||||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||||
let value = match *self {
|
if self.was_calc {
|
||||||
LengthOrPercentage::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
|
return coord.set_value(CoordDataValue::Calc((*self).into()))
|
||||||
LengthOrPercentage::Percentage(p) => CoordDataValue::Percent(p.0),
|
}
|
||||||
LengthOrPercentage::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
debug_assert!(self.percentage.is_none() || self.unclamped_length() == Length::zero());
|
||||||
};
|
if let Some(p) = self.percentage {
|
||||||
coord.set_value(value);
|
return coord.set_value(CoordDataValue::Percent(p.0));
|
||||||
|
}
|
||||||
|
coord.set_value(CoordDataValue::Coord(self.unclamped_length().to_i32_au()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||||
match coord.as_value() {
|
match coord.as_value() {
|
||||||
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::Length(Au(coord).into())),
|
CoordDataValue::Coord(coord) => Some(LengthOrPercentage::new(Au(coord).into(), None)),
|
||||||
CoordDataValue::Percent(p) => Some(LengthOrPercentage::Percentage(Percentage(p))),
|
CoordDataValue::Percent(p) => Some(LengthOrPercentage::new(Au(0).into(), Some(Percentage(p)))),
|
||||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentage::Calc(calc.into())),
|
CoordDataValue::Calc(calc) => Some(calc.into()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,48 +183,32 @@ impl GeckoStyleCoordConvertible for Length {
|
||||||
|
|
||||||
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
|
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
|
||||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||||
let value = match *self {
|
match *self {
|
||||||
LengthOrPercentageOrAuto::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
|
LengthOrPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto),
|
||||||
LengthOrPercentageOrAuto::Percentage(p) => CoordDataValue::Percent(p.0),
|
LengthOrPercentageOrAuto::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord),
|
||||||
LengthOrPercentageOrAuto::Auto => CoordDataValue::Auto,
|
}
|
||||||
LengthOrPercentageOrAuto::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
|
||||||
};
|
|
||||||
coord.set_value(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||||
match coord.as_value() {
|
match coord.as_value() {
|
||||||
CoordDataValue::Coord(coord) => {
|
|
||||||
Some(LengthOrPercentageOrAuto::Length(Au(coord).into()))
|
|
||||||
},
|
|
||||||
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrAuto::Percentage(Percentage(p))),
|
|
||||||
CoordDataValue::Auto => Some(LengthOrPercentageOrAuto::Auto),
|
CoordDataValue::Auto => Some(LengthOrPercentageOrAuto::Auto),
|
||||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrAuto::Calc(calc.into())),
|
_ => LengthOrPercentage::from_gecko_style_coord(coord).map(LengthOrPercentageOrAuto::LengthOrPercentage),
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
|
impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
|
||||||
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||||
let value = match *self {
|
match *self {
|
||||||
LengthOrPercentageOrNone::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
|
LengthOrPercentageOrNone::None => coord.set_value(CoordDataValue::None),
|
||||||
LengthOrPercentageOrNone::Percentage(p) => CoordDataValue::Percent(p.0),
|
LengthOrPercentageOrNone::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord),
|
||||||
LengthOrPercentageOrNone::None => CoordDataValue::None,
|
}
|
||||||
LengthOrPercentageOrNone::Calc(calc) => CoordDataValue::Calc(calc.into()),
|
|
||||||
};
|
|
||||||
coord.set_value(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||||
match coord.as_value() {
|
match coord.as_value() {
|
||||||
CoordDataValue::Coord(coord) => {
|
|
||||||
Some(LengthOrPercentageOrNone::Length(Au(coord).into()))
|
|
||||||
},
|
|
||||||
CoordDataValue::Percent(p) => Some(LengthOrPercentageOrNone::Percentage(Percentage(p))),
|
|
||||||
CoordDataValue::None => Some(LengthOrPercentageOrNone::None),
|
CoordDataValue::None => Some(LengthOrPercentageOrNone::None),
|
||||||
CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrNone::Calc(calc.into())),
|
_ => LengthOrPercentage::from_gecko_style_coord(coord).map(LengthOrPercentageOrNone::LengthOrPercentage),
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,11 +69,14 @@ impl nsCSSValue {
|
||||||
|
|
||||||
/// Sets LengthOrPercentage value to this nsCSSValue.
|
/// Sets LengthOrPercentage value to this nsCSSValue.
|
||||||
pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) {
|
pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) {
|
||||||
match lop {
|
if lop.was_calc {
|
||||||
LengthOrPercentage::Length(px) => self.set_px(px.px()),
|
return bindings::Gecko_CSSValue_SetCalc(self, lop.into())
|
||||||
LengthOrPercentage::Percentage(pc) => self.set_percentage(pc.0),
|
|
||||||
LengthOrPercentage::Calc(calc) => bindings::Gecko_CSSValue_SetCalc(self, calc.into()),
|
|
||||||
}
|
}
|
||||||
|
debug_assert!(lop.percentage.is_none() || lop.unclamped_length() == Length::zero());
|
||||||
|
if let Some(p) = lop.percentage {
|
||||||
|
return self.set_percentage(p.0);
|
||||||
|
}
|
||||||
|
self.set_px(lop.unclamped_length().px());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a px value to this nsCSSValue.
|
/// Sets a px value to this nsCSSValue.
|
||||||
|
@ -90,13 +93,16 @@ impl nsCSSValue {
|
||||||
pub unsafe fn get_lop(&self) -> LengthOrPercentage {
|
pub unsafe fn get_lop(&self) -> LengthOrPercentage {
|
||||||
match self.mUnit {
|
match self.mUnit {
|
||||||
nsCSSUnit::eCSSUnit_Pixel => {
|
nsCSSUnit::eCSSUnit_Pixel => {
|
||||||
LengthOrPercentage::Length(Length::new(bindings::Gecko_CSSValue_GetNumber(self)))
|
LengthOrPercentage::new(
|
||||||
|
Length::new(bindings::Gecko_CSSValue_GetNumber(self)),
|
||||||
|
None,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
nsCSSUnit::eCSSUnit_Percent => LengthOrPercentage::Percentage(Percentage(
|
nsCSSUnit::eCSSUnit_Percent => LengthOrPercentage::new_percent(Percentage(
|
||||||
bindings::Gecko_CSSValue_GetPercentage(self),
|
bindings::Gecko_CSSValue_GetPercentage(self),
|
||||||
)),
|
)),
|
||||||
nsCSSUnit::eCSSUnit_Calc => {
|
nsCSSUnit::eCSSUnit_Calc => {
|
||||||
LengthOrPercentage::Calc(bindings::Gecko_CSSValue_GetCalc(self).into())
|
bindings::Gecko_CSSValue_GetCalc(self).into()
|
||||||
},
|
},
|
||||||
_ => panic!("Unexpected unit"),
|
_ => panic!("Unexpected unit"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -558,18 +558,16 @@ def set_gecko_property(ffi_name, expr):
|
||||||
},
|
},
|
||||||
CoordDataValue::Coord(coord) => {
|
CoordDataValue::Coord(coord) => {
|
||||||
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
LengthOrPercentage::Length(Au(coord).into())
|
LengthOrPercentage::new(Au(coord).into(), None)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
CoordDataValue::Percent(p) => {
|
CoordDataValue::Percent(p) => {
|
||||||
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
LengthOrPercentage::Percentage(Percentage(p))
|
LengthOrPercentage::new(Au(0).into(), Some(Percentage(p)))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
CoordDataValue::Calc(calc) => {
|
CoordDataValue::Calc(calc) => {
|
||||||
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
SvgLengthOrPercentageOrNumber::LengthOrPercentage(calc.into())
|
||||||
LengthOrPercentage::Calc(calc.into())
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
_ => unreachable!("Unexpected coordinate in ${ident}"),
|
_ => unreachable!("Unexpected coordinate in ${ident}"),
|
||||||
};
|
};
|
||||||
|
@ -5062,6 +5060,7 @@ clip-path
|
||||||
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
|
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
|
||||||
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
||||||
use crate::values::computed::LengthOrPercentage;
|
use crate::values::computed::LengthOrPercentage;
|
||||||
|
use crate::values::generics::NonNegative;
|
||||||
use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
|
use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
|
||||||
|
|
||||||
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
|
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
|
||||||
|
@ -5075,13 +5074,13 @@ clip-path
|
||||||
vec.push(SvgLengthOrPercentageOrNumber::Number(number.into())),
|
vec.push(SvgLengthOrPercentageOrNumber::Number(number.into())),
|
||||||
CoordDataValue::Coord(coord) =>
|
CoordDataValue::Coord(coord) =>
|
||||||
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
LengthOrPercentage::Length(Au(coord).into()).into())),
|
NonNegative(LengthOrPercentage::new(Au(coord).into(), None).into()))),
|
||||||
CoordDataValue::Percent(p) =>
|
CoordDataValue::Percent(p) =>
|
||||||
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
LengthOrPercentage::Percentage(Percentage(p)).into())),
|
NonNegative(LengthOrPercentage::new_percent(Percentage(p)).into()))),
|
||||||
CoordDataValue::Calc(calc) =>
|
CoordDataValue::Calc(calc) =>
|
||||||
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
LengthOrPercentage::Calc(calc.into()).into())),
|
NonNegative(LengthOrPercentage::from(calc).clamp_to_non_negative()))),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ ${helpers.single_keyword(
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"text-indent",
|
"text-indent",
|
||||||
"LengthOrPercentage",
|
"LengthOrPercentage",
|
||||||
"computed::LengthOrPercentage::Length(computed::Length::new(0.))",
|
"computed::LengthOrPercentage::zero()",
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="ComputedValue",
|
||||||
spec="https://drafts.csswg.org/css-text/#propdef-text-indent",
|
spec="https://drafts.csswg.org/css-text/#propdef-text-indent",
|
||||||
allow_quirks=True,
|
allow_quirks=True,
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"margin-%s" % side[0],
|
"margin-%s" % side[0],
|
||||||
"LengthOrPercentageOrAuto",
|
"LengthOrPercentageOrAuto",
|
||||||
"computed::LengthOrPercentageOrAuto::Length(computed::Length::new(0.))",
|
"computed::LengthOrPercentageOrAuto::zero()",
|
||||||
alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"),
|
alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"),
|
||||||
allow_quirks=not side[1],
|
allow_quirks=not side[1],
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="ComputedValue",
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard
|
||||||
use crate::str::CssStringWriter;
|
use crate::str::CssStringWriter;
|
||||||
use crate::stylesheets::{Origin, StylesheetInDocument};
|
use crate::stylesheets::{Origin, StylesheetInDocument};
|
||||||
use crate::values::computed::{Context, ToComputedValue};
|
use crate::values::computed::{Context, ToComputedValue};
|
||||||
use crate::values::specified::{LengthOrPercentageOrAuto, NoCalcLength, ViewportPercentageLength};
|
use crate::values::specified::{self, LengthOrPercentageOrAuto, NoCalcLength, ViewportPercentageLength};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::CowRcStr;
|
use cssparser::CowRcStr;
|
||||||
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||||
|
@ -157,7 +157,9 @@ impl FromMeta for ViewportLength {
|
||||||
fn from_meta(value: &str) -> Option<ViewportLength> {
|
fn from_meta(value: &str) -> Option<ViewportLength> {
|
||||||
macro_rules! specified {
|
macro_rules! specified {
|
||||||
($value:expr) => {
|
($value:expr) => {
|
||||||
ViewportLength::Specified(LengthOrPercentageOrAuto::Length($value))
|
ViewportLength::Specified(LengthOrPercentageOrAuto::LengthOrPercentage(
|
||||||
|
specified::LengthOrPercentage::Length($value)
|
||||||
|
))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,16 +754,10 @@ impl MaybeNew for ViewportConstraints {
|
||||||
if let Some($value) = $value {
|
if let Some($value) = $value {
|
||||||
match *$value {
|
match *$value {
|
||||||
ViewportLength::Specified(ref length) => match *length {
|
ViewportLength::Specified(ref length) => match *length {
|
||||||
LengthOrPercentageOrAuto::Length(ref value) => {
|
|
||||||
Some(Au::from(value.to_computed_value(&context)))
|
|
||||||
},
|
|
||||||
LengthOrPercentageOrAuto::Percentage(value) => {
|
|
||||||
Some(initial_viewport.$dimension.scale_by(value.0))
|
|
||||||
},
|
|
||||||
LengthOrPercentageOrAuto::Auto => None,
|
LengthOrPercentageOrAuto::Auto => None,
|
||||||
LengthOrPercentageOrAuto::Calc(ref calc) => calc
|
LengthOrPercentageOrAuto::LengthOrPercentage(ref lop) => Some(lop
|
||||||
.to_computed_value(&context)
|
.to_computed_value(&context)
|
||||||
.to_used_value(Some(initial_viewport.$dimension)),
|
.to_used_value(initial_viewport.$dimension)),
|
||||||
},
|
},
|
||||||
ViewportLength::ExtendToZoom => {
|
ViewportLength::ExtendToZoom => {
|
||||||
// $extend_to will be 'None' if 'extend-to-zoom' is 'auto'
|
// $extend_to will be 'None' if 'extend-to-zoom' is 'auto'
|
||||||
|
|
|
@ -4,15 +4,14 @@
|
||||||
|
|
||||||
//! Animation implementation for various length-related types.
|
//! Animation implementation for various length-related types.
|
||||||
|
|
||||||
use super::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
use super::{Animate, Procedure, ToAnimatedValue};
|
||||||
use crate::values::computed::length::{CalcLengthOrPercentage, Length};
|
use crate::values::computed::length::LengthOrPercentage;
|
||||||
use crate::values::computed::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
|
||||||
use crate::values::computed::MaxLength as ComputedMaxLength;
|
use crate::values::computed::MaxLength as ComputedMaxLength;
|
||||||
use crate::values::computed::MozLength as ComputedMozLength;
|
use crate::values::computed::MozLength as ComputedMozLength;
|
||||||
use crate::values::computed::Percentage;
|
use crate::values::computed::Percentage;
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
||||||
impl Animate for CalcLengthOrPercentage {
|
impl Animate for LengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||||
let animate_percentage_half = |this: Option<Percentage>, other: Option<Percentage>| {
|
let animate_percentage_half = |this: Option<Percentage>, other: Option<Percentage>| {
|
||||||
|
@ -28,42 +27,17 @@ impl Animate for CalcLengthOrPercentage {
|
||||||
.unclamped_length()
|
.unclamped_length()
|
||||||
.animate(&other.unclamped_length(), procedure)?;
|
.animate(&other.unclamped_length(), procedure)?;
|
||||||
let percentage = animate_percentage_half(self.percentage, other.percentage)?;
|
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,
|
length,
|
||||||
percentage,
|
percentage,
|
||||||
self.clamping_mode,
|
self.clamping_mode,
|
||||||
|
is_calc,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToAnimatedZero for LengthOrPercentageOrAuto {
|
// FIXME(emilio): These should use NonNegative<> instead.
|
||||||
#[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(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToAnimatedValue for ComputedMaxLength {
|
impl ToAnimatedValue for ComputedMaxLength {
|
||||||
type AnimatedValue = Self;
|
type AnimatedValue = Self;
|
||||||
|
|
||||||
|
@ -74,18 +48,15 @@ impl ToAnimatedValue for ComputedMaxLength {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
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;
|
use crate::values::generics::length::MaxLength as GenericMaxLength;
|
||||||
match animated {
|
match animated {
|
||||||
GenericMaxLength::LengthOrPercentageOrNone(lopn) => {
|
GenericMaxLength::LengthOrPercentageOrNone(lopn) => {
|
||||||
let result = match lopn {
|
let result = match lopn {
|
||||||
LengthOrPercentageOrNone::Length(px) => {
|
LengthOrPercentageOrNone::LengthOrPercentage(len) => {
|
||||||
LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
|
LengthOrPercentageOrNone::LengthOrPercentage(len.clamp_to_non_negative())
|
||||||
},
|
},
|
||||||
LengthOrPercentageOrNone::Percentage(percentage) => {
|
LengthOrPercentageOrNone::None => lopn,
|
||||||
LengthOrPercentageOrNone::Percentage(Percentage(percentage.0.max(0.)))
|
|
||||||
},
|
|
||||||
_ => lopn,
|
|
||||||
};
|
};
|
||||||
GenericMaxLength::LengthOrPercentageOrNone(result)
|
GenericMaxLength::LengthOrPercentageOrNone(result)
|
||||||
},
|
},
|
||||||
|
@ -104,20 +75,10 @@ impl ToAnimatedValue for ComputedMozLength {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
use crate::values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
|
|
||||||
use crate::values::generics::length::MozLength as GenericMozLength;
|
use crate::values::generics::length::MozLength as GenericMozLength;
|
||||||
match animated {
|
match animated {
|
||||||
GenericMozLength::LengthOrPercentageOrAuto(lopa) => {
|
GenericMozLength::LengthOrPercentageOrAuto(lopa) => {
|
||||||
let result = match lopa {
|
GenericMozLength::LengthOrPercentageOrAuto(lopa.clamp_to_non_negative())
|
||||||
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)
|
|
||||||
},
|
},
|
||||||
_ => animated,
|
_ => animated,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
//! module's raison d'être is to ultimately contain all these types.
|
//! module's raison d'être is to ultimately contain all these types.
|
||||||
|
|
||||||
use crate::properties::PropertyId;
|
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::url::ComputedUrl;
|
||||||
use crate::values::computed::Angle as ComputedAngle;
|
use crate::values::computed::Angle as ComputedAngle;
|
||||||
use crate::values::computed::Image;
|
use crate::values::computed::Image;
|
||||||
|
@ -335,7 +335,7 @@ macro_rules! trivial_to_animated_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
trivial_to_animated_value!(Au);
|
trivial_to_animated_value!(Au);
|
||||||
trivial_to_animated_value!(CalcLengthOrPercentage);
|
trivial_to_animated_value!(LengthOrPercentage);
|
||||||
trivial_to_animated_value!(ComputedAngle);
|
trivial_to_animated_value!(ComputedAngle);
|
||||||
trivial_to_animated_value!(ComputedUrl);
|
trivial_to_animated_value!(ComputedUrl);
|
||||||
trivial_to_animated_value!(bool);
|
trivial_to_animated_value!(bool);
|
||||||
|
|
|
@ -32,10 +32,16 @@ fn to_number_or_percentage(
|
||||||
value: &SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number>,
|
value: &SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number>,
|
||||||
) -> Result<NumberOrPercentage, ()> {
|
) -> Result<NumberOrPercentage, ()> {
|
||||||
Ok(match *value {
|
Ok(match *value {
|
||||||
SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref l) => match *l {
|
SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref l) => {
|
||||||
LengthOrPercentage::Length(ref l) => NumberOrPercentage::Number(l.px()),
|
match l.percentage {
|
||||||
LengthOrPercentage::Percentage(ref p) => NumberOrPercentage::Percentage(*p),
|
Some(p) => {
|
||||||
LengthOrPercentage::Calc(..) => return Err(()),
|
if l.unclamped_length().px() != 0. {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
NumberOrPercentage::Percentage(p)
|
||||||
|
}
|
||||||
|
None => NumberOrPercentage::Number(l.length().px())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
SvgLengthOrPercentageOrNumber::Number(ref n) => NumberOrPercentage::Number(*n),
|
SvgLengthOrPercentageOrNumber::Number(ref n) => NumberOrPercentage::Number(*n),
|
||||||
})
|
})
|
||||||
|
@ -55,7 +61,7 @@ impl Animate for SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> {
|
||||||
NumberOrPercentage::Percentage(ref this),
|
NumberOrPercentage::Percentage(ref this),
|
||||||
NumberOrPercentage::Percentage(ref other),
|
NumberOrPercentage::Percentage(ref other),
|
||||||
) => Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
) => Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
LengthOrPercentage::Percentage(this.animate(other, procedure)?),
|
LengthOrPercentage::new_percent(this.animate(other, procedure)?),
|
||||||
)),
|
)),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1167,17 +1167,6 @@ impl Animate for ComputedTransformOperation {
|
||||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1318591#c0.
|
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1318591#c0.
|
||||||
impl ComputeSquaredDistance for ComputedTransformOperation {
|
impl ComputeSquaredDistance for ComputedTransformOperation {
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
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) {
|
match (self, other) {
|
||||||
(&TransformOperation::Matrix3D(ref this), &TransformOperation::Matrix3D(ref other)) => {
|
(&TransformOperation::Matrix3D(ref this), &TransformOperation::Matrix3D(ref other)) => {
|
||||||
this.compute_squared_distance(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 fx, ref fy, ref fz),
|
||||||
&TransformOperation::Translate3D(ref tx, ref ty, ref tz),
|
&TransformOperation::Translate3D(ref tx, ref ty, ref tz),
|
||||||
) => {
|
) => {
|
||||||
let fx = extract_pixel_length(&fx);
|
// For translate, We don't want to require doing layout in order
|
||||||
let fy = extract_pixel_length(&fy);
|
// to calculate the result, so drop the percentage part.
|
||||||
let tx = extract_pixel_length(&tx);
|
//
|
||||||
let ty = extract_pixel_length(&ty);
|
// 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)? +
|
Ok(fx.compute_squared_distance(&tx)? +
|
||||||
fy.compute_squared_distance(&ty)? +
|
fy.compute_squared_distance(&ty)? +
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
use crate::values::computed::position::Position;
|
use crate::values::computed::position::Position;
|
||||||
use crate::values::computed::url::ComputedImageUrl;
|
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::{Angle, Color, Context};
|
||||||
use crate::values::computed::{Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
use crate::values::computed::{Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
||||||
use crate::values::generics::image::{self as generic, CompatMode};
|
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::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
|
||||||
LineDirection::Corner(..) => false,
|
LineDirection::Corner(..) => false,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
LineDirection::MozPosition(
|
LineDirection::MozPosition(Some(Position { ref vertical, ref horizontal }), None) => {
|
||||||
Some(Position {
|
|
||||||
horizontal: LengthOrPercentage::Percentage(Percentage(x)),
|
|
||||||
vertical: LengthOrPercentage::Percentage(Percentage(y)),
|
|
||||||
}),
|
|
||||||
None,
|
|
||||||
) => {
|
|
||||||
// `50% 0%` is the default value for line direction.
|
// `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,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! `<length>` computed values, and related ones.
|
//! `<length>` computed values, and related ones.
|
||||||
|
|
||||||
use super::{Context, Number, Percentage, ToComputedValue};
|
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::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use crate::values::generics::length::MaxLength as GenericMaxLength;
|
use crate::values::generics::length::MaxLength as GenericMaxLength;
|
||||||
use crate::values::generics::length::MozLength as GenericMozLength;
|
use crate::values::generics::length::MozLength as GenericMozLength;
|
||||||
|
@ -68,15 +68,38 @@ impl ToComputedValue for specified::Length {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedZero)]
|
#[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero)]
|
||||||
pub struct CalcLengthOrPercentage {
|
pub struct LengthOrPercentage {
|
||||||
#[animation(constant)]
|
#[animation(constant)]
|
||||||
pub clamping_mode: AllowedNumericType,
|
pub clamping_mode: AllowedNumericType,
|
||||||
length: Length,
|
length: Length,
|
||||||
pub percentage: Option<Percentage>,
|
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]
|
#[inline]
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||||
// FIXME(nox): This looks incorrect to me, to add a distance between lengths
|
// FIXME(nox): This looks incorrect to me, to add a distance between lengths
|
||||||
|
@ -89,24 +112,36 @@ impl ComputeSquaredDistance for CalcLengthOrPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CalcLengthOrPercentage {
|
impl LengthOrPercentage {
|
||||||
/// Returns a new `CalcLengthOrPercentage`.
|
/// Returns a new `LengthOrPercentage`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(length: Length, percentage: Option<Percentage>) -> Self {
|
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]
|
#[inline]
|
||||||
pub fn with_clamping_mode(
|
pub fn with_clamping_mode(
|
||||||
length: Length,
|
length: Length,
|
||||||
percentage: Option<Percentage>,
|
percentage: Option<Percentage>,
|
||||||
clamping_mode: AllowedNumericType,
|
clamping_mode: AllowedNumericType,
|
||||||
|
was_calc: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
clamping_mode,
|
clamping_mode,
|
||||||
length,
|
length,
|
||||||
percentage,
|
percentage,
|
||||||
|
was_calc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,22 +166,38 @@ impl CalcLengthOrPercentage {
|
||||||
self.length
|
self.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Return the percentage value as CSSFloat.
|
/// Return the percentage value as CSSFloat.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn percentage(&self) -> CSSFloat {
|
pub fn percentage(&self) -> CSSFloat {
|
||||||
self.percentage.map_or(0., |p| p.0)
|
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.
|
/// Convert the computed value into used value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_used_value(&self, container_len: Option<Au>) -> Option<Au> {
|
pub fn maybe_to_used_value(&self, container_len: Option<Au>) -> Option<Au> {
|
||||||
self.to_pixel_length(container_len).map(Au::from)
|
self.maybe_to_pixel_length(container_len).map(Au::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If there are special rules for computing percentages in a value (e.g.
|
/// If there are special rules for computing percentages in a value (e.g.
|
||||||
/// the height property), they apply whenever a calc() expression contains
|
/// the height property), they apply whenever a calc() expression contains
|
||||||
/// percentages.
|
/// 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) {
|
match (container_len, self.percentage) {
|
||||||
(Some(len), Some(percent)) => {
|
(Some(len), Some(percent)) => {
|
||||||
let pixel = self.length.px() + len.scale_by(percent.0).to_f32_px();
|
let pixel = self.length.px() + len.scale_by(percent.0).to_f32_px();
|
||||||
|
@ -158,81 +209,12 @@ impl CalcLengthOrPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LengthOrPercentage> for CalcLengthOrPercentage {
|
impl ToCss for LengthOrPercentage {
|
||||||
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 {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
use num_traits::Zero;
|
specified::LengthOrPercentage::from_computed_value(self).to_css(dest)
|
||||||
|
|
||||||
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(")")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +225,7 @@ impl specified::CalcLengthOrPercentage {
|
||||||
context: &Context,
|
context: &Context,
|
||||||
zoom_fn: F,
|
zoom_fn: F,
|
||||||
base_size: FontBaseSize,
|
base_size: FontBaseSize,
|
||||||
) -> CalcLengthOrPercentage
|
) -> LengthOrPercentage
|
||||||
where
|
where
|
||||||
F: Fn(Length) -> Length,
|
F: Fn(Length) -> Length,
|
||||||
{
|
{
|
||||||
|
@ -277,10 +259,11 @@ impl specified::CalcLengthOrPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CalcLengthOrPercentage {
|
LengthOrPercentage {
|
||||||
clamping_mode: self.clamping_mode,
|
clamping_mode: self.clamping_mode,
|
||||||
length: Length::new(length.min(f32::MAX).max(f32::MIN)),
|
length: Length::new(length.min(f32::MAX).max(f32::MIN)),
|
||||||
percentage: self.percentage,
|
percentage: self.percentage,
|
||||||
|
was_calc: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +272,7 @@ impl specified::CalcLengthOrPercentage {
|
||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
base_size: FontBaseSize,
|
base_size: FontBaseSize,
|
||||||
) -> CalcLengthOrPercentage {
|
) -> LengthOrPercentage {
|
||||||
self.to_computed_value_with_zoom(
|
self.to_computed_value_with_zoom(
|
||||||
context,
|
context,
|
||||||
|abs| context.maybe_zoom_text(abs.into()).0,
|
|abs| context.maybe_zoom_text(abs.into()).0,
|
||||||
|
@ -324,15 +307,15 @@ impl specified::CalcLengthOrPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for 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
|
// 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)
|
self.to_computed_value_with_zoom(context, |abs| abs, FontBaseSize::CurrentStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_computed_value(computed: &CalcLengthOrPercentage) -> Self {
|
fn from_computed_value(computed: &LengthOrPercentage) -> Self {
|
||||||
specified::CalcLengthOrPercentage {
|
specified::CalcLengthOrPercentage {
|
||||||
clamping_mode: computed.clamping_mode,
|
clamping_mode: computed.clamping_mode,
|
||||||
absolute: Some(AbsoluteLength::from_computed_value(&computed.length)),
|
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 {
|
impl LengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn zero() -> LengthOrPercentage {
|
pub fn zero() -> LengthOrPercentage {
|
||||||
LengthOrPercentage::Length(Length::new(0.))
|
LengthOrPercentage::new(Length::new(0.), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// 1px length value for SVG defaults
|
/// 1px length value for SVG defaults
|
||||||
|
#[inline]
|
||||||
pub fn one() -> LengthOrPercentage {
|
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 true if the computed value is absolute 0 or 0%.
|
||||||
///
|
|
||||||
/// (Returns false for calc() values, even if ones that may resolve to zero.)
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_definitely_zero(&self) -> bool {
|
pub fn is_definitely_zero(&self) -> bool {
|
||||||
use self::LengthOrPercentage::*;
|
self.unclamped_length().px() == 0.0 && self.percentage.map_or(true, |p| p.0 == 0.0)
|
||||||
match *self {
|
|
||||||
Length(l) => l.px() == 0.0,
|
|
||||||
Percentage(p) => p.0 == 0.0,
|
|
||||||
Calc(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the
|
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the
|
||||||
// hash key.
|
// hash key.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
|
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
|
||||||
use self::LengthOrPercentage::*;
|
(
|
||||||
match *self {
|
Au::from(self.unclamped_length()),
|
||||||
Length(l) => (Au::from(l), NotNan::new(0.0).unwrap()),
|
NotNan::new(self.percentage()).unwrap(),
|
||||||
Percentage(p) => (Au(0), NotNan::new(p.0).unwrap()),
|
)
|
||||||
Calc(c) => (
|
|
||||||
Au::from(c.unclamped_length()),
|
|
||||||
NotNan::new(c.percentage()).unwrap(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the used value.
|
/// Returns the used value.
|
||||||
|
@ -440,27 +361,40 @@ impl LengthOrPercentage {
|
||||||
|
|
||||||
/// Returns the used value as CSSPixelLength.
|
/// Returns the used value as CSSPixelLength.
|
||||||
pub fn to_pixel_length(&self, containing_length: Au) -> Length {
|
pub fn to_pixel_length(&self, containing_length: Au) -> Length {
|
||||||
match *self {
|
self.maybe_to_pixel_length(Some(containing_length)).unwrap()
|
||||||
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()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the clamped non-negative values.
|
/// 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]
|
#[inline]
|
||||||
pub fn clamp_to_non_negative(self) -> Self {
|
pub fn clamp_to_non_negative(self) -> Self {
|
||||||
match self {
|
if self.was_calc {
|
||||||
LengthOrPercentage::Length(length) => {
|
return Self::with_clamping_mode(
|
||||||
LengthOrPercentage::Length(length.clamp_to_non_negative())
|
self.length,
|
||||||
},
|
self.percentage,
|
||||||
LengthOrPercentage::Percentage(percentage) => {
|
AllowedNumericType::NonNegative,
|
||||||
LengthOrPercentage::Percentage(percentage.clamp_to_non_negative())
|
self.was_calc,
|
||||||
},
|
)
|
||||||
_ => self,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
fn to_computed_value(&self, context: &Context) -> LengthOrPercentage {
|
||||||
match *self {
|
match *self {
|
||||||
specified::LengthOrPercentage::Length(ref value) => {
|
specified::LengthOrPercentage::Length(ref value) => {
|
||||||
LengthOrPercentage::Length(value.to_computed_value(context))
|
LengthOrPercentage::new(value.to_computed_value(context), None)
|
||||||
},
|
},
|
||||||
specified::LengthOrPercentage::Percentage(value) => {
|
specified::LengthOrPercentage::Percentage(value) => {
|
||||||
LengthOrPercentage::Percentage(value)
|
LengthOrPercentage::new_percent(value)
|
||||||
},
|
},
|
||||||
specified::LengthOrPercentage::Calc(ref calc) => {
|
specified::LengthOrPercentage::Calc(ref calc) => {
|
||||||
LengthOrPercentage::Calc((**calc).to_computed_value(context))
|
(**calc).to_computed_value(context)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_computed_value(computed: &LengthOrPercentage) -> Self {
|
fn from_computed_value(computed: &LengthOrPercentage) -> Self {
|
||||||
match *computed {
|
let length = computed.unclamped_length();
|
||||||
LengthOrPercentage::Length(value) => {
|
if let Some(p) = computed.as_percentage() {
|
||||||
specified::LengthOrPercentage::Length(ToComputedValue::from_computed_value(&value))
|
return specified::LengthOrPercentage::Percentage(p)
|
||||||
},
|
|
||||||
LengthOrPercentage::Percentage(value) => {
|
|
||||||
specified::LengthOrPercentage::Percentage(value)
|
|
||||||
},
|
|
||||||
LengthOrPercentage::Calc(ref calc) => specified::LengthOrPercentage::Calc(Box::new(
|
|
||||||
ToComputedValue::from_computed_value(calc),
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
impl IsZeroLength for LengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_zero_length(&self) -> bool {
|
fn is_zero_length(&self) -> bool {
|
||||||
match *self {
|
self.is_definitely_zero()
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[animate(fallback = "Self::animate_fallback")]
|
|
||||||
#[css(derive_debug)]
|
#[css(derive_debug)]
|
||||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToCss)]
|
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss)]
|
||||||
#[distance(fallback = "Self::compute_squared_distance_fallback")]
|
|
||||||
pub enum LengthOrPercentageOrAuto {
|
pub enum LengthOrPercentageOrAuto {
|
||||||
Length(Length),
|
LengthOrPercentage(LengthOrPercentage),
|
||||||
Percentage(Percentage),
|
|
||||||
Auto,
|
Auto,
|
||||||
Calc(CalcLengthOrPercentage),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthOrPercentageOrAuto {
|
impl LengthOrPercentageOrAuto {
|
||||||
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
|
/// Returns the `0` value.
|
||||||
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(())?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compute_squared_distance_fallback(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
pub fn zero() -> Self {
|
||||||
<Option<CalcLengthOrPercentage>>::compute_squared_distance(
|
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::zero())
|
||||||
&(*self).into(),
|
|
||||||
&(*other).into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,24 +492,21 @@ impl ToAnimatedValue for NonNegativeLengthOrPercentageOrAuto {
|
||||||
|
|
||||||
impl LengthOrPercentageOrAuto {
|
impl LengthOrPercentageOrAuto {
|
||||||
/// Returns true if the computed value is absolute 0 or 0%.
|
/// 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]
|
#[inline]
|
||||||
pub fn is_definitely_zero(&self) -> bool {
|
pub fn is_definitely_zero(&self) -> bool {
|
||||||
use self::LengthOrPercentageOrAuto::*;
|
use self::LengthOrPercentageOrAuto::*;
|
||||||
match *self {
|
match *self {
|
||||||
Length(l) => l.px() == 0.0,
|
LengthOrPercentage(ref l) => l.is_definitely_zero(),
|
||||||
Percentage(p) => p.0 == 0.0,
|
Auto => false,
|
||||||
Calc(_) | 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::*;
|
use self::LengthOrPercentageOrAuto::*;
|
||||||
match self {
|
match self {
|
||||||
Length(l) => Length(l.clamp_to_non_negative()),
|
LengthOrPercentage(l) => LengthOrPercentage(l.clamp_to_non_negative()),
|
||||||
Percentage(p) => Percentage(p.clamp_to_non_negative()),
|
Auto => Auto,
|
||||||
_ => self,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -600,16 +517,12 @@ impl ToComputedValue for specified::LengthOrPercentageOrAuto {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAuto {
|
fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrAuto {
|
||||||
match *self {
|
match *self {
|
||||||
specified::LengthOrPercentageOrAuto::Length(ref value) => {
|
specified::LengthOrPercentageOrAuto::LengthOrPercentage(ref value) => {
|
||||||
LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
|
LengthOrPercentageOrAuto::LengthOrPercentage(
|
||||||
},
|
value.to_computed_value(context),
|
||||||
specified::LengthOrPercentageOrAuto::Percentage(value) => {
|
)
|
||||||
LengthOrPercentageOrAuto::Percentage(value)
|
|
||||||
},
|
},
|
||||||
specified::LengthOrPercentageOrAuto::Auto => LengthOrPercentageOrAuto::Auto,
|
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 {
|
fn from_computed_value(computed: &LengthOrPercentageOrAuto) -> Self {
|
||||||
match *computed {
|
match *computed {
|
||||||
LengthOrPercentageOrAuto::Auto => specified::LengthOrPercentageOrAuto::Auto,
|
LengthOrPercentageOrAuto::Auto => specified::LengthOrPercentageOrAuto::Auto,
|
||||||
LengthOrPercentageOrAuto::Length(value) => specified::LengthOrPercentageOrAuto::Length(
|
LengthOrPercentageOrAuto::LengthOrPercentage(ref value) => {
|
||||||
ToComputedValue::from_computed_value(&value),
|
specified::LengthOrPercentageOrAuto::LengthOrPercentage(
|
||||||
),
|
ToComputedValue::from_computed_value(value),
|
||||||
LengthOrPercentageOrAuto::Percentage(value) => {
|
)
|
||||||
specified::LengthOrPercentageOrAuto::Percentage(value)
|
|
||||||
},
|
},
|
||||||
LengthOrPercentageOrAuto::Calc(calc) => specified::LengthOrPercentageOrAuto::Calc(
|
|
||||||
Box::new(ToComputedValue::from_computed_value(&calc)),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[animate(fallback = "Self::animate_fallback")]
|
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
|
||||||
#[css(derive_debug)]
|
#[css(derive_debug)]
|
||||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)]
|
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss)]
|
||||||
#[distance(fallback = "Self::compute_squared_distance_fallback")]
|
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Length),
|
LengthOrPercentage(LengthOrPercentage),
|
||||||
Percentage(Percentage),
|
|
||||||
Calc(CalcLengthOrPercentage),
|
|
||||||
None,
|
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 {
|
impl LengthOrPercentageOrNone {
|
||||||
/// Returns the used value.
|
/// Returns the used value.
|
||||||
pub fn to_used_value(&self, containing_length: Au) -> Option<Au> {
|
pub fn to_used_value(&self, containing_length: Au) -> Option<Au> {
|
||||||
match *self {
|
match *self {
|
||||||
LengthOrPercentageOrNone::None => None,
|
LengthOrPercentageOrNone::None => None,
|
||||||
LengthOrPercentageOrNone::Length(length) => Some(Au::from(length)),
|
LengthOrPercentageOrNone::LengthOrPercentage(ref lop) => {
|
||||||
LengthOrPercentageOrNone::Percentage(percent) => {
|
Some(lop.to_used_value(containing_length))
|
||||||
Some(containing_length.scale_by(percent.0))
|
|
||||||
},
|
},
|
||||||
LengthOrPercentageOrNone::Calc(ref calc) => calc.to_used_value(Some(containing_length)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(emilio): Derive this.
|
||||||
impl ToComputedValue for specified::LengthOrPercentageOrNone {
|
impl ToComputedValue for specified::LengthOrPercentageOrNone {
|
||||||
type ComputedValue = LengthOrPercentageOrNone;
|
type ComputedValue = LengthOrPercentageOrNone;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrNone {
|
fn to_computed_value(&self, context: &Context) -> LengthOrPercentageOrNone {
|
||||||
match *self {
|
match *self {
|
||||||
specified::LengthOrPercentageOrNone::Length(ref value) => {
|
specified::LengthOrPercentageOrNone::LengthOrPercentage(ref value) => {
|
||||||
LengthOrPercentageOrNone::Length(value.to_computed_value(context))
|
LengthOrPercentageOrNone::LengthOrPercentage(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::None => LengthOrPercentageOrNone::None,
|
specified::LengthOrPercentageOrNone::None => LengthOrPercentageOrNone::None,
|
||||||
}
|
}
|
||||||
|
@ -698,15 +577,11 @@ impl ToComputedValue for specified::LengthOrPercentageOrNone {
|
||||||
fn from_computed_value(computed: &LengthOrPercentageOrNone) -> Self {
|
fn from_computed_value(computed: &LengthOrPercentageOrNone) -> Self {
|
||||||
match *computed {
|
match *computed {
|
||||||
LengthOrPercentageOrNone::None => specified::LengthOrPercentageOrNone::None,
|
LengthOrPercentageOrNone::None => specified::LengthOrPercentageOrNone::None,
|
||||||
LengthOrPercentageOrNone::Length(value) => specified::LengthOrPercentageOrNone::Length(
|
LengthOrPercentageOrNone::LengthOrPercentage(value) => {
|
||||||
ToComputedValue::from_computed_value(&value),
|
specified::LengthOrPercentageOrNone::LengthOrPercentage(
|
||||||
),
|
ToComputedValue::from_computed_value(&value),
|
||||||
LengthOrPercentageOrNone::Percentage(value) => {
|
)
|
||||||
specified::LengthOrPercentageOrNone::Percentage(value)
|
|
||||||
},
|
},
|
||||||
LengthOrPercentageOrNone::Calc(calc) => specified::LengthOrPercentageOrNone::Calc(
|
|
||||||
Box::new(ToComputedValue::from_computed_value(&calc)),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -719,19 +594,19 @@ impl ToAnimatedValue for NonNegativeLengthOrPercentage {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||||
self.into()
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
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 {
|
impl From<NonNegativeLength> for NonNegativeLengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(length: NonNegativeLength) -> Self {
|
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 {
|
impl NonNegativeLengthOrPercentage {
|
||||||
/// Get zero value.
|
/// Get zero value.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -798,11 +682,6 @@ impl CSSPixelLength {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn clamp_to_non_negative(self) -> Self {
|
|
||||||
Self::new(self.px().max(0.))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the length with app_unit i32 type.
|
/// Return the length with app_unit i32 type.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_i32_au(&self) -> i32 {
|
pub fn to_i32_au(&self) -> i32 {
|
||||||
|
@ -810,11 +689,19 @@ impl CSSPixelLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the absolute value of this length.
|
/// Return the absolute value of this length.
|
||||||
|
#[inline]
|
||||||
pub fn abs(self) -> Self {
|
pub fn abs(self) -> Self {
|
||||||
CSSPixelLength::new(self.0.abs())
|
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
|
/// Zero value
|
||||||
|
#[inline]
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
CSSPixelLength::new(0.)
|
CSSPixelLength::new(0.)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier,
|
||||||
pub use self::gecko::ScrollSnapPoint;
|
pub use self::gecko::ScrollSnapPoint;
|
||||||
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
|
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
|
||||||
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
|
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::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
|
||||||
pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto};
|
pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
|
|
@ -28,8 +28,8 @@ impl Position {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn center() -> Self {
|
pub fn center() -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@ impl TransformOrigin {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn initial_value() -> Self {
|
pub fn initial_value() -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||||
LengthOrPercentage::Percentage(Percentage(0.5)),
|
LengthOrPercentage::new_percent(Percentage(0.5)),
|
||||||
Length::new(0.),
|
Length::new(0.),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,10 +103,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> ToAnimatedZero for Spacing<V>
|
impl<V> ToAnimatedZero for Spacing<V> {
|
||||||
where
|
|
||||||
V: From<Au>,
|
|
||||||
{
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||||
Err(())
|
Err(())
|
||||||
|
|
|
@ -288,18 +288,14 @@ impl ToAbsoluteLength for ComputedLength {
|
||||||
impl ToAbsoluteLength for ComputedLengthOrPercentage {
|
impl ToAbsoluteLength for ComputedLengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_pixel_length(&self, containing_len: Option<Au>) -> Result<CSSFloat, ()> {
|
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 {
|
match containing_len {
|
||||||
Some(relative_len) => Ok(self.to_pixel_length(relative_len).px()),
|
Some(relative_len) => Ok(self.to_pixel_length(relative_len).px()),
|
||||||
// If we don't have reference box, we cannot resolve the used value,
|
// 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
|
// so only retrieve the length part. This will be used for computing
|
||||||
// distance without any layout info.
|
// 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()));
|
info = parent.keyword_info.map(|i| i.compose(ratio, abs.into()));
|
||||||
}
|
}
|
||||||
let calc = calc.to_computed_value_zoomed(context, base_size);
|
let calc = calc.to_computed_value_zoomed(context, base_size);
|
||||||
calc.to_used_value(Some(base_size.resolve(context)))
|
calc.to_used_value(base_size.resolve(context)).into()
|
||||||
.unwrap()
|
|
||||||
.into()
|
|
||||||
},
|
},
|
||||||
FontSize::Keyword(i) => {
|
FontSize::Keyword(i) => {
|
||||||
// As a specified keyword, this is keyword derived
|
// As a specified keyword, this is keyword derived
|
||||||
|
|
|
@ -789,6 +789,12 @@ impl LengthOrPercentage {
|
||||||
LengthOrPercentage::Length(NoCalcLength::zero())
|
LengthOrPercentage::Length(NoCalcLength::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Returns a `0%` value.
|
||||||
|
pub fn zero_percent() -> LengthOrPercentage {
|
||||||
|
LengthOrPercentage::Percentage(computed::Percentage::zero())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_internal<'i, 't>(
|
fn parse_internal<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
|
@ -898,24 +904,8 @@ impl IsZeroLength for LengthOrPercentage {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||||
pub enum LengthOrPercentageOrAuto {
|
pub enum LengthOrPercentageOrAuto {
|
||||||
Length(NoCalcLength),
|
LengthOrPercentage(LengthOrPercentage),
|
||||||
Percentage(computed::Percentage),
|
|
||||||
Auto,
|
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 {
|
impl LengthOrPercentageOrAuto {
|
||||||
|
@ -925,48 +915,16 @@ impl LengthOrPercentageOrAuto {
|
||||||
num_context: AllowedNumericType,
|
num_context: AllowedNumericType,
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
// FIXME: remove early returns when lifetimes are non-lexical
|
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||||
{
|
return Ok(LengthOrPercentageOrAuto::Auto);
|
||||||
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())),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let calc = input.parse_nested_block(|i| {
|
Ok(LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::parse_internal(
|
||||||
CalcNode::parse_length_or_percentage(context, i, num_context)
|
context,
|
||||||
})?;
|
input,
|
||||||
Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
|
num_context,
|
||||||
|
allow_quirks,
|
||||||
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length, percentage, or auto.
|
/// Parse a non-negative length, percentage, or auto.
|
||||||
|
@ -1000,13 +958,13 @@ impl LengthOrPercentageOrAuto {
|
||||||
|
|
||||||
/// Returns a value representing a `0` length.
|
/// Returns a value representing a `0` length.
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
LengthOrPercentageOrAuto::Length(NoCalcLength::zero())
|
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a value representing `0%`.
|
/// Returns a value representing `0%`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero_percent() -> Self {
|
pub fn zero_percent() -> Self {
|
||||||
LengthOrPercentageOrAuto::Percentage(computed::Percentage::zero())
|
LengthOrPercentageOrAuto::LengthOrPercentage(LengthOrPercentage::zero_percent())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
|
@ -1076,9 +1034,7 @@ impl Parse for NonNegativeLengthOrPercentageOrAuto {
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(NoCalcLength),
|
LengthOrPercentage(LengthOrPercentage),
|
||||||
Percentage(computed::Percentage),
|
|
||||||
Calc(Box<CalcLengthOrPercentage>),
|
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,48 +1045,16 @@ impl LengthOrPercentageOrNone {
|
||||||
num_context: AllowedNumericType,
|
num_context: AllowedNumericType,
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
// FIXME: remove early returns when lifetimes are non-lexical
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
{
|
return Ok(LengthOrPercentageOrNone::None);
|
||||||
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())),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let calc = input.parse_nested_block(|i| {
|
Ok(LengthOrPercentageOrNone::LengthOrPercentage(LengthOrPercentage::parse_internal(
|
||||||
CalcNode::parse_length_or_percentage(context, i, num_context)
|
context,
|
||||||
})?;
|
input,
|
||||||
Ok(LengthOrPercentageOrNone::Calc(Box::new(calc)))
|
num_context,
|
||||||
|
allow_quirks,
|
||||||
|
)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative LengthOrPercentageOrNone.
|
/// Parse a non-negative LengthOrPercentageOrNone.
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
use crate::hash::FxHashMap;
|
use crate::hash::FxHashMap;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::str::HTML_SPACE_CHARACTERS;
|
use crate::str::HTML_SPACE_CHARACTERS;
|
||||||
use crate::values::computed::CalcLengthOrPercentage;
|
|
||||||
use crate::values::computed::LengthOrPercentage as ComputedLengthOrPercentage;
|
use crate::values::computed::LengthOrPercentage as ComputedLengthOrPercentage;
|
||||||
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
||||||
use crate::values::generics::position::Position as GenericPosition;
|
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 {
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
match *self {
|
match *self {
|
||||||
PositionComponent::Center => ComputedLengthOrPercentage::Percentage(Percentage(0.5)),
|
PositionComponent::Center => ComputedLengthOrPercentage::new_percent(Percentage(0.5)),
|
||||||
PositionComponent::Side(ref keyword, None) => {
|
PositionComponent::Side(ref keyword, None) => {
|
||||||
let p = Percentage(if keyword.is_start() { 0. } else { 1. });
|
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() => {
|
PositionComponent::Side(ref keyword, Some(ref length)) if !keyword.is_start() => {
|
||||||
match length.to_computed_value(context) {
|
let length = length.to_computed_value(context);
|
||||||
ComputedLengthOrPercentage::Length(length) => ComputedLengthOrPercentage::Calc(
|
let p = Percentage(1. - length.percentage());
|
||||||
CalcLengthOrPercentage::new(-length, Some(Percentage::hundred())),
|
let l = -length.unclamped_length();
|
||||||
),
|
ComputedLengthOrPercentage::with_clamping_mode(
|
||||||
ComputedLengthOrPercentage::Percentage(p) => {
|
l,
|
||||||
ComputedLengthOrPercentage::Percentage(Percentage(1.0 - p.0))
|
Some(p),
|
||||||
},
|
length.clamping_mode,
|
||||||
ComputedLengthOrPercentage::Calc(calc) => {
|
length.was_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)))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
PositionComponent::Side(_, Some(ref length)) |
|
PositionComponent::Side(_, Some(ref length)) |
|
||||||
PositionComponent::Length(ref length) => length.to_computed_value(context),
|
PositionComponent::Length(ref length) => length.to_computed_value(context),
|
||||||
|
|
|
@ -323,12 +323,12 @@ where
|
||||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
match *self {
|
match *self {
|
||||||
OriginComponent::Center => {
|
OriginComponent::Center => {
|
||||||
ComputedLengthOrPercentage::Percentage(ComputedPercentage(0.5))
|
ComputedLengthOrPercentage::new_percent(ComputedPercentage(0.5))
|
||||||
},
|
},
|
||||||
OriginComponent::Length(ref length) => length.to_computed_value(context),
|
OriginComponent::Length(ref length) => length.to_computed_value(context),
|
||||||
OriginComponent::Side(ref keyword) => {
|
OriginComponent::Side(ref keyword) => {
|
||||||
let p = ComputedPercentage(if keyword.is_start() { 0. } else { 1. });
|
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