mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Let aspect-ratio (css-sizing-4) support 'auto | <ratio>'.
In order to test its parsing and serialization, we expose it but protect it behind a pref. Besides, I would like to drop layout.css.aspect-ratio-number.enabled in the next patch because the spec has been updated. It seems we don't have to keep this pref and we should always use Number. Differential Revision: https://phabricator.services.mozilla.com/D74955
This commit is contained in:
parent
bd23e05c47
commit
fc9321bb23
8 changed files with 185 additions and 18 deletions
|
@ -272,3 +272,26 @@ where
|
||||||
<Self as num_traits::Zero>::is_zero(self)
|
<Self as num_traits::Zero>::is_zero(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait pretty much similar to num_traits::One, but without the need of
|
||||||
|
/// implementing `Mul`.
|
||||||
|
pub trait One {
|
||||||
|
/// Reutrns the one value.
|
||||||
|
fn one() -> Self;
|
||||||
|
|
||||||
|
/// Returns whether this value is one.
|
||||||
|
fn is_one(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> One for T
|
||||||
|
where
|
||||||
|
T: num_traits::One + PartialEq,
|
||||||
|
{
|
||||||
|
fn one() -> Self {
|
||||||
|
<Self as num_traits::One>::one()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_one(&self) -> bool {
|
||||||
|
*self == One::one()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -328,6 +328,7 @@ class Longhand(object):
|
||||||
"AlignItems",
|
"AlignItems",
|
||||||
"AlignSelf",
|
"AlignSelf",
|
||||||
"Appearance",
|
"Appearance",
|
||||||
|
"AspectRatio",
|
||||||
"BreakBetween",
|
"BreakBetween",
|
||||||
"BreakWithin",
|
"BreakWithin",
|
||||||
"BackgroundRepeat",
|
"BackgroundRepeat",
|
||||||
|
@ -364,7 +365,6 @@ class Longhand(object):
|
||||||
"MozScriptSizeMultiplier",
|
"MozScriptSizeMultiplier",
|
||||||
"TextDecorationSkipInk",
|
"TextDecorationSkipInk",
|
||||||
"NonNegativeNumber",
|
"NonNegativeNumber",
|
||||||
"Number",
|
|
||||||
"OffsetRotate",
|
"OffsetRotate",
|
||||||
"Opacity",
|
"Opacity",
|
||||||
"OutlineStyle",
|
"OutlineStyle",
|
||||||
|
|
|
@ -447,17 +447,13 @@ ${helpers.predefined_type(
|
||||||
servo_restyle_damage="reflow",
|
servo_restyle_damage="reflow",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
// NOTE(emilio): Before exposing this property to content, we probably need to
|
|
||||||
// change syntax and such, and make it apply to more elements.
|
|
||||||
//
|
|
||||||
// For now, it's used only for mapped attributes.
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"aspect-ratio",
|
"aspect-ratio",
|
||||||
"Number",
|
"AspectRatio",
|
||||||
"computed::Number::zero()",
|
"computed::AspectRatio::auto()",
|
||||||
engines="gecko servo-2013",
|
engines="gecko servo-2013",
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="discrete",
|
||||||
spec="Internal, for now",
|
spec="https://drafts.csswg.org/css-sizing-4/#aspect-ratio",
|
||||||
enabled_in="",
|
gecko_pref="layout.css.aspect-ratio.enabled",
|
||||||
servo_restyle_damage="reflow",
|
servo_restyle_damage="reflow",
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::media_queries::Device;
|
||||||
use crate::properties;
|
use crate::properties;
|
||||||
use crate::properties::{ComputedValues, LonghandId, StyleBuilder};
|
use crate::properties::{ComputedValues, LonghandId, StyleBuilder};
|
||||||
use crate::rule_cache::RuleCacheConditions;
|
use crate::rule_cache::RuleCacheConditions;
|
||||||
use crate::{ArcSlice, Atom};
|
use crate::{ArcSlice, Atom, One};
|
||||||
use euclid::default::Size2D;
|
use euclid::default::Size2D;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -68,6 +68,7 @@ pub use self::list::Quotes;
|
||||||
pub use self::motion::{OffsetPath, OffsetRotate};
|
pub use self::motion::{OffsetPath, OffsetRotate};
|
||||||
pub use self::outline::OutlineStyle;
|
pub use self::outline::OutlineStyle;
|
||||||
pub use self::percentage::{NonNegativePercentage, Percentage};
|
pub use self::percentage::{NonNegativePercentage, Percentage};
|
||||||
|
pub use self::position::AspectRatio;
|
||||||
pub use self::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto, ZIndex};
|
pub use self::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto, ZIndex};
|
||||||
pub use self::rect::NonNegativeLengthOrNumberRect;
|
pub use self::rect::NonNegativeLengthOrNumberRect;
|
||||||
pub use self::resolution::Resolution;
|
pub use self::resolution::Resolution;
|
||||||
|
@ -600,6 +601,18 @@ impl From<NonNegativeNumber> for CSSFloat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl One for NonNegativeNumber {
|
||||||
|
#[inline]
|
||||||
|
fn one() -> Self {
|
||||||
|
NonNegative(1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_one(&self) -> bool {
|
||||||
|
self.0 == 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A wrapper of Number, but the value between 0 and 1
|
/// A wrapper of Number, but the value between 0 and 1
|
||||||
pub type ZeroToOneNumber = ZeroToOne<CSSFloat>;
|
pub type ZeroToOneNumber = ZeroToOne<CSSFloat>;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
//!
|
//!
|
||||||
//! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
|
//! [position]: https://drafts.csswg.org/css-backgrounds-3/#position
|
||||||
|
|
||||||
use crate::values::computed::{Integer, LengthPercentage, Percentage};
|
use crate::values::computed::{Integer, LengthPercentage, NonNegativeNumber, Percentage};
|
||||||
|
use crate::values::generics::position::AspectRatio as GenericAspectRatio;
|
||||||
use crate::values::generics::position::Position as GenericPosition;
|
use crate::values::generics::position::Position as GenericPosition;
|
||||||
use crate::values::generics::position::PositionComponent as GenericPositionComponent;
|
use crate::values::generics::position::PositionComponent as GenericPositionComponent;
|
||||||
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
||||||
|
@ -68,3 +69,6 @@ impl GenericPositionComponent for LengthPercentage {
|
||||||
|
|
||||||
/// A computed value for the `z-index` property.
|
/// A computed value for the `z-index` property.
|
||||||
pub type ZIndex = GenericZIndex<Integer>;
|
pub type ZIndex = GenericZIndex<Integer>;
|
||||||
|
|
||||||
|
/// A computed value for the `aspect-ratio` property.
|
||||||
|
pub type AspectRatio = GenericAspectRatio<NonNegativeNumber>;
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
//! Generic types for CSS handling of specified and computed values of
|
//! Generic types for CSS handling of specified and computed values of
|
||||||
//! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position)
|
//! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position)
|
||||||
|
|
||||||
|
use crate::One;
|
||||||
|
use std::fmt::{self, Write};
|
||||||
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
/// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position).
|
/// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position).
|
||||||
#[derive(
|
#[derive(
|
||||||
Animate,
|
Animate,
|
||||||
|
@ -150,3 +154,74 @@ impl<Integer> ZIndex<Integer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A generic value for the `<ratio>` value.
|
||||||
|
// FIXME: Use this for aspect-ratio in both css-sizing-4 and media-queries in the following patch.
|
||||||
|
#[derive(
|
||||||
|
Animate,
|
||||||
|
Clone,
|
||||||
|
ComputeSquaredDistance,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToAnimatedZero,
|
||||||
|
ToComputedValue,
|
||||||
|
ToResolvedValue,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Ratio<N>(pub N, pub N);
|
||||||
|
|
||||||
|
impl<N> ToCss for Ratio<N>
|
||||||
|
where
|
||||||
|
N: ToCss + One + std::cmp::PartialEq,
|
||||||
|
{
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
self.0.to_css(dest)?;
|
||||||
|
// The second defaults to 1. So if it is one, we omit it in serialization.
|
||||||
|
if !self.1.is_one() {
|
||||||
|
dest.write_str(" / ")?;
|
||||||
|
self.1.to_css(dest)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic value for the `aspect-ratio` property.
|
||||||
|
#[derive(
|
||||||
|
Animate,
|
||||||
|
Clone,
|
||||||
|
ComputeSquaredDistance,
|
||||||
|
Copy,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
|
ToAnimatedZero,
|
||||||
|
ToComputedValue,
|
||||||
|
ToCss,
|
||||||
|
ToResolvedValue,
|
||||||
|
ToShmem,
|
||||||
|
)]
|
||||||
|
#[repr(C, u8)]
|
||||||
|
pub enum GenericAspectRatio<N> {
|
||||||
|
/// The <ratio> value.
|
||||||
|
Ratio(#[css(field_bound)] Ratio<N>),
|
||||||
|
/// The keyword `auto`.
|
||||||
|
Auto,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::GenericAspectRatio as AspectRatio;
|
||||||
|
|
||||||
|
impl<R> AspectRatio<R> {
|
||||||
|
/// Returns `auto`
|
||||||
|
#[inline]
|
||||||
|
pub fn auto() -> Self {
|
||||||
|
AspectRatio::Auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,8 @@ use crate::context::QuirksMode;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::serialize_atom_identifier;
|
use crate::values::serialize_atom_identifier;
|
||||||
use crate::values::specified::calc::CalcNode;
|
use crate::values::specified::calc::CalcNode;
|
||||||
use crate::{Atom, Namespace, Prefix, Zero};
|
use crate::{Atom, Namespace, One, Prefix, Zero};
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use num_traits::One;
|
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
@ -72,6 +71,7 @@ pub use self::list::Quotes;
|
||||||
pub use self::motion::{OffsetPath, OffsetRotate};
|
pub use self::motion::{OffsetPath, OffsetRotate};
|
||||||
pub use self::outline::OutlineStyle;
|
pub use self::outline::OutlineStyle;
|
||||||
pub use self::percentage::Percentage;
|
pub use self::percentage::Percentage;
|
||||||
|
pub use self::position::AspectRatio;
|
||||||
pub use self::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto};
|
pub use self::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto};
|
||||||
pub use self::position::{PositionComponent, ZIndex};
|
pub use self::position::{PositionComponent, ZIndex};
|
||||||
pub use self::rect::NonNegativeLengthOrNumberRect;
|
pub use self::rect::NonNegativeLengthOrNumberRect;
|
||||||
|
@ -375,6 +375,18 @@ impl Parse for NonNegativeNumber {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl One for NonNegativeNumber {
|
||||||
|
#[inline]
|
||||||
|
fn one() -> Self {
|
||||||
|
NonNegativeNumber::new(1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_one(&self) -> bool {
|
||||||
|
self.0.get() == 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NonNegativeNumber {
|
impl NonNegativeNumber {
|
||||||
/// Returns a new non-negative number with the value `val`.
|
/// Returns a new non-negative number with the value `val`.
|
||||||
pub fn new(val: CSSFloat) -> Self {
|
pub fn new(val: CSSFloat) -> Self {
|
||||||
|
@ -537,7 +549,7 @@ impl Zero for Integer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl One for Integer {
|
impl num_traits::One for Integer {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Self {
|
fn one() -> Self {
|
||||||
Self::new(1)
|
Self::new(1)
|
||||||
|
|
|
@ -12,13 +12,14 @@ use crate::selector_map::PrecomputedHashMap;
|
||||||
use crate::str::HTML_SPACE_CHARACTERS;
|
use crate::str::HTML_SPACE_CHARACTERS;
|
||||||
use crate::values::computed::LengthPercentage as ComputedLengthPercentage;
|
use crate::values::computed::LengthPercentage as ComputedLengthPercentage;
|
||||||
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
use crate::values::computed::{Context, Percentage, ToComputedValue};
|
||||||
|
use crate::values::generics::position::AspectRatio as GenericAspectRatio;
|
||||||
use crate::values::generics::position::Position as GenericPosition;
|
use crate::values::generics::position::Position as GenericPosition;
|
||||||
use crate::values::generics::position::PositionComponent as GenericPositionComponent;
|
use crate::values::generics::position::PositionComponent as GenericPositionComponent;
|
||||||
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
||||||
|
use crate::values::generics::position::Ratio as GenericRatio;
|
||||||
use crate::values::generics::position::ZIndex as GenericZIndex;
|
use crate::values::generics::position::ZIndex as GenericZIndex;
|
||||||
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
|
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage, NonNegativeNumber};
|
||||||
use crate::Atom;
|
use crate::{Atom, One, Zero};
|
||||||
use crate::Zero;
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -877,3 +878,46 @@ impl GridTemplateAreas {
|
||||||
|
|
||||||
/// A specified value for the `z-index` property.
|
/// A specified value for the `z-index` property.
|
||||||
pub type ZIndex = GenericZIndex<Integer>;
|
pub type ZIndex = GenericZIndex<Integer>;
|
||||||
|
|
||||||
|
/// A specified value for the `aspect-ratio` property.
|
||||||
|
pub type AspectRatio = GenericAspectRatio<NonNegativeNumber>;
|
||||||
|
|
||||||
|
// FIXME: Add field_bound for parse custom derive, so we can drop this.
|
||||||
|
impl Parse for AspectRatio {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
if input
|
||||||
|
.try(|input| input.expect_ident_matching("auto"))
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
return Ok(AspectRatio::Auto);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericRatio::parse(context, input).map(AspectRatio::Ratio)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-values-4/#ratios
|
||||||
|
impl Parse for GenericRatio<NonNegativeNumber> {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
let a = NonNegativeNumber::parse(context, input)?;
|
||||||
|
let b = match input.try_parse(|input| input.expect_delim('/')) {
|
||||||
|
Ok(()) => NonNegativeNumber::parse(context, input)?,
|
||||||
|
_ => One::one(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// The computed value of a <ratio> is the pair of numbers provided, unless
|
||||||
|
// both numbers are zero, in which case the computed value is the pair (1, 0)
|
||||||
|
// (same as 1 / 0).
|
||||||
|
// https://drafts.csswg.org/css-values-4/#ratios
|
||||||
|
if a.is_zero() && b.is_zero() {
|
||||||
|
return Ok(GenericRatio(One::one(), Zero::zero()));
|
||||||
|
}
|
||||||
|
return Ok(GenericRatio(a, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue