From c2fcc9ce1aec95f03490854e2a10200aaf4d7031 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 12 Sep 2017 13:53:39 -0700 Subject: [PATCH 1/6] stylo: Add keyword info to computed value of font-size --- components/gfx/font_context.rs | 10 +- components/layout/multicol.rs | 8 +- components/layout/text.rs | 2 +- components/style/gecko/media_queries.rs | 2 +- components/style/matching.rs | 3 +- components/style/properties/gecko.mako.rs | 11 +- .../style/properties/longhand/font.mako.rs | 139 ++++++++++++++---- components/style/rule_cache.rs | 2 +- components/style/servo/media_queries.rs | 2 +- components/style/values/computed/length.rs | 4 +- components/style/values/computed/mod.rs | 4 +- components/style/values/specified/length.rs | 4 +- components/style/values/specified/text.rs | 2 +- 13 files changed, 141 insertions(+), 52 deletions(-) diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 2badbce35fe..7c0b36800c2 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -118,7 +118,7 @@ impl FontContext { let layout_font_group_cache_key = LayoutFontGroupCacheKey { pointer: style.clone(), - size: Au::from(style.font_size), + size: style.font_size.size(), }; if let Some(ref cached_font_group) = self.layout_font_group_cache.get( &layout_font_group_cache_key) { @@ -148,7 +148,7 @@ impl FontContext { Some(ref cached_font_ref) => { let cached_font = (*cached_font_ref).borrow(); if cached_font.descriptor == desc && - cached_font.requested_pt_size == Au::from(style.font_size) && + cached_font.requested_pt_size == style.font_size.size() && cached_font.variant == style.font_variant_caps { fonts.push((*cached_font_ref).clone()); cache_hit = true; @@ -166,7 +166,7 @@ impl FontContext { Some(template_info) => { let layout_font = self.create_layout_font(template_info.font_template, desc.clone(), - Au::from(style.font_size), + style.font_size.size(), style.font_variant_caps, template_info.font_key); let font = match layout_font { @@ -199,7 +199,7 @@ impl FontContext { for cached_font_entry in &self.fallback_font_cache { let cached_font = cached_font_entry.font.borrow(); if cached_font.descriptor == desc && - cached_font.requested_pt_size == Au::from(style.font_size) && + cached_font.requested_pt_size == style.font_size.size() && cached_font.variant == style.font_variant_caps { fonts.push(cached_font_entry.font.clone()); cache_hit = true; @@ -211,7 +211,7 @@ impl FontContext { let template_info = self.font_cache_thread.last_resort_font_template(desc.clone()); let layout_font = self.create_layout_font(template_info.font_template, desc.clone(), - Au::from(style.font_size), + style.font_size.size(), style.font_variant_caps, template_info.font_key); match layout_font { diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 8d59092956d..2cb181f1f97 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -97,10 +97,10 @@ impl Flow for MulticolFlow { { let column_style = self.block_flow.fragment.style.get_column(); - let column_gap = Au::from(match column_style.column_gap { - Either::First(len) => len, - Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size, - }); + let column_gap = match column_style.column_gap { + Either::First(len) => len.into(), + Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size.size(), + }; let mut column_count; if let Either::First(column_width) = column_style.column_width { diff --git a/components/layout/text.rs b/components/layout/text.rs index 23cd69a89db..1915b2b878d 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -447,7 +447,7 @@ pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: ::Serv /// Returns the line block-size needed by the given computed style and font size. pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> Au { - let font_size = Au::from(style.get_font().font_size); + let font_size = style.get_font().font_size.size(); match style.get_inheritedtext().line_height { LineHeight::Normal => Au::from(metrics.line_gap), LineHeight::Number(l) => font_size.scale_by(l.0), diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 2765547aaf9..2e298431820 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -78,7 +78,7 @@ impl Device { pres_context: pres_context, default_values: ComputedValues::default_values(unsafe { &*pres_context }), // FIXME(bz): Seems dubious? - root_font_size: AtomicIsize::new(font_size::get_initial_value().0.to_i32_au() as isize), + root_font_size: AtomicIsize::new(font_size::get_initial_value().size().0 as isize), body_text_color: AtomicUsize::new(unsafe { &*pres_context }.mDefaultColor as usize), used_root_font_size: AtomicBool::new(false), used_viewport_size: AtomicBool::new(false), diff --git a/components/style/matching.rs b/components/style/matching.rs index 9018727f996..faa62cae051 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -511,7 +511,6 @@ pub trait MatchMethods : TElement { mut new_styles: ResolvedElementStyles, important_rules_changed: bool, ) -> ChildCascadeRequirement { - use app_units::Au; use dom::TNode; use std::cmp; @@ -553,7 +552,7 @@ pub trait MatchMethods : TElement { if old_styles.primary.as_ref().map_or(true, |s| s.get_font().clone_font_size() != new_font_size) { debug_assert!(self.owner_doc_matches_for_testing(device)); - device.set_root_font_size(Au::from(new_font_size)); + device.set_root_font_size(new_font_size.size()); // If the root font-size changed since last time, and something // in the document did use rem units, ensure we recascade the // entire tree. diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 1606a2dc0df..c5cad20c6ba 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2167,8 +2167,8 @@ fn static_assert() { } pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) { - self.gecko.mSize = v.0.to_i32_au(); - self.gecko.mScriptUnconstrainedSize = v.0.to_i32_au(); + self.gecko.mSize = v.size().0; + self.gecko.mScriptUnconstrainedSize = v.size().0; } /// Set font size, taking into account scriptminsize and scriptlevel @@ -2185,7 +2185,7 @@ fn static_assert() { self.fixup_font_min_size(device); None } else { - self.gecko.mSize = v.0.to_i32_au(); + self.gecko.mSize = v.size().0; self.fixup_font_min_size(device); Some(Au(parent.gecko.mScriptUnconstrainedSize).into()) } @@ -2348,7 +2348,10 @@ fn static_assert() { } pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T { - Au(self.gecko.mSize).into() + longhands::font_size::computed_value::T { + size: Au(self.gecko.mSize).into(), + info: None, // XXXManishearth this is a placeholder + } } pub fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) { diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 6092f80289b..d41cd314bb2 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -596,7 +596,7 @@ ${helpers.single_keyword_system("font-variant-caps", } -<%helpers:longhand name="font-size" animation_value_type="NonNegativeLength" +<%helpers:longhand name="font-size" animation_value_type="ComputedValue" flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER" allow_quirks="True" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size"> use app_units::Au; @@ -648,13 +648,56 @@ ${helpers.single_keyword_system("font-variant-caps", } pub mod computed_value { + use app_units::Au; + use std::fmt; + use style_traits::ToCss; use values::computed::NonNegativeLength; - pub type T = NonNegativeLength; + + #[derive(Copy, Clone, PartialEq, Debug)] + #[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] + #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + pub struct T { + pub size: NonNegativeLength, + pub info: Option, + } + + #[derive(Copy, Clone, PartialEq, Debug)] + #[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] + #[cfg_attr(feature = "servo", derive(HeapSizeOf))] + pub struct KeywordInfo { + pub kw: super::KeywordSize, + pub factor: f32, + pub offset: NonNegativeLength, + } + + impl KeywordInfo { + /// Given a parent keyword info (self), apply an additional factor/offset to it + pub fn compose(self, factor: f32, offset: NonNegativeLength) -> Self { + KeywordInfo { + kw: self.kw, + factor: self.factor * factor, + offset: self.offset.scale_by(factor) + offset, + } + } + } + + impl T { + pub fn size(self) -> Au { + self.size.into() + } + } + + impl ToCss for T { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.size.to_css(dest) + } + } } /// CSS font keywords #[derive(Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] + #[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum KeywordSize { XXSmall = 1, // This is to enable the NonZero optimization @@ -727,7 +770,7 @@ ${helpers.single_keyword_system("font-variant-caps", impl ToComputedValue for KeywordSize { type ComputedValue = NonNegativeLength; #[inline] - fn to_computed_value(&self, _: &Context) -> computed_value::T { + fn to_computed_value(&self, _: &Context) -> NonNegativeLength { // https://drafts.csswg.org/css-fonts-3/#font-size-prop use values::FONT_MEDIUM_PX; match *self { @@ -743,7 +786,7 @@ ${helpers.single_keyword_system("font-variant-caps", } #[inline] - fn from_computed_value(_: &computed_value::T) -> Self { + fn from_computed_value(_: &NonNegativeLength) -> Self { unreachable!() } } @@ -751,7 +794,7 @@ ${helpers.single_keyword_system("font-variant-caps", impl ToComputedValue for KeywordSize { type ComputedValue = NonNegativeLength; #[inline] - fn to_computed_value(&self, cx: &Context) -> computed_value::T { + fn to_computed_value(&self, cx: &Context) -> NonNegativeLength { use gecko_bindings::structs::nsIAtom; use values::specified::length::au_to_int_px; // Data from nsRuleNode.cpp in Gecko @@ -792,7 +835,7 @@ ${helpers.single_keyword_system("font-variant-caps", } #[inline] - fn from_computed_value(_: &computed_value::T) -> Self { + fn from_computed_value(_: &NonNegativeLength) -> Self { unreachable!() } } @@ -863,11 +906,18 @@ ${helpers.single_keyword_system("font-variant-caps", &self, context: &Context, base_size: FontBaseSize, - ) -> NonNegativeLength { + ) -> computed_value::T { use values::specified::length::FontRelativeLength; - match *self { + let mut info = None; + let size = match *self { SpecifiedValue::Length(LengthOrPercentage::Length( NoCalcLength::FontRelative(value))) => { + if let FontRelativeLength::Em(em) = value { + // If the parent font was keyword-derived, this is too. + // Tack the em unit onto the factor + info = context.style().get_parent_font() + .clone_font_size().info.map(|i| i.compose(em, Au(0).into())); + } value.to_computed_value(context, base_size).into() } SpecifiedValue::Length(LengthOrPercentage::Length( @@ -876,21 +926,45 @@ ${helpers.single_keyword_system("font-variant-caps", } SpecifiedValue::Length(LengthOrPercentage::Length( NoCalcLength::Absolute(ref l))) => { - context.maybe_zoom_text(l.to_computed_value(context)).into() + context.maybe_zoom_text(l.to_computed_value(context).into()) } SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => { l.to_computed_value(context).into() } SpecifiedValue::Length(LengthOrPercentage::Percentage(pc)) => { + // If the parent font was keyword-derived, this is too. + // Tack the % onto the factor + info = context.style().get_parent_font().clone_font_size().info.map(|i| i.compose(pc.0, Au(0).into())); base_size.resolve(context).scale_by(pc.0).into() } SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => { + let parent = context.style().get_parent_font().clone_font_size(); + // if we contain em/% units and the parent was keyword derived, this is too + // Extract the ratio/offset and compose it + if (calc.em.is_some() || calc.percentage.is_some()) && parent.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.info.map(|i| i.compose(ratio, abs)); + } 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, offset) => { + SpecifiedValue::Keyword(key, fraction, offset) => { + // As a specified keyword, this is keyword derived + info = Some(computed_value::KeywordInfo { + kw: key, + factor: fraction, + offset: offset, + }); let key_len = key.to_computed_value(context).scale_by(fraction) + offset; - context.maybe_zoom_text(key_len.0).into() + context.maybe_zoom_text(key_len).into() } SpecifiedValue::Smaller => { FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) @@ -903,17 +977,25 @@ ${helpers.single_keyword_system("font-variant-caps", SpecifiedValue::System(_) => { <%self:nongecko_unreachable> - context.cached_system_font.as_ref().unwrap().font_size + context.cached_system_font.as_ref().unwrap().font_size.size } - } + }; + computed_value::T { size, info } } } #[inline] #[allow(missing_docs)] pub fn get_initial_value() -> computed_value::T { - NonNegativeLength::new(FONT_MEDIUM_PX as f32) + computed_value::T { + size: Au::from_px(FONT_MEDIUM_PX).into(), + info: Some(computed_value::KeywordInfo { + kw: KeywordSize::Medium, + factor: 1., + offset: Au(0).into(), + }) + } } #[inline] @@ -933,7 +1015,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] fn from_computed_value(computed: &computed_value::T) -> Self { SpecifiedValue::Length(LengthOrPercentage::Length( - ToComputedValue::from_computed_value(&computed.0) + ToComputedValue::from_computed_value(&computed.size.0) )) } } @@ -980,7 +1062,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[allow(unused_mut)] pub fn cascade_specified_font_size(context: &mut Context, specified_value: &SpecifiedValue, - mut computed: NonNegativeLength) { + mut computed: computed_value::T) { 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) { @@ -1011,8 +1093,15 @@ ${helpers.single_keyword_system("font-variant-caps", context.builder.get_font().gecko().mGenericID != context.builder.get_parent_font().gecko().mGenericID { if let Some((kw, ratio, offset)) = context.builder.font_size_keyword { - let len = kw.to_computed_value(context).scale_by(ratio) + offset; - computed = context.maybe_zoom_text(len.0).into(); + let len = context.maybe_zoom_text(kw.to_computed_value(context).scale_by(ratio) + offset); + computed = computed_value::T { + size: len, + info: Some(computed_value::KeywordInfo { + kw: kw, + factor: ratio, + offset: offset + }), + } } } % endif @@ -1031,7 +1120,7 @@ ${helpers.single_keyword_system("font-variant-caps", .to_computed_value_against(context, FontBaseSize::Custom(Au::from(parent))); context.builder .mutate_font() - .apply_unconstrained_font_size(new_unconstrained); + .apply_unconstrained_font_size(new_unconstrained.size); } } @@ -1042,8 +1131,7 @@ ${helpers.single_keyword_system("font-variant-caps", // 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, offset)| { - let len = SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context); - context.maybe_zoom_text(len.0).into() + context.maybe_zoom_text(SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context).size) }); let parent_kw; let device = context.builder.device; @@ -1068,10 +1156,9 @@ ${helpers.single_keyword_system("font-variant-caps", pub fn cascade_initial_font_size(context: &mut Context) { // font-size's default ("medium") does not always // compute to the same value and depends on the font - let computed = context.maybe_zoom_text( - longhands::font_size::get_initial_specified_value() - .to_computed_value(context).0 - ).into(); + let mut computed = longhands::font_size::get_initial_specified_value() + .to_computed_value(context); + computed.size = context.maybe_zoom_text(computed.size); context.builder.mutate_font().set_font_size(computed); % if product == "gecko": let device = context.builder.device; @@ -2552,7 +2639,7 @@ ${helpers.single_keyword("-moz-math-variant", let weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight); let ret = ComputedSystemFont { font_family: longhands::font_family::computed_value::T(family), - font_size: Au(system.size).into(), + font_size: longhands::font_size::computed_value::T { size: Au(system.size).into(), info: None }, font_weight: weight, font_size_adjust: longhands::font_size_adjust::computed_value ::T::from_gecko_adjust(system.sizeAdjust), diff --git a/components/style/rule_cache.rs b/components/style/rule_cache.rs index 7862414f530..be0bcc43c3b 100644 --- a/components/style/rule_cache.rs +++ b/components/style/rule_cache.rs @@ -52,7 +52,7 @@ impl RuleCacheConditions { } if let Some(fs) = self.font_size { - if style.get_font().clone_font_size() != fs { + if style.get_font().clone_font_size().size != fs { return false; } } diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index f3a8670adcf..bd6b2a1f003 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -67,7 +67,7 @@ impl Device { viewport_size, device_pixel_ratio, // FIXME(bz): Seems dubious? - root_font_size: AtomicIsize::new(font_size::get_initial_value().0.to_i32_au() as isize), + root_font_size: AtomicIsize::new(font_size::get_initial_value().size().0 as isize), used_root_font_size: AtomicBool::new(false), used_viewport_units: AtomicBool::new(false), } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 3e85339f875..a0d70b45a34 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -35,7 +35,7 @@ impl ToComputedValue for specified::NoCalcLength { specified::NoCalcLength::ViewportPercentage(length) => length.to_computed_value(context.viewport_size_for_viewport_unit_resolution()), specified::NoCalcLength::ServoCharacterWidth(length) => - length.to_computed_value(Au::from(context.style().get_font().clone_font_size())), + length.to_computed_value(context.style().get_font().clone_font_size().size()), #[cfg(feature = "gecko")] specified::NoCalcLength::Physical(length) => length.to_computed_value(context), @@ -269,7 +269,7 @@ impl specified::CalcLengthOrPercentage { /// Compute font-size or line-height taking into account text-zoom if necessary. pub fn to_computed_value_zoomed(&self, context: &Context, base_size: FontBaseSize) -> CalcLengthOrPercentage { - self.to_computed_value_with_zoom(context, |abs| context.maybe_zoom_text(abs), base_size) + self.to_computed_value_with_zoom(context, |abs| context.maybe_zoom_text(abs.into()).0, base_size) } } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 5b7f251ff26..1c8a478f205 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -159,7 +159,7 @@ impl<'a> Context<'a> { /// Apply text-zoom if enabled. #[cfg(feature = "gecko")] - pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength { + pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength { // We disable zoom for by unsetting the // -x-text-zoom property, which leads to a false value // in mAllowZoom @@ -172,7 +172,7 @@ impl<'a> Context<'a> { /// (Servo doesn't do text-zoom) #[cfg(feature = "servo")] - pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength { + pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength { size } } diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 3c7c8a722f1..257781f62ae 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -96,8 +96,8 @@ impl FontBaseSize { pub fn resolve(&self, context: &Context) -> Au { match *self { FontBaseSize::Custom(size) => size, - FontBaseSize::CurrentStyle => Au::from(context.style().get_font().clone_font_size()), - FontBaseSize::InheritedStyle => Au::from(context.style().get_parent_font().clone_font_size()), + FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().size(), + FontBaseSize::InheritedStyle => context.style().get_parent_font().clone_font_size().size(), } } } diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index e8f0b899760..2d4cd532f5c 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -100,7 +100,7 @@ impl ToComputedValue for LineHeight { GenericLineHeight::Length(ref non_negative_lop) => { let result = match non_negative_lop.0 { LengthOrPercentage::Length(NoCalcLength::Absolute(ref abs)) => { - context.maybe_zoom_text(abs.to_computed_value(context)) + context.maybe_zoom_text(abs.to_computed_value(context).into()).0 } LengthOrPercentage::Length(ref length) => { length.to_computed_value(context) From c73dc5704b397527ba91c44c16d2063bb17a3133 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 12 Sep 2017 13:53:39 -0700 Subject: [PATCH 2/6] stylo: Add font keyword info fields on nsStyleFont --- .../style/gecko/generated/structs_debug.rs | 45 ++++++++++---- .../style/gecko/generated/structs_release.rs | 45 ++++++++++---- components/style/properties/gecko.mako.rs | 62 ++++++++++++++++++- 3 files changed, 124 insertions(+), 28 deletions(-) diff --git a/components/style/gecko/generated/structs_debug.rs b/components/style/gecko/generated/structs_debug.rs index 5f4e696f5ea..44487348c3d 100644 --- a/components/style/gecko/generated/structs_debug.rs +++ b/components/style/gecko/generated/structs_debug.rs @@ -440,6 +440,7 @@ pub mod root { pub const NS_STYLE_FONT_SIZE_XXXLARGE: ::std::os::raw::c_uint = 7; pub const NS_STYLE_FONT_SIZE_LARGER: ::std::os::raw::c_uint = 8; pub const NS_STYLE_FONT_SIZE_SMALLER: ::std::os::raw::c_uint = 9; + pub const NS_STYLE_FONT_SIZE_NO_KEYWORD: ::std::os::raw::c_uint = 10; pub const NS_STYLE_FONT_STRETCH_ULTRA_CONDENSED: ::std::os::raw::c_int = -4; pub const NS_STYLE_FONT_STRETCH_EXTRA_CONDENSED: ::std::os::raw::c_int = @@ -4528,7 +4529,7 @@ pub mod root { } #[test] fn bindgen_test_layout_GeckoFont() { - assert_eq!(::std::mem::size_of::() , 120usize , concat + assert_eq!(::std::mem::size_of::() , 128usize , concat ! ( "Size of: " , stringify ! ( GeckoFont ) )); assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( GeckoFont ) )); @@ -12647,6 +12648,9 @@ pub mod root { pub struct nsStyleFont { pub mFont: root::nsFont, pub mSize: root::nscoord, + pub mFontSizeFactor: f32, + pub mFontSizeOffset: root::nscoord, + pub mFontSizeKeyword: u8, pub mGenericID: u8, pub mScriptLevel: i8, pub mMathVariant: u8, @@ -12662,7 +12666,7 @@ pub mod root { pub const nsStyleFont_kHasFinishStyle: bool = false; #[test] fn bindgen_test_layout_nsStyleFont() { - assert_eq!(::std::mem::size_of::() , 120usize , concat ! + assert_eq!(::std::mem::size_of::() , 128usize , concat ! ( "Size of: " , stringify ! ( nsStyleFont ) )); assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( nsStyleFont ) )); @@ -12676,61 +12680,76 @@ pub mod root { as usize } , 88usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mSize ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsStyleFont ) ) . mFontSizeFactor as + * const _ as usize } , 92usize , concat ! ( + "Alignment of field: " , stringify ! ( nsStyleFont ) , + "::" , stringify ! ( mFontSizeFactor ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsStyleFont ) ) . mFontSizeOffset as + * const _ as usize } , 96usize , concat ! ( + "Alignment of field: " , stringify ! ( nsStyleFont ) , + "::" , stringify ! ( mFontSizeOffset ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsStyleFont ) ) . mFontSizeKeyword as + * const _ as usize } , 100usize , concat ! ( + "Alignment of field: " , stringify ! ( nsStyleFont ) , + "::" , stringify ! ( mFontSizeKeyword ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mGenericID as * - const _ as usize } , 92usize , concat ! ( + const _ as usize } , 101usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mGenericID ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mScriptLevel as * - const _ as usize } , 93usize , concat ! ( + const _ as usize } , 102usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptLevel ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mMathVariant as * - const _ as usize } , 94usize , concat ! ( + const _ as usize } , 103usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mMathVariant ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mMathDisplay as * - const _ as usize } , 95usize , concat ! ( + const _ as usize } , 104usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mMathDisplay ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mMinFontSizeRatio - as * const _ as usize } , 96usize , concat ! ( + as * const _ as usize } , 105usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mMinFontSizeRatio ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mExplicitLanguage - as * const _ as usize } , 97usize , concat ! ( + as * const _ as usize } , 106usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mExplicitLanguage ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mAllowZoom as * - const _ as usize } , 98usize , concat ! ( + const _ as usize } , 107usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mAllowZoom ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mScriptUnconstrainedSize as * const _ as usize } , - 100usize , concat ! ( + 108usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptUnconstrainedSize ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mScriptMinSize as * - const _ as usize } , 104usize , concat ! ( + const _ as usize } , 112usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptMinSize ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . - mScriptSizeMultiplier as * const _ as usize } , 108usize , + mScriptSizeMultiplier as * const _ as usize } , 116usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptSizeMultiplier ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mLanguage as * - const _ as usize } , 112usize , concat ! ( + const _ as usize } , 120usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mLanguage ) )); } diff --git a/components/style/gecko/generated/structs_release.rs b/components/style/gecko/generated/structs_release.rs index faf3924a299..b1f42171436 100644 --- a/components/style/gecko/generated/structs_release.rs +++ b/components/style/gecko/generated/structs_release.rs @@ -440,6 +440,7 @@ pub mod root { pub const NS_STYLE_FONT_SIZE_XXXLARGE: ::std::os::raw::c_uint = 7; pub const NS_STYLE_FONT_SIZE_LARGER: ::std::os::raw::c_uint = 8; pub const NS_STYLE_FONT_SIZE_SMALLER: ::std::os::raw::c_uint = 9; + pub const NS_STYLE_FONT_SIZE_NO_KEYWORD: ::std::os::raw::c_uint = 10; pub const NS_STYLE_FONT_STRETCH_ULTRA_CONDENSED: ::std::os::raw::c_int = -4; pub const NS_STYLE_FONT_STRETCH_EXTRA_CONDENSED: ::std::os::raw::c_int = @@ -4448,7 +4449,7 @@ pub mod root { } #[test] fn bindgen_test_layout_GeckoFont() { - assert_eq!(::std::mem::size_of::() , 120usize , concat + assert_eq!(::std::mem::size_of::() , 128usize , concat ! ( "Size of: " , stringify ! ( GeckoFont ) )); assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( GeckoFont ) )); @@ -12494,6 +12495,9 @@ pub mod root { pub struct nsStyleFont { pub mFont: root::nsFont, pub mSize: root::nscoord, + pub mFontSizeFactor: f32, + pub mFontSizeOffset: root::nscoord, + pub mFontSizeKeyword: u8, pub mGenericID: u8, pub mScriptLevel: i8, pub mMathVariant: u8, @@ -12509,7 +12513,7 @@ pub mod root { pub const nsStyleFont_kHasFinishStyle: bool = false; #[test] fn bindgen_test_layout_nsStyleFont() { - assert_eq!(::std::mem::size_of::() , 120usize , concat ! + assert_eq!(::std::mem::size_of::() , 128usize , concat ! ( "Size of: " , stringify ! ( nsStyleFont ) )); assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( "Alignment of " , stringify ! ( nsStyleFont ) )); @@ -12523,61 +12527,76 @@ pub mod root { as usize } , 88usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mSize ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsStyleFont ) ) . mFontSizeFactor as + * const _ as usize } , 92usize , concat ! ( + "Alignment of field: " , stringify ! ( nsStyleFont ) , + "::" , stringify ! ( mFontSizeFactor ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsStyleFont ) ) . mFontSizeOffset as + * const _ as usize } , 96usize , concat ! ( + "Alignment of field: " , stringify ! ( nsStyleFont ) , + "::" , stringify ! ( mFontSizeOffset ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsStyleFont ) ) . mFontSizeKeyword as + * const _ as usize } , 100usize , concat ! ( + "Alignment of field: " , stringify ! ( nsStyleFont ) , + "::" , stringify ! ( mFontSizeKeyword ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mGenericID as * - const _ as usize } , 92usize , concat ! ( + const _ as usize } , 101usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mGenericID ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mScriptLevel as * - const _ as usize } , 93usize , concat ! ( + const _ as usize } , 102usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptLevel ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mMathVariant as * - const _ as usize } , 94usize , concat ! ( + const _ as usize } , 103usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mMathVariant ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mMathDisplay as * - const _ as usize } , 95usize , concat ! ( + const _ as usize } , 104usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mMathDisplay ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mMinFontSizeRatio - as * const _ as usize } , 96usize , concat ! ( + as * const _ as usize } , 105usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mMinFontSizeRatio ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mExplicitLanguage - as * const _ as usize } , 97usize , concat ! ( + as * const _ as usize } , 106usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mExplicitLanguage ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mAllowZoom as * - const _ as usize } , 98usize , concat ! ( + const _ as usize } , 107usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mAllowZoom ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mScriptUnconstrainedSize as * const _ as usize } , - 100usize , concat ! ( + 108usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptUnconstrainedSize ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mScriptMinSize as * - const _ as usize } , 104usize , concat ! ( + const _ as usize } , 112usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptMinSize ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . - mScriptSizeMultiplier as * const _ as usize } , 108usize , + mScriptSizeMultiplier as * const _ as usize } , 116usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mScriptSizeMultiplier ) )); assert_eq! (unsafe { & ( * ( 0 as * const nsStyleFont ) ) . mLanguage as * - const _ as usize } , 112usize , concat ! ( + const _ as usize } , 120usize , concat ! ( "Alignment of field: " , stringify ! ( nsStyleFont ) , "::" , stringify ! ( mLanguage ) )); } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index c5cad20c6ba..556046aa112 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2167,8 +2167,27 @@ fn static_assert() { } pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) { + use self::longhands::font_size::KeywordSize; self.gecko.mSize = v.size().0; self.gecko.mScriptUnconstrainedSize = v.size().0; + if let Some(info) = v.info { + self.gecko.mFontSizeKeyword = match info.kw { + KeywordSize::XXSmall => structs::NS_STYLE_FONT_SIZE_XXSMALL, + KeywordSize::XSmall => structs::NS_STYLE_FONT_SIZE_XSMALL, + KeywordSize::Small => structs::NS_STYLE_FONT_SIZE_SMALL, + KeywordSize::Medium => structs::NS_STYLE_FONT_SIZE_MEDIUM, + KeywordSize::Large => structs::NS_STYLE_FONT_SIZE_LARGE, + KeywordSize::XLarge => structs::NS_STYLE_FONT_SIZE_XLARGE, + KeywordSize::XXLarge => structs::NS_STYLE_FONT_SIZE_XXLARGE, + KeywordSize::XXXLarge => structs::NS_STYLE_FONT_SIZE_XXXLARGE, + } as u8; + self.gecko.mFontSizeFactor = info.factor; + self.gecko.mFontSizeOffset = info.offset.0.to_i32_au(); + } else { + self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8; + self.gecko.mFontSizeFactor = 1.; + self.gecko.mFontSizeOffset = 0; + } } /// Set font size, taking into account scriptminsize and scriptlevel @@ -2327,12 +2346,24 @@ fn static_assert() { // In the case that MathML has given us an adjusted size, apply it. // Keep track of the unconstrained adjusted size. self.gecko.mSize = adjusted_size.0; + + // Technically the MathML constrained size may also be keyword-derived + // but we ignore this since it would be too complicated + // to correctly track and it's mostly unnecessary. + self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8; + self.gecko.mFontSizeFactor = 1.; + self.gecko.mFontSizeOffset = 0; + self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0; self.fixup_font_min_size(device); false } else if let Some(size) = kw_inherited_size { // Parent element was a keyword-derived size. self.gecko.mSize = size.0.to_i32_au(); + // Copy keyword info over. + self.gecko.mFontSizeFactor = parent.gecko.mFontSizeFactor; + self.gecko.mFontSizeOffset = parent.gecko.mFontSizeOffset; + self.gecko.mFontSizeKeyword = parent.gecko.mFontSizeKeyword; // MathML constraints didn't apply here, so we can ignore this. self.gecko.mScriptUnconstrainedSize = size.0.to_i32_au(); self.fixup_font_min_size(device); @@ -2341,6 +2372,10 @@ fn static_assert() { // MathML isn't affecting us, and our parent element does not // have a keyword-derived size. Set things normally. self.gecko.mSize = parent.gecko.mSize; + // copy keyword info over + self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8; + self.gecko.mFontSizeFactor = 1.; + self.gecko.mFontSizeOffset = 0; self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize; self.fixup_font_min_size(device); false @@ -2348,9 +2383,32 @@ fn static_assert() { } pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T { + use self::longhands::font_size::KeywordSize; + let size = Au(self.gecko.mSize).into(); + let kw = match self.gecko.mFontSizeKeyword as u32 { + structs::NS_STYLE_FONT_SIZE_XXSMALL => KeywordSize::XXSmall, + structs::NS_STYLE_FONT_SIZE_XSMALL => KeywordSize::XSmall, + structs::NS_STYLE_FONT_SIZE_SMALL => KeywordSize::Small, + structs::NS_STYLE_FONT_SIZE_MEDIUM => KeywordSize::Medium, + structs::NS_STYLE_FONT_SIZE_LARGE => KeywordSize::Large, + structs::NS_STYLE_FONT_SIZE_XLARGE => KeywordSize::XLarge, + structs::NS_STYLE_FONT_SIZE_XXLARGE => KeywordSize::XXLarge, + structs::NS_STYLE_FONT_SIZE_XXXLARGE => KeywordSize::XXXLarge, + structs::NS_STYLE_FONT_SIZE_NO_KEYWORD => { + return longhands::font_size::computed_value::T { + size: size, + info: None, + } + } + _ => unreachable!("mFontSizeKeyword should be an absolute keyword or NO_KEYWORD") + }; longhands::font_size::computed_value::T { - size: Au(self.gecko.mSize).into(), - info: None, // XXXManishearth this is a placeholder + size: size, + info: Some(longhands::font_size::computed_value::KeywordInfo { + kw: kw, + factor: self.gecko.mFontSizeFactor, + offset: Au(self.gecko.mFontSizeOffset).into() + }) } } From e1a39a2012a5e17422d6fa08b684a4d27668131e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 15 Sep 2017 15:25:02 -0700 Subject: [PATCH 3/6] stylo: Remove FontComputationData, switch over to using the new font tracking --- .../style/gecko/generated/structs_debug.rs | 29 +---- .../style/gecko/generated/structs_release.rs | 29 +---- components/style/properties/gecko.mako.rs | 19 +--- .../style/properties/longhand/font.mako.rs | 107 ++++-------------- .../style/properties/properties.mako.rs | 52 +-------- 5 files changed, 34 insertions(+), 202 deletions(-) diff --git a/components/style/gecko/generated/structs_debug.rs b/components/style/gecko/generated/structs_debug.rs index 44487348c3d..77a82e963d3 100644 --- a/components/style/gecko/generated/structs_debug.rs +++ b/components/style/gecko/generated/structs_debug.rs @@ -10,7 +10,6 @@ pub type ServoUnsafeCell = ::std::cell::UnsafeCell; pub type ServoCell = ::std::cell::Cell; pub type ServoNodeData = AtomicRefCell; pub type ServoWritingMode = ::logical_geometry::WritingMode; -pub type ServoFontComputationData = ::properties::FontComputationData; pub type ServoCustomPropertiesMap = Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>; pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>; pub type ServoVisitedStyle = Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>; @@ -4463,19 +4462,6 @@ pub mod root { FirstLetterContinuation = 1, PlaceholderFrame = 2, } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum ServoKeywordSize { - Empty = 0, - XXSmall = 1, - XSmall = 2, - Small = 3, - Medium = 4, - Large = 5, - XLarge = 6, - XXLarge = 7, - XXXLarge = 8, - } #[repr(C)] #[derive(Debug)] pub struct ServoStyleContext { @@ -4487,7 +4473,7 @@ pub mod root { } #[test] fn bindgen_test_layout_ServoStyleContext() { - assert_eq!(::std::mem::size_of::() , 280usize , + assert_eq!(::std::mem::size_of::() , 264usize , concat ! ( "Size of: " , stringify ! ( ServoStyleContext ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -4510,14 +4496,14 @@ pub mod root { assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextInheritingAnonBoxStyle as * const _ as usize } , - 264usize , concat ! ( + 248usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextInheritingAnonBoxStyle ) )); assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextLazyPseudoStyle as * const _ as usize } , - 272usize , concat ! ( + 256usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextLazyPseudoStyle ) )); @@ -14828,11 +14814,10 @@ pub mod root { /// /// relevant link for this element. A element's "relevant link" is the /// /// element being matched if it is a link or the nearest ancestor link. pub visited_style: ::gecko_bindings::structs::ServoVisitedStyle, - pub font_computation_data: ::gecko_bindings::structs::ServoFontComputationData, } #[test] fn bindgen_test_layout_ServoComputedData() { - assert_eq!(::std::mem::size_of::() , 232usize , + assert_eq!(::std::mem::size_of::() , 216usize , concat ! ( "Size of: " , stringify ! ( ServoComputedData ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -14979,12 +14964,6 @@ pub mod root { as * const _ as usize } , 208usize , concat ! ( "Alignment of field: " , stringify ! ( ServoComputedData ) , "::" , stringify ! ( visited_style ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const ServoComputedData ) ) . - font_computation_data as * const _ as usize } , 216usize , - concat ! ( - "Alignment of field: " , stringify ! ( ServoComputedData ) - , "::" , stringify ! ( font_computation_data ) )); } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/components/style/gecko/generated/structs_release.rs b/components/style/gecko/generated/structs_release.rs index b1f42171436..a91c6dd4b3d 100644 --- a/components/style/gecko/generated/structs_release.rs +++ b/components/style/gecko/generated/structs_release.rs @@ -10,7 +10,6 @@ pub type ServoUnsafeCell = ::std::cell::UnsafeCell; pub type ServoCell = ::std::cell::Cell; pub type ServoNodeData = AtomicRefCell; pub type ServoWritingMode = ::logical_geometry::WritingMode; -pub type ServoFontComputationData = ::properties::FontComputationData; pub type ServoCustomPropertiesMap = Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>; pub type ServoRuleNode = Option<::rule_tree::StrongRuleNode>; pub type ServoVisitedStyle = Option<::servo_arc::RawOffsetArc<::properties::ComputedValues>>; @@ -4383,19 +4382,6 @@ pub mod root { FirstLetterContinuation = 1, PlaceholderFrame = 2, } - #[repr(u32)] - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub enum ServoKeywordSize { - Empty = 0, - XXSmall = 1, - XSmall = 2, - Small = 3, - Medium = 4, - Large = 5, - XLarge = 6, - XXLarge = 7, - XXXLarge = 8, - } #[repr(C)] #[derive(Debug)] pub struct ServoStyleContext { @@ -4407,7 +4393,7 @@ pub mod root { } #[test] fn bindgen_test_layout_ServoStyleContext() { - assert_eq!(::std::mem::size_of::() , 272usize , + assert_eq!(::std::mem::size_of::() , 256usize , concat ! ( "Size of: " , stringify ! ( ServoStyleContext ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -4430,14 +4416,14 @@ pub mod root { assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextInheritingAnonBoxStyle as * const _ as usize } , - 256usize , concat ! ( + 240usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextInheritingAnonBoxStyle ) )); assert_eq! (unsafe { & ( * ( 0 as * const ServoStyleContext ) ) . mNextLazyPseudoStyle as * const _ as usize } , - 264usize , concat ! ( + 248usize , concat ! ( "Alignment of field: " , stringify ! ( ServoStyleContext ) , "::" , stringify ! ( mNextLazyPseudoStyle ) )); @@ -14675,11 +14661,10 @@ pub mod root { /// /// relevant link for this element. A element's "relevant link" is the /// /// element being matched if it is a link or the nearest ancestor link. pub visited_style: ::gecko_bindings::structs::ServoVisitedStyle, - pub font_computation_data: ::gecko_bindings::structs::ServoFontComputationData, } #[test] fn bindgen_test_layout_ServoComputedData() { - assert_eq!(::std::mem::size_of::() , 232usize , + assert_eq!(::std::mem::size_of::() , 216usize , concat ! ( "Size of: " , stringify ! ( ServoComputedData ) )); assert_eq! (::std::mem::align_of::() , 8usize , @@ -14826,12 +14811,6 @@ pub mod root { as * const _ as usize } , 208usize , concat ! ( "Alignment of field: " , stringify ! ( ServoComputedData ) , "::" , stringify ! ( visited_style ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const ServoComputedData ) ) . - font_computation_data as * const _ as usize } , 216usize , - concat ! ( - "Alignment of field: " , stringify ! ( ServoComputedData ) - , "::" , stringify ! ( font_computation_data ) )); } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 556046aa112..6114267e236 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::*; -use properties::{default_font_size_keyword, longhands, FontComputationData, Importance, LonghandId}; +use properties::{longhands, Importance, LonghandId}; use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId}; use rule_tree::StrongRuleNode; use selector_parser::PseudoElement; @@ -85,7 +85,6 @@ impl ComputedValues { pseudo: Option<<&PseudoElement>, custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -96,7 +95,6 @@ impl ComputedValues { ComputedValuesInner::new( custom_properties, writing_mode, - font_size_keyword, flags, rules, visited_style, @@ -114,7 +112,6 @@ impl ComputedValues { ComputedValuesInner::new( /* custom_properties = */ None, /* writing_mode = */ WritingMode::empty(), // FIXME(bz): This seems dubious - default_font_size_keyword(), ComputedValueFlags::empty(), /* rules = */ None, /* visited_style = */ None, @@ -174,7 +171,6 @@ impl Clone for ComputedValuesInner { % endfor custom_properties: self.custom_properties.clone(), writing_mode: self.writing_mode.clone(), - font_computation_data: self.font_computation_data.clone(), flags: self.flags.clone(), rules: self.rules.clone(), visited_style: self.visited_style.clone(), @@ -188,7 +184,6 @@ type ParentStyleContextInfo<'a> = Option< &'a ComputedValues>; impl ComputedValuesInner { pub fn new(custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -199,7 +194,6 @@ impl ComputedValuesInner { ComputedValuesInner { custom_properties: custom_properties, writing_mode: writing_mode, - font_computation_data: font_size_keyword, rules: rules, visited_style: visited_style.map(|x| Arc::into_raw_offset(x)), flags: flags, @@ -2322,11 +2316,9 @@ fn static_assert() { /// This function will also handle scriptminsize and scriptlevel /// so should not be called when you just want the font sizes to be copied. /// Hence the different name. - /// - /// Returns true if the inherited keyword size was actually used pub fn inherit_font_size_from(&mut self, parent: &Self, kw_inherited_size: Option, - device: &Device) -> bool { + device: &Device) { let (adjusted_size, adjusted_unconstrained_size) = self.calculate_script_level_size(parent, device); if adjusted_size.0 != parent.gecko.mSize || @@ -2355,8 +2347,6 @@ fn static_assert() { self.gecko.mFontSizeOffset = 0; self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0; - self.fixup_font_min_size(device); - false } else if let Some(size) = kw_inherited_size { // Parent element was a keyword-derived size. self.gecko.mSize = size.0.to_i32_au(); @@ -2366,8 +2356,6 @@ fn static_assert() { self.gecko.mFontSizeKeyword = parent.gecko.mFontSizeKeyword; // MathML constraints didn't apply here, so we can ignore this. self.gecko.mScriptUnconstrainedSize = size.0.to_i32_au(); - self.fixup_font_min_size(device); - true } else { // MathML isn't affecting us, and our parent element does not // have a keyword-derived size. Set things normally. @@ -2377,9 +2365,8 @@ fn static_assert() { self.gecko.mFontSizeFactor = 1.; self.gecko.mFontSizeOffset = 0; self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize; - self.fixup_font_min_size(device); - false } + self.fixup_font_min_size(device); } pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T { diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index d41cd314bb2..9d3ceba8d74 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", use style_traits::ToCss; use values::FONT_MEDIUM_PX; use values::computed::NonNegativeLength; - use values::specified::{AllowQuirks, FontRelativeLength, LengthOrPercentage, NoCalcLength}; + use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength}; use values::specified::length::FontBaseSize; impl ToCss for SpecifiedValue { @@ -861,46 +861,6 @@ ${helpers.single_keyword_system("font-variant-caps", }, 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, context: &Context) -> Option<(f32, NonNegativeLength)> { - match *self { - SpecifiedValue::Length(ref lop) => { - match *lop { - LengthOrPercentage::Percentage(pc) => { - Some((pc.0, NonNegativeLength::zero())) - } - LengthOrPercentage::Length(ref nocalc) => { - match *nocalc { - NoCalcLength::FontRelative(FontRelativeLength::Em(em)) => { - Some((em, NonNegativeLength::zero())) - } - _ => 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))) - .length_component().into(); - Some((ratio, abs)) - } - } - } - SpecifiedValue::Larger => Some((LARGER_FONT_SIZE_RATIO, Au(0).into())), - SpecifiedValue::Smaller => Some((1. / LARGER_FONT_SIZE_RATIO, Au(0).into())), - _ => None, - } - } - /// Compute it against a given base font size pub fn to_computed_value_against( &self, @@ -908,6 +868,11 @@ ${helpers.single_keyword_system("font-variant-caps", base_size: FontBaseSize, ) -> computed_value::T { use values::specified::length::FontRelativeLength; + let compose_keyword = |factor| { + context.style().get_parent_font() + .clone_font_size().info + .map(|i| i.compose(factor, Au(0).into())) + }; let mut info = None; let size = match *self { SpecifiedValue::Length(LengthOrPercentage::Length( @@ -915,8 +880,7 @@ ${helpers.single_keyword_system("font-variant-caps", if let FontRelativeLength::Em(em) = value { // If the parent font was keyword-derived, this is too. // Tack the em unit onto the factor - info = context.style().get_parent_font() - .clone_font_size().info.map(|i| i.compose(em, Au(0).into())); + info = compose_keyword(em); } value.to_computed_value(context, base_size).into() } @@ -934,7 +898,7 @@ ${helpers.single_keyword_system("font-variant-caps", SpecifiedValue::Length(LengthOrPercentage::Percentage(pc)) => { // If the parent font was keyword-derived, this is too. // Tack the % onto the factor - info = context.style().get_parent_font().clone_font_size().info.map(|i| i.compose(pc.0, Au(0).into())); + info = compose_keyword(pc.0); base_size.resolve(context).scale_by(pc.0).into() } SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => { @@ -967,10 +931,12 @@ ${helpers.single_keyword_system("font-variant-caps", context.maybe_zoom_text(key_len).into() } SpecifiedValue::Smaller => { + info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO); FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) .to_computed_value(context, base_size).into() } SpecifiedValue::Larger => { + info = compose_keyword(LARGER_FONT_SIZE_RATIO); FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO) .to_computed_value(context, base_size).into() } @@ -1063,25 +1029,6 @@ ${helpers.single_keyword_system("font-variant-caps", pub fn cascade_specified_font_size(context: &mut Context, specified_value: &SpecifiedValue, mut computed: computed_value::T) { - 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, old_abs)) = *context.builder.inherited_font_computation_data() { - context.builder.font_size_keyword = - Some((kw, fraction * ratio, abs + old_abs.scale_by(ratio))); - } else { - context.builder.font_size_keyword = None; - } - } else { - context.builder.font_size_keyword = None; - } - // we could use clone_language and clone_font_family() here but that's // expensive. Do it only in gecko mode for now. % if product == "gecko": @@ -1092,16 +1039,9 @@ ${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, offset)) = context.builder.font_size_keyword { - let len = context.maybe_zoom_text(kw.to_computed_value(context).scale_by(ratio) + offset); - computed = computed_value::T { - size: len, - info: Some(computed_value::KeywordInfo { - kw: kw, - factor: ratio, - offset: offset - }), - } + if let Some(info) = computed.info { + computed.size = context.maybe_zoom_text(info.kw.to_computed_value(context) + .scale_by(info.factor) + info.offset) } } % endif @@ -1130,21 +1070,17 @@ ${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, offset)| { - context.maybe_zoom_text(SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context).size) + let kw_inherited_size = context.builder.get_parent_font() + .clone_font_size() + .info.map(|info| { + context.maybe_zoom_text(SpecifiedValue::Keyword(info.kw, info.factor, info.offset) + .to_computed_value(context).size) }); - 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.inherit_font_size_from(parent_font, kw_inherited_size, device) - }; + font.inherit_font_size_from(context.builder.get_parent_font(), + kw_inherited_size, + context.builder.device); context.builder.put_font(font); - context.builder.font_size_keyword = - if used_kw { parent_kw } else { None }; } /// Cascade the initial value for the `font-size` property. @@ -1164,7 +1100,6 @@ ${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., Au(0).into())); } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 2536b49a3c8..31693b1a85a 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -10,6 +10,7 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> +#[cfg(feature = "servo")] use app_units::Au; use servo_arc::{Arc, UniqueArc}; use smallbitvec::SmallBitVec; @@ -92,32 +93,6 @@ pub trait MaybeBoxed { fn maybe_boxed(self) -> Out; } - -/// This is where we store extra font data while -/// while computing font sizes. -/// -/// 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, NonNegativeLength)>; - -/// Default value for FontComputationData -pub fn default_font_size_keyword() -> FontComputationData { - Some((Default::default(), 1., Au(0).into())) -} - impl MaybeBoxed for T { #[inline] fn maybe_boxed(self) -> T { self } @@ -1845,9 +1820,8 @@ pub mod style_structs { /// (Servo does not handle MathML, so this just calls copy_font_size_from) pub fn inherit_font_size_from(&mut self, parent: &Self, _: Option, - _: &Device) -> bool { + _: &Device) { self.copy_font_size_from(parent); - false } /// (Servo does not handle MathML, so this just calls set_font_size) pub fn apply_font_size(&mut self, @@ -1985,9 +1959,6 @@ pub struct ComputedValuesInner { /// The writing mode of this computed values struct. pub writing_mode: WritingMode, - /// The keyword behind the current font-size property, if any - pub font_computation_data: FontComputationData, - /// A set of flags we use to store misc information regarding this style. pub flags: ComputedValueFlags, @@ -2043,7 +2014,6 @@ impl ComputedValues { _: Option<<&PseudoElement>, custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -2055,7 +2025,6 @@ impl ComputedValues { inner: ComputedValuesInner::new( custom_properties, writing_mode, - font_size_keyword, flags, rules, visited_style, @@ -2076,7 +2045,6 @@ impl ComputedValuesInner { pub fn new( custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: FontComputationData, flags: ComputedValueFlags, rules: Option, visited_style: Option>, @@ -2087,7 +2055,6 @@ impl ComputedValuesInner { ComputedValuesInner { custom_properties: custom_properties, writing_mode: writing_mode, - font_computation_data: font_size_keyword, rules: rules, visited_style: visited_style, flags: flags, @@ -2609,8 +2576,6 @@ 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: FontComputationData, /// Flags for the computed value. pub flags: ComputedValueFlags, /// The element's style if visited, only computed if there's a relevant link @@ -2633,7 +2598,6 @@ impl<'a> StyleBuilder<'a> { rules: Option, custom_properties: Option>, writing_mode: WritingMode, - font_size_keyword: FontComputationData, mut flags: ComputedValueFlags, visited_style: Option>, ) -> Self { @@ -2671,7 +2635,6 @@ impl<'a> StyleBuilder<'a> { modified_reset: false, custom_properties, writing_mode, - font_size_keyword, flags, visited_style, % for style_struct in data.active_style_structs(): @@ -2714,7 +2677,6 @@ 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, flags: style_to_derive_from.flags, visited_style: style_to_derive_from.clone_visited_style(), % for style_struct in data.active_style_structs(): @@ -2834,7 +2796,6 @@ impl<'a> StyleBuilder<'a> { /* rules = */ None, parent.custom_properties(), parent.writing_mode, - parent.font_computation_data, parent.flags, parent.clone_visited_style() ) @@ -2941,7 +2902,6 @@ impl<'a> StyleBuilder<'a> { self.pseudo, self.custom_properties, self.writing_mode, - self.font_size_keyword, self.flags, self.rules, self.visited_style, @@ -2964,11 +2924,6 @@ impl<'a> StyleBuilder<'a> { /// ::first-line case some of the inherited information needs to come from /// one ComputedValues instance and some from a different one. - /// Inherited font bits. - pub fn inherited_font_computation_data(&self) -> &FontComputationData { - &self.inherited_style.font_computation_data - } - /// Inherited writing-mode. pub fn inherited_writing_mode(&self) -> &WritingMode { &self.inherited_style.writing_mode @@ -3006,7 +2961,6 @@ mod lazy_static_module { use logical_geometry::WritingMode; use servo_arc::Arc; 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. @@ -3025,7 +2979,6 @@ mod lazy_static_module { % endfor custom_properties: None, writing_mode: WritingMode::empty(), - font_computation_data: default_font_size_keyword(), rules: None, visited_style: None, flags: ComputedValueFlags::empty(), @@ -3252,7 +3205,6 @@ where Some(rules.clone()), custom_properties, WritingMode::empty(), - inherited_style.font_computation_data, ComputedValueFlags::empty(), visited_style, ), From df9d7cd941def693c55fb0bf49a19b9bf666bd77 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 18 Sep 2017 13:25:59 -0700 Subject: [PATCH 4/6] stylo: Move font-size stuff to values::*::font --- components/style/properties/gecko.mako.rs | 7 +- .../style/properties/longhand/font.mako.rs | 383 +----------------- components/style/values/computed/font.rs | 61 +++ components/style/values/computed/mod.rs | 1 + components/style/values/mod.rs | 3 - components/style/values/specified/font.rs | 355 ++++++++++++++++ components/style/values/specified/length.rs | 8 +- components/style/values/specified/mod.rs | 1 + 8 files changed, 430 insertions(+), 389 deletions(-) create mode 100644 components/style/values/computed/font.rs create mode 100644 components/style/values/specified/font.rs diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 6114267e236..a0490db4e1d 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2161,7 +2161,7 @@ fn static_assert() { } pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) { - use self::longhands::font_size::KeywordSize; + use values::specified::font::KeywordSize; self.gecko.mSize = v.size().0; self.gecko.mScriptUnconstrainedSize = v.size().0; if let Some(info) = v.info { @@ -2370,7 +2370,8 @@ fn static_assert() { } pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T { - use self::longhands::font_size::KeywordSize; + use values::computed::font::KeywordInfo; + use values::specified::font::KeywordSize; let size = Au(self.gecko.mSize).into(); let kw = match self.gecko.mFontSizeKeyword as u32 { structs::NS_STYLE_FONT_SIZE_XXSMALL => KeywordSize::XXSmall, @@ -2391,7 +2392,7 @@ fn static_assert() { }; longhands::font_size::computed_value::T { size: size, - info: Some(longhands::font_size::computed_value::KeywordInfo { + info: Some(KeywordInfo { kw: kw, factor: self.gecko.mFontSizeFactor, offset: Au(self.gecko.mFontSizeOffset).into() diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 9d3ceba8d74..455ea5dd14b 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -600,363 +600,23 @@ ${helpers.single_keyword_system("font-variant-caps", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER" allow_quirks="True" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size"> use app_units::Au; - use properties::longhands::system_font::SystemFont; - use std::fmt; - use style_traits::ToCss; - use values::FONT_MEDIUM_PX; - use values::computed::NonNegativeLength; - use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength}; + use values::specified::AllowQuirks; use values::specified::length::FontBaseSize; - - 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::Smaller => dest.write_str("smaller"), - SpecifiedValue::Larger => dest.write_str("larger"), - SpecifiedValue::System(sys) => sys.to_css(dest), - } - } - } - - #[derive(Clone, Debug, PartialEq)] - #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] - #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - pub enum SpecifiedValue { - Length(specified::LengthOrPercentage), - /// A keyword value, along with a ratio and absolute offset. - /// The ratio in any specified keyword value - /// 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 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, NonNegativeLength), - Smaller, - Larger, - System(SystemFont) - } - - impl From for SpecifiedValue { - fn from(other: specified::LengthOrPercentage) -> Self { - SpecifiedValue::Length(other) - } - } + use values::specified::font::{FONT_MEDIUM_PX, KeywordSize}; pub mod computed_value { - use app_units::Au; - use std::fmt; - use style_traits::ToCss; - use values::computed::NonNegativeLength; - - #[derive(Copy, Clone, PartialEq, Debug)] - #[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] - #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - pub struct T { - pub size: NonNegativeLength, - pub info: Option, - } - - #[derive(Copy, Clone, PartialEq, Debug)] - #[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] - #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - pub struct KeywordInfo { - pub kw: super::KeywordSize, - pub factor: f32, - pub offset: NonNegativeLength, - } - - impl KeywordInfo { - /// Given a parent keyword info (self), apply an additional factor/offset to it - pub fn compose(self, factor: f32, offset: NonNegativeLength) -> Self { - KeywordInfo { - kw: self.kw, - factor: self.factor * factor, - offset: self.offset.scale_by(factor) + offset, - } - } - } - - impl T { - pub fn size(self) -> Au { - self.size.into() - } - } - - impl ToCss for T { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.size.to_css(dest) - } - } + use values::computed::font; + pub type T = font::FontSize; } - /// CSS font keywords - #[derive(Clone, Copy, Debug, PartialEq)] - #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] - #[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] - #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - pub enum KeywordSize { - XXSmall = 1, // This is to enable the NonZero optimization - // which simplifies the representation of Option - // in bindgen - XSmall, - Small, - Medium, - Large, - XLarge, - XXLarge, - // This is not a real font keyword and will not parse - // HTML font-size 7 corresponds to this value - XXXLarge, - } - - pub use self::KeywordSize::*; - - impl KeywordSize { - pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - try_match_ident_ignore_ascii_case! { input.expect_ident()?, - "xx-small" => Ok(XXSmall), - "x-small" => Ok(XSmall), - "small" => Ok(Small), - "medium" => Ok(Medium), - "large" => Ok(Large), - "x-large" => Ok(XLarge), - "xx-large" => Ok(XXLarge), - } - } - - pub fn html_size(&self) -> u8 { - match *self { - KeywordSize::XXSmall => 0, - KeywordSize::XSmall => 1, - KeywordSize::Small => 2, - KeywordSize::Medium => 3, - KeywordSize::Large => 4, - KeywordSize::XLarge => 5, - KeywordSize::XXLarge => 6, - KeywordSize::XXXLarge => 7, - } - } - } - - impl Default for KeywordSize { - fn default() -> Self { - Medium - } - } - - impl ToCss for KeywordSize { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - dest.write_str(match *self { - XXSmall => "xx-small", - XSmall => "x-small", - Small => "small", - Medium => "medium", - Large => "large", - XLarge => "x-large", - XXLarge => "xx-large", - XXXLarge => unreachable!("We should never serialize \ - specified values set via - HTML presentation attributes"), - }) - } - } - - % if product == "servo": - impl ToComputedValue for KeywordSize { - type ComputedValue = NonNegativeLength; - #[inline] - fn to_computed_value(&self, _: &Context) -> NonNegativeLength { - // https://drafts.csswg.org/css-fonts-3/#font-size-prop - use values::FONT_MEDIUM_PX; - match *self { - XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5, - XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4, - Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9, - Medium => Au::from_px(FONT_MEDIUM_PX), - Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5, - XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2, - XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2, - XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3, - }.into() - } - - #[inline] - fn from_computed_value(_: &NonNegativeLength) -> Self { - unreachable!() - } - } - % else: - impl ToComputedValue for KeywordSize { - type ComputedValue = NonNegativeLength; - #[inline] - fn to_computed_value(&self, cx: &Context) -> NonNegativeLength { - use gecko_bindings::structs::nsIAtom; - use values::specified::length::au_to_int_px; - // Data from nsRuleNode.cpp in Gecko - // Mapping from base size and HTML size to pixels - // The first index is (base_size - 9), the second is the - // HTML size. "0" is CSS keyword xx-small, not HTML size 0, - // since HTML size 0 is the same as 1. - // - // xxs xs s m l xl xxl - - // - 0/1 2 3 4 5 6 7 - static FONT_SIZE_MAPPING: [[i32; 8]; 8] = [ - [9, 9, 9, 9, 11, 14, 18, 27], - [9, 9, 9, 10, 12, 15, 20, 30], - [9, 9, 10, 11, 13, 17, 22, 33], - [9, 9, 10, 12, 14, 18, 24, 36], - [9, 10, 12, 13, 16, 20, 26, 39], - [9, 10, 12, 14, 17, 21, 28, 42], - [9, 10, 13, 15, 18, 23, 30, 45], - [9, 10, 13, 16, 18, 24, 32, 48] - ]; - - static FONT_SIZE_FACTORS: [i32; 8] = [60, 75, 89, 100, 120, 150, 200, 300]; - - // XXXManishearth handle quirks mode - - let ref gecko_font = cx.style().get_font().gecko(); - let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw::(), |atom| { - cx.font_metrics_provider.get_size(atom, gecko_font.mGenericID).0 - }) }; - - let base_size_px = au_to_int_px(base_size as f32); - let html_size = self.html_size() as usize; - if base_size_px >= 9 && base_size_px <= 16 { - NonNegativeLength::new(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size] as f32) - } else { - Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into() - } - } - - #[inline] - fn from_computed_value(_: &NonNegativeLength) -> Self { - unreachable!() - } - } - % endif - - /// This is the ratio applied for font-size: larger - /// and smaller by both Firefox and Chrome - const LARGER_FONT_SIZE_RATIO: f32 = 1.2; - - impl SpecifiedValue { - /// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size - pub fn from_html_size(size: u8) -> Self { - SpecifiedValue::Keyword(match size { - // If value is less than 1, let it be 1. - 0 | 1 => XSmall, - 2 => Small, - 3 => Medium, - 4 => Large, - 5 => XLarge, - 6 => XXLarge, - // If value is greater than 7, let it be 7. - _ => XXXLarge, - }, 1., Au(0).into()) - } - - /// Compute it against a given base font size - pub fn to_computed_value_against( - &self, - context: &Context, - base_size: FontBaseSize, - ) -> computed_value::T { - use values::specified::length::FontRelativeLength; - let compose_keyword = |factor| { - context.style().get_parent_font() - .clone_font_size().info - .map(|i| i.compose(factor, Au(0).into())) - }; - let mut info = None; - let size = match *self { - SpecifiedValue::Length(LengthOrPercentage::Length( - NoCalcLength::FontRelative(value))) => { - if let FontRelativeLength::Em(em) = value { - // If the parent font was keyword-derived, this is too. - // Tack the em unit onto the factor - info = compose_keyword(em); - } - value.to_computed_value(context, base_size).into() - } - SpecifiedValue::Length(LengthOrPercentage::Length( - NoCalcLength::ServoCharacterWidth(value))) => { - value.to_computed_value(base_size.resolve(context)).into() - } - SpecifiedValue::Length(LengthOrPercentage::Length( - NoCalcLength::Absolute(ref l))) => { - context.maybe_zoom_text(l.to_computed_value(context).into()) - } - SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => { - l.to_computed_value(context).into() - } - SpecifiedValue::Length(LengthOrPercentage::Percentage(pc)) => { - // If the parent font was keyword-derived, this is too. - // Tack the % onto the factor - info = compose_keyword(pc.0); - base_size.resolve(context).scale_by(pc.0).into() - } - SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => { - let parent = context.style().get_parent_font().clone_font_size(); - // if we contain em/% units and the parent was keyword derived, this is too - // Extract the ratio/offset and compose it - if (calc.em.is_some() || calc.percentage.is_some()) && parent.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.info.map(|i| i.compose(ratio, abs)); - } - let calc = calc.to_computed_value_zoomed(context, base_size); - calc.to_used_value(Some(base_size.resolve(context))).unwrap().into() - } - SpecifiedValue::Keyword(key, fraction, offset) => { - // As a specified keyword, this is keyword derived - info = Some(computed_value::KeywordInfo { - kw: key, - factor: fraction, - offset: offset, - }); - let key_len = key.to_computed_value(context).scale_by(fraction) + offset; - context.maybe_zoom_text(key_len).into() - } - SpecifiedValue::Smaller => { - info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO); - FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) - .to_computed_value(context, base_size).into() - } - SpecifiedValue::Larger => { - info = compose_keyword(LARGER_FONT_SIZE_RATIO); - FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO) - .to_computed_value(context, base_size).into() - } - - SpecifiedValue::System(_) => { - <%self:nongecko_unreachable> - context.cached_system_font.as_ref().unwrap().font_size.size - - } - }; - computed_value::T { size, info } - } - } + pub use values::specified::font::FontSize as SpecifiedValue; #[inline] #[allow(missing_docs)] pub fn get_initial_value() -> computed_value::T { computed_value::T { size: Au::from_px(FONT_MEDIUM_PX).into(), - info: Some(computed_value::KeywordInfo { + info: Some(::values::computed::font::KeywordInfo { kw: KeywordSize::Medium, factor: 1., offset: Au(0).into(), @@ -966,26 +626,10 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Keyword(Medium, 1., Au(0).into()) + SpecifiedValue::Keyword(KeywordSize::Medium, 1., Au(0).into()) } - impl ToComputedValue for SpecifiedValue { - type ComputedValue = computed_value::T; - - #[inline] - fn to_computed_value(&self, context: &Context) -> computed_value::T { - self.to_computed_value_against(context, FontBaseSize::InheritedStyle) - } - - #[inline] - fn from_computed_value(computed: &computed_value::T) -> Self { - SpecifiedValue::Length(LengthOrPercentage::Length( - ToComputedValue::from_computed_value(&computed.size.0) - )) - } - } - /// | | | pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { @@ -1012,19 +656,6 @@ ${helpers.single_keyword_system("font-variant-caps", } } - impl SpecifiedValue { - pub fn system_font(f: SystemFont) -> Self { - SpecifiedValue::System(f) - } - pub fn get_system(&self) -> Option { - if let SpecifiedValue::System(s) = *self { - Some(s) - } else { - None - } - } - } - #[allow(unused_mut)] pub fn cascade_specified_font_size(context: &mut Context, specified_value: &SpecifiedValue, diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs new file mode 100644 index 00000000000..62110779d61 --- /dev/null +++ b/components/style/values/computed/font.rs @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Computed values for font properties + +use app_units::Au; +use std::fmt; +use style_traits::ToCss; +use values::computed::NonNegativeLength; +use values::specified::font as specified; + +#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +/// The computed value of font-size +pub struct FontSize { + /// The size. + pub size: NonNegativeLength, + /// If derived from a keyword, the keyword and additional transformations applied to it + pub info: Option, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +/// Additional information for keyword-derived font sizes. +pub struct KeywordInfo { + /// The keyword used + pub kw: specified::KeywordSize, + /// A factor to be multiplied by the computed size of the keyword + pub factor: f32, + /// An additional Au offset to add to the kw*factor in the case of calcs + pub offset: NonNegativeLength, +} + +impl KeywordInfo { + /// Given a parent keyword info (self), apply an additional factor/offset to it + pub fn compose(self, factor: f32, offset: NonNegativeLength) -> Self { + KeywordInfo { + kw: self.kw, + factor: self.factor * factor, + offset: self.offset.scale_by(factor) + offset, + } + } +} + +impl FontSize { + /// The actual computed font size. + pub fn size(self) -> Au { + self.size.into() + } +} + +impl ToCss for FontSize { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.size.to_css(dest) + } +} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 1c8a478f205..d7f6ddc5af9 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -67,6 +67,7 @@ pub mod box_; pub mod color; pub mod effects; pub mod flex; +pub mod font; pub mod image; #[cfg(feature = "gecko")] pub mod gecko; diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 2a0483ca630..15978aa04a3 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -29,9 +29,6 @@ pub type CSSFloat = f32; /// A CSS integer value. pub type CSSInteger = i32; -/// The default font size. -pub const FONT_MEDIUM_PX: i32 = 16; - define_keyword_type!(None_, "none"); define_keyword_type!(Auto, "auto"); define_keyword_type!(Normal, "normal"); diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs new file mode 100644 index 00000000000..af0d5df149b --- /dev/null +++ b/components/style/values/specified/font.rs @@ -0,0 +1,355 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Specified values for font properties + +#[cfg(feature = "gecko")] +use Atom; +use app_units::Au; +use cssparser::Parser; +use properties::longhands::system_font::SystemFont; +use std::fmt; +use style_traits::{ToCss, ParseError}; +use values::computed::{font as computed, Context, NonNegativeLength, ToComputedValue}; +use values::specified::{LengthOrPercentage, NoCalcLength}; +use values::specified::length::FontBaseSize; + +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +/// A specified font-size value +pub enum FontSize { + /// A length; e.g. 10px. + Length(LengthOrPercentage), + /// A keyword value, along with a ratio and absolute offset. + /// The ratio in any specified keyword value + /// 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 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, NonNegativeLength), + /// font-size: smaller + Smaller, + /// font-size: larger + Larger, + /// Derived from a specified system font. + System(SystemFont) +} + +impl ToCss for FontSize { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + FontSize::Length(ref lop) => lop.to_css(dest), + FontSize::Keyword(kw, _, _) => kw.to_css(dest), + FontSize::Smaller => dest.write_str("smaller"), + FontSize::Larger => dest.write_str("larger"), + FontSize::System(sys) => sys.to_css(dest), + } + } +} + +impl From for FontSize { + fn from(other: LengthOrPercentage) -> Self { + FontSize::Length(other) + } +} + +/// CSS font keywords +#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] +#[allow(missing_docs)] +pub enum KeywordSize { + XXSmall = 1, // This is to enable the NonZero optimization + // which simplifies the representation of Option + // in bindgen + XSmall, + Small, + Medium, + Large, + XLarge, + XXLarge, + // This is not a real font keyword and will not parse + // HTML font-size 7 corresponds to this value + XXXLarge, +} + +impl KeywordSize { + /// Parse a keyword size + pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { + try_match_ident_ignore_ascii_case! { input.expect_ident()?, + "xx-small" => Ok(KeywordSize::XXSmall), + "x-small" => Ok(KeywordSize::XSmall), + "small" => Ok(KeywordSize::Small), + "medium" => Ok(KeywordSize::Medium), + "large" => Ok(KeywordSize::Large), + "x-large" => Ok(KeywordSize::XLarge), + "xx-large" => Ok(KeywordSize::XXLarge), + } + } + + /// Convert to an HTML value + pub fn html_size(&self) -> u8 { + match *self { + KeywordSize::XXSmall => 0, + KeywordSize::XSmall => 1, + KeywordSize::Small => 2, + KeywordSize::Medium => 3, + KeywordSize::Large => 4, + KeywordSize::XLarge => 5, + KeywordSize::XXLarge => 6, + KeywordSize::XXXLarge => 7, + } + } +} + +impl Default for KeywordSize { + fn default() -> Self { + KeywordSize::Medium + } +} + +impl ToCss for KeywordSize { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + dest.write_str(match *self { + KeywordSize::XXSmall => "xx-small", + KeywordSize::XSmall => "x-small", + KeywordSize::Small => "small", + KeywordSize::Medium => "medium", + KeywordSize::Large => "large", + KeywordSize::XLarge => "x-large", + KeywordSize::XXLarge => "xx-large", + KeywordSize::XXXLarge => unreachable!("We should never serialize \ + specified values set via + HTML presentation attributes"), + }) + } +} + +/// This is the ratio applied for font-size: larger +/// and smaller by both Firefox and Chrome +const LARGER_FONT_SIZE_RATIO: f32 = 1.2; + +/// The default font size. +pub const FONT_MEDIUM_PX: i32 = 16; + +#[cfg(feature = "servo")] +impl ToComputedValue for KeywordSize { + type ComputedValue = NonNegativeLength; + #[inline] + fn to_computed_value(&self, _: &Context) -> NonNegativeLength { + // https://drafts.csswg.org/css-fonts-3/#font-size-prop + match *self { + KeywordSize::XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5, + KeywordSize::XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4, + KeywordSize::Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9, + KeywordSize::Medium => Au::from_px(FONT_MEDIUM_PX), + KeywordSize::Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5, + KeywordSize::XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2, + KeywordSize::XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2, + KeywordSize::XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3, + }.into() + } + + #[inline] + fn from_computed_value(_: &NonNegativeLength) -> Self { + unreachable!() + } +} + +#[cfg(feature = "gecko")] +impl ToComputedValue for KeywordSize { + type ComputedValue = NonNegativeLength; + #[inline] + fn to_computed_value(&self, cx: &Context) -> NonNegativeLength { + use gecko_bindings::structs::nsIAtom; + use values::specified::length::au_to_int_px; + // Data from nsRuleNode.cpp in Gecko + // Mapping from base size and HTML size to pixels + // The first index is (base_size - 9), the second is the + // HTML size. "0" is CSS keyword xx-small, not HTML size 0, + // since HTML size 0 is the same as 1. + // + // xxs xs s m l xl xxl - + // - 0/1 2 3 4 5 6 7 + static FONT_SIZE_MAPPING: [[i32; 8]; 8] = [ + [9, 9, 9, 9, 11, 14, 18, 27], + [9, 9, 9, 10, 12, 15, 20, 30], + [9, 9, 10, 11, 13, 17, 22, 33], + [9, 9, 10, 12, 14, 18, 24, 36], + [9, 10, 12, 13, 16, 20, 26, 39], + [9, 10, 12, 14, 17, 21, 28, 42], + [9, 10, 13, 15, 18, 23, 30, 45], + [9, 10, 13, 16, 18, 24, 32, 48] + ]; + + static FONT_SIZE_FACTORS: [i32; 8] = [60, 75, 89, 100, 120, 150, 200, 300]; + + // XXXManishearth handle quirks mode (bug 1401322) + + let ref gecko_font = cx.style().get_font().gecko(); + let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw::(), |atom| { + cx.font_metrics_provider.get_size(atom, gecko_font.mGenericID).0 + }) }; + + let base_size_px = au_to_int_px(base_size as f32); + let html_size = self.html_size() as usize; + if base_size_px >= 9 && base_size_px <= 16 { + Au::from_px(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size]).into() + } else { + Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into() + } + } + + #[inline] + fn from_computed_value(_: &NonNegativeLength) -> Self { + unreachable!() + } +} + +impl FontSize { + /// https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size + pub fn from_html_size(size: u8) -> Self { + FontSize::Keyword(match size { + // If value is less than 1, let it be 1. + 0 | 1 => KeywordSize::XSmall, + 2 => KeywordSize::Small, + 3 => KeywordSize::Medium, + 4 => KeywordSize::Large, + 5 => KeywordSize::XLarge, + 6 => KeywordSize::XXLarge, + // If value is greater than 7, let it be 7. + _ => KeywordSize::XXXLarge, + }, 1., Au(0).into()) + } + + /// Compute it against a given base font size + pub fn to_computed_value_against( + &self, + context: &Context, + base_size: FontBaseSize, + ) -> computed::FontSize { + use values::specified::length::FontRelativeLength; + + let compose_keyword = |factor| { + context.style().get_parent_font() + .clone_font_size().info + .map(|i| i.compose(factor, Au(0).into())) + }; + let mut info = None; + let size = match *self { + FontSize::Length(LengthOrPercentage::Length( + NoCalcLength::FontRelative(value))) => { + if let FontRelativeLength::Em(em) = value { + // If the parent font was keyword-derived, this is too. + // Tack the em unit onto the factor + info = compose_keyword(em); + } + value.to_computed_value(context, base_size).into() + } + FontSize::Length(LengthOrPercentage::Length( + NoCalcLength::ServoCharacterWidth(value))) => { + value.to_computed_value(base_size.resolve(context)).into() + } + FontSize::Length(LengthOrPercentage::Length( + NoCalcLength::Absolute(ref l))) => { + context.maybe_zoom_text(l.to_computed_value(context).into()) + } + FontSize::Length(LengthOrPercentage::Length(ref l)) => { + l.to_computed_value(context).into() + } + FontSize::Length(LengthOrPercentage::Percentage(pc)) => { + // If the parent font was keyword-derived, this is too. + // Tack the % onto the factor + info = compose_keyword(pc.0); + base_size.resolve(context).scale_by(pc.0).into() + } + FontSize::Length(LengthOrPercentage::Calc(ref calc)) => { + let parent = context.style().get_parent_font().clone_font_size(); + // if we contain em/% units and the parent was keyword derived, this is too + // Extract the ratio/offset and compose it + if (calc.em.is_some() || calc.percentage.is_some()) && parent.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.info.map(|i| i.compose(ratio, abs)); + } + let calc = calc.to_computed_value_zoomed(context, base_size); + calc.to_used_value(Some(base_size.resolve(context))).unwrap().into() + } + FontSize::Keyword(key, fraction, offset) => { + // As a specified keyword, this is keyword derived + info = Some(computed::KeywordInfo { + kw: key, + factor: fraction, + offset: offset, + }); + context.maybe_zoom_text(key.to_computed_value(context).scale_by(fraction) + offset) + } + FontSize::Smaller => { + info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO); + FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) + .to_computed_value(context, base_size).into() + } + FontSize::Larger => { + info = compose_keyword(LARGER_FONT_SIZE_RATIO); + FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO) + .to_computed_value(context, base_size).into() + } + + FontSize::System(_) => { + #[cfg(feature = "servo")] { + unreachable!() + } + #[cfg(feature = "gecko")] { + context.cached_system_font.as_ref().unwrap().font_size.size + } + } + }; + computed::FontSize { size, info } + } +} + +impl ToComputedValue for FontSize { + type ComputedValue = computed::FontSize; + + #[inline] + fn to_computed_value(&self, context: &Context) -> computed::FontSize { + self.to_computed_value_against(context, FontBaseSize::InheritedStyle) + } + + #[inline] + fn from_computed_value(computed: &computed::FontSize) -> Self { + FontSize::Length(LengthOrPercentage::Length( + ToComputedValue::from_computed_value(&computed.size.0) + )) + } +} + +impl FontSize { + /// Construct a system font value. + pub fn system_font(f: SystemFont) -> Self { + FontSize::System(f) + } + + /// Obtain the system font, if any + pub fn get_system(&self) -> Option { + if let FontSize::System(s) = *self { + Some(s) + } else { + None + } + } +} diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 257781f62ae..7d1ff581a79 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -18,7 +18,7 @@ use style_traits::{ToCss, ParseError, StyleParseError}; use style_traits::values::specified::AllowedNumericType; use stylesheets::CssRuleType; use super::{AllowQuirks, Number, ToComputedValue, Percentage}; -use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, None_, Normal}; +use values::{Auto, CSSFloat, Either, None_, Normal}; use values::{ExtremumLength, serialize_dimension}; use values::computed::{self, CSSPixelLength, Context}; use values::generics::NonNegative; @@ -571,12 +571,6 @@ impl NoCalcLength { } } - #[inline] - /// Returns a `medium` length. - pub fn medium() -> NoCalcLength { - NoCalcLength::Absolute(AbsoluteLength::Px(FONT_MEDIUM_PX as f32)) - } - /// Get an absolute length from a px value. #[inline] pub fn from_px(px_value: CSSFloat) -> NoCalcLength { diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 856aecca90a..1add4928007 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -65,6 +65,7 @@ pub mod calc; pub mod color; pub mod effects; pub mod flex; +pub mod font; #[cfg(feature = "gecko")] pub mod gecko; pub mod grid; From cd6f68c5450451a78b8dc8a5755f178c20122629 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 18 Sep 2017 14:12:10 -0700 Subject: [PATCH 5/6] stylo: Clean up keyword values --- components/style/properties/gecko.mako.rs | 6 ++-- .../style/properties/longhand/font.mako.rs | 22 +++++++------- components/style/values/computed/font.rs | 25 ++++++++++++---- components/style/values/specified/font.rs | 29 +++++++++---------- 4 files changed, 48 insertions(+), 34 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index a0490db4e1d..33fe7cd5af0 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2164,7 +2164,7 @@ fn static_assert() { use values::specified::font::KeywordSize; self.gecko.mSize = v.size().0; self.gecko.mScriptUnconstrainedSize = v.size().0; - if let Some(info) = v.info { + if let Some(info) = v.keyword_info { self.gecko.mFontSizeKeyword = match info.kw { KeywordSize::XXSmall => structs::NS_STYLE_FONT_SIZE_XXSMALL, KeywordSize::XSmall => structs::NS_STYLE_FONT_SIZE_XSMALL, @@ -2385,14 +2385,14 @@ fn static_assert() { structs::NS_STYLE_FONT_SIZE_NO_KEYWORD => { return longhands::font_size::computed_value::T { size: size, - info: None, + keyword_info: None, } } _ => unreachable!("mFontSizeKeyword should be an absolute keyword or NO_KEYWORD") }; longhands::font_size::computed_value::T { size: size, - info: Some(KeywordInfo { + keyword_info: Some(KeywordInfo { kw: kw, factor: self.gecko.mFontSizeFactor, offset: Au(self.gecko.mFontSizeOffset).into() diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 455ea5dd14b..5b7b62be04a 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -603,6 +603,7 @@ ${helpers.single_keyword_system("font-variant-caps", use values::specified::AllowQuirks; use values::specified::length::FontBaseSize; use values::specified::font::{FONT_MEDIUM_PX, KeywordSize}; + use values::computed::font::{KeywordInfo}; pub mod computed_value { use values::computed::font; @@ -616,17 +617,13 @@ ${helpers.single_keyword_system("font-variant-caps", pub fn get_initial_value() -> computed_value::T { computed_value::T { size: Au::from_px(FONT_MEDIUM_PX).into(), - info: Some(::values::computed::font::KeywordInfo { - kw: KeywordSize::Medium, - factor: 1., - offset: Au(0).into(), - }) + keyword_info: Some(KeywordInfo::medium()) } } #[inline] pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Keyword(KeywordSize::Medium, 1., Au(0).into()) + SpecifiedValue::Keyword(KeywordInfo::medium()) } @@ -647,7 +644,7 @@ ${helpers.single_keyword_system("font-variant-caps", } if let Ok(kw) = input.try(KeywordSize::parse) { - return Ok(SpecifiedValue::Keyword(kw, 1., Au(0).into())) + return Ok(SpecifiedValue::Keyword(kw.into())) } try_match_ident_ignore_ascii_case! { input.expect_ident()?, @@ -670,7 +667,7 @@ ${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(info) = computed.info { + if let Some(info) = computed.keyword_info { computed.size = context.maybe_zoom_text(info.kw.to_computed_value(context) .scale_by(info.factor) + info.offset) } @@ -703,8 +700,8 @@ ${helpers.single_keyword_system("font-variant-caps", // handle mathml scriptlevel changes let kw_inherited_size = context.builder.get_parent_font() .clone_font_size() - .info.map(|info| { - context.maybe_zoom_text(SpecifiedValue::Keyword(info.kw, info.factor, info.offset) + .keyword_info.map(|info| { + context.maybe_zoom_text(SpecifiedValue::Keyword(info) .to_computed_value(context).size) }); let mut font = context.builder.take_font(); @@ -2205,7 +2202,10 @@ ${helpers.single_keyword("-moz-math-variant", let weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight); let ret = ComputedSystemFont { font_family: longhands::font_family::computed_value::T(family), - font_size: longhands::font_size::computed_value::T { size: Au(system.size).into(), info: None }, + font_size: longhands::font_size::computed_value::T { + size: Au(system.size).into(), + keyword_info: None + }, font_weight: weight, font_size_adjust: longhands::font_size_adjust::computed_value ::T::from_gecko_adjust(system.sizeAdjust), diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 62110779d61..5ba0a0e4953 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -10,8 +10,8 @@ use style_traits::ToCss; use values::computed::NonNegativeLength; use values::specified::font as specified; -#[derive(Copy, Clone, PartialEq, Debug)] -#[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] +#[derive(Animate, ComputeSquaredDistance, ToAnimatedValue, ToAnimatedZero)] +#[derive(Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] /// The computed value of font-size @@ -19,11 +19,11 @@ pub struct FontSize { /// The size. pub size: NonNegativeLength, /// If derived from a keyword, the keyword and additional transformations applied to it - pub info: Option, + pub keyword_info: Option, } -#[derive(Copy, Clone, PartialEq, Debug)] -#[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] +#[derive(Animate, ComputeSquaredDistance, ToAnimatedValue, ToAnimatedZero)] +#[derive(Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] /// Additional information for keyword-derived font sizes. @@ -45,6 +45,21 @@ impl KeywordInfo { offset: self.offset.scale_by(factor) + offset, } } + + /// KeywordInfo value for font-size: medium + pub fn medium() -> Self { + specified::KeywordSize::Medium.into() + } +} + +impl From for KeywordInfo { + fn from(x: specified::KeywordSize) -> Self { + KeywordInfo { + kw: x, + factor: 1., + offset: Au(0).into(), + } + } } impl FontSize { diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index af0d5df149b..417d2909413 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -32,7 +32,7 @@ pub enum FontSize { /// go into the ratio, and the remaining units all computed together /// will go into the offset. /// See bug 1355707. - Keyword(KeywordSize, f32, NonNegativeLength), + Keyword(computed::KeywordInfo), /// font-size: smaller Smaller, /// font-size: larger @@ -45,7 +45,7 @@ impl ToCss for FontSize { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { FontSize::Length(ref lop) => lop.to_css(dest), - FontSize::Keyword(kw, _, _) => kw.to_css(dest), + FontSize::Keyword(info) => info.kw.to_css(dest), FontSize::Smaller => dest.write_str("smaller"), FontSize::Larger => dest.write_str("larger"), FontSize::System(sys) => sys.to_css(dest), @@ -60,8 +60,8 @@ impl From for FontSize { } /// CSS font keywords +#[derive(Animate, ComputeSquaredDistance, ToAnimatedValue, ToAnimatedZero)] #[derive(Clone, Copy, Debug, PartialEq)] -#[derive(ToAnimatedValue, Animate, ToAnimatedZero, ComputeSquaredDistance)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[allow(missing_docs)] @@ -226,7 +226,7 @@ impl FontSize { 6 => KeywordSize::XXLarge, // If value is greater than 7, let it be 7. _ => KeywordSize::XXXLarge, - }, 1., Au(0).into()) + }.into()) } /// Compute it against a given base font size @@ -239,7 +239,7 @@ impl FontSize { let compose_keyword = |factor| { context.style().get_parent_font() - .clone_font_size().info + .clone_font_size().keyword_info .map(|i| i.compose(factor, Au(0).into())) }; let mut info = None; @@ -274,7 +274,7 @@ impl FontSize { let parent = context.style().get_parent_font().clone_font_size(); // if we contain em/% units and the parent was keyword derived, this is too // Extract the ratio/offset and compose it - if (calc.em.is_some() || calc.percentage.is_some()) && parent.info.is_some() { + 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 @@ -284,19 +284,15 @@ impl FontSize { // 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.info.map(|i| i.compose(ratio, abs)); + info = parent.keyword_info.map(|i| i.compose(ratio, abs)); } let calc = calc.to_computed_value_zoomed(context, base_size); calc.to_used_value(Some(base_size.resolve(context))).unwrap().into() } - FontSize::Keyword(key, fraction, offset) => { + FontSize::Keyword(i) => { // As a specified keyword, this is keyword derived - info = Some(computed::KeywordInfo { - kw: key, - factor: fraction, - offset: offset, - }); - context.maybe_zoom_text(key.to_computed_value(context).scale_by(fraction) + offset) + info = Some(i); + context.maybe_zoom_text(i.kw.to_computed_value(context).scale_by(i.factor) + i.offset) } FontSize::Smaller => { info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO); @@ -318,7 +314,10 @@ impl FontSize { } } }; - computed::FontSize { size, info } + computed::FontSize { + size: size, + keyword_info: info, + } } } From 454fb9f1e45bd33d8a67647e55279329e2452506 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 23 Sep 2017 11:25:42 -0700 Subject: [PATCH 6/6] stylo: Update ComputedValues size in test --- tests/unit/stylo/size_of.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/stylo/size_of.rs b/tests/unit/stylo/size_of.rs index 4a05b25ada3..a6e7d5e7c7c 100644 --- a/tests/unit/stylo/size_of.rs +++ b/tests/unit/stylo/size_of.rs @@ -32,7 +32,7 @@ fn size_of_selectors_dummy_types() { size_of_test!(test_size_of_rule, style::stylist::Rule, 32); // Large pages generate tens of thousands of ComputedValues. -size_of_test!(test_size_of_cv, ComputedValues, 272); +size_of_test!(test_size_of_cv, ComputedValues, 256); size_of_test!(test_size_of_option_arc_cv, Option>, 8); size_of_test!(test_size_of_option_rule_node, Option, 8);