diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index ac64e6b5f34..a23ed306bd9 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -14,7 +14,7 @@ use crate::media_queries::MediaType; use crate::properties::ComputedValues; use crate::string_cache::Atom; use crate::values::computed::font::GenericFontFamily; -use crate::values::computed::{ColorScheme, Length}; +use crate::values::computed::{ColorScheme, Length, NonNegativeLength}; use crate::values::specified::color::SystemColor; use crate::values::specified::font::FONT_MEDIUM_PX; use crate::values::specified::ViewportVariant; @@ -115,6 +115,30 @@ impl Device { &self.environment } + /// Returns the computed line-height for the font in a given computed values instance. + /// + /// If you pass down an element, then the used line-height is returned. + pub fn calc_line_height( + &self, + line_height: &crate::values::computed::LineHeight, + vertical: bool, + font: &crate::properties::style_structs::Font, + element: Option, + ) -> NonNegativeLength { + let pres_context = self.pres_context(); + let au = Au(unsafe { + bindings::Gecko_CalcLineHeight( + line_height, + pres_context.map_or(std::ptr::null(), |pc| pc), + vertical, + font.gecko(), + element.map_or(std::ptr::null(), |e| e.0) + ) + }); + NonNegativeLength::new(au.to_f32_px()) + } + + /// Tells the device that a new viewport rule has been found, and stores the /// relevant viewport constraints. pub fn account_for_viewport_rule(&mut self, _constraints: &ViewportConstraints) { diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 2587bd1987c..69feaa2f1e5 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -3145,24 +3145,18 @@ impl ComputedValues { } % endfor - /// Writes the value of the given longhand as a string in `dest`. - /// - /// Note that the value will usually be the computed value, except for - /// colors, where it's resolved. + /// Writes the (resolved or computed) value of the given longhand as a string in `dest`. /// /// TODO(emilio): We should move all the special resolution from /// nsComputedDOMStyle to ToResolvedValue instead. - pub fn get_resolved_value( + pub fn computed_or_resolved_value( &self, property_id: LonghandId, + context: Option<<&resolved::Context>, dest: &mut CssStringWriter, ) -> fmt::Result { use crate::values::resolved::ToResolvedValue; - let mut dest = CssWriter::new(dest); - let context = resolved::Context { - style: self, - }; match property_id { % for specified_type, props in groupby(data.longhands, key=lambda x: x.specified_type()): <% props = list(props) %> @@ -3173,34 +3167,39 @@ impl ComputedValues { % endfor _ => unsafe { debug_unreachable!() }, }; - value.to_resolved_value(&context).to_css(&mut dest) + if let Some(c) = context { + value.to_resolved_value(c).to_css(&mut dest) + } else { + value.to_css(&mut dest) + } } % endfor } } /// Returns the given longhand's resolved value as a property declaration. - pub fn resolved_declaration(&self, property_id: LonghandId) -> PropertyDeclaration { + pub fn computed_or_resolved_declaration( + &self, + property_id: LonghandId, + context: Option<<&resolved::Context>, + ) -> PropertyDeclaration { use crate::values::resolved::ToResolvedValue; use crate::values::computed::ToComputedValue; - - let context = resolved::Context { - style: self, - }; - match property_id { % for specified_type, props in groupby(data.longhands, key=lambda x: x.specified_type()): <% props = list(props) %> ${" |\n".join("LonghandId::{}".format(p.camel_case) for p in props)} => { - let value = match property_id { + let mut computed_value = match property_id { % for prop in props: LonghandId::${prop.camel_case} => self.clone_${prop.ident}(), % endfor _ => unsafe { debug_unreachable!() }, }; - let resolved = value.to_resolved_value(&context); - let computed = ToResolvedValue::from_resolved_value(resolved); - let specified = ToComputedValue::from_computed_value(&computed); + if let Some(c) = context { + let resolved = computed_value.to_resolved_value(c); + computed_value = ToResolvedValue::from_resolved_value(resolved); + } + let specified = ToComputedValue::from_computed_value(&computed_value); % if props[0].boxed: let specified = Box::new(specified); % endif diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 3db55672705..ba395c1c366 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -119,12 +119,12 @@ impl ToResolvedValue for LineHeight { fn to_resolved_value(self, context: &ResolvedContext) -> Self::ResolvedValue { // Resolve to an absolute based on font size. - if let LineHeight::Number(num) = &self { - let size = context.style.get_font().clone_font_size().computed_size(); - LineHeight::Length(NonNegativeLength::new(size.px() * num.0)) - } else { - self + if matches!(self, Self::Normal | Self::MozBlockHeight) { + return self; } + let wm = context.style.writing_mode; + let vertical = wm.is_vertical() && !wm.is_sideways(); + Self::Length(context.device.calc_line_height(&self, vertical, context.style.get_font(), Some(context.element_info.element))) } #[inline] diff --git a/components/style/values/resolved/mod.rs b/components/style/values/resolved/mod.rs index a765980756c..4bd4be22d2a 100644 --- a/components/style/values/resolved/mod.rs +++ b/components/style/values/resolved/mod.rs @@ -5,6 +5,7 @@ //! Resolved values. These are almost always computed values, but in some cases //! there are used values. +use crate::media_queries::Device; use crate::properties::ComputedValues; use crate::ArcSlice; use cssparser; @@ -16,12 +17,22 @@ mod counters; use crate::values::computed; +/// Element-specific information needed to resolve property values. +pub struct ResolvedElementInfo<'a> { + /// Element we're resolving line-height against. + #[cfg(feature = "gecko")] + pub element: crate::gecko::wrapper::GeckoElement<'a>, +} + /// Information needed to resolve a given value. pub struct Context<'a> { /// The style we're resolving for. This is useful to resolve currentColor. pub style: &'a ComputedValues, - // TODO(emilio): Add layout box information, and maybe property-specific - // information? + /// The device / document we're resolving style for. Useful to do font metrics stuff needed for + /// line-height. + pub device: &'a Device, + /// The element-specific information to resolve the value. + pub element_info: ResolvedElementInfo<'a>, } /// A trait to represent the conversion between resolved and resolved values.