mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +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);
|
.add_flags(ComputedValueFlags::USES_VIEWPORT_UNITS);
|
||||||
length.to_computed_value(context)
|
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) => {
|
specified::NoCalcLength::ServoCharacterWidth(length) => {
|
||||||
length.to_computed_value(context.style().get_font().clone_font_size().size())
|
length.to_computed_value(context.style().get_font().clone_font_size().size())
|
||||||
},
|
},
|
||||||
|
|
|
@ -44,6 +44,12 @@ pub enum SortKey {
|
||||||
Percentage,
|
Percentage,
|
||||||
Cap,
|
Cap,
|
||||||
Ch,
|
Ch,
|
||||||
|
Cqb,
|
||||||
|
Cqh,
|
||||||
|
Cqi,
|
||||||
|
Cqmax,
|
||||||
|
Cqmin,
|
||||||
|
Cqw,
|
||||||
Deg,
|
Deg,
|
||||||
Dvb,
|
Dvb,
|
||||||
Dvh,
|
Dvh,
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::values::generics::calc as generic;
|
use crate::values::generics::calc as generic;
|
||||||
use crate::values::generics::calc::{MinMaxOp, SortKey};
|
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::{AbsoluteLength, FontRelativeLength, NoCalcLength};
|
||||||
|
use crate::values::specified::length::{ContainerRelativeLength, ViewportPercentageLength};
|
||||||
use crate::values::specified::{self, Angle, Time};
|
use crate::values::specified::{self, Angle, Time};
|
||||||
use crate::values::{CSSFloat, CSSInteger};
|
use crate::values::{CSSFloat, CSSInteger};
|
||||||
use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
|
use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
|
||||||
|
@ -258,6 +258,14 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
ViewportPercentageLength::Lvi(..) => SortKey::Lvi,
|
ViewportPercentageLength::Lvi(..) => SortKey::Lvi,
|
||||||
ViewportPercentageLength::Dvi(..) => SortKey::Dvi,
|
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!(),
|
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
|
/// A `<length>` without taking `calc` expressions into account
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-values/#lengths>
|
/// <https://drafts.csswg.org/css-values/#lengths>
|
||||||
|
@ -662,6 +758,10 @@ pub enum NoCalcLength {
|
||||||
/// <https://drafts.csswg.org/css-values/#viewport-relative-lengths>
|
/// <https://drafts.csswg.org/css-values/#viewport-relative-lengths>
|
||||||
ViewportPercentage(ViewportPercentageLength),
|
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.
|
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
||||||
///
|
///
|
||||||
/// This cannot be specified by the user directly and is only generated by
|
/// 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::Absolute(v) => NoCalcLength::Absolute(v * scalar),
|
||||||
NoCalcLength::FontRelative(v) => NoCalcLength::FontRelative(v * scalar),
|
NoCalcLength::FontRelative(v) => NoCalcLength::FontRelative(v * scalar),
|
||||||
NoCalcLength::ViewportPercentage(v) => NoCalcLength::ViewportPercentage(v * scalar),
|
NoCalcLength::ViewportPercentage(v) => NoCalcLength::ViewportPercentage(v * scalar),
|
||||||
|
NoCalcLength::ContainerRelative(v) => NoCalcLength::ContainerRelative(v * scalar),
|
||||||
NoCalcLength::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
NoCalcLength::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -691,6 +792,7 @@ impl NoCalcLength {
|
||||||
NoCalcLength::Absolute(v) => v.unitless_value(),
|
NoCalcLength::Absolute(v) => v.unitless_value(),
|
||||||
NoCalcLength::FontRelative(v) => v.unitless_value(),
|
NoCalcLength::FontRelative(v) => v.unitless_value(),
|
||||||
NoCalcLength::ViewportPercentage(v) => v.unitless_value(),
|
NoCalcLength::ViewportPercentage(v) => v.unitless_value(),
|
||||||
|
NoCalcLength::ContainerRelative(v) => v.unitless_value(),
|
||||||
NoCalcLength::ServoCharacterWidth(c) => c.0 as f32,
|
NoCalcLength::ServoCharacterWidth(c) => c.0 as f32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -701,6 +803,7 @@ impl NoCalcLength {
|
||||||
NoCalcLength::Absolute(v) => v.is_negative(),
|
NoCalcLength::Absolute(v) => v.is_negative(),
|
||||||
NoCalcLength::FontRelative(v) => v.is_negative(),
|
NoCalcLength::FontRelative(v) => v.is_negative(),
|
||||||
NoCalcLength::ViewportPercentage(v) => v.is_negative(),
|
NoCalcLength::ViewportPercentage(v) => v.is_negative(),
|
||||||
|
NoCalcLength::ContainerRelative(v) => v.is_negative(),
|
||||||
NoCalcLength::ServoCharacterWidth(c) => c.0 < 0,
|
NoCalcLength::ServoCharacterWidth(c) => c.0 < 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,8 +814,11 @@ impl NoCalcLength {
|
||||||
/// because the font they're relative to should be zoomed already.
|
/// because the font they're relative to should be zoomed already.
|
||||||
pub fn should_zoom_text(&self) -> bool {
|
pub fn should_zoom_text(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Absolute(..) | Self::ViewportPercentage(..) => true,
|
Self::Absolute(..) |
|
||||||
Self::ServoCharacterWidth(..) | Self::FontRelative(..) => false,
|
Self::ViewportPercentage(..) |
|
||||||
|
Self::ContainerRelative(..) => true,
|
||||||
|
Self::ServoCharacterWidth(..) |
|
||||||
|
Self::FontRelative(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,6 +916,26 @@ impl NoCalcLength {
|
||||||
"dvi" if !context.in_page_rule() => {
|
"dvi" if !context.in_page_rule() => {
|
||||||
NoCalcLength::ViewportPercentage(ViewportPercentageLength::Dvi(value))
|
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(()),
|
_ => return Err(()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -828,6 +954,9 @@ impl NoCalcLength {
|
||||||
(&ViewportPercentage(ref one), &ViewportPercentage(ref other)) => {
|
(&ViewportPercentage(ref one), &ViewportPercentage(ref other)) => {
|
||||||
ViewportPercentage(one.try_sum(other)?)
|
ViewportPercentage(one.try_sum(other)?)
|
||||||
},
|
},
|
||||||
|
(&ContainerRelative(ref one), &ContainerRelative(ref other)) => {
|
||||||
|
ContainerRelative(one.try_sum(other)?)
|
||||||
|
},
|
||||||
(&ServoCharacterWidth(ref one), &ServoCharacterWidth(ref other)) => {
|
(&ServoCharacterWidth(ref one), &ServoCharacterWidth(ref other)) => {
|
||||||
ServoCharacterWidth(CharacterWidth(one.0 + other.0))
|
ServoCharacterWidth(CharacterWidth(one.0 + other.0))
|
||||||
},
|
},
|
||||||
|
@ -838,6 +967,7 @@ impl NoCalcLength {
|
||||||
Absolute(..) |
|
Absolute(..) |
|
||||||
FontRelative(..) |
|
FontRelative(..) |
|
||||||
ViewportPercentage(..) |
|
ViewportPercentage(..) |
|
||||||
|
ContainerRelative(..) |
|
||||||
ServoCharacterWidth(..) => {},
|
ServoCharacterWidth(..) => {},
|
||||||
}
|
}
|
||||||
debug_unreachable!("Forgot to handle unit in try_sum()")
|
debug_unreachable!("Forgot to handle unit in try_sum()")
|
||||||
|
@ -877,6 +1007,7 @@ impl PartialOrd for NoCalcLength {
|
||||||
(&ViewportPercentage(ref one), &ViewportPercentage(ref other)) => {
|
(&ViewportPercentage(ref one), &ViewportPercentage(ref other)) => {
|
||||||
one.partial_cmp(other)
|
one.partial_cmp(other)
|
||||||
},
|
},
|
||||||
|
(&ContainerRelative(ref one), &ContainerRelative(ref other)) => one.partial_cmp(other),
|
||||||
(&ServoCharacterWidth(ref one), &ServoCharacterWidth(ref other)) => {
|
(&ServoCharacterWidth(ref one), &ServoCharacterWidth(ref other)) => {
|
||||||
one.0.partial_cmp(&other.0)
|
one.0.partial_cmp(&other.0)
|
||||||
},
|
},
|
||||||
|
@ -887,6 +1018,7 @@ impl PartialOrd for NoCalcLength {
|
||||||
Absolute(..) |
|
Absolute(..) |
|
||||||
FontRelative(..) |
|
FontRelative(..) |
|
||||||
ViewportPercentage(..) |
|
ViewportPercentage(..) |
|
||||||
|
ContainerRelative(..) |
|
||||||
ServoCharacterWidth(..) => {},
|
ServoCharacterWidth(..) => {},
|
||||||
}
|
}
|
||||||
debug_unreachable!("Forgot an arm in partial_cmp?")
|
debug_unreachable!("Forgot an arm in partial_cmp?")
|
||||||
|
@ -905,6 +1037,7 @@ impl Zero for NoCalcLength {
|
||||||
NoCalcLength::Absolute(v) => v.is_zero(),
|
NoCalcLength::Absolute(v) => v.is_zero(),
|
||||||
NoCalcLength::FontRelative(v) => v.is_zero(),
|
NoCalcLength::FontRelative(v) => v.is_zero(),
|
||||||
NoCalcLength::ViewportPercentage(v) => v.is_zero(),
|
NoCalcLength::ViewportPercentage(v) => v.is_zero(),
|
||||||
|
NoCalcLength::ContainerRelative(v) => v.is_zero(),
|
||||||
NoCalcLength::ServoCharacterWidth(v) => v.0 == 0,
|
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 {
|
impl Mul<CSSFloat> for ViewportPercentageLength {
|
||||||
type Output = ViewportPercentageLength;
|
type Output = ViewportPercentageLength;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue