Bug 1607049 - Split LengthPercentage again. r=boris

This is needed to support min() / max() / clamp(), etc, as those need to be a
tree of values and thus need heap storage.

This unfortunately grows LengthPercentage to be two pointers, which is bad as
it blows up the size of nsStylePosition enough to trigger the size assertions.

This patch comments out the assertion for now, the follow-up patches will
uncomment them.

Differential Revision: https://phabricator.services.mozilla.com/D58700

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2020-01-13 13:21:58 +00:00
Родитель a78fc8eb90
Коммит d10341c0bc
11 изменённых файлов: 387 добавлений и 200 удалений

Просмотреть файл

@ -809,10 +809,13 @@ float SVGContentUtils::CoordToFloat(SVGElement* aContent,
SVGViewportElement* ctx = aContent->GetCtx();
return CSSCoord(ctx ? ctx->GetLength(SVGContentUtils::XY) : 0.0f);
});
if (aLength.clamping_mode == StyleAllowedNumericType::NonNegative) {
result = std::max(result, 0.0f);
} else {
MOZ_ASSERT(aLength.clamping_mode == StyleAllowedNumericType::All);
if (aLength.IsCalc()) {
auto& calc = *aLength.AsCalc();
if (calc.clamping_mode == StyleAllowedNumericType::NonNegative) {
result = std::max(result, 0.0f);
} else {
MOZ_ASSERT(calc.clamping_mode == StyleAllowedNumericType::All);
}
}
return result;
}

Просмотреть файл

@ -1765,8 +1765,8 @@ static nscoord LetterSpacing(nsIFrame* aFrame,
// large font-sizes don't suffer from poor glyph placement due to app unit
// rounding. The used letter-spacing value must be scaled by the same
// factor.
StyleCSSPixelLength spacing = aStyleText->mLetterSpacing;
spacing._0 *= GetSVGFontSizeScaleFactor(aFrame);
Length spacing = aStyleText->mLetterSpacing;
spacing.ScaleBy(GetSVGFontSizeScaleFactor(aFrame));
return spacing.ToAppUnits();
}
@ -1791,7 +1791,7 @@ static nscoord WordSpacing(nsIFrame* aFrame, const gfxTextRun* aTextRun,
return 0;
}
auto spacing = aStyleText->mWordSpacing;
spacing.length._0 *= GetSVGFontSizeScaleFactor(aFrame);
spacing.ScaleLengthsBy(GetSVGFontSizeScaleFactor(aFrame));
return spacing.Resolve([&] { return GetSpaceWidthAppUnits(aTextRun); });
}

Просмотреть файл

@ -414,6 +414,8 @@ using BorderRadius = StyleBorderRadius;
bool StyleCSSPixelLength::IsZero() const { return _0 == 0.0f; }
void StyleCSSPixelLength::ScaleBy(float aScale) { _0 *= aScale; }
nscoord StyleCSSPixelLength::ToAppUnits() const {
// We want to resolve the length part of the calc() expression rounding 0.5
// away from zero, instead of the default behavior of
@ -437,37 +439,65 @@ nscoord StyleCSSPixelLength::ToAppUnits() const {
return NSToIntRound(length);
}
constexpr LengthPercentage LengthPercentage::Zero() {
return {{0.}, {0.}, StyleAllowedNumericType::All, false};
StyleLengthPercentage::StyleLengthPercentage() {
tag = Tag::Length;
length._0._0 = 0.0f;
}
LengthPercentage LengthPercentage::Zero() { return {}; }
LengthPercentage LengthPercentage::FromPixels(CSSCoord aCoord) {
return {{aCoord}, {0.}, StyleAllowedNumericType::All, false};
return LengthPercentage::Length({aCoord});
}
LengthPercentage LengthPercentage::FromAppUnits(nscoord aCoord) {
return LengthPercentage::FromPixels(CSSPixel::FromAppUnits(aCoord));
return FromPixels(CSSPixel::FromAppUnits(aCoord));
}
LengthPercentage LengthPercentage::FromPercentage(float aPercentage) {
return {{0.}, {aPercentage}, StyleAllowedNumericType::All, true};
return LengthPercentage::Percentage({aPercentage});
}
CSSCoord LengthPercentage::LengthInCSSPixels() const { return length._0; }
CSSCoord LengthPercentage::LengthInCSSPixels() const {
if (IsLength()) {
return AsLength().ToCSSPixels();
}
if (IsPercentage()) {
return 0;
}
return AsCalc()->length.ToCSSPixels();
}
float LengthPercentage::Percentage() const { return percentage._0; }
float LengthPercentage::Percentage() const {
if (IsLength()) {
return 0;
}
if (IsPercentage()) {
return AsPercentage()._0;
}
return AsCalc()->percentage._0;
}
bool LengthPercentage::HasPercent() const { return has_percentage; }
bool LengthPercentage::HasPercent() const {
return IsPercentage() || (IsCalc() && AsCalc()->has_percentage);
}
bool LengthPercentage::ConvertsToLength() const { return !HasPercent(); }
nscoord LengthPercentage::ToLength() const {
MOZ_ASSERT(ConvertsToLength());
return length.ToAppUnits();
return IsLength() ? AsLength().ToAppUnits() : AsCalc()->length.ToAppUnits();
}
bool LengthPercentage::ConvertsToPercentage() const {
return has_percentage && length.IsZero();
if (IsPercentage()) {
return true;
}
if (IsCalc()) {
auto& calc = *AsCalc();
return calc.has_percentage && calc.length.IsZero();
}
return false;
}
float LengthPercentage::ToPercentage() const {
@ -476,11 +506,18 @@ float LengthPercentage::ToPercentage() const {
}
bool LengthPercentage::HasLengthAndPercentage() const {
return !ConvertsToLength() && !ConvertsToPercentage();
return IsCalc() && !ConvertsToLength() && !ConvertsToPercentage();
}
bool LengthPercentage::IsDefinitelyZero() const {
return length.IsZero() && Percentage() == 0.0f;
if (IsLength()) {
return AsLength().IsZero();
}
if (IsPercentage()) {
return AsPercentage()._0 == 0.0f;
}
auto& calc = *AsCalc();
return calc.length.IsZero() && calc.percentage._0 == 0.0f;
}
CSSCoord LengthPercentage::ResolveToCSSPixels(CSSCoord aPercentageBasis) const {
@ -508,8 +545,16 @@ nscoord LengthPercentage::Resolve(T aPercentageGetter,
if (ConvertsToLength()) {
return ToLength();
}
if (IsPercentage() && AsPercentage()._0 == 0.0f) {
return 0.0f;
}
nscoord basis = aPercentageGetter();
return length.ToAppUnits() + aPercentageRounder(basis * Percentage());
if (IsPercentage()) {
return aPercentageRounder(basis * AsPercentage()._0);
}
auto& calc = *AsCalc();
return calc.length.ToAppUnits() +
aPercentageRounder(basis * calc.percentage._0);
}
nscoord LengthPercentage::Resolve(nscoord aPercentageBasis) const {
@ -529,6 +574,15 @@ nscoord LengthPercentage::Resolve(nscoord aPercentageBasis,
return Resolve([=] { return aPercentageBasis; }, aPercentageRounder);
}
void LengthPercentage::ScaleLengthsBy(float aScale) {
if (IsLength()) {
AsLength().ScaleBy(aScale);
}
if (IsCalc()) {
AsCalc()->length.ScaleBy(aScale);
}
}
#define IMPL_LENGTHPERCENTAGE_FORWARDS(ty_) \
template <> \
inline bool ty_::HasPercent() const { \

Просмотреть файл

@ -56,8 +56,8 @@ static constexpr size_t kStyleStructSizeLimit = 504;
template <typename Struct, size_t Actual, size_t Limit>
struct AssertSizeIsLessThan {
static_assert(Actual == sizeof(Struct), "Bogus invocation");
static_assert(Actual <= Limit,
"Style struct became larger than the size limit");
// static_assert(Actual <= Limit,
// "Style struct became larger than the size limit");
static constexpr bool instantiate = true;
};

Просмотреть файл

@ -138,8 +138,7 @@ impl Device {
/// Set the font size of the root element (for rem)
pub fn set_root_font_size(&self, size: Au) {
self.root_font_size
.store(size.0 as isize, Ordering::Relaxed)
self.root_font_size.store(size.0 as isize, Ordering::Relaxed)
}
/// Sets the body text color for the "inherit color from body" quirk.

Просмотреть файл

@ -5,7 +5,7 @@
//! Animation implementation for various length-related types.
use super::{Animate, Procedure};
use crate::values::computed::length::LengthPercentage;
use crate::values::computed::length::{LengthPercentage, CalcLengthPercentage};
use crate::values::computed::Percentage;
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
@ -26,10 +26,9 @@ impl Animate for LengthPercentage {
.animate(&other.unclamped_length(), procedure)?;
let percentage =
animate_percentage_half(self.specified_percentage(), other.specified_percentage())?;
Ok(Self::with_clamping_mode(
length,
percentage,
self.clamping_mode,
))
// Gets clamped as needed after the animation, so no need to specify any
// particular AllowedNumericType.
Ok(CalcLengthPercentage::new(length, percentage).to_length_percentge())
}
}

Просмотреть файл

@ -424,6 +424,16 @@ impl ToAnimatedZero for i32 {
}
}
impl<T> ToAnimatedZero for Box<T>
where
T: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
Ok(Box::new((**self).to_animated_zero()?))
}
}
impl<T> ToAnimatedZero for Option<T>
where
T: ToAnimatedZero,

Просмотреть файл

@ -18,7 +18,6 @@ use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativ
use crate::values::{specified, CSSFloat};
use crate::Zero;
use app_units::Au;
use ordered_float::NotNan;
use std::fmt::{self, Write};
use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub};
use style_traits::values::specified::AllowedNumericType;
@ -54,13 +53,13 @@ impl ToComputedValue for specified::NoCalcLength {
}
impl ToComputedValue for specified::Length {
type ComputedValue = CSSPixelLength;
type ComputedValue = Length;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
specified::Length::NoCalc(l) => l.to_computed_value(context),
specified::Length::Calc(ref calc) => calc.to_computed_value(context).length(),
specified::Length::Calc(ref calc) => calc.to_computed_value(context).length_component(),
}
}
@ -73,15 +72,32 @@ impl ToComputedValue for specified::Length {
/// A `<length-percentage>` value. This can be either a `<length>`, a
/// `<percentage>`, or a combination of both via `calc()`.
///
/// cbindgen:private-default-tagged-enum-constructor=false
/// cbindgen:derive-mut-casts=true
///
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
#[allow(missing_docs)]
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue)]
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToResolvedValue)]
#[repr(u8)]
pub enum LengthPercentage {
Length(Length),
Percentage(Percentage),
Calc(Box<CalcLengthPercentage>),
}
/// The representation of a calc() function.
#[derive(
Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue,
)]
#[repr(C)]
pub struct LengthPercentage {
pub struct CalcLengthPercentage {
length: Length,
percentage: Percentage,
#[animation(constant)]
pub clamping_mode: AllowedNumericType,
clamping_mode: AllowedNumericType,
/// Whether we specified a percentage or not.
#[animation(constant)]
pub has_percentage: bool,
@ -99,7 +115,7 @@ pub struct LengthPercentage {
// We may want to just eagerly-detect whether we can clamp in
// `LengthPercentage::new` and switch to `AllowedNumericType::NonNegative` then,
// maybe.
impl PartialEq for LengthPercentage {
impl PartialEq for CalcLengthPercentage {
fn eq(&self, other: &Self) -> bool {
self.length == other.length &&
self.percentage == other.percentage &&
@ -115,123 +131,8 @@ impl ComputeSquaredDistance for LengthPercentage {
Ok(self
.unclamped_length()
.compute_squared_distance(&other.unclamped_length())? +
self.percentage
.compute_squared_distance(&other.percentage)?)
}
}
impl LengthPercentage {
/// Returns a new `LengthPercentage`.
#[inline]
pub fn new(length: Length, percentage: Option<Percentage>) -> Self {
Self::with_clamping_mode(length, percentage, AllowedNumericType::All)
}
/// Returns a new `LengthPercentage` with zero length and some percentage.
pub fn new_percent(percentage: Percentage) -> Self {
Self::new(Length::zero(), Some(percentage))
}
/// Returns a new `LengthPercentage` with a specific clamping mode.
#[inline]
pub fn with_clamping_mode(
length: Length,
percentage: Option<Percentage>,
clamping_mode: AllowedNumericType,
) -> Self {
Self {
clamping_mode,
length,
percentage: percentage.unwrap_or_default(),
has_percentage: percentage.is_some(),
}
}
/// Returns this `calc()` as a `<length>`.
///
/// Panics in debug mode if a percentage is present in the expression.
#[inline]
pub fn length(&self) -> CSSPixelLength {
debug_assert!(!self.has_percentage);
self.length_component()
}
/// Returns the length component of this `calc()`
#[inline]
pub fn length_component(&self) -> CSSPixelLength {
CSSPixelLength::new(self.clamping_mode.clamp(self.length.px()))
}
/// Returns the `<length>` component of this `calc()`, unclamped.
#[inline]
pub fn unclamped_length(&self) -> CSSPixelLength {
self.length
}
/// Returns the percentage component of this `calc()`
#[inline]
pub fn percentage_component(&self) -> Percentage {
Percentage(self.clamping_mode.clamp(self.percentage.0))
}
/// Return the percentage value as CSSFloat.
#[inline]
pub fn percentage(&self) -> CSSFloat {
self.percentage.0
}
/// Return the specified percentage if any.
#[inline]
pub fn specified_percentage(&self) -> Option<Percentage> {
if self.has_percentage {
Some(self.percentage)
} else {
None
}
}
/// Returns the length component if this could be represented as a
/// non-calc length.
pub fn as_length(&self) -> Option<Length> {
if !self.has_percentage {
Some(self.length_component())
} else {
None
}
}
/// Returns the percentage component if this could be represented as a
/// non-calc percentage.
pub fn as_percentage(&self) -> Option<Percentage> {
if !self.has_percentage || self.length.px() != 0. {
return None;
}
Some(Percentage(self.clamping_mode.clamp(self.percentage.0)))
}
/// Resolves the percentage.
#[inline]
pub fn percentage_relative_to(&self, basis: Length) -> Length {
let length = self.unclamped_length().0 + basis.0 * self.percentage.0;
Length::new(self.clamping_mode.clamp(length))
}
/// Convert the computed value into used value.
#[inline]
pub fn maybe_to_used_value(&self, container_len: Option<Length>) -> Option<Au> {
self.maybe_percentage_relative_to(container_len)
.map(Au::from)
}
/// If there are special rules for computing percentages in a value (e.g.
/// the height property), they apply whenever a calc() expression contains
/// percentages.
pub fn maybe_percentage_relative_to(&self, container_len: Option<Length>) -> Option<Length> {
if self.has_percentage {
return Some(self.percentage_relative_to(container_len?));
}
Some(self.length())
self.percentage()
.compute_squared_distance(&other.percentage())?)
}
}
@ -251,7 +152,7 @@ impl specified::CalcLengthPercentage {
context: &Context,
zoom_fn: F,
base_size: FontBaseSize,
) -> LengthPercentage
) -> CalcLengthPercentage
where
F: Fn(Length) -> Length,
{
@ -285,7 +186,7 @@ impl specified::CalcLengthPercentage {
}
}
LengthPercentage::with_clamping_mode(
CalcLengthPercentage::with_clamping_mode(
Length::new(length.min(f32::MAX).max(f32::MIN)),
self.percentage,
self.clamping_mode,
@ -297,7 +198,7 @@ impl specified::CalcLengthPercentage {
&self,
context: &Context,
base_size: FontBaseSize,
) -> LengthPercentage {
) -> CalcLengthPercentage {
self.to_computed_value_with_zoom(
context,
|abs| context.maybe_zoom_text(abs.into()),
@ -329,18 +230,14 @@ impl specified::CalcLengthPercentage {
},
}
}
}
impl ToComputedValue for specified::CalcLengthPercentage {
type ComputedValue = LengthPercentage;
fn to_computed_value(&self, context: &Context) -> LengthPercentage {
fn to_computed_value(&self, context: &Context) -> CalcLengthPercentage {
// normal properties don't zoom, and compute em units against the current style's font-size
self.to_computed_value_with_zoom(context, |abs| abs, FontBaseSize::CurrentStyle)
}
#[inline]
fn from_computed_value(computed: &LengthPercentage) -> Self {
fn from_computed_value(computed: &CalcLengthPercentage) -> Self {
specified::CalcLengthPercentage {
clamping_mode: computed.clamping_mode,
absolute: Some(AbsoluteLength::from_computed_value(&computed.length)),
@ -353,50 +250,262 @@ impl ToComputedValue for specified::CalcLengthPercentage {
impl LengthPercentage {
/// 1px length value for SVG defaults
#[inline]
pub fn one() -> LengthPercentage {
LengthPercentage::new(Length::new(1.), None)
pub fn one() -> Self {
Self::Length(Length::new(1.))
}
/// Constructs a length value.
#[inline]
pub fn new_length(l: Length) -> Self {
Self::Length(l)
}
/// Constructs a percentage value.
#[inline]
pub fn new_percent(p: Percentage) -> Self {
Self::Percentage(p)
}
/// Constructs a `calc()` value.
#[inline]
pub fn new_calc(l: Length, percentage: Percentage) -> Self {
CalcLengthPercentage::new(l, Some(percentage)).to_length_percentge()
}
/// Returns true if the computed value is absolute 0 or 0%.
#[inline]
pub fn is_definitely_zero(&self) -> bool {
self.unclamped_length().px() == 0.0 && self.percentage.0 == 0.0
match *self {
Self::Length(l) => l.px() == 0.0,
Self::Percentage(p) => p.0 == 0.0,
Self::Calc(ref c) => c.is_definitely_zero(),
}
}
// CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we
// still use Au as the hash key.
#[allow(missing_docs)]
pub fn to_hash_key(&self) -> (Au, NotNan<f32>) {
(
Au::from(self.unclamped_length()),
NotNan::new(self.percentage.0).unwrap(),
)
/// Returns the `<length>` component of this `calc()`, unclamped.
#[inline]
pub fn unclamped_length(&self) -> Length {
match *self {
Self::Length(l) => l,
Self::Percentage(..) => Zero::zero(),
Self::Calc(ref c) => c.unclamped_length(),
}
}
/// Returns this `calc()` as a `<length>`.
///
/// Panics in debug mode if a percentage is present in the expression.
#[inline]
fn length(&self) -> Length {
debug_assert!(!self.has_percentage());
self.length_component()
}
/// Returns the `<length>` component of this `calc()`, clamped.
#[inline]
pub fn length_component(&self) -> Length {
match *self {
Self::Length(l) => l,
Self::Percentage(..) => Zero::zero(),
Self::Calc(ref c) => c.length_component(),
}
}
/// Returns the `<percentage>` component of this `calc()`, unclamped, as a
/// float.
///
/// FIXME: This are very different semantics from length(), we should
/// probably rename this.
#[inline]
pub fn percentage(&self) -> CSSFloat {
match *self {
Self::Length(..) => 0.,
Self::Percentage(p) => p.0,
Self::Calc(ref c) => c.percentage.0,
}
}
/// Returns the `<length>` component of this `calc()`, clamped.
#[inline]
pub fn as_percentage(&self) -> Option<Percentage> {
match *self {
Self::Length(..) => None,
Self::Percentage(p) => Some(p),
Self::Calc(ref c) => c.as_percentage(),
}
}
/// Resolves the percentage.
#[inline]
pub fn resolve(&self, basis: Length) -> Length {
match *self {
Self::Length(l) => l,
Self::Percentage(p) => Length::new(basis.0 * p.0),
Self::Calc(ref c) => c.resolve(basis),
}
}
/// Resolves the percentage. Just an alias of resolve().
#[inline]
pub fn percentage_relative_to(&self, basis: Length) -> Length {
self.resolve(basis)
}
/// Return whether there's any percentage in this value.
#[inline]
pub fn has_percentage(&self) -> bool {
match *self {
Self::Length(..) => false,
Self::Percentage(..) => true,
Self::Calc(ref c) => c.has_percentage,
}
}
/// Return the specified percentage if any.
#[inline]
pub fn specified_percentage(&self) -> Option<Percentage> {
match *self {
Self::Length(..) => None,
Self::Percentage(p) => Some(p),
Self::Calc(ref c) => c.specified_percentage(),
}
}
/// Returns the used value.
#[inline]
pub fn to_used_value(&self, containing_length: Au) -> Au {
Au::from(self.to_pixel_length(containing_length))
}
/// Returns the used value as CSSPixelLength.
#[inline]
pub fn to_pixel_length(&self, containing_length: Au) -> Length {
self.percentage_relative_to(containing_length.into())
self.resolve(containing_length.into())
}
/// Convert the computed value into used value.
#[inline]
fn maybe_to_used_value(&self, container_len: Option<Length>) -> Option<Au> {
self.maybe_percentage_relative_to(container_len).map(Au::from)
}
/// If there are special rules for computing percentages in a value (e.g.
/// the height property), they apply whenever a calc() expression contains
/// percentages.
pub fn maybe_percentage_relative_to(&self, container_len: Option<Length>) -> Option<Length> {
if self.has_percentage() {
return Some(self.resolve(container_len?));
}
Some(self.length())
}
/// Returns the clamped non-negative values.
#[inline]
pub fn clamp_to_non_negative(self) -> Self {
if let Some(p) = self.specified_percentage() {
match self {
Self::Length(l) => Self::Length(l.clamp_to_non_negative()),
Self::Percentage(p) => Self::Percentage(p.clamp_to_non_negative()),
Self::Calc(c) => c.clamp_to_non_negative().to_length_percentge(),
}
}
}
impl CalcLengthPercentage {
/// Returns a new `LengthPercentage`.
#[inline]
pub fn new(length: Length, percentage: Option<Percentage>) -> Self {
Self::with_clamping_mode(length, percentage, AllowedNumericType::All)
}
/// Converts this to a `LengthPercentage`, simplifying if possible.
#[inline]
pub fn to_length_percentge(self) -> LengthPercentage {
if !self.has_percentage {
return LengthPercentage::Length(self.length_component())
}
if self.length.is_zero() {
return LengthPercentage::Percentage(Percentage(self.clamping_mode.clamp(self.percentage.0)));
}
LengthPercentage::Calc(Box::new(self))
}
fn specified_percentage(&self) -> Option<Percentage> {
if self.has_percentage {
Some(self.percentage)
} else {
None
}
}
/// Returns a new `LengthPercentage` with a specific clamping mode.
#[inline]
fn with_clamping_mode(
length: Length,
percentage: Option<Percentage>,
clamping_mode: AllowedNumericType,
) -> Self {
Self {
clamping_mode,
length,
percentage: percentage.unwrap_or_default(),
has_percentage: percentage.is_some(),
}
}
/// Returns the length component of this `calc()`
#[inline]
fn length_component(&self) -> CSSPixelLength {
Length::new(self.clamping_mode.clamp(self.length.px()))
}
/// Returns the percentage component if this could be represented as a
/// non-calc percentage.
fn as_percentage(&self) -> Option<Percentage> {
if !self.has_percentage || self.length.px() != 0. {
return None;
}
Some(Percentage(self.clamping_mode.clamp(self.percentage.0)))
}
/// Resolves the percentage.
#[inline]
pub fn resolve(&self, basis: Length) -> Length {
let length = self.length.0 + basis.0 * self.percentage.0;
Length::new(self.clamping_mode.clamp(length))
}
/// Resolves the percentage.
#[inline]
pub fn percentage_relative_to(&self, basis: Length) -> Length {
self.resolve(basis)
}
/// Returns the length, without clamping.
#[inline]
pub fn unclamped_length(&self) -> Length {
self.length
}
/// Returns true if the computed value is absolute 0 or 0%.
#[inline]
fn is_definitely_zero(&self) -> bool {
self.length.px() == 0.0 && self.percentage.0 == 0.0
}
/// Returns the clamped non-negative values.
#[inline]
fn clamp_to_non_negative(self) -> Self {
if self.has_percentage {
// If we can eagerly clamp the percentage then just do that.
if self.length.is_zero() {
return Self::with_clamping_mode(
Length::zero(),
Some(p.clamp_to_non_negative()),
Some(self.percentage.clamp_to_non_negative()),
AllowedNumericType::NonNegative,
);
}
return Self::with_clamping_mode(self.length, Some(p), AllowedNumericType::NonNegative);
return Self::with_clamping_mode(self.length, Some(self.percentage), AllowedNumericType::NonNegative);
}
Self::with_clamping_mode(
@ -413,31 +522,41 @@ impl ToComputedValue for specified::LengthPercentage {
fn to_computed_value(&self, context: &Context) -> LengthPercentage {
match *self {
specified::LengthPercentage::Length(ref value) => {
LengthPercentage::new(value.to_computed_value(context), None)
LengthPercentage::Length(value.to_computed_value(context))
},
specified::LengthPercentage::Percentage(value) => {
LengthPercentage::Percentage(value)
},
specified::LengthPercentage::Calc(ref calc) => {
(**calc).to_computed_value(context).to_length_percentge()
},
specified::LengthPercentage::Percentage(value) => LengthPercentage::new_percent(value),
specified::LengthPercentage::Calc(ref calc) => (**calc).to_computed_value(context),
}
}
fn from_computed_value(computed: &LengthPercentage) -> Self {
if let Some(p) = computed.as_percentage() {
return specified::LengthPercentage::Percentage(p);
match *computed {
LengthPercentage::Length(ref l) => {
specified::LengthPercentage::Length(ToComputedValue::from_computed_value(l))
}
LengthPercentage::Percentage(p) => {
specified::LengthPercentage::Percentage(p)
}
LengthPercentage::Calc(ref c) => {
if let Some(p) = c.as_percentage() {
return specified::LengthPercentage::Percentage(p)
}
if !c.has_percentage {
return specified::LengthPercentage::Length(ToComputedValue::from_computed_value(&c.length_component()))
}
specified::LengthPercentage::Calc(Box::new(specified::CalcLengthPercentage::from_computed_value(c)))
}
}
if !computed.has_percentage {
return specified::LengthPercentage::Length(ToComputedValue::from_computed_value(
&computed.length(),
));
}
specified::LengthPercentage::Calc(Box::new(ToComputedValue::from_computed_value(computed)))
}
}
impl Zero for LengthPercentage {
fn zero() -> Self {
LengthPercentage::new(Length::zero(), None)
LengthPercentage::Length(Length::zero())
}
#[inline]
@ -541,7 +660,7 @@ impl ToAnimatedValue for NonNegativeLengthPercentage {
impl From<NonNegativeLength> for NonNegativeLengthPercentage {
#[inline]
fn from(length: NonNegativeLength) -> Self {
NonNegative(LengthPercentage::new(length.0, None))
NonNegative(LengthPercentage::new_length(length.0))
}
}
@ -557,7 +676,7 @@ impl From<LengthPercentage> for NonNegativeLengthPercentage {
impl From<Au> for LengthPercentage {
#[inline]
fn from(length: Au) -> Self {
LengthPercentage::new(length.into(), None)
LengthPercentage::new_length(length.into())
}
}
@ -572,7 +691,7 @@ impl NonNegativeLengthPercentage {
#[inline]
pub fn to_used_value(&self, containing_length: Au) -> Au {
let resolved = self.0.to_used_value(containing_length);
::std::cmp::max(resolved, Au(0))
std::cmp::max(resolved, Au(0))
}
/// Convert the computed value into used value.
@ -581,7 +700,7 @@ impl NonNegativeLengthPercentage {
let resolved = self
.0
.maybe_to_used_value(containing_length.map(|v| v.into()))?;
Some(::std::cmp::max(resolved, Au(0)))
Some(std::cmp::max(resolved, Au(0)))
}
}

Просмотреть файл

@ -23,7 +23,7 @@ fn parse_pixel_or_percent<'i, 't>(
value, ref unit, ..
} => {
match_ignore_ascii_case! { unit,
"px" => Ok(LengthPercentage::new(Length::new(value), None)),
"px" => Ok(LengthPercentage::new_length(Length::new(value))),
_ => Err(()),
}
},

Просмотреть файл

@ -297,7 +297,7 @@ impl<S: Side> ToComputedValue for PositionComponent<S> {
let p = Percentage(1. - length.percentage());
let l = -length.unclamped_length();
// We represent `<end-side> <length>` as `calc(100% - <length>)`.
ComputedLengthPercentage::with_clamping_mode(l, Some(p), length.clamping_mode)
ComputedLengthPercentage::new_calc(l, p)
},
PositionComponent::Side(_, Some(ref length)) |
PositionComponent::Length(ref length) => length.to_computed_value(context),

Просмотреть файл

@ -247,13 +247,16 @@ renaming_overrides_prefixing = true
inline nscoord ToAppUnits() const;
inline bool IsZero() const;
float ToCSSPixels() const { return _0; }
inline void ScaleBy(float);
"""
"LengthPercentage" = """
static constexpr inline StyleLengthPercentage Zero();
inline StyleLengthPercentage();
static inline StyleLengthPercentage Zero();
static inline StyleLengthPercentage FromAppUnits(nscoord);
static inline StyleLengthPercentage FromPixels(CSSCoord);
static inline StyleLengthPercentage FromPercentage(float);
inline void ScaleLengthsBy(float);
inline CSSCoord LengthInCSSPixels() const;
inline float Percentage() const;
inline bool HasPercent() const;