From b43e2fb0dfeb06717f75f579d268d6228056c071 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 1 Apr 2017 09:48:40 +0200 Subject: [PATCH] Macroize conversion of @font-face values to Gecko types --- components/style/font_face.rs | 41 ++++++--- components/style/gecko/rules.rs | 89 ++++++++++--------- components/style/gecko_bindings/sugar/mod.rs | 2 +- .../gecko_bindings/sugar/ns_css_value.rs | 11 +++ 4 files changed, 89 insertions(+), 54 deletions(-) diff --git a/components/style/font_face.rs b/components/style/font_face.rs index b559ea744fe..41a5d992a41 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -12,6 +12,7 @@ use computed_values::{font_style, font_weight, font_stretch}; use computed_values::font_family::FamilyName; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; +#[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors; #[cfg(feature = "gecko")] use cssparser::UnicodeRange; use parser::{ParserContext, log_css_error, Parse}; use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; @@ -174,7 +175,7 @@ impl Parse for Source { macro_rules! font_face_descriptors_common { ( - $( #[$doc: meta] $name: tt $ident: ident: $ty: ty, )* + $( #[$doc: meta] $name: tt $ident: ident / $gecko_ident: ident: $ty: ty, )* ) => { /// Data inside a `@font-face` rule. /// @@ -195,6 +196,19 @@ macro_rules! font_face_descriptors_common { )* } } + + /// Convert to Gecko types + #[cfg(feature = "gecko")] + pub fn set_descriptors(&self, descriptors: &mut CSSFontFaceDescriptors) { + $( + if let Some(ref value) = self.$ident { + descriptors.$gecko_ident.set_from(value) + } + )* + // Leave unset descriptors to eCSSUnit_Null, + // FontFaceSet::FindOrCreateUserFontEntryFromFontFace does the defaulting + // to initial values. + } } impl ToCssWithGuard for FontFaceRuleData { @@ -232,15 +246,16 @@ macro_rules! font_face_descriptors_common { macro_rules! font_face_descriptors { ( mandatory descriptors = [ - $( #[$m_doc: meta] $m_name: tt $m_ident: ident: $m_ty: ty, )* + $( #[$m_doc: meta] $m_name: tt $m_ident: ident / $m_gecko_ident: ident: $m_ty: ty, )* ] optional descriptors = [ - $( #[$o_doc: meta] $o_name: tt $o_ident: ident: $o_ty: ty = $o_initial: expr, )* + $( #[$o_doc: meta] $o_name: tt $o_ident: ident / $o_gecko_ident: ident: $o_ty: ty = + $o_initial: expr, )* ] ) => { font_face_descriptors_common! { - $( #[$m_doc] $m_name $m_ident: $m_ty, )* - $( #[$o_doc] $o_name $o_ident: $o_ty, )* + $( #[$m_doc] $m_name $m_ident / $m_gecko_ident: $m_ty, )* + $( #[$o_doc] $o_name $o_ident / $o_gecko_ident: $o_ty, )* } impl FontFaceRuleData { @@ -286,23 +301,23 @@ macro_rules! font_face_descriptors { font_face_descriptors! { mandatory descriptors = [ /// The name of this font face - "font-family" family: FamilyName, + "font-family" family / mFamily: FamilyName, /// The alternative sources for this font face. - "src" sources: Vec, + "src" sources / mSrc: Vec, ] optional descriptors = [ /// The style of this font face - "font-style" style: font_style::T = font_style::T::normal, + "font-style" style / mStyle: font_style::T = font_style::T::normal, /// The weight of this font face - "font-weight" weight: font_weight::T = font_weight::T::Weight400 /* normal */, + "font-weight" weight / mWeight: font_weight::T = font_weight::T::Weight400 /* normal */, /// The stretch of this font face - "font-stretch" stretch: font_stretch::T = font_stretch::T::normal, + "font-stretch" stretch / mStretch: font_stretch::T = font_stretch::T::normal, /// The ranges of code points outside of which this font face should not be used. - "unicode-range" unicode_range: Vec = vec![ + "unicode-range" unicode_range / mUnicodeRange: Vec = vec![ UnicodeRange { start: 0, end: 0x10FFFF } ], @@ -314,10 +329,10 @@ font_face_descriptors! { font_face_descriptors! { mandatory descriptors = [ /// The name of this font face - "font-family" family: FamilyName, + "font-family" family / mFamily: FamilyName, /// The alternative sources for this font face. - "src" sources: Vec, + "src" sources / mSrc: Vec, ] optional descriptors = [ ] diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs index b0b50547787..548266c4c40 100644 --- a/components/style/gecko/rules.rs +++ b/components/style/gecko/rules.rs @@ -4,9 +4,13 @@ //! Bindings for CSS Rule objects +use computed_values::{font_style, font_weight, font_stretch}; +use computed_values::font_family::FamilyName; +use cssparser::UnicodeRange; use font_face::{FontFaceRuleData, Source}; use gecko_bindings::bindings; -use gecko_bindings::structs::{self, CSSFontFaceDescriptors, nsCSSFontFaceRule}; +use gecko_bindings::structs::{self, nsCSSFontFaceRule, nsCSSValue}; +use gecko_bindings::sugar::ns_css_value::ToNsCssValue; use gecko_bindings::sugar::refptr::{RefPtr, UniqueRefPtr}; use shared_lock::{ToCssWithGuard, SharedRwLockReadGuard}; use std::fmt; @@ -14,40 +18,46 @@ use std::fmt; /// A @font-face rule pub type FontFaceRule = RefPtr; -fn set_font_face_descriptors(descriptors: &mut CSSFontFaceDescriptors, - data: FontFaceRuleData) { - // font-family - if let Some(ref family) = data.family { - descriptors.mFamily.set_string_from_atom(&family.name); +impl ToNsCssValue for FamilyName { + fn convert(&self, nscssvalue: &mut nsCSSValue) { + nscssvalue.set_string_from_atom(&self.name) } +} - macro_rules! map_enum { - ($target:ident = ($data:ident: $prop:ident) { - $($servo:ident => $gecko:ident,)+ - }) => {{ - if let Some(ref value) = data.$data { - use computed_values::$prop::T; - descriptors.$target.set_enum(match *value { - $( T::$servo => structs::$gecko as i32, )+ - }) +impl ToNsCssValue for font_weight::T { + fn convert(&self, nscssvalue: &mut nsCSSValue) { + nscssvalue.set_integer(*self as i32) + } +} + +macro_rules! map_enum { + ( + $( + $prop:ident { + $($servo:ident => $gecko:ident,)+ } - }} + )+ + ) => { + $( + impl ToNsCssValue for $prop::T { + fn convert(&self, nscssvalue: &mut nsCSSValue) { + nscssvalue.set_enum(match *self { + $( $prop::T::$servo => structs::$gecko as i32, )+ + }) + } + } + )+ } +} - // font-style - map_enum!(mStyle = (style: font_style) { +map_enum! { + font_style { normal => NS_FONT_STYLE_NORMAL, italic => NS_FONT_STYLE_ITALIC, oblique => NS_FONT_STYLE_OBLIQUE, - }); - - // font-weight - if let Some(weight) = data.weight { - descriptors.mWeight.set_integer(weight as i32); } - // font-stretch - map_enum!(mStretch = (stretch: font_stretch) { + font_stretch { normal => NS_FONT_STRETCH_NORMAL, ultra_condensed => NS_FONT_STRETCH_ULTRA_CONDENSED, extra_condensed => NS_FONT_STRETCH_EXTRA_CONDENSED, @@ -57,11 +67,12 @@ fn set_font_face_descriptors(descriptors: &mut CSSFontFaceDescriptors, expanded => NS_FONT_STRETCH_EXPANDED, extra_expanded => NS_FONT_STRETCH_EXTRA_EXPANDED, ultra_expanded => NS_FONT_STRETCH_ULTRA_EXPANDED, - }); + } +} - // src - if let Some(ref sources) = data.sources { - let src_len = sources.iter().fold(0, |acc, src| { +impl ToNsCssValue for Vec { + fn convert(&self, nscssvalue: &mut nsCSSValue) { + let src_len = self.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, @@ -69,11 +80,11 @@ fn set_font_face_descriptors(descriptors: &mut CSSFontFaceDescriptors, } }); let mut target_srcs = - descriptors.mSrc.set_array(src_len as i32).as_mut_slice().iter_mut(); + nscssvalue.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 sources.iter() { + for src in self.iter() { match *src { Source::Url(ref url) => { next!().set_url(&url.url); @@ -88,20 +99,18 @@ fn set_font_face_descriptors(descriptors: &mut CSSFontFaceDescriptors, } debug_assert!(target_srcs.next().is_none(), "Should have filled all slots"); } +} - // unicode-range - if let Some(ref unicode_range) = data.unicode_range { - let target_ranges = descriptors.mUnicodeRange - .set_array((unicode_range.len() * 2) as i32) +impl ToNsCssValue for Vec { + fn convert(&self, nscssvalue: &mut nsCSSValue) { + let target_ranges = nscssvalue + .set_array((self.len() * 2) as i32) .as_mut_slice().chunks_mut(2); - for (range, target) in unicode_range.iter().zip(target_ranges) { + for (range, target) in self.iter().zip(target_ranges) { target[0].set_integer(range.start as i32); target[1].set_integer(range.end as i32); } } - - // Leave unset descriptors to eCSSUnit_Null, - // FontFaceSet::FindOrCreateUserFontEntryFromFontFace does the defaulting to initial values. } impl From for FontFaceRule { @@ -109,7 +118,7 @@ impl From for FontFaceRule { let mut result = unsafe { UniqueRefPtr::from_addrefed(bindings::Gecko_CSSFontFaceRule_Create()) }; - set_font_face_descriptors(&mut result.mDecl.mDescriptors, data); + data.set_descriptors(&mut result.mDecl.mDescriptors); result.get() } } diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs index c531a2efa01..1c004c8fcc1 100644 --- a/components/style/gecko_bindings/sugar/mod.rs +++ b/components/style/gecko_bindings/sugar/mod.rs @@ -6,7 +6,7 @@ mod ns_com_ptr; mod ns_css_shadow_array; -mod ns_css_value; +pub mod ns_css_value; mod ns_style_auto_array; pub mod ns_style_coord; mod ns_t_array; diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs index ff6ad413d50..d22f1148549 100644 --- a/components/style/gecko_bindings/sugar/ns_css_value.rs +++ b/components/style/gecko_bindings/sugar/ns_css_value.rs @@ -163,6 +163,11 @@ impl nsCSSValue { unsafe { bindings::Gecko_CSSValue_SetArray(self, len) } unsafe { self.mValue.mArray.as_mut().as_mut() }.unwrap() } + + /// Generic set from any value that implements the ToNsCssValue trait. + pub fn set_from(&mut self, value: &T) { + value.convert(self) + } } impl Drop for nsCSSValue { @@ -210,3 +215,9 @@ impl IndexMut for nsCSSValue_Array { &mut self.as_mut_slice()[i] } } + +/// Generic conversion to nsCSSValue +pub trait ToNsCssValue { + /// Convert + fn convert(&self, nscssvalue: &mut nsCSSValue); +}