Use Gecko nsCSSFontFaceRule for font face rule. r=Manishearth draft
authorXidorn Quan <me@upsuper.org>
Wed, 29 Mar 2017 10:41:00 +1100
changeset 552762 91f6a57588afedf6fc9f2af7d9d3a67be93b9984
parent 552761 036a91e26a4a065e1b8dc5c0769b86b9511c8c19
child 552763 738af53d5d4050c7cf736a974e48d7db6357de82
push id51449
push userxquan@mozilla.com
push dateTue, 28 Mar 2017 23:45:05 +0000
reviewersManishearth
milestone55.0a1
Use Gecko nsCSSFontFaceRule for font face rule. r=Manishearth MozReview-Commit-ID: C7oKPKqSfR2
servo/components/style/gecko/mod.rs
servo/components/style/gecko/rules.rs
servo/components/style/lib.rs
servo/components/style/stylesheets.rs
--- a/servo/components/style/gecko/mod.rs
+++ b/servo/components/style/gecko/mod.rs
@@ -8,15 +8,16 @@
 mod non_ts_pseudo_class_list;
 
 pub mod arc_types;
 pub mod conversions;
 pub mod data;
 pub mod global_style_data;
 pub mod media_queries;
 pub mod restyle_damage;
+pub mod rules;
 pub mod selector_parser;
 pub mod snapshot;
 pub mod snapshot_helpers;
 pub mod traversal;
 pub mod url;
 pub mod values;
 pub mod wrapper;
new file mode 100644
--- /dev/null
+++ b/servo/components/style/gecko/rules.rs
@@ -0,0 +1,121 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Bindings for CSS Rule objects
+
+use gecko_bindings::bindings;
+use gecko_bindings::structs::{self, CSSFontFaceDescriptors, nsCSSFontFaceRule};
+use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr};
+use font_face::{FontFaceData, Source};
+use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard};
+use std::fmt;
+
+/// A @font-face rule
+pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
+
+fn set_font_face_descriptors(descriptors: &mut CSSFontFaceDescriptors,
+                             data: FontFaceData) {
+    // font-family
+    descriptors.mFamily.set_string_from_atom(&data.family.0);
+
+    macro_rules! map_enum {
+        ($target:ident = ($data:ident: $prop:ident) {
+            $($servo:ident => $gecko:ident,)+
+        }) => {{
+            use computed_values::$prop::T;
+            descriptors.$target.set_enum(match data.$data {
+                $( T::$servo => structs::$gecko as i32, )+
+            })
+        }}
+    }
+
+    // font-style
+    map_enum!(mStyle = (style: font_style) {
+        normal => NS_FONT_STYLE_NORMAL,
+        italic => NS_FONT_STYLE_ITALIC,
+        oblique => NS_FONT_STYLE_OBLIQUE,
+    });
+
+    // font-weight
+    descriptors.mWeight.set_integer(data.weight as i32);
+
+    // font-stretch
+    map_enum!(mStretch = (stretch: font_stretch) {
+        normal          => NS_FONT_STRETCH_NORMAL,
+        ultra_condensed => NS_FONT_STRETCH_ULTRA_CONDENSED,
+        extra_condensed => NS_FONT_STRETCH_EXTRA_CONDENSED,
+        condensed       => NS_FONT_STRETCH_CONDENSED,
+        semi_condensed  => NS_FONT_STRETCH_SEMI_CONDENSED,
+        semi_expanded   => NS_FONT_STRETCH_SEMI_EXPANDED,
+        expanded        => NS_FONT_STRETCH_EXPANDED,
+        extra_expanded  => NS_FONT_STRETCH_EXTRA_EXPANDED,
+        ultra_expanded  => NS_FONT_STRETCH_ULTRA_EXPANDED,
+    });
+
+    // src
+    let src_len = data.sources.iter().fold(0, |acc, src| {
+        acc + match *src {
+            // Each format hint takes one position in the array of mSrc.
+            Source::Url(ref url) => url.format_hints.len() + 1,
+            Source::Local(_) => 1,
+        }
+    });
+    let mut target_srcs =
+        descriptors.mSrc.set_array(src_len as i32).as_mut_slice().iter_mut();
+    macro_rules! next { () => {
+        target_srcs.next().expect("Length of target_srcs should be enough")
+    } }
+    for src in data.sources.iter() {
+        match *src {
+            Source::Url(ref url) => {
+                next!().set_url(&url.url);
+                for hint in url.format_hints.iter() {
+                    next!().set_font_format(&hint);
+                }
+            }
+            Source::Local(ref name) => {
+                next!().set_local_font(&name.0);
+            }
+        }
+    }
+    debug_assert!(target_srcs.next().is_none(), "Should have filled all slots");
+
+    // unicode-range
+    let target_ranges = descriptors.mUnicodeRange
+        .set_array((data.unicode_range.len() * 2) as i32)
+        .as_mut_slice().chunks_mut(2);
+    for (range, target) in data.unicode_range.iter().zip(target_ranges) {
+        target[0].set_integer(range.start as i32);
+        target[1].set_integer(range.end as i32);
+    }
+
+    // The following three descriptors are not implemented yet.
+    // font-feature-settings
+    descriptors.mFontFeatureSettings.set_normal();
+    // font-language-override
+    descriptors.mFontLanguageOverride.set_normal();
+    // font-display
+    descriptors.mDisplay.set_enum(structs::NS_FONT_DISPLAY_AUTO as i32);
+}
+
+impl From<FontFaceData> for FontFaceRule {
+    fn from(data: FontFaceData) -> FontFaceRule {
+        let mut result = unsafe {
+            UniqueRefPtr::from_addrefed(bindings::Gecko_CSSFontFaceRule_Create())
+        };
+        set_font_face_descriptors(&mut result.mDecl.mDescriptors, data);
+        result.get()
+    }
+}
+
+impl ToCssWithGuard for FontFaceRule {
+    fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
+    where W: fmt::Write {
+        ns_auto_string!(css_text);
+        unsafe {
+            bindings::Gecko_CSSFontFaceRule_GetCssText(self.get(), &mut *css_text);
+        }
+        write!(dest, "{}", css_text)
+    }
+}
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -52,17 +52,19 @@ extern crate heapsize;
 #[cfg(feature = "servo")] #[macro_use] extern crate html5ever_atoms;
 #[macro_use]
 extern crate lazy_static;
 #[macro_use]
 extern crate log;
 #[allow(unused_extern_crates)]
 #[macro_use]
 extern crate matches;
-#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
+#[cfg(feature = "gecko")]
+#[macro_use]
+extern crate nsstring_vendor as nsstring;
 #[cfg(feature = "gecko")] extern crate num_cpus;
 extern crate num_integer;
 extern crate num_traits;
 extern crate ordered_float;
 extern crate parking_lot;
 extern crate pdqsort;
 extern crate rayon;
 extern crate selectors;
--- a/servo/components/style/stylesheets.rs
+++ b/servo/components/style/stylesheets.rs
@@ -6,17 +6,21 @@
 
 #![deny(missing_docs)]
 
 use {Atom, Prefix, Namespace};
 use cssparser::{AtRuleParser, Parser, QualifiedRuleParser};
 use cssparser::{AtRuleType, RuleListParser, SourcePosition, Token, parse_one_rule};
 use cssparser::ToCss as ParserToCss;
 use error_reporting::ParseErrorReporter;
-use font_face::{FontFaceData, parse_font_face_block};
+#[cfg(feature = "servo")]
+use font_face::FontFaceData;
+use font_face::parse_font_face_block;
+#[cfg(feature = "gecko")]
+pub use gecko::rules::FontFaceRule;
 use keyframes::{Keyframe, parse_keyframe_list};
 use media_queries::{Device, MediaList, parse_media_query_list};
 use parking_lot::RwLock;
 use parser::{ParserContext, ParserContextExtraData, log_css_error};
 use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
 use selector_parser::{SelectorImpl, SelectorParser};
 use selectors::parser::SelectorList;
 use servo_config::prefs::PREFS;
@@ -547,16 +551,17 @@ impl ToCssWithGuard for StyleRule {
         }
         // Step 5
         try!(dest.write_str("}"));
         Ok(())
     }
 }
 
 /// A @font-face rule
+#[cfg(feature = "servo")]
 pub type FontFaceRule = FontFaceData;
 
 impl Stylesheet {
     /// Updates an empty stylesheet from a given string of text.
     pub fn update_from_str(existing: &Stylesheet,
                            css: &str,
                            stylesheet_loader: Option<&StylesheetLoader>,
                            error_reporter: &ParseErrorReporter,