Use Gecko nsCSSFontFaceRule for font face rule. r=Manishearth
draft
Use Gecko nsCSSFontFaceRule for font face rule. r=Manishearth
MozReview-Commit-ID: C7oKPKqSfR2
--- 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,