зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1607049 - Pack LengthPercentage better. r=jwatt
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 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d4c2489000
Коммит
ba0cc69e47
|
@ -810,7 +810,7 @@ float SVGContentUtils::CoordToFloat(SVGElement* aContent,
|
|||
return CSSCoord(ctx ? ctx->GetLength(SVGContentUtils::XY) : 0.0f);
|
||||
});
|
||||
if (aLength.IsCalc()) {
|
||||
auto& calc = *aLength.AsCalc();
|
||||
auto& calc = aLength.AsCalc();
|
||||
if (calc.clamping_mode == StyleAllowedNumericType::NonNegative) {
|
||||
result = std::max(result, 0.0f);
|
||||
} else {
|
||||
|
|
|
@ -200,4 +200,9 @@ using StyleAtomicUsize = std::atomic<size_t>;
|
|||
|
||||
} // namespace mozilla
|
||||
|
||||
# ifndef HAVE_64BIT_BUILD
|
||||
static_assert(sizeof(void*) == 4, "");
|
||||
# define SERVO_32_BITS 1
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -439,15 +439,101 @@ nscoord StyleCSSPixelLength::ToAppUnits() const {
|
|||
return NSToIntRound(length);
|
||||
}
|
||||
|
||||
StyleLengthPercentage::StyleLengthPercentage() {
|
||||
tag = Tag::Length;
|
||||
length._0._0 = 0.0f;
|
||||
bool LengthPercentage::IsLength() const { return Tag() == TAG_LENGTH; }
|
||||
|
||||
StyleLengthPercentageUnion::StyleLengthPercentageUnion() {
|
||||
length = {TAG_LENGTH, {0.0f}};
|
||||
MOZ_ASSERT(IsLength());
|
||||
}
|
||||
|
||||
static_assert(sizeof(LengthPercentage) == sizeof(uint64_t), "");
|
||||
|
||||
Length& LengthPercentage::AsLength() {
|
||||
MOZ_ASSERT(IsLength());
|
||||
return length.length;
|
||||
}
|
||||
|
||||
const Length& LengthPercentage::AsLength() const {
|
||||
return const_cast<LengthPercentage*>(this)->AsLength();
|
||||
}
|
||||
|
||||
bool LengthPercentage::IsPercentage() const { return Tag() == TAG_PERCENTAGE; }
|
||||
|
||||
StylePercentage& LengthPercentage::AsPercentage() {
|
||||
MOZ_ASSERT(IsPercentage());
|
||||
return percentage.percentage;
|
||||
}
|
||||
|
||||
const StylePercentage& LengthPercentage::AsPercentage() const {
|
||||
return const_cast<LengthPercentage*>(this)->AsPercentage();
|
||||
}
|
||||
|
||||
bool LengthPercentage::IsCalc() const { return Tag() == TAG_CALC; }
|
||||
|
||||
StyleCalcLengthPercentage& LengthPercentage::AsCalc() {
|
||||
MOZ_ASSERT(IsCalc());
|
||||
return *calc.ptr;
|
||||
}
|
||||
|
||||
const StyleCalcLengthPercentage& LengthPercentage::AsCalc() const {
|
||||
return const_cast<LengthPercentage*>(this)->AsCalc();
|
||||
}
|
||||
|
||||
StyleLengthPercentageUnion::StyleLengthPercentageUnion(const Self& aOther) {
|
||||
if (aOther.IsLength()) {
|
||||
length = {TAG_LENGTH, aOther.AsLength()};
|
||||
} else if (aOther.IsPercentage()) {
|
||||
percentage = {TAG_PERCENTAGE, aOther.AsPercentage()};
|
||||
} else {
|
||||
MOZ_ASSERT(aOther.IsCalc());
|
||||
calc = {
|
||||
#ifdef SERVO_32_BITS
|
||||
TAG_CALC,
|
||||
#endif
|
||||
new StyleCalcLengthPercentage(aOther.AsCalc()),
|
||||
};
|
||||
}
|
||||
MOZ_ASSERT(Tag() == aOther.Tag());
|
||||
}
|
||||
|
||||
StyleLengthPercentageUnion::~StyleLengthPercentageUnion() {
|
||||
if (IsCalc()) {
|
||||
delete calc.ptr;
|
||||
}
|
||||
}
|
||||
|
||||
LengthPercentage& LengthPercentage::operator=(const LengthPercentage& aOther) {
|
||||
if (this != &aOther) {
|
||||
this->~LengthPercentage();
|
||||
new (this) LengthPercentage(aOther);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool LengthPercentage::operator==(const LengthPercentage& aOther) const {
|
||||
if (Tag() != aOther.Tag()) {
|
||||
return false;
|
||||
}
|
||||
if (IsLength()) {
|
||||
return AsLength() == aOther.AsLength();
|
||||
}
|
||||
if (IsPercentage()) {
|
||||
return AsPercentage() == aOther.AsPercentage();
|
||||
}
|
||||
return AsCalc() == aOther.AsCalc();
|
||||
}
|
||||
|
||||
bool LengthPercentage::operator!=(const LengthPercentage& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
LengthPercentage LengthPercentage::Zero() { return {}; }
|
||||
|
||||
LengthPercentage LengthPercentage::FromPixels(CSSCoord aCoord) {
|
||||
return LengthPercentage::Length({aCoord});
|
||||
LengthPercentage l;
|
||||
MOZ_ASSERT(l.IsLength());
|
||||
l.length.length = {aCoord};
|
||||
return l;
|
||||
}
|
||||
|
||||
LengthPercentage LengthPercentage::FromAppUnits(nscoord aCoord) {
|
||||
|
@ -455,7 +541,9 @@ LengthPercentage LengthPercentage::FromAppUnits(nscoord aCoord) {
|
|||
}
|
||||
|
||||
LengthPercentage LengthPercentage::FromPercentage(float aPercentage) {
|
||||
return LengthPercentage::Percentage({aPercentage});
|
||||
LengthPercentage l;
|
||||
l.percentage = {TAG_PERCENTAGE, {aPercentage}};
|
||||
return l;
|
||||
}
|
||||
|
||||
CSSCoord LengthPercentage::LengthInCSSPixels() const {
|
||||
|
@ -465,7 +553,7 @@ CSSCoord LengthPercentage::LengthInCSSPixels() const {
|
|||
if (IsPercentage()) {
|
||||
return 0;
|
||||
}
|
||||
return AsCalc()->length.ToCSSPixels();
|
||||
return AsCalc().length.ToCSSPixels();
|
||||
}
|
||||
|
||||
float LengthPercentage::Percentage() const {
|
||||
|
@ -475,18 +563,18 @@ float LengthPercentage::Percentage() const {
|
|||
if (IsPercentage()) {
|
||||
return AsPercentage()._0;
|
||||
}
|
||||
return AsCalc()->percentage._0;
|
||||
return AsCalc().percentage._0;
|
||||
}
|
||||
|
||||
bool LengthPercentage::HasPercent() const {
|
||||
return IsPercentage() || (IsCalc() && AsCalc()->has_percentage);
|
||||
return IsPercentage() || (IsCalc() && AsCalc().has_percentage);
|
||||
}
|
||||
|
||||
bool LengthPercentage::ConvertsToLength() const { return !HasPercent(); }
|
||||
|
||||
nscoord LengthPercentage::ToLength() const {
|
||||
MOZ_ASSERT(ConvertsToLength());
|
||||
return IsLength() ? AsLength().ToAppUnits() : AsCalc()->length.ToAppUnits();
|
||||
return IsLength() ? AsLength().ToAppUnits() : AsCalc().length.ToAppUnits();
|
||||
}
|
||||
|
||||
bool LengthPercentage::ConvertsToPercentage() const {
|
||||
|
@ -494,7 +582,7 @@ bool LengthPercentage::ConvertsToPercentage() const {
|
|||
return true;
|
||||
}
|
||||
if (IsCalc()) {
|
||||
auto& calc = *AsCalc();
|
||||
auto& calc = AsCalc();
|
||||
return calc.has_percentage && calc.length.IsZero();
|
||||
}
|
||||
return false;
|
||||
|
@ -516,7 +604,7 @@ bool LengthPercentage::IsDefinitelyZero() const {
|
|||
if (IsPercentage()) {
|
||||
return AsPercentage()._0 == 0.0f;
|
||||
}
|
||||
auto& calc = *AsCalc();
|
||||
auto& calc = AsCalc();
|
||||
return calc.length.IsZero() && calc.percentage._0 == 0.0f;
|
||||
}
|
||||
|
||||
|
@ -552,7 +640,7 @@ nscoord LengthPercentage::Resolve(T aPercentageGetter,
|
|||
if (IsPercentage()) {
|
||||
return aPercentageRounder(basis * AsPercentage()._0);
|
||||
}
|
||||
auto& calc = *AsCalc();
|
||||
auto& calc = AsCalc();
|
||||
return calc.length.ToAppUnits() +
|
||||
aPercentageRounder(basis * calc.percentage._0);
|
||||
}
|
||||
|
@ -579,7 +667,7 @@ void LengthPercentage::ScaleLengthsBy(float aScale) {
|
|||
AsLength().ScaleBy(aScale);
|
||||
}
|
||||
if (IsCalc()) {
|
||||
AsCalc()->length.ScaleBy(aScale);
|
||||
AsCalc().length.ScaleBy(aScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,19 +3,83 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! `<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 crate::values::animated::ToAnimatedValue;
|
||||
use crate::values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use crate::values::generics::NonNegative;
|
||||
use crate::values::specified::length::FontBaseSize;
|
||||
use crate::values::{specified, CSSFloat};
|
||||
use crate::Zero;
|
||||
use app_units::Au;
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
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
|
||||
/// `<percentage>`, or a combination of both via `calc()`.
|
||||
///
|
||||
|
@ -23,13 +87,87 @@ use style_traits::{CssWriter, ToCss};
|
|||
/// cbindgen:derive-mut-casts=true
|
||||
///
|
||||
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToResolvedValue)]
|
||||
#[repr(u8)]
|
||||
pub enum LengthPercentage {
|
||||
///
|
||||
/// The tag is stored in the lower two bits.
|
||||
///
|
||||
/// 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),
|
||||
Percentage(Percentage),
|
||||
Calc(Box<CalcLengthPercentage>),
|
||||
}
|
||||
|
||||
impl LengthPercentage {
|
||||
|
@ -41,14 +179,28 @@ impl LengthPercentage {
|
|||
|
||||
/// Constructs a length value.
|
||||
#[inline]
|
||||
pub fn new_length(l: Length) -> Self {
|
||||
Self::Length(l)
|
||||
pub fn new_length(length: Length) -> Self {
|
||||
let length = Self(LengthPercentageUnion {
|
||||
length: LengthVariant {
|
||||
tag: LengthPercentageUnion::TAG_LENGTH,
|
||||
length,
|
||||
}
|
||||
});
|
||||
debug_assert_eq!(length.tag(), Tag::Length);
|
||||
length
|
||||
}
|
||||
|
||||
/// Constructs a percentage value.
|
||||
#[inline]
|
||||
pub fn new_percent(p: Percentage) -> Self {
|
||||
Self::Percentage(p)
|
||||
pub fn new_percent(percentage: Percentage) -> Self {
|
||||
let percent = Self(LengthPercentageUnion {
|
||||
percentage: PercentageVariant {
|
||||
tag: LengthPercentageUnion::TAG_PERCENTAGE,
|
||||
percentage,
|
||||
}
|
||||
});
|
||||
debug_assert_eq!(percent.tag(), Tag::Percentage);
|
||||
percent
|
||||
}
|
||||
|
||||
/// Constructs a `calc()` value.
|
||||
|
@ -57,23 +209,77 @@ impl LengthPercentage {
|
|||
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%.
|
||||
#[inline]
|
||||
pub fn is_definitely_zero(&self) -> bool {
|
||||
match *self {
|
||||
Self::Length(l) => l.px() == 0.0,
|
||||
Self::Percentage(p) => p.0 == 0.0,
|
||||
Self::Calc(ref c) => c.is_definitely_zero(),
|
||||
match self.unpack() {
|
||||
Unpacked::Length(l) => l.px() == 0.0,
|
||||
Unpacked::Percentage(p) => p.0 == 0.0,
|
||||
Unpacked::Calc(ref c) => c.is_definitely_zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(),
|
||||
match self.unpack() {
|
||||
Unpacked::Length(l) => l,
|
||||
Unpacked::Percentage(..) => Zero::zero(),
|
||||
Unpacked::Calc(c) => c.unclamped_length(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +295,10 @@ impl LengthPercentage {
|
|||
/// 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(),
|
||||
match self.unpack() {
|
||||
Unpacked::Length(l) => l,
|
||||
Unpacked::Percentage(..) => Zero::zero(),
|
||||
Unpacked::Calc(c) => c.length_component(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,30 +309,30 @@ impl LengthPercentage {
|
|||
/// 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,
|
||||
match self.unpack() {
|
||||
Unpacked::Length(..) => 0.,
|
||||
Unpacked::Percentage(p) => p.0,
|
||||
Unpacked::Calc(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(),
|
||||
match self.unpack() {
|
||||
Unpacked::Length(..) => None,
|
||||
Unpacked::Percentage(p) => Some(p),
|
||||
Unpacked::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.px() * p.0),
|
||||
Self::Calc(ref c) => c.resolve(basis),
|
||||
match self.unpack() {
|
||||
Unpacked::Length(l) => l,
|
||||
Unpacked::Percentage(p) => Length::new(basis.px() * p.0),
|
||||
Unpacked::Calc(ref c) => c.resolve(basis),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,20 +345,20 @@ impl LengthPercentage {
|
|||
/// 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,
|
||||
match self.unpack() {
|
||||
Unpacked::Length(..) => false,
|
||||
Unpacked::Percentage(..) => true,
|
||||
Unpacked::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(),
|
||||
match self.unpack() {
|
||||
Unpacked::Length(..) => None,
|
||||
Unpacked::Percentage(p) => Some(p),
|
||||
Unpacked::Calc(ref c) => c.specified_percentage(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,11 +392,43 @@ impl LengthPercentage {
|
|||
|
||||
/// Returns the clamped non-negative values.
|
||||
#[inline]
|
||||
pub fn clamp_to_non_negative(self) -> Self {
|
||||
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(),
|
||||
pub fn clamp_to_non_negative(&self) -> Self {
|
||||
match self.unpack() {
|
||||
Unpacked::Length(l) => Self::new_length(l.clamp_to_non_negative()),
|
||||
Unpacked::Percentage(p) => Self::new_percent(p.clamp_to_non_negative()),
|
||||
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 {
|
||||
match *self {
|
||||
specified::LengthPercentage::Length(ref value) => {
|
||||
LengthPercentage::Length(value.to_computed_value(context))
|
||||
LengthPercentage::new_length(value.to_computed_value(context))
|
||||
},
|
||||
specified::LengthPercentage::Percentage(value) => {
|
||||
LengthPercentage::Percentage(value)
|
||||
LengthPercentage::new_percent(value)
|
||||
},
|
||||
specified::LengthPercentage::Calc(ref calc) => {
|
||||
(**calc).to_computed_value(context).to_length_percentge()
|
||||
|
@ -213,14 +451,14 @@ impl ToComputedValue for specified::LengthPercentage {
|
|||
}
|
||||
|
||||
fn from_computed_value(computed: &LengthPercentage) -> Self {
|
||||
match *computed {
|
||||
LengthPercentage::Length(ref l) => {
|
||||
match computed.unpack() {
|
||||
Unpacked::Length(ref l) => {
|
||||
specified::LengthPercentage::Length(ToComputedValue::from_computed_value(l))
|
||||
}
|
||||
LengthPercentage::Percentage(p) => {
|
||||
Unpacked::Percentage(p) => {
|
||||
specified::LengthPercentage::Percentage(p)
|
||||
}
|
||||
LengthPercentage::Calc(ref c) => {
|
||||
Unpacked::Calc(c) => {
|
||||
if let Some(p) = c.as_percentage() {
|
||||
return specified::LengthPercentage::Percentage(p)
|
||||
}
|
||||
|
@ -257,7 +495,7 @@ impl ToCss for LengthPercentage {
|
|||
|
||||
impl Zero for LengthPercentage {
|
||||
fn zero() -> Self {
|
||||
LengthPercentage::Length(Length::zero())
|
||||
LengthPercentage::new_length(Length::zero())
|
||||
}
|
||||
|
||||
#[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.
|
||||
#[derive(
|
||||
Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue,
|
||||
|
@ -295,12 +551,12 @@ impl CalcLengthPercentage {
|
|||
#[inline]
|
||||
pub fn to_length_percentge(self) -> LengthPercentage {
|
||||
if !self.has_percentage {
|
||||
return LengthPercentage::Length(self.length_component())
|
||||
return LengthPercentage::new_length(self.length_component())
|
||||
}
|
||||
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> {
|
||||
|
@ -369,7 +625,7 @@ impl CalcLengthPercentage {
|
|||
|
||||
/// Returns the clamped non-negative values.
|
||||
#[inline]
|
||||
fn clamp_to_non_negative(self) -> Self {
|
||||
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() {
|
||||
|
|
|
@ -78,6 +78,7 @@ trivial_to_resolved_value!(computed::url::ComputedUrl);
|
|||
trivial_to_resolved_value!(computed::url::ComputedImageUrl);
|
||||
#[cfg(feature = "servo")]
|
||||
trivial_to_resolved_value!(html5ever::Prefix);
|
||||
trivial_to_resolved_value!(computed::LengthPercentage);
|
||||
|
||||
impl<A, B> ToResolvedValue for (A, B)
|
||||
where
|
||||
|
|
|
@ -46,6 +46,8 @@ derive_neq = true
|
|||
# This will actually never be defined, but is handy to avoid cbindgen
|
||||
# generating Servo-only types.
|
||||
"feature = servo" = "CBINDGEN_IS_SERVO"
|
||||
"target_pointer_width = 32" = "SERVO_32_BITS"
|
||||
"target_pointer_width = 64" = "HAVE_64BIT_BUILD"
|
||||
|
||||
[macro_expansion]
|
||||
bitflags = true
|
||||
|
@ -189,7 +191,7 @@ include = [
|
|||
"Content",
|
||||
"ContentItem",
|
||||
]
|
||||
item_types = ["enums", "structs", "typedefs", "functions", "constants"]
|
||||
item_types = ["enums", "structs", "unions", "typedefs", "functions", "constants"]
|
||||
renaming_overrides_prefixing = true
|
||||
|
||||
# Prevent some renaming for Gecko types that cbindgen doesn't otherwise understand.
|
||||
|
@ -250,12 +252,49 @@ renaming_overrides_prefixing = true
|
|||
inline void ScaleBy(float);
|
||||
"""
|
||||
|
||||
"LengthPercentage" = """
|
||||
inline StyleLengthPercentage();
|
||||
static inline StyleLengthPercentage Zero();
|
||||
static inline StyleLengthPercentage FromAppUnits(nscoord);
|
||||
static inline StyleLengthPercentage FromPixels(CSSCoord);
|
||||
static inline StyleLengthPercentage FromPercentage(float);
|
||||
"LengthPercentageUnion" = """
|
||||
using Self = StyleLengthPercentageUnion;
|
||||
|
||||
// TODO(emilio): cbindgen should be able to generate these in the body of the
|
||||
// union, but it seems it's only implemented for structs, not unions.
|
||||
static const uint32_t TAG_CALC = StyleLengthPercentageUnion_TAG_CALC;
|
||||
static const uint32_t TAG_LENGTH = StyleLengthPercentageUnion_TAG_LENGTH;
|
||||
static const uint32_t TAG_PERCENTAGE = StyleLengthPercentageUnion_TAG_PERCENTAGE;
|
||||
static const uint32_t TAG_MASK = StyleLengthPercentageUnion_TAG_MASK;
|
||||
|
||||
private:
|
||||
uint32_t Tag() const {
|
||||
return tag.tag & TAG_MASK;
|
||||
}
|
||||
|
||||
public:
|
||||
// We need to do all this manually because cbingen can't reason about unions.
|
||||
inline StyleLengthPercentageUnion();
|
||||
inline StyleLengthPercentageUnion(const Self&);
|
||||
inline ~StyleLengthPercentageUnion();
|
||||
inline Self& operator=(const Self&);
|
||||
|
||||
inline bool operator==(const Self& aOther) const;
|
||||
inline bool operator!=(const Self& aOther) const;
|
||||
|
||||
inline bool IsLength() const;
|
||||
inline bool IsPercentage() const;
|
||||
inline bool IsCalc() const;
|
||||
|
||||
inline const StyleLength& AsLength() const;
|
||||
inline StyleLength& AsLength();
|
||||
|
||||
inline const StylePercentage& AsPercentage() const;
|
||||
inline StylePercentage& AsPercentage();
|
||||
|
||||
inline const StyleCalcLengthPercentage& AsCalc() const;
|
||||
inline StyleCalcLengthPercentage& AsCalc();
|
||||
|
||||
static inline Self Zero();
|
||||
static inline Self FromAppUnits(nscoord);
|
||||
static inline Self FromPixels(CSSCoord);
|
||||
static inline Self FromPercentage(float);
|
||||
|
||||
inline void ScaleLengthsBy(float);
|
||||
inline CSSCoord LengthInCSSPixels() const;
|
||||
inline float Percentage() const;
|
||||
|
|
Загрузка…
Ссылка в новой задаче