diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index c88d389bd3b..5f0f0d19a78 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -2471,6 +2471,11 @@ extern "C" { CSSPseudoElementType) -> ServoComputedValuesStrong; } +extern "C" { + pub fn Servo_SerializeFontValueForCanvas(declarations: + RawServoDeclarationBlockBorrowed, + buffer: *mut nsAString); +} extern "C" { pub fn Servo_GetStyleFont(computed_values: ServoComputedValuesBorrowedOrNull) diff --git a/components/style/gecko/generated/structs_debug.rs b/components/style/gecko/generated/structs_debug.rs index b8bd2ca8e5d..8f4e4f16319 100644 --- a/components/style/gecko/generated/structs_debug.rs +++ b/components/style/gecko/generated/structs_debug.rs @@ -34192,7 +34192,7 @@ pub mod root { root::nsCharTraits ) )); } #[test] - fn __bindgen_test_layout__bindgen_ty_id_210589_instantiation_99() { + fn __bindgen_test_layout__bindgen_ty_id_210592_instantiation_99() { assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( "Size of template specialization: " , stringify ! ( u8 ) )); @@ -34201,7 +34201,7 @@ pub mod root { ) )); } #[test] - fn __bindgen_test_layout__bindgen_ty_id_210625_instantiation_100() { + fn __bindgen_test_layout__bindgen_ty_id_210628_instantiation_100() { assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( "Size of template specialization: " , stringify ! ( u8 ) )); diff --git a/components/style/gecko/generated/structs_release.rs b/components/style/gecko/generated/structs_release.rs index bbfaaee933a..a530ced0463 100644 --- a/components/style/gecko/generated/structs_release.rs +++ b/components/style/gecko/generated/structs_release.rs @@ -33682,7 +33682,7 @@ pub mod root { root::nsCharTraits ) )); } #[test] - fn __bindgen_test_layout__bindgen_ty_id_206916_instantiation_97() { + fn __bindgen_test_layout__bindgen_ty_id_206919_instantiation_97() { assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( "Size of template specialization: " , stringify ! ( u8 ) )); @@ -33691,7 +33691,7 @@ pub mod root { ) )); } #[test] - fn __bindgen_test_layout__bindgen_ty_id_206952_instantiation_98() { + fn __bindgen_test_layout__bindgen_ty_id_206955_instantiation_98() { assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( "Size of template specialization: " , stringify ! ( u8 ) )); diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 74a138721e7..1bd565f2153 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -12,6 +12,7 @@ use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter}; use error_reporting::ParseErrorReporter; use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error}; use std::fmt; +use std::slice::Iter; use style_traits::ToCss; use stylesheets::{CssRuleType, Origin, UrlExtraData}; use super::*; @@ -54,6 +55,25 @@ pub struct PropertyDeclarationBlock { longhands: LonghandIdSet, } +/// Iterator for PropertyDeclaration to be generated from PropertyDeclarationBlock. +#[derive(Clone)] +pub struct PropertyDeclarationIterator<'a> { + iter: Iter<'a, (PropertyDeclaration, Importance)>, +} + +impl<'a> Iterator for PropertyDeclarationIterator<'a> { + type Item = &'a PropertyDeclaration; + #[inline] + fn next(&mut self) -> Option<&'a PropertyDeclaration> { + // we use this function because a closure won't be `Clone` + fn get_declaration(dec: &(PropertyDeclaration, Importance)) + -> &PropertyDeclaration { + &dec.0 + } + self.iter.next().map(get_declaration as fn(_) -> _) + } +} + impl fmt::Debug for PropertyDeclarationBlock { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.declarations.fmt(f) @@ -93,6 +113,13 @@ impl PropertyDeclarationBlock { &self.declarations } + /// Iterate over only PropertyDeclaration. + pub fn declarations_iter(&self) -> PropertyDeclarationIterator { + PropertyDeclarationIterator { + iter: self.declarations.iter(), + } + } + /// Returns whether this block contains any declaration with `!important`. /// /// This is based on the `important_count` counter, @@ -369,15 +396,10 @@ impl PropertyDeclarationBlock { } } Ok(shorthand) => { - // we use this function because a closure won't be `Clone` - fn get_declaration(dec: &(PropertyDeclaration, Importance)) - -> &PropertyDeclaration { - &dec.0 - } if !self.declarations.iter().all(|decl| decl.0.shorthands().contains(&shorthand)) { return Err(fmt::Error) } - let iter = self.declarations.iter().map(get_declaration as fn(_) -> _); + let iter = self.declarations_iter(); match shorthand.get_shorthand_appendable_value(iter) { Some(AppendableValue::Css { css, .. }) => { dest.write_str(css) diff --git a/components/style/properties/shorthand/font.mako.rs b/components/style/properties/shorthand/font.mako.rs index 18e2b97d387..acb7199d486 100644 --- a/components/style/properties/shorthand/font.mako.rs +++ b/components/style/properties/shorthand/font.mako.rs @@ -122,8 +122,67 @@ SomeSystem, None } + % endif + enum SerializeFor { + Normal, + % if product == "gecko": + Canvas, + % endif + } - impl<'a> LonghandsToSerialize<'a> { + impl<'a> LonghandsToSerialize<'a> { + fn to_css_for(&self, + serialize_for: SerializeFor, + dest: &mut W) -> fmt::Result where W: fmt::Write { + % if product == "gecko": + match self.check_system() { + CheckSystemResult::AllSystem(sys) => return sys.to_css(dest), + CheckSystemResult::SomeSystem => return Ok(()), + CheckSystemResult::None => () + } + % endif + + % if product == "gecko" or data.testing: + % for name in gecko_sub_properties: + if self.font_${name} != &font_${name}::get_initial_specified_value() { + return Ok(()); + } + % endfor + % endif + + // In case of serialization for canvas font, we need to drop + // initial values of properties other than size and family. + % for name in "style variant_caps weight stretch".split(): + let needs_this_property = match serialize_for { + SerializeFor::Normal => true, + % if product == "gecko": + SerializeFor::Canvas => + self.font_${name} != &font_${name}::get_initial_specified_value(), + % endif + }; + if needs_this_property { + self.font_${name}.to_css(dest)?; + dest.write_str(" ")?; + } + % endfor + + self.font_size.to_css(dest)?; + + match *self.line_height { + line_height::SpecifiedValue::Normal => {}, + _ => { + dest.write_str("/")?; + self.line_height.to_css(dest)?; + } + } + + dest.write_str(" ")?; + self.font_family.to_css(dest)?; + + Ok(()) + } + + % if product == "gecko": /// Check if some or all members are system fonts fn check_system(&self) -> CheckSystemResult { let mut sys = None; @@ -148,47 +207,18 @@ CheckSystemResult::None } } - } - % endif + + /// Serialize the shorthand value for canvas font attribute. + pub fn to_css_for_canvas(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.to_css_for(SerializeFor::Canvas, dest) + } + % endif + } // This may be a bit off, unsure, possibly needs changes impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - % if product == "gecko": - match self.check_system() { - CheckSystemResult::AllSystem(sys) => return sys.to_css(dest), - CheckSystemResult::SomeSystem => return Ok(()), - CheckSystemResult::None => () - } - % endif - - % if product == "gecko" or data.testing: - % for name in gecko_sub_properties: - if self.font_${name} != &font_${name}::get_initial_specified_value() { - return Ok(()); - } - % endfor - % endif - - % for name in "style variant_caps weight stretch".split(): - self.font_${name}.to_css(dest)?; - dest.write_str(" ")?; - % endfor - - self.font_size.to_css(dest)?; - - match *self.line_height { - line_height::SpecifiedValue::Normal => {}, - _ => { - dest.write_str("/")?; - self.line_height.to_css(dest)?; - } - } - - dest.write_str(" ")?; - self.font_family.to_css(dest)?; - - Ok(()) + self.to_css_for(SerializeFor::Normal, dest) } } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index bc4db3e7204..c3617682dc7 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -1434,6 +1434,29 @@ pub extern "C" fn Servo_DeclarationBlock_SerializeOneValue( }) } +#[no_mangle] +pub extern "C" fn Servo_SerializeFontValueForCanvas( + declarations: RawServoDeclarationBlockBorrowed, + buffer: *mut nsAString) { + use style::properties::shorthands::font; + + read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| { + let longhands = match font::LonghandsToSerialize::from_iter(decls.declarations_iter()) { + Ok(l) => l, + Err(()) => { + warn!("Unexpected property!"); + return; + } + }; + + let mut string = String::new(); + let rv = longhands.to_css_for_canvas(&mut string); + debug_assert!(rv.is_ok()); + + write!(unsafe { &mut *buffer }, "{}", string).expect("Failed to copy string"); + }) +} + #[no_mangle] pub extern "C" fn Servo_DeclarationBlock_Count(declarations: RawServoDeclarationBlockBorrowed) -> u32 { read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {