mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1822041 - Color interpolation takes none keyword into account r=emilio,layout-reviewers
Now that the none keyword is available, we can take it into account when interpolating colors following the rules from the spec here: https://drafts.csswg.org/css-color-4/#interpolation-missing Differential Revision: https://phabricator.services.mozilla.com/D172666
This commit is contained in:
parent
9d5cddea34
commit
03828b4c67
@ -25,7 +25,7 @@ inline StyleAbsoluteColor StyleAbsoluteColor::FromColor(nscolor aColor) {
|
|||||||
inline StyleAbsoluteColor StyleAbsoluteColor::Srgb(float red, float green,
|
inline StyleAbsoluteColor StyleAbsoluteColor::Srgb(float red, float green,
|
||||||
float blue, float alpha) {
|
float blue, float alpha) {
|
||||||
return StyleAbsoluteColor{StyleColorComponents{red, green, blue}, alpha,
|
return StyleAbsoluteColor{StyleColorComponents{red, green, blue}, alpha,
|
||||||
StyleColorSpace::Srgb, StyleSerializationFlags{0}};
|
StyleColorSpace::Srgb, StyleColorFlags{0}};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StyleAbsoluteColor StyleAbsoluteColor::Transparent() {
|
inline StyleAbsoluteColor StyleAbsoluteColor::Transparent() {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
//! Color mixing/interpolation.
|
//! Color mixing/interpolation.
|
||||||
|
|
||||||
use super::{AbsoluteColor, ColorComponents, ColorSpace};
|
use super::{AbsoluteColor, ColorComponents, ColorFlags, ColorSpace};
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
@ -135,24 +135,6 @@ impl ToCss for ColorInterpolationMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A color modelled in a specific color space (such as sRGB or CIE XYZ).
|
|
||||||
///
|
|
||||||
/// For now, colors modelled in other spaces need to be convertible to and from
|
|
||||||
/// `RGBA` because we use sRGB for displaying colors.
|
|
||||||
trait ModelledColor: Clone + Copy {
|
|
||||||
/// Linearly interpolate between the left and right colors.
|
|
||||||
///
|
|
||||||
/// The HueInterpolationMethod parameter is only for color spaces where the hue is
|
|
||||||
/// represented as an angle (e.g., CIE LCH).
|
|
||||||
fn lerp(
|
|
||||||
left_bg: &Self,
|
|
||||||
left_weight: f32,
|
|
||||||
right_bg: &Self,
|
|
||||||
right_weight: f32,
|
|
||||||
hue_interpolation: HueInterpolationMethod,
|
|
||||||
) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mix two colors into one.
|
/// Mix two colors into one.
|
||||||
pub fn mix(
|
pub fn mix(
|
||||||
interpolation: ColorInterpolationMethod,
|
interpolation: ColorInterpolationMethod,
|
||||||
@ -187,6 +169,38 @@ pub fn mix(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// What the outcome of each component should be in a mix result.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
#[repr(u8)]
|
||||||
|
enum ComponentMixOutcome {
|
||||||
|
/// Mix the left and right sides to give the result.
|
||||||
|
Mix,
|
||||||
|
/// Carry the left side forward to the result.
|
||||||
|
UseLeft,
|
||||||
|
/// Carry the right side forward to the result.
|
||||||
|
UseRight,
|
||||||
|
/// The resulting component should also be none.
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentMixOutcome {
|
||||||
|
fn from_colors(
|
||||||
|
left: &AbsoluteColor,
|
||||||
|
right: &AbsoluteColor,
|
||||||
|
flags_to_check: ColorFlags,
|
||||||
|
) -> Self {
|
||||||
|
match (
|
||||||
|
left.flags.contains(flags_to_check),
|
||||||
|
right.flags.contains(flags_to_check),
|
||||||
|
) {
|
||||||
|
(true, true) => Self::None,
|
||||||
|
(true, false) => Self::UseRight,
|
||||||
|
(false, true) => Self::UseLeft,
|
||||||
|
(false, false) => Self::Mix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn mix_in(
|
fn mix_in(
|
||||||
color_space: ColorSpace,
|
color_space: ColorSpace,
|
||||||
left_color: &AbsoluteColor,
|
left_color: &AbsoluteColor,
|
||||||
@ -196,6 +210,13 @@ fn mix_in(
|
|||||||
hue_interpolation: HueInterpolationMethod,
|
hue_interpolation: HueInterpolationMethod,
|
||||||
alpha_multiplier: f32,
|
alpha_multiplier: f32,
|
||||||
) -> AbsoluteColor {
|
) -> AbsoluteColor {
|
||||||
|
let outcomes = [
|
||||||
|
ComponentMixOutcome::from_colors(left_color, right_color, ColorFlags::C1_IS_NONE),
|
||||||
|
ComponentMixOutcome::from_colors(left_color, right_color, ColorFlags::C2_IS_NONE),
|
||||||
|
ComponentMixOutcome::from_colors(left_color, right_color, ColorFlags::C3_IS_NONE),
|
||||||
|
ComponentMixOutcome::from_colors(left_color, right_color, ColorFlags::ALPHA_IS_NONE),
|
||||||
|
];
|
||||||
|
|
||||||
// Convert both colors into the interpolation color space.
|
// Convert both colors into the interpolation color space.
|
||||||
let left = left_color.to_color_space(color_space);
|
let left = left_color.to_color_space(color_space);
|
||||||
let left = left.raw_components();
|
let left = left.raw_components();
|
||||||
@ -203,13 +224,14 @@ fn mix_in(
|
|||||||
let right = right_color.to_color_space(color_space);
|
let right = right_color.to_color_space(color_space);
|
||||||
let right = right.raw_components();
|
let right = right.raw_components();
|
||||||
|
|
||||||
let result = interpolate_premultiplied(
|
let (result, result_flags) = interpolate_premultiplied(
|
||||||
&left,
|
&left,
|
||||||
left_weight,
|
left_weight,
|
||||||
&right,
|
&right,
|
||||||
right_weight,
|
right_weight,
|
||||||
color_space.hue_index(),
|
color_space.hue_index(),
|
||||||
hue_interpolation,
|
hue_interpolation,
|
||||||
|
&outcomes,
|
||||||
);
|
);
|
||||||
|
|
||||||
let alpha = if alpha_multiplier != 1.0 {
|
let alpha = if alpha_multiplier != 1.0 {
|
||||||
@ -225,11 +247,19 @@ fn mix_in(
|
|||||||
// then divide after calculations?
|
// then divide after calculations?
|
||||||
let alpha = (alpha * 1000.0).round() / 1000.0;
|
let alpha = (alpha * 1000.0).round() / 1000.0;
|
||||||
|
|
||||||
AbsoluteColor::new(
|
let mut result = AbsoluteColor::new(
|
||||||
color_space,
|
color_space,
|
||||||
ColorComponents(result[0], result[1], result[2]),
|
ColorComponents(result[0], result[1], result[2]),
|
||||||
alpha,
|
alpha,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
result.flags = result_flags;
|
||||||
|
// If both sides are legacy RGB, then the result stays in legacy RGB.
|
||||||
|
if !left_color.is_legacy_color() || !right_color.is_legacy_color() {
|
||||||
|
result.flags.insert(ColorFlags::AS_COLOR_FUNCTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interpolate_premultiplied_component(
|
fn interpolate_premultiplied_component(
|
||||||
@ -239,9 +269,8 @@ fn interpolate_premultiplied_component(
|
|||||||
right: f32,
|
right: f32,
|
||||||
right_weight: f32,
|
right_weight: f32,
|
||||||
right_alpha: f32,
|
right_alpha: f32,
|
||||||
inverse_of_result_alpha: f32,
|
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
(left * left_weight * left_alpha + right * right_weight * right_alpha) * inverse_of_result_alpha
|
left * left_weight * left_alpha + right * right_weight * right_alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize hue into [0, 360)
|
// Normalize hue into [0, 360)
|
||||||
@ -323,6 +352,63 @@ fn interpolate_hue(
|
|||||||
left * left_weight + right * right_weight
|
left * left_weight + right * right_weight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InterpolatedAlpha {
|
||||||
|
/// The adjusted left alpha value.
|
||||||
|
left: f32,
|
||||||
|
/// The adjusted right alpha value.
|
||||||
|
right: f32,
|
||||||
|
/// The interpolated alpha value.
|
||||||
|
interpolated: f32,
|
||||||
|
/// Whether the alpha component should be `none`.
|
||||||
|
is_none: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interpolate_alpha(
|
||||||
|
left: f32,
|
||||||
|
left_weight: f32,
|
||||||
|
right: f32,
|
||||||
|
right_weight: f32,
|
||||||
|
outcome: ComponentMixOutcome,
|
||||||
|
) -> InterpolatedAlpha {
|
||||||
|
// <https://drafts.csswg.org/css-color-4/#interpolation-missing>
|
||||||
|
let mut result = match outcome {
|
||||||
|
ComponentMixOutcome::Mix => {
|
||||||
|
let interpolated = left * left_weight + right * right_weight;
|
||||||
|
InterpolatedAlpha {
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
interpolated,
|
||||||
|
is_none: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ComponentMixOutcome::UseLeft => InterpolatedAlpha {
|
||||||
|
left,
|
||||||
|
right: left,
|
||||||
|
interpolated: left,
|
||||||
|
is_none: false,
|
||||||
|
},
|
||||||
|
ComponentMixOutcome::UseRight => InterpolatedAlpha {
|
||||||
|
left: right,
|
||||||
|
right,
|
||||||
|
interpolated: right,
|
||||||
|
is_none: false,
|
||||||
|
},
|
||||||
|
ComponentMixOutcome::None => InterpolatedAlpha {
|
||||||
|
left: 1.0,
|
||||||
|
right: 1.0,
|
||||||
|
interpolated: 0.0,
|
||||||
|
is_none: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clip all alpha values to [0.0..1.0].
|
||||||
|
result.left = result.left.clamp(0.0, 1.0);
|
||||||
|
result.right = result.right.clamp(0.0, 1.0);
|
||||||
|
result.interpolated = result.interpolated.clamp(0.0, 1.0);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
fn interpolate_premultiplied(
|
fn interpolate_premultiplied(
|
||||||
left: &[f32; 4],
|
left: &[f32; 4],
|
||||||
left_weight: f32,
|
left_weight: f32,
|
||||||
@ -330,39 +416,60 @@ fn interpolate_premultiplied(
|
|||||||
right_weight: f32,
|
right_weight: f32,
|
||||||
hue_index: Option<usize>,
|
hue_index: Option<usize>,
|
||||||
hue_interpolation: HueInterpolationMethod,
|
hue_interpolation: HueInterpolationMethod,
|
||||||
) -> [f32; 4] {
|
outcomes: &[ComponentMixOutcome; 4],
|
||||||
let left_alpha = left[3];
|
) -> ([f32; 4], ColorFlags) {
|
||||||
let right_alpha = right[3];
|
let alpha = interpolate_alpha(left[3], left_weight, right[3], right_weight, outcomes[3]);
|
||||||
let result_alpha = (left_alpha * left_weight + right_alpha * right_weight).min(1.);
|
let mut flags = if alpha.is_none {
|
||||||
|
ColorFlags::ALPHA_IS_NONE
|
||||||
|
} else {
|
||||||
|
ColorFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
let mut result = [0.; 4];
|
let mut result = [0.; 4];
|
||||||
if result_alpha <= 0. {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inverse_of_result_alpha = 1. / result_alpha;
|
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
let is_hue = hue_index == Some(i);
|
match outcomes[i] {
|
||||||
result[i] = if is_hue {
|
ComponentMixOutcome::Mix => {
|
||||||
interpolate_hue(
|
let is_hue = hue_index == Some(i);
|
||||||
left[i],
|
result[i] = if is_hue {
|
||||||
left_weight,
|
normalize_hue(interpolate_hue(
|
||||||
right[i],
|
left[i],
|
||||||
right_weight,
|
left_weight,
|
||||||
hue_interpolation,
|
right[i],
|
||||||
)
|
right_weight,
|
||||||
} else {
|
hue_interpolation,
|
||||||
interpolate_premultiplied_component(
|
))
|
||||||
left[i],
|
} else {
|
||||||
left_weight,
|
let interpolated = interpolate_premultiplied_component(
|
||||||
left_alpha,
|
left[i],
|
||||||
right[i],
|
left_weight,
|
||||||
right_weight,
|
alpha.left,
|
||||||
right_alpha,
|
right[i],
|
||||||
inverse_of_result_alpha,
|
right_weight,
|
||||||
)
|
alpha.right,
|
||||||
};
|
);
|
||||||
}
|
|
||||||
result[3] = result_alpha;
|
|
||||||
|
|
||||||
result
|
if alpha.interpolated == 0.0 {
|
||||||
|
interpolated
|
||||||
|
} else {
|
||||||
|
interpolated / alpha.interpolated
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
ComponentMixOutcome::UseLeft => result[i] = left[i],
|
||||||
|
ComponentMixOutcome::UseRight => result[i] = right[i],
|
||||||
|
ComponentMixOutcome::None => {
|
||||||
|
result[i] = 0.0;
|
||||||
|
match i {
|
||||||
|
0 => flags.insert(ColorFlags::C1_IS_NONE),
|
||||||
|
1 => flags.insert(ColorFlags::C2_IS_NONE),
|
||||||
|
2 => flags.insert(ColorFlags::C3_IS_NONE),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[3] = alpha.interpolated;
|
||||||
|
|
||||||
|
(result, flags)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ bitflags! {
|
|||||||
/// Flags used when serializing colors.
|
/// Flags used when serializing colors.
|
||||||
#[derive(Default, MallocSizeOf, ToShmem)]
|
#[derive(Default, MallocSizeOf, ToShmem)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct SerializationFlags : u8 {
|
pub struct ColorFlags : u8 {
|
||||||
/// If set, serializes sRGB colors into `color(srgb ...)` instead of
|
/// If set, serializes sRGB colors into `color(srgb ...)` instead of
|
||||||
/// `rgba(...)`.
|
/// `rgba(...)`.
|
||||||
const AS_COLOR_FUNCTION = 1 << 0;
|
const AS_COLOR_FUNCTION = 1 << 0;
|
||||||
@ -157,7 +157,7 @@ pub struct AbsoluteColor {
|
|||||||
/// The current color space that the components represent.
|
/// The current color space that the components represent.
|
||||||
pub color_space: ColorSpace,
|
pub color_space: ColorSpace,
|
||||||
/// Extra flags used durring serialization of this color.
|
/// Extra flags used durring serialization of this color.
|
||||||
pub flags: SerializationFlags,
|
pub flags: ColorFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given an [`AbsoluteColor`], return the 4 float components as the type given,
|
/// Given an [`AbsoluteColor`], return the 4 float components as the type given,
|
||||||
@ -207,7 +207,7 @@ impl AbsoluteColor {
|
|||||||
components,
|
components,
|
||||||
alpha: alpha.clamp(0.0, 1.0),
|
alpha: alpha.clamp(0.0, 1.0),
|
||||||
color_space,
|
color_space,
|
||||||
flags: SerializationFlags::empty(),
|
flags: ColorFlags::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ impl AbsoluteColor {
|
|||||||
pub fn is_legacy_color(&self) -> bool {
|
pub fn is_legacy_color(&self) -> bool {
|
||||||
// rgb(), rgba(), hsl(), hsla(), hwb(), hwba()
|
// rgb(), rgba(), hsl(), hsla(), hwb(), hwba()
|
||||||
match self.color_space {
|
match self.color_space {
|
||||||
ColorSpace::Srgb => !self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION),
|
ColorSpace::Srgb => !self.flags.contains(ColorFlags::AS_COLOR_FUNCTION),
|
||||||
ColorSpace::Hsl | ColorSpace::Hwb => true,
|
ColorSpace::Hsl | ColorSpace::Hwb => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@ -377,7 +377,7 @@ impl ToCss for AbsoluteColor {
|
|||||||
{
|
{
|
||||||
macro_rules! value_or_none {
|
macro_rules! value_or_none {
|
||||||
($v:expr,$flag:tt) => {{
|
($v:expr,$flag:tt) => {{
|
||||||
if self.flags.contains(SerializationFlags::$flag) {
|
if self.flags.contains(ColorFlags::$flag) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some($v)
|
Some($v)
|
||||||
@ -402,7 +402,7 @@ impl ToCss for AbsoluteColor {
|
|||||||
Self::new(ColorSpace::Srgb, rgb, self.alpha).to_css(dest)
|
Self::new(ColorSpace::Srgb, rgb, self.alpha).to_css(dest)
|
||||||
},
|
},
|
||||||
|
|
||||||
ColorSpace::Srgb if !self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION) => {
|
ColorSpace::Srgb if !self.flags.contains(ColorFlags::AS_COLOR_FUNCTION) => {
|
||||||
// Althought we are passing Option<_> in here, the to_css fn
|
// Althought we are passing Option<_> in here, the to_css fn
|
||||||
// knows that the "none" keyword is not supported in the
|
// knows that the "none" keyword is not supported in the
|
||||||
// rgb/rgba legacy syntax.
|
// rgb/rgba legacy syntax.
|
||||||
@ -431,7 +431,7 @@ impl ToCss for AbsoluteColor {
|
|||||||
let color_space = match self.color_space {
|
let color_space = match self.color_space {
|
||||||
ColorSpace::Srgb => {
|
ColorSpace::Srgb => {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION),
|
self.flags.contains(ColorFlags::AS_COLOR_FUNCTION),
|
||||||
"The case without this flag should be handled in the wrapping match case!!"
|
"The case without this flag should be handled in the wrapping match case!!"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
use super::AllowQuirks;
|
use super::AllowQuirks;
|
||||||
use crate::color::mix::ColorInterpolationMethod;
|
use crate::color::mix::ColorInterpolationMethod;
|
||||||
use crate::color::{AbsoluteColor, ColorComponents, ColorSpace, SerializationFlags};
|
use crate::color::{AbsoluteColor, ColorComponents, ColorFlags, ColorSpace};
|
||||||
use crate::media_queries::Device;
|
use crate::media_queries::Device;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
||||||
@ -400,14 +400,14 @@ fn new_absolute(
|
|||||||
c3: Option<f32>,
|
c3: Option<f32>,
|
||||||
alpha: Option<f32>,
|
alpha: Option<f32>,
|
||||||
) -> Color {
|
) -> Color {
|
||||||
let mut flags = SerializationFlags::empty();
|
let mut flags = ColorFlags::empty();
|
||||||
|
|
||||||
macro_rules! c {
|
macro_rules! c {
|
||||||
($v:expr,$flag:tt) => {{
|
($v:expr,$flag:tt) => {{
|
||||||
if let Some(value) = $v {
|
if let Some(value) = $v {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
flags |= SerializationFlags::$flag;
|
flags |= ColorFlags::$flag;
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
@ -505,7 +505,7 @@ impl cssparser::FromParsedColor for Color {
|
|||||||
let mut result = new_absolute(color_space.into(), c1, c2, c3, alpha);
|
let mut result = new_absolute(color_space.into(), c1, c2, c3, alpha);
|
||||||
if let Color::Absolute(ref mut absolute) = result {
|
if let Color::Absolute(ref mut absolute) = result {
|
||||||
if matches!(absolute.color.color_space, ColorSpace::Srgb) {
|
if matches!(absolute.color.color_space, ColorSpace::Srgb) {
|
||||||
absolute.color.flags |= SerializationFlags::AS_COLOR_FUNCTION;
|
absolute.color.flags |= ColorFlags::AS_COLOR_FUNCTION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
@ -621,10 +621,8 @@ impl Color {
|
|||||||
absolute.color.color_space,
|
absolute.color.color_space,
|
||||||
ColorSpace::Srgb | ColorSpace::Hsl
|
ColorSpace::Srgb | ColorSpace::Hsl
|
||||||
);
|
);
|
||||||
let is_color_function = absolute
|
let is_color_function =
|
||||||
.color
|
absolute.color.flags.contains(ColorFlags::AS_COLOR_FUNCTION);
|
||||||
.flags
|
|
||||||
.contains(SerializationFlags::AS_COLOR_FUNCTION);
|
|
||||||
let pref_enabled = static_prefs::pref!("layout.css.more_color_4.enabled");
|
let pref_enabled = static_prefs::pref!("layout.css.more_color_4.enabled");
|
||||||
|
|
||||||
(is_legacy_color && !is_color_function) || pref_enabled
|
(is_legacy_color && !is_color_function) || pref_enabled
|
||||||
|
@ -1,387 +0,0 @@
|
|||||||
[color-computed-color-mix-function.html]
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(100 0 50deg), lch(100 0 330deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(100 0 330deg), lch(100 0 50deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch shorter hue, lch(100 0 50deg), lch(100 0 330deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch shorter hue, lch(100 0 330deg), lch(100 0 50deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch increasing hue, lch(100 0 330deg), lch(100 0 50deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch decreasing hue, lch(100 0 50deg), lch(100 0 330deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(none none none), lch(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(none none none), lch(50 60 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(10 20 30deg), lch(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(10 20 none), lch(50 60 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(10 20 30deg), lch(50 60 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50 none 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lch, lch(10 20 30deg / none), lch(50 60 70deg / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(100 0 50deg), oklch(100 0 330deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(100 0 330deg), oklch(100 0 50deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch shorter hue, oklch(100 0 50deg), oklch(100 0 330deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch shorter hue, oklch(100 0 330deg), oklch(100 0 50deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch increasing hue, oklch(100 0 330deg), oklch(100 0 50deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch decreasing hue, oklch(100 0 50deg), oklch(100 0 330deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(none none none), oklch(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(none none none), oklch(50 60 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(10 20 none), oklch(50 60 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(10 20 30deg), oklch(50 60 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50 none 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklch, oklch(10 20 30deg / none), oklch(50 60 70deg / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(none none none), lab(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(none none none), lab(50 60 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(10 20 30), lab(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(10 20 none), lab(50 60 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(10 20 30), lab(50 60 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(none 20 30), lab(50 none 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in lab, lab(10 20 30 / none), lab(50 60 70 / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(none none none), oklab(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(none none none), oklab(50 60 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(10 20 none), oklab(50 60 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(10 20 30), oklab(50 60 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50 none 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in oklab, oklab(10 20 30 / none), oklab(50 60 70 / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))']
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))']
|
|
||||||
expected: FAIL
|
|
Loading…
Reference in New Issue
Block a user