Bug 1962602 - Give gfxFontGroup::GetMetricsForCSSUnits flags to control whether it should load extra font resources to measure the ZERO or WATER IDEOGRAPH characters. r=firefox-style-system-reviewers,emilio

This makes the style system pass flags down to GetMetricsForCSSUnits to specify
whether it needs the 'ch' or 'ic' units, which may trigger downloading additional
font resources.

There should be no change in user-visible behavior, except by observing (e.g. in
the devtools network panel) what resources end up being fetched in an example
like the reporter's.

Differential Revision: https://phabricator.services.mozilla.com/D246780
This commit is contained in:
Jonathan Kew
2025-04-26 16:22:46 +00:00
parent 3a5538d573
commit c68d97e633
13 changed files with 102 additions and 47 deletions

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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),
}
}

View File

@@ -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,
)
}

View File

@@ -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