Bug 1882754 - Clean up and simplify the color ToCss implementations. r=layout-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D203118
This commit is contained in:
Tiaan Louw 2024-02-29 16:37:17 +00:00
Родитель 599f3538c7
Коммит 2b84327e28
1 изменённых файлов: 41 добавлений и 279 удалений

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

@ -38,26 +38,6 @@ impl<'a> ToCss for ModernComponent<'a> {
}
}
impl ToCss for ColorFunction {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
dest.write_str("color(")?;
self.color_space.to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c1).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c2).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c3).to_css(dest)?;
serialize_color_alpha(dest, self.alpha, false)?;
dest.write_char(')')
}
}
impl ToCss for AbsoluteColor {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@ -66,22 +46,37 @@ impl ToCss for AbsoluteColor {
match self.color_space {
ColorSpace::Srgb if self.flags.contains(ColorFlags::IS_LEGACY_SRGB) => {
// The "none" keyword is not supported in the rgb/rgba legacy syntax.
RgbaLegacy::from_floats(
self.components.0,
self.components.1,
self.components.2,
self.alpha,
)
.to_css(dest)
let has_alpha = self.alpha != OPAQUE;
dest.write_str(if has_alpha { "rgba(" } else { "rgb(" })?;
clamp_unit_f32(self.components.0).to_css(dest)?;
dest.write_str(", ")?;
clamp_unit_f32(self.components.1).to_css(dest)?;
dest.write_str(", ")?;
clamp_unit_f32(self.components.2).to_css(dest)?;
// Legacy syntax does not allow none components.
serialize_color_alpha(dest, Some(self.alpha), true)?;
dest.write_char(')')
},
ColorSpace::Hsl | ColorSpace::Hwb => self.into_srgb_legacy().to_css(dest),
ColorSpace::Lab => Lab::new(self.c0(), self.c1(), self.c2(), self.alpha()).to_css(dest),
ColorSpace::Lch => Lch::new(self.c0(), self.c1(), self.c2(), self.alpha()).to_css(dest),
ColorSpace::Oklab => {
Oklab::new(self.c0(), self.c1(), self.c2(), self.alpha()).to_css(dest)
},
ColorSpace::Oklch => {
Oklch::new(self.c0(), self.c1(), self.c2(), self.alpha()).to_css(dest)
ColorSpace::Oklab | ColorSpace::Lab | ColorSpace::Oklch | ColorSpace::Lch => {
if let ColorSpace::Oklab | ColorSpace::Oklch = self.color_space {
dest.write_str("ok")?;
}
if let ColorSpace::Oklab | ColorSpace::Lab = self.color_space {
dest.write_str("lab(")?;
} else {
dest.write_str("lch(")?;
}
ModernComponent(&self.c0()).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c1()).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c2()).to_css(dest)?;
serialize_color_alpha(dest, self.alpha(), false)?;
dest.write_char(')')
},
_ => {
#[cfg(debug_assertions)]
@ -91,7 +86,6 @@ impl ToCss for AbsoluteColor {
!self.flags.contains(ColorFlags::IS_LEGACY_SRGB),
"legacy srgb is not a color function"
);
PredefinedColorSpace::Srgb
},
ColorSpace::SrgbLinear |
ColorSpace::DisplayP3 |
@ -107,14 +101,18 @@ impl ToCss for AbsoluteColor {
},
};
let color_function = ColorFunction::new(
self.color_space,
self.c0(),
self.c1(),
self.c2(),
self.alpha(),
);
color_function.to_css(dest)
dest.write_str("color(")?;
self.color_space.to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c0()).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c1()).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.c2()).to_css(dest)?;
serialize_color_alpha(dest, self.alpha(), false)?;
dest.write_char(')')
},
}
}
@ -251,239 +249,3 @@ impl AbsoluteColor {
}
}
}
/// A color with red, green, blue, and alpha components, in a byte each.
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct RgbaLegacy {
/// The red component.
pub red: u8,
/// The green component.
pub green: u8,
/// The blue component.
pub blue: u8,
/// The alpha component.
pub alpha: f32,
}
impl RgbaLegacy {
/// Constructs a new RGBA value from float components. It expects the red,
/// green, blue and alpha channels in that order, and all values will be
/// clamped to the 0.0 ... 1.0 range.
#[inline]
pub fn from_floats(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
Self::new(
clamp_unit_f32(red),
clamp_unit_f32(green),
clamp_unit_f32(blue),
alpha.clamp(0.0, OPAQUE),
)
}
/// Same thing, but with `u8` values instead of floats in the 0 to 1 range.
#[inline]
pub const fn new(red: u8, green: u8, blue: u8, alpha: f32) -> Self {
Self {
red,
green,
blue,
alpha,
}
}
}
impl ToCss for RgbaLegacy {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
let has_alpha = self.alpha != OPAQUE;
dest.write_str(if has_alpha { "rgba(" } else { "rgb(" })?;
self.red.to_css(dest)?;
dest.write_str(", ")?;
self.green.to_css(dest)?;
dest.write_str(", ")?;
self.blue.to_css(dest)?;
// Legacy syntax does not allow none components.
serialize_color_alpha(dest, Some(self.alpha), true)?;
dest.write_char(')')
}
}
// NOTE: LAB and OKLAB is not declared inside the [impl_lab_like] macro,
// because it causes cbindgen to ignore them.
/// Color specified by lightness, a- and b-axis components.
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Lab {
/// The lightness component.
pub lightness: Option<f32>,
/// The a-axis component.
pub a: Option<f32>,
/// The b-axis component.
pub b: Option<f32>,
/// The alpha component.
pub alpha: Option<f32>,
}
/// Color specified by lightness, a- and b-axis components.
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Oklab {
/// The lightness component.
pub lightness: Option<f32>,
/// The a-axis component.
pub a: Option<f32>,
/// The b-axis component.
pub b: Option<f32>,
/// The alpha component.
pub alpha: Option<f32>,
}
macro_rules! impl_lab_like {
($cls:ident, $fname:literal) => {
impl $cls {
/// Construct a new Lab color format with lightness, a, b and alpha components.
pub fn new(
lightness: Option<f32>,
a: Option<f32>,
b: Option<f32>,
alpha: Option<f32>,
) -> Self {
Self {
lightness,
a,
b,
alpha,
}
}
}
impl ToCss for $cls {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
dest.write_str($fname)?;
dest.write_str("(")?;
ModernComponent(&self.lightness).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.a).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.b).to_css(dest)?;
serialize_color_alpha(dest, self.alpha, false)?;
dest.write_char(')')
}
}
};
}
impl_lab_like!(Lab, "lab");
impl_lab_like!(Oklab, "oklab");
// NOTE: LCH and OKLCH is not declared inside the [impl_lch_like] macro,
// because it causes cbindgen to ignore them.
/// Color specified by lightness, chroma and hue components.
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Lch {
/// The lightness component.
pub lightness: Option<f32>,
/// The chroma component.
pub chroma: Option<f32>,
/// The hue component.
pub hue: Option<f32>,
/// The alpha component.
pub alpha: Option<f32>,
}
/// Color specified by lightness, chroma and hue components.
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Oklch {
/// The lightness component.
pub lightness: Option<f32>,
/// The chroma component.
pub chroma: Option<f32>,
/// The hue component.
pub hue: Option<f32>,
/// The alpha component.
pub alpha: Option<f32>,
}
macro_rules! impl_lch_like {
($cls:ident, $fname:literal) => {
impl $cls {
/// Construct a new color with lightness, chroma and hue components.
pub fn new(
lightness: Option<f32>,
chroma: Option<f32>,
hue: Option<f32>,
alpha: Option<f32>,
) -> Self {
Self {
lightness,
chroma,
hue,
alpha,
}
}
}
impl ToCss for $cls {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
dest.write_str($fname)?;
dest.write_str("(")?;
ModernComponent(&self.lightness).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.chroma).to_css(dest)?;
dest.write_char(' ')?;
ModernComponent(&self.hue).to_css(dest)?;
serialize_color_alpha(dest, self.alpha, false)?;
dest.write_char(')')
}
}
};
}
impl_lch_like!(Lch, "lch");
impl_lch_like!(Oklch, "oklch");
/// A color specified by the color() function.
/// <https://drafts.csswg.org/css-color-4/#color-function>
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct ColorFunction {
/// The color space for this color.
pub color_space: ColorSpace,
/// The first component of the color. Either red or x.
pub c1: Option<f32>,
/// The second component of the color. Either green or y.
pub c2: Option<f32>,
/// The third component of the color. Either blue or z.
pub c3: Option<f32>,
/// The alpha component of the color.
pub alpha: Option<f32>,
}
impl ColorFunction {
/// Construct a new color function definition with the given color space and
/// color components.
pub fn new(
color_space: ColorSpace,
c1: Option<f32>,
c2: Option<f32>,
c3: Option<f32>,
alpha: Option<f32>,
) -> Self {
Self {
color_space,
c1,
c2,
c3,
alpha,
}
}
}