diff options
-rw-r--r-- | components/style/gecko/generated/bindings.rs | 6 | ||||
-rw-r--r-- | components/style/properties/gecko.mako.rs | 27 | ||||
-rw-r--r-- | components/style/properties/longhand/font.mako.rs | 42 | ||||
-rw-r--r-- | components/style/properties/properties.mako.rs | 73 |
4 files changed, 113 insertions, 35 deletions
diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index 3eed899e538..f12de6938cf 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -1347,6 +1347,12 @@ extern "C" { RawGeckoPresContextBorrowed); } extern "C" { + pub fn Gecko_nsStyleFont_PrefillDefaultForGeneric(font: *mut nsStyleFont, + pres_context: + RawGeckoPresContextBorrowed, + generic_id: u8); +} +extern "C" { pub fn Gecko_nsStyleFont_FixupMinFontSize(font: *mut nsStyleFont, pres_context: RawGeckoPresContextBorrowed); diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index efefebcfe16..3c0b57c9fe0 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -221,6 +221,9 @@ impl ${style_struct.gecko_struct_name} { pub fn gecko(&self) -> &${style_struct.gecko_ffi_name} { &self.gecko } + pub fn gecko_mut(&mut self) -> &mut ${style_struct.gecko_ffi_name} { + &mut self.gecko + } } </%def> @@ -1587,7 +1590,6 @@ fn static_assert() { pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) { use properties::longhands::font_family::computed_value::FontFamily; - use gecko_bindings::structs::FontFamilyType; let list = &mut self.gecko.mFont.fontlist; unsafe { Gecko_FontFamilyList_Clear(list); } @@ -1600,28 +1602,7 @@ fn static_assert() { unsafe { Gecko_FontFamilyList_AppendNamed(list, f.name.as_ptr(), f.quoted); } } FontFamily::Generic(ref name) => { - let (family_type, generic) = - if name == &atom!("serif") { - (FontFamilyType::eFamily_serif, - structs::kGenericFont_serif) - } else if name == &atom!("sans-serif") { - (FontFamilyType::eFamily_sans_serif, - structs::kGenericFont_sans_serif) - } else if name == &atom!("cursive") { - (FontFamilyType::eFamily_cursive, - structs::kGenericFont_cursive) - } else if name == &atom!("fantasy") { - (FontFamilyType::eFamily_fantasy, - structs::kGenericFont_fantasy) - } else if name == &atom!("monospace") { - (FontFamilyType::eFamily_monospace, - structs::kGenericFont_monospace) - } else if name == &atom!("-moz-fixed") { - (FontFamilyType::eFamily_moz_fixed, - structs::kGenericFont_moz_fixed) - } else { - panic!("Unknown generic font family") - }; + let (family_type, generic) = FontFamily::generic(name); if v.0.len() == 1 { self.gecko.mGenericID = generic; } diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 51963a7dbb0..825577b1e60 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -191,6 +191,33 @@ quoted: false, })) } + + #[cfg(feature = "gecko")] + /// Return the generic ID for a given generic font name + pub fn generic(name: &Atom) -> (::gecko_bindings::structs::FontFamilyType, u8) { + use gecko_bindings::structs::{self, FontFamilyType}; + if *name == atom!("serif") { + (FontFamilyType::eFamily_serif, + structs::kGenericFont_serif) + } else if *name == atom!("sans-serif") { + (FontFamilyType::eFamily_sans_serif, + structs::kGenericFont_sans_serif) + } else if *name == atom!("cursive") { + (FontFamilyType::eFamily_cursive, + structs::kGenericFont_cursive) + } else if *name == atom!("fantasy") { + (FontFamilyType::eFamily_fantasy, + structs::kGenericFont_fantasy) + } else if *name == atom!("monospace") { + (FontFamilyType::eFamily_monospace, + structs::kGenericFont_monospace) + } else if *name == atom!("-moz-fixed") { + (FontFamilyType::eFamily_moz_fixed, + structs::kGenericFont_moz_fixed) + } else { + panic!("Unknown generic {}", name); + } + } } impl ToCss for FamilyName { @@ -260,6 +287,21 @@ System(SystemFont), } + #[cfg(feature = "gecko")] + impl SpecifiedValue { + /// Return the generic ID if it is a single generic font + pub fn single_generic(&self) -> Option<u8> { + if let SpecifiedValue::Values(ref values) = *self { + if values.len() == 1 { + if let FontFamily::Generic(ref name) = values[0] { + return Some(FontFamily::generic(name).1); + } + } + } + None + } + } + impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; fn to_computed_value(&self, _cx: &Context) -> Self::ComputedValue { diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 1a4af56d9cc..a0264d41e8c 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2732,6 +2732,52 @@ pub fn apply_declarations<'a, F, I>(device: &Device, let writing_mode = get_writing_mode(context.style.get_inheritedbox()); context.style.writing_mode = writing_mode; + let mut _skip_font_family = false; + + % if product == "gecko": + // Whenever a single generic value is specified, gecko will do a bunch of + // recalculation walking up the rule tree, including handling the font-size stuff. + // It basically repopulates the font struct with the default font for a given + // generic and language. We handle the font-size stuff separately, so this boils + // down to just copying over the font-family lists (no other aspect of the default + // font can be configured). + + if seen.contains(LonghandId::XLang) || font_family.is_some() { + // if just the language changed, the inherited generic is all we need + let mut generic = inherited_style.get_font().gecko().mGenericID; + if let Some(declaration) = font_family { + if let PropertyDeclaration::FontFamily(ref fam) = *declaration { + if let Some(id) = fam.single_generic() { + generic = id; + // In case of a specified font family with a single generic, we will + // end up setting font family below, but its value would get + // overwritten later in the pipeline when cascading. + // + // We instead skip cascading font-family in that case. + // + // In case of the language changing, we wish for a specified font- + // family to override this, so we do not skip cascading then. + _skip_font_family = true; + } + } + } + + // In case of just the language changing, the parent could have had no generic, + // which Gecko just does regular cascading with. Do the same. + // This can only happen in the case where the language changed but the family did not + if generic != structs::kGenericFont_NONE { + let pres_context = context.device.pres_context; + let gecko_font = context.mutate_style().mutate_font().gecko_mut(); + gecko_font.mGenericID = generic; + unsafe { + bindings::Gecko_nsStyleFont_PrefillDefaultForGeneric(gecko_font, + &*pres_context, + generic); + } + } + } + % endif + // It is important that font_size is computed before // the late properties (for em units), but after font-family // (for the base-font-size dependence for default and keyword font-sizes) @@ -2743,18 +2789,21 @@ pub fn apply_declarations<'a, F, I>(device: &Device, // To avoid an extra iteration, we just pull out the property // during the early iteration and cascade them in order // after it. - if let Some(declaration) = font_family { - let discriminant = LonghandId::FontFamily as usize; - (CASCADE_PROPERTY[discriminant])(declaration, - inherited_style, - default_style, - &mut context, - &mut cacheable, - &mut cascade_info, - error_reporter); - % if product == "gecko": - context.style.mutate_font().fixup_none_generic(context.device); - % endif + if !_skip_font_family { + if let Some(declaration) = font_family { + + let discriminant = LonghandId::FontFamily as usize; + (CASCADE_PROPERTY[discriminant])(declaration, + inherited_style, + default_style, + &mut context, + &mut cacheable, + &mut cascade_info, + error_reporter); + % if product == "gecko": + context.style.mutate_font().fixup_none_generic(context.device); + % endif + } } if let Some(declaration) = font_size { |