Skip to content

Commit

Permalink
style: Add FFI function for parsing IntersectionObserver rootMargin v…
Browse files Browse the repository at this point in the history
…alues.
  • Loading branch information
heycam committed Oct 17, 2017
1 parent eecee32 commit ef28ccb
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 5 deletions.
14 changes: 12 additions & 2 deletions components/style/gecko_bindings/sugar/ns_css_value.rs
Expand Up @@ -75,17 +75,27 @@ impl nsCSSValue {
pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) {
match lop {
LengthOrPercentage::Length(px) => {
bindings::Gecko_CSSValue_SetPixelLength(self, px.px())
self.set_px(px.px())
}
LengthOrPercentage::Percentage(pc) => {
bindings::Gecko_CSSValue_SetPercentage(self, pc.0)
self.set_percentage(pc.0)
}
LengthOrPercentage::Calc(calc) => {
bindings::Gecko_CSSValue_SetCalc(self, calc.into())
}
}
}

/// Sets a px value to this nsCSSValue.
pub unsafe fn set_px(&mut self, px: f32) {
bindings::Gecko_CSSValue_SetPixelLength(self, px)
}

/// Sets a percentage value to this nsCSSValue.
pub unsafe fn set_percentage(&mut self, unit_value: f32) {
bindings::Gecko_CSSValue_SetPercentage(self, unit_value)
}

/// Returns LengthOrPercentage value.
pub unsafe fn get_lop(&self) -> LengthOrPercentage {
use values::computed::Length;
Expand Down
71 changes: 69 additions & 2 deletions components/style/values/specified/gecko.rs
Expand Up @@ -4,10 +4,15 @@

//! Specified types for legacy Gecko-only properties.

use cssparser::Parser;
use cssparser::{Parser, Token};
use gecko_bindings::structs;
use gecko_bindings::sugar::ns_css_value::ToNsCssValue;
use parser::{Parse, ParserContext};
use style_traits::ParseError;
use style_traits::{ParseError, StyleParseErrorKind};
use values::CSSFloat;
use values::computed;
use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use values::generics::rect::Rect;
use values::specified::length::LengthOrPercentage;

/// A specified type for scroll snap points.
Expand All @@ -25,3 +30,65 @@ impl Parse for ScrollSnapPoint {
Ok(GenericScrollSnapPoint::Repeat(length))
}
}

/// A component of an IntersectionObserverRootMargin.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum PixelOrPercentage {
/// An absolute length in pixels (px)
Px(CSSFloat),
/// A percentage (%)
Percentage(computed::Percentage),
}

impl Parse for PixelOrPercentage {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
let token = input.next()?;
let value = match *token {
Token::Dimension { value, ref unit, .. } => {
match_ignore_ascii_case! { unit,
"px" => Ok(PixelOrPercentage::Px(value)),
_ => Err(()),
}
}
Token::Percentage { unit_value, .. } => {
Ok(PixelOrPercentage::Percentage(
computed::Percentage(unit_value)
))
}
_ => Err(()),
};
value.map_err(|()| {
location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
})
}
}

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); }
}
}
}
}

/// The value of an IntersectionObserver's rootMargin property.
pub struct IntersectionObserverRootMargin(pub Rect<PixelOrPercentage>);

impl Parse for IntersectionObserverRootMargin {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, PixelOrPercentage::parse)?;
Ok(IntersectionObserverRootMargin(rect))
}
}
40 changes: 39 additions & 1 deletion ports/geckolib/glue.rs
Expand Up @@ -112,7 +112,7 @@ use style::gecko_bindings::sugar::refptr::RefPtr;
use style::gecko_properties::style_structs;
use style::invalidation::element::restyle_hints;
use style::media_queries::{Device, MediaList, parse_media_query_list};
use style::parser::{ParserContext, self};
use style::parser::{Parse, ParserContext, self};
use style::properties::{CascadeFlags, ComputedValues, DeclarationSource, Importance};
use style::properties::{IS_FIELDSET_CONTENT, IS_LINK, IS_VISITED_LINK, LonghandIdSet};
use style::properties::{LonghandId, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
Expand Down Expand Up @@ -146,6 +146,7 @@ use style::values::animated::{Animate, Procedure, ToAnimatedZero};
use style::values::computed::{Context, ToComputedValue};
use style::values::distance::ComputeSquaredDistance;
use style::values::specified;
use style::values::specified::gecko::IntersectionObserverRootMargin;
use style_traits::{PARSING_MODE_DEFAULT, ToCss};
use super::error_reporter::ErrorReporter;
use super::stylesheet_loader::StylesheetLoader;
Expand Down Expand Up @@ -2212,6 +2213,7 @@ pub extern "C" fn Servo_ParseEasing(
) -> bool {
use style::properties::longhands::transition_timing_function;

// FIXME Dummy URL data would work fine here.
let url_data = unsafe { RefPtr::from_ptr_ref(&data) };
let context = ParserContext::new(Origin::Author,
url_data,
Expand Down Expand Up @@ -4270,3 +4272,39 @@ pub extern "C" fn Servo_ComputeColor(
Err(_) => false,
}
}

#[no_mangle]
pub extern "C" fn Servo_ParseIntersectionObserverRootMargin(
value: *const nsAString,
result: *mut structs::nsCSSRect,
) -> bool {
let value = unsafe { value.as_ref().unwrap().to_string() };
let result = unsafe { 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 context = ParserContext::new(
Origin::Author,
url_data,
Some(CssRuleType::Style),
PARSING_MODE_DEFAULT,
QuirksMode::NoQuirks,
);

let margin = parser.parse_entirely(|p| {
IntersectionObserverRootMargin::parse(&context, p)
});
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);
true
}
Err(..) => false,
}
}

0 comments on commit ef28ccb

Please sign in to comment.