diff options
-rw-r--r-- | components/style/gecko/wrapper.rs | 10 | ||||
-rw-r--r-- | components/style/gecko_bindings/bindings.rs | 28 | ||||
-rw-r--r-- | ports/geckolib/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/geckolib/Cargo.toml | 1 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 128 | ||||
-rw-r--r-- | ports/geckolib/lib.rs | 1 | ||||
-rw-r--r-- | tests/unit/stylo/Cargo.toml | 1 | ||||
-rw-r--r-- | tests/unit/stylo/lib.rs | 1 |
8 files changed, 170 insertions, 2 deletions
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index f2a7532883c..407ff4694e4 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -70,6 +70,16 @@ pub struct GeckoDeclarationBlock { pub immutable: AtomicBool, } +impl PartialEq for GeckoDeclarationBlock { + fn eq(&self, other: &GeckoDeclarationBlock) -> bool { + match (&self.declarations, &other.declarations) { + (&None, &None) => true, + (&Some(ref s), &Some(ref other)) => *s.read() == *other.read(), + _ => false, + } + } +} + unsafe impl HasFFI for GeckoDeclarationBlock { type FFIType = bindings::ServoDeclarationBlock; } diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index 3781bbe81d4..3529dce9b87 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko_bindings/bindings.rs @@ -165,6 +165,7 @@ use gecko_bindings::structs::nsINode; use gecko_bindings::structs::nsIDocument; use gecko_bindings::structs::nsIPrincipal; use gecko_bindings::structs::nsIURI; +use gecko_bindings::structs::nsString; use gecko_bindings::structs::RawGeckoNode; use gecko_bindings::structs::RawGeckoElement; use gecko_bindings::structs::RawGeckoDocument; @@ -400,6 +401,11 @@ extern "C" { aLength: u32) -> bool; } extern "C" { + pub fn Gecko_Utf8SliceToString(aString: *mut nsString, + aBuffer: *const u8, + aBufferLen: usize); +} +extern "C" { pub fn Gecko_FontFamilyList_Clear(aList: *mut FontFamilyList); } extern "C" { @@ -848,6 +854,18 @@ extern "C" { RawServoStyleSheetBorrowed); } extern "C" { + pub fn Servo_ParseProperty(property_bytes: *const u8, + property_length: u32, + value_bytes: *const u8, + value_length: u32, + base_bytes: *const u8, + base_length: u32, + base: *mut ThreadSafeURIHolder, + referrer: *mut ThreadSafeURIHolder, + principal: *mut ThreadSafePrincipalHolder) + -> ServoDeclarationBlockStrong; +} +extern "C" { pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32, cache: *mut nsHTMLCSSStyleSheet) -> ServoDeclarationBlockStrong; @@ -861,6 +879,11 @@ extern "C" { ServoDeclarationBlockBorrowed); } extern "C" { + pub fn Servo_DeclarationBlock_Equals(a: ServoDeclarationBlockBorrowed, + b: ServoDeclarationBlockBorrowed) + -> bool; +} +extern "C" { pub fn Servo_DeclarationBlock_GetCache(declarations: ServoDeclarationBlockBorrowed) -> *mut nsHTMLCSSStyleSheet; @@ -930,6 +953,11 @@ extern "C" { set: RawServoStyleSetBorrowedMut); } extern "C" { + pub fn Servo_RestyleWithAddedDeclaration(declarations: ServoDeclarationBlockBorrowed, + previous_style: ServoComputedValuesBorrowed) + -> ServoComputedValuesStrong; +} +extern "C" { pub fn Servo_GetStyleFont(computed_values: ServoComputedValuesBorrowedOrNull) -> *const nsStyleFont; diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock index 8b9e70c0d8f..17b8d28f868 100644 --- a/ports/geckolib/Cargo.lock +++ b/ports/geckolib/Cargo.lock @@ -3,6 +3,7 @@ name = "geckoservo" version = "0.0.1" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -407,6 +408,7 @@ name = "stylo_tests" version = "0.0.1" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "geckoservo 0.0.1", diff --git a/ports/geckolib/Cargo.toml b/ports/geckolib/Cargo.toml index 50260374172..ebe538fabb9 100644 --- a/ports/geckolib/Cargo.toml +++ b/ports/geckolib/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["staticlib", "rlib"] [dependencies] app_units = "0.3" +cssparser = {version = "0.7"} env_logger = "0.3" euclid = "0.10.1" lazy_static = "0.2" diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 4d710c7376c..f7237b59561 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use app_units::Au; +use cssparser::{Parser, ToCss}; use env_logger; use euclid::Size2D; use parking_lot::RwLock; @@ -29,17 +30,22 @@ use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedVal use style::gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclarationBlockStrong}; use style::gecko_bindings::bindings::{ThreadSafePrincipalHolder, ThreadSafeURIHolder}; use style::gecko_bindings::bindings::{nsHTMLCSSStyleSheet, ServoComputedValuesBorrowedOrNull}; +use style::gecko_bindings::bindings::Gecko_Utf8SliceToString; use style::gecko_bindings::bindings::RawServoStyleSetBorrowedMut; use style::gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom}; use style::gecko_bindings::structs::ServoElementSnapshot; use style::gecko_bindings::structs::nsRestyleHint; +use style::gecko_bindings::structs::nsString; use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI}; use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong}; use style::parallel; -use style::parser::ParserContextExtraData; -use style::properties::{ComputedValues, parse_one_declaration}; +use style::parser::{ParserContext, ParserContextExtraData}; +use style::properties::{ComputedValues, Importance, PropertyDeclaration}; +use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock}; +use style::properties::{cascade, parse_one_declaration}; use style::selector_impl::PseudoElementCascadeType; +use style::selector_matching::ApplicableDeclarationBlock; use style::sequential; use style::string_cache::Atom; use style::stylesheets::{Origin, Stylesheet}; @@ -91,6 +97,7 @@ fn restyle_subtree(node: GeckoNode, raw_data: RawServoStyleSetBorrowedMut) { LocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone()); let shared_style_context = SharedStyleContext { + // FIXME (bug 1303229): Use the actual viewport size here viewport_size: Size2D::new(Au(0), Au(0)), screen_size_changed: false, generation: 0, @@ -121,6 +128,35 @@ pub extern "C" fn Servo_RestyleSubtree(node: RawGeckoNodeBorrowed, } #[no_mangle] +pub extern "C" fn Servo_RestyleWithAddedDeclaration(declarations: ServoDeclarationBlockBorrowed, + previous_style: ServoComputedValuesBorrowed) + -> ServoComputedValuesStrong +{ + match GeckoDeclarationBlock::as_arc(&declarations).declarations { + Some(ref declarations) => { + let declaration_block = ApplicableDeclarationBlock { + mixed_declarations: declarations.clone(), + importance: Importance::Normal, + source_order: 0, + specificity: ::std::u32::MAX, + }; + let previous_style = ComputedValues::as_arc(&previous_style); + + // FIXME (bug 1303229): Use the actual viewport size here + let (computed, _) = cascade(Size2D::new(Au(0), Au(0)), + &[declaration_block], + false, + Some(previous_style), + None, + None, + Box::new(StdoutErrorReporter)); + Arc::new(computed).into_strong() + }, + None => ServoComputedValuesStrong::null(), + } +} + +#[no_mangle] pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 { *NUM_THREADS as u32 } @@ -338,6 +374,54 @@ pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) -> () { let _ = data.into_box::<PerDocumentStyleData>(); } + +#[no_mangle] +pub extern "C" fn Servo_ParseProperty(property_bytes: *const u8, + property_length: u32, + value_bytes: *const u8, + value_length: u32, + base_bytes: *const u8, + base_length: u32, + base: *mut ThreadSafeURIHolder, + referrer: *mut ThreadSafeURIHolder, + principal: *mut ThreadSafePrincipalHolder) + -> ServoDeclarationBlockStrong { + // All this string wrangling is temporary until the Gecko string bindings land (bug 1294742). + let name = unsafe { from_utf8_unchecked(slice::from_raw_parts(property_bytes, + property_length as usize)) }; + let value_str = unsafe { from_utf8_unchecked(slice::from_raw_parts(value_bytes, + value_length as usize)) }; + let base_str = unsafe { from_utf8_unchecked(slice::from_raw_parts(base_bytes, + base_length as usize)) }; + let base_url = Url::parse(base_str).unwrap(); + let extra_data = ParserContextExtraData { + base: Some(GeckoArcURI::new(base)), + referrer: Some(GeckoArcURI::new(referrer)), + principal: Some(GeckoArcPrincipal::new(principal)), + }; + + let context = ParserContext::new_with_extra_data(Origin::Author, &base_url, + Box::new(StdoutErrorReporter), + extra_data); + + let mut results = vec![]; + match PropertyDeclaration::parse(name, &context, &mut Parser::new(value_str), + &mut results, false) { + PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {}, + _ => return ServoDeclarationBlockStrong::null(), + } + + let results = results.into_iter().map(|r| (r, Importance::Normal)).collect(); + + Arc::new(GeckoDeclarationBlock { + declarations: Some(Arc::new(RwLock::new(PropertyDeclarationBlock { + declarations: results, + important_count: 0, + }))), + cache: AtomicPtr::new(ptr::null_mut()), + immutable: AtomicBool::new(false), + }).into_strong() +} #[no_mangle] pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32, cache: *mut nsHTMLCSSStyleSheet) @@ -363,6 +447,13 @@ pub extern "C" fn Servo_DeclarationBlock_Release(declarations: ServoDeclarationB } #[no_mangle] +pub extern "C" fn Servo_DeclarationBlock_Equals(a: ServoDeclarationBlockBorrowed, + b: ServoDeclarationBlockBorrowed) + -> bool { + GeckoDeclarationBlock::as_arc(&a) == GeckoDeclarationBlock::as_arc(&b) +} + +#[no_mangle] pub extern "C" fn Servo_DeclarationBlock_GetCache(declarations: ServoDeclarationBlockBorrowed) -> *mut nsHTMLCSSStyleSheet { GeckoDeclarationBlock::as_arc(&declarations).cache.load(Ordering::Relaxed) @@ -379,6 +470,39 @@ pub extern "C" fn Servo_DeclarationBlock_ClearCachePointer(declarations: ServoDe } #[no_mangle] +pub extern "C" fn Servo_DeclarationBlock_SerializeOneValue( + declarations: ServoDeclarationBlockBorrowed, + buffer: *mut nsString) +{ + let mut string = String::new(); + + if let Some(ref declarations) = GeckoDeclarationBlock::as_arc(&declarations).declarations { + declarations.read().to_css(&mut string).unwrap(); + // FIXME: We are expecting |declarations| to be a declaration block with either a single + // longhand property-declaration or a series of longhand property-declarations that make + // up a single shorthand property. As a result, it should be possible to serialize + // |declarations| as a single declaration. However, we only want to return the *value* from + // that single declaration. For now, we just manually strip the property name, colon, + // leading spacing, and trailing space. In future we should find a more robust way to do + // this. + // + // See https://github.com/servo/servo/issues/13423 + debug_assert!(string.find(':').is_some()); + let position = string.find(':').unwrap(); + // Get the value after the first colon and any following whitespace. + let value = &string[(position + 1)..].trim_left(); + debug_assert!(value.ends_with(';')); + let length = value.len() - 1; // Strip last semicolon. + + // FIXME: Once we have nsString bindings for Servo (bug 1294742), we should be able to drop + // this and fill in |buffer| directly. + unsafe { + Gecko_Utf8SliceToString(buffer, value.as_ptr(), length); + } + } +} + +#[no_mangle] pub extern "C" fn Servo_CSSSupports(property: *const u8, property_length: u32, value: *const u8, value_length: u32) -> bool { let property = unsafe { from_utf8_unchecked(slice::from_raw_parts(property, property_length as usize)) }; diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs index 0b6493db278..cdfca9b8653 100644 --- a/ports/geckolib/lib.rs +++ b/ports/geckolib/lib.rs @@ -5,6 +5,7 @@ #[macro_use]extern crate style; extern crate app_units; +extern crate cssparser; extern crate env_logger; extern crate euclid; extern crate libc; diff --git a/tests/unit/stylo/Cargo.toml b/tests/unit/stylo/Cargo.toml index 300f31cea64..87dc62cd042 100644 --- a/tests/unit/stylo/Cargo.toml +++ b/tests/unit/stylo/Cargo.toml @@ -13,6 +13,7 @@ doctest = false [dependencies] app_units = "0.3" +cssparser = {version = "0.7"} env_logger = "0.3" euclid = "0.10.1" lazy_static = "0.2" diff --git a/tests/unit/stylo/lib.rs b/tests/unit/stylo/lib.rs index d4d3711279c..8690c17f517 100644 --- a/tests/unit/stylo/lib.rs +++ b/tests/unit/stylo/lib.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ extern crate app_units; +extern crate cssparser; extern crate env_logger; extern crate euclid; extern crate geckoservo; |