mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
style: Convert RGBA to AbsoluteColor for computed/animated/resolved CSS colors
Computed color values will not be in the correct format, closer to the one specified by the author. This also means that colors accross the code are stored now as AbsoluteColor or StyleAbsoluteColor. This allows color space/gamut information to be available for use. Some animation related test failures had to be changed, because colors now has greater precision. Animated a color now causes a lot more animation updates, which was not initially expected. See the bug for discussion. Differential Revision: https://phabricator.services.mozilla.com/D171021
This commit is contained in:
parent
3763d9a6cc
commit
8c1c4073e2
19 changed files with 233 additions and 258 deletions
|
@ -6,7 +6,6 @@
|
|||
|
||||
use super::{AbsoluteColor, ColorComponents, ColorSpace};
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::animated::color::AnimatedRGBA as RGBA;
|
||||
use cssparser::Parser;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
|
@ -65,12 +64,34 @@ pub struct ColorInterpolationMethod {
|
|||
|
||||
impl ColorInterpolationMethod {
|
||||
/// Returns the srgb interpolation method.
|
||||
pub fn srgb() -> Self {
|
||||
pub const fn srgb() -> Self {
|
||||
Self {
|
||||
space: ColorSpace::Srgb,
|
||||
hue: HueInterpolationMethod::Shorter,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the oklab interpolation method used for default color
|
||||
/// interpolcation.
|
||||
pub const fn oklab() -> Self {
|
||||
Self {
|
||||
space: ColorSpace::Oklab,
|
||||
hue: HueInterpolationMethod::Shorter,
|
||||
}
|
||||
}
|
||||
|
||||
/// Decides the best method for interpolating between the given colors.
|
||||
/// https://drafts.csswg.org/css-color-4/#interpolation-space
|
||||
pub fn best_interpolation_between(left: &AbsoluteColor, right: &AbsoluteColor) -> Self {
|
||||
// The preferred color space to use for interpolating colors is Oklab.
|
||||
// However, if either of the colors are in legacy rgb(), hsl() or hwb(),
|
||||
// then interpolation is done in sRGB.
|
||||
if !left.is_legacy_color() || !right.is_legacy_color() {
|
||||
Self::oklab()
|
||||
} else {
|
||||
Self::srgb()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for ColorInterpolationMethod {
|
||||
|
@ -118,7 +139,7 @@ impl ToCss for ColorInterpolationMethod {
|
|||
///
|
||||
/// 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 + From<RGBA> + Into<RGBA> {
|
||||
trait ModelledColor: Clone + Copy {
|
||||
/// Linearly interpolate between the left and right colors.
|
||||
///
|
||||
/// The HueInterpolationMethod parameter is only for color spaces where the hue is
|
||||
|
@ -134,7 +155,7 @@ trait ModelledColor: Clone + Copy + From<RGBA> + Into<RGBA> {
|
|||
|
||||
/// Mix two colors into one.
|
||||
pub fn mix(
|
||||
interpolation: &ColorInterpolationMethod,
|
||||
interpolation: ColorInterpolationMethod,
|
||||
left_color: &AbsoluteColor,
|
||||
mut left_weight: f32,
|
||||
right_color: &AbsoluteColor,
|
||||
|
|
|
@ -13,6 +13,7 @@ use style_traits::{CssWriter, ToCss};
|
|||
|
||||
/// The 3 components that make up a color. (Does not include the alpha component)
|
||||
#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||
#[repr(C)]
|
||||
pub struct ColorComponents(pub f32, pub f32, pub f32);
|
||||
|
||||
impl ColorComponents {
|
||||
|
@ -46,6 +47,11 @@ impl ColorComponents {
|
|||
)]
|
||||
#[repr(u8)]
|
||||
pub enum ColorSpace {
|
||||
/// A color specified in the sRGB color space with either the rgb/rgba(..)
|
||||
/// functions or the newer color(srgb ..) function. If the color(..)
|
||||
/// function is used, the AS_COLOR_FUNCTION flag will be set. Examples:
|
||||
/// "color(srgb 0.691 0.139 0.259)", "rgb(176, 35, 66)"
|
||||
Srgb = 0,
|
||||
/// A color specified in the Hsl notation in the sRGB color space, e.g.
|
||||
/// "hsl(289.18 93.136% 65.531%)"
|
||||
/// https://drafts.csswg.org/css-color-4/#the-hsl-notation
|
||||
|
@ -70,9 +76,6 @@ pub enum ColorSpace {
|
|||
/// "oklch(40.101% 0.12332 21.555)".
|
||||
/// https://w3c.github.io/csswg-drafts/css-color-4/#lch-colors
|
||||
Oklch,
|
||||
/// A color specified with the color(..) function and the "srgb" color
|
||||
/// space, e.g. "color(srgb 0.691 0.139 0.259)".
|
||||
Srgb,
|
||||
/// A color specified with the color(..) function and the "srgb-linear"
|
||||
/// color space, e.g. "color(srgb-linear 0.435 0.017 0.055)".
|
||||
SrgbLinear,
|
||||
|
@ -141,7 +144,7 @@ bitflags! {
|
|||
|
||||
/// An absolutely specified color, using either rgb(), rgba(), lab(), lch(),
|
||||
/// oklab(), oklch() or color().
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||
#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||
#[repr(C)]
|
||||
pub struct AbsoluteColor {
|
||||
/// The 3 components that make up colors in any color space.
|
||||
|
@ -179,22 +182,69 @@ macro_rules! color_components_as {
|
|||
}
|
||||
|
||||
impl AbsoluteColor {
|
||||
/// Create a new [AbsoluteColor] with the given [ColorSpace] and components.
|
||||
/// Create a new [`AbsoluteColor`] with the given [`ColorSpace`] and
|
||||
/// components.
|
||||
pub fn new(color_space: ColorSpace, components: ColorComponents, alpha: f32) -> Self {
|
||||
let mut components = components;
|
||||
|
||||
// Lightness must not be less than 0.
|
||||
if matches!(
|
||||
color_space,
|
||||
ColorSpace::Lab | ColorSpace::Lch | ColorSpace::Oklab | ColorSpace::Oklch
|
||||
) {
|
||||
components.0 = components.0.max(0.0);
|
||||
}
|
||||
|
||||
// Chroma must not be less than 0.
|
||||
if matches!(color_space, ColorSpace::Lch | ColorSpace::Oklch) {
|
||||
components.1 = components.1.max(0.0);
|
||||
}
|
||||
|
||||
Self {
|
||||
components,
|
||||
alpha,
|
||||
alpha: alpha.clamp(0.0, 1.0),
|
||||
color_space,
|
||||
flags: SerializationFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`AbsoluteColor`] from rgba values in the sRGB color space.
|
||||
pub fn srgb(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
|
||||
Self::new(ColorSpace::Srgb, ColorComponents(red, green, blue), alpha)
|
||||
}
|
||||
|
||||
/// Create a new transparent color.
|
||||
pub fn transparent() -> Self {
|
||||
Self::srgb(0.0, 0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
/// Create a new opaque black color.
|
||||
pub fn black() -> Self {
|
||||
Self::srgb(0.0, 0.0, 0.0, 1.0)
|
||||
}
|
||||
|
||||
/// Create a new opaque white color.
|
||||
pub fn white() -> Self {
|
||||
Self::srgb(1.0, 1.0, 1.0, 1.0)
|
||||
}
|
||||
|
||||
/// Return all the components of the color in an array. (Includes alpha)
|
||||
#[inline]
|
||||
pub fn raw_components(&self) -> &[f32; 4] {
|
||||
unsafe { color_components_as!(self, [f32; 4]) }
|
||||
}
|
||||
|
||||
/// Returns true if this color is in one of the legacy color formats.
|
||||
#[inline]
|
||||
pub fn is_legacy_color(&self) -> bool {
|
||||
// rgb(), rgba(), hsl(), hsla(), hwb(), hwba()
|
||||
match self.color_space {
|
||||
ColorSpace::Srgb => !self.flags.contains(SerializationFlags::AS_COLOR_FUNCTION),
|
||||
ColorSpace::Hsl | ColorSpace::Hwb => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the alpha component.
|
||||
#[inline]
|
||||
pub fn alpha(&self) -> f32 {
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
|
||||
//! Gecko's media-query device and expression representation.
|
||||
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::context::QuirksMode;
|
||||
use crate::custom_properties::CssEnvironment;
|
||||
use crate::font_metrics::FontMetrics;
|
||||
use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
||||
use crate::gecko::values::{convert_absolute_color_to_nscolor, convert_nscolor_to_absolute_color};
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::gecko_bindings::structs;
|
||||
use crate::media_queries::MediaType;
|
||||
|
@ -20,7 +21,6 @@ use crate::values::specified::font::FONT_MEDIUM_PX;
|
|||
use crate::values::specified::ViewportVariant;
|
||||
use crate::values::{CustomIdent, KeyframesName};
|
||||
use app_units::{Au, AU_PER_PX};
|
||||
use cssparser::RGBA;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::{Scale, SideOffsets2D};
|
||||
use servo_arc::Arc;
|
||||
|
@ -189,9 +189,11 @@ impl Device {
|
|||
/// Sets the body text color for the "inherit color from body" quirk.
|
||||
///
|
||||
/// <https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk>
|
||||
pub fn set_body_text_color(&self, color: RGBA) {
|
||||
self.body_text_color
|
||||
.store(convert_rgba_to_nscolor(&color) as usize, Ordering::Relaxed)
|
||||
pub fn set_body_text_color(&self, color: AbsoluteColor) {
|
||||
self.body_text_color.store(
|
||||
convert_absolute_color_to_nscolor(&color) as usize,
|
||||
Ordering::Relaxed,
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets the base size given a generic font family and a language.
|
||||
|
@ -268,8 +270,8 @@ impl Device {
|
|||
}
|
||||
|
||||
/// Returns the body text color.
|
||||
pub fn body_text_color(&self) -> RGBA {
|
||||
convert_nscolor_to_rgba(self.body_text_color.load(Ordering::Relaxed) as u32)
|
||||
pub fn body_text_color(&self) -> AbsoluteColor {
|
||||
convert_nscolor_to_absolute_color(self.body_text_color.load(Ordering::Relaxed) as u32)
|
||||
}
|
||||
|
||||
/// Gets the document pointer.
|
||||
|
@ -494,17 +496,17 @@ impl Device {
|
|||
///
|
||||
/// This is only for forced-colors/high-contrast, so looking at light colors
|
||||
/// is ok.
|
||||
pub fn default_background_color(&self) -> RGBA {
|
||||
pub fn default_background_color(&self) -> AbsoluteColor {
|
||||
let normal = ColorScheme::normal();
|
||||
convert_nscolor_to_rgba(self.system_nscolor(SystemColor::Canvas, &normal))
|
||||
convert_nscolor_to_absolute_color(self.system_nscolor(SystemColor::Canvas, &normal))
|
||||
}
|
||||
|
||||
/// Returns the default foreground color.
|
||||
///
|
||||
/// See above for looking at light colors only.
|
||||
pub fn default_color(&self) -> RGBA {
|
||||
pub fn default_color(&self) -> AbsoluteColor {
|
||||
let normal = ColorScheme::normal();
|
||||
convert_nscolor_to_rgba(self.system_nscolor(SystemColor::Canvastext, &normal))
|
||||
convert_nscolor_to_absolute_color(self.system_nscolor(SystemColor::Canvastext, &normal))
|
||||
}
|
||||
|
||||
/// Returns the current effective text zoom.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
//! Different kind of helpers to interact with Gecko values.
|
||||
|
||||
use crate::color::{AbsoluteColor, ColorSpace};
|
||||
use crate::counter_style::{Symbol, Symbols};
|
||||
use crate::gecko_bindings::bindings;
|
||||
use crate::gecko_bindings::structs::CounterStylePtr;
|
||||
|
@ -13,23 +14,28 @@ use crate::values::generics::CounterStyle;
|
|||
use crate::values::Either;
|
||||
use crate::Atom;
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
use std::cmp::max;
|
||||
|
||||
/// Convert a given RGBA value to `nscolor`.
|
||||
pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
|
||||
/// Convert a color value to `nscolor`.
|
||||
pub fn convert_absolute_color_to_nscolor(color: &AbsoluteColor) -> u32 {
|
||||
let srgb = color.to_color_space(ColorSpace::Srgb);
|
||||
u32::from_le_bytes([
|
||||
rgba.red,
|
||||
rgba.green,
|
||||
rgba.blue,
|
||||
(rgba.alpha * 255.0).round() as u8,
|
||||
(srgb.components.0 * 255.0).round() as u8,
|
||||
(srgb.components.1 * 255.0).round() as u8,
|
||||
(srgb.components.2 * 255.0).round() as u8,
|
||||
(srgb.alpha * 255.0).round() as u8,
|
||||
])
|
||||
}
|
||||
|
||||
/// Convert a given `nscolor` to a Servo RGBA value.
|
||||
pub fn convert_nscolor_to_rgba(color: u32) -> RGBA {
|
||||
/// Convert a given `nscolor` to a Servo AbsoluteColor value.
|
||||
pub fn convert_nscolor_to_absolute_color(color: u32) -> AbsoluteColor {
|
||||
let [r, g, b, a] = color.to_le_bytes();
|
||||
RGBA::new(r, g, b, a as f32 / 255.0)
|
||||
AbsoluteColor::srgb(
|
||||
r as f32 / 255.0,
|
||||
g as f32 / 255.0,
|
||||
b as f32 / 255.0,
|
||||
a as f32 / 255.0,
|
||||
)
|
||||
}
|
||||
|
||||
/// Round `width` down to the nearest device pixel, but any non-zero value that
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//! The main cascading algorithm of the style system.
|
||||
|
||||
use crate::applicable_declarations::CascadePriority;
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::context::QuirksMode;
|
||||
use crate::custom_properties::CustomPropertiesBuilder;
|
||||
use crate::dom::TElement;
|
||||
|
@ -411,9 +412,8 @@ fn tweak_when_ignoring_colors(
|
|||
declaration: &mut Cow<PropertyDeclaration>,
|
||||
declarations_to_apply_unless_overriden: &mut DeclarationsToApplyUnlessOverriden,
|
||||
) {
|
||||
use crate::values::specified::Color;
|
||||
use crate::values::computed::ToComputedValue;
|
||||
use cssparser::RGBA;
|
||||
use crate::values::specified::Color;
|
||||
|
||||
if !longhand_id.ignored_when_document_colors_disabled() {
|
||||
return;
|
||||
|
@ -445,7 +445,7 @@ fn tweak_when_ignoring_colors(
|
|||
// We assume here currentColor is opaque.
|
||||
let color = color
|
||||
.to_computed_value(context)
|
||||
.into_rgba(RGBA::new(0, 0, 0, 1.0));
|
||||
.resolve_into_absolute(&AbsoluteColor::black());
|
||||
color.alpha
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#[allow(unused_imports)]
|
||||
use app_units::Au;
|
||||
#[allow(unused_imports)]
|
||||
use cssparser::{Color as CSSParserColor, RGBA};
|
||||
#[allow(unused_imports)]
|
||||
use crate::values::specified::AllowQuirks;
|
||||
#[allow(unused_imports)]
|
||||
use crate::Zero;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
${helpers.predefined_type(
|
||||
"color",
|
||||
"ColorPropertyValue",
|
||||
"::cssparser::RGBA::new(0, 0, 0, 1.0)",
|
||||
"crate::color::AbsoluteColor::black()",
|
||||
engines="gecko servo",
|
||||
animation_value_type="AnimatedRGBA",
|
||||
animation_value_type="AbsoluteColor",
|
||||
ignored_when_colors_disabled="True",
|
||||
spec="https://drafts.csswg.org/css-color/#color",
|
||||
)}
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::{ops, ptr};
|
|||
use std::fmt::{self, Write};
|
||||
use std::mem;
|
||||
|
||||
use cssparser::{Parser, RGBA, TokenSerializationType};
|
||||
use cssparser::{Parser, TokenSerializationType};
|
||||
use cssparser::ParserInput;
|
||||
#[cfg(feature = "servo")] use euclid::SideOffsets2D;
|
||||
use crate::context::QuirksMode;
|
||||
|
@ -3233,8 +3233,9 @@ impl ComputedValues {
|
|||
/// let top_color =
|
||||
/// style.resolve_color(style.get_border().clone_border_top_color());
|
||||
#[inline]
|
||||
pub fn resolve_color(&self, color: computed::Color) -> RGBA {
|
||||
color.into_rgba(self.get_inherited_text().clone_color())
|
||||
pub fn resolve_color(&self, color: computed::Color) -> crate::color::AbsoluteColor {
|
||||
let current_color = self.get_inherited_text().clone_color();
|
||||
color.resolve_into_absolute(¤t_color)
|
||||
}
|
||||
|
||||
/// Returns which longhand properties have different values in the two
|
||||
|
|
|
@ -17,7 +17,6 @@ use crate::values::specified::font::FONT_MEDIUM_PX;
|
|||
use crate::values::specified::ViewportVariant;
|
||||
use crate::values::KeyframesName;
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
use euclid::default::Size2D as UntypedSize2D;
|
||||
use euclid::{Scale, SideOffsets2D, Size2D};
|
||||
use mime::Mime;
|
||||
|
|
|
@ -184,9 +184,12 @@ impl FontPaletteValuesRule {
|
|||
}
|
||||
for c in &self.override_colors {
|
||||
if let SpecifiedColor::Absolute(ref absolute) = c.color {
|
||||
let rgba = absolute.color.to_rgba();
|
||||
unsafe {
|
||||
Gecko_SetFontPaletteOverride(palette_values, c.index.0.value(), rgba);
|
||||
Gecko_SetFontPaletteOverride(
|
||||
palette_values,
|
||||
c.index.0.value(),
|
||||
(&absolute.color) as *const _ as *mut _,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,82 +5,21 @@
|
|||
//! Animated types for CSS colors.
|
||||
|
||||
use crate::color::mix::ColorInterpolationMethod;
|
||||
use crate::color::{AbsoluteColor, ColorComponents, ColorSpace};
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::values::animated::{Animate, Procedure, ToAnimatedZero};
|
||||
use crate::values::computed::Percentage;
|
||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use crate::values::generics::color::{GenericColor, GenericColorMix};
|
||||
|
||||
/// An animated RGBA color.
|
||||
///
|
||||
/// Unlike in computed values, each component value may exceed the
|
||||
/// range `[0.0, 1.0]`.
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToAnimatedZero, ToAnimatedValue)]
|
||||
#[repr(C)]
|
||||
pub struct AnimatedRGBA {
|
||||
/// The red component.
|
||||
pub red: f32,
|
||||
/// The green component.
|
||||
pub green: f32,
|
||||
/// The blue component.
|
||||
pub blue: f32,
|
||||
/// The alpha component.
|
||||
pub alpha: f32,
|
||||
}
|
||||
|
||||
impl From<AbsoluteColor> for AnimatedRGBA {
|
||||
fn from(value: AbsoluteColor) -> Self {
|
||||
let srgb = value.to_color_space(ColorSpace::Srgb);
|
||||
|
||||
Self::new(
|
||||
srgb.components.0,
|
||||
srgb.components.1,
|
||||
srgb.components.2,
|
||||
srgb.alpha,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnimatedRGBA> for AbsoluteColor {
|
||||
fn from(value: AnimatedRGBA) -> Self {
|
||||
Self::new(
|
||||
ColorSpace::Srgb,
|
||||
ColorComponents(value.red, value.green, value.blue),
|
||||
value.alpha,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
use self::AnimatedRGBA as RGBA;
|
||||
|
||||
impl RGBA {
|
||||
/// Returns a transparent color.
|
||||
#[inline]
|
||||
pub fn transparent() -> Self {
|
||||
Self::new(0., 0., 0., 0.)
|
||||
}
|
||||
|
||||
/// Returns a new color.
|
||||
#[inline]
|
||||
pub fn new(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
|
||||
RGBA {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Animate for RGBA {
|
||||
impl Animate for AbsoluteColor {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
let (left_weight, right_weight) = procedure.weights();
|
||||
Ok(crate::color::mix::mix(
|
||||
&ColorInterpolationMethod::srgb(),
|
||||
&AbsoluteColor::from(self.clone()),
|
||||
ColorInterpolationMethod::best_interpolation_between(self, other),
|
||||
self,
|
||||
left_weight as f32,
|
||||
&AbsoluteColor::from(other.clone()),
|
||||
other,
|
||||
right_weight as f32,
|
||||
/* normalize_weights = */ false,
|
||||
)
|
||||
|
@ -88,20 +27,20 @@ impl Animate for RGBA {
|
|||
}
|
||||
}
|
||||
|
||||
impl ComputeSquaredDistance for RGBA {
|
||||
impl ComputeSquaredDistance for AbsoluteColor {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
let start = [
|
||||
self.alpha,
|
||||
self.red * self.alpha,
|
||||
self.green * self.alpha,
|
||||
self.blue * self.alpha,
|
||||
self.components.0 * self.alpha,
|
||||
self.components.1 * self.alpha,
|
||||
self.components.2 * self.alpha,
|
||||
];
|
||||
let end = [
|
||||
other.alpha,
|
||||
other.red * other.alpha,
|
||||
other.green * other.alpha,
|
||||
other.blue * other.alpha,
|
||||
other.components.0 * other.alpha,
|
||||
other.components.1 * other.alpha,
|
||||
other.components.2 * other.alpha,
|
||||
];
|
||||
start
|
||||
.iter()
|
||||
|
@ -112,19 +51,11 @@ impl ComputeSquaredDistance for RGBA {
|
|||
}
|
||||
|
||||
/// An animated value for `<color>`.
|
||||
pub type Color = GenericColor<RGBA, Percentage>;
|
||||
pub type Color = GenericColor<Percentage>;
|
||||
|
||||
/// An animated value for `<color-mix>`.
|
||||
pub type ColorMix = GenericColorMix<Color, Percentage>;
|
||||
|
||||
impl Color {
|
||||
fn to_rgba(&self, current_color: RGBA) -> RGBA {
|
||||
let mut clone = self.clone();
|
||||
clone.simplify(Some(¤t_color));
|
||||
*clone.as_numeric().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Animate for Color {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
|
@ -146,15 +77,16 @@ impl Animate for Color {
|
|||
impl ComputeSquaredDistance for Color {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
let current_color = RGBA::transparent();
|
||||
self.to_rgba(current_color)
|
||||
.compute_squared_distance(&other.to_rgba(current_color))
|
||||
let current_color = AbsoluteColor::transparent();
|
||||
self.clone()
|
||||
.resolve_into_absolute(¤t_color)
|
||||
.compute_squared_distance(&other.clone().resolve_into_absolute(¤t_color))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnimatedZero for Color {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
Ok(Color::rgba(RGBA::transparent()))
|
||||
Ok(Color::Absolute(AbsoluteColor::transparent()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//! computed values and need yet another intermediate representation. This
|
||||
//! module's raison d'être is to ultimately contain all these types.
|
||||
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::properties::PropertyId;
|
||||
use crate::values::computed::length::LengthPercentage;
|
||||
use crate::values::computed::url::ComputedUrl;
|
||||
|
@ -380,6 +381,7 @@ trivial_to_animated_value!(ComputedUrl);
|
|||
trivial_to_animated_value!(bool);
|
||||
trivial_to_animated_value!(f32);
|
||||
trivial_to_animated_value!(i32);
|
||||
trivial_to_animated_value!(AbsoluteColor);
|
||||
// Note: This implementation is for ToAnimatedValue of ShapeSource.
|
||||
//
|
||||
// SVGPathData uses Box<[T]>. If we want to derive ToAnimatedValue for all the
|
||||
|
|
|
@ -4,24 +4,24 @@
|
|||
|
||||
//! Computed color values.
|
||||
|
||||
use crate::values::animated::color::AnimatedRGBA;
|
||||
use crate::values::animated::ToAnimatedValue;
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::values::animated::ToAnimatedZero;
|
||||
use crate::values::computed::percentage::Percentage;
|
||||
use crate::values::generics::color::{GenericCaretColor, GenericColor, GenericColorOrAuto};
|
||||
use cssparser::{Color as CSSParserColor, RGBA};
|
||||
use cssparser::Color as CSSParserColor;
|
||||
use std::fmt;
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
pub use crate::values::specified::color::{ColorScheme, PrintColorAdjust, ForcedColorAdjust};
|
||||
pub use crate::values::specified::color::{ColorScheme, ForcedColorAdjust, PrintColorAdjust};
|
||||
|
||||
/// The computed value of the `color` property.
|
||||
pub type ColorPropertyValue = RGBA;
|
||||
pub type ColorPropertyValue = AbsoluteColor;
|
||||
|
||||
/// The computed value of `-moz-font-smoothing-background-color`.
|
||||
pub type MozFontSmoothingBackgroundColor = RGBA;
|
||||
pub type MozFontSmoothingBackgroundColor = AbsoluteColor;
|
||||
|
||||
/// A computed value for `<color>`.
|
||||
pub type Color = GenericColor<RGBA, Percentage>;
|
||||
pub type Color = GenericColor<Percentage>;
|
||||
|
||||
impl ToCss for Color {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
|
@ -29,7 +29,7 @@ impl ToCss for Color {
|
|||
W: fmt::Write,
|
||||
{
|
||||
match *self {
|
||||
Self::Numeric(ref c) => c.to_css(dest),
|
||||
Self::Absolute(ref c) => c.to_css(dest),
|
||||
Self::CurrentColor => cssparser::ToCss::to_css(&CSSParserColor::CurrentColor, dest),
|
||||
Self::ColorMix(ref m) => m.to_css(dest),
|
||||
}
|
||||
|
@ -39,44 +39,30 @@ impl ToCss for Color {
|
|||
impl Color {
|
||||
/// Returns a complex color value representing transparent.
|
||||
pub fn transparent() -> Color {
|
||||
Color::rgba(RGBA::transparent())
|
||||
Color::Absolute(AbsoluteColor::transparent())
|
||||
}
|
||||
|
||||
/// Returns opaque black.
|
||||
pub fn black() -> Color {
|
||||
Color::rgba(RGBA::new(0, 0, 0, 1.0))
|
||||
Color::Absolute(AbsoluteColor::black())
|
||||
}
|
||||
|
||||
/// Returns opaque white.
|
||||
pub fn white() -> Color {
|
||||
Color::rgba(RGBA::new(255, 255, 255, 1.0))
|
||||
Color::Absolute(AbsoluteColor::white())
|
||||
}
|
||||
|
||||
/// Combine this complex color with the given foreground color into
|
||||
/// a numeric RGBA color.
|
||||
pub fn into_rgba(mut self, current_color: RGBA) -> RGBA {
|
||||
/// Combine this complex color with the given foreground color into an
|
||||
/// absolute color.
|
||||
pub fn resolve_into_absolute(mut self, current_color: &AbsoluteColor) -> AbsoluteColor {
|
||||
self.simplify(Some(¤t_color));
|
||||
*self.as_numeric().unwrap()
|
||||
*self.as_absolute().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnimatedValue for RGBA {
|
||||
type AnimatedValue = AnimatedRGBA;
|
||||
|
||||
#[inline]
|
||||
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||
AnimatedRGBA::new(
|
||||
self.red_f32(),
|
||||
self.green_f32(),
|
||||
self.blue_f32(),
|
||||
self.alpha_f32(),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||
// RGBA::from_floats clamps each component values.
|
||||
RGBA::from_floats(animated.red, animated.green, animated.blue, animated.alpha)
|
||||
impl ToAnimatedZero for AbsoluteColor {
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
Ok(Self::transparent())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
use crate::color::mix::ColorInterpolationMethod;
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::values::animated::color::AnimatedRGBA;
|
||||
use crate::values::animated::ToAnimatedValue;
|
||||
use crate::values::specified::percentage::ToPercentage;
|
||||
use std::fmt::{self, Write};
|
||||
|
@ -16,9 +15,9 @@ use style_traits::{CssWriter, ToCss};
|
|||
/// the current foreground color (currentcolor keyword).
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToAnimatedValue, ToShmem)]
|
||||
#[repr(C)]
|
||||
pub enum GenericColor<RGBA, Percentage> {
|
||||
pub enum GenericColor<Percentage> {
|
||||
/// The actual numeric color.
|
||||
Numeric(RGBA),
|
||||
Absolute(AbsoluteColor),
|
||||
/// The `CurrentColor` keyword.
|
||||
CurrentColor,
|
||||
/// The color-mix() function.
|
||||
|
@ -92,17 +91,18 @@ impl<Color: ToCss, Percentage: ToCss + ToPercentage> ToCss for ColorMix<Color, P
|
|||
}
|
||||
}
|
||||
|
||||
impl<RGBA, Percentage> ColorMix<GenericColor<RGBA, Percentage>, Percentage> {
|
||||
fn to_rgba(&self) -> Option<RGBA>
|
||||
impl<Percentage> ColorMix<GenericColor<Percentage>, Percentage> {
|
||||
/// 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.
|
||||
fn mix_into_absolute(&self) -> Option<AbsoluteColor>
|
||||
where
|
||||
RGBA: Clone + ToAnimatedValue<AnimatedValue = AnimatedRGBA>,
|
||||
Percentage: ToPercentage,
|
||||
{
|
||||
let left = AbsoluteColor::from(self.left.as_numeric()?.clone().to_animated_value());
|
||||
let right = AbsoluteColor::from(self.right.as_numeric()?.clone().to_animated_value());
|
||||
let left = self.left.as_absolute()?.to_animated_value();
|
||||
let right = self.right.as_absolute()?.to_animated_value();
|
||||
|
||||
let mixed = crate::color::mix::mix(
|
||||
&self.interpolation,
|
||||
self.interpolation,
|
||||
&left,
|
||||
self.left_percentage.to_percentage(),
|
||||
&right,
|
||||
|
@ -116,36 +116,34 @@ impl<RGBA, Percentage> ColorMix<GenericColor<RGBA, Percentage>, Percentage> {
|
|||
|
||||
pub use self::GenericColor as Color;
|
||||
|
||||
impl<RGBA, Percentage> Color<RGBA, Percentage> {
|
||||
/// Returns the numeric rgba value if this color is numeric, or None
|
||||
/// otherwise.
|
||||
pub fn as_numeric(&self) -> Option<&RGBA> {
|
||||
impl<Percentage> Color<Percentage> {
|
||||
/// If this color is absolute return it's value, otherwise return None.
|
||||
pub fn as_absolute(&self) -> Option<&AbsoluteColor> {
|
||||
match *self {
|
||||
Self::Numeric(ref rgba) => Some(rgba),
|
||||
Self::Absolute(ref absolute) => Some(absolute),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Simplifies the color-mix()es to the extent possible given a current
|
||||
/// color (or not).
|
||||
pub fn simplify(&mut self, current_color: Option<&RGBA>)
|
||||
pub fn simplify(&mut self, current_color: Option<&AbsoluteColor>)
|
||||
where
|
||||
RGBA: Clone + ToAnimatedValue<AnimatedValue = AnimatedRGBA>,
|
||||
Percentage: ToPercentage,
|
||||
{
|
||||
match *self {
|
||||
Self::Numeric(..) => {},
|
||||
Self::Absolute(..) => {},
|
||||
Self::CurrentColor => {
|
||||
if let Some(c) = current_color {
|
||||
*self = Self::Numeric(c.clone());
|
||||
*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.to_rgba() {
|
||||
*self = Self::Numeric(mix);
|
||||
if let Some(mix) = mix.mix_into_absolute() {
|
||||
*self = Self::Absolute(mix);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -156,19 +154,14 @@ impl<RGBA, Percentage> Color<RGBA, Percentage> {
|
|||
Self::CurrentColor
|
||||
}
|
||||
|
||||
/// Returns a numeric color representing the given RGBA value.
|
||||
pub fn rgba(color: RGBA) -> Self {
|
||||
Self::Numeric(color)
|
||||
}
|
||||
|
||||
/// Whether it is a currentcolor value (no numeric color component).
|
||||
pub fn is_currentcolor(&self) -> bool {
|
||||
matches!(*self, Self::CurrentColor)
|
||||
}
|
||||
|
||||
/// Whether it is a numeric color (no currentcolor component).
|
||||
pub fn is_numeric(&self) -> bool {
|
||||
matches!(*self, Self::Numeric(..))
|
||||
/// Whether this color is an absolute color.
|
||||
pub fn is_absolute(&self) -> bool {
|
||||
matches!(*self, Self::Absolute(..))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
|
||||
use super::{Context, ToResolvedValue};
|
||||
|
||||
use crate::color::AbsoluteColor;
|
||||
use crate::values::computed::color as computed;
|
||||
use crate::values::generics::color as generics;
|
||||
|
||||
impl ToResolvedValue for computed::Color {
|
||||
// A resolved color value is an rgba color, with currentcolor resolved.
|
||||
type ResolvedValue = cssparser::RGBA;
|
||||
type ResolvedValue = AbsoluteColor;
|
||||
|
||||
#[inline]
|
||||
fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
|
||||
|
@ -20,14 +21,14 @@ impl ToResolvedValue for computed::Color {
|
|||
|
||||
#[inline]
|
||||
fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
|
||||
generics::Color::rgba(resolved)
|
||||
generics::Color::Absolute(resolved)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToResolvedValue for computed::CaretColor {
|
||||
// A resolved caret-color value is an rgba color, with auto resolving to
|
||||
// currentcolor.
|
||||
type ResolvedValue = cssparser::RGBA;
|
||||
type ResolvedValue = AbsoluteColor;
|
||||
|
||||
#[inline]
|
||||
fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
use crate::media_queries::Device;
|
||||
use crate::properties::ComputedValues;
|
||||
use crate::ArcSlice;
|
||||
use cssparser;
|
||||
use servo_arc::Arc;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -87,7 +86,7 @@ trivial_to_resolved_value!(usize);
|
|||
trivial_to_resolved_value!(String);
|
||||
trivial_to_resolved_value!(Box<str>);
|
||||
trivial_to_resolved_value!(crate::OwnedStr);
|
||||
trivial_to_resolved_value!(cssparser::RGBA);
|
||||
trivial_to_resolved_value!(crate::color::AbsoluteColor);
|
||||
trivial_to_resolved_value!(crate::Atom);
|
||||
trivial_to_resolved_value!(crate::values::AtomIdent);
|
||||
trivial_to_resolved_value!(app_units::Au);
|
||||
|
|
|
@ -106,32 +106,6 @@ impl ColorMix {
|
|||
}
|
||||
}
|
||||
|
||||
impl AbsoluteColor {
|
||||
/// Convenience function to create a color in the sRGB color space.
|
||||
pub fn from_rgba(rgba: RGBA) -> Self {
|
||||
let red = rgba.red as f32 / 255.0;
|
||||
let green = rgba.green as f32 / 255.0;
|
||||
let blue = rgba.blue as f32 / 255.0;
|
||||
|
||||
Self::new(
|
||||
ColorSpace::Srgb,
|
||||
ColorComponents(red, green, blue),
|
||||
rgba.alpha,
|
||||
)
|
||||
}
|
||||
|
||||
/// Convert the color to sRGB color space and return it in the RGBA struct.
|
||||
pub fn to_rgba(&self) -> RGBA {
|
||||
let rgba = self.to_color_space(ColorSpace::Srgb);
|
||||
|
||||
let red = (rgba.components.0 * 255.0).round() as u8;
|
||||
let green = (rgba.components.1 * 255.0).round() as u8;
|
||||
let blue = (rgba.components.2 * 255.0).round() as u8;
|
||||
|
||||
RGBA::new(red, green, blue, rgba.alpha)
|
||||
}
|
||||
}
|
||||
|
||||
/// Container holding an absolute color and the text specified by an author.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||
pub struct Absolute {
|
||||
|
@ -172,6 +146,13 @@ pub enum Color {
|
|||
InheritFromBodyQuirk,
|
||||
}
|
||||
|
||||
impl From<AbsoluteColor> for Color {
|
||||
#[inline]
|
||||
fn from(value: AbsoluteColor) -> Self {
|
||||
Self::from_absolute_color(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// System colors. A bunch of these are ad-hoc, others come from Windows:
|
||||
///
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsyscolor
|
||||
|
@ -413,7 +394,7 @@ pub enum SystemColor {
|
|||
impl SystemColor {
|
||||
#[inline]
|
||||
fn compute(&self, cx: &Context) -> ComputedColor {
|
||||
use crate::gecko::values::convert_nscolor_to_rgba;
|
||||
use crate::gecko::values::convert_nscolor_to_absolute_color;
|
||||
use crate::gecko_bindings::bindings;
|
||||
|
||||
// TODO: We should avoid cloning here most likely, though it's
|
||||
|
@ -423,13 +404,7 @@ impl SystemColor {
|
|||
if color == bindings::NS_SAME_AS_FOREGROUND_COLOR {
|
||||
return ComputedColor::currentcolor();
|
||||
}
|
||||
ComputedColor::rgba(convert_nscolor_to_rgba(color))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RGBA> for Color {
|
||||
fn from(value: RGBA) -> Self {
|
||||
Color::rgba(value)
|
||||
ComputedColor::Absolute(convert_nscolor_to_absolute_color(color))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,12 +686,12 @@ impl Color {
|
|||
pub fn honored_in_forced_colors_mode(&self, allow_transparent: bool) -> bool {
|
||||
match *self {
|
||||
#[cfg(feature = "gecko")]
|
||||
Color::InheritFromBodyQuirk => false,
|
||||
Color::CurrentColor => true,
|
||||
Self::InheritFromBodyQuirk => false,
|
||||
Self::CurrentColor => true,
|
||||
#[cfg(feature = "gecko")]
|
||||
Color::System(..) => true,
|
||||
Color::Absolute(ref absolute) => allow_transparent && absolute.color.alpha() == 0.0,
|
||||
Color::ColorMix(ref mix) => {
|
||||
Self::System(..) => true,
|
||||
Self::Absolute(ref absolute) => allow_transparent && absolute.color.alpha() == 0.0,
|
||||
Self::ColorMix(ref mix) => {
|
||||
mix.left.honored_in_forced_colors_mode(allow_transparent) &&
|
||||
mix.right.honored_in_forced_colors_mode(allow_transparent)
|
||||
},
|
||||
|
@ -725,22 +700,21 @@ impl Color {
|
|||
|
||||
/// Returns currentcolor value.
|
||||
#[inline]
|
||||
pub fn currentcolor() -> Color {
|
||||
Color::CurrentColor
|
||||
pub fn currentcolor() -> Self {
|
||||
Self::CurrentColor
|
||||
}
|
||||
|
||||
/// Returns transparent value.
|
||||
#[inline]
|
||||
pub fn transparent() -> Color {
|
||||
pub fn transparent() -> Self {
|
||||
// We should probably set authored to "transparent", but maybe it doesn't matter.
|
||||
Color::rgba(RGBA::transparent())
|
||||
Self::from_absolute_color(AbsoluteColor::transparent())
|
||||
}
|
||||
|
||||
/// Returns an absolute RGBA color value.
|
||||
#[inline]
|
||||
pub fn rgba(rgba: RGBA) -> Self {
|
||||
/// Create a color from an [`AbsoluteColor`].
|
||||
pub fn from_absolute_color(color: AbsoluteColor) -> Self {
|
||||
Color::Absolute(Box::new(Absolute {
|
||||
color: AbsoluteColor::from_rgba(rgba),
|
||||
color,
|
||||
authored: None,
|
||||
}))
|
||||
}
|
||||
|
@ -758,7 +732,14 @@ impl Color {
|
|||
return Err(e);
|
||||
}
|
||||
Color::parse_quirky_color(input)
|
||||
.map(Color::rgba)
|
||||
.map(|rgba| {
|
||||
Color::from_absolute_color(AbsoluteColor::srgb(
|
||||
rgba.red as f32 / 255.0,
|
||||
rgba.green as f32 / 255.0,
|
||||
rgba.blue as f32 / 255.0,
|
||||
rgba.alpha, // alpha value is already a float and in range [0..1]
|
||||
))
|
||||
})
|
||||
.map_err(|_| e)
|
||||
})
|
||||
}
|
||||
|
@ -840,7 +821,7 @@ impl Color {
|
|||
pub fn to_computed_color(&self, context: Option<&Context>) -> Option<ComputedColor> {
|
||||
Some(match *self {
|
||||
Color::CurrentColor => ComputedColor::CurrentColor,
|
||||
Color::Absolute(ref absolute) => ComputedColor::Numeric(absolute.color.to_rgba()),
|
||||
Color::Absolute(ref absolute) => ComputedColor::Absolute(absolute.color),
|
||||
Color::ColorMix(ref mix) => {
|
||||
use crate::values::computed::percentage::Percentage;
|
||||
|
||||
|
@ -860,7 +841,9 @@ impl Color {
|
|||
#[cfg(feature = "gecko")]
|
||||
Color::System(system) => system.compute(context?),
|
||||
#[cfg(feature = "gecko")]
|
||||
Color::InheritFromBodyQuirk => ComputedColor::rgba(context?.device().body_text_color()),
|
||||
Color::InheritFromBodyQuirk => {
|
||||
ComputedColor::Absolute(context?.device().body_text_color())
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -874,7 +857,7 @@ impl ToComputedValue for Color {
|
|||
|
||||
fn from_computed_value(computed: &ComputedColor) -> Self {
|
||||
match *computed {
|
||||
ComputedColor::Numeric(ref color) => Color::rgba(*color),
|
||||
ComputedColor::Absolute(ref color) => Self::from_absolute_color(color.clone()),
|
||||
ComputedColor::CurrentColor => Color::CurrentColor,
|
||||
ComputedColor::ColorMix(ref mix) => {
|
||||
Color::ColorMix(Box::new(ToComputedValue::from_computed_value(&**mix)))
|
||||
|
@ -902,16 +885,16 @@ impl Parse for MozFontSmoothingBackgroundColor {
|
|||
}
|
||||
|
||||
impl ToComputedValue for MozFontSmoothingBackgroundColor {
|
||||
type ComputedValue = RGBA;
|
||||
type ComputedValue = AbsoluteColor;
|
||||
|
||||
fn to_computed_value(&self, context: &Context) -> RGBA {
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
self.0
|
||||
.to_computed_value(context)
|
||||
.into_rgba(RGBA::transparent())
|
||||
.resolve_into_absolute(&AbsoluteColor::transparent())
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &RGBA) -> Self {
|
||||
MozFontSmoothingBackgroundColor(Color::rgba(*computed))
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
MozFontSmoothingBackgroundColor(Color::from_absolute_color(*computed))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -949,18 +932,19 @@ impl SpecifiedValueInfo for Color {
|
|||
pub struct ColorPropertyValue(pub Color);
|
||||
|
||||
impl ToComputedValue for ColorPropertyValue {
|
||||
type ComputedValue = RGBA;
|
||||
type ComputedValue = AbsoluteColor;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> RGBA {
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
let current_color = context.builder.get_parent_inherited_text().clone_color();
|
||||
self.0
|
||||
.to_computed_value(context)
|
||||
.into_rgba(context.builder.get_parent_inherited_text().clone_color())
|
||||
.resolve_into_absolute(¤t_color)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &RGBA) -> Self {
|
||||
ColorPropertyValue(Color::rgba(*computed).into())
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
ColorPropertyValue(Color::from_absolute_color(*computed).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -501,7 +501,6 @@ impl_to_css_for_predefined_type!(i8);
|
|||
impl_to_css_for_predefined_type!(i32);
|
||||
impl_to_css_for_predefined_type!(u16);
|
||||
impl_to_css_for_predefined_type!(u32);
|
||||
impl_to_css_for_predefined_type!(::cssparser::RGBA);
|
||||
impl_to_css_for_predefined_type!(::cssparser::Token<'a>);
|
||||
impl_to_css_for_predefined_type!(::cssparser::UnicodeRange);
|
||||
|
||||
|
|
|
@ -224,7 +224,6 @@ impl_trivial_to_shmem!(
|
|||
usize
|
||||
);
|
||||
|
||||
impl_trivial_to_shmem!(cssparser::RGBA);
|
||||
impl_trivial_to_shmem!(cssparser::SourceLocation);
|
||||
impl_trivial_to_shmem!(cssparser::TokenSerializationType);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue