mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
style: Pack LengthPercentage better.
So that it takes one pointer instead of two, and doesn't make nsStylePosition's size blow up. This is not as ugly as I was fearing, thankfully, though it requires a bit of boilerplate. I think it's acceptable. Differential Revision: https://phabricator.services.mozilla.com/D58702
This commit is contained in:
parent
4d5bd94a2b
commit
88fe64d845
2 changed files with 315 additions and 58 deletions
|
@ -3,19 +3,83 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! `<length-percentage>` computed values, and related ones.
|
//! `<length-percentage>` computed values, and related ones.
|
||||||
|
//!
|
||||||
|
//! The over-all design is a tagged pointer, with the lower bits of the pointer
|
||||||
|
//! being non-zero if it is a non-calc value.
|
||||||
|
//!
|
||||||
|
//! It is expected to take 64 bits both in x86 and x86-64. This is implemented
|
||||||
|
//! as a `union`, with 4 different variants:
|
||||||
|
//!
|
||||||
|
//! * The length and percentage variants have a { tag, f32 } (effectively)
|
||||||
|
//! layout. The tag has to overlap with the lower 2 bits of the calc variant.
|
||||||
|
//!
|
||||||
|
//! * The `calc()` variant is a { tag, pointer } in x86 (so same as the
|
||||||
|
//! others), or just a { pointer } in x86-64 (so that the two bits of the tag
|
||||||
|
//! can be obtained from the lower bits of the pointer).
|
||||||
|
//!
|
||||||
|
//! * There's a `tag` variant just to make clear when only the tag is intended
|
||||||
|
//! to be read. Note that the tag needs to be masked always by `TAG_MASK`, to
|
||||||
|
//! deal with the pointer variant in x86-64.
|
||||||
|
//!
|
||||||
|
//! The assertions in the constructor methods ensure that the tag getter matches
|
||||||
|
//! our expectations.
|
||||||
|
|
||||||
use super::{Context, Length, Percentage, ToComputedValue};
|
use super::{Context, Length, Percentage, ToComputedValue};
|
||||||
use crate::values::animated::ToAnimatedValue;
|
use crate::values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
use crate::values::specified::length::FontBaseSize;
|
use crate::values::specified::length::FontBaseSize;
|
||||||
use crate::values::{specified, CSSFloat};
|
use crate::values::{specified, CSSFloat};
|
||||||
use crate::Zero;
|
use crate::Zero;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::values::specified::AllowedNumericType;
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct LengthVariant {
|
||||||
|
tag: u32,
|
||||||
|
length: Length,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PercentageVariant {
|
||||||
|
tag: u32,
|
||||||
|
percentage: Percentage,
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(emilio): cbindgen only understands the #[cfg] on the top level
|
||||||
|
// definition.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
pub struct CalcVariant {
|
||||||
|
tag: u32,
|
||||||
|
ptr: *mut CalcLengthPercentage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
pub struct CalcVariant {
|
||||||
|
ptr: *mut CalcLengthPercentage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TagVariant {
|
||||||
|
tag: u32,
|
||||||
|
}
|
||||||
|
|
||||||
/// A `<length-percentage>` value. This can be either a `<length>`, a
|
/// A `<length-percentage>` value. This can be either a `<length>`, a
|
||||||
/// `<percentage>`, or a combination of both via `calc()`.
|
/// `<percentage>`, or a combination of both via `calc()`.
|
||||||
///
|
///
|
||||||
|
@ -23,13 +87,87 @@ use style_traits::{CssWriter, ToCss};
|
||||||
/// cbindgen:derive-mut-casts=true
|
/// cbindgen:derive-mut-casts=true
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
|
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
|
||||||
#[allow(missing_docs)]
|
///
|
||||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToResolvedValue)]
|
/// The tag is stored in the lower two bits.
|
||||||
#[repr(u8)]
|
///
|
||||||
pub enum LengthPercentage {
|
/// We need to use a struct instead of the union directly because unions with
|
||||||
|
/// Drop implementations are unstable, looks like.
|
||||||
|
///
|
||||||
|
/// Also we need the union and the variants to be `pub` (even though the member
|
||||||
|
/// is private) so that cbindgen generates it. They're not part of the public
|
||||||
|
/// API otherwise.
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct LengthPercentage(LengthPercentageUnion);
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union LengthPercentageUnion {
|
||||||
|
length: LengthVariant,
|
||||||
|
percentage: PercentageVariant,
|
||||||
|
calc: CalcVariant,
|
||||||
|
tag: TagVariant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LengthPercentageUnion {
|
||||||
|
#[doc(hidden)] // Need to be public so that cbindgen generates it.
|
||||||
|
pub const TAG_CALC: u32 = 0;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const TAG_LENGTH: u32 = 1;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const TAG_PERCENTAGE: u32 = 2;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub const TAG_MASK: u32 = 0b11;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
#[repr(u32)]
|
||||||
|
enum Tag {
|
||||||
|
Calc = LengthPercentageUnion::TAG_CALC,
|
||||||
|
Length = LengthPercentageUnion::TAG_LENGTH,
|
||||||
|
Percentage = LengthPercentageUnion::TAG_PERCENTAGE,
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the members should be 64 bits, even in 32-bit builds.
|
||||||
|
#[allow(unused)]
|
||||||
|
unsafe fn static_assert() {
|
||||||
|
std::mem::transmute::<u64, LengthVariant>(0u64);
|
||||||
|
std::mem::transmute::<u64, PercentageVariant>(0u64);
|
||||||
|
std::mem::transmute::<u64, CalcVariant>(0u64);
|
||||||
|
std::mem::transmute::<u64, LengthPercentage>(0u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for LengthPercentage {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.tag() == Tag::Calc {
|
||||||
|
let _ = unsafe { Box::from_raw(self.0.calc.ptr) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MallocSizeOf for LengthPercentage {
|
||||||
|
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
|
match self.unpack() {
|
||||||
|
Unpacked::Length(..) | Unpacked::Percentage(..) => 0,
|
||||||
|
Unpacked::Calc(c) => unsafe { ops.malloc_size_of(c) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An unpacked `<length-percentage>` that borrows the `calc()` variant.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
enum Unpacked<'a> {
|
||||||
|
Calc(&'a CalcLengthPercentage),
|
||||||
|
Length(Length),
|
||||||
|
Percentage(Percentage),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An unpacked `<length-percentage>` that owns the `calc()` variant, for
|
||||||
|
/// serialization purposes.
|
||||||
|
#[derive(Deserialize, Serialize, PartialEq)]
|
||||||
|
enum Serializable {
|
||||||
|
Calc(CalcLengthPercentage),
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
Calc(Box<CalcLengthPercentage>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthPercentage {
|
impl LengthPercentage {
|
||||||
|
@ -41,14 +179,28 @@ impl LengthPercentage {
|
||||||
|
|
||||||
/// Constructs a length value.
|
/// Constructs a length value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_length(l: Length) -> Self {
|
pub fn new_length(length: Length) -> Self {
|
||||||
Self::Length(l)
|
let length = Self(LengthPercentageUnion {
|
||||||
|
length: LengthVariant {
|
||||||
|
tag: LengthPercentageUnion::TAG_LENGTH,
|
||||||
|
length,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
debug_assert_eq!(length.tag(), Tag::Length);
|
||||||
|
length
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a percentage value.
|
/// Constructs a percentage value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_percent(p: Percentage) -> Self {
|
pub fn new_percent(percentage: Percentage) -> Self {
|
||||||
Self::Percentage(p)
|
let percent = Self(LengthPercentageUnion {
|
||||||
|
percentage: PercentageVariant {
|
||||||
|
tag: LengthPercentageUnion::TAG_PERCENTAGE,
|
||||||
|
percentage,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
debug_assert_eq!(percent.tag(), Tag::Percentage);
|
||||||
|
percent
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a `calc()` value.
|
/// Constructs a `calc()` value.
|
||||||
|
@ -57,23 +209,77 @@ impl LengthPercentage {
|
||||||
CalcLengthPercentage::new(l, percentage).to_length_percentge()
|
CalcLengthPercentage::new(l, percentage).to_length_percentge()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Private version of new_calc() that constructs a calc() variant without
|
||||||
|
/// checking.
|
||||||
|
fn new_calc_unchecked(calc: Box<CalcLengthPercentage>) -> Self {
|
||||||
|
let ptr = Box::into_raw(calc);
|
||||||
|
let calc = Self(LengthPercentageUnion {
|
||||||
|
calc: CalcVariant {
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
tag: LengthPercentageUnion::TAG_CALC,
|
||||||
|
ptr,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
debug_assert_eq!(calc.tag(), Tag::Calc);
|
||||||
|
calc
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn tag(&self) -> Tag {
|
||||||
|
match unsafe { self.0.tag.tag & LengthPercentageUnion::TAG_MASK } {
|
||||||
|
LengthPercentageUnion::TAG_CALC => Tag::Calc,
|
||||||
|
LengthPercentageUnion::TAG_LENGTH => Tag::Length,
|
||||||
|
LengthPercentageUnion::TAG_PERCENTAGE => Tag::Percentage,
|
||||||
|
_ => unreachable!("Bogus tag?"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unpack<'a>(&'a self) -> Unpacked<'a> {
|
||||||
|
unsafe {
|
||||||
|
match self.tag() {
|
||||||
|
Tag::Calc => Unpacked::Calc(&*self.0.calc.ptr),
|
||||||
|
Tag::Length => Unpacked::Length(self.0.length.length),
|
||||||
|
Tag::Percentage => Unpacked::Percentage(self.0.percentage.percentage),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn to_serializable(&self) -> Serializable {
|
||||||
|
match self.unpack() {
|
||||||
|
Unpacked::Calc(c) => Serializable::Calc(c.clone()),
|
||||||
|
Unpacked::Length(l) => Serializable::Length(l),
|
||||||
|
Unpacked::Percentage(p) => Serializable::Percentage(p),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_serializable(s: Serializable) -> Self {
|
||||||
|
match s {
|
||||||
|
Serializable::Calc(c) => Self::new_calc_unchecked(Box::new(c)),
|
||||||
|
Serializable::Length(l) => Self::new_length(l),
|
||||||
|
Serializable::Percentage(p) => Self::new_percent(p),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the computed value is absolute 0 or 0%.
|
/// Returns true if the computed value is absolute 0 or 0%.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_definitely_zero(&self) -> bool {
|
pub fn is_definitely_zero(&self) -> bool {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(l) => l.px() == 0.0,
|
Unpacked::Length(l) => l.px() == 0.0,
|
||||||
Self::Percentage(p) => p.0 == 0.0,
|
Unpacked::Percentage(p) => p.0 == 0.0,
|
||||||
Self::Calc(ref c) => c.is_definitely_zero(),
|
Unpacked::Calc(ref c) => c.is_definitely_zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `<length>` component of this `calc()`, unclamped.
|
/// Returns the `<length>` component of this `calc()`, unclamped.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unclamped_length(&self) -> Length {
|
pub fn unclamped_length(&self) -> Length {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(l) => l,
|
Unpacked::Length(l) => l,
|
||||||
Self::Percentage(..) => Zero::zero(),
|
Unpacked::Percentage(..) => Zero::zero(),
|
||||||
Self::Calc(ref c) => c.unclamped_length(),
|
Unpacked::Calc(c) => c.unclamped_length(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +295,10 @@ impl LengthPercentage {
|
||||||
/// Returns the `<length>` component of this `calc()`, clamped.
|
/// Returns the `<length>` component of this `calc()`, clamped.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn length_component(&self) -> Length {
|
pub fn length_component(&self) -> Length {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(l) => l,
|
Unpacked::Length(l) => l,
|
||||||
Self::Percentage(..) => Zero::zero(),
|
Unpacked::Percentage(..) => Zero::zero(),
|
||||||
Self::Calc(ref c) => c.length_component(),
|
Unpacked::Calc(c) => c.length_component(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,30 +309,30 @@ impl LengthPercentage {
|
||||||
/// probably rename this.
|
/// probably rename this.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn percentage(&self) -> CSSFloat {
|
pub fn percentage(&self) -> CSSFloat {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(..) => 0.,
|
Unpacked::Length(..) => 0.,
|
||||||
Self::Percentage(p) => p.0,
|
Unpacked::Percentage(p) => p.0,
|
||||||
Self::Calc(ref c) => c.percentage.0,
|
Unpacked::Calc(c) => c.percentage.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `<length>` component of this `calc()`, clamped.
|
/// Returns the `<length>` component of this `calc()`, clamped.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_percentage(&self) -> Option<Percentage> {
|
pub fn as_percentage(&self) -> Option<Percentage> {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(..) => None,
|
Unpacked::Length(..) => None,
|
||||||
Self::Percentage(p) => Some(p),
|
Unpacked::Percentage(p) => Some(p),
|
||||||
Self::Calc(ref c) => c.as_percentage(),
|
Unpacked::Calc(ref c) => c.as_percentage(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves the percentage.
|
/// Resolves the percentage.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resolve(&self, basis: Length) -> Length {
|
pub fn resolve(&self, basis: Length) -> Length {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(l) => l,
|
Unpacked::Length(l) => l,
|
||||||
Self::Percentage(p) => Length::new(basis.px() * p.0),
|
Unpacked::Percentage(p) => Length::new(basis.px() * p.0),
|
||||||
Self::Calc(ref c) => c.resolve(basis),
|
Unpacked::Calc(ref c) => c.resolve(basis),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,20 +345,20 @@ impl LengthPercentage {
|
||||||
/// Return whether there's any percentage in this value.
|
/// Return whether there's any percentage in this value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_percentage(&self) -> bool {
|
pub fn has_percentage(&self) -> bool {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(..) => false,
|
Unpacked::Length(..) => false,
|
||||||
Self::Percentage(..) => true,
|
Unpacked::Percentage(..) => true,
|
||||||
Self::Calc(ref c) => c.has_percentage,
|
Unpacked::Calc(ref c) => c.has_percentage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the specified percentage if any.
|
/// Return the specified percentage if any.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn specified_percentage(&self) -> Option<Percentage> {
|
pub fn specified_percentage(&self) -> Option<Percentage> {
|
||||||
match *self {
|
match self.unpack() {
|
||||||
Self::Length(..) => None,
|
Unpacked::Length(..) => None,
|
||||||
Self::Percentage(p) => Some(p),
|
Unpacked::Percentage(p) => Some(p),
|
||||||
Self::Calc(ref c) => c.specified_percentage(),
|
Unpacked::Calc(ref c) => c.specified_percentage(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,11 +392,43 @@ impl LengthPercentage {
|
||||||
|
|
||||||
/// Returns the clamped non-negative values.
|
/// Returns the clamped non-negative values.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clamp_to_non_negative(self) -> Self {
|
pub fn clamp_to_non_negative(&self) -> Self {
|
||||||
match self {
|
match self.unpack() {
|
||||||
Self::Length(l) => Self::Length(l.clamp_to_non_negative()),
|
Unpacked::Length(l) => Self::new_length(l.clamp_to_non_negative()),
|
||||||
Self::Percentage(p) => Self::Percentage(p.clamp_to_non_negative()),
|
Unpacked::Percentage(p) => Self::new_percent(p.clamp_to_non_negative()),
|
||||||
Self::Calc(c) => c.clamp_to_non_negative().to_length_percentge(),
|
Unpacked::Calc(c) => c.clamp_to_non_negative().to_length_percentge(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for LengthPercentage {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.unpack() == other.unpack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for LengthPercentage {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.unpack().fmt(formatter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToAnimatedZero for LengthPercentage {
|
||||||
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||||
|
Ok(match self.unpack() {
|
||||||
|
Unpacked::Length(l) => Self::new_length(l.to_animated_zero()?),
|
||||||
|
Unpacked::Percentage(p) => Self::new_percent(p.to_animated_zero()?),
|
||||||
|
Unpacked::Calc(c) => Self::new_calc_unchecked(Box::new(c.to_animated_zero()?)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for LengthPercentage {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self.unpack() {
|
||||||
|
Unpacked::Length(l) => Self::new_length(l),
|
||||||
|
Unpacked::Percentage(p) => Self::new_percent(p),
|
||||||
|
Unpacked::Calc(c) => Self::new_calc_unchecked(Box::new(c.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,10 +439,10 @@ impl ToComputedValue for specified::LengthPercentage {
|
||||||
fn to_computed_value(&self, context: &Context) -> LengthPercentage {
|
fn to_computed_value(&self, context: &Context) -> LengthPercentage {
|
||||||
match *self {
|
match *self {
|
||||||
specified::LengthPercentage::Length(ref value) => {
|
specified::LengthPercentage::Length(ref value) => {
|
||||||
LengthPercentage::Length(value.to_computed_value(context))
|
LengthPercentage::new_length(value.to_computed_value(context))
|
||||||
},
|
},
|
||||||
specified::LengthPercentage::Percentage(value) => {
|
specified::LengthPercentage::Percentage(value) => {
|
||||||
LengthPercentage::Percentage(value)
|
LengthPercentage::new_percent(value)
|
||||||
},
|
},
|
||||||
specified::LengthPercentage::Calc(ref calc) => {
|
specified::LengthPercentage::Calc(ref calc) => {
|
||||||
(**calc).to_computed_value(context).to_length_percentge()
|
(**calc).to_computed_value(context).to_length_percentge()
|
||||||
|
@ -213,14 +451,14 @@ impl ToComputedValue for specified::LengthPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_computed_value(computed: &LengthPercentage) -> Self {
|
fn from_computed_value(computed: &LengthPercentage) -> Self {
|
||||||
match *computed {
|
match computed.unpack() {
|
||||||
LengthPercentage::Length(ref l) => {
|
Unpacked::Length(ref l) => {
|
||||||
specified::LengthPercentage::Length(ToComputedValue::from_computed_value(l))
|
specified::LengthPercentage::Length(ToComputedValue::from_computed_value(l))
|
||||||
}
|
}
|
||||||
LengthPercentage::Percentage(p) => {
|
Unpacked::Percentage(p) => {
|
||||||
specified::LengthPercentage::Percentage(p)
|
specified::LengthPercentage::Percentage(p)
|
||||||
}
|
}
|
||||||
LengthPercentage::Calc(ref c) => {
|
Unpacked::Calc(c) => {
|
||||||
if let Some(p) = c.as_percentage() {
|
if let Some(p) = c.as_percentage() {
|
||||||
return specified::LengthPercentage::Percentage(p)
|
return specified::LengthPercentage::Percentage(p)
|
||||||
}
|
}
|
||||||
|
@ -257,7 +495,7 @@ impl ToCss for LengthPercentage {
|
||||||
|
|
||||||
impl Zero for LengthPercentage {
|
impl Zero for LengthPercentage {
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
LengthPercentage::Length(Length::zero())
|
LengthPercentage::new_length(Length::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -266,6 +504,24 @@ impl Zero for LengthPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for LengthPercentage {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
self.to_serializable().serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for LengthPercentage {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
Ok(Self::from_serializable(Serializable::deserialize(deserializer)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The representation of a calc() function.
|
/// The representation of a calc() function.
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue,
|
Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue,
|
||||||
|
@ -295,12 +551,12 @@ impl CalcLengthPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_length_percentge(self) -> LengthPercentage {
|
pub fn to_length_percentge(self) -> LengthPercentage {
|
||||||
if !self.has_percentage {
|
if !self.has_percentage {
|
||||||
return LengthPercentage::Length(self.length_component())
|
return LengthPercentage::new_length(self.length_component())
|
||||||
}
|
}
|
||||||
if self.length.is_zero() {
|
if self.length.is_zero() {
|
||||||
return LengthPercentage::Percentage(Percentage(self.clamping_mode.clamp(self.percentage.0)));
|
return LengthPercentage::new_percent(Percentage(self.clamping_mode.clamp(self.percentage.0)));
|
||||||
}
|
}
|
||||||
LengthPercentage::Calc(Box::new(self))
|
LengthPercentage::new_calc_unchecked(Box::new(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn specified_percentage(&self) -> Option<Percentage> {
|
fn specified_percentage(&self) -> Option<Percentage> {
|
||||||
|
@ -369,7 +625,7 @@ impl CalcLengthPercentage {
|
||||||
|
|
||||||
/// Returns the clamped non-negative values.
|
/// Returns the clamped non-negative values.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clamp_to_non_negative(self) -> Self {
|
fn clamp_to_non_negative(&self) -> Self {
|
||||||
if self.has_percentage {
|
if self.has_percentage {
|
||||||
// If we can eagerly clamp the percentage then just do that.
|
// If we can eagerly clamp the percentage then just do that.
|
||||||
if self.length.is_zero() {
|
if self.length.is_zero() {
|
||||||
|
|
|
@ -78,6 +78,7 @@ trivial_to_resolved_value!(computed::url::ComputedUrl);
|
||||||
trivial_to_resolved_value!(computed::url::ComputedImageUrl);
|
trivial_to_resolved_value!(computed::url::ComputedImageUrl);
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
trivial_to_resolved_value!(html5ever::Prefix);
|
trivial_to_resolved_value!(html5ever::Prefix);
|
||||||
|
trivial_to_resolved_value!(computed::LengthPercentage);
|
||||||
|
|
||||||
impl<A, B> ToResolvedValue for (A, B)
|
impl<A, B> ToResolvedValue for (A, B)
|
||||||
where
|
where
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue