diff --git a/components/style/gecko/generated/structs_debug.rs b/components/style/gecko/generated/structs_debug.rs index 982722b5ef5..0ff3aa97058 100644 --- a/components/style/gecko/generated/structs_debug.rs +++ b/components/style/gecko/generated/structs_debug.rs @@ -5007,7 +5007,7 @@ pub mod root { } #[test] fn bindgen_test_layout_ServoStyleContext() { - assert_eq!(::std::mem::size_of::() , 272usize , + assert_eq!(::std::mem::size_of::() , 280usize , concat ! ( "Size of: " , stringify ! ( ServoStyleContext ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -5030,14 +5030,14 @@ pub mod root { assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextInheritingAnonBoxStyle as * const _ as usize } , - 256usize , concat ! ( + 264usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextInheritingAnonBoxStyle ) )); assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextLazyPseudoStyle as * const _ as usize } , - 264usize , concat ! ( + 272usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextLazyPseudoStyle ) )); @@ -15914,7 +15914,7 @@ pub mod root { } #[test] fn bindgen_test_layout_ServoComputedData() { - assert_eq!(::std::mem::size_of::() , 224usize , + assert_eq!(::std::mem::size_of::() , 232usize , concat ! ( "Size of: " , stringify ! ( ServoComputedData ) )); assert_eq! (::std::mem::align_of::() , 8usize , diff --git a/components/style/gecko/generated/structs_release.rs b/components/style/gecko/generated/structs_release.rs index eb0379fca12..b91938c68c2 100644 --- a/components/style/gecko/generated/structs_release.rs +++ b/components/style/gecko/generated/structs_release.rs @@ -4895,7 +4895,7 @@ pub mod root { } #[test] fn bindgen_test_layout_ServoStyleContext() { - assert_eq!(::std::mem::size_of::() , 264usize , + assert_eq!(::std::mem::size_of::() , 272usize , concat ! ( "Size of: " , stringify ! ( ServoStyleContext ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -4918,14 +4918,14 @@ pub mod root { assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextInheritingAnonBoxStyle as * const _ as usize } , - 248usize , concat ! ( + 256usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextInheritingAnonBoxStyle ) )); assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextLazyPseudoStyle as * const _ as usize } , - 256usize , concat ! ( + 264usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextLazyPseudoStyle ) )); @@ -15706,7 +15706,7 @@ pub mod root { } #[test] fn bindgen_test_layout_ServoComputedData() { - assert_eq!(::std::mem::size_of::() , 224usize , + assert_eq!(::std::mem::size_of::() , 232usize , concat ! ( "Size of: " , stringify ! ( ServoComputedData ) )); assert_eq! (::std::mem::align_of::() , 8usize , diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index a2d01bbf4ca..480e080acbc 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -53,7 +53,7 @@ use logical_geometry::WritingMode; use media_queries::Device; use properties::animated_properties::TransitionProperty; use properties::computed_value_flags::ComputedValueFlags; -use properties::{longhands, FontComputationData, Importance, LonghandId}; +use properties::{default_font_size_keyword, longhands, FontComputationData, Importance, LonghandId}; use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId}; use rule_tree::StrongRuleNode; use selector_parser::PseudoElement; @@ -85,7 +85,7 @@ impl ComputedValues { pseudo: Option<<&PseudoElement>, custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, + font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -114,7 +114,7 @@ impl ComputedValues { ComputedValuesInner::new( /* custom_properties = */ None, /* writing_mode = */ WritingMode::empty(), // FIXME(bz): This seems dubious - FontComputationData::default_font_size_keyword(), + default_font_size_keyword(), ComputedValueFlags::empty(), /* rules = */ None, /* visited_style = */ None, @@ -188,7 +188,7 @@ type ParentStyleContextInfo<'a> = Option< &'a ComputedValues>; impl ComputedValuesInner { pub fn new(custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, + font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -199,7 +199,7 @@ impl ComputedValuesInner { ComputedValuesInner { custom_properties: custom_properties, writing_mode: writing_mode, - font_computation_data: FontComputationData::new(font_size_keyword), + font_computation_data: font_size_keyword, rules: rules, visited_style: visited_style.map(|x| Arc::into_raw_offset(x)), flags: flags, diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 18c25ecbd79..d9adc9610d8 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -605,7 +605,7 @@ ${helpers.single_keyword_system("font-variant-caps", 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"), SpecifiedValue::System(sys) => sys.to_css(dest), @@ -617,13 +617,17 @@ ${helpers.single_keyword_system("font-variant-caps", #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum SpecifiedValue { Length(specified::LengthOrPercentage), - /// A keyword value, along with a ratio. + /// A keyword value, along with a ratio and absolute offset. /// The ratio in any specified keyword value - /// will be 1, but we cascade keywordness even + /// will be 1 (with offset 0), 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), + /// have been applied, which is where the ratio + /// comes in. The offset comes in if we cascaded a calc value, + /// where the font-relative portion (em and percentage) will + /// go into the ratio, and the remaining units all computed together + /// will go into the offset. + /// See bug 1355707. + Keyword(KeywordSize, f32, NonNegativeAu), Smaller, Larger, System(SystemFont) @@ -802,32 +806,45 @@ ${helpers.single_keyword_system("font-variant-caps", 6 => XXLarge, // If value is greater than 7, let it be 7. _ => XXXLarge, - }, 1.) + }, 1., Au(0).into()) } /// 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 { + pub fn as_font_ratio(&self, context: &Context) -> Option<(f32, NonNegativeAu)> { match *self { SpecifiedValue::Length(ref lop) => { match *lop { LengthOrPercentage::Percentage(pc) => { - Some(pc.0) + Some((pc.0, Au(0).into())) } LengthOrPercentage::Length(ref nocalc) => { match *nocalc { NoCalcLength::FontRelative(FontRelativeLength::Em(em)) => { - Some(em) + Some((em, Au(0).into())) } _ => None, } } - // FIXME(emilio): This looks super fishy! - LengthOrPercentage::Calc(..) => None, + LengthOrPercentage::Calc(ref calc) => { + if calc.em.is_none() && calc.percentage.is_none() { + return None; + } + 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(); + Some((ratio, abs)) + } } } - SpecifiedValue::Larger => Some(LARGER_FONT_SIZE_RATIO), - SpecifiedValue::Smaller => Some(1. / LARGER_FONT_SIZE_RATIO), + SpecifiedValue::Larger => Some((LARGER_FONT_SIZE_RATIO, Au(0).into())), + SpecifiedValue::Smaller => Some((1. / LARGER_FONT_SIZE_RATIO, Au(0).into())), _ => None, } } @@ -862,8 +879,8 @@ ${helpers.single_keyword_system("font-variant-caps", let calc = calc.to_computed_value_zoomed(context, base_size); calc.to_used_value(Some(base_size.resolve(context))).unwrap().into() } - SpecifiedValue::Keyword(ref key, fraction) => { - context.maybe_zoom_text(key.to_computed_value(context).scale_by(fraction)) + SpecifiedValue::Keyword(ref key, fraction, offset) => { + context.maybe_zoom_text(key.to_computed_value(context).scale_by(fraction) + offset) } SpecifiedValue::Smaller => { FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) @@ -891,7 +908,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Keyword(Medium, 1.) + SpecifiedValue::Keyword(Medium, 1., Au(0).into()) } @@ -928,7 +945,7 @@ ${helpers.single_keyword_system("font-variant-caps", } if let Ok(kw) = input.try(KeywordSize::parse) { - return Ok(SpecifiedValue::Keyword(kw, 1.)) + return Ok(SpecifiedValue::Keyword(kw, 1., Au(0).into())) } try_match_ident_ignore_ascii_case! { input.expect_ident()?, @@ -954,17 +971,18 @@ ${helpers.single_keyword_system("font-variant-caps", pub fn cascade_specified_font_size(context: &mut Context, specified_value: &SpecifiedValue, mut computed: NonNegativeAu) { - if let SpecifiedValue::Keyword(kw, fraction) = *specified_value { - context.builder.font_size_keyword = Some((kw, fraction)); - } else if let Some(ratio) = specified_value.as_font_ratio() { + if let SpecifiedValue::Keyword(kw, fraction, offset) = *specified_value { + context.builder.font_size_keyword = Some((kw, fraction, offset)); + } else if let Some((ratio, abs)) = specified_value.as_font_ratio(context) { // 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.builder.inherited_font_computation_data().font_size_keyword { - context.builder.font_size_keyword = Some((kw, fraction * ratio)); + if let Some((kw, fraction, old_abs)) = *context.builder.inherited_font_computation_data() { + context.builder.font_size_keyword = + Some((kw, fraction * ratio, abs + old_abs.0.scale_by(ratio).into())); } else { context.builder.font_size_keyword = None; } @@ -982,8 +1000,8 @@ ${helpers.single_keyword_system("font-variant-caps", context.builder.get_parent_font().gecko().mLanguage.raw::() || context.builder.get_font().gecko().mGenericID != context.builder.get_parent_font().gecko().mGenericID { - if let Some((kw, ratio)) = context.builder.font_size_keyword { - computed = context.maybe_zoom_text(kw.to_computed_value(context).scale_by(ratio)); + if let Some((kw, ratio, offset)) = context.builder.font_size_keyword { + computed = context.maybe_zoom_text(kw.to_computed_value(context).scale_by(ratio) + offset); } } % endif @@ -1012,15 +1030,15 @@ ${helpers.single_keyword_system("font-variant-caps", // If inheriting, we must recompute font-size in case of language // changes using the font_size_keyword. We also need to do this to // handle mathml scriptlevel changes - let kw_inherited_size = context.builder.font_size_keyword.map(|(kw, ratio)| { - context.maybe_zoom_text(SpecifiedValue::Keyword(kw, ratio).to_computed_value(context)) + let kw_inherited_size = context.builder.font_size_keyword.map(|(kw, ratio, offset)| { + context.maybe_zoom_text(SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context)) }); let parent_kw; let device = context.builder.device; let mut font = context.builder.take_font(); let used_kw = { let parent_font = context.builder.get_parent_font(); - parent_kw = context.builder.inherited_font_computation_data().font_size_keyword; + parent_kw = *context.builder.inherited_font_computation_data(); font.inherit_font_size_from(parent_font, kw_inherited_size, device) }; @@ -1047,7 +1065,7 @@ ${helpers.single_keyword_system("font-variant-caps", let device = context.builder.device; context.builder.mutate_font().fixup_font_min_size(device); % endif - context.builder.font_size_keyword = Some((Default::default(), 1.)); + context.builder.font_size_keyword = Some((Default::default(), 1., Au(0).into())); } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index d9769383d1e..b13f2ac1717 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -10,7 +10,7 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> -#[cfg(feature = "servo")] use app_units::Au; +use app_units::Au; use servo_arc::{Arc, UniqueArc}; use smallbitvec::SmallBitVec; use std::borrow::Cow; @@ -94,43 +94,27 @@ pub trait MaybeBoxed { /// This is where we store extra font data while /// while computing font sizes. -#[derive(Clone, Debug)] -pub struct FontComputationData { - /// 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)> -} +/// +/// 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 (as well as adding any +/// absolute offset from calcs) +pub type FontComputationData = Option<(longhands::font_size::KeywordSize, f32, NonNegativeAu)>; - -impl FontComputationData { - /// Assigns values for variables in struct FontComputationData - pub fn new(font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>) -> Self { - FontComputationData { - font_size_keyword: font_size_keyword - } - } - - /// Assigns default values for variables in struct FontComputationData - pub fn default_font_size_keyword() -> Option<(longhands::font_size::KeywordSize, f32)> { - Some((Default::default(), 1.)) - } - - /// Gets a FontComputationData with the default values. - pub fn default_values() -> Self { - Self::new(Self::default_font_size_keyword()) - } +/// Default value for FontComputationData +pub fn default_font_size_keyword() -> FontComputationData { + Some((Default::default(), 1., Au(0).into())) } impl MaybeBoxed for T { @@ -2007,7 +1991,7 @@ impl ComputedValues { _: Option<<&PseudoElement>, custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, + font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -2040,7 +2024,7 @@ impl ComputedValuesInner { pub fn new( custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, + font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -2051,7 +2035,7 @@ impl ComputedValuesInner { ComputedValuesInner { custom_properties: custom_properties, writing_mode: writing_mode, - font_computation_data: FontComputationData::new(font_size_keyword), + font_computation_data: font_size_keyword, rules: rules, visited_style: visited_style, flags: flags, @@ -2564,7 +2548,7 @@ pub struct StyleBuilder<'a> { /// TODO(emilio): Make private. pub writing_mode: WritingMode, /// The keyword behind the current font-size property, if any. - pub font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, + pub font_size_keyword: FontComputationData, /// Flags for the computed value. pub flags: ComputedValueFlags, /// The element's style if visited, only computed if there's a relevant link @@ -2587,7 +2571,7 @@ impl<'a> StyleBuilder<'a> { rules: Option, custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>, + font_size_keyword: FontComputationData, flags: ComputedValueFlags, visited_style: Option>, ) -> Self { @@ -2657,7 +2641,7 @@ impl<'a> StyleBuilder<'a> { rules: None, // FIXME(emilio): Dubious... custom_properties: style_to_derive_from.custom_properties(), writing_mode: style_to_derive_from.writing_mode, - font_size_keyword: style_to_derive_from.font_computation_data.font_size_keyword, + font_size_keyword: style_to_derive_from.font_computation_data, flags: style_to_derive_from.flags, visited_style: style_to_derive_from.clone_visited_style(), % for style_struct in data.active_style_structs(): @@ -2757,7 +2741,7 @@ impl<'a> StyleBuilder<'a> { /* rules = */ None, parent.custom_properties(), parent.writing_mode, - parent.font_computation_data.font_size_keyword, + parent.font_computation_data, parent.flags, parent.clone_visited_style() ) @@ -2912,7 +2896,8 @@ pub use self::lazy_static_module::INITIAL_SERVO_VALUES; mod lazy_static_module { use logical_geometry::WritingMode; use servo_arc::Arc; - use super::{ComputedValues, ComputedValuesInner, longhands, style_structs, FontComputationData}; + use super::{ComputedValues, ComputedValuesInner, longhands, style_structs}; + use super::default_font_size_keyword; use super::computed_value_flags::ComputedValueFlags; /// The initial values for all style structs as defined by the specification. @@ -2931,7 +2916,7 @@ mod lazy_static_module { % endfor custom_properties: None, writing_mode: WritingMode::empty(), - font_computation_data: FontComputationData::default_values(), + font_computation_data: default_font_size_keyword(), rules: None, visited_style: None, flags: ComputedValueFlags::empty(), @@ -3152,7 +3137,7 @@ where Some(rules.clone()), custom_properties, WritingMode::empty(), - inherited_style.font_computation_data.font_size_keyword, + inherited_style.font_computation_data, ComputedValueFlags::empty(), visited_style, ), diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 5878fde0f51..7df0886ccd5 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -113,6 +113,12 @@ impl CalcLengthOrPercentage { #[inline] pub fn length(&self) -> Au { debug_assert!(self.percentage.is_none()); + self.length_component() + } + + /// Returns the length component of this `calc()` + #[inline] + pub fn length_component(&self) -> Au { self.clamping_mode.clamp(self.length) } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 339417ff2e7..22852114eab 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -14,8 +14,7 @@ use properties; use properties::{ComputedValues, StyleBuilder}; #[cfg(feature = "servo")] use servo_url::ServoUrl; -use std::f32; -use std::fmt; +use std::{f32, fmt, ops}; #[cfg(feature = "servo")] use std::sync::Arc; use style_traits::ToCss; @@ -563,6 +562,13 @@ impl NonNegativeAu { } } +impl ops::Add for NonNegativeAu { + type Output = NonNegativeAu; + fn add(self, other: Self) -> Self { + (self.0 + other.0).into() + } +} + impl From for NonNegativeAu { #[inline] fn from(au: Au) -> NonNegativeAu {