diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index e810c3e4f31e..f8eee7a9617a 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -2919,7 +2919,9 @@ static GeckoFontMetrics GetFontMetricsFromCanvas(void* aContext) { 0.0f, 0.0f}; } - auto metrics = fontGroup->GetMetricsForCSSUnits(nsFontMetrics::eHorizontal); + auto metrics = fontGroup->GetMetricsForCSSUnits( + nsFontMetrics::eHorizontal, StyleQueryFontMetricsFlags::NEEDS_CH | + StyleQueryFontMetricsFlags::NEEDS_IC); return {Length::FromPixels(metrics.xHeight), Length::FromPixels(metrics.zeroWidth), Length::FromPixels(metrics.capHeight), @@ -3037,8 +3039,9 @@ class CanvasUserSpaceMetrics final : public UserSpaceMetricsWithSize { return Gecko_GetFontMetrics( mPresContext, WritingMode(mCanvasStyle).IsVertical(), mCanvasStyle->StyleFont(), mCanvasStyle->StyleFont()->mFont.size, - /* aUseUserFontSet = */ true, - /* aRetrieveMathScales */ false); + StyleQueryFontMetricsFlags::USE_USER_FONT_SET | + StyleQueryFontMetricsFlags::NEEDS_CH | + StyleQueryFontMetricsFlags::NEEDS_IC); } case Type::Root: return GetFontMetrics(mPresContext->Document()->GetRootElement()); diff --git a/dom/svg/SVGAnimatedLength.cpp b/dom/svg/SVGAnimatedLength.cpp index 5176bc5a1e63..0a570be640c6 100644 --- a/dom/svg/SVGAnimatedLength.cpp +++ b/dom/svg/SVGAnimatedLength.cpp @@ -133,8 +133,9 @@ GeckoFontMetrics UserSpaceMetrics::GetFontMetrics(const Element* aElement) { metrics = Gecko_GetFontMetrics( presContext, WritingMode(style).IsVertical(), style->StyleFont(), style->StyleFont()->mFont.size, - /* aUseUserFontSet = */ true, - /* aRetrieveMathScales */ false); + StyleQueryFontMetricsFlags::USE_USER_FONT_SET | + StyleQueryFontMetricsFlags::NEEDS_CH | + StyleQueryFontMetricsFlags::NEEDS_IC); }); } return metrics; @@ -290,8 +291,9 @@ GeckoFontMetrics NonSVGFrameUserSpaceMetrics::GetFontMetricsForType( return Gecko_GetFontMetrics( mFrame->PresContext(), mFrame->GetWritingMode().IsVertical(), mFrame->StyleFont(), mFrame->StyleFont()->mFont.size, - /* aUseUserFontSet = */ true, - /* aRetrieveMathScales */ false); + StyleQueryFontMetricsFlags::USE_USER_FONT_SET | + StyleQueryFontMetricsFlags::NEEDS_CH | + StyleQueryFontMetricsFlags::NEEDS_IC); case Type::Root: return GetFontMetrics( mFrame->PresContext()->Document()->GetRootElement()); diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp index 3730fca4f922..28d828fc701c 100644 --- a/gfx/thebes/gfxTextRun.cpp +++ b/gfx/thebes/gfxTextRun.cpp @@ -3940,7 +3940,7 @@ already_AddRefed gfxFontGroup::WhichSystemFontSupportsChar( } gfxFont::Metrics gfxFontGroup::GetMetricsForCSSUnits( - gfxFont::Orientation aOrientation) { + gfxFont::Orientation aOrientation, StyleQueryFontMetricsFlags aFlags) { bool isFirst; RefPtr font = GetFirstValidFont(0x20, nullptr, &isFirst); auto metrics = font->GetMetrics(aOrientation); @@ -3948,7 +3948,8 @@ gfxFont::Metrics gfxFontGroup::GetMetricsForCSSUnits( // If the font we used to get metrics was not the first in the list, // or if it doesn't support the ZERO character, check for the font that // does support ZERO and use its metrics for the 'ch' unit. - if (!isFirst || !font->HasCharacter('0')) { + if ((aFlags & StyleQueryFontMetricsFlags::NEEDS_CH) && + (!isFirst || !font->HasCharacter('0'))) { RefPtr zeroFont = GetFirstValidFont('0'); if (zeroFont != font) { const auto& zeroMetrics = zeroFont->GetMetrics(aOrientation); @@ -3957,7 +3958,8 @@ gfxFont::Metrics gfxFontGroup::GetMetricsForCSSUnits( } // Likewise for the WATER ideograph character used as the basis for 'ic'. - if (!isFirst || !font->HasCharacter(0x6C34)) { + if ((aFlags & StyleQueryFontMetricsFlags::NEEDS_IC) && + (!isFirst || !font->HasCharacter(0x6C34))) { RefPtr icFont = GetFirstValidFont(0x6C34); if (icFont != font) { const auto& icMetrics = icFont->GetMetrics(aOrientation); diff --git a/gfx/thebes/gfxTextRun.h b/gfx/thebes/gfxTextRun.h index a527ad3d817a..7fbb5d8e7f67 100644 --- a/gfx/thebes/gfxTextRun.h +++ b/gfx/thebes/gfxTextRun.h @@ -1072,7 +1072,11 @@ class gfxFontGroup final : public gfxTextRunFactory { // to render specific characters, not simply the "first available" font. // https://drafts.csswg.org/css-values-4/#ch // https://drafts.csswg.org/css-values-4/#ic - gfxFont::Metrics GetMetricsForCSSUnits(gfxFont::Orientation aOrientation); + // Whether extra font resources may be loaded to resolve 'ch' and 'ic' + // depends on the corresponding flags passed by the caller. + gfxFont::Metrics GetMetricsForCSSUnits( + gfxFont::Orientation aOrientation, + mozilla::StyleQueryFontMetricsFlags aFlags); protected: friend class mozilla::PostTraversalTask; diff --git a/layout/style/GeckoBindings.cpp b/layout/style/GeckoBindings.cpp index 6a74c9fde3a0..53f26981b2c3 100644 --- a/layout/style/GeckoBindings.cpp +++ b/layout/style/GeckoBindings.cpp @@ -1285,8 +1285,8 @@ void AssertIsMainThreadOrServoFontMetricsLocked() { GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext* aPresContext, bool aIsVertical, const nsStyleFont* aFont, - Length aFontSize, bool aUseUserFontSet, - bool aRetrieveMathScales) { + Length aFontSize, + StyleQueryFontMetricsFlags flags) { AutoWriteLock guard(*sServoFFILock); // Getting font metrics can require some main thread only work to be @@ -1302,13 +1302,14 @@ GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext* aPresContext, nsPresContext* presContext = const_cast(aPresContext); RefPtr fm = nsLayoutUtils::GetMetricsFor( - presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet); + presContext, aIsVertical, aFont, aFontSize, + bool(flags & StyleQueryFontMetricsFlags::USE_USER_FONT_SET)); auto* fontGroup = fm->GetThebesFontGroup(); - auto metrics = fontGroup->GetMetricsForCSSUnits(fm->Orientation()); + auto metrics = fontGroup->GetMetricsForCSSUnits(fm->Orientation(), flags); float scriptPercentScaleDown = 0; float scriptScriptPercentScaleDown = 0; - if (aRetrieveMathScales) { + if (flags & StyleQueryFontMetricsFlags::NEEDS_MATH_SCALES) { RefPtr font = fontGroup->GetFirstValidFont(); if (font->TryGetMathTable()) { scriptPercentScaleDown = static_cast( diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h index c7cf59c2661c..ba4b3b641656 100644 --- a/layout/style/GeckoBindings.h +++ b/layout/style/GeckoBindings.h @@ -472,11 +472,9 @@ struct GeckoFontMetrics { float mScriptScriptPercentScaleDown; // zero is invalid or means not found. }; -GeckoFontMetrics Gecko_GetFontMetrics(const nsPresContext*, bool is_vertical, - const nsStyleFont* font, - mozilla::Length font_size, - bool use_user_font_set, - bool retrieve_math_scales); +GeckoFontMetrics Gecko_GetFontMetrics( + const nsPresContext*, bool is_vertical, const nsStyleFont* font, + mozilla::Length font_size, mozilla::StyleQueryFontMetricsFlags flags); mozilla::StyleSheet* Gecko_StyleSheet_Clone(const mozilla::StyleSheet* aSheet); diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index 0ae7445cfd44..ae62e3423cdf 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -634,7 +634,8 @@ cbindgen-types = [ { gecko = "StyleInert", servo = "crate::values::computed::ui::Inert" }, { gecko = "StyleMargin", servo = "crate::values::computed::length::Margin" }, { gecko = "StyleGenericAnchorFunction", servo = "crate::values::generics::position::GenericAnchorFunction" }, - { gecko = "StylePositionProperty", servo = "crate::values::computed::PositionProperty"}, + { gecko = "StylePositionProperty", servo = "crate::values::computed::PositionProperty" }, + { gecko = "StyleQueryFontMetricsFlags", servo = "crate::gecko::media_queries::QueryFontMetricsFlags" }, ] mapped-generic-types = [ diff --git a/servo/components/style/gecko/media_queries.rs b/servo/components/style/gecko/media_queries.rs index 59d5b1489413..645a54d55dab 100644 --- a/servo/components/style/gecko/media_queries.rs +++ b/servo/components/style/gecko/media_queries.rs @@ -29,6 +29,23 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}; use std::{cmp, fmt}; use style_traits::{CSSPixel, DevicePixel}; +/// Flags for the query_font_metrics() function. +#[repr(C)] +pub struct QueryFontMetricsFlags(u8); + +bitflags! { + impl QueryFontMetricsFlags: u8 { + /// Should we use the user font set? + const USE_USER_FONT_SET = 1 << 0; + /// Does the caller need the `ch` unit (width of the ZERO glyph)? + const NEEDS_CH = 1 << 1; + /// Does the caller need the `ic` unit (width of the WATER ideograph)? + const NEEDS_IC = 1 << 2; + /// Does the caller need math scales to be retrieved? + const NEEDS_MATH_SCALES = 1 << 3; + } +} + /// The `Device` in Gecko wraps a pres context, has a default values computed, /// and contains all the viewport rule state. pub struct Device { @@ -227,8 +244,7 @@ impl Device { vertical: bool, font: &crate::properties::style_structs::Font, base_size: Length, - in_media_query: bool, - retrieve_math_scales: bool, + flags: QueryFontMetricsFlags, ) -> FontMetrics { self.used_font_metrics.store(true, Ordering::Relaxed); let pc = match self.pres_context() { @@ -241,9 +257,7 @@ impl Device { vertical, &**font, base_size, - // we don't use the user font set in a media query - !in_media_query, - retrieve_math_scales, + flags, ) }; FontMetrics { diff --git a/servo/components/style/properties/cascade.rs b/servo/components/style/properties/cascade.rs index a2a957902940..2365a72aaf54 100644 --- a/servo/components/style/properties/cascade.rs +++ b/servo/components/style/properties/cascade.rs @@ -1355,6 +1355,8 @@ impl<'b> Cascade<'b> { } let (new_size, new_unconstrained_size) = { + use crate::gecko::media_queries::QueryFontMetricsFlags; + let builder = &context.builder; let font = builder.get_font(); let parent_font = builder.get_parent_font(); @@ -1376,7 +1378,7 @@ impl<'b> Cascade<'b> { let font_metrics = context.query_font_metrics( FontBaseSize::InheritedStyle, FontMetricsOrientation::Horizontal, - /* retrieve_math_scales = */ true, + QueryFontMetricsFlags::NEEDS_MATH_SCALES, ); scale_factor_for_math_depth_change( parent_font.mMathDepth as i32, diff --git a/servo/components/style/values/computed/font.rs b/servo/components/style/values/computed/font.rs index d5dc33705083..3ce5235e3add 100644 --- a/servo/components/style/values/computed/font.rs +++ b/servo/components/style/values/computed/font.rs @@ -4,6 +4,7 @@ //! Computed values for font properties +use crate::gecko::media_queries::QueryFontMetricsFlags; use crate::parser::{Parse, ParserContext}; use crate::values::animated::ToAnimatedValue; use crate::values::computed::{ @@ -802,13 +803,13 @@ impl ToComputedValue for specified::FontSizeAdjust { fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { use crate::font_metrics::FontMetricsOrientation; - let font_metrics = |vertical| { + let font_metrics = |vertical, flags| { let orient = if vertical { FontMetricsOrientation::MatchContextPreferVertical } else { FontMetricsOrientation::Horizontal }; - let metrics = context.query_font_metrics(FontBaseSize::CurrentStyle, orient, false); + let metrics = context.query_font_metrics(FontBaseSize::CurrentStyle, orient, flags); let font_size = context.style().get_font().clone_font_size().used_size.0; (metrics, font_size) }; @@ -817,13 +818,13 @@ impl ToComputedValue for specified::FontSizeAdjust { // returns the fallback value, or if that is negative, resolves using ascent instead // of the missing field (this is the fallback for cap-height). macro_rules! resolve { - ($basis:ident, $value:expr, $vertical:expr, $field:ident, $fallback:expr) => {{ + ($basis:ident, $value:expr, $vertical:expr, $field:ident, $fallback:expr, $flags:expr) => {{ match $value { specified::FontSizeAdjustFactor::Number(f) => { FontSizeAdjust::$basis(f.to_computed_value(context)) }, specified::FontSizeAdjustFactor::FromFont => { - let (metrics, font_size) = font_metrics($vertical); + let (metrics, font_size) = font_metrics($vertical, $flags); let ratio = if let Some(metric) = metrics.$field { metric / font_size } else if $fallback >= 0.0 { @@ -843,13 +844,21 @@ impl ToComputedValue for specified::FontSizeAdjust { match *self { Self::None => FontSizeAdjust::None, - Self::ExHeight(val) => resolve!(ExHeight, val, false, x_height, 0.5), - Self::CapHeight(val) => { - resolve!(CapHeight, val, false, cap_height, -1.0 /* fall back to ascent */) + Self::ExHeight(val) => { + resolve!(ExHeight, val, false, x_height, 0.5, QueryFontMetricsFlags::empty()) + }, + Self::CapHeight(val) => { + resolve!(CapHeight, val, false, cap_height, -1.0 /* fall back to ascent */, QueryFontMetricsFlags::empty()) + }, + Self::ChWidth(val) => { + resolve!(ChWidth, val, false, zero_advance_measure, 0.5, QueryFontMetricsFlags::NEEDS_CH) + }, + Self::IcWidth(val) => { + resolve!(IcWidth, val, false, ic_width, 1.0, QueryFontMetricsFlags::NEEDS_IC) + }, + Self::IcHeight(val) => { + resolve!(IcHeight, val, true, ic_width, 1.0, QueryFontMetricsFlags::NEEDS_IC) }, - Self::ChWidth(val) => resolve!(ChWidth, val, false, zero_advance_measure, 0.5), - Self::IcWidth(val) => resolve!(IcWidth, val, false, ic_width, 1.0), - Self::IcHeight(val) => resolve!(IcHeight, val, true, ic_width, 1.0), } } diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs index 9caa30037f08..028d89da0a7e 100644 --- a/servo/components/style/values/computed/mod.rs +++ b/servo/components/style/values/computed/mod.rs @@ -18,6 +18,7 @@ use crate::computed_value_flags::ComputedValueFlags; use crate::context::QuirksMode; use crate::custom_properties::ComputedCustomProperties; use crate::font_metrics::{FontMetrics, FontMetricsOrientation}; +use crate::gecko::media_queries::QueryFontMetricsFlags; use crate::media_queries::Device; #[cfg(feature = "gecko")] use crate::properties; @@ -363,7 +364,7 @@ impl<'a> Context<'a> { &self, base_size: FontBaseSize, orientation: FontMetricsOrientation, - retrieve_math_scales: bool, + mut flags: QueryFontMetricsFlags, ) -> FontMetrics { if self.for_non_inherited_property { self.rule_cache_conditions.borrow_mut().set_uncacheable(); @@ -390,12 +391,14 @@ impl<'a> Context<'a> { FontMetricsOrientation::MatchContextPreferVertical => wm.is_text_vertical(), FontMetricsOrientation::Horizontal => false, }; + if !self.in_media_or_container_query() { + flags |= QueryFontMetricsFlags::USE_USER_FONT_SET + } self.device().query_font_metrics( vertical, font, size, - self.in_media_or_container_query(), - retrieve_math_scales, + flags, ) } diff --git a/servo/components/style/values/specified/length.rs b/servo/components/style/values/specified/length.rs index cc11be9cc0f2..031e72ef4b77 100644 --- a/servo/components/style/values/specified/length.rs +++ b/servo/components/style/values/specified/length.rs @@ -9,6 +9,7 @@ use super::{AllowQuirks, Number, Percentage, ToComputedValue}; use crate::computed_value_flags::ComputedValueFlags; use crate::font_metrics::{FontMetrics, FontMetricsOrientation}; +use crate::gecko::media_queries::QueryFontMetricsFlags; #[cfg(feature = "gecko")] use crate::gecko_bindings::structs::GeckoFontMetrics; use crate::parser::{Parse, ParserContext}; @@ -249,9 +250,13 @@ impl FontRelativeLength { context: &Context, base_size: FontBaseSize, orientation: FontMetricsOrientation, + flags: QueryFontMetricsFlags, ) -> FontMetrics { - let retrieve_math_scales = false; - context.query_font_metrics(base_size, orientation, retrieve_math_scales) + context.query_font_metrics( + base_size, + orientation, + flags, + ) } let reference_font_size = base_size.resolve(context); @@ -268,8 +273,12 @@ impl FontRelativeLength { }, Self::Ex(length) => { // The x-height is an intrinsically horizontal metric. - let metrics = - query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal); + let metrics = query_font_metrics( + context, + base_size, + FontMetricsOrientation::Horizontal, + QueryFontMetricsFlags::empty(), + ); let reference_size = metrics.x_height.unwrap_or_else(|| { // https://drafts.csswg.org/css-values/#ex // @@ -295,6 +304,7 @@ impl FontRelativeLength { context, base_size, FontMetricsOrientation::MatchContextPreferHorizontal, + QueryFontMetricsFlags::NEEDS_CH, ); let reference_size = metrics.zero_advance_measure.unwrap_or_else(|| { // https://drafts.csswg.org/css-values/#ch @@ -319,8 +329,12 @@ impl FontRelativeLength { (reference_size, length) }, Self::Cap(length) => { - let metrics = - query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal); + let metrics = query_font_metrics( + context, + base_size, + FontMetricsOrientation::Horizontal, + QueryFontMetricsFlags::empty(), + ); let reference_size = metrics.cap_height.unwrap_or_else(|| { // https://drafts.csswg.org/css-values/#cap // @@ -337,6 +351,7 @@ impl FontRelativeLength { context, base_size, FontMetricsOrientation::MatchContextPreferVertical, + QueryFontMetricsFlags::NEEDS_IC, ); let reference_size = metrics.ic_width.unwrap_or_else(|| { // https://drafts.csswg.org/css-values/#ic diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml index 724d34e8c5ce..4ff50908d4b5 100644 --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml @@ -331,6 +331,7 @@ include = [ "Margin", "PositionProperty", "PhysicalAxis", + "QueryFontMetricsFlags", ] item_types = [ "enums",