From 8997888c6f359f6ad35c8f1defd28c7986d22bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 14 Feb 2023 22:36:31 +0000 Subject: [PATCH] style: Expose line-height resolution to style, and use it from ToResolvedValue For ToResolvedValue implementation purposes we wouldn't need to split out the vertical / font / line-height arguments and we could just pass around the ComputedStyle, but the lh unit would need that distinction, (because computing lh on font properties should use the parent style). Differential Revision: https://phabricator.services.mozilla.com/D168705 --- components/style/gecko/media_queries.rs | 26 ++++++++++++- .../style/properties/properties.mako.rs | 39 +++++++++---------- components/style/values/computed/text.rs | 10 ++--- components/style/values/resolved/mod.rs | 15 ++++++- 4 files changed, 62 insertions(+), 28 deletions(-) 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.