mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
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:
parent
96526acd5c
commit
fbd6dd0fce
@ -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" },
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(" ")?;
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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)?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,6 @@ exclude = [
|
||||
"NS_LogDtor",
|
||||
"SelectorList",
|
||||
"AuthorStyles",
|
||||
"ColorFunction",
|
||||
]
|
||||
include = [
|
||||
"AnchorName",
|
||||
|
Loading…
Reference in New Issue
Block a user