diff options
40 files changed, 817 insertions, 689 deletions
diff --git a/Cargo.lock b/Cargo.lock index 38414c4669a..217bc8c7dec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1419,7 +1419,6 @@ dependencies = [ "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "canvas_traits 0.0.1", - "cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index 763ac1288a4..e9679887da6 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -14,7 +14,6 @@ app_units = "0.4.1" atomic_refcell = "0.1" bitflags = "0.7" canvas_traits = {path = "../canvas_traits"} -cssparser = "0.13.7" euclid = "0.13" fnv = "1.0" gfx = {path = "../gfx"} diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 6794d144a47..4a7f2814cbf 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -422,8 +422,7 @@ pub trait FragmentDisplayListBuilding { bounds: &Rect<Au>, stops: &[GradientItem], direction: &LineDirection, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::Gradient; fn convert_radial_gradient(&self, @@ -431,8 +430,7 @@ pub trait FragmentDisplayListBuilding { stops: &[GradientItem], shape: &EndingShape, center: &Position, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::RadialGradient; /// Adds the display items necessary to paint the background linear gradient of this fragment @@ -634,8 +632,7 @@ fn build_border_radius_for_inner_rect(outer_rect: &Rect<Au>, } fn convert_gradient_stops(gradient_items: &[GradientItem], - total_length: Au, - style: &ServoComputedValues) -> Vec<GradientStop> { + total_length: Au) -> Vec<GradientStop> { // Determine the position of each stop per CSS-IMAGES § 3.4. // Only keep the color stops, discard the color interpolation hints. @@ -722,7 +719,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem], }; stops.push(GradientStop { offset: offset, - color: style.resolve_color(stop.color).to_gfx_color() + color: stop.color.to_gfx_color() }) } stops @@ -1192,8 +1189,7 @@ impl FragmentDisplayListBuilding for Fragment { bounds: &Rect<Au>, stops: &[GradientItem], direction: &LineDirection, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::Gradient { let angle = match *direction { LineDirection::Angle(angle) => angle.radians(), @@ -1234,7 +1230,7 @@ impl FragmentDisplayListBuilding for Fragment { let length = Au::from_f32_px( (delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); - let mut stops = convert_gradient_stops(stops, length, style); + let mut stops = convert_gradient_stops(stops, length); // Only clamped gradients need to be fixed because in repeating gradients // there is no "first" or "last" stop because they repeat infinitly in @@ -1258,8 +1254,7 @@ impl FragmentDisplayListBuilding for Fragment { stops: &[GradientItem], shape: &EndingShape, center: &Position, - repeating: bool, - style: &ServoComputedValues) + repeating: bool) -> display_list::RadialGradient { let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width), center.vertical.to_used_value(bounds.size.height)); @@ -1278,7 +1273,7 @@ impl FragmentDisplayListBuilding for Fragment { }, }; - let mut stops = convert_gradient_stops(stops, radius.width, style); + let mut stops = convert_gradient_stops(stops, radius.width); // Repeating gradients have no last stops that can be ignored. So // fixup is not necessary but may actually break the gradient. if !repeating { @@ -1322,8 +1317,7 @@ impl FragmentDisplayListBuilding for Fragment { let gradient = self.convert_linear_gradient(&bounds, &gradient.items[..], angle_or_corner, - gradient.repeating, - style); + gradient.repeating); DisplayItem::Gradient(box GradientDisplayItem { base: base, gradient: gradient, @@ -1334,8 +1328,7 @@ impl FragmentDisplayListBuilding for Fragment { &gradient.items[..], shape, center, - gradient.repeating, - style); + gradient.repeating); DisplayItem::RadialGradient(box RadialGradientDisplayItem { base: base, gradient: gradient, @@ -1459,8 +1452,7 @@ impl FragmentDisplayListBuilding for Fragment { let grad = self.convert_linear_gradient(&bounds, &gradient.items[..], &angle_or_corner, - gradient.repeating, - style); + gradient.repeating); state.add_display_item(DisplayItem::Border(box BorderDisplayItem { base: base, @@ -1478,8 +1470,7 @@ impl FragmentDisplayListBuilding for Fragment { &gradient.items[..], shape, center, - gradient.repeating, - style); + gradient.repeating); state.add_display_item(DisplayItem::Border(box BorderDisplayItem { base: base, border_widths: border.to_physical(style.writing_mode), diff --git a/components/layout/lib.rs b/components/layout/lib.rs index 65923c10554..ca85d83e9d1 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -16,7 +16,6 @@ extern crate atomic_refcell; extern crate bitflags; extern crate canvas_traits; extern crate core; -extern crate cssparser; extern crate euclid; extern crate fnv; extern crate gfx; diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 8c54297d4b5..47f74891488 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -9,7 +9,6 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use context::LayoutContext; -use cssparser::Color; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use flow::{self, Flow, FlowClass, IS_ABSOLUTELY_POSITIONED, OpaqueFlow}; @@ -22,6 +21,7 @@ use std::fmt; use style::computed_values::{border_collapse, border_top_style, vertical_align}; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; use style::properties::ServoComputedValues; +use style::values::computed::Color; use table::InternalTable; use table_row::{CollapsedBorder, CollapsedBorderProvenance}; diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 8d074f59c52..2fb61a336de 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -9,7 +9,6 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer}; use context::LayoutContext; -use cssparser::{Color, RGBA}; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState}; use euclid::Point2D; use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; @@ -26,7 +25,7 @@ use style::computed_values::{border_collapse, border_spacing, border_top_style}; use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode}; use style::properties::ServoComputedValues; use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW}; -use style::values::computed::LengthOrPercentageOrAuto; +use style::values::computed::{Color, LengthOrPercentageOrAuto}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt}; use table_cell::{CollapsedBordersForCell, TableCellFlow}; @@ -606,7 +605,7 @@ impl CollapsedBorder { CollapsedBorder { style: border_top_style::T::none, width: Au(0), - color: Color::RGBA(RGBA::transparent()), + color: Color::transparent(), provenance: CollapsedBorderProvenance::FromTable, } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index cb882f53463..189410ce77a 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -4,7 +4,6 @@ //! Element nodes. -use cssparser::Color; use devtools_traits::AttrInfo; use dom::activation::Activatable; use dom::attr::{Attr, AttrHelpersForLayout}; @@ -113,7 +112,7 @@ use style::stylearc::Arc; use style::stylist::ApplicableDeclarationBlock; use style::thread_state; use style::values::{CSSFloat, Either}; -use style::values::specified::{self, CSSColor}; +use style::values::specified; use stylesheet_loader::StylesheetOwner; // TODO: Update focus state when the top-level browsing context gains or loses system focus, @@ -422,8 +421,8 @@ impl LayoutElementHelpers for LayoutJS<Element> { if let Some(color) = bgcolor { hints.push(from_declaration( shared_lock, - PropertyDeclaration::BackgroundColor( - CSSColor { parsed: Color::RGBA(color), authored: None }))); + PropertyDeclaration::BackgroundColor(color.into()) + )); } let background = if let Some(this) = self.downcast::<HTMLBodyElement>() { @@ -457,10 +456,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { hints.push(from_declaration( shared_lock, PropertyDeclaration::Color( - longhands::color::SpecifiedValue(CSSColor { - parsed: Color::RGBA(color), - authored: None, - }) + longhands::color::SpecifiedValue(color.into()) ) )); } diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 9f222690404..4266c61826a 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -183,7 +183,6 @@ impl nsStyleImage { } fn set_gradient(&mut self, gradient: Gradient) { - use cssparser::Color as CSSColor; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_CIRCULAR, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL}; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER}; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE}; @@ -321,19 +320,7 @@ impl nsStyleImage { match *item { GradientItem::ColorStop(ref stop) => { - gecko_stop.mColor = match stop.color { - CSSColor::CurrentColor => { - // TODO(emilio): gecko just stores an nscolor, - // and it doesn't seem to support currentColor - // as value in a gradient. - // - // Double-check it and either remove - // currentColor for servo or see how gecko - // handles this. - 0 - }, - CSSColor::RGBA(ref rgba) => convert_rgba_to_nscolor(rgba), - }; + gecko_stop.mColor = convert_rgba_to_nscolor(&stop.color); gecko_stop.mIsInterpolationHint = false; coord.set(stop.position); }, diff --git a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs index 003da073b23..fe818d71330 100644 --- a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs +++ b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs @@ -5,10 +5,9 @@ //! Rust helpers for Gecko's `nsCSSShadowItem`. use app_units::Au; -use cssparser::Color; use gecko::values::{convert_rgba_to_nscolor, convert_nscolor_to_rgba}; use gecko_bindings::structs::nsCSSShadowItem; -use values::computed::Shadow; +use values::computed::{Color, Shadow}; impl nsCSSShadowItem { /// Set this item to the given shadow value. @@ -18,14 +17,14 @@ impl nsCSSShadowItem { self.mRadius = other.blur_radius.0; self.mSpread = other.spread_radius.0; self.mInset = other.inset; - self.mColor = match other.color { - Color::RGBA(rgba) => { - self.mHasColor = true; - convert_rgba_to_nscolor(&rgba) - }, + if other.color.is_currentcolor() { // TODO handle currentColor // https://bugzilla.mozilla.org/show_bug.cgi?id=760345 - Color::CurrentColor => 0, + self.mHasColor = false; + self.mColor = 0; + } else { + self.mHasColor = true; + self.mColor = convert_rgba_to_nscolor(&other.color.color); } } @@ -37,7 +36,7 @@ impl nsCSSShadowItem { blur_radius: Au(self.mRadius), spread_radius: Au(self.mSpread), inset: self.mInset, - color: Color::RGBA(convert_nscolor_to_rgba(self.mColor)), + color: Color::rgba(convert_nscolor_to_rgba(self.mColor)), } } } diff --git a/components/style/gecko_bindings/sugar/style_complex_color.rs b/components/style/gecko_bindings/sugar/style_complex_color.rs index 47d9046e874..cd0e408b26f 100644 --- a/components/style/gecko_bindings/sugar/style_complex_color.rs +++ b/components/style/gecko_bindings/sugar/style_complex_color.rs @@ -4,10 +4,10 @@ //! Rust helpers to interact with Gecko's StyleComplexColor. -use cssparser; use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; use gecko_bindings::structs::{nscolor, StyleComplexColor}; -use values; +use values::{Auto, Either}; +use values::computed::Color as ComputedColor; impl From<nscolor> for StyleComplexColor { fn from(other: nscolor) -> Self { @@ -39,40 +39,41 @@ impl StyleComplexColor { } } -impl From<cssparser::Color> for StyleComplexColor { - fn from(other: cssparser::Color) -> Self { - use cssparser::Color; - - match other { - Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba).into(), - Color::CurrentColor => StyleComplexColor::current_color(), +impl From<ComputedColor> for StyleComplexColor { + fn from(other: ComputedColor) -> Self { + StyleComplexColor { + mColor: convert_rgba_to_nscolor(&other.color).into(), + mForegroundRatio: other.foreground_ratio, + mIsAuto: false, } } } -impl From<StyleComplexColor> for values::computed::ColorOrAuto { - fn from(color: StyleComplexColor) -> Self { - use values::{Auto, Either}; - - if color.mIsAuto { - return Either::Second(Auto); +impl From<StyleComplexColor> for ComputedColor { + fn from(other: StyleComplexColor) -> Self { + debug_assert!(!other.mIsAuto); + ComputedColor { + color: convert_nscolor_to_rgba(other.mColor), + foreground_ratio: other.mForegroundRatio, } + } +} - Either::First(color.into()) +impl From<Either<ComputedColor, Auto>> for StyleComplexColor { + fn from(other: Either<ComputedColor, Auto>) -> Self { + match other { + Either::First(color) => color.into(), + Either::Second(_auto) => StyleComplexColor::auto(), + } } } -impl From<StyleComplexColor> for cssparser::Color { +impl From<StyleComplexColor> for Either<ComputedColor, Auto> { fn from(other: StyleComplexColor) -> Self { - use cssparser::Color; - - if other.mForegroundRatio == 0 { - Color::RGBA(convert_nscolor_to_rgba(other.mColor)) - } else if other.mForegroundRatio == 255 { - Color::CurrentColor + if !other.mIsAuto { + Either::First(other.into()) } else { - // FIXME #13546 handle interpolation values - Color::CurrentColor + Either::Second(Auto) } } } diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 06735ef888b..15d9f2fc89a 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -148,7 +148,7 @@ class Longhand(object): def __init__(self, style_struct, name, spec=None, animation_value_type=None, derived_from=None, keyword=None, predefined_type=None, custom_cascade=False, experimental=False, internal=False, need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False, - allowed_in_keyframe_block=True, complex_color=False, cast_type='u8', + allowed_in_keyframe_block=True, cast_type='u8', has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False, flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False, vector=False): @@ -169,7 +169,6 @@ class Longhand(object): self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case self.depend_on_viewport_size = depend_on_viewport_size self.derived_from = (derived_from or "").split() - self.complex_color = complex_color self.cast_type = cast_type self.logical = arg_to_bool(logical) self.alias = alias.split() if alias else [] diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 3c0b57c9fe0..0df0ee4bde6 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -11,7 +11,6 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> use app_units::Au; -use cssparser::Color; use custom_properties::ComputedValuesMap; use gecko_bindings::bindings; % for style_struct in data.style_structs: @@ -43,7 +42,7 @@ use gecko_bindings::bindings::Gecko_SetNullImageValue; use gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull; use gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom}; use gecko_bindings::bindings::RawGeckoPresContextBorrowed; -use gecko_bindings::structs::{self, StyleComplexColor}; +use gecko_bindings::structs; use gecko_bindings::structs::nsCSSPropertyID; use gecko_bindings::structs::nsStyleVariables; use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut}; @@ -316,32 +315,15 @@ def set_gecko_property(ffi_name, expr): } </%def> -/// Convert a Servo color into an nscolor; with currentColor as 0 -/// -/// Call sites will need to be updated after https://bugzilla.mozilla.org/show_bug.cgi?id=760345 -fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { - match color { - Color::RGBA(rgba) => { - convert_rgba_to_nscolor(&rgba) - }, - Color::CurrentColor => 0, - } -} - -<%def name="impl_color_setter(ident, gecko_ffi_name, complex_color=True)"> +<%def name="impl_color_setter(ident, gecko_ffi_name)"> #[allow(unreachable_code)] #[allow(non_snake_case)] pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - % if complex_color: - let result = v.into(); - % else: - let result = color_to_nscolor_zero_currentcolor(v); - % endif - ${set_gecko_property(gecko_ffi_name, "result")} + ${set_gecko_property(gecko_ffi_name, "v.into()")} } </%def> -<%def name="impl_color_copy(ident, gecko_ffi_name, complex_color=True)"> +<%def name="impl_color_copy(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn copy_${ident}_from(&mut self, other: &Self) { let color = ${get_gecko_property(gecko_ffi_name, self_param = "other")}; @@ -349,14 +331,10 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { } </%def> -<%def name="impl_color_clone(ident, gecko_ffi_name, complex_color=True)"> +<%def name="impl_color_clone(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - % if complex_color: - ${get_gecko_property(gecko_ffi_name)}.into() - % else: - Color::RGBA(convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})) - % endif + ${get_gecko_property(gecko_ffi_name)}.into() } </%def> @@ -408,15 +386,29 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { % endif </%def> -<%def name="impl_color(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> -<%call expr="impl_color_setter(ident, gecko_ffi_name, complex_color)"></%call> -<%call expr="impl_color_copy(ident, gecko_ffi_name, complex_color)"></%call> +<%def name="impl_color(ident, gecko_ffi_name, need_clone=False)"> +<%call expr="impl_color_setter(ident, gecko_ffi_name)"></%call> +<%call expr="impl_color_copy(ident, gecko_ffi_name)"></%call> % if need_clone: - <%call expr="impl_color_clone(ident, gecko_ffi_name, complex_color)"></%call> + <%call expr="impl_color_clone(ident, gecko_ffi_name)"></%call> % endif </%def> -<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> +<%def name="impl_rgba_color(ident, gecko_ffi_name, need_clone=False)"> + #[allow(non_snake_case)] + pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { + ${set_gecko_property(gecko_ffi_name, "convert_rgba_to_nscolor(&v)")} + } + <%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call> + % if need_clone: + #[allow(non_snake_case)] + pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { + convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)}) + } + % endif +</%def> + +<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { use values::generics::SVGPaintKind; @@ -444,14 +436,14 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { SVGPaintKind::Color(color) => { paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color; unsafe { - *paint.mPaint.mColor.as_mut() = color_to_nscolor_zero_currentcolor(color); + *paint.mPaint.mColor.as_mut() = convert_rgba_to_nscolor(&color); } } } if let Some(fallback) = fallback { paint.mFallbackType = nsStyleSVGFallbackType::eStyleSVGFallbackType_Color; - paint.mFallbackColor = color_to_nscolor_zero_currentcolor(fallback); + paint.mFallbackColor = convert_rgba_to_nscolor(&fallback); } } @@ -472,7 +464,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { use self::structs::nsStyleSVGFallbackType; let ref paint = ${get_gecko_property(gecko_ffi_name)}; let fallback = if let nsStyleSVGFallbackType::eStyleSVGFallbackType_Color = paint.mFallbackType { - Some(Color::RGBA(convert_nscolor_to_rgba(paint.mFallbackColor))) + Some(convert_nscolor_to_rgba(paint.mFallbackColor)) } else { None }; @@ -485,7 +477,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { SVGPaintKind::None } nsStyleSVGPaintType::eStyleSVGPaintType_Color => { - unsafe { SVGPaintKind::Color(Color::RGBA(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref()))) } + unsafe { SVGPaintKind::Color(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref())) } } }; SVGPaint { @@ -716,7 +708,8 @@ impl Debug for ${style_struct.gecko_struct_name} { "Number": impl_simple, "Integer": impl_simple, "Opacity": impl_simple, - "CSSColor": impl_color, + "Color": impl_color, + "RGBAColor": impl_rgba_color, "SVGPaint": impl_svg_paint, "UrlOrNone": impl_css_url, } @@ -736,8 +729,6 @@ impl Debug for ${style_struct.gecko_struct_name} { args.update(cast_type=longhand.cast_type) else: method = predefined_types[longhand.predefined_type] - if longhand.predefined_type in ["CSSColor"]: - args.update(complex_color=longhand.complex_color) method(**args) @@ -948,7 +939,7 @@ fn static_assert() { structs::Side::eSide${to_camel_case(side.ident)}); } for color in colors { - let c = color_to_nscolor_zero_currentcolor(*color); + let c = convert_rgba_to_nscolor(color); unsafe { bindings::Gecko_AppendMozBorderColors(&mut self.gecko, structs::Side::eSide${to_camel_case(side.ident)}, @@ -4268,25 +4259,7 @@ clip-path } } - pub fn set_caret_color(&mut self, v: longhands::caret_color::computed_value::T){ - use values::Either; - - match v { - Either::First(color) => { - self.gecko.mCaretColor = StyleComplexColor::from(color); - } - Either::Second(_auto) => { - self.gecko.mCaretColor = StyleComplexColor::auto(); - } - } - } - - pub fn copy_caret_color_from(&mut self, other: &Self){ - self.gecko.mCaretColor = other.gecko.mCaretColor; - } - - <%call expr="impl_color_clone('caret_color', 'mCaretColor')"></%call> - + <%call expr="impl_color('caret_color', 'mCaretColor', need_clone=True)"></%call> </%self:impl_trait> <%self:impl_trait style_struct_name="Column" diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 4ba7e6b505a..41501e5ddd8 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -7,7 +7,7 @@ <% from data import SYSTEM_FONT_LONGHANDS %> use app_units::Au; -use cssparser::{Color as CSSParserColor, Parser, RGBA, serialize_identifier}; +use cssparser::{Parser, RGBA, serialize_identifier}; use euclid::{Point2D, Size2D}; #[cfg(feature = "gecko")] use gecko_bindings::bindings::RawServoAnimationValueMap; #[cfg(feature = "gecko")] use gecko_bindings::structs::RawGeckoGfxMatrix4x4; @@ -38,7 +38,7 @@ use values::CSSFloat; use values::{Auto, Either}; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::{BorderCornerRadius, ClipRect}; -use values::computed::{CalcLengthOrPercentage, Context, ComputedValueAsSpecified}; +use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified}; use values::computed::{LengthOrPercentage, MaxLength, MozLength, Shadow, ToComputedValue}; use values::generics::{SVGPaint, SVGPaintKind}; use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; @@ -2721,38 +2721,19 @@ impl Animatable for IntermediateRGBA { } } -impl From<Either<CSSParserColor, Auto>> for Either<IntermediateColor, Auto> { - fn from(from: Either<CSSParserColor, Auto>) -> Either<IntermediateColor, Auto> { +impl From<Either<Color, Auto>> for Either<IntermediateColor, Auto> { + fn from(from: Either<Color, Auto>) -> Either<IntermediateColor, Auto> { match from { - Either::First(from) => - match from { - CSSParserColor::RGBA(color) => - Either::First(IntermediateColor::IntermediateRGBA( - IntermediateRGBA::new(color.red_f32(), - color.green_f32(), - color.blue_f32(), - color.alpha_f32()))), - CSSParserColor::CurrentColor => - Either::First(IntermediateColor::CurrentColor), - }, + Either::First(from) => Either::First(from.into()), Either::Second(Auto) => Either::Second(Auto), } } } -impl From<Either<IntermediateColor, Auto>> for Either<CSSParserColor, Auto> { - fn from(from: Either<IntermediateColor, Auto>) -> Either<CSSParserColor, Auto> { +impl From<Either<IntermediateColor, Auto>> for Either<Color, Auto> { + fn from(from: Either<IntermediateColor, Auto>) -> Either<Color, Auto> { match from { - Either::First(from) => - match from { - IntermediateColor::IntermediateRGBA(color) => - Either::First(CSSParserColor::RGBA(RGBA::from_floats(color.red, - color.green, - color.blue, - color.alpha))), - IntermediateColor::CurrentColor => - Either::First(CSSParserColor::CurrentColor), - }, + Either::First(from) => Either::First(from.into()), Either::Second(Auto) => Either::Second(Auto), } } @@ -2761,22 +2742,89 @@ impl From<Either<IntermediateColor, Auto>> for Either<CSSParserColor, Auto> { #[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] -pub enum IntermediateColor { - CurrentColor, - IntermediateRGBA(IntermediateRGBA), +pub struct IntermediateColor { + color: IntermediateRGBA, + foreground_ratio: f32, +} + +impl IntermediateColor { + fn currentcolor() -> Self { + IntermediateColor { + color: IntermediateRGBA::transparent(), + foreground_ratio: 1., + } + } + + fn transparent() -> Self { + IntermediateColor { + color: IntermediateRGBA::transparent(), + foreground_ratio: 0., + } + } + + fn is_currentcolor(&self) -> bool { + self.foreground_ratio >= 1. + } + + fn is_numeric(&self) -> bool { + self.foreground_ratio <= 0. + } + + fn effective_intermediate_rgba(&self) -> IntermediateRGBA { + IntermediateRGBA { + alpha: self.color.alpha * (1. - self.foreground_ratio), + .. self.color + } + } } impl Animatable for IntermediateColor { #[inline] fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { - match (*self, *other) { - (IntermediateColor::IntermediateRGBA(ref this), - IntermediateColor::IntermediateRGBA(ref other)) => { - this.add_weighted(other, self_portion, other_portion) - .map(IntermediateColor::IntermediateRGBA) + // Common cases are interpolating between two numeric colors, + // two currentcolors, and a numeric color and a currentcolor. + // + // Note: this algorithm assumes self_portion + other_portion + // equals to one, so it may be broken for additive operation. + // To properly support additive color interpolation, we would + // need two ratio fields in computed color types. + if self.foreground_ratio == other.foreground_ratio { + if self.is_currentcolor() { + Ok(IntermediateColor::currentcolor()) + } else { + Ok(IntermediateColor { + color: self.color.add_weighted(&other.color, self_portion, other_portion)?, + foreground_ratio: self.foreground_ratio, + }) } - // FIXME: Bug 1345709: Implement currentColor animations. - _ => Err(()), + } else if self.is_currentcolor() && other.is_numeric() { + Ok(IntermediateColor { + color: other.color, + foreground_ratio: self_portion as f32, + }) + } else if self.is_numeric() && other.is_currentcolor() { + Ok(IntermediateColor { + color: self.color, + foreground_ratio: other_portion as f32, + }) + } else { + // For interpolating between two complex colors, we need to + // generate colors with effective alpha value. + let self_color = self.effective_intermediate_rgba(); + let other_color = other.effective_intermediate_rgba(); + let color = self_color.add_weighted(&other_color, self_portion, other_portion)?; + // Then we compute the final foreground ratio, and derive + // the final alpha value from the effective alpha value. + let foreground_ratio = self.foreground_ratio + .add_weighted(&other.foreground_ratio, self_portion, other_portion)?; + let alpha = color.alpha / (1. - foreground_ratio); + Ok(IntermediateColor { + color: IntermediateRGBA { + alpha: alpha, + .. color + }, + foreground_ratio: foreground_ratio, + }) } } @@ -2787,45 +2835,49 @@ impl Animatable for IntermediateColor { #[inline] fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> { - match (*self, *other) { - (IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(ref other)) => { - this.compute_squared_distance(other) - }, - _ => Ok(0.0), + // All comments in add_weighted also applies here. + if self.foreground_ratio == other.foreground_ratio { + if self.is_currentcolor() { + Ok(0.) + } else { + self.color.compute_squared_distance(&other.color) + } + } else if self.is_currentcolor() && other.is_numeric() { + Ok(IntermediateRGBA::transparent().compute_squared_distance(&other.color)? + 1.) + } else if self.is_numeric() && other.is_currentcolor() { + Ok(self.color.compute_squared_distance(&IntermediateRGBA::transparent())? + 1.) + } else { + let self_color = self.effective_intermediate_rgba(); + let other_color = other.effective_intermediate_rgba(); + let dist = self_color.compute_squared_distance(&other_color)?; + let ratio_diff = (self.foreground_ratio - other.foreground_ratio) as f64; + Ok(dist + ratio_diff * ratio_diff) } } } -impl From<CSSParserColor> for IntermediateColor { - fn from(color: CSSParserColor) -> IntermediateColor { - match color { - CSSParserColor::RGBA(color) => - IntermediateColor::IntermediateRGBA(IntermediateRGBA::new(color.red_f32(), - color.green_f32(), - color.blue_f32(), - color.alpha_f32())), - CSSParserColor::CurrentColor => IntermediateColor::CurrentColor, +impl From<Color> for IntermediateColor { + fn from(color: Color) -> IntermediateColor { + IntermediateColor { + color: color.color.into(), + foreground_ratio: color.foreground_ratio as f32 * (1. / 255.), } } } -impl From<IntermediateColor> for CSSParserColor { - fn from(color: IntermediateColor) -> CSSParserColor { - match color { - IntermediateColor::IntermediateRGBA(color) => - CSSParserColor::RGBA(RGBA::from_floats(color.red, - color.green, - color.blue, - color.alpha)), - IntermediateColor::CurrentColor => CSSParserColor::CurrentColor, +impl From<IntermediateColor> for Color { + fn from(color: IntermediateColor) -> Color { + Color { + color: color.color.into(), + foreground_ratio: (color.foreground_ratio * 255.).round() as u8, } } } /// Animatable SVGPaint -pub type IntermediateSVGPaint = SVGPaint<IntermediateColor>; +pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>; /// Animatable SVGPaintKind -pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateColor>; +pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateRGBA>; impl From<::values::computed::SVGPaint> for IntermediateSVGPaint { fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint { @@ -3024,7 +3076,7 @@ impl Animatable for IntermediateShadowList { offset_y: Au(0), blur_radius: Au(0), spread_radius: Au(0), - color: IntermediateColor::IntermediateRGBA(IntermediateRGBA::transparent()), + color: IntermediateColor::transparent(), inset: false, }; diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 4937a2569b0..9b799c220b9 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -6,12 +6,11 @@ <% data.new_style_struct("Background", inherited=False) %> -${helpers.predefined_type("background-color", "CSSColor", - "::cssparser::Color::RGBA(::cssparser::RGBA::transparent())", +${helpers.predefined_type("background-color", "Color", + "computed_value::T::transparent()", initial_specified_value="SpecifiedValue::transparent()", spec="https://drafts.csswg.org/css-backgrounds/#background-color", animation_value_type="IntermediateColor", - complex_color=True, ignored_when_colors_disabled=True, allow_quirks=True)} diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index 693d1f32551..0fd7196baf5 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -16,8 +16,8 @@ return "https://drafts.csswg.org/css-backgrounds/#border-%s-%s" % (side[0], kind) %> % for side in ALL_SIDES: - ${helpers.predefined_type("border-%s-color" % side[0], "CSSColor", - "::cssparser::Color::CurrentColor", + ${helpers.predefined_type("border-%s-color" % side[0], "Color", + "computed_value::T::currentcolor()", alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"), spec=maybe_logical_spec(side, "color"), animation_value_type="IntermediateColor", @@ -66,21 +66,21 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style', ignored_when_colors_disabled="True"> use std::fmt; use style_traits::ToCss; - use values::specified::CSSColor; + use values::specified::RGBAColor; no_viewport_percentage!(SpecifiedValue); pub mod computed_value { - use values::computed::CSSColor; + use cssparser::RGBA; #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - pub struct T(pub Option<Vec<CSSColor>>); + pub struct T(pub Option<Vec<RGBA>>); } #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { None, - Colors(Vec<CSSColor>), + Colors(Vec<RGBAColor>), } impl ToCss for computed_value::T { @@ -168,7 +168,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style', } let mut result = Vec::new(); - while let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + while let Ok(value) = input.try(|i| RGBAColor::parse(context, i)) { result.push(value); } diff --git a/components/style/properties/longhand/color.mako.rs b/components/style/properties/longhand/color.mako.rs index 0728516ab41..fe5e411801e 100644 --- a/components/style/properties/longhand/color.mako.rs +++ b/components/style/properties/longhand/color.mako.rs @@ -13,25 +13,26 @@ ignored_when_colors_disabled="True" spec="https://drafts.csswg.org/css-color/#color"> use cssparser::RGBA; - use values::specified::{AllowQuirks, Color, CSSColor}; + use values::specified::{AllowQuirks, Color}; impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - self.0.parsed.to_computed_value(context) + self.0.to_computed_value(context) + .to_rgba(context.inherited_style.get_color().clone_color()) } #[inline] fn from_computed_value(computed: &computed_value::T) -> Self { - SpecifiedValue(Color::RGBA(*computed).into()) + SpecifiedValue(Color::rgba(*computed).into()) } } #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq, ToCss)] - pub struct SpecifiedValue(pub CSSColor); + pub struct SpecifiedValue(pub Color); no_viewport_percentage!(SpecifiedValue); pub mod computed_value { @@ -43,7 +44,7 @@ RGBA::new(0, 0, 0, 255) // black } pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { - CSSColor::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue) + Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue) } // FIXME(#15973): Add servo support for system colors diff --git a/components/style/properties/longhand/column.mako.rs b/components/style/properties/longhand/column.mako.rs index 2c99a7f1dc3..440e5d94d81 100644 --- a/components/style/properties/longhand/column.mako.rs +++ b/components/style/properties/longhand/column.mako.rs @@ -51,12 +51,11 @@ ${helpers.predefined_type("column-rule-width", extra_prefixes="moz")} // https://drafts.csswg.org/css-multicol-1/#crc -${helpers.predefined_type("column-rule-color", "CSSColor", - "::cssparser::Color::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", +${helpers.predefined_type("column-rule-color", "Color", + "computed_value::T::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", extra_prefixes="moz", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")} ${helpers.single_keyword("column-span", "none all", diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index 9b4004712ec..649caa5cece 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -685,12 +685,11 @@ ${helpers.predefined_type("word-spacing", % endif </%helpers:longhand> -${helpers.predefined_type("text-emphasis-color", "CSSColor", - "::cssparser::Color::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", +${helpers.predefined_type("text-emphasis-color", "Color", + "computed_value::T::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")} @@ -705,20 +704,18 @@ ${helpers.predefined_type( // CSS Compatibility // https://compat.spec.whatwg.org ${helpers.predefined_type( - "-webkit-text-fill-color", "CSSColor", - "CSSParserColor::CurrentColor", + "-webkit-text-fill-color", "Color", + "computed_value::T::currentcolor()", products="gecko", animation_value_type="IntermediateColor", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")} ${helpers.predefined_type( - "-webkit-text-stroke-color", "CSSColor", - "CSSParserColor::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", + "-webkit-text-stroke-color", "Color", + "computed_value::T::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", - complex_color=True, need_clone=True, - ignored_when_colors_disabled=True, + need_clone=True, ignored_when_colors_disabled=True, spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")} ${helpers.predefined_type("-webkit-text-stroke-width", diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index 1640953e305..03ec187135e 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -10,9 +10,9 @@ additional_methods=[Method("outline_has_nonzero_width", "bool")]) %> // TODO(pcwalton): `invert` -${helpers.predefined_type("outline-color", "CSSColor", "computed::CSSColor::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", - animation_value_type="IntermediateColor", complex_color=True, need_clone=True, +${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", + animation_value_type="IntermediateColor", need_clone=True, ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")} diff --git a/components/style/properties/longhand/svg.mako.rs b/components/style/properties/longhand/svg.mako.rs index c9704795b8a..9021121f370 100644 --- a/components/style/properties/longhand/svg.mako.rs +++ b/components/style/properties/longhand/svg.mako.rs @@ -20,8 +20,8 @@ ${helpers.single_keyword("vector-effect", "none non-scaling-stroke", // Section 13 - Gradients and Patterns ${helpers.predefined_type( - "stop-color", "CSSColor", - "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))", + "stop-color", "RGBAColor", + "RGBA::new(0, 0, 0, 255)", products="gecko", animation_value_type="none", spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")} @@ -34,8 +34,8 @@ ${helpers.predefined_type("stop-opacity", "Opacity", "1.0", // Section 15 - Filter Effects ${helpers.predefined_type( - "flood-color", "CSSColor", - "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))", + "flood-color", "RGBAColor", + "RGBA::new(0, 0, 0, 255)", products="gecko", animation_value_type="none", spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")} @@ -45,8 +45,8 @@ ${helpers.predefined_type("flood-opacity", "Opacity", spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty")} ${helpers.predefined_type( - "lighting-color", "CSSColor", - "CSSParserColor::RGBA(RGBA::new(255, 255, 255, 255))", + "lighting-color", "RGBAColor", + "RGBA::new(255, 255, 255, 255)", products="gecko", animation_value_type="none", spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")} diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index d636ed3cb64..08113b228f2 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -278,10 +278,9 @@ ${helpers.single_keyword("text-decoration-style", spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")} ${helpers.predefined_type( - "text-decoration-color", "CSSColor", - "computed::CSSColor::CurrentColor", - initial_specified_value="specified::CSSColor::currentcolor()", - complex_color=True, + "text-decoration-color", "Color", + "computed_value::T::currentcolor()", + initial_specified_value="specified::Color::currentcolor()", products="gecko", animation_value_type="IntermediateColor", ignored_when_colors_disabled=True, diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a0264d41e8c..9e8420fa471 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -18,7 +18,7 @@ use std::ops::Deref; use stylearc::{Arc, UniqueArc}; use app_units::Au; -#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA}; +#[cfg(feature = "servo")] use cssparser::RGBA; use cssparser::{Parser, TokenSerializationType, serialize_identifier}; use error_reporting::ParseErrorReporter; #[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D; @@ -40,7 +40,6 @@ use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraDat #[cfg(feature = "servo")] use values::Either; use values::generics::text::LineHeight; use values::computed; -use values::specified::Color; use cascade_info::CascadeInfo; use rule_tree::{CascadeLevel, StrongRuleNode}; use style_adjuster::StyleAdjuster; @@ -1938,11 +1937,8 @@ impl ComputedValues { /// Usage example: /// let top_color = style.resolve_color(style.Border.border_top_color); #[inline] - pub fn resolve_color(&self, color: CSSParserColor) -> RGBA { - match color { - CSSParserColor::RGBA(rgba) => rgba, - CSSParserColor::CurrentColor => self.get_color().color, - } + pub fn resolve_color(&self, color: computed::Color) -> RGBA { + color.to_rgba(self.get_color().color) } /// Get the logical computed inline size. @@ -2626,7 +2622,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device, let ignore_colors = !device.use_document_colors(); let default_background_color_decl = if ignore_colors { let color = device.default_background_color(); - Some(PropertyDeclaration::BackgroundColor(Color::RGBA(color).into())) + Some(PropertyDeclaration::BackgroundColor(color.into())) } else { None }; diff --git a/components/style/properties/shorthand/background.mako.rs b/components/style/properties/shorthand/background.mako.rs index 36652a73520..3767d80bed9 100644 --- a/components/style/properties/shorthand/background.mako.rs +++ b/components/style/properties/shorthand/background.mako.rs @@ -15,7 +15,7 @@ use properties::longhands::background_clip; use properties::longhands::background_clip::single_value::computed_value::T as Clip; use properties::longhands::background_origin::single_value::computed_value::T as Origin; - use values::specified::{CSSColor, Position, PositionComponent}; + use values::specified::{Color, Position, PositionComponent}; use parser::Parse; impl From<background_origin::single_value::SpecifiedValue> for background_clip::single_value::SpecifiedValue { @@ -50,7 +50,7 @@ % endfor loop { if background_color.is_none() { - if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { background_color = Some(value); continue } @@ -112,7 +112,7 @@ })); Ok(expanded! { - background_color: background_color.unwrap_or(CSSColor::transparent()), + background_color: background_color.unwrap_or(Color::transparent()), background_image: background_image, background_position_x: background_position_x, background_position_y: background_position_y, diff --git a/components/style/properties/shorthand/border.mako.rs b/components/style/properties/shorthand/border.mako.rs index c84549a544f..b5ebe773c66 100644 --- a/components/style/properties/shorthand/border.mako.rs +++ b/components/style/properties/shorthand/border.mako.rs @@ -5,7 +5,7 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> <% from data import to_rust_ident, ALL_SIDES, PHYSICAL_SIDES, maybe_moz_logical_alias %> -${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::CSSColor::parse", +${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Color::parse", spec="https://drafts.csswg.org/css-backgrounds/#border-color", allow_quirks=True)} @@ -44,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style", pub fn parse_border(context: &ParserContext, input: &mut Parser) - -> Result<(specified::CSSColor, + -> Result<(specified::Color, specified::BorderStyle, specified::BorderSideWidth), ()> { - use values::specified::{CSSColor, BorderStyle, BorderSideWidth}; + use values::specified::{Color, BorderStyle, BorderSideWidth}; let _unused = context; let mut color = None; let mut style = None; @@ -55,7 +55,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) let mut any = false; loop { if color.is_none() { - if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { color = Some(value); any = true; continue @@ -78,7 +78,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) break } if any { - Ok((color.unwrap_or_else(|| CSSColor::currentcolor()), + Ok((color.unwrap_or_else(|| Color::currentcolor()), style.unwrap_or(BorderStyle::none), width.unwrap_or(BorderSideWidth::Medium))) } else { diff --git a/components/style/properties/shorthand/outline.mako.rs b/components/style/properties/shorthand/outline.mako.rs index 8a1ab5900da..649651c02d9 100644 --- a/components/style/properties/shorthand/outline.mako.rs +++ b/components/style/properties/shorthand/outline.mako.rs @@ -18,7 +18,7 @@ let mut any = false; loop { if color.is_none() { - if let Ok(value) = input.try(|i| specified::CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| specified::Color::parse(context, i)) { color = Some(value); any = true; continue diff --git a/components/style/properties/shorthand/serialize.mako.rs b/components/style/properties/shorthand/serialize.mako.rs index f8c1ef9bc3e..a86704a5488 100644 --- a/components/style/properties/shorthand/serialize.mako.rs +++ b/components/style/properties/shorthand/serialize.mako.rs @@ -3,18 +3,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use style_traits::ToCss; -use values::specified::{BorderStyle, Color, CSSColor}; +use values::specified::{BorderStyle, Color}; use std::fmt; fn serialize_directional_border<W, I,>(dest: &mut W, width: &I, style: &BorderStyle, - color: &CSSColor) + color: &Color) -> fmt::Result where W: fmt::Write, I: ToCss { width.to_css(dest)?; dest.write_str(" ")?; style.to_css(dest)?; - if color.parsed != Color::CurrentColor { + if *color != Color::CurrentColor { dest.write_str(" ")?; color.to_css(dest)?; } diff --git a/components/style/properties/shorthand/text.mako.rs b/components/style/properties/shorthand/text.mako.rs index c5e7ba12c5e..111adb4de1b 100644 --- a/components/style/properties/shorthand/text.mako.rs +++ b/components/style/properties/shorthand/text.mako.rs @@ -70,7 +70,7 @@ self.text_decoration_style.to_css(dest)?; } - if self.text_decoration_color.parsed != specified::Color::CurrentColor { + if *self.text_decoration_color != specified::Color::CurrentColor { dest.write_str(" ")?; self.text_decoration_color.to_css(dest)?; } diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 37e7334b9db..c51f6f94ff7 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -912,7 +912,6 @@ impl StrongRuleNode { -> bool where E: ::dom::TElement { - use cssparser::RGBA; use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_BACKGROUND, NS_AUTHOR_SPECIFIED_BORDER}; use gecko_bindings::structs::{NS_AUTHOR_SPECIFIED_PADDING, NS_AUTHOR_SPECIFIED_TEXT_SHADOW}; use properties::{CSSWideKeyword, LonghandId, LonghandIdSet}; @@ -1083,7 +1082,7 @@ impl StrongRuleNode { if properties.contains(id) { if !author_colors_allowed { if let PropertyDeclaration::BackgroundColor(ref color) = *declaration { - return color.parsed == Color::RGBA(RGBA::transparent()) + return *color == Color::transparent() } } return true diff --git a/components/style/values/computed/color.rs b/components/style/values/computed/color.rs new file mode 100644 index 00000000000..8c9a863b2c5 --- /dev/null +++ b/components/style/values/computed/color.rs @@ -0,0 +1,144 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Computed color values. + +use cssparser::{Color as CSSParserColor, RGBA}; +use std::fmt; +use style_traits::ToCss; + +/// This struct represents a combined color from a numeric color and +/// the current foreground color (currentcolor keyword). +/// Conceptually, the formula is "color * (1 - p) + currentcolor * p" +/// where p is foreground_ratio. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct Color { + /// RGBA color. + pub color: RGBA, + /// The ratio of currentcolor in complex color. + pub foreground_ratio: u8, +} + +fn blend_color_component(bg: u8, fg: u8, fg_alpha: u8) -> u8 { + let bg_ratio = (u8::max_value() - fg_alpha) as u32; + let fg_ratio = fg_alpha as u32; + let color = bg as u32 * bg_ratio + fg as u32 * fg_ratio; + // Rounding divide the number by 255 + ((color + 127) / 255) as u8 +} + +impl Color { + /// Returns a numeric color representing the given RGBA value. + pub fn rgba(rgba: RGBA) -> Color { + Color { + color: rgba, + foreground_ratio: 0, + } + } + + /// Returns a complex color value representing transparent. + pub fn transparent() -> Color { + Color::rgba(RGBA::transparent()) + } + + /// Returns a complex color value representing currentcolor. + pub fn currentcolor() -> Color { + Color { + color: RGBA::transparent(), + foreground_ratio: u8::max_value(), + } + } + + /// Whether it is a numeric color (no currentcolor component). + pub fn is_numeric(&self) -> bool { + self.foreground_ratio == 0 + } + + /// Whether it is a currentcolor value (no numeric color component). + pub fn is_currentcolor(&self) -> bool { + self.foreground_ratio == u8::max_value() + } + + /// Combine this complex color with the given foreground color into + /// a numeric RGBA color. It currently uses linear blending. + pub fn to_rgba(&self, fg_color: RGBA) -> RGBA { + // Common cases that the complex color is either pure numeric + // color or pure currentcolor. + if self.is_numeric() { + return self.color; + } + if self.is_currentcolor() { + return fg_color.clone(); + } + // Common case that alpha channel is equal (usually both are opaque). + let fg_ratio = self.foreground_ratio; + if self.color.alpha == fg_color.alpha { + let r = blend_color_component(self.color.red, fg_color.red, fg_ratio); + let g = blend_color_component(self.color.green, fg_color.green, fg_ratio); + let b = blend_color_component(self.color.blue, fg_color.blue, fg_ratio); + return RGBA::new(r, g, b, fg_color.alpha); + } + + // For the more complicated case that the alpha value differs, + // we use the following formula to compute the components: + // alpha = self_alpha * (1 - fg_ratio) + fg_alpha * fg_ratio + // color = (self_color * self_alpha * (1 - fg_ratio) + + // fg_color * fg_alpha * fg_ratio) / alpha + + let p1 = (1. / 255.) * (255 - fg_ratio) as f32; + let a1 = self.color.alpha_f32(); + let r1 = a1 * self.color.red_f32(); + let g1 = a1 * self.color.green_f32(); + let b1 = a1 * self.color.blue_f32(); + + let p2 = 1. - p1; + let a2 = fg_color.alpha_f32(); + let r2 = a2 * fg_color.red_f32(); + let g2 = a2 * fg_color.green_f32(); + let b2 = a2 * fg_color.blue_f32(); + + let a = p1 * a1 + p2 * a2; + if a == 0.0 { + return RGBA::transparent(); + } + + let inverse_a = 1. / a; + let r = (p1 * r1 + p2 * r2) * inverse_a; + let g = (p1 * g1 + p2 * g2) * inverse_a; + let b = (p1 * b1 + p2 * b2) * inverse_a; + return RGBA::from_floats(r, g, b, a); + } +} + +impl PartialEq for Color { + fn eq(&self, other: &Color) -> bool { + self.foreground_ratio == other.foreground_ratio && + (self.is_currentcolor() || self.color == other.color) + } +} + +impl From<RGBA> for Color { + fn from(color: RGBA) -> Color { + Color { + color: color, + foreground_ratio: 0, + } + } +} + +impl ToCss for Color { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.is_numeric() { + self.color.to_css(dest) + } else if self.is_currentcolor() { + CSSParserColor::CurrentColor.to_css(dest) + } else { + Ok(()) + } + } +} + +/// Computed value type for the specified RGBAColor. +pub type RGBAColor = RGBA; diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs index 5f51dd22f85..3718be2fbd3 100644 --- a/components/style/values/computed/image.rs +++ b/components/style/values/computed/image.rs @@ -7,7 +7,7 @@ //! //! [image]: https://drafts.csswg.org/css-images/#image-values -use cssparser::Color as CSSColor; +use cssparser::RGBA; use std::f32::consts::PI; use std::fmt; use style_traits::ToCss; @@ -35,7 +35,7 @@ pub type Gradient = GenericGradient< Length, LengthOrPercentage, Position, - CSSColor, + RGBA, >; /// A computed gradient kind. @@ -60,10 +60,10 @@ pub enum LineDirection { pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>; /// A computed gradient item. -pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>; +pub type GradientItem = GenericGradientItem<RGBA, LengthOrPercentage>; /// A computed color stop. -pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>; +pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>; /// Computed values for ImageRect. pub type ImageRect = GenericImageRect<NumberOrPercentage>; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 1547cf29424..ff682255d99 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -23,11 +23,11 @@ use super::generics::grid::TrackList as GenericTrackList; use super::specified; pub use app_units::Au; -pub use cssparser::Color as CSSColor; pub use properties::animated_properties::TransitionProperty; pub use self::background::BackgroundSize; pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth}; pub use self::border::{BorderRadius, BorderCornerRadius}; +pub use self::color::{Color, RGBAColor}; pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -48,6 +48,7 @@ pub use self::transform::{TimingFunction, TransformOrigin}; pub mod background; pub mod basic_shape; pub mod border; +pub mod color; pub mod image; #[cfg(feature = "gecko")] pub mod gecko; @@ -360,86 +361,6 @@ impl ToCss for Time { } } -impl ToComputedValue for specified::Color { - type ComputedValue = RGBA; - - #[cfg(not(feature = "gecko"))] - fn to_computed_value(&self, context: &Context) -> RGBA { - match *self { - specified::Color::RGBA(rgba) => rgba, - specified::Color::CurrentColor => context.inherited_style.get_color().clone_color(), - } - } - - #[cfg(feature = "gecko")] - fn to_computed_value(&self, context: &Context) -> RGBA { - use gecko::values::convert_nscolor_to_rgba as to_rgba; - // It's safe to access the nsPresContext immutably during style computation. - let pres_context = unsafe { &*context.device.pres_context }; - match *self { - specified::Color::RGBA(rgba) => rgba, - specified::Color::System(system) => to_rgba(system.to_computed_value(context)), - specified::Color::CurrentColor => context.inherited_style.get_color().clone_color(), - specified::Color::MozDefaultColor => to_rgba(pres_context.mDefaultColor), - specified::Color::MozDefaultBackgroundColor => to_rgba(pres_context.mBackgroundColor), - specified::Color::MozHyperlinktext => to_rgba(pres_context.mLinkColor), - specified::Color::MozActiveHyperlinktext => to_rgba(pres_context.mActiveLinkColor), - specified::Color::MozVisitedHyperlinktext => to_rgba(pres_context.mVisitedLinkColor), - specified::Color::InheritFromBodyQuirk => { - use dom::TElement; - use gecko::wrapper::GeckoElement; - use gecko_bindings::bindings::Gecko_GetBody; - let body = unsafe { - Gecko_GetBody(pres_context) - }; - if let Some(body) = body { - let wrap = GeckoElement(body); - let borrow = wrap.borrow_data(); - borrow.as_ref().unwrap() - .styles().primary.values() - .get_color() - .clone_color() - } else { - to_rgba(pres_context.mDefaultColor) - } - }, - } - } - - fn from_computed_value(computed: &RGBA) -> Self { - specified::Color::RGBA(*computed) - } -} - -impl ToComputedValue for specified::CSSColor { - type ComputedValue = CSSColor; - - #[cfg(not(feature = "gecko"))] - #[inline] - fn to_computed_value(&self, _context: &Context) -> CSSColor { - self.parsed - } - - #[cfg(feature = "gecko")] - #[inline] - fn to_computed_value(&self, context: &Context) -> CSSColor { - match self.parsed { - specified::Color::RGBA(rgba) => CSSColor::RGBA(rgba), - specified::Color::CurrentColor => CSSColor::CurrentColor, - // Resolve non-standard -moz keywords to RGBA: - non_standard => CSSColor::RGBA(non_standard.to_computed_value(context)), - } - } - - #[inline] - fn from_computed_value(computed: &CSSColor) -> Self { - (match *computed { - CSSColor::RGBA(rgba) => specified::Color::RGBA(rgba), - CSSColor::CurrentColor => specified::Color::CurrentColor, - }).into() - } -} - #[cfg(feature = "gecko")] impl ToComputedValue for specified::JustifyItems { type ComputedValue = JustifyItems; @@ -480,7 +401,7 @@ pub struct Shadow { pub offset_y: Au, pub blur_radius: Au, pub spread_radius: Au, - pub color: CSSColor, + pub color: Color, pub inset: bool, } @@ -559,9 +480,9 @@ impl IntegerOrAuto { } /// Computed SVG Paint value -pub type SVGPaint = ::values::generics::SVGPaint<CSSColor>; +pub type SVGPaint = ::values::generics::SVGPaint<RGBA>; /// Computed SVG Paint Kind value -pub type SVGPaintKind = ::values::generics::SVGPaintKind<CSSColor>; +pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBA>; impl Default for SVGPaint { fn default() -> Self { @@ -577,7 +498,7 @@ impl SVGPaint { pub fn black() -> Self { let rgba = RGBA::from_floats(0., 0., 0., 1.); SVGPaint { - kind: ::values::generics::SVGPaintKind::Color(CSSColor::RGBA(rgba)), + kind: ::values::generics::SVGPaintKind::Color(rgba), fallback: None, } } @@ -662,4 +583,4 @@ impl ClipRectOrAuto { } /// <color> | auto -pub type ColorOrAuto = Either<CSSColor, Auto>; +pub type ColorOrAuto = Either<Color, Auto>; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 0599563a494..9fb5e849c5c 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -2,102 +2,336 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -//! Non-standard CSS color values +//! Specified color values. -#[cfg(not(feature = "gecko"))] pub use self::servo::Color; -#[cfg(feature = "gecko")] pub use self::gecko::Color; +use cssparser::{Color as CSSParserColor, Parser, RGBA, Token}; +#[cfg(feature = "gecko")] +use gecko_bindings::structs::nscolor; +use itoa; +use parser::{ParserContext, Parse}; +#[cfg(feature = "gecko")] +use properties::longhands::color::SystemColor; +use std::fmt; +use std::io::Write; +use style_traits::ToCss; +use super::AllowQuirks; +use values::computed::{Color as ComputedColor, Context, ToComputedValue}; -#[cfg(not(feature = "gecko"))] -mod servo { - pub use cssparser::Color; - use cssparser::Parser; - use parser::{Parse, ParserContext}; +/// Specified color value +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum Color { + /// The 'currentColor' keyword + CurrentColor, + /// A specific RGBA color + Numeric { + /// Parsed RGBA color + parsed: RGBA, + /// Authored representation + authored: Option<Box<str>>, + }, + /// A complex color value from computed value + Complex(ComputedColor), - impl Parse for Color { - fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> { - Color::parse(input) - } - } + /// A system color + #[cfg(feature = "gecko")] + System(SystemColor), + /// A special color keyword value used in Gecko + #[cfg(feature = "gecko")] + Special(gecko::SpecialColorKeyword), + /// Quirksmode-only rule for inheriting color from the body + #[cfg(feature = "gecko")] + InheritFromBodyQuirk, } +no_viewport_percentage!(Color); + #[cfg(feature = "gecko")] mod gecko { - use cssparser::{Color as CSSParserColor, Parser, RGBA}; - use parser::{Parse, ParserContext}; - use properties::longhands::color::SystemColor; - use std::fmt; use style_traits::ToCss; - /// Color value including non-standard -moz prefixed values. - #[derive(Clone, Copy, PartialEq, Debug)] - pub enum Color { - /// The 'currentColor' keyword - CurrentColor, - /// A specific RGBA color - RGBA(RGBA), - /// A system color - System(SystemColor), - /// -moz-default-color - MozDefaultColor, - /// -moz-default-background-color - MozDefaultBackgroundColor, - /// -moz-hyperlinktext - MozHyperlinktext, - /// -moz-activehyperlinktext - MozActiveHyperlinktext, - /// -moz-visitedhyperlinktext - MozVisitedHyperlinktext, - /// Quirksmode-only rule for inheriting color from the body - InheritFromBodyQuirk, - } - - no_viewport_percentage!(Color); - - impl From<CSSParserColor> for Color { - fn from(value: CSSParserColor) -> Self { - match value { + define_css_keyword_enum! { SpecialColorKeyword: + "-moz-default-color" => MozDefaultColor, + "-moz-default-background-color" => MozDefaultBackgroundColor, + "-moz-hyperlinktext" => MozHyperlinktext, + "-moz-activehyperlinktext" => MozActiveHyperlinktext, + "-moz-visitedhyperlinktext" => MozVisitedHyperlinktext, + } +} + +impl From<RGBA> for Color { + fn from(value: RGBA) -> Self { + Color::rgba(value) + } +} + +impl Parse for Color { + fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> { + // Currently we only store authored value for color keywords, + // because all browsers serialize those values as keywords for + // specified value. + let start_position = input.position(); + let authored = match input.next() { + Ok(Token::Ident(s)) => Some(s.to_lowercase().into_boxed_str()), + _ => None, + }; + input.reset(start_position); + if let Ok(value) = input.try(CSSParserColor::parse) { + Ok(match value { CSSParserColor::CurrentColor => Color::CurrentColor, - CSSParserColor::RGBA(x) => Color::RGBA(x), + CSSParserColor::RGBA(rgba) => Color::Numeric { + parsed: rgba, + authored: authored, + }, + }) + } else { + #[cfg(feature = "gecko")] { + if let Ok(system) = input.try(SystemColor::parse) { + Ok(Color::System(system)) + } else { + gecko::SpecialColorKeyword::parse(input).map(Color::Special) + } + } + #[cfg(not(feature = "gecko"))] { + Err(()) } } } +} + +impl ToCss for Color { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), + Color::Numeric { authored: Some(ref authored), .. } => dest.write_str(authored), + Color::Numeric { parsed: ref rgba, .. } => rgba.to_css(dest), + Color::Complex(_) => Ok(()), + #[cfg(feature = "gecko")] + Color::System(system) => system.to_css(dest), + #[cfg(feature = "gecko")] + Color::Special(special) => special.to_css(dest), + #[cfg(feature = "gecko")] + Color::InheritFromBodyQuirk => Ok(()), + } + } +} + +/// A wrapper of cssparser::Color::parse_hash. +/// +/// That function should never return CurrentColor, so it makes no sense +/// to handle a cssparser::Color here. This should really be done in +/// cssparser directly rather than here. +fn parse_hash_color(value: &[u8]) -> Result<RGBA, ()> { + CSSParserColor::parse_hash(value).map(|color| { + match color { + CSSParserColor::RGBA(rgba) => rgba, + CSSParserColor::CurrentColor => + unreachable!("parse_hash should never return currentcolor"), + } + }) +} + +impl Color { + /// Returns currentcolor value. + #[inline] + pub fn currentcolor() -> Color { + Color::CurrentColor + } + + /// Returns transparent value. + #[inline] + pub fn transparent() -> Color { + // We should probably set authored to "transparent", but maybe it doesn't matter. + Color::rgba(RGBA::transparent()) + } + + /// Returns a numeric RGBA color value. + #[inline] + pub fn rgba(rgba: RGBA) -> Self { + Color::Numeric { + parsed: rgba, + authored: None, + } + } + + /// Parse a color, with quirks. + /// + /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk + pub fn parse_quirky(context: &ParserContext, + input: &mut Parser, + allow_quirks: AllowQuirks) + -> Result<Self, ()> { + input.try(|i| Self::parse(context, i)).or_else(|_| { + if !allow_quirks.allowed(context.quirks_mode) { + return Err(()); + } + Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba)) + }) + } - impl Parse for Color { - fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> { - if let Ok(value) = input.try(CSSParserColor::parse) { - Ok(value.into()) - } else if let Ok(system) = input.try(SystemColor::parse) { - Ok(Color::System(system)) - } else { - let ident = input.expect_ident()?; - match_ignore_ascii_case! { &ident, - "-moz-default-color" => Ok(Color::MozDefaultColor), - "-moz-default-background-color" => Ok(Color::MozDefaultBackgroundColor), - "-moz-hyperlinktext" => Ok(Color::MozHyperlinktext), - "-moz-activehyperlinktext" => Ok(Color::MozActiveHyperlinktext), - "-moz-visitedhyperlinktext" => Ok(Color::MozVisitedHyperlinktext), - _ => Err(()) + /// Parse a <quirky-color> value. + /// + /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk + fn parse_quirky_color(input: &mut Parser) -> Result<RGBA, ()> { + let (number, dimension) = match input.next()? { + Token::Number(number) => { + (number, None) + }, + Token::Dimension(number, dimension) => { + (number, Some(dimension)) + }, + Token::Ident(ident) => { + if ident.len() != 3 && ident.len() != 6 { + return Err(()); } + return parse_hash_color(ident.as_bytes()); } + _ => { + return Err(()); + }, + }; + let value = number.int_value.ok_or(())?; + if value < 0 { + return Err(()); + } + let length = if value <= 9 { + 1 + } else if value <= 99 { + 2 + } else if value <= 999 { + 3 + } else if value <= 9999 { + 4 + } else if value <= 99999 { + 5 + } else if value <= 999999 { + 6 + } else { + return Err(()) + }; + let total = length + dimension.as_ref().map_or(0, |d| d.len()); + if total > 6 { + return Err(()); + } + let mut serialization = [b'0'; 6]; + let space_padding = 6 - total; + let mut written = space_padding; + written += itoa::write(&mut serialization[written..], value).unwrap(); + if let Some(dimension) = dimension { + written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap(); + } + debug_assert!(written == 6); + parse_hash_color(&serialization) + } + + /// Returns false if the color is completely transparent, and + /// true otherwise. + pub fn is_non_transparent(&self) -> bool { + match *self { + Color::Numeric { ref parsed, .. } => parsed.alpha != 0, + _ => true, } } +} + +#[cfg(feature = "gecko")] +fn convert_nscolor_to_computedcolor(color: nscolor) -> ComputedColor { + use gecko::values::convert_nscolor_to_rgba; + ComputedColor::rgba(convert_nscolor_to_rgba(color)) +} + +impl ToComputedValue for Color { + type ComputedValue = ComputedColor; - impl ToCss for Color { - fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - // Standard values: - Color::CurrentColor => CSSParserColor::CurrentColor.to_css(dest), - Color::RGBA(rgba) => rgba.to_css(dest), - Color::System(system) => system.to_css(dest), - - // Non-standard values: - Color::MozDefaultColor => dest.write_str("-moz-default-color"), - Color::MozDefaultBackgroundColor => dest.write_str("-moz-default-background-color"), - Color::MozHyperlinktext => dest.write_str("-moz-hyperlinktext"), - Color::MozActiveHyperlinktext => dest.write_str("-moz-activehyperlinktext"), - Color::MozVisitedHyperlinktext => dest.write_str("-moz-visitedhyperlinktext"), - Color::InheritFromBodyQuirk => Ok(()), + fn to_computed_value(&self, _context: &Context) -> ComputedColor { + match *self { + Color::CurrentColor => ComputedColor::currentcolor(), + Color::Numeric { ref parsed, .. } => ComputedColor::rgba(*parsed), + Color::Complex(ref complex) => *complex, + #[cfg(feature = "gecko")] + Color::System(system) => + convert_nscolor_to_computedcolor(system.to_computed_value(_context)), + #[cfg(feature = "gecko")] + Color::Special(special) => { + use self::gecko::SpecialColorKeyword as Keyword; + let pres_context = unsafe { &*_context.device.pres_context }; + convert_nscolor_to_computedcolor(match special { + Keyword::MozDefaultColor => pres_context.mDefaultColor, + Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor, + Keyword::MozHyperlinktext => pres_context.mLinkColor, + Keyword::MozActiveHyperlinktext => pres_context.mActiveLinkColor, + Keyword::MozVisitedHyperlinktext => pres_context.mVisitedLinkColor, + }) } + #[cfg(feature = "gecko")] + Color::InheritFromBodyQuirk => { + use dom::TElement; + use gecko::wrapper::GeckoElement; + use gecko_bindings::bindings::Gecko_GetBody; + let pres_context = unsafe { &*_context.device.pres_context }; + let body = unsafe { + Gecko_GetBody(pres_context) + }; + if let Some(body) = body { + let wrap = GeckoElement(body); + let borrow = wrap.borrow_data(); + ComputedColor::rgba(borrow.as_ref().unwrap() + .styles().primary.values() + .get_color() + .clone_color()) + } else { + convert_nscolor_to_computedcolor(pres_context.mDefaultColor) + } + }, + } + } + + fn from_computed_value(computed: &ComputedColor) -> Self { + if computed.is_numeric() { + Color::rgba(computed.color) + } else if computed.is_currentcolor() { + Color::currentcolor() + } else { + Color::Complex(*computed) } } } + +/// Specified color value, but resolved to just RGBA for computed value +/// with value from color property at the same context. +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct RGBAColor(pub Color); + +no_viewport_percentage!(RGBAColor); + +impl Parse for RGBAColor { + fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { + Color::parse(context, input).map(RGBAColor) + } +} + +impl ToCss for RGBAColor { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.0.to_css(dest) + } +} + +impl ToComputedValue for RGBAColor { + type ComputedValue = RGBA; + + fn to_computed_value(&self, context: &Context) -> RGBA { + self.0.to_computed_value(context) + .to_rgba(context.style.get_color().clone_color()) + } + + fn from_computed_value(computed: &RGBA) -> Self { + RGBAColor(Color::rgba(*computed)) + } +} + +impl From<Color> for RGBAColor { + fn from(color: Color) -> RGBAColor { + RGBAColor(color) + } +} diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 4564bc0993f..4284f2f2a43 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -24,8 +24,8 @@ use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRe use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExtent}; use values::generics::image::PaintWorklet; use values::generics::position::Position as GenericPosition; -use values::specified::{Angle, CSSColor, Color, Length, LengthOrPercentage}; -use values::specified::{Number, NumberOrPercentage, Percentage}; +use values::specified::{Angle, Color, Length, LengthOrPercentage}; +use values::specified::{Number, NumberOrPercentage, Percentage, RGBAColor}; use values::specified::position::{Position, PositionComponent, Side, X, Y}; use values::specified::url::SpecifiedUrl; @@ -43,7 +43,7 @@ pub type Gradient = GenericGradient< Length, LengthOrPercentage, Position, - CSSColor, + RGBAColor, >; /// A specified gradient kind. @@ -72,10 +72,10 @@ pub enum LineDirection { pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>; /// A specified gradient item. -pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>; +pub type GradientItem = GenericGradientItem<RGBAColor, LengthOrPercentage>; /// A computed color stop. -pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>; +pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>; /// Specified values for `moz-image-rect` /// -moz-image-rect(<uri>, top, right, bottom, left); @@ -386,11 +386,11 @@ impl Gradient { "to" => 1., _ => return Err(()), }; - let color = CSSColor::parse(context, i)?; - if color.parsed == Color::CurrentColor { + let color = Color::parse(context, i)?; + if color == Color::CurrentColor { return Err(()); } - Ok((color, p)) + Ok((color.into(), p)) })?; if reverse_stops { p = 1. - p; @@ -405,11 +405,11 @@ impl Gradient { if items.is_empty() { items = vec![ GenericGradientItem::ColorStop(GenericColorStop { - color: CSSColor::transparent(), + color: Color::transparent().into(), position: Some(Percentage(0.).into()), }), GenericGradientItem::ColorStop(GenericColorStop { - color: CSSColor::transparent(), + color: Color::transparent().into(), position: Some(Percentage(1.).into()), }), ]; @@ -674,7 +674,7 @@ impl GradientItem { impl Parse for ColorStop { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { Ok(ColorStop { - color: try!(CSSColor::parse(context, input)), + color: try!(RGBAColor::parse(context, input)), position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(), }) } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 59ff135c303..2ea37db841f 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -8,15 +8,13 @@ use Namespace; use context::QuirksMode; -use cssparser::{self, Parser, Token, serialize_identifier}; -use itoa; +use cssparser::{Parser, Token, serialize_identifier}; use parser::{ParserContext, Parse}; use self::grid::TrackSizeOrRepeat; use self::url::SpecifiedUrl; use std::ascii::AsciiExt; use std::f32; use std::fmt; -use std::io::Write; use style_traits::ToCss; use style_traits::values::specified::AllowedNumericType; use super::{Auto, CSSFloat, CSSInteger, Either, None_}; @@ -33,7 +31,7 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify pub use self::background::BackgroundSize; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth}; -pub use self::color::Color; +pub use self::color::{Color, RGBAColor}; pub use self::rect::LengthOrNumberRect; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -92,166 +90,6 @@ impl ComputedValueAsSpecified for SpecifiedUrl {} no_viewport_percentage!(SpecifiedUrl); } -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub struct CSSColor { - pub parsed: Color, - pub authored: Option<Box<str>>, -} - -impl Parse for CSSColor { - fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { - Self::parse_quirky(context, input, AllowQuirks::No) - } -} - -impl CSSColor { - /// Parse a color, with quirks. - /// - /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk - pub fn parse_quirky(context: &ParserContext, - input: &mut Parser, - allow_quirks: AllowQuirks) - -> Result<Self, ()> { - let start_position = input.position(); - let authored = match input.next() { - Ok(Token::Ident(s)) => Some(s.into_owned().into_boxed_str()), - _ => None, - }; - input.reset(start_position); - if let Ok(parsed) = input.try(|i| Parse::parse(context, i)) { - return Ok(CSSColor { - parsed: parsed, - authored: authored, - }); - } - if !allow_quirks.allowed(context.quirks_mode) { - return Err(()); - } - let (number, dimension) = match input.next()? { - Token::Number(number) => { - (number, None) - }, - Token::Dimension(number, dimension) => { - (number, Some(dimension)) - }, - Token::Ident(ident) => { - if ident.len() != 3 && ident.len() != 6 { - return Err(()); - } - return cssparser::Color::parse_hash(ident.as_bytes()).map(|color| { - Self { - parsed: color.into(), - authored: None - } - }); - } - _ => { - return Err(()); - }, - }; - let value = number.int_value.ok_or(())?; - if value < 0 { - return Err(()); - } - let length = if value <= 9 { - 1 - } else if value <= 99 { - 2 - } else if value <= 999 { - 3 - } else if value <= 9999 { - 4 - } else if value <= 99999 { - 5 - } else if value <= 999999 { - 6 - } else { - return Err(()) - }; - let total = length + dimension.as_ref().map_or(0, |d| d.len()); - if total > 6 { - return Err(()); - } - let mut serialization = [b'0'; 6]; - let space_padding = 6 - total; - let mut written = space_padding; - written += itoa::write(&mut serialization[written..], value).unwrap(); - if let Some(dimension) = dimension { - written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap(); - } - debug_assert!(written == 6); - Ok(CSSColor { - parsed: cssparser::Color::parse_hash(&serialization).map(From::from)?, - authored: None, - }) - } - - /// Returns false if the color is completely transparent, and - /// true otherwise. - pub fn is_non_transparent(&self) -> bool { - match self.parsed { - Color::RGBA(rgba) if rgba.alpha == 0 => false, - _ => true, - } - } -} - -no_viewport_percentage!(CSSColor); - -impl ToCss for CSSColor { - fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match self.authored { - Some(ref s) => dest.write_str(s), - None => self.parsed.to_css(dest), - } - } -} - -impl From<Color> for CSSColor { - fn from(color: Color) -> Self { - CSSColor { - parsed: color, - authored: None, - } - } -} - -impl CSSColor { - #[inline] - /// Returns currentcolor value. - pub fn currentcolor() -> CSSColor { - Color::CurrentColor.into() - } - - #[inline] - /// Returns transparent value. - pub fn transparent() -> CSSColor { - // We should probably set authored to "transparent", but maybe it doesn't matter. - Color::RGBA(cssparser::RGBA::transparent()).into() - } -} - -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -pub struct CSSRGBA { - pub parsed: cssparser::RGBA, - pub authored: Option<Box<str>>, -} - -no_viewport_percentage!(CSSRGBA); - -impl ToCss for CSSRGBA { - fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match self.authored { - Some(ref s) => dest.write_str(s), - None => self.parsed.to_css(dest), - } - } -} - /// Parse an `<integer>` value, handling `calc()` correctly. pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> { match try!(input.next()) { @@ -843,7 +681,7 @@ pub struct Shadow { pub offset_y: Length, pub blur_radius: Length, pub spread_radius: Length, - pub color: Option<CSSColor>, + pub color: Option<Color>, pub inset: bool, } @@ -857,10 +695,8 @@ impl ToComputedValue for Shadow { offset_y: self.offset_y.to_computed_value(context), blur_radius: self.blur_radius.to_computed_value(context), spread_radius: self.spread_radius.to_computed_value(context), - color: self.color - .as_ref() - .map(|color| color.to_computed_value(context)) - .unwrap_or(cssparser::Color::CurrentColor), + color: self.color.as_ref().unwrap_or(&Color::CurrentColor) + .to_computed_value(context), inset: self.inset, } } @@ -933,7 +769,7 @@ impl Shadow { } } if color.is_none() { - if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) { + if let Ok(value) = input.try(|i| Color::parse(context, i)) { color = Some(value); continue } @@ -961,10 +797,10 @@ impl Shadow { no_viewport_percentage!(SVGPaint); /// Specified SVG Paint value -pub type SVGPaint = ::values::generics::SVGPaint<CSSColor>; +pub type SVGPaint = ::values::generics::SVGPaint<RGBAColor>; /// Specified SVG Paint Kind value -pub type SVGPaintKind = ::values::generics::SVGPaintKind<CSSColor>; +pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBAColor>; impl ToComputedValue for SVGPaint { type ComputedValue = super::computed::SVGPaint; @@ -991,12 +827,7 @@ impl ToComputedValue for SVGPaintKind { #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - self.convert(|color| { - match color.parsed { - Color::CurrentColor => cssparser::Color::RGBA(context.style().get_color().clone_color()), - _ => color.to_computed_value(context), - } - }) + self.convert(|color| color.to_computed_value(context)) } #[inline] @@ -1164,7 +995,7 @@ impl ClipRectOrAuto { } /// <color> | auto -pub type ColorOrAuto = Either<CSSColor, Auto>; +pub type ColorOrAuto = Either<Color, Auto>; /// Whether quirks are allowed in this context. #[derive(Clone, Copy, PartialEq)] diff --git a/components/style/values/specified/mod.rs.rej b/components/style/values/specified/mod.rs.rej new file mode 100644 index 00000000000..0136e286c72 --- /dev/null +++ b/components/style/values/specified/mod.rs.rej @@ -0,0 +1,44 @@ +--- components/style/values/specified/mod.rs ++++ components/style/values/specified/mod.rs +@@ -4,40 +4,38 @@ + + //! Specified values. + //! + //! TODO(emilio): Enhance docs. + + use Namespace; + use context::QuirksMode; + use cssparser::{self, Parser, Token, serialize_identifier}; +-use itoa; + use parser::{ParserContext, Parse}; + use self::grid::TrackSizeOrRepeat; + use self::url::SpecifiedUrl; + use std::ascii::AsciiExt; + use std::f32; + use std::fmt; +-use std::io::Write; + use style_traits::ToCss; + use style_traits::values::specified::AllowedNumericType; + use super::{Auto, CSSFloat, CSSInteger, Either, None_}; + use super::computed::{self, Context}; + use super::computed::{Shadow as ComputedShadow, ToComputedValue}; + use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; + use super::generics::grid::TrackList as GenericTrackList; + use values::computed::ComputedValueAsSpecified; + use values::specified::calc::CalcNode; + + #[cfg(feature = "gecko")] + pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems}; + pub use self::background::BackgroundSize; + pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; + pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth}; +-pub use self::color::Color; ++pub use self::color::{CSSColor, Color}; + pub use self::rect::LengthOrNumberRect; + pub use super::generics::grid::GridLine; + pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient}; + pub use self::image::{GradientItem, GradientKind, Image, ImageRect, ImageLayer}; + pub use self::length::AbsoluteLength; + pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage}; + pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto}; + pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength}; diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 6363e38deb1..fa08f50e4db 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -2216,10 +2216,10 @@ pub extern "C" fn Servo_DeclarationBlock_SetCurrentColor(declarations: RawServoDeclarationBlockBorrowed, property: nsCSSPropertyID) { use style::properties::{PropertyDeclaration, LonghandId}; - use style::values::specified::{Color, CSSColor}; + use style::values::specified::Color; let long = get_longhand_from_id!(property); - let cc = CSSColor { parsed: Color::CurrentColor, authored: None }; + let cc = Color::currentcolor(); let prop = match_wrap_declared! { long, BorderTopColor => cc, @@ -2240,11 +2240,11 @@ pub extern "C" fn Servo_DeclarationBlock_SetColorValue(declarations: use style::gecko::values::convert_nscolor_to_rgba; use style::properties::{PropertyDeclaration, LonghandId}; use style::properties::longhands; - use style::values::specified::{Color, CSSColor}; + use style::values::specified::Color; let long = get_longhand_from_id!(property); let rgba = convert_nscolor_to_rgba(value); - let color = CSSColor { parsed: Color::RGBA(rgba), authored: None }; + let color = Color::rgba(rgba); let prop = match_wrap_declared! { long, BorderTopColor => color, diff --git a/tests/unit/style/parsing/ui.rs b/tests/unit/style/parsing/ui.rs index 9347b1fbc01..14d96656b32 100644 --- a/tests/unit/style/parsing/ui.rs +++ b/tests/unit/style/parsing/ui.rs @@ -2,10 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use cssparser::{Color, RGBA}; +use cssparser::RGBA; use parsing::parse; use style::values::{Auto, Either}; -use style::values::specified::CSSColor; +use style::values::specified::Color; use style_traits::ToCss; #[test] @@ -33,13 +33,13 @@ fn test_caret_color() { let auto = parse_longhand!(caret_color, "auto"); assert_eq!(auto, Either::Second(Auto)); - let blue_color = CSSColor { - parsed: Color::RGBA(RGBA { + let blue_color = Color::Numeric { + parsed: RGBA { red: 0, green: 0, blue: 255, alpha: 255, - }), + }, authored: Some(String::from("blue").into_boxed_str()), }; diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index e8009794a5a..9ee2877101a 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -5,11 +5,11 @@ use properties::parse; use style::computed_values::display::T::inline_block; use style::properties::{PropertyDeclaration, Importance, PropertyId}; -use style::properties::longhands::outline_color::computed_value::T as ComputedColor; use style::properties::parse_property_declaration_list; use style::values::{RGBA, Auto}; use style::values::CustomIdent; -use style::values::specified::{BorderStyle, BorderSideWidth, CSSColor, Length, LengthOrPercentage}; +use style::values::specified::{BorderStyle, BorderSideWidth, Color}; +use style::values::specified::{Length, LengthOrPercentage}; use style::values::specified::{LengthOrPercentageOrAuto, LengthOrPercentageOrAutoOrContent}; use style::values::specified::{NoCalcLength, PositionComponent}; use style::values::specified::position::Y; @@ -110,10 +110,7 @@ mod shorthand_serialization { let line = TextDecorationLine::OVERLINE; let style = TextDecorationStyle::dotted; - let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(128, 0, 128, 255)), - authored: None - }; + let color = RGBA::new(128, 0, 128, 255).into(); properties.push(PropertyDeclaration::TextDecorationLine(line)); properties.push(PropertyDeclaration::TextDecorationStyle(style)); @@ -129,7 +126,7 @@ mod shorthand_serialization { let line = TextDecorationLine::UNDERLINE; let style = TextDecorationStyle::solid; - let color = CSSColor::currentcolor(); + let color = Color::currentcolor(); properties.push(PropertyDeclaration::TextDecorationLine(line)); properties.push(PropertyDeclaration::TextDecorationStyle(style)); @@ -229,10 +226,7 @@ mod shorthand_serialization { properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone())); properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone())); - let blue = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), - authored: None - }; + let blue = Color::rgba(RGBA::new(0, 0, 255, 255)); properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderRightColor(blue.clone())); @@ -262,10 +256,7 @@ mod shorthand_serialization { properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone())); properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone())); - let blue = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), - authored: None - }; + let blue = Color::rgba(RGBA::new(0, 0, 255, 255)); properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderRightColor(blue.clone())); @@ -332,15 +323,8 @@ mod shorthand_serialization { fn border_color_should_serialize_correctly() { let mut properties = Vec::new(); - let red = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), - authored: None - }; - - let blue = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(0, 0, 255, 255)), - authored: None - }; + let red = Color::rgba(RGBA::new(255, 0, 0, 255)); + let blue = Color::rgba(RGBA::new(0, 0, 255, 255)); properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderRightColor(red.clone())); @@ -405,10 +389,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = BorderStyle::solid; - let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), - authored: None - }; + let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::BorderTopWidth(width)); properties.push(PropertyDeclaration::BorderTopStyle(style)); @@ -418,10 +399,10 @@ mod shorthand_serialization { assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);"); } - fn get_border_property_values() -> (BorderSideWidth, BorderStyle, CSSColor) { + fn get_border_property_values() -> (BorderSideWidth, BorderStyle, Color) { (BorderSideWidth::Length(Length::from_px(4f32)), BorderStyle::solid, - CSSColor::currentcolor()) + Color::currentcolor()) } #[test] @@ -532,10 +513,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = Either::Second(BorderStyle::solid); - let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), - authored: None - }; + let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineStyle(style)); @@ -551,10 +529,7 @@ mod shorthand_serialization { let width = BorderSideWidth::Length(Length::from_px(4f32)); let style = Either::First(Auto); - let color = CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), - authored: None - }; + let color = RGBA::new(255, 0, 0, 255).into(); properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineStyle(style)); properties.push(PropertyDeclaration::OutlineColor(color)); diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 686a3979a9a..e8967c54c0c 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -158,9 +158,9 @@ fn test_parse_stylesheet() { )), block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![ (PropertyDeclaration::BackgroundColor( - longhands::background_color::SpecifiedValue { + longhands::background_color::SpecifiedValue::Numeric { authored: Some("blue".to_owned().into_boxed_str()), - parsed: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 255, 255)), + parsed: cssparser::RGBA::new(0, 0, 255, 255), } ), Importance::Normal), diff --git a/tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini b/tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini deleted file mode 100644 index 5f750141b21..00000000000 --- a/tests/wpt/metadata-css/cssom-1_dev/html/cssstyledeclaration-csstext.htm.ini +++ /dev/null @@ -1,5 +0,0 @@ -[cssstyledeclaration-csstext.htm] - type: testharness - [uppercase value] - expected: FAIL - |