diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 81f0af1f1d8..f21f33bfd63 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2505,9 +2505,12 @@ fn static_assert() { /// Set font size, taking into account scriptminsize and scriptlevel /// Returns Some(size) if we have to recompute the script unconstrained size - pub fn apply_font_size(&mut self, v: FontSize, - parent: &Self, - device: &Device) -> Option { + pub fn apply_font_size( + &mut self, + v: FontSize, + parent: &Self, + device: &Device, + ) -> Option { let (adjusted_size, adjusted_unconstrained_size) = self.calculate_script_level_size(parent, device); // In this case, we have been unaffected by scriptminsize, ignore it diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index fdf6eb171a0..9ecd11ea599 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -593,15 +593,25 @@ impl FontSize { // Extract the ratio/offset and compose it if (calc.em.is_some() || calc.percentage.is_some()) && parent.keyword_info.is_some() { let ratio = calc.em.unwrap_or(0.) + calc.percentage.map_or(0., |pc| pc.0); - // Compute it, but shave off the font-relative part (em, %) - // This will mean that other font-relative units like ex and ch will be computed against - // the old font even when the font changes. There's no particular "right answer" for what - // to do here -- Gecko recascades as if the font had changed, we instead track the changes - // and reapply, which means that we carry over old computed ex/ch values whilst Gecko - // recomputes new ones. This is enough of an edge case to not really matter. - let abs = calc.to_computed_value_zoomed(context, FontBaseSize::Custom(Au(0).into())) - .length_component().into(); - info = parent.keyword_info.map(|i| i.compose(ratio, abs)); + // Compute it, but shave off the font-relative part (em, %). + // + // This will mean that other font-relative units like ex and + // ch will be computed against the old parent font even when + // the font changes. + // + // There's no particular "right answer" for what to do here, + // Gecko recascades as if the font had changed, we instead + // track the changes and reapply, which means that we carry + // over old computed ex/ch values whilst Gecko recomputes + // new ones. + // + // This is enough of an edge case to not really matter. + let abs = calc.to_computed_value_zoomed( + context, + FontBaseSize::InheritedStyleButStripEmUnits, + ).length_component(); + + info = parent.keyword_info.map(|i| i.compose(ratio, abs.into())); } let calc = calc.to_computed_value_zoomed(context, base_size); calc.to_used_value(Some(base_size.resolve(context))).unwrap().into() diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 92307dd31d5..cb83b80abf9 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -71,11 +71,17 @@ pub enum FontRelativeLength { /// A source to resolve font-relative units against #[derive(Clone, Copy, Debug, PartialEq)] pub enum FontBaseSize { - /// Use the font-size of the current element + /// Use the font-size of the current element. CurrentStyle, - /// Use the inherited font-size + /// Use the inherited font-size. InheritedStyle, - /// Use a custom base size + /// Use the inherited font-size, but strip em units. + /// + /// FIXME(emilio): This is very complex, and should go away. + InheritedStyleButStripEmUnits, + /// Use a custom base size. + /// + /// FIXME(emilio): This is very dubious, and only used for MathML. Custom(Au), } @@ -85,6 +91,7 @@ impl FontBaseSize { match *self { FontBaseSize::Custom(size) => size, FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().size(), + FontBaseSize::InheritedStyleButStripEmUnits | FontBaseSize::InheritedStyle => context.style().get_parent_font().clone_font_size().size(), } } @@ -99,36 +106,48 @@ impl FontRelativeLength { CSSPixelLength::new(pixel) } - /// Return reference font size. We use the base_size flag to pass a different size - /// for computing font-size and unconstrained font-size. - /// This returns a pair, the first one is the reference font size, and the second one is the - /// unpacked relative length. + /// Return reference font size. + /// + /// We use the base_size flag to pass a different size for computing + /// font-size and unconstrained font-size. + /// + /// This returns a pair, the first one is the reference font size, and the + /// second one is the unpacked relative length. fn reference_font_size_and_length( &self, context: &Context, base_size: FontBaseSize, ) -> (Au, CSSFloat) { - fn query_font_metrics(context: &Context, reference_font_size: Au) -> FontMetricsQueryResult { - context.font_metrics_provider.query(context.style().get_font(), - reference_font_size, - context.style().writing_mode, - context.in_media_query, - context.device()) + fn query_font_metrics( + context: &Context, + reference_font_size: Au, + ) -> FontMetricsQueryResult { + context.font_metrics_provider.query( + context.style().get_font(), + reference_font_size, + context.style().writing_mode, + context.in_media_query, + context.device(), + ) } let reference_font_size = base_size.resolve(context); - match *self { FontRelativeLength::Em(length) => { if context.for_non_inherited_property.is_some() { - if matches!(base_size, FontBaseSize::CurrentStyle) { + if base_size == FontBaseSize::CurrentStyle { context.rule_cache_conditions.borrow_mut() .set_font_size_dependency( reference_font_size.into() ); } } - (reference_font_size, length) + + if base_size == FontBaseSize::InheritedStyleButStripEmUnits { + (Au(0), length) + } else { + (reference_font_size, length) + } }, FontRelativeLength::Ex(length) => { if context.for_non_inherited_property.is_some() { @@ -182,7 +201,7 @@ impl FontRelativeLength { // https://drafts.csswg.org/css-values/#rem: // // When specified on the font-size property of the root - // element, the rem units refer to the property’s initial + // element, the rem units refer to the property's initial // value. // let reference_size = if context.is_root_element || context.in_media_query {