diff options
author | bors-servo <infra@servo.org> | 2023-05-11 21:04:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-11 21:04:45 +0200 |
commit | 9bec0d0f8e92e90b5d8c99ba691a9d9a6bb41bcc (patch) | |
tree | fbfaa73aa4702fdb2a32fe6838388189ab1d41db | |
parent | feaa66b5972c3e31d77c2acce7d626c455320535 (diff) | |
parent | ab2ba273e342c6f1a0c1f29cca3f551fd8926e94 (diff) | |
download | servo-9bec0d0f8e92e90b5d8c99ba691a9d9a6bb41bcc.tar.gz servo-9bec0d0f8e92e90b5d8c99ba691a9d9a6bb41bcc.zip |
Auto merge of #29728 - Loirooriol:sync-fontprovider-D157589, r=mrobinson
Simplify our setup for font metric queries from style
This is a backport of https://phabricator.services.mozilla.com/D157589,
by Emilio Cobos Álvarez, plus some additions so that Servo compiles,
and some parts from https://phabricator.services.mozilla.com/D144455.
Should have no change in behavior.
<!-- Please describe your changes on the following line: -->
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [ ] These changes fix #___ (GitHub issue number if applicable)
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because there should be no change in behavior
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
-rw-r--r-- | components/layout/query.rs | 4 | ||||
-rw-r--r-- | components/layout/traversal.rs | 1 | ||||
-rw-r--r-- | components/layout_2020/query.rs | 2 | ||||
-rw-r--r-- | components/layout_2020/traversal.rs | 1 | ||||
-rw-r--r-- | components/script/layout_dom/element.rs | 3 | ||||
-rw-r--r-- | components/script_layout_interface/wrapper_traits.rs | 3 | ||||
-rw-r--r-- | components/style/context.rs | 28 | ||||
-rw-r--r-- | components/style/dom.rs | 7 | ||||
-rw-r--r-- | components/style/driver.rs | 2 | ||||
-rw-r--r-- | components/style/font_metrics.rs | 63 | ||||
-rw-r--r-- | components/style/gecko/media_queries.rs | 72 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 128 | ||||
-rw-r--r-- | components/style/parallel.rs | 11 | ||||
-rw-r--r-- | components/style/properties/cascade.rs | 8 | ||||
-rw-r--r-- | components/style/servo/media_queries.rs | 17 | ||||
-rw-r--r-- | components/style/style_resolver.rs | 1 | ||||
-rw-r--r-- | components/style/stylesheets/viewport_rule.rs | 4 | ||||
-rw-r--r-- | components/style/stylist.rs | 30 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 53 | ||||
-rw-r--r-- | components/style/values/specified/font.rs | 34 | ||||
-rw-r--r-- | components/style/values/specified/length.rs | 22 |
21 files changed, 172 insertions, 322 deletions
diff --git a/components/layout/query.rs b/components/layout/query.rs index 1d4e810c23a..98a3ec662fb 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -856,7 +856,7 @@ where if element.has_data() { node.to_threadsafe().as_element().unwrap().resolved_style() } else { - let mut tlc = ThreadLocalStyleContext::new(&context.style_context); + let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { shared: &context.style_context, thread_local: &mut tlc, @@ -911,7 +911,7 @@ pub fn process_resolved_style_request<'dom>( return String::new(); } - let mut tlc = ThreadLocalStyleContext::new(&context.style_context); + let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { shared: &context.style_context, thread_local: &mut tlc, diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index d07f76105e8..840aba5ef05 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -46,7 +46,6 @@ impl<'a, 'dom, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a> where E: TElement, E::ConcreteNode: LayoutNode<'dom>, - E::FontMetricsProvider: Send, { fn process_preorder<F>( &self, diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs index 74420ae2bb5..3fd02a1597c 100644 --- a/components/layout_2020/query.rs +++ b/components/layout_2020/query.rs @@ -356,7 +356,7 @@ pub fn process_resolved_style_request_for_unstyled_node<'dom>( return String::new(); } - let mut tlc = ThreadLocalStyleContext::new(&context.style_context); + let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { shared: &context.style_context, thread_local: &mut tlc, diff --git a/components/layout_2020/traversal.rs b/components/layout_2020/traversal.rs index 1f73a7816f1..7ddb0e85ed4 100644 --- a/components/layout_2020/traversal.rs +++ b/components/layout_2020/traversal.rs @@ -34,7 +34,6 @@ impl<'a, 'dom, E> DomTraversal<E> for RecalcStyle<'a> where E: TElement, E::ConcreteNode: LayoutNode<'dom>, - E::FontMetricsProvider: Send, { fn process_preorder<F>( &self, diff --git a/components/script/layout_dom/element.rs b/components/script/layout_dom/element.rs index 9b9f8c4790b..adbeba7e39d 100644 --- a/components/script/layout_dom/element.rs +++ b/components/script/layout_dom/element.rs @@ -33,7 +33,6 @@ use style::context::SharedStyleContext; use style::data::ElementData; use style::dom::{DomChildren, LayoutIterator, TDocument, TElement, TNode, TShadowRoot}; use style::element_state::*; -use style::font_metrics::ServoMetricsProvider; use style::properties::PropertyDeclarationBlock; use style::selector_parser::{ extended_filtering, AttrValue as SelectorAttrValue, Lang, NonTSPseudoClass, PseudoElement, @@ -169,8 +168,6 @@ impl<'dom, LayoutDataType: LayoutDataTrait> style::dom::TElement type ConcreteNode = ServoLayoutNode<'dom, LayoutDataType>; type TraversalChildrenIterator = DomChildren<Self::ConcreteNode>; - type FontMetricsProvider = ServoMetricsProvider; - fn as_node(&self) -> ServoLayoutNode<'dom, LayoutDataType> { ServoLayoutNode::from_layout_js(self.element.upcast()) } diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 9091a394161..8ba009a7a47 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -25,7 +25,6 @@ use style::context::SharedStyleContext; use style::data::ElementData; use style::dom::OpaqueNode; use style::dom::{LayoutIterator, NodeInfo, TElement, TNode}; -use style::font_metrics::ServoMetricsProvider; use style::properties::ComputedValues; use style::selector_parser::{PseudoElement, PseudoElementCascadeType, SelectorImpl}; use style::stylist::RuleInclusion; @@ -439,7 +438,6 @@ pub trait ThreadSafeLayoutElement<'dom>: &context.guards, &style_pseudo, Some(data.styles.primary()), - &ServoMetricsProvider, ), PseudoElementCascadeType::Lazy => { context @@ -451,7 +449,6 @@ pub trait ThreadSafeLayoutElement<'dom>: RuleInclusion::All, data.styles.primary(), /* is_probe = */ false, - &ServoMetricsProvider, /* matching_func = */ None, ) .unwrap() diff --git a/components/style/context.rs b/components/style/context.rs index 21b3633f670..08fdb4d1eef 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -9,7 +9,6 @@ use crate::animation::DocumentAnimationSet; use crate::bloom::StyleBloom; use crate::data::{EagerPseudoStyles, ElementData}; use crate::dom::{SendElement, TElement}; -use crate::font_metrics::FontMetricsProvider; #[cfg(feature = "gecko")] use crate::gecko_bindings::structs; use crate::parallel::{STACK_SAFETY_MARGIN_KB, STYLE_THREAD_STACK_SIZE_KB}; @@ -720,9 +719,6 @@ pub struct ThreadLocalStyleContext<E: TElement> { pub selector_flags: SelectorFlagsMap<E>, /// Statistics about the traversal. pub statistics: PerThreadTraversalStatistics, - /// The struct used to compute and cache font metrics from style - /// for evaluation of the font-relative em/ch units and font-size - pub font_metrics_provider: E::FontMetricsProvider, /// A checker used to ensure that parallel.rs does not recurse indefinitely /// even on arbitrarily deep trees. See Gecko bug 1376883. pub stack_limit_checker: StackLimitChecker, @@ -731,27 +727,8 @@ pub struct ThreadLocalStyleContext<E: TElement> { } impl<E: TElement> ThreadLocalStyleContext<E> { - /// Creates a new `ThreadLocalStyleContext` from a shared one. - #[cfg(feature = "servo")] - pub fn new(shared: &SharedStyleContext) -> Self { - ThreadLocalStyleContext { - sharing_cache: StyleSharingCache::new(), - rule_cache: RuleCache::new(), - bloom_filter: StyleBloom::new(), - tasks: SequentialTaskList(Vec::new()), - selector_flags: SelectorFlagsMap::new(), - statistics: PerThreadTraversalStatistics::default(), - font_metrics_provider: E::FontMetricsProvider::create_from(shared), - stack_limit_checker: StackLimitChecker::new( - (STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024, - ), - nth_index_cache: NthIndexCache::default(), - } - } - - #[cfg(feature = "gecko")] - /// Creates a new `ThreadLocalStyleContext` from a shared one. - pub fn new(shared: &SharedStyleContext) -> Self { + /// Creates a new `ThreadLocalStyleContext` + pub fn new() -> Self { ThreadLocalStyleContext { sharing_cache: StyleSharingCache::new(), rule_cache: RuleCache::new(), @@ -759,7 +736,6 @@ impl<E: TElement> ThreadLocalStyleContext<E> { tasks: SequentialTaskList(Vec::new()), selector_flags: SelectorFlagsMap::new(), statistics: PerThreadTraversalStatistics::default(), - font_metrics_provider: E::FontMetricsProvider::create_from(shared), stack_limit_checker: StackLimitChecker::new( (STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024, ), diff --git a/components/style/dom.rs b/components/style/dom.rs index 86c5a382891..c23b985a628 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -13,7 +13,6 @@ use crate::context::SharedStyleContext; use crate::context::{PostAnimationTasks, UpdateAnimationsTasks}; use crate::data::ElementData; use crate::element_state::ElementState; -use crate::font_metrics::FontMetricsProvider; use crate::media_queries::Device; use crate::properties::{AnimationDeclarations, ComputedValues, PropertyDeclarationBlock}; use crate::selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl}; @@ -363,12 +362,6 @@ pub trait TElement: /// syntax. type TraversalChildrenIterator: Iterator<Item = Self::ConcreteNode>; - /// Type of the font metrics provider - /// - /// XXXManishearth It would be better to make this a type parameter on - /// ThreadLocalStyleContext and StyleContext - type FontMetricsProvider: FontMetricsProvider + Send; - /// Get this element as a node. fn as_node(&self) -> Self::ConcreteNode; diff --git a/components/style/driver.rs b/components/style/driver.rs index eab7c3a6a31..475d04269c5 100644 --- a/components/style/driver.rs +++ b/components/style/driver.rs @@ -91,7 +91,7 @@ where // ThreadLocalStyleContext has not released its TLS borrow by that point, // we'll panic on double-borrow. let mut tls_slots = None; - let mut tlc = ThreadLocalStyleContext::new(traversal.shared_context()); + let mut tlc = ThreadLocalStyleContext::new(); let mut context = StyleContext { shared: traversal.shared_context(), thread_local: &mut tlc, diff --git a/components/style/font_metrics.rs b/components/style/font_metrics.rs index db435539735..13a4e9e182b 100644 --- a/components/style/font_metrics.rs +++ b/components/style/font_metrics.rs @@ -6,9 +6,7 @@ #![deny(missing_docs)] -use crate::context::SharedStyleContext; use crate::values::computed::Length; -use crate::Atom; /// Represents the font metrics that style needs from a font to compute the /// value of certain CSS units like `ex`. @@ -47,64 +45,3 @@ pub enum FontMetricsOrientation { /// Force getting horizontal metrics. Horizontal, } - -/// A trait used to represent something capable of providing us font metrics. -pub trait FontMetricsProvider { - /// Obtain the metrics for given font family. - fn query( - &self, - _context: &crate::values::computed::Context, - _base_size: crate::values::specified::length::FontBaseSize, - _orientation: FontMetricsOrientation, - ) -> FontMetrics { - Default::default() - } - - /// Get default size of a given language and generic family. - fn get_size( - &self, - font_name: &Atom, - font_family: crate::values::computed::font::GenericFontFamily, - ) -> Length; - - /// Construct from a shared style context - fn create_from(context: &SharedStyleContext) -> Self - where - Self: Sized; -} - -// TODO: Servo's font metrics provider will probably not live in this crate, so this will -// have to be replaced with something else (perhaps a trait method on TElement) -// when we get there -#[derive(Debug)] -#[cfg(feature = "servo")] -/// Dummy metrics provider for Servo. Knows nothing about fonts and does not provide -/// any metrics. -pub struct ServoMetricsProvider; - -#[cfg(feature = "servo")] -impl FontMetricsProvider for ServoMetricsProvider { - fn create_from(_: &SharedStyleContext) -> Self { - ServoMetricsProvider - } - - fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Length { - unreachable!("Dummy provider should never be used to compute font size") - } -} - -// Servo's font metrics provider will probably not live in this crate, so this will -// have to be replaced with something else (perhaps a trait method on TElement) -// when we get there - -#[cfg(feature = "gecko")] -/// Construct a font metrics provider for the current product -pub fn get_metrics_provider_for_product() -> crate::gecko::wrapper::GeckoFontMetricsProvider { - crate::gecko::wrapper::GeckoFontMetricsProvider::new() -} - -#[cfg(feature = "servo")] -/// Construct a font metrics provider for the current product -pub fn get_metrics_provider_for_product() -> ServoMetricsProvider { - ServoMetricsProvider -} diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index a116121a258..08ef628f1ff 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -6,12 +6,14 @@ use crate::context::QuirksMode; use crate::custom_properties::CssEnvironment; +use crate::font_metrics::FontMetrics; use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; use crate::gecko_bindings::bindings; use crate::gecko_bindings::structs; use crate::media_queries::MediaType; use crate::properties::ComputedValues; use crate::string_cache::Atom; +use crate::values::computed::font::GenericFontFamily; use crate::values::computed::Length; use crate::values::specified::font::FONT_MEDIUM_PX; use crate::values::{CustomIdent, KeyframesName}; @@ -50,6 +52,8 @@ pub struct Device { /// Whether any styles computed in the document relied on the root font-size /// by using rem units. used_root_font_size: AtomicBool, + /// Whether any styles computed in the document relied on font metrics. + used_font_metrics: AtomicBool, /// Whether any styles computed in the document relied on the viewport size /// by using vw/vh/vmin/vmax units. used_viewport_size: AtomicBool, @@ -91,6 +95,7 @@ impl Device { root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()), body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize), used_root_font_size: AtomicBool::new(false), + used_font_metrics: AtomicBool::new(false), used_viewport_size: AtomicBool::new(false), environment: CssEnvironment, } @@ -157,6 +162,67 @@ impl Device { .store(convert_rgba_to_nscolor(&color) as usize, Ordering::Relaxed) } + /// Gets the base size given a generic font family and a language. + pub fn base_size_for_generic(&self, language: &Atom, generic: GenericFontFamily) -> Length { + unsafe { bindings::Gecko_GetBaseSize(self.document(), language.as_ptr(), generic) } + } + + /// Queries font metrics + pub fn query_font_metrics( + &self, + vertical: bool, + font: &crate::properties::style_structs::Font, + base_size: Length, + in_media_query: bool, + retrieve_math_scales: bool, + ) -> FontMetrics { + self.used_font_metrics.store(true, Ordering::Relaxed); + let pc = match self.pres_context() { + Some(pc) => pc, + None => return Default::default(), + }; + let gecko_metrics = unsafe { + bindings::Gecko_GetFontMetrics( + pc, + vertical, + font.gecko(), + base_size, + // we don't use the user font set in a media query + !in_media_query, + retrieve_math_scales, + ) + }; + FontMetrics { + x_height: Some(gecko_metrics.mXSize), + zero_advance_measure: if gecko_metrics.mChSize.px() >= 0. { + Some(gecko_metrics.mChSize) + } else { + None + }, + cap_height: if gecko_metrics.mCapHeight.px() >= 0. { + Some(gecko_metrics.mCapHeight) + } else { + None + }, + ic_width: if gecko_metrics.mIcWidth.px() >= 0. { + Some(gecko_metrics.mIcWidth) + } else { + None + }, + ascent: gecko_metrics.mAscent, + script_percent_scale_down: if gecko_metrics.mScriptPercentScaleDown > 0. { + Some(gecko_metrics.mScriptPercentScaleDown) + } else { + None + }, + script_script_percent_scale_down: if gecko_metrics.mScriptScriptPercentScaleDown > 0. { + Some(gecko_metrics.mScriptScriptPercentScaleDown) + } else { + None + }, + } + } + /// Returns the body text color. pub fn body_text_color(&self) -> RGBA { convert_nscolor_to_rgba(self.body_text_color.load(Ordering::Relaxed) as u32) @@ -196,6 +262,7 @@ impl Device { pub fn rebuild_cached_data(&mut self) { self.reset_computed_values(); self.used_root_font_size.store(false, Ordering::Relaxed); + self.used_font_metrics.store(false, Ordering::Relaxed); self.used_viewport_size.store(false, Ordering::Relaxed); } @@ -287,6 +354,11 @@ impl Device { self.used_viewport_size.load(Ordering::Relaxed) } + /// Returns whether font metrics have been queried. + pub fn used_font_metrics(&self) -> bool { + self.used_font_metrics.load(Ordering::Relaxed) + } + /// Returns the device pixel ratio. pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> { let pc = match self.pres_context() { diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 78e41cf767f..7d4b4e03f73 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -20,7 +20,6 @@ use crate::context::{PostAnimationTasks, QuirksMode, SharedStyleContext, UpdateA use crate::data::ElementData; use crate::dom::{LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNode, TShadowRoot}; use crate::element_state::{DocumentState, ElementState}; -use crate::font_metrics::{FontMetrics, FontMetricsOrientation, FontMetricsProvider}; use crate::gecko::data::GeckoStyleSheet; use crate::gecko::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl}; use crate::gecko::snapshot_helpers; @@ -67,9 +66,6 @@ use crate::selector_parser::{AttrValue, HorizontalDirection, Lang}; use crate::shared_lock::{Locked, SharedRwLock}; use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use crate::stylist::CascadeData; -use crate::values::computed::font::GenericFontFamily; -use crate::values::computed::Length; -use crate::values::specified::length::FontBaseSize; use crate::values::{AtomIdent, AtomString}; use crate::CaseSensitivityExt; use crate::LocalName; @@ -81,7 +77,6 @@ use selectors::matching::{ElementSelectorFlags, MatchingContext}; use selectors::sink::Push; use selectors::{Element, OpaqueElement}; use servo_arc::{Arc, ArcBorrow, RawOffsetArc}; -use std::cell::RefCell; use std::fmt; use std::hash::{Hash, Hasher}; use std::mem; @@ -920,131 +915,8 @@ fn get_animation_rule( } } -#[derive(Debug)] -/// Gecko font metrics provider -pub struct GeckoFontMetricsProvider { - /// Cache of base font sizes for each language. Usually will have 1 element. - /// - /// This may be slow on pages using more languages, might be worth - /// optimizing by caching lang->group mapping separately and/or using a - /// hashmap on larger loads. - pub font_size_cache: RefCell<Vec<(Atom, DefaultFontSizes)>>, -} - -impl GeckoFontMetricsProvider { - /// Construct - pub fn new() -> Self { - GeckoFontMetricsProvider { - font_size_cache: RefCell::new(Vec::new()), - } - } -} - -impl FontMetricsProvider for GeckoFontMetricsProvider { - fn create_from(_: &SharedStyleContext) -> GeckoFontMetricsProvider { - GeckoFontMetricsProvider::new() - } - - fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Length { - let mut cache = self.font_size_cache.borrow_mut(); - if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) { - return sizes.1.size_for_generic(font_family); - } - let sizes = unsafe { bindings::Gecko_GetBaseSize(font_name.as_ptr()) }; - let size = sizes.size_for_generic(font_family); - cache.push((font_name.clone(), sizes)); - size - } - - fn query( - &self, - context: &crate::values::computed::Context, - base_size: FontBaseSize, - orientation: FontMetricsOrientation, - ) -> FontMetrics { - let pc = match context.device().pres_context() { - Some(pc) => pc, - None => return Default::default(), - }; - - let size = base_size.resolve(context); - let style = context.style(); - - let (wm, font) = match base_size { - FontBaseSize::CurrentStyle => (style.writing_mode, style.get_font()), - // This is only used for font-size computation. - FontBaseSize::InheritedStyle => { - (*style.inherited_writing_mode(), style.get_parent_font()) - }, - }; - - let vertical_metrics = match orientation { - FontMetricsOrientation::MatchContextPreferHorizontal => { - wm.is_vertical() && wm.is_upright() - }, - FontMetricsOrientation::MatchContextPreferVertical => { - wm.is_vertical() && !wm.is_sideways() - }, - FontMetricsOrientation::Horizontal => false, - }; - let gecko_metrics = unsafe { - bindings::Gecko_GetFontMetrics( - pc, - vertical_metrics, - font.gecko(), - size, - // we don't use the user font set in a media query - !context.in_media_query, - ) - }; - FontMetrics { - x_height: Some(gecko_metrics.mXSize), - zero_advance_measure: if gecko_metrics.mChSize.px() >= 0. { - Some(gecko_metrics.mChSize) - } else { - None - }, - cap_height: if gecko_metrics.mCapHeight.px() >= 0. { - Some(gecko_metrics.mCapHeight) - } else { - None - }, - ascent: gecko_metrics.mAscent, - } - } -} - -/// The default font sizes for generic families for a given language group. -#[derive(Debug)] -#[repr(C)] -pub struct DefaultFontSizes { - variable: Length, - serif: Length, - sans_serif: Length, - monospace: Length, - cursive: Length, - fantasy: Length, -} - -impl DefaultFontSizes { - fn size_for_generic(&self, font_family: GenericFontFamily) -> Length { - match font_family { - GenericFontFamily::None => self.variable, - GenericFontFamily::Serif => self.serif, - GenericFontFamily::SansSerif => self.sans_serif, - GenericFontFamily::Monospace => self.monospace, - GenericFontFamily::Cursive => self.cursive, - GenericFontFamily::Fantasy => self.fantasy, - GenericFontFamily::MozEmoji => unreachable!( - "Should never get here, since this doesn't (yet) appear on font family" - ), - } - } -} - impl<'le> TElement for GeckoElement<'le> { type ConcreteNode = GeckoNode<'le>; - type FontMetricsProvider = GeckoFontMetricsProvider; type TraversalChildrenIterator = GeckoChildrenIterator<'le>; fn inheritance_parent(&self) -> Option<Self> { diff --git a/components/style/parallel.rs b/components/style/parallel.rs index 44618ef2fc1..f03bf64fe61 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -75,14 +75,11 @@ type WorkUnit<N> = ArrayVec<SendNode<N>, WORK_UNIT_MAX>; /// out of line so we don't allocate stack space for the entire struct /// in the caller. #[inline(never)] -fn create_thread_local_context<'scope, E, D>( - traversal: &'scope D, - slot: &mut Option<ThreadLocalStyleContext<E>>, -) where +fn create_thread_local_context<'scope, E>(slot: &mut Option<ThreadLocalStyleContext<E>>) +where E: TElement + 'scope, - D: DomTraversal<E>, { - *slot = Some(ThreadLocalStyleContext::new(traversal.shared_context())); + *slot = Some(ThreadLocalStyleContext::new()); } /// A parallel top-down DOM traversal. @@ -127,7 +124,7 @@ fn top_down_dom<'a, 'scope, E, D>( // Scope the borrow of the TLS so that the borrow is dropped before // a potential recursive call when we pass TailCall. let mut tlc = tls.ensure(|slot: &mut Option<ThreadLocalStyleContext<E>>| { - create_thread_local_context(traversal, slot) + create_thread_local_context(slot) }); // Check that we're not in danger of running out of stack. diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index acfdfc51457..f7ab9f95fde 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -7,7 +7,6 @@ use crate::context::QuirksMode; use crate::custom_properties::CustomPropertiesBuilder; use crate::dom::TElement; -use crate::font_metrics::FontMetricsProvider; use crate::logical_geometry::WritingMode; use crate::media_queries::Device; use crate::properties::{ @@ -82,7 +81,6 @@ pub fn cascade<E>( parent_style_ignoring_first_line: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, visited_rules: Option<&StrongRuleNode>, - font_metrics_provider: &dyn FontMetricsProvider, quirks_mode: QuirksMode, rule_cache: Option<&RuleCache>, rule_cache_conditions: &mut RuleCacheConditions, @@ -99,7 +97,6 @@ where parent_style, parent_style_ignoring_first_line, layout_parent_style, - font_metrics_provider, CascadeMode::Unvisited { visited_rules }, quirks_mode, rule_cache, @@ -197,7 +194,6 @@ fn cascade_rules<E>( parent_style: Option<&ComputedValues>, parent_style_ignoring_first_line: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, - font_metrics_provider: &dyn FontMetricsProvider, cascade_mode: CascadeMode, quirks_mode: QuirksMode, rule_cache: Option<&RuleCache>, @@ -220,7 +216,6 @@ where parent_style, parent_style_ignoring_first_line, layout_parent_style, - font_metrics_provider, cascade_mode, quirks_mode, rule_cache, @@ -256,7 +251,6 @@ pub fn apply_declarations<'a, E, I>( parent_style: Option<&ComputedValues>, parent_style_ignoring_first_line: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, - font_metrics_provider: &dyn FontMetricsProvider, cascade_mode: CascadeMode, quirks_mode: QuirksMode, rule_cache: Option<&RuleCache>, @@ -317,7 +311,6 @@ where in_media_query: false, for_smil_animation: false, for_non_inherited_property: None, - font_metrics_provider, quirks_mode, rule_cache_conditions: RefCell::new(rule_cache_conditions), }; @@ -762,7 +755,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { visited_parent!(parent_style), visited_parent!(parent_style_ignoring_first_line), visited_parent!(layout_parent_style), - self.context.font_metrics_provider, CascadeMode::Visited { writing_mode }, self.context.quirks_mode, // The rule cache doesn't care about caching :visited diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index 17949c723d0..4b535a9b875 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -6,6 +6,7 @@ use crate::context::QuirksMode; use crate::custom_properties::CssEnvironment; +use crate::font_metrics::FontMetrics; use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements}; use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription}; use crate::media_queries::media_feature_expression::RangeOrOperator; @@ -156,6 +157,22 @@ impl Device { self.device_pixel_ratio } + /// Queries dummy font metrics for Servo. Knows nothing about fonts and does not provide + /// any metrics. + /// TODO: Servo's font metrics provider will probably not live in this crate, so this will + /// have to be replaced with something else (perhaps a trait method on TElement) + /// when we get there + pub fn query_font_metrics( + &self, + _vertical: bool, + _font: &crate::properties::style_structs::Font, + _base_size: CSSPixelLength, + _in_media_query: bool, + _retrieve_math_scales: bool, + ) -> FontMetrics { + Default::default() + } + /// Take into account a viewport rule taken from the stylesheets. pub fn account_for_viewport_rule(&mut self, constraints: &ViewportConstraints) { self.viewport_size = constraints.size; diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index 7c28e001403..81517f6cd64 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -351,7 +351,6 @@ where parent_style, parent_style, layout_parent_style, - &self.context.thread_local.font_metrics_provider, Some(&self.context.thread_local.rule_cache), &mut conditions, ); diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index 9f751ece265..3353662cb4b 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -9,7 +9,6 @@ use crate::context::QuirksMode; use crate::error_reporting::ContextualParseError; -use crate::font_metrics::get_metrics_provider_for_product; use crate::media_queries::Device; use crate::parser::{Parse, ParserContext}; use crate::properties::StyleBuilder; @@ -673,14 +672,11 @@ impl MaybeNew for ViewportConstraints { // DEVICE-ADAPT § 6.2.3 Resolve non-auto lengths to pixel lengths let initial_viewport = device.au_viewport_size(); - let provider = get_metrics_provider_for_product(); - let mut conditions = RuleCacheConditions::default(); let context = Context { // Note: DEVICE-ADAPT § 5. states that relative length values are // resolved against initial values builder: StyleBuilder::for_inheritance(device, None, None), - font_metrics_provider: &provider, cached_system_font: None, in_media_query: false, quirks_mode: quirks_mode, diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 9a2134450de..5cb40b968eb 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -8,7 +8,6 @@ use crate::applicable_declarations::{ApplicableDeclarationBlock, ApplicableDecla use crate::context::{CascadeInputs, QuirksMode}; use crate::dom::{TElement, TShadowRoot}; use crate::element_state::{DocumentState, ElementState}; -use crate::font_metrics::FontMetricsProvider; #[cfg(feature = "gecko")] use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion}; use crate::invalidation::element::invalidation_map::InvalidationMap; @@ -662,7 +661,6 @@ impl Stylist { guards: &StylesheetGuards, pseudo: &PseudoElement, parent: Option<&ComputedValues>, - font_metrics: &dyn FontMetricsProvider, ) -> Arc<ComputedValues> where E: TElement, @@ -671,13 +669,7 @@ impl Stylist { let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]); - self.precomputed_values_for_pseudo_with_rule_node::<E>( - guards, - pseudo, - parent, - font_metrics, - rule_node, - ) + self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node) } /// Computes the style for a given "precomputed" pseudo-element with @@ -690,7 +682,6 @@ impl Stylist { guards: &StylesheetGuards, pseudo: &PseudoElement, parent: Option<&ComputedValues>, - font_metrics: &dyn FontMetricsProvider, rules: StrongRuleNode, ) -> Arc<ComputedValues> where @@ -704,7 +695,6 @@ impl Stylist { pseudo, guards, parent, - font_metrics, None, ) } @@ -759,13 +749,7 @@ impl Stylist { where E: TElement, { - use crate::font_metrics::ServoMetricsProvider; - self.precomputed_values_for_pseudo::<E>( - guards, - &pseudo, - Some(parent_style), - &ServoMetricsProvider, - ) + self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style)) } /// Computes a pseudo-element style lazily during layout. @@ -783,7 +767,6 @@ impl Stylist { rule_inclusion: RuleInclusion, parent_style: &ComputedValues, is_probe: bool, - font_metrics: &dyn FontMetricsProvider, matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>, ) -> Option<Arc<ComputedValues>> where @@ -804,7 +787,6 @@ impl Stylist { pseudo, guards, Some(parent_style), - font_metrics, Some(element), )) } @@ -819,7 +801,6 @@ impl Stylist { pseudo: &PseudoElement, guards: &StylesheetGuards, parent_style: Option<&ComputedValues>, - font_metrics: &dyn FontMetricsProvider, element: Option<E>, ) -> Arc<ComputedValues> where @@ -845,7 +826,6 @@ impl Stylist { parent_style, parent_style, parent_style, - font_metrics, /* rule_cache = */ None, &mut RuleCacheConditions::default(), ) @@ -872,7 +852,6 @@ impl Stylist { parent_style: Option<&ComputedValues>, parent_style_ignoring_first_line: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, - font_metrics: &dyn FontMetricsProvider, rule_cache: Option<&RuleCache>, rule_cache_conditions: &mut RuleCacheConditions, ) -> Arc<ComputedValues> @@ -909,7 +888,6 @@ impl Stylist { parent_style_ignoring_first_line, layout_parent_style, visited_rules, - font_metrics, self.quirks_mode, rule_cache, rule_cache_conditions, @@ -1326,10 +1304,7 @@ impl Stylist { where E: TElement, { - use crate::font_metrics::get_metrics_provider_for_product; - let block = declarations.read_with(guards.author); - let metrics = get_metrics_provider_for_product(); // We don't bother inserting these declarations in the rule tree, since // it'd be quite useless and slow. @@ -1348,7 +1323,6 @@ impl Stylist { Some(parent_style), Some(parent_style), Some(parent_style), - &metrics, CascadeMode::Unvisited { visited_rules: None, }, diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 1b242547307..9dbbf40b5f4 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -14,13 +14,15 @@ use super::generics::transform::IsParallelTo; use super::generics::{self, GreaterThanOrEqualToOne, NonNegative, ZeroToOne}; use super::specified; use super::{CSSFloat, CSSInteger}; +use crate::computed_value_flags::ComputedValueFlags; use crate::context::QuirksMode; -use crate::font_metrics::{get_metrics_provider_for_product, FontMetricsProvider}; +use crate::font_metrics::{FontMetrics, FontMetricsOrientation}; use crate::media_queries::Device; #[cfg(feature = "gecko")] use crate::properties; use crate::properties::{ComputedValues, LonghandId, StyleBuilder}; use crate::rule_cache::RuleCacheConditions; +use crate::values::specified::length::FontBaseSize; use crate::{ArcSlice, Atom, One}; use euclid::{default, Point2D, Rect, Size2D}; use servo_arc::Arc; @@ -155,10 +157,6 @@ pub struct Context<'a> { #[cfg(feature = "servo")] pub cached_system_font: Option<()>, - /// A font metrics provider, used to access font metrics to implement - /// font-relative units. - pub font_metrics_provider: &'a dyn FontMetricsProvider, - /// Whether or not we are computing the media list in a media query pub in_media_query: bool, @@ -192,11 +190,9 @@ impl<'a> Context<'a> { F: FnOnce(&Context) -> R, { let mut conditions = RuleCacheConditions::default(); - let provider = get_metrics_provider_for_product(); let context = Context { builder: StyleBuilder::for_inheritance(device, None, None), - font_metrics_provider: &provider, cached_system_font: None, in_media_query: true, quirks_mode, @@ -213,6 +209,49 @@ impl<'a> Context<'a> { self.builder.device } + /// Queries font metrics. + pub fn query_font_metrics( + &self, + base_size: FontBaseSize, + orientation: FontMetricsOrientation, + retrieve_math_scales: bool, + ) -> FontMetrics { + if self.for_non_inherited_property.is_some() { + self.rule_cache_conditions.borrow_mut().set_uncacheable(); + } + self.builder.add_flags(match base_size { + FontBaseSize::CurrentStyle => ComputedValueFlags::DEPENDS_ON_SELF_FONT_METRICS, + FontBaseSize::InheritedStyle => ComputedValueFlags::DEPENDS_ON_INHERITED_FONT_METRICS, + }); + let size = base_size.resolve(self); + let style = self.style(); + + let (wm, font) = match base_size { + FontBaseSize::CurrentStyle => (style.writing_mode, style.get_font()), + // This is only used for font-size computation. + FontBaseSize::InheritedStyle => { + (*style.inherited_writing_mode(), style.get_parent_font()) + }, + }; + + let vertical = match orientation { + FontMetricsOrientation::MatchContextPreferHorizontal => { + wm.is_vertical() && wm.is_upright() + }, + FontMetricsOrientation::MatchContextPreferVertical => { + wm.is_vertical() && !wm.is_sideways() + }, + FontMetricsOrientation::Horizontal => false, + }; + self.device().query_font_metrics( + vertical, + font, + size, + self.in_media_query, + retrieve_math_scales, + ) + } + /// The current viewport size, used to resolve viewport units. pub fn viewport_size_for_viewport_unit_resolution(&self) -> default::Size2D<Au> { self.builder diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index bda757440bb..b83b6411fee 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -5,6 +5,8 @@ //! Specified values for font properties #[cfg(feature = "gecko")] +use crate::context::QuirksMode; +#[cfg(feature = "gecko")] use crate::gecko_bindings::bindings; use crate::parser::{Parse, ParserContext}; use crate::properties::longhands::system_font::SystemFont; @@ -811,8 +813,27 @@ impl FontSizeKeyword { #[cfg(feature = "gecko")] #[inline] fn to_length(&self, cx: &Context) -> NonNegativeLength { - use crate::context::QuirksMode; + let gecko_font = cx.style().get_font().gecko(); + let family = &gecko_font.mFont.family.families; + let generic = family + .single_generic() + .unwrap_or(computed::GenericFontFamily::None); + let base_size = unsafe { + Atom::with(gecko_font.mLanguage.mRawPtr, |language| { + cx.device().base_size_for_generic(language, generic) + }) + }; + self.to_length_without_context(cx.quirks_mode, base_size) + } + /// Resolve a keyword length without any context, with explicit arguments. + #[cfg(feature = "gecko")] + #[inline] + pub fn to_length_without_context( + &self, + quirks_mode: QuirksMode, + base_size: Length, + ) -> NonNegativeLength { // The tables in this function are originally from // nsRuleNode::CalcFontPointSize in Gecko: // @@ -856,19 +877,10 @@ impl FontSizeKeyword { ]; static FONT_SIZE_FACTORS: [i32; 8] = [60, 75, 89, 100, 120, 150, 200, 300]; - - let ref gecko_font = cx.style().get_font().gecko(); - let base_size = unsafe { - Atom::with(gecko_font.mLanguage.mRawPtr, |atom| { - cx.font_metrics_provider - .get_size(atom, gecko_font.mGenericID) - }) - }; - let base_size_px = base_size.px().round() as i32; let html_size = self.html_size() as usize; NonNegative(if base_size_px >= 9 && base_size_px <= 16 { - let mapping = if cx.quirks_mode == QuirksMode::Quirks { + let mapping = if quirks_mode == QuirksMode::Quirks { QUIRKS_FONT_SIZE_MAPPING } else { FONT_SIZE_MAPPING diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 62f070893a6..cf529408c98 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -7,7 +7,6 @@ //! [length]: https://drafts.csswg.org/css-values/#lengths use super::{AllowQuirks, Number, Percentage, ToComputedValue}; -use crate::computed_value_flags::ComputedValueFlags; use crate::font_metrics::{FontMetrics, FontMetricsOrientation}; use crate::parser::{Parse, ParserContext}; use crate::values::computed::{self, CSSPixelLength, Context}; @@ -159,16 +158,11 @@ impl FontRelativeLength { base_size: FontBaseSize, orientation: FontMetricsOrientation, ) -> FontMetrics { - context - .font_metrics_provider - .query(context, base_size, orientation) + let retrieve_math_scales = false; + context.query_font_metrics(base_size, orientation, retrieve_math_scales) } let reference_font_size = base_size.resolve(context); - let font_metrics_flag = match base_size { - FontBaseSize::CurrentStyle => ComputedValueFlags::DEPENDS_ON_SELF_FONT_METRICS, - FontBaseSize::InheritedStyle => ComputedValueFlags::DEPENDS_ON_INHERITED_FONT_METRICS, - }; match *self { FontRelativeLength::Em(length) => { if context.for_non_inherited_property.is_some() { @@ -183,10 +177,6 @@ impl FontRelativeLength { (reference_font_size, length) }, FontRelativeLength::Ex(length) => { - if context.for_non_inherited_property.is_some() { - context.rule_cache_conditions.borrow_mut().set_uncacheable(); - } - context.builder.add_flags(font_metrics_flag); // The x-height is an intrinsically horizontal metric. let metrics = query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal); @@ -202,10 +192,6 @@ impl FontRelativeLength { (reference_size, length) }, FontRelativeLength::Ch(length) => { - if context.for_non_inherited_property.is_some() { - context.rule_cache_conditions.borrow_mut().set_uncacheable(); - } - context.builder.add_flags(font_metrics_flag); // https://drafts.csswg.org/css-values/#ch: // // Equal to the used advance measure of the “0” (ZERO, @@ -239,10 +225,6 @@ impl FontRelativeLength { (reference_size, length) }, FontRelativeLength::Cap(length) => { - if context.for_non_inherited_property.is_some() { - context.rule_cache_conditions.borrow_mut().set_uncacheable(); - } - context.builder.add_flags(font_metrics_flag); let metrics = query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal); let reference_size = metrics.cap_height.unwrap_or_else(|| { |