diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 06db99fd1cc..0f3daec3039 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -874,33 +874,23 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { true } - /// The default font type (which is stored in FontFamilyList's - /// `mDefaultFontType`) depends on the current lang group and generic font - /// family, so we may need to recompute it if or the family changed. - /// - /// Also, we prioritize non-document fonts here if we need to (see the pref - /// `browser.display.use_document_fonts`). + /// The initial font depends on the current lang group so we may need to + /// recompute it if the language changed. #[inline] #[cfg(feature = "gecko")] - fn recompute_default_font_family_type_if_needed(&mut self) { + fn recompute_initial_font_family_if_needed(&mut self) { use crate::gecko_bindings::bindings; - use crate::values::computed::font::GenericFontFamily; + use crate::values::computed::font::FontFamily; - if !self.seen.contains(LonghandId::XLang) && !self.seen.contains(LonghandId::FontFamily) { + if !self.seen.contains(LonghandId::XLang) { return; } let builder = &mut self.context.builder; - let (default_font_type, prioritize_user_fonts) = { + let default_font_type = { let font = builder.get_font().gecko(); - // System fonts are all right, and should have the default font type - // set to none already, so bail out early. - if font.mFont.family.is_system_font { - debug_assert_eq!( - font.mFont.family.families.fallback, - GenericFontFamily::None - ); + if !font.mFont.family.is_initial { return; } @@ -911,29 +901,52 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { ) }; - let use_document_fonts = static_prefs::pref!("browser.display.use_document_fonts") != 0; - - // We prioritize user fonts over document fonts if the pref is set, - // and we don't have a generic family already (or we're using - // cursive or fantasy, since they're ignored, see bug 789788), and - // we have a generic family to actually replace it with. - let prioritize_user_fonts = - !use_document_fonts && - default_font_type != GenericFontFamily::None && - font.mFont.family.families.needs_user_font_prioritization(); - - if !prioritize_user_fonts && default_font_type == font.mFont.family.families.fallback { - // Nothing to do. + let initial_generic = font.mFont.family.families.single_generic(); + debug_assert!(initial_generic.is_some(), "Initial font should be just one generic font"); + if initial_generic == Some(default_font_type) { return; } - (default_font_type, prioritize_user_fonts) + + default_font_type }; let font = builder.mutate_font().gecko_mut(); - font.mFont.family.families.fallback = default_font_type; - if prioritize_user_fonts { - font.mFont.family.families.prioritize_first_generic_or_prepend(default_font_type); + // NOTE: Leaves is_initial untouched. + font.mFont.family.families = FontFamily::generic(default_font_type).families.clone(); + } + + /// Prioritize user fonts if needed by pref. + #[inline] + #[cfg(feature = "gecko")] + fn prioritize_user_fonts_if_needed(&mut self) { + use crate::gecko_bindings::bindings; + + if !self.seen.contains(LonghandId::FontFamily) { + return; } + + if static_prefs::pref!("browser.display.use_document_fonts") != 0 { + return; + } + + let builder = &mut self.context.builder; + let default_font_type = { + let font = builder.get_font().gecko(); + + if !font.mFont.family.families.needs_user_font_prioritization() { + return; + } + + unsafe { + bindings::Gecko_nsStyleFont_ComputeFallbackFontTypeForLanguage( + builder.device.document(), + font.mLanguage.mRawPtr, + ) + } + }; + + let font = builder.mutate_font().gecko_mut(); + font.mFont.family.families.prioritize_first_generic_or_prepend(default_font_type); } /// Some keyword sizes depend on the font family and language. @@ -1107,7 +1120,8 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { #[cfg(feature = "gecko")] { self.unzoom_fonts_if_needed(); - self.recompute_default_font_family_type_if_needed(); + self.recompute_initial_font_family_if_needed(); + self.prioritize_user_fonts_if_needed(); self.recompute_keyword_font_size_if_needed(); self.handle_mathml_scriptlevel_if_needed(); self.constrain_font_size_if_needed() diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 4e06d4e6efa..275bbbc0eba 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -182,6 +182,9 @@ pub struct FontFamily { pub families: FontFamilyList, /// Whether this font-family came from a specified system-font. pub is_system_font: bool, + /// Whether this is the initial font-family that might react to language + /// changes. + pub is_initial: bool, } macro_rules! static_font_family { @@ -193,10 +196,9 @@ macro_rules! static_font_family { list: crate::ArcSlice::from_iter_leaked(std::iter::once($family)), #[cfg(feature = "servo")] list: Box::new([$family]), - #[cfg(feature = "gecko")] - fallback: GenericFontFamily::None, }, is_system_font: false, + is_initial: false, }; } }; @@ -234,9 +236,9 @@ impl FontFamily { syntax: FontFamilyNameSyntax::Identifiers, }, ))), - fallback: GenericFontFamily::None, }, is_system_font: true, + is_initial: false, } } @@ -303,7 +305,7 @@ impl ToCss for FontFamily { Some(f) => f.to_css(dest)?, None => { #[cfg(feature = "gecko")] - return self.families.fallback.to_css(dest); + return return Ok(()); #[cfg(feature = "servo")] unreachable!(); }, @@ -562,8 +564,6 @@ impl SingleFontFamily { pub struct FontFamilyList { /// The actual list of font families specified. pub list: crate::ArcSlice, - /// A fallback font type (none, serif, or sans-serif, generally). - pub fallback: GenericFontFamily, } /// A list of font families. @@ -592,17 +592,6 @@ impl FontFamilyList { self.list.iter() } - /// Puts the fallback in the list if needed. - #[cfg(feature = "gecko")] - pub fn normalize(&mut self) { - if self.fallback == GenericFontFamily::None { - return; - } - let mut new_list = self.list.iter().cloned().collect::>(); - new_list.push(SingleFontFamily::Generic(self.fallback)); - self.list = crate::ArcSlice::from_iter(new_list.into_iter()); - } - /// If there's a generic font family on the list which is suitable for user /// font prioritization, then move it to the front of the list. Otherwise, /// prepend the default generic. @@ -629,7 +618,7 @@ impl FontFamilyList { /// Returns whether we need to prioritize user fonts. #[cfg(feature = "gecko")] - pub (crate) fn needs_user_font_prioritization(&self) -> bool { + pub(crate) fn needs_user_font_prioritization(&self) -> bool { self.iter().next().map_or(true, |f| match f { SingleFontFamily::Generic(f) => !f.valid_for_user_font_prioritization(), _ => true, diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index d11a2411a5d..40a559a20be 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -697,6 +697,7 @@ impl ToComputedValue for FontFamily { FontFamily::Values(ref list) => computed::FontFamily { families: list.clone(), is_system_font: false, + is_initial: false, }, FontFamily::System(_) => self.compute_system(context), } @@ -736,8 +737,6 @@ impl Parse for FontFamily { list: crate::ArcSlice::from_iter(values.into_iter()), #[cfg(feature = "servo")] list: values.into_boxed_slice(), - #[cfg(feature = "gecko")] - fallback: computed::GenericFontFamily::None, })) } }