Bug 1886170 - Change Color Parser trait into a concrete type r=layout-reviewers,emilio

The ColorParser trait only has one implementation so we can make it a
concrete type now.  It will be extended in the future.

Differential Revision: https://phabricator.services.mozilla.com/D207009
This commit is contained in:
Tiaan Louw 2024-04-09 14:00:02 +00:00
Родитель e92422d5f8
Коммит 4884a8c671
2 изменённых файлов: 112 добавлений и 158 удалений

Просмотреть файл

@ -13,10 +13,14 @@ use super::{
component::{ColorComponent, ColorComponentType},
AbsoluteColor,
};
use crate::values::{
generics::calc::CalcUnits,
specified::{
angle::Angle as SpecifiedAngle, calc::Leaf as SpecifiedLeaf, color::Color as SpecifiedColor,
use crate::{
parser::ParserContext,
values::{
generics::calc::CalcUnits,
specified::{
angle::Angle as SpecifiedAngle, calc::Leaf as SpecifiedLeaf,
color::Color as SpecifiedColor,
},
},
};
use cssparser::{
@ -60,13 +64,10 @@ pub fn parse_color_keyword(ident: &str) -> Result<SpecifiedColor, ()> {
/// Parse a CSS color using the specified [`ColorParser`] and return a new color
/// value on success.
pub fn parse_color_with<'i, 't, P>(
color_parser: &P,
pub fn parse_color_with<'i, 't>(
color_parser: &ColorParser<'_, '_>,
input: &mut Parser<'i, 't>,
) -> Result<SpecifiedColor, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<SpecifiedColor, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
match *token {
@ -90,14 +91,11 @@ where
/// Parse one of the color functions: rgba(), lab(), color(), etc.
#[inline]
fn parse_color_function<'i, 't, P>(
color_parser: &P,
fn parse_color_function<'i, 't>(
color_parser: &ColorParser<'_, '_>,
name: CowRcStr<'i>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let color = match_ignore_ascii_case! { &name,
"rgb" | "rgba" => parse_rgb(color_parser, arguments),
"hsl" | "hsla" => parse_hsl(color_parser, arguments),
@ -115,13 +113,10 @@ where
Ok(color)
}
fn parse_legacy_alpha<'i, 't, P>(
color_parser: &P,
fn parse_legacy_alpha<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
if !arguments.is_exhausted() {
arguments.expect_comma()?;
color_parser.parse_number_or_percentage(arguments, false)
@ -132,13 +127,10 @@ where
}
}
fn parse_modern_alpha<'i, 't, P>(
color_parser: &P,
fn parse_modern_alpha<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
if !arguments.is_exhausted() {
arguments.expect_delim('/')?;
color_parser.parse_number_or_percentage(arguments, true)
@ -160,13 +152,10 @@ impl ColorComponent<NumberOrPercentage> {
}
/// Parse the relative color syntax "from" syntax `from <color>`.
fn parse_origin_color<'i, 't, P>(
color_parser: &P,
fn parse_origin_color<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<Option<SpecifiedColor>, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<Option<SpecifiedColor>, ParseError<'i>> {
if !rcs_enabled() {
return Ok(None);
}
@ -185,13 +174,10 @@ where
}
#[inline]
fn parse_rgb<'i, 't, P>(
color_parser: &P,
fn parse_rgb<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let origin_color = parse_origin_color(color_parser, arguments)?;
let location = arguments.current_source_location();
@ -255,13 +241,10 @@ where
///
/// <https://drafts.csswg.org/css-color/#the-hsl-notation>
#[inline]
fn parse_hsl<'i, 't, P>(
color_parser: &P,
fn parse_hsl<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let origin_color = parse_origin_color(color_parser, arguments)?;
let hue = color_parser.parse_number_or_angle(arguments, true)?;
@ -302,21 +285,18 @@ where
///
/// <https://drafts.csswg.org/css-color/#the-hbw-notation>
#[inline]
fn parse_hwb<'i, 't, P>(
color_parser: &P,
fn parse_hwb<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let _origin_color = parse_origin_color(color_parser, arguments)?;
let (hue, whiteness, blackness, alpha) = parse_components(
color_parser,
arguments,
P::parse_number_or_angle,
P::parse_number_or_percentage,
P::parse_number_or_percentage,
ColorParser::parse_number_or_angle,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
)?;
Ok(ColorFunction::Hwb(hue, whiteness, blackness, alpha))
@ -330,22 +310,19 @@ type IntoLabFn<Output> = fn(
) -> Output;
#[inline]
fn parse_lab_like<'i, 't, P>(
color_parser: &P,
fn parse_lab_like<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
into_color: IntoLabFn<ColorFunction>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let _origin_color = parse_origin_color(color_parser, arguments)?;
let (lightness, a, b, alpha) = parse_components(
color_parser,
arguments,
P::parse_number_or_percentage,
P::parse_number_or_percentage,
P::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
)?;
Ok(into_color(lightness, a, b, alpha))
@ -359,22 +336,19 @@ type IntoLchFn<Output> = fn(
) -> Output;
#[inline]
fn parse_lch_like<'i, 't, P>(
color_parser: &P,
fn parse_lch_like<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
into_color: IntoLchFn<ColorFunction>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let _origin_color = parse_origin_color(color_parser, arguments)?;
let (lightness, chroma, hue, alpha) = parse_components(
color_parser,
arguments,
P::parse_number_or_percentage,
P::parse_number_or_percentage,
P::parse_number_or_angle,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_angle,
)?;
Ok(into_color(lightness, chroma, hue, alpha))
@ -382,13 +356,10 @@ where
/// Parse the color() function.
#[inline]
fn parse_color_with_color_space<'i, 't, P>(
color_parser: &P,
fn parse_color_with_color_space<'i, 't>(
color_parser: &ColorParser<'_, '_>,
arguments: &mut Parser<'i, 't>,
) -> Result<ColorFunction, ParseError<'i>>
where
P: ColorParser<'i>,
{
) -> Result<ColorFunction, ParseError<'i>> {
let _origin_color = parse_origin_color(color_parser, arguments)?;
let color_space = {
@ -402,9 +373,9 @@ where
let (c1, c2, c3, alpha) = parse_components(
color_parser,
arguments,
P::parse_number_or_percentage,
P::parse_number_or_percentage,
P::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
ColorParser::parse_number_or_percentage,
)?;
Ok(ColorFunction::Color(color_space, c1, c2, c3, alpha))
@ -421,18 +392,29 @@ type ComponentParseResult<'i, R1, R2, R3> = Result<
>;
/// Parse the color components and alpha with the modern [color-4] syntax.
pub fn parse_components<'i, 't, P, F1, F2, F3, R1, R2, R3>(
color_parser: &P,
pub fn parse_components<'a, 'b: 'a, 'i, 't, F1, F2, F3, R1, R2, R3>(
color_parser: &ColorParser<'a, 'b>,
input: &mut Parser<'i, 't>,
f1: F1,
f2: F2,
f3: F3,
) -> ComponentParseResult<'i, R1, R2, R3>
where
P: ColorParser<'i>,
F1: FnOnce(&P, &mut Parser<'i, 't>, bool) -> Result<ColorComponent<R1>, ParseError<'i>>,
F2: FnOnce(&P, &mut Parser<'i, 't>, bool) -> Result<ColorComponent<R2>, ParseError<'i>>,
F3: FnOnce(&P, &mut Parser<'i, 't>, bool) -> Result<ColorComponent<R3>, ParseError<'i>>,
F1: FnOnce(
&ColorParser<'a, 'b>,
&mut Parser<'i, 't>,
bool,
) -> Result<ColorComponent<R1>, ParseError<'i>>,
F2: FnOnce(
&ColorParser<'a, 'b>,
&mut Parser<'i, 't>,
bool,
) -> Result<ColorComponent<R2>, ParseError<'i>>,
F3: FnOnce(
&ColorParser<'a, 'b>,
&mut Parser<'i, 't>,
bool,
) -> Result<ColorComponent<R3>, ParseError<'i>>,
{
let r1 = f1(color_parser, input, true)?;
let r2 = f2(color_parser, input, true)?;
@ -577,42 +559,61 @@ impl ColorComponentType for f32 {
}
}
/// A trait that can be used to hook into how `cssparser` parses color
/// components, with the intention of implementing more complicated behavior.
///
/// For example, this is used by Servo to support calc() in color.
pub trait ColorParser<'i> {
/// Parse an `<angle>` or `<number>`.
///
/// Returns the result in degrees.
fn parse_number_or_angle<'t>(
/// Used to parse the components of a color.
pub struct ColorParser<'a, 'b: 'a> {
/// Parser context used for parsing the colors.
pub context: &'a ParserContext<'b>,
}
impl<'a, 'b: 'a> ColorParser<'a, 'b> {
/// Parse an `<number>` or `<angle>` value.
fn parse_number_or_angle<'i, 't>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<NumberOrAngle>, ParseError<'i>>;
) -> Result<ColorComponent<NumberOrAngle>, ParseError<'i>> {
ColorComponent::parse(self.context, input, allow_none)
}
/// Parse a `<percentage>` value.
///
/// Returns the result in a number from 0.0 to 1.0.
fn parse_percentage<'t>(
fn parse_percentage<'i, 't>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<f32>, ParseError<'i>>;
) -> Result<ColorComponent<f32>, ParseError<'i>> {
let location = input.current_source_location();
// We can use the [NumberOrPercentage] type here, because parsing it
// doesn't have any more overhead than just parsing a percentage on its
// own.
Ok(
match ColorComponent::<NumberOrPercentage>::parse(self.context, input, allow_none)? {
ColorComponent::None => ColorComponent::None,
ColorComponent::Value(NumberOrPercentage::Percentage { unit_value }) => {
ColorComponent::Value(unit_value)
},
_ => return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
},
)
}
/// Parse a `<number>` value.
fn parse_number<'t>(
fn parse_number<'i, 't>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<f32>, ParseError<'i>>;
) -> Result<ColorComponent<f32>, ParseError<'i>> {
ColorComponent::parse(self.context, input, allow_none)
}
/// Parse a `<number>` value or a `<percentage>` value.
fn parse_number_or_percentage<'t>(
/// Parse a `<number>` or `<percentage>` value.
fn parse_number_or_percentage<'i, 't>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>>;
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
ColorComponent::parse(self.context, input, allow_none)
}
}
/// This trait is used by the [`ColorParser`] to construct colors of any type.

Просмотреть файл

@ -7,7 +7,9 @@
use super::AllowQuirks;
use crate::color::component::ColorComponent;
use crate::color::convert::normalize_hue;
use crate::color::parsing::{self, FromParsedColor, NumberOrAngle, NumberOrPercentage};
use crate::color::parsing::{
self, ColorParser, FromParsedColor, NumberOrAngle, NumberOrPercentage,
};
use crate::color::{mix::ColorInterpolationMethod, AbsoluteColor, ColorSpace};
use crate::media_queries::Device;
use crate::parser::{Parse, ParserContext};
@ -620,55 +622,6 @@ impl FromParsedColor for Color {
}
}
struct ColorParser<'a, 'b: 'a>(&'a ParserContext<'b>);
impl<'a, 'b: 'a, 'i: 'a> parsing::ColorParser<'i> for ColorParser<'a, 'b> {
fn parse_number_or_angle<'t>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<NumberOrAngle>, ParseError<'i>> {
ColorComponent::parse(self.0, input, allow_none)
}
fn parse_percentage<'t>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<f32>, ParseError<'i>> {
let location = input.current_source_location();
// We can use the [NumberOrPercentage] type here, because parsing it
// doesn't have any more overhead than just parsing a percentage on its
// own.
Ok(
match ColorComponent::<NumberOrPercentage>::parse(self.0, input, allow_none)? {
ColorComponent::None => ColorComponent::None,
ColorComponent::Value(NumberOrPercentage::Percentage { unit_value }) => {
ColorComponent::Value(unit_value)
},
_ => return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
},
)
}
fn parse_number<'t>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<f32>, ParseError<'i>> {
ColorComponent::parse(self.0, input, allow_none)
}
fn parse_number_or_percentage<'t>(
&self,
input: &mut Parser<'i, 't>,
allow_none: bool,
) -> Result<ColorComponent<NumberOrPercentage>, ParseError<'i>> {
ColorComponent::parse(self.0, input, allow_none)
}
}
/// Whether to preserve authored colors during parsing. That's useful only if we
/// plan to serialize the color back.
#[derive(Copy, Clone)]
@ -705,7 +658,7 @@ impl Color {
},
};
let color_parser = ColorParser(&*context);
let color_parser = ColorParser { context: &context };
match input.try_parse(|i| parsing::parse_color_with(&color_parser, i)) {
Ok(mut color) => {
if let Color::Absolute(ref mut absolute) = color {