From 14534660f7b20d4b4359624e9d719d70c9e25271 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 12 Apr 2017 04:33:10 -0500 Subject: [PATCH] servo: Merge #16371 - stylo: Cascade relative font-sizes applied to keyword sizes (from Manishearth:stylo-rel-base-size); r=heycam r=heycam https://bugzilla.mozilla.org/show_bug.cgi?id=1355707 Source-Repo: https://github.com/servo/servo Source-Revision: 805b29cd53179d3812be272f5f5ab5330965365d --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : e706d5f79410a992a98913909e0292a24d514d27 --- .../components/style/properties/gecko.mako.rs | 20 ++++++++-- .../style/properties/helpers.mako.rs | 19 ++++++++-- .../style/properties/longhand/font.mako.rs | 38 +++++++++++++++---- .../style/properties/properties.mako.rs | 10 ++--- 4 files changed, 68 insertions(+), 19 deletions(-) diff --git a/servo/components/style/properties/gecko.mako.rs b/servo/components/style/properties/gecko.mako.rs index a5e63ee7416a..4f066f46da59 100644 --- a/servo/components/style/properties/gecko.mako.rs +++ b/servo/components/style/properties/gecko.mako.rs @@ -79,7 +79,21 @@ pub struct ComputedValues { custom_properties: Option>, pub writing_mode: WritingMode, pub root_font_size: Au, - pub font_size_keyword: Option, + /// font-size keyword values (and font-size-relative values applied + /// to keyword values) need to preserve their identity as originating + /// from keywords and relative font sizes. We store this information + /// out of band in the ComputedValues. When None, the font size on the + /// current struct was computed from a value that was not a keyword + /// or a chain of font-size-relative values applying to successive parents + /// terminated by a keyword. When Some, this means the font-size was derived + /// from a keyword value or a keyword value on some ancestor with only + /// font-size-relative keywords and regular inheritance in between. The + /// integer stores the final ratio of the chain of font size relative values. + /// and is 1 when there was just a keyword and no relative values. + /// + /// When this is Some, we compute font sizes by computing the keyword against + /// the generic font, and then multiplying it by the ratio. + pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, } impl ComputedValues { @@ -102,7 +116,7 @@ impl ComputedValues { pub fn new(custom_properties: Option>, writing_mode: WritingMode, root_font_size: Au, - font_size_keyword: Option, + font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, % for style_struct in data.style_structs: ${style_struct.ident}: Arc, % endfor @@ -123,7 +137,7 @@ impl ComputedValues { custom_properties: None, writing_mode: WritingMode::empty(), // FIXME(bz): This seems dubious root_font_size: longhands::font_size::get_initial_value(), // FIXME(bz): Also seems dubious? - font_size_keyword: Some(Default::default()), + font_size_keyword: Some((Default::default(), 1.)), % for style_struct in data.style_structs: ${style_struct.ident}: style_structs::${style_struct.name}::default(pres_context), % endfor diff --git a/servo/components/style/properties/helpers.mako.rs b/servo/components/style/properties/helpers.mako.rs index 35911564ca7f..de6e3424e515 100644 --- a/servo/components/style/properties/helpers.mako.rs +++ b/servo/components/style/properties/helpers.mako.rs @@ -267,8 +267,21 @@ DeclaredValue::Value(ref specified_value) => { let computed = specified_value.to_computed_value(context); % if property.ident == "font_size": - if let longhands::font_size::SpecifiedValue::Keyword(kw) = **specified_value { - context.mutate_style().font_size_keyword = Some(kw); + if let longhands::font_size::SpecifiedValue::Keyword(kw, fraction) + = **specified_value { + context.mutate_style().font_size_keyword = Some((kw, fraction)); + } else if let Some(ratio) = specified_value.as_font_ratio() { + // In case a font-size-relative value was applied to a keyword + // value, we must preserve this fact in case the generic font family + // changes. relative values (em and %) applied to keywords must be + // recomputed from the base size for the keyword and the relative size. + // + // See bug 1355707 + if let Some((kw, fraction)) = context.inherited_style().font_size_keyword { + context.mutate_style().font_size_keyword = Some((kw, fraction * ratio)); + } else { + context.mutate_style().font_size_keyword = None; + } } else { context.mutate_style().font_size_keyword = None; } @@ -294,7 +307,7 @@ .to_computed_value(context); context.mutate_style().mutate_${data.current_style_struct.name_lower}() .set_font_size(computed); - context.mutate_style().font_size_keyword = Some(Default::default()); + context.mutate_style().font_size_keyword = Some((Default::default(), 1.)); % else: // We assume that it's faster to use copy_*_from rather than // set_*(get_initial_value()); diff --git a/servo/components/style/properties/longhand/font.mako.rs b/servo/components/style/properties/longhand/font.mako.rs index 64c83d418c51..8f35d2e540e2 100644 --- a/servo/components/style/properties/longhand/font.mako.rs +++ b/servo/components/style/properties/longhand/font.mako.rs @@ -415,13 +415,14 @@ ${helpers.single_keyword("font-variant-caps", use std::fmt; use style_traits::ToCss; use values::{FONT_MEDIUM_PX, HasViewportPercentage}; - use values::specified::{LengthOrPercentage, Length, NoCalcLength, Percentage}; + use values::specified::{FontRelativeLength, LengthOrPercentage, Length}; + use values::specified::{NoCalcLength, Percentage}; impl ToCss for SpecifiedValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { SpecifiedValue::Length(ref lop) => lop.to_css(dest), - SpecifiedValue::Keyword(kw) => kw.to_css(dest), + SpecifiedValue::Keyword(kw, _) => kw.to_css(dest), SpecifiedValue::Smaller => dest.write_str("smaller"), SpecifiedValue::Larger => dest.write_str("larger"), } @@ -441,7 +442,13 @@ ${helpers.single_keyword("font-variant-caps", #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { Length(specified::LengthOrPercentage), - Keyword(KeywordSize), + /// A keyword value, along with a ratio. + /// The ratio in any specified keyword value + /// will be 1, but we cascade keywordness even + /// after font-relative (percent and em) values + /// have been applied, which is where the keyword + /// comes in. See bug 1355707 + Keyword(KeywordSize, f32), Smaller, Larger, } @@ -596,7 +603,22 @@ ${helpers.single_keyword("font-variant-caps", 6 => XXLarge, // If value is greater than 7, let it be 7. _ => XXXLarge, - }) + }, 1.) + } + + /// If this value is specified as a ratio of the parent font (em units or percent) + /// return the ratio + pub fn as_font_ratio(&self) -> Option { + if let SpecifiedValue::Length(ref lop) = *self { + if let LengthOrPercentage::Percentage(pc) = *lop { + return Some(pc.0) + } else if let LengthOrPercentage::Length(ref nocalc) = *lop { + if let NoCalcLength::FontRelative(FontRelativeLength::Em(em)) = *nocalc { + return Some(em) + } + } + } + None } } @@ -608,7 +630,7 @@ ${helpers.single_keyword("font-variant-caps", #[inline] pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Keyword(Medium) + SpecifiedValue::Keyword(Medium, 1.) } impl ToComputedValue for SpecifiedValue { @@ -637,8 +659,8 @@ ${helpers.single_keyword("font-variant-caps", calc.length() + context.inherited_style().get_font().clone_font_size() .scale_by(calc.percentage()) } - SpecifiedValue::Keyword(ref key) => { - key.to_computed_value(context) + SpecifiedValue::Keyword(ref key, fraction) => { + key.to_computed_value(context).scale_by(fraction) } SpecifiedValue::Smaller => { FontRelativeLength::Em(0.85).to_computed_value(context, @@ -665,7 +687,7 @@ ${helpers.single_keyword("font-variant-caps", } if let Ok(kw) = input.try(KeywordSize::parse) { - return Ok(SpecifiedValue::Keyword(kw)) + return Ok(SpecifiedValue::Keyword(kw, 1.)) } match_ignore_ascii_case! {&*input.expect_ident()?, diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index 28bfc925cb76..e86009652c27 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -1569,7 +1569,7 @@ pub struct ComputedValues { /// The root element's computed font size. pub root_font_size: Au, /// The keyword behind the current font-size property, if any - pub font_size_keyword: Option, + pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, } #[cfg(feature = "servo")] @@ -1578,7 +1578,7 @@ impl ComputedValues { pub fn new(custom_properties: Option>, writing_mode: WritingMode, root_font_size: Au, - font_size_keyword: Option, + font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, % for style_struct in data.active_style_structs(): ${style_struct.ident}: Arc, % endfor @@ -1910,7 +1910,7 @@ mod lazy_static_module { custom_properties: None, writing_mode: WritingMode::empty(), root_font_size: longhands::font_size::get_initial_value(), - font_size_keyword: Some(Default::default()), + font_size_keyword: Some((Default::default(), 1.)), }; } } @@ -2205,12 +2205,12 @@ pub fn apply_declarations<'a, F, I>(device: &Device, &mut cacheable, &mut cascade_info, error_reporter); - } else if let Some(kw) = inherited_style.font_size_keyword { + } else if let Some((kw, fraction)) = inherited_style.font_size_keyword { // Font size keywords will inherit as keywords and be recomputed // each time. let discriminant = LonghandId::FontSize as usize; let size = PropertyDeclaration::FontSize( - longhands::font_size::SpecifiedValue::Keyword(kw) + longhands::font_size::SpecifiedValue::Keyword(kw, fraction) ); (CASCADE_PROPERTY[discriminant])(&size, inherited_style,