mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
style: Hardening color checks
Avoid trying to resolve a currentcolor when a foreground color is not available. Differential Revision: https://phabricator.services.mozilla.com/D177368
This commit is contained in:
parent
f967d3c4fd
commit
18c701e6b5
6 changed files with 54 additions and 55 deletions
|
@ -443,10 +443,10 @@ fn tweak_when_ignoring_colors(
|
||||||
|
|
||||||
fn alpha_channel(color: &Color, context: &computed::Context) -> f32 {
|
fn alpha_channel(color: &Color, context: &computed::Context) -> f32 {
|
||||||
// We assume here currentColor is opaque.
|
// We assume here currentColor is opaque.
|
||||||
let color = color
|
color
|
||||||
.to_computed_value(context)
|
.to_computed_value(context)
|
||||||
.resolve_into_absolute(&AbsoluteColor::black());
|
.resolve_to_absolute(&AbsoluteColor::black())
|
||||||
color.alpha
|
.alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
// A few special-cases ahead.
|
// A few special-cases ahead.
|
||||||
|
|
|
@ -3239,7 +3239,7 @@ impl ComputedValues {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn resolve_color(&self, color: computed::Color) -> crate::color::AbsoluteColor {
|
pub fn resolve_color(&self, color: computed::Color) -> crate::color::AbsoluteColor {
|
||||||
let current_color = self.get_inherited_text().clone_color();
|
let current_color = self.get_inherited_text().clone_color();
|
||||||
color.resolve_into_absolute(¤t_color)
|
color.resolve_to_absolute(¤t_color)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns which longhand properties have different values in the two
|
/// Returns which longhand properties have different values in the two
|
||||||
|
|
|
@ -22,8 +22,7 @@ impl Animate for AbsoluteColor {
|
||||||
other,
|
other,
|
||||||
right_weight as f32,
|
right_weight as f32,
|
||||||
/* normalize_weights = */ false,
|
/* normalize_weights = */ false,
|
||||||
)
|
))
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ impl Animate for Color {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||||
let (left_weight, right_weight) = procedure.weights();
|
let (left_weight, right_weight) = procedure.weights();
|
||||||
let mut color = Color::ColorMix(Box::new(ColorMix {
|
Ok(Self::from_color_mix(ColorMix {
|
||||||
interpolation: ColorInterpolationMethod::srgb(),
|
interpolation: ColorInterpolationMethod::srgb(),
|
||||||
left: self.clone(),
|
left: self.clone(),
|
||||||
left_percentage: Percentage(left_weight as f32),
|
left_percentage: Percentage(left_weight as f32),
|
||||||
|
@ -68,9 +67,7 @@ impl Animate for Color {
|
||||||
right_percentage: Percentage(right_weight as f32),
|
right_percentage: Percentage(right_weight as f32),
|
||||||
// See https://github.com/w3c/csswg-drafts/issues/7324
|
// See https://github.com/w3c/csswg-drafts/issues/7324
|
||||||
normalize_weights: false,
|
normalize_weights: false,
|
||||||
}));
|
}))
|
||||||
color.simplify(None);
|
|
||||||
Ok(color)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +75,8 @@ impl ComputeSquaredDistance for Color {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||||
let current_color = AbsoluteColor::transparent();
|
let current_color = AbsoluteColor::transparent();
|
||||||
self.clone()
|
self.resolve_to_absolute(¤t_color)
|
||||||
.resolve_into_absolute(¤t_color)
|
.compute_squared_distance(&other.resolve_to_absolute(¤t_color))
|
||||||
.compute_squared_distance(&other.clone().resolve_into_absolute(¤t_color))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
use crate::color::AbsoluteColor;
|
use crate::color::AbsoluteColor;
|
||||||
use crate::values::animated::ToAnimatedZero;
|
use crate::values::animated::ToAnimatedZero;
|
||||||
use crate::values::computed::percentage::Percentage;
|
use crate::values::computed::percentage::Percentage;
|
||||||
use crate::values::generics::color::{GenericCaretColor, GenericColor, GenericColorOrAuto};
|
use crate::values::generics::color::{
|
||||||
|
GenericCaretColor, GenericColor, GenericColorMix, GenericColorOrAuto,
|
||||||
|
};
|
||||||
use cssparser::Color as CSSParserColor;
|
use cssparser::Color as CSSParserColor;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
@ -23,6 +25,9 @@ pub type MozFontSmoothingBackgroundColor = AbsoluteColor;
|
||||||
/// A computed value for `<color>`.
|
/// A computed value for `<color>`.
|
||||||
pub type Color = GenericColor<Percentage>;
|
pub type Color = GenericColor<Percentage>;
|
||||||
|
|
||||||
|
/// A computed color-mix().
|
||||||
|
pub type ColorMix = GenericColorMix<Color, Percentage>;
|
||||||
|
|
||||||
impl ToCss for Color {
|
impl ToCss for Color {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
|
@ -37,6 +42,16 @@ impl ToCss for Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
|
/// Create a new computed [`Color`] from a given color-mix, simplifying it to an absolute color
|
||||||
|
/// if possible.
|
||||||
|
pub fn from_color_mix(color_mix: ColorMix) -> Self {
|
||||||
|
if let Some(absolute) = color_mix.mix_to_absolute() {
|
||||||
|
Self::Absolute(absolute)
|
||||||
|
} else {
|
||||||
|
Self::ColorMix(Box::new(color_mix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a complex color value representing transparent.
|
/// Returns a complex color value representing transparent.
|
||||||
pub fn transparent() -> Color {
|
pub fn transparent() -> Color {
|
||||||
Color::Absolute(AbsoluteColor::transparent())
|
Color::Absolute(AbsoluteColor::transparent())
|
||||||
|
@ -54,9 +69,25 @@ impl Color {
|
||||||
|
|
||||||
/// Combine this complex color with the given foreground color into an
|
/// Combine this complex color with the given foreground color into an
|
||||||
/// absolute color.
|
/// absolute color.
|
||||||
pub fn resolve_into_absolute(mut self, current_color: &AbsoluteColor) -> AbsoluteColor {
|
pub fn resolve_to_absolute(&self, current_color: &AbsoluteColor) -> AbsoluteColor {
|
||||||
self.simplify(Some(¤t_color));
|
use crate::values::specified::percentage::ToPercentage;
|
||||||
*self.as_absolute().unwrap()
|
|
||||||
|
match *self {
|
||||||
|
Self::Absolute(c) => c,
|
||||||
|
Self::CurrentColor => *current_color,
|
||||||
|
Self::ColorMix(ref mix) => {
|
||||||
|
let left = mix.left.resolve_to_absolute(current_color);
|
||||||
|
let right = mix.right.resolve_to_absolute(current_color);
|
||||||
|
crate::color::mix::mix(
|
||||||
|
mix.interpolation,
|
||||||
|
&left,
|
||||||
|
mix.left_percentage.to_percentage(),
|
||||||
|
&right,
|
||||||
|
mix.right_percentage.to_percentage(),
|
||||||
|
mix.normalize_weights,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
use crate::color::mix::ColorInterpolationMethod;
|
use crate::color::mix::ColorInterpolationMethod;
|
||||||
use crate::color::AbsoluteColor;
|
use crate::color::AbsoluteColor;
|
||||||
use crate::values::animated::ToAnimatedValue;
|
|
||||||
use crate::values::specified::percentage::ToPercentage;
|
use crate::values::specified::percentage::ToPercentage;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
@ -94,23 +93,21 @@ impl<Color: ToCss, Percentage: ToCss + ToPercentage> ToCss for ColorMix<Color, P
|
||||||
impl<Percentage> ColorMix<GenericColor<Percentage>, Percentage> {
|
impl<Percentage> ColorMix<GenericColor<Percentage>, Percentage> {
|
||||||
/// Mix the colors so that we get a single color. If any of the 2 colors are
|
/// Mix the colors so that we get a single color. If any of the 2 colors are
|
||||||
/// not mixable (perhaps not absolute?), then return None.
|
/// not mixable (perhaps not absolute?), then return None.
|
||||||
fn mix_into_absolute(&self) -> Option<AbsoluteColor>
|
pub fn mix_to_absolute(&self) -> Option<AbsoluteColor>
|
||||||
where
|
where
|
||||||
Percentage: ToPercentage,
|
Percentage: ToPercentage,
|
||||||
{
|
{
|
||||||
let left = self.left.as_absolute()?.to_animated_value();
|
let left = self.left.as_absolute()?;
|
||||||
let right = self.right.as_absolute()?.to_animated_value();
|
let right = self.right.as_absolute()?;
|
||||||
|
|
||||||
let mixed = crate::color::mix::mix(
|
Some(crate::color::mix::mix(
|
||||||
self.interpolation,
|
self.interpolation,
|
||||||
&left,
|
&left,
|
||||||
self.left_percentage.to_percentage(),
|
self.left_percentage.to_percentage(),
|
||||||
&right,
|
&right,
|
||||||
self.right_percentage.to_percentage(),
|
self.right_percentage.to_percentage(),
|
||||||
self.normalize_weights,
|
self.normalize_weights,
|
||||||
);
|
))
|
||||||
|
|
||||||
Some(ToAnimatedValue::from_animated_value(mixed.into()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,30 +122,6 @@ impl<Percentage> Color<Percentage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simplifies the color-mix()es to the extent possible given a current
|
|
||||||
/// color (or not).
|
|
||||||
pub fn simplify(&mut self, current_color: Option<&AbsoluteColor>)
|
|
||||||
where
|
|
||||||
Percentage: ToPercentage,
|
|
||||||
{
|
|
||||||
match *self {
|
|
||||||
Self::Absolute(..) => {},
|
|
||||||
Self::CurrentColor => {
|
|
||||||
if let Some(c) = current_color {
|
|
||||||
*self = Self::Absolute(c.clone());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Self::ColorMix(ref mut mix) => {
|
|
||||||
mix.left.simplify(current_color);
|
|
||||||
mix.right.simplify(current_color);
|
|
||||||
|
|
||||||
if let Some(mix) = mix.mix_into_absolute() {
|
|
||||||
*self = Self::Absolute(mix);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a color value representing currentcolor.
|
/// Returns a color value representing currentcolor.
|
||||||
pub fn currentcolor() -> Self {
|
pub fn currentcolor() -> Self {
|
||||||
Self::CurrentColor
|
Self::CurrentColor
|
||||||
|
|
|
@ -883,16 +883,15 @@ impl Color {
|
||||||
|
|
||||||
let left = mix.left.to_computed_color(context)?;
|
let left = mix.left.to_computed_color(context)?;
|
||||||
let right = mix.right.to_computed_color(context)?;
|
let right = mix.right.to_computed_color(context)?;
|
||||||
let mut color = ComputedColor::ColorMix(Box::new(GenericColorMix {
|
|
||||||
|
ComputedColor::from_color_mix(GenericColorMix {
|
||||||
interpolation: mix.interpolation,
|
interpolation: mix.interpolation,
|
||||||
left,
|
left,
|
||||||
left_percentage: Percentage(mix.left_percentage.get()),
|
left_percentage: Percentage(mix.left_percentage.get()),
|
||||||
right,
|
right,
|
||||||
right_percentage: Percentage(mix.right_percentage.get()),
|
right_percentage: Percentage(mix.right_percentage.get()),
|
||||||
normalize_weights: mix.normalize_weights,
|
normalize_weights: mix.normalize_weights,
|
||||||
}));
|
})
|
||||||
color.simplify(None);
|
|
||||||
color
|
|
||||||
},
|
},
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
Color::System(system) => system.compute(context?),
|
Color::System(system) => system.compute(context?),
|
||||||
|
@ -946,7 +945,7 @@ impl ToComputedValue for MozFontSmoothingBackgroundColor {
|
||||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
self.0
|
self.0
|
||||||
.to_computed_value(context)
|
.to_computed_value(context)
|
||||||
.resolve_into_absolute(&AbsoluteColor::transparent())
|
.resolve_to_absolute(&AbsoluteColor::transparent())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
@ -995,7 +994,7 @@ impl ToComputedValue for ColorPropertyValue {
|
||||||
let current_color = context.builder.get_parent_inherited_text().clone_color();
|
let current_color = context.builder.get_parent_inherited_text().clone_color();
|
||||||
self.0
|
self.0
|
||||||
.to_computed_value(context)
|
.to_computed_value(context)
|
||||||
.resolve_into_absolute(¤t_color)
|
.resolve_to_absolute(¤t_color)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue