mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
style: Implement parsing of container relative lengths
- For now, implementation always returns the fallback value, i.e. small viewport lengths. - Enabled via existing pref `layout.css.container-queries.enabled`. Differential Revision: https://phabricator.services.mozilla.com/D158054
This commit is contained in:
parent
4dd841a036
commit
d8785f3a22
4 changed files with 202 additions and 3 deletions
|
@ -58,6 +58,13 @@ impl specified::NoCalcLength {
|
|||
.add_flags(ComputedValueFlags::USES_VIEWPORT_UNITS);
|
||||
length.to_computed_value(context)
|
||||
},
|
||||
specified::NoCalcLength::ContainerRelative(length) => {
|
||||
// Fallback uses small viewport size.
|
||||
context
|
||||
.builder
|
||||
.add_flags(ComputedValueFlags::USES_VIEWPORT_UNITS);
|
||||
length.to_computed_value(context)
|
||||
},
|
||||
specified::NoCalcLength::ServoCharacterWidth(length) => {
|
||||
length.to_computed_value(context.style().get_font().clone_font_size().size())
|
||||
},
|
||||
|
|
|
@ -44,6 +44,12 @@ pub enum SortKey {
|
|||
Percentage,
|
||||
Cap,
|
||||
Ch,
|
||||
Cqb,
|
||||
Cqh,
|
||||
Cqi,
|
||||
Cqmax,
|
||||
Cqmin,
|
||||
Cqw,
|
||||
Deg,
|
||||
Dvb,
|
||||
Dvh,
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
use crate::parser::ParserContext;
|
||||
use crate::values::generics::calc as generic;
|
||||
use crate::values::generics::calc::{MinMaxOp, SortKey};
|
||||
use crate::values::specified::length::ViewportPercentageLength;
|
||||
use crate::values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
|
||||
use crate::values::specified::length::{ContainerRelativeLength, ViewportPercentageLength};
|
||||
use crate::values::specified::{self, Angle, Time};
|
||||
use crate::values::{CSSFloat, CSSInteger};
|
||||
use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
|
||||
|
@ -258,6 +258,14 @@ impl generic::CalcNodeLeaf for Leaf {
|
|||
ViewportPercentageLength::Lvi(..) => SortKey::Lvi,
|
||||
ViewportPercentageLength::Dvi(..) => SortKey::Dvi,
|
||||
},
|
||||
NoCalcLength::ContainerRelative(ref cq) => match *cq {
|
||||
ContainerRelativeLength::Cqw(..) => SortKey::Cqw,
|
||||
ContainerRelativeLength::Cqh(..) => SortKey::Cqh,
|
||||
ContainerRelativeLength::Cqi(..) => SortKey::Cqi,
|
||||
ContainerRelativeLength::Cqb(..) => SortKey::Cqb,
|
||||
ContainerRelativeLength::Cqmin(..) => SortKey::Cqmin,
|
||||
ContainerRelativeLength::Cqmax(..) => SortKey::Cqmax,
|
||||
},
|
||||
NoCalcLength::ServoCharacterWidth(..) => unreachable!(),
|
||||
},
|
||||
}
|
||||
|
|
|
@ -642,6 +642,102 @@ impl Add<AbsoluteLength> for AbsoluteLength {
|
|||
}
|
||||
}
|
||||
|
||||
/// A container query length.
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-contain-3/#container-lengths>
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
|
||||
pub enum ContainerRelativeLength {
|
||||
/// 1% of query container's width
|
||||
#[css(dimension)]
|
||||
Cqw(CSSFloat),
|
||||
/// 1% of query container's height
|
||||
#[css(dimension)]
|
||||
Cqh(CSSFloat),
|
||||
/// 1% of query container's inline size
|
||||
#[css(dimension)]
|
||||
Cqi(CSSFloat),
|
||||
/// 1% of query container's block size
|
||||
#[css(dimension)]
|
||||
Cqb(CSSFloat),
|
||||
/// The smaller value of `cqi` or `cqb`
|
||||
#[css(dimension)]
|
||||
Cqmin(CSSFloat),
|
||||
/// The larger value of `cqi` or `cqb`
|
||||
#[css(dimension)]
|
||||
Cqmax(CSSFloat),
|
||||
}
|
||||
|
||||
impl ContainerRelativeLength {
|
||||
fn unitless_value(&self) -> CSSFloat {
|
||||
match *self {
|
||||
ContainerRelativeLength::Cqw(v) |
|
||||
ContainerRelativeLength::Cqh(v) |
|
||||
ContainerRelativeLength::Cqi(v) |
|
||||
ContainerRelativeLength::Cqb(v) |
|
||||
ContainerRelativeLength::Cqmin(v) |
|
||||
ContainerRelativeLength::Cqmax(v) => v,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.unitless_value() == 0.
|
||||
}
|
||||
|
||||
fn is_negative(&self) -> bool {
|
||||
self.unitless_value() < 0.
|
||||
}
|
||||
|
||||
fn try_sum(&self, other: &Self) -> Result<Self, ()> {
|
||||
use self::ContainerRelativeLength::*;
|
||||
|
||||
if std::mem::discriminant(self) != std::mem::discriminant(other) {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Ok(match (self, other) {
|
||||
(&Cqw(one), &Cqw(other)) => Cqw(one + other),
|
||||
(&Cqh(one), &Cqh(other)) => Cqh(one + other),
|
||||
(&Cqi(one), &Cqi(other)) => Cqi(one + other),
|
||||
(&Cqb(one), &Cqb(other)) => Cqb(one + other),
|
||||
(&Cqmin(one), &Cqmin(other)) => Cqmin(one + other),
|
||||
(&Cqmax(one), &Cqmax(other)) => Cqmax(one + other),
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/68867, then
|
||||
// https://github.com/rust-lang/rust/pull/95161. rustc isn't
|
||||
// able to figure it own on its own so we help.
|
||||
_ => unsafe {
|
||||
match *self {
|
||||
Cqw(..) | Cqh(..) | Cqi(..) | Cqb(..) | Cqmin(..) | Cqmax(..) => {},
|
||||
}
|
||||
debug_unreachable!("Forgot to handle unit in try_sum()")
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/// Computes the given container-relative length.
|
||||
pub fn to_computed_value(&self, context: &Context) -> CSSPixelLength {
|
||||
// TODO(dshin): For now, use the small viewport size.
|
||||
let small_viewport_size = match *self {
|
||||
ContainerRelativeLength::Cqw(v) => ViewportPercentageLength::Svw(v),
|
||||
ContainerRelativeLength::Cqh(v) => ViewportPercentageLength::Svh(v),
|
||||
ContainerRelativeLength::Cqi(v) => ViewportPercentageLength::Svi(v),
|
||||
ContainerRelativeLength::Cqb(v) => ViewportPercentageLength::Svb(v),
|
||||
ContainerRelativeLength::Cqmin(v) => ViewportPercentageLength::Svmin(v),
|
||||
ContainerRelativeLength::Cqmax(v) => ViewportPercentageLength::Svmax(v),
|
||||
};
|
||||
small_viewport_size.to_computed_value(context)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn are_container_queries_enabled() -> bool {
|
||||
static_prefs::pref!("layout.css.container-queries.enabled")
|
||||
}
|
||||
#[cfg(feature = "servo")]
|
||||
fn are_container_queries_enabled() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// A `<length>` without taking `calc` expressions into account
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-values/#lengths>
|
||||
|
@ -662,6 +758,10 @@ pub enum NoCalcLength {
|
|||
/// <https://drafts.csswg.org/css-values/#viewport-relative-lengths>
|
||||
ViewportPercentage(ViewportPercentageLength),
|
||||
|
||||
/// A container query length.
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-contain-3/#container-lengths>
|
||||
ContainerRelative(ContainerRelativeLength),
|
||||
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
||||
///
|
||||
/// This cannot be specified by the user directly and is only generated by
|
||||
|
@ -679,6 +779,7 @@ impl Mul<CSSFloat> for NoCalcLength {
|
|||
NoCalcLength::Absolute(v) => NoCalcLength::Absolute(v * scalar),
|
||||
NoCalcLength::FontRelative(v) => NoCalcLength::FontRelative(v * scalar),
|
||||
NoCalcLength::ViewportPercentage(v) => NoCalcLength::ViewportPercentage(v * scalar),
|
||||
NoCalcLength::ContainerRelative(v) => NoCalcLength::ContainerRelative(v * scalar),
|
||||
NoCalcLength::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
||||
}
|
||||
}
|
||||
|
@ -691,6 +792,7 @@ impl NoCalcLength {
|
|||
NoCalcLength::Absolute(v) => v.unitless_value(),
|
||||
NoCalcLength::FontRelative(v) => v.unitless_value(),
|
||||
NoCalcLength::ViewportPercentage(v) => v.unitless_value(),
|
||||
NoCalcLength::ContainerRelative(v) => v.unitless_value(),
|
||||
NoCalcLength::ServoCharacterWidth(c) => c.0 as f32,
|
||||
}
|
||||
}
|
||||
|
@ -701,6 +803,7 @@ impl NoCalcLength {
|
|||
NoCalcLength::Absolute(v) => v.is_negative(),
|
||||
NoCalcLength::FontRelative(v) => v.is_negative(),
|
||||
NoCalcLength::ViewportPercentage(v) => v.is_negative(),
|
||||
NoCalcLength::ContainerRelative(v) => v.is_negative(),
|
||||
NoCalcLength::ServoCharacterWidth(c) => c.0 < 0,
|
||||
}
|
||||
}
|
||||
|
@ -711,8 +814,11 @@ impl NoCalcLength {
|
|||
/// because the font they're relative to should be zoomed already.
|
||||
pub fn should_zoom_text(&self) -> bool {
|
||||
match *self {
|
||||
Self::Absolute(..) | Self::ViewportPercentage(..) => true,
|
||||
Self::ServoCharacterWidth(..) | Self::FontRelative(..) => false,
|
||||
Self::Absolute(..) |
|
||||
Self::ViewportPercentage(..) |
|
||||
Self::ContainerRelative(..) => true,
|
||||
Self::ServoCharacterWidth(..) |
|
||||
Self::FontRelative(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -810,6 +916,26 @@ impl NoCalcLength {
|
|||
"dvi" if !context.in_page_rule() => {
|
||||
NoCalcLength::ViewportPercentage(ViewportPercentageLength::Dvi(value))
|
||||
},
|
||||
// Container query lengths. Inherit the limitation from viewport units since
|
||||
// we may fall back to them.
|
||||
"cqw" if !context.in_page_rule() && are_container_queries_enabled() => {
|
||||
NoCalcLength::ContainerRelative(ContainerRelativeLength::Cqw(value))
|
||||
},
|
||||
"cqh" if !context.in_page_rule() && are_container_queries_enabled() => {
|
||||
NoCalcLength::ContainerRelative(ContainerRelativeLength::Cqh(value))
|
||||
},
|
||||
"cqi" if !context.in_page_rule() && are_container_queries_enabled() => {
|
||||
NoCalcLength::ContainerRelative(ContainerRelativeLength::Cqi(value))
|
||||
},
|
||||
"cqb" if !context.in_page_rule() && are_container_queries_enabled() => {
|
||||
NoCalcLength::ContainerRelative(ContainerRelativeLength::Cqb(value))
|
||||
},
|
||||
"cqmin" if !context.in_page_rule() && are_container_queries_enabled() => {
|
||||
NoCalcLength::ContainerRelative(ContainerRelativeLength::Cqmin(value))
|
||||
},
|
||||
"cqmax" if !context.in_page_rule() && are_container_queries_enabled() => {
|
||||
NoCalcLength::ContainerRelative(ContainerRelativeLength::Cqmax(value))
|
||||
},
|
||||
_ => return Err(()),
|
||||
})
|
||||
}
|
||||
|
@ -828,6 +954,9 @@ impl NoCalcLength {
|
|||
(&ViewportPercentage(ref one), &ViewportPercentage(ref other)) => {
|
||||
ViewportPercentage(one.try_sum(other)?)
|
||||
},
|
||||
(&ContainerRelative(ref one), &ContainerRelative(ref other)) => {
|
||||
ContainerRelative(one.try_sum(other)?)
|
||||
},
|
||||
(&ServoCharacterWidth(ref one), &ServoCharacterWidth(ref other)) => {
|
||||
ServoCharacterWidth(CharacterWidth(one.0 + other.0))
|
||||
},
|
||||
|
@ -838,6 +967,7 @@ impl NoCalcLength {
|
|||
Absolute(..) |
|
||||
FontRelative(..) |
|
||||
ViewportPercentage(..) |
|
||||
ContainerRelative(..) |
|
||||
ServoCharacterWidth(..) => {},
|
||||
}
|
||||
debug_unreachable!("Forgot to handle unit in try_sum()")
|
||||
|
@ -877,6 +1007,7 @@ impl PartialOrd for NoCalcLength {
|
|||
(&ViewportPercentage(ref one), &ViewportPercentage(ref other)) => {
|
||||
one.partial_cmp(other)
|
||||
},
|
||||
(&ContainerRelative(ref one), &ContainerRelative(ref other)) => one.partial_cmp(other),
|
||||
(&ServoCharacterWidth(ref one), &ServoCharacterWidth(ref other)) => {
|
||||
one.0.partial_cmp(&other.0)
|
||||
},
|
||||
|
@ -887,6 +1018,7 @@ impl PartialOrd for NoCalcLength {
|
|||
Absolute(..) |
|
||||
FontRelative(..) |
|
||||
ViewportPercentage(..) |
|
||||
ContainerRelative(..) |
|
||||
ServoCharacterWidth(..) => {},
|
||||
}
|
||||
debug_unreachable!("Forgot an arm in partial_cmp?")
|
||||
|
@ -905,6 +1037,7 @@ impl Zero for NoCalcLength {
|
|||
NoCalcLength::Absolute(v) => v.is_zero(),
|
||||
NoCalcLength::FontRelative(v) => v.is_zero(),
|
||||
NoCalcLength::ViewportPercentage(v) => v.is_zero(),
|
||||
NoCalcLength::ContainerRelative(v) => v.is_zero(),
|
||||
NoCalcLength::ServoCharacterWidth(v) => v.0 == 0,
|
||||
}
|
||||
}
|
||||
|
@ -986,6 +1119,51 @@ impl Mul<CSSFloat> for FontRelativeLength {
|
|||
}
|
||||
}
|
||||
|
||||
impl Mul<CSSFloat> for ContainerRelativeLength {
|
||||
type Output = ContainerRelativeLength;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, scalar: CSSFloat) -> ContainerRelativeLength {
|
||||
match self {
|
||||
ContainerRelativeLength::Cqw(v) => ContainerRelativeLength::Cqw(v * scalar),
|
||||
ContainerRelativeLength::Cqh(v) => ContainerRelativeLength::Cqh(v * scalar),
|
||||
ContainerRelativeLength::Cqi(v) => ContainerRelativeLength::Cqi(v * scalar),
|
||||
ContainerRelativeLength::Cqb(v) => ContainerRelativeLength::Cqb(v * scalar),
|
||||
ContainerRelativeLength::Cqmin(v) => ContainerRelativeLength::Cqmin(v * scalar),
|
||||
ContainerRelativeLength::Cqmax(v) => ContainerRelativeLength::Cqmax(v * scalar),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for ContainerRelativeLength {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||
use self::ContainerRelativeLength::*;
|
||||
|
||||
if std::mem::discriminant(self) != std::mem::discriminant(other) {
|
||||
return None;
|
||||
}
|
||||
|
||||
match (self, other) {
|
||||
(&Cqw(ref one), &Cqw(ref other)) => one.partial_cmp(other),
|
||||
(&Cqh(ref one), &Cqh(ref other)) => one.partial_cmp(other),
|
||||
(&Cqi(ref one), &Cqi(ref other)) => one.partial_cmp(other),
|
||||
(&Cqb(ref one), &Cqb(ref other)) => one.partial_cmp(other),
|
||||
(&Cqmin(ref one), &Cqmin(ref other)) => one.partial_cmp(other),
|
||||
(&Cqmax(ref one), &Cqmax(ref other)) => one.partial_cmp(other),
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/68867, then
|
||||
// https://github.com/rust-lang/rust/pull/95161. rustc isn't
|
||||
// able to figure it own on its own so we help.
|
||||
_ => unsafe {
|
||||
match *self {
|
||||
Cqw(..) | Cqh(..) | Cqi(..) | Cqb(..) | Cqmin(..) | Cqmax(..) => {},
|
||||
}
|
||||
debug_unreachable!("Forgot to handle unit in try_sum()")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<CSSFloat> for ViewportPercentageLength {
|
||||
type Output = ViewportPercentageLength;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue