Bug 1920496 - Make ColorFunction be stored in ComputedStyle r=emilio

We now fully support the full ColorFunction in the ComputedStyle struct
in layout.  This solves an issue where colors are copied on the C++
side.

Some structs had to be renamed to avoid name collisions in the generates
C++ code.

Some specified structs has the #[repr(C)] attribute now to include them
in the ComputedStyle struct.  This is not really correct as they are
specified values and only computed values should be there. Splitting all
the unit structs into specified and computed is a lot of changes so
there is a follow up bug here:
https://bugzilla.mozilla.org/show_bug.cgi?id=1924483

Differential Revision: https://phabricator.services.mozilla.com/D225080
This commit is contained in:
Tiaan Louw 2024-10-16 13:45:19 +00:00
parent 96526acd5c
commit fbd6dd0fce
9 changed files with 168 additions and 134 deletions

View File

@ -503,6 +503,7 @@ cbindgen-types = [
{ gecko = "StyleSystemFont", servo = "crate::values::specified::font::SystemFont" },
{ gecko = "StyleGenericColorOrAuto", servo = "crate::values::generics::color::ColorOrAuto" },
{ gecko = "StyleGenericScrollbarColor", servo = "crate::values::generics::ui::ScrollbarColor" },
{ gecko = "StyleColorComponent", servo = "crate::color::component::ColorComponent" },
{ gecko = "StyleAbsoluteColor", servo = "crate::color::AbsoluteColor" },
{ gecko = "StyleOrigin", servo = "crate::stylesheets::Origin" },
{ gecko = "StyleGenericVerticalAlign", servo = "crate::values::generics::box_::VerticalAlign" },

View File

@ -70,15 +70,6 @@ namespace mozilla {
class ComputedStyle;
template <typename T>
struct StyleColorFunction {};
template <typename T>
inline bool operator==(const StyleColorFunction<T>& left,
const StyleColorFunction<T>& right) {
return &left == &right;
}
using Matrix4x4Components = float[16];
using StyleMatrix4x4Components = Matrix4x4Components;

View File

@ -9,80 +9,82 @@ use std::fmt::Write;
use super::{
component::ColorComponent,
convert::normalize_hue,
parsing::{NumberOrAngle, NumberOrPercentage},
parsing::{NumberOrAngleComponent, NumberOrPercentageComponent},
AbsoluteColor, ColorFlags, ColorSpace,
};
use crate::values::{
computed::color::Color as ComputedColor, normalize, specified::color::Color as SpecifiedColor,
computed::color::Color as ComputedColor, generics::Optional, normalize,
specified::color::Color as SpecifiedColor,
};
use cssparser::color::{clamp_floor_256_f32, OPAQUE};
/// Represents a specified color function.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToShmem)]
pub enum ColorFunction<Color> {
#[repr(u8)]
pub enum ColorFunction<OriginColor> {
/// <https://drafts.csswg.org/css-color-4/#rgb-functions>
Rgb(
Option<Color>, // origin
ColorComponent<NumberOrPercentage>, // red
ColorComponent<NumberOrPercentage>, // green
ColorComponent<NumberOrPercentage>, // blue
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrPercentageComponent>, // red
ColorComponent<NumberOrPercentageComponent>, // green
ColorComponent<NumberOrPercentageComponent>, // blue
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#the-hsl-notation>
Hsl(
Option<Color>, // origin
ColorComponent<NumberOrAngle>, // hue
ColorComponent<NumberOrPercentage>, // saturation
ColorComponent<NumberOrPercentage>, // lightness
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrAngleComponent>, // hue
ColorComponent<NumberOrPercentageComponent>, // saturation
ColorComponent<NumberOrPercentageComponent>, // lightness
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#the-hwb-notation>
Hwb(
Option<Color>, // origin
ColorComponent<NumberOrAngle>, // hue
ColorComponent<NumberOrPercentage>, // whiteness
ColorComponent<NumberOrPercentage>, // blackness
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrAngleComponent>, // hue
ColorComponent<NumberOrPercentageComponent>, // whiteness
ColorComponent<NumberOrPercentageComponent>, // blackness
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#specifying-lab-lch>
Lab(
Option<Color>, // origin
ColorComponent<NumberOrPercentage>, // lightness
ColorComponent<NumberOrPercentage>, // a
ColorComponent<NumberOrPercentage>, // b
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrPercentageComponent>, // lightness
ColorComponent<NumberOrPercentageComponent>, // a
ColorComponent<NumberOrPercentageComponent>, // b
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#specifying-lab-lch>
Lch(
Option<Color>, // origin
ColorComponent<NumberOrPercentage>, // lightness
ColorComponent<NumberOrPercentage>, // chroma
ColorComponent<NumberOrAngle>, // hue
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrPercentageComponent>, // lightness
ColorComponent<NumberOrPercentageComponent>, // chroma
ColorComponent<NumberOrAngleComponent>, // hue
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#specifying-oklab-oklch>
Oklab(
Option<Color>, // origin
ColorComponent<NumberOrPercentage>, // lightness
ColorComponent<NumberOrPercentage>, // a
ColorComponent<NumberOrPercentage>, // b
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrPercentageComponent>, // lightness
ColorComponent<NumberOrPercentageComponent>, // a
ColorComponent<NumberOrPercentageComponent>, // b
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#specifying-oklab-oklch>
Oklch(
Option<Color>, // origin
ColorComponent<NumberOrPercentage>, // lightness
ColorComponent<NumberOrPercentage>, // chroma
ColorComponent<NumberOrAngle>, // hue
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrPercentageComponent>, // lightness
ColorComponent<NumberOrPercentageComponent>, // chroma
ColorComponent<NumberOrAngleComponent>, // hue
ColorComponent<NumberOrPercentageComponent>, // alpha
),
/// <https://drafts.csswg.org/css-color-4/#color-function>
Color(
Option<Color>, // origin
ColorComponent<NumberOrPercentage>, // red / x
ColorComponent<NumberOrPercentage>, // green / y
ColorComponent<NumberOrPercentage>, // blue / z
ColorComponent<NumberOrPercentage>, // alpha
Optional<OriginColor>, // origin
ColorComponent<NumberOrPercentageComponent>, // red / x
ColorComponent<NumberOrPercentageComponent>, // green / y
ColorComponent<NumberOrPercentageComponent>, // blue / z
ColorComponent<NumberOrPercentageComponent>, // alpha
ColorSpace,
),
}
@ -101,7 +103,7 @@ impl ColorFunction<AbsoluteColor> {
ColorFunction::Rgb(origin_color, r, g, b, alpha) => {
#[inline]
fn resolve(
component: &ColorComponent<NumberOrPercentage>,
component: &ColorComponent<NumberOrPercentageComponent>,
origin_color: Option<&AbsoluteColor>,
) -> Result<u8, ()> {
Ok(clamp_floor_256_f32(
@ -112,8 +114,9 @@ impl ColorFunction<AbsoluteColor> {
))
}
let origin_color =
origin_color.map(|o| o.to_color_space(ColorSpace::Srgb).into_srgb_legacy());
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Srgb).into_srgb_legacy());
let r = resolve(r, origin_color.as_ref())?;
let g = resolve(g, origin_color.as_ref())?;
@ -138,7 +141,9 @@ impl ColorFunction<AbsoluteColor> {
// color to be out of gamut and not clamp.
let use_rgb_sytax = origin_color.is_none();
let origin_color = origin_color.map(|o| o.to_color_space(ColorSpace::Hsl));
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Hsl));
let mut result = AbsoluteColor::new(
ColorSpace::Hsl,
@ -179,7 +184,9 @@ impl ColorFunction<AbsoluteColor> {
const WHITENESS_RANGE: f32 = 100.0;
const BLACKNESS_RANGE: f32 = 100.0;
let origin_color = origin_color.map(|o| o.to_color_space(ColorSpace::Hwb));
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Hwb));
let mut result = AbsoluteColor::new(
ColorSpace::Hwb,
@ -214,7 +221,9 @@ impl ColorFunction<AbsoluteColor> {
const LIGHTNESS_RANGE: f32 = 100.0;
const A_B_RANGE: f32 = 125.0;
let origin_color = origin_color.map(|o| o.to_color_space(ColorSpace::Lab));
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Lab));
AbsoluteColor::new(
ColorSpace::Lab,
@ -233,7 +242,9 @@ impl ColorFunction<AbsoluteColor> {
const LIGHTNESS_RANGE: f32 = 100.0;
const CHROMA_RANGE: f32 = 150.0;
let origin_color = origin_color.map(|o| o.to_color_space(ColorSpace::Lch));
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Lch));
AbsoluteColor::new(
ColorSpace::Lch,
@ -252,7 +263,9 @@ impl ColorFunction<AbsoluteColor> {
const LIGHTNESS_RANGE: f32 = 1.0;
const A_B_RANGE: f32 = 0.4;
let origin_color = origin_color.map(|o| o.to_color_space(ColorSpace::Oklab));
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Oklab));
AbsoluteColor::new(
ColorSpace::Oklab,
@ -271,7 +284,9 @@ impl ColorFunction<AbsoluteColor> {
const LIGHTNESS_RANGE: f32 = 1.0;
const CHROMA_RANGE: f32 = 0.4;
let origin_color = origin_color.map(|o| o.to_color_space(ColorSpace::Oklch));
let origin_color = origin_color
.as_ref()
.map(|o| o.to_color_space(ColorSpace::Oklch));
AbsoluteColor::new(
ColorSpace::Oklch,
@ -285,9 +300,19 @@ impl ColorFunction<AbsoluteColor> {
)
},
ColorFunction::Color(origin_color, r, g, b, alpha, color_space) => {
let origin_color = origin_color.map(|o| o.to_color_space(*color_space));
let origin_color = origin_color.as_ref().map(|o| {
let mut result = o.to_color_space(*color_space);
// If the origin color was a `rgb(..)` function, we should
// make sure it doesn't have the legacy flag any more so
// that it is recognized as a `color(srgb ..)` function.
result.flags.set(ColorFlags::IS_LEGACY_SRGB, false);
result
});
AbsoluteColor::new(
(*color_space).into(),
*color_space,
r.resolve(origin_color.as_ref())?.map(|c| c.to_number(1.0)),
g.resolve(origin_color.as_ref())?.map(|c| c.to_number(1.0)),
b.resolve(origin_color.as_ref())?.map(|c| c.to_number(1.0)),
@ -328,7 +353,7 @@ impl<Color> ColorFunction<Color> {
macro_rules! map {
($f:ident, $o:expr, $c0:expr, $c1:expr, $c2:expr, $alpha:expr) => {{
ColorFunction::$f(
$o.as_ref().and_then(f),
$o.as_ref().and_then(f).into(),
$c0.clone(),
$c1.clone(),
$c2.clone(),
@ -345,7 +370,7 @@ impl<Color> ColorFunction<Color> {
ColorFunction::Oklab(o, c0, c1, c2, alpha) => map!(Oklab, o, c0, c1, c2, alpha),
ColorFunction::Oklch(o, c0, c1, c2, alpha) => map!(Oklch, o, c0, c1, c2, alpha),
ColorFunction::Color(o, c0, c1, c2, alpha, color_space) => ColorFunction::Color(
o.as_ref().and_then(f),
o.as_ref().and_then(f).into(),
c0.clone(),
c1.clone(),
c2.clone(),
@ -414,7 +439,7 @@ impl<C: style_traits::ToCss> style_traits::ToCss for ColorFunction<C> {
},
};
if let Some(origin_color) = origin_color {
if let Optional::Some(origin_color) = origin_color {
dest.write_str("from ")?;
origin_color.to_css(dest)?;
dest.write_str(" ")?;

View File

@ -14,8 +14,8 @@ use crate::{
parser::ParserContext,
values::{
animated::ToAnimatedValue,
generics::calc::CalcUnits,
specified::calc::{CalcNode as SpecifiedCalcNode, Leaf as SpecifiedLeaf},
generics::calc::{CalcUnits, GenericCalcNode},
specified::calc::Leaf,
},
};
use cssparser::{color::OPAQUE, Parser, Token};
@ -23,13 +23,14 @@ use style_traits::{ParseError, StyleParseErrorKind, ToCss};
/// A single color component.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u8)]
pub enum ColorComponent<ValueType> {
/// The "none" keyword.
None,
/// A absolute value.
Value(ValueType),
/// A calc() value.
Calc(Box<SpecifiedCalcNode>),
Calc(Box<GenericCalcNode<Leaf>>),
/// Used when alpha components are not specified.
AlphaOmitted,
}
@ -59,7 +60,7 @@ pub trait ColorComponentType: Sized + Clone {
/// Try to create a new component from the given [CalcNodeLeaf] that was
/// resolved from a [CalcNode].
fn try_from_leaf(leaf: &SpecifiedLeaf) -> Result<Self, ()>;
fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()>;
}
impl<ValueType: ColorComponentType> ColorComponent<ValueType> {
@ -85,17 +86,17 @@ impl<ValueType: ColorComponentType> ColorComponent<ValueType> {
return Err(location.new_unexpected_token_error(t.clone()));
}
let node = SpecifiedCalcNode::Leaf(SpecifiedLeaf::ColorComponent(channel_keyword));
let node = GenericCalcNode::Leaf(Leaf::ColorComponent(channel_keyword));
Ok(ColorComponent::Calc(Box::new(node)))
},
Token::Function(ref name) => {
let function = SpecifiedCalcNode::math_function(context, name, location)?;
let function = GenericCalcNode::math_function(context, name, location)?;
let units = if rcs_enabled() {
ValueType::units() | CalcUnits::COLOR_COMPONENT
} else {
ValueType::units()
};
let mut node = SpecifiedCalcNode::parse(context, input, function, units)?;
let mut node = GenericCalcNode::parse(context, input, function, units)?;
if rcs_enabled() {
// Check that we only have allowed channel_keywords.
@ -103,11 +104,11 @@ impl<ValueType: ColorComponentType> ColorComponent<ValueType> {
// better, do the validation during parsing the calc node.
let mut is_valid = true;
node.visit_depth_first(|node| {
let SpecifiedCalcNode::Leaf(leaf) = node else {
let GenericCalcNode::Leaf(leaf) = node else {
return;
};
let SpecifiedLeaf::ColorComponent(channel_keyword) = leaf else {
let Leaf::ColorComponent(channel_keyword) = leaf else {
return;
};
@ -144,12 +145,12 @@ impl<ValueType: ColorComponentType> ColorComponent<ValueType> {
ColorComponent::Calc(node) => {
let Ok(resolved_leaf) = node.resolve_map(|leaf| {
Ok(match leaf {
SpecifiedLeaf::ColorComponent(channel_keyword) => {
Leaf::ColorComponent(channel_keyword) => {
if let Some(origin_color) = origin_color {
if let Ok(value) =
origin_color.get_component_by_channel_keyword(*channel_keyword)
{
SpecifiedLeaf::Number(value.unwrap_or(0.0))
Leaf::Number(value.unwrap_or(0.0))
} else {
return Err(());
}
@ -194,8 +195,7 @@ impl<ValueType: ToCss> ToCss for ColorComponent<ValueType> {
// it again here.
// There are some contradicting wpt's, which depends on resolution of:
// <https://github.com/web-platform-tests/wpt/issues/47921>
if let SpecifiedCalcNode::Leaf(SpecifiedLeaf::ColorComponent(channel_keyword)) =
node.as_ref()
if let GenericCalcNode::Leaf(Leaf::ColorComponent(channel_keyword)) = node.as_ref()
{
channel_keyword.to_css(dest)?;
} else {

View File

@ -14,11 +14,8 @@ use super::{
use crate::{
parser::{Parse, ParserContext},
values::{
generics::calc::CalcUnits,
specified::{
angle::Angle as SpecifiedAngle, calc::Leaf as SpecifiedLeaf,
color::Color as SpecifiedColor,
},
generics::{calc::CalcUnits, Optional},
specified::{angle::Angle as SpecifiedAngle, calc::Leaf, color::Color as SpecifiedColor},
},
};
use cssparser::{
@ -35,6 +32,7 @@ pub fn rcs_enabled() -> bool {
/// Represents a channel keyword inside a color.
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, PartialOrd, ToCss, ToShmem)]
#[repr(u8)]
pub enum ChannelKeyword {
/// alpha
Alpha,
@ -240,14 +238,14 @@ fn parse_rgb<'i, 't>(
let alpha = parse_legacy_alpha(context, arguments, RGB_CHANNEL_KEYWORDS)?;
ColorFunction::Rgb(origin_color, maybe_red, green, blue, alpha)
ColorFunction::Rgb(origin_color.into(), maybe_red, green, blue, alpha)
} else {
let green = parse_number_or_percentage(context, arguments, true, RGB_CHANNEL_KEYWORDS)?;
let blue = parse_number_or_percentage(context, arguments, true, RGB_CHANNEL_KEYWORDS)?;
let alpha = parse_modern_alpha(context, arguments, RGB_CHANNEL_KEYWORDS)?;
ColorFunction::Rgb(origin_color, maybe_red, green, blue, alpha)
ColorFunction::Rgb(origin_color.into(), maybe_red, green, blue, alpha)
})
}
@ -283,7 +281,7 @@ fn parse_hsl<'i, 't>(
};
Ok(ColorFunction::Hsl(
origin_color,
origin_color.into(),
hue,
saturation,
lightness,
@ -307,7 +305,7 @@ fn parse_hwb<'i, 't>(
let alpha = parse_modern_alpha(context, arguments, HWB_CHANNEL_KEYWORDS)?;
Ok(ColorFunction::Hwb(
origin_color,
origin_color.into(),
hue,
whiteness,
blackness,
@ -316,11 +314,11 @@ fn parse_hwb<'i, 't>(
}
type IntoLabFn<Output> = fn(
origin: Option<SpecifiedColor>,
l: ColorComponent<NumberOrPercentage>,
a: ColorComponent<NumberOrPercentage>,
b: ColorComponent<NumberOrPercentage>,
alpha: ColorComponent<NumberOrPercentage>,
origin: Optional<SpecifiedColor>,
l: ColorComponent<NumberOrPercentageComponent>,
a: ColorComponent<NumberOrPercentageComponent>,
b: ColorComponent<NumberOrPercentageComponent>,
alpha: ColorComponent<NumberOrPercentageComponent>,
) -> Output;
#[inline]
@ -336,15 +334,15 @@ fn parse_lab_like<'i, 't>(
let alpha = parse_modern_alpha(context, arguments, LAB_CHANNEL_KEYWORDS)?;
Ok(into_color(origin_color, lightness, a, b, alpha))
Ok(into_color(origin_color.into(), lightness, a, b, alpha))
}
type IntoLchFn<Output> = fn(
origin: Option<SpecifiedColor>,
l: ColorComponent<NumberOrPercentage>,
a: ColorComponent<NumberOrPercentage>,
b: ColorComponent<NumberOrAngle>,
alpha: ColorComponent<NumberOrPercentage>,
origin: Optional<SpecifiedColor>,
l: ColorComponent<NumberOrPercentageComponent>,
a: ColorComponent<NumberOrPercentageComponent>,
b: ColorComponent<NumberOrAngleComponent>,
alpha: ColorComponent<NumberOrPercentageComponent>,
) -> Output;
#[inline]
@ -360,7 +358,13 @@ fn parse_lch_like<'i, 't>(
let alpha = parse_modern_alpha(context, arguments, LCH_CHANNEL_KEYWORDS)?;
Ok(into_color(origin_color, lightness, chroma, hue, alpha))
Ok(into_color(
origin_color.into(),
lightness,
chroma,
hue,
alpha,
))
}
/// Parse the color() function.
@ -389,7 +393,7 @@ fn parse_color_with_color_space<'i, 't>(
let alpha = parse_modern_alpha(context, arguments, allowed_channel_keywords)?;
Ok(ColorFunction::Color(
origin_color,
origin_color.into(),
c1,
c2,
c3,
@ -400,7 +404,8 @@ fn parse_color_with_color_space<'i, 't>(
/// Either a percentage or a number.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToShmem)]
pub enum NumberOrPercentage {
#[repr(u8)]
pub enum NumberOrPercentageComponent {
/// `<number>`.
Number(f32),
/// `<percentage>`
@ -408,7 +413,7 @@ pub enum NumberOrPercentage {
Percentage(f32),
}
impl NumberOrPercentage {
impl NumberOrPercentageComponent {
/// Return the value as a number. Percentages will be adjusted to the range
/// [0..percent_basis].
pub fn to_number(&self, percentage_basis: f32) -> f32 {
@ -419,7 +424,7 @@ impl NumberOrPercentage {
}
}
impl ColorComponentType for NumberOrPercentage {
impl ColorComponentType for NumberOrPercentageComponent {
fn from_value(value: f32) -> Self {
Self::Number(value)
}
@ -438,10 +443,10 @@ impl ColorComponentType for NumberOrPercentage {
})
}
fn try_from_leaf(leaf: &SpecifiedLeaf) -> Result<Self, ()> {
fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()> {
Ok(match *leaf {
SpecifiedLeaf::Percentage(unit_value) => Self::Percentage(unit_value),
SpecifiedLeaf::Number(value) => Self::Number(value),
Leaf::Percentage(unit_value) => Self::Percentage(unit_value),
Leaf::Number(value) => Self::Number(value),
_ => return Err(()),
})
}
@ -449,7 +454,8 @@ impl ColorComponentType for NumberOrPercentage {
/// Either an angle or a number.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToShmem)]
pub enum NumberOrAngle {
#[repr(u8)]
pub enum NumberOrAngleComponent {
/// `<number>`.
Number(f32),
/// `<angle>`
@ -457,7 +463,7 @@ pub enum NumberOrAngle {
Angle(f32),
}
impl NumberOrAngle {
impl NumberOrAngleComponent {
/// Return the angle in degrees. `NumberOrAngle::Number` is returned as
/// degrees, because it is the canonical unit.
pub fn degrees(&self) -> f32 {
@ -468,7 +474,7 @@ impl NumberOrAngle {
}
}
impl ColorComponentType for NumberOrAngle {
impl ColorComponentType for NumberOrAngleComponent {
fn from_value(value: f32) -> Self {
Self::Number(value)
}
@ -487,7 +493,7 @@ impl ColorComponentType for NumberOrAngle {
SpecifiedAngle::parse_dimension(value, unit, /* from_calc = */ false)
.map(|angle| angle.degrees())?;
NumberOrAngle::Angle(degrees)
NumberOrAngleComponent::Angle(degrees)
},
_ => {
return Err(());
@ -495,10 +501,10 @@ impl ColorComponentType for NumberOrAngle {
})
}
fn try_from_leaf(leaf: &SpecifiedLeaf) -> Result<Self, ()> {
fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()> {
Ok(match *leaf {
SpecifiedLeaf::Angle(angle) => Self::Angle(angle.degrees()),
SpecifiedLeaf::Number(value) => Self::Number(value),
Leaf::Angle(angle) => Self::Angle(angle.degrees()),
Leaf::Number(value) => Self::Number(value),
_ => return Err(()),
})
}
@ -522,8 +528,8 @@ impl ColorComponentType for f32 {
}
}
fn try_from_leaf(leaf: &SpecifiedLeaf) -> Result<Self, ()> {
if let SpecifiedLeaf::Number(value) = *leaf {
fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()> {
if let Leaf::Number(value) = *leaf {
Ok(value)
} else {
Err(())
@ -537,7 +543,7 @@ fn parse_number_or_angle<'i, 't>(
input: &mut Parser<'i, 't>,
allow_none: bool,
allowed_channel_keywords: &[ChannelKeyword],
) -> Result<ColorComponent<NumberOrAngle>, ParseError<'i>> {
) -> Result<ColorComponent<NumberOrAngleComponent>, ParseError<'i>> {
ColorComponent::parse(context, input, allow_none, allowed_channel_keywords)
}
@ -547,10 +553,10 @@ fn parse_percentage<'i, 't>(
input: &mut Parser<'i, 't>,
allow_none: bool,
allowed_channel_keywords: &[ChannelKeyword],
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
) -> Result<ColorComponent<NumberOrPercentageComponent>, ParseError<'i>> {
let location = input.current_source_location();
let value = ColorComponent::<NumberOrPercentage>::parse(
let value = ColorComponent::<NumberOrPercentageComponent>::parse(
context,
input,
allow_none,
@ -570,10 +576,10 @@ fn parse_number<'i, 't>(
input: &mut Parser<'i, 't>,
allow_none: bool,
allowed_channel_keywords: &[ChannelKeyword],
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
) -> Result<ColorComponent<NumberOrPercentageComponent>, ParseError<'i>> {
let location = input.current_source_location();
let value = ColorComponent::<NumberOrPercentage>::parse(
let value = ColorComponent::<NumberOrPercentageComponent>::parse(
context,
input,
allow_none,
@ -593,7 +599,7 @@ fn parse_number_or_percentage<'i, 't>(
input: &mut Parser<'i, 't>,
allow_none: bool,
allowed_channel_keywords: &[ChannelKeyword],
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
) -> Result<ColorComponent<NumberOrPercentageComponent>, ParseError<'i>> {
ColorComponent::parse(context, input, allow_none, allowed_channel_keywords)
}
@ -601,7 +607,7 @@ fn parse_legacy_alpha<'i, 't>(
context: &ParserContext,
arguments: &mut Parser<'i, 't>,
allowed_channel_keywords: &[ChannelKeyword],
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
) -> Result<ColorComponent<NumberOrPercentageComponent>, ParseError<'i>> {
if !arguments.is_exhausted() {
arguments.expect_comma()?;
parse_number_or_percentage(context, arguments, false, allowed_channel_keywords)
@ -614,7 +620,7 @@ fn parse_modern_alpha<'i, 't>(
context: &ParserContext,
arguments: &mut Parser<'i, 't>,
allowed_channel_keywords: &[ChannelKeyword],
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
) -> Result<ColorComponent<NumberOrPercentageComponent>, ParseError<'i>> {
if !arguments.is_exhausted() {
arguments.expect_delim('/')?;
parse_number_or_percentage(context, arguments, true, allowed_channel_keywords)
@ -623,13 +629,13 @@ fn parse_modern_alpha<'i, 't>(
}
}
impl ColorComponent<NumberOrPercentage> {
impl ColorComponent<NumberOrPercentageComponent> {
/// Return true if the value contained inside is/can resolve to a percentage.
/// Also returns false if the node is invalid somehow.
fn could_be_number(&self) -> bool {
match self {
Self::None | Self::AlphaOmitted => true,
Self::Value(value) => matches!(value, NumberOrPercentage::Number { .. }),
Self::Value(value) => matches!(value, NumberOrPercentageComponent::Number { .. }),
Self::Calc(node) => {
if let Ok(unit) = node.unit() {
unit.is_empty()
@ -645,7 +651,7 @@ impl ColorComponent<NumberOrPercentage> {
fn could_be_percentage(&self) -> bool {
match self {
Self::None | Self::AlphaOmitted => true,
Self::Value(value) => matches!(value, NumberOrPercentage::Percentage { .. }),
Self::Value(value) => matches!(value, NumberOrPercentageComponent::Percentage { .. }),
Self::Calc(node) => {
if let Ok(unit) = node.unit() {
unit == CalcUnits::PERCENTAGE

View File

@ -5,7 +5,7 @@
//! Write colors into CSS strings.
use super::{
parsing::{NumberOrAngle, NumberOrPercentage},
parsing::{NumberOrAngleComponent, NumberOrPercentageComponent},
AbsoluteColor, ColorFlags, ColorSpace,
};
use crate::values::normalize;
@ -41,7 +41,7 @@ impl<'a> ToCss for ModernComponent<'a> {
}
}
impl ToCss for NumberOrPercentage {
impl ToCss for NumberOrPercentageComponent {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
@ -56,7 +56,7 @@ impl ToCss for NumberOrPercentage {
}
}
impl ToCss for NumberOrAngle {
impl ToCss for NumberOrAngleComponent {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,

View File

@ -72,6 +72,7 @@ pub enum MathFunction {
/// A leaf node inside a `Calc` expression's AST.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u8)]
pub enum Leaf {
/// `<length>`
Length(NoCalcLength),

View File

@ -51,6 +51,7 @@ pub const PX_PER_PC: CSSFloat = PX_PER_PT * 12.;
/// added here, `custom_properties::NonCustomReferences::from_unit`
/// must also be updated. Consult the comment in that function as to why.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[repr(u8)]
pub enum FontRelativeLength {
/// A "em" value: https://drafts.csswg.org/css-values/#em
#[css(dimension)]
@ -458,6 +459,7 @@ enum ViewportUnit {
///
/// <https://drafts.csswg.org/css-values/#viewport-relative-lengths>
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[repr(u8)]
pub enum ViewportPercentageLength {
/// <https://drafts.csswg.org/css-values/#valdef-length-vw>
#[css(dimension)]
@ -713,6 +715,7 @@ impl ViewportPercentageLength {
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[repr(C)]
pub struct CharacterWidth(pub i32);
impl CharacterWidth {
@ -730,6 +733,7 @@ impl CharacterWidth {
/// Represents an absolute length with its unit
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[repr(u8)]
pub enum AbsoluteLength {
/// An absolute length in pixels (px)
#[css(dimension)]
@ -831,6 +835,7 @@ impl PartialOrd for AbsoluteLength {
///
/// <https://drafts.csswg.org/css-contain-3/#container-lengths>
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[repr(u8)]
pub enum ContainerRelativeLength {
/// 1% of query container's width
#[css(dimension)]
@ -958,6 +963,7 @@ impl ContainerRelativeLength {
///
/// <https://drafts.csswg.org/css-values/#lengths>
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)]
#[repr(u8)]
pub enum NoCalcLength {
/// An absolute length
///
@ -2014,7 +2020,8 @@ impl Size {
parse_size_non_length!(Size, input, "auto" => Auto);
parse_fit_content_function!(Size, input, context, allow_quirks);
if let Ok(length) = input.try_parse(|i| NonNegativeLengthPercentage::parse_quirky(context, i, allow_quirks)) {
if let Ok(length) =
input.try_parse(|i| NonNegativeLengthPercentage::parse_quirky(context, i, allow_quirks)) {
return Ok(GenericSize::LengthPercentage(length));
}
Ok(Self::AnchorSizeFunction(Box::new(GenericAnchorSizeFunction::parse(context, input)?)))
@ -2049,10 +2056,14 @@ impl MaxSize {
parse_size_non_length!(MaxSize, input, "none" => None);
parse_fit_content_function!(MaxSize, input, context, allow_quirks);
if let Ok(length) = input.try_parse(|i| NonNegativeLengthPercentage::parse_quirky(context, i, allow_quirks)) {
if let Ok(length) =
input.try_parse(|i| NonNegativeLengthPercentage::parse_quirky(context, i, allow_quirks))
{
return Ok(GenericMaxSize::LengthPercentage(length));
}
Ok(Self::AnchorSizeFunction(Box::new(GenericAnchorSizeFunction::parse(context, input)?)))
Ok(Self::AnchorSizeFunction(Box::new(
GenericAnchorSizeFunction::parse(context, input)?,
)))
}
}

View File

@ -84,7 +84,6 @@ exclude = [
"NS_LogDtor",
"SelectorList",
"AuthorStyles",
"ColorFunction",
]
include = [
"AnchorName",