diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index 92675468073..52cfec65d74 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; @@ -399,6 +400,11 @@ extern "C" { *const ::std::os::raw::c_char, 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); } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 499c9c9d4e1..50c4e923cb8 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use app_units::Au; -use cssparser::Parser; +use cssparser::{Parser, ToCss}; use env_logger; use euclid::Size2D; use parking_lot::RwLock; @@ -30,11 +30,13 @@ 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; @@ -436,6 +438,39 @@ pub extern "C" fn Servo_DeclarationBlock_ClearCachePointer(declarations: ServoDe GeckoDeclarationBlock::as_arc(&declarations).cache.store(ptr::null_mut(), Ordering::Relaxed) } +#[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 {