diff --git a/components/style/values/specified/gecko.rs b/components/style/values/specified/gecko.rs index 7f625be4794..7b5c51928be 100644 --- a/components/style/values/specified/gecko.rs +++ b/components/style/values/specified/gecko.rs @@ -5,12 +5,14 @@ //! Specified types for legacy Gecko-only properties. use cssparser::{Parser, Token}; -use gecko_bindings::structs; -use gecko_bindings::sugar::ns_css_value::ToNsCssValue; +use gecko::values::GeckoStyleCoordConvertible; +use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut}; use parser::{Parse, ParserContext}; -use style_traits::{ParseError, StyleParseErrorKind}; -use values::CSSFloat; +use std::fmt; +use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use style_traits::values::SequenceWriter; use values::computed; +use values::computed::length::CSSPixelLength; use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint; use values::generics::rect::Rect; use values::specified::length::LengthOrPercentage; @@ -32,10 +34,10 @@ impl Parse for ScrollSnapPoint { } /// A component of an IntersectionObserverRootMargin. -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, ToCss)] pub enum PixelOrPercentage { /// An absolute length in pixels (px) - Px(CSSFloat), + Pixel(CSSPixelLength), /// A percentage (%) Percentage(computed::Percentage), } @@ -50,7 +52,7 @@ impl Parse for PixelOrPercentage { let value = match *token { Token::Dimension { value, ref unit, .. } => { match_ignore_ascii_case! { unit, - "px" => Ok(PixelOrPercentage::Px(value)), + "px" => Ok(PixelOrPercentage::Pixel(CSSPixelLength::new(value))), _ => Err(()), } } @@ -67,17 +69,22 @@ impl Parse for PixelOrPercentage { } } -impl ToNsCssValue for PixelOrPercentage { - fn convert(self, nscssvalue: &mut structs::nsCSSValue) { - match self { - PixelOrPercentage::Px(px) => { - unsafe { nscssvalue.set_px(px); } - } - PixelOrPercentage::Percentage(pc) => { - unsafe { nscssvalue.set_percentage(pc.0); } - } +impl GeckoStyleCoordConvertible for PixelOrPercentage { + fn to_gecko_style_coord(&self, coord: &mut T) { + match *self { + PixelOrPercentage::Pixel(ref l) => l.to_gecko_style_coord(coord), + PixelOrPercentage::Percentage(ref pc) => pc.to_gecko_style_coord(coord), } } + + fn from_gecko_style_coord(coord: &T) -> Option { + CSSPixelLength::from_gecko_style_coord(coord) + .map(PixelOrPercentage::Pixel) + .or_else(|| { + computed::Percentage::from_gecko_style_coord(coord) + .map(PixelOrPercentage::Percentage) + }) + } } /// The value of an IntersectionObserver's rootMargin property. @@ -97,3 +104,20 @@ impl Parse for IntersectionObserverRootMargin { Ok(IntersectionObserverRootMargin(rect)) } } + +// Strictly speaking this is not ToCss. It's serializing for DOM. But +// we can just reuse the infrastructure of this. +// +// +impl ToCss for IntersectionObserverRootMargin { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { + // We cannot use the ToCss impl of Rect, because that would + // merge items when they are equal. We want to list them all. + let mut writer = SequenceWriter::new(dest, " "); + let rect = &self.0; + writer.item(&rect.0)?; + writer.item(&rect.1)?; + writer.item(&rect.2)?; + writer.item(&rect.3) + } +} diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 77023cc6bc0..7db1872f487 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -157,8 +157,9 @@ use style::values::{CustomIdent, KeyframesName}; use style::values::animated::{Animate, Procedure, ToAnimatedZero}; use style::values::computed::{Context, ToComputedValue}; use style::values::distance::ComputeSquaredDistance; +use style::values::generics::rect::Rect; use style::values::specified; -use style::values::specified::gecko::IntersectionObserverRootMargin; +use style::values::specified::gecko::{IntersectionObserverRootMargin, PixelOrPercentage}; use style::values::specified::source_size_list::SourceSizeList; use style_traits::{CssWriter, ParsingMode, StyleParseErrorKind, ToCss}; use super::error_reporter::ErrorReporter; @@ -5204,17 +5205,17 @@ pub extern "C" fn Servo_ComputeColor( } #[no_mangle] -pub extern "C" fn Servo_ParseIntersectionObserverRootMargin( +pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_Parse( value: *const nsAString, - result: *mut structs::nsCSSRect, + result: *mut structs::nsStyleSides, ) -> bool { - let value = unsafe { value.as_ref().unwrap().to_string() }; - let result = unsafe { result.as_mut().unwrap() }; + let value = value.as_ref().unwrap().to_string(); + let result = result.as_mut().unwrap(); let mut input = ParserInput::new(&value); let mut parser = Parser::new(&mut input); - let url_data = unsafe { dummy_url_data() }; + let url_data = dummy_url_data(); let context = ParserContext::new( Origin::Author, url_data, @@ -5228,17 +5229,25 @@ pub extern "C" fn Servo_ParseIntersectionObserverRootMargin( }); match margin { Ok(margin) => { - let rect = margin.0; - result.mTop.set_from(rect.0); - result.mRight.set_from(rect.1); - result.mBottom.set_from(rect.2); - result.mLeft.set_from(rect.3); + margin.0.to_gecko_rect(result); true } Err(..) => false, } } +#[no_mangle] +pub unsafe extern "C" fn Servo_IntersectionObserverRootMargin_ToString( + rect: *const structs::nsStyleSides, + result: *mut nsAString, +) { + let rect = Rect:::: + from_gecko_rect(rect.as_ref().unwrap()).unwrap(); + let root_margin = IntersectionObserverRootMargin(rect); + let mut writer = CssWriter::new(result.as_mut().unwrap()); + root_margin.to_css(&mut writer).unwrap(); +} + #[no_mangle] pub extern "C" fn Servo_ParseTransformIntoMatrix( value: *const nsAString,