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.
|
||||
pub fn mix(left: &Color, right: &Color, progress: f32) -> Self {
|
||||
left.animate(right, Procedure::Interpolate { progress: progress as f64 }).unwrap()
|
||||
pub fn mix(
|
||||
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 {
|
||||
|
|
|
@ -28,8 +28,9 @@ use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind};
|
|||
#[allow(missing_docs)]
|
||||
pub struct ColorMix {
|
||||
pub left: Color,
|
||||
pub left_percentage: Percentage,
|
||||
pub right: Color,
|
||||
pub percentage: Percentage,
|
||||
pub right_percentage: Percentage,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -71,14 +72,27 @@ impl Parse for ColorMix {
|
|||
// TODO: support multiple interpolation spaces.
|
||||
input.expect_ident_matching("srgb")?;
|
||||
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
|
||||
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, ")?;
|
||||
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(" ")?;
|
||||
self.percentage.to_css(dest)?;
|
||||
self.left_percentage.to_css(dest)?;
|
||||
}
|
||||
dest.write_str(", ")?;
|
||||
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(")")
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +691,12 @@ impl Color {
|
|||
|
||||
let left = mix.left.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")]
|
||||
Color::System(system) => system.compute(context?),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue