mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
style: Address spec changes re. color-mix
It was clarified that the percentages are weights, and two weights are now allowed. Missing percentages are computed as 100% - the other or 50%. Other than that, commas are required etc, which is good since that's how I implemented it originally. Differential Revision: https://phabricator.services.mozilla.com/D107295
This commit is contained in:
parent
685d269e31
commit
2bafbb46f5
2 changed files with 85 additions and 13 deletions
|
@ -105,8 +105,44 @@ impl Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mix two colors into one.
|
/// Mix two colors into one.
|
||||||
pub fn mix(left: &Color, right: &Color, progress: f32) -> Self {
|
pub fn mix(
|
||||||
left.animate(right, Procedure::Interpolate { progress: progress as f64 }).unwrap()
|
left_color: &Color,
|
||||||
|
left_weight: f32,
|
||||||
|
right_color: &Color,
|
||||||
|
right_weight: f32,
|
||||||
|
) -> Self {
|
||||||
|
let left_bg = left_color.scaled_rgba();
|
||||||
|
let right_bg = right_color.scaled_rgba();
|
||||||
|
let alpha = (left_bg.alpha * left_weight +
|
||||||
|
right_bg.alpha * right_weight)
|
||||||
|
.min(1.);
|
||||||
|
|
||||||
|
let mut fg = 0.;
|
||||||
|
let mut red = 0.;
|
||||||
|
let mut green = 0.;
|
||||||
|
let mut blue = 0.;
|
||||||
|
|
||||||
|
let colors = [
|
||||||
|
(left_color, &left_bg, left_weight),
|
||||||
|
(right_color, &right_bg, right_weight),
|
||||||
|
];
|
||||||
|
|
||||||
|
for &(color, bg, weight) in &colors {
|
||||||
|
fg += color.ratios.fg * weight;
|
||||||
|
|
||||||
|
red += bg.red * bg.alpha * weight;
|
||||||
|
green += bg.green * bg.alpha * weight;
|
||||||
|
blue += bg.blue * bg.alpha * weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
let color = if alpha <= 0. {
|
||||||
|
RGBA::transparent()
|
||||||
|
} else {
|
||||||
|
let inv = 1. / alpha;
|
||||||
|
RGBA::new(red * inv, green * inv, blue * inv, alpha)
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::new(color, ComplexColorRatios { bg: 1., fg })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scaled_rgba(&self) -> RGBA {
|
fn scaled_rgba(&self) -> RGBA {
|
||||||
|
|
|
@ -28,8 +28,9 @@ use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind};
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub struct ColorMix {
|
pub struct ColorMix {
|
||||||
pub left: Color,
|
pub left: Color,
|
||||||
|
pub left_percentage: Percentage,
|
||||||
pub right: Color,
|
pub right: Color,
|
||||||
pub percentage: Percentage,
|
pub right_percentage: Percentage,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
@ -71,14 +72,27 @@ impl Parse for ColorMix {
|
||||||
// TODO: support multiple interpolation spaces.
|
// TODO: support multiple interpolation spaces.
|
||||||
input.expect_ident_matching("srgb")?;
|
input.expect_ident_matching("srgb")?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
let left = Color::parse(context, input)?;
|
|
||||||
let percentage = input.try_parse(|input| {
|
|
||||||
Percentage::parse(context, input)
|
|
||||||
}).unwrap_or_else(|_| Percentage::new(0.5));
|
|
||||||
input.expect_comma()?;
|
|
||||||
let right = Color::parse(context, input)?;
|
|
||||||
|
|
||||||
Ok(ColorMix { left, right, percentage })
|
let left = Color::parse(context, input)?;
|
||||||
|
let left_percentage = input.try_parse(|input| Percentage::parse(context, input)).ok();
|
||||||
|
|
||||||
|
input.expect_comma()?;
|
||||||
|
|
||||||
|
let right = Color::parse(context, input)?;
|
||||||
|
let right_percentage = input
|
||||||
|
.try_parse(|input| Percentage::parse(context, input))
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
Percentage::new(1.0 - left_percentage.map_or(0.5, |p| p.get()))
|
||||||
|
});
|
||||||
|
|
||||||
|
let left_percentage =
|
||||||
|
left_percentage.unwrap_or_else(|| Percentage::new(1.0 - right_percentage.get()));
|
||||||
|
Ok(ColorMix {
|
||||||
|
left,
|
||||||
|
left_percentage,
|
||||||
|
right,
|
||||||
|
right_percentage,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,14 +102,31 @@ impl ToCss for ColorMix {
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
|
fn can_omit(percent: &Percentage, other: &Percentage, is_left: bool) -> bool {
|
||||||
|
if percent.is_calc() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if percent.get() == 0.5 {
|
||||||
|
return other.get() == 0.5;
|
||||||
|
}
|
||||||
|
if is_left {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(1.0 - percent.get() - other.get()).abs() <= f32::EPSILON
|
||||||
|
}
|
||||||
|
|
||||||
dest.write_str("color-mix(in srgb, ")?;
|
dest.write_str("color-mix(in srgb, ")?;
|
||||||
self.left.to_css(dest)?;
|
self.left.to_css(dest)?;
|
||||||
if self.percentage.get() != 0.5 || self.percentage.is_calc() {
|
if !can_omit(&self.left_percentage, &self.right_percentage, true) {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.percentage.to_css(dest)?;
|
self.left_percentage.to_css(dest)?;
|
||||||
}
|
}
|
||||||
dest.write_str(", ")?;
|
dest.write_str(", ")?;
|
||||||
self.right.to_css(dest)?;
|
self.right.to_css(dest)?;
|
||||||
|
if !can_omit(&self.right_percentage, &self.left_percentage, false) {
|
||||||
|
dest.write_str(" ")?;
|
||||||
|
self.right_percentage.to_css(dest)?;
|
||||||
|
}
|
||||||
dest.write_str(")")
|
dest.write_str(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,7 +691,12 @@ impl Color {
|
||||||
|
|
||||||
let left = mix.left.to_computed_color(context)?.to_animated_value();
|
let left = mix.left.to_computed_color(context)?.to_animated_value();
|
||||||
let right = mix.right.to_computed_color(context)?.to_animated_value();
|
let right = mix.right.to_computed_color(context)?.to_animated_value();
|
||||||
ToAnimatedValue::from_animated_value(AnimatedColor::mix(&left, &right, mix.percentage.get()))
|
ToAnimatedValue::from_animated_value(AnimatedColor::mix(
|
||||||
|
&left,
|
||||||
|
mix.left_percentage.get(),
|
||||||
|
&right,
|
||||||
|
mix.right_percentage.get(),
|
||||||
|
))
|
||||||
},
|
},
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
Color::System(system) => system.compute(context?),
|
Color::System(system) => system.compute(context?),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue