style: Allow FontMetricsProvider to produce ex height and zero width independently.

We are always able to produce an x height, but depending on whether the
glyph exists, we sometimes can't produce a zero glyph width.

Differential Revision: https://phabricator.services.mozilla.com/D23424
This commit is contained in:
Cameron McCormack 2019-03-21 04:50:43 +00:00 committed by Emilio Cobos Álvarez
parent 39df092bce
commit d5f208e18c
3 changed files with 29 additions and 38 deletions

View file

@ -12,22 +12,12 @@ use app_units::Au;
/// Represents the font metrics that style needs from a font to compute the /// Represents the font metrics that style needs from a font to compute the
/// value of certain CSS units like `ex`. /// value of certain CSS units like `ex`.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, Default, PartialEq)]
pub struct FontMetrics { pub struct FontMetrics {
/// The x-height of the font. /// The x-height of the font.
pub x_height: Au, pub x_height: Option<Au>,
/// The zero advance. This is usually writing mode dependent /// The zero advance. This is usually writing mode dependent
pub zero_advance_measure: Au, pub zero_advance_measure: Option<Au>,
}
/// The result for querying font metrics for a given font family.
#[derive(Clone, Debug, PartialEq)]
pub enum FontMetricsQueryResult {
/// The font is available, but we may or may not have found any font metrics
/// for it.
Available(FontMetrics),
/// The font is not available.
NotAvailable,
} }
/// A trait used to represent something capable of providing us font metrics. /// A trait used to represent something capable of providing us font metrics.
@ -38,7 +28,7 @@ pub trait FontMetricsProvider {
_context: &crate::values::computed::Context, _context: &crate::values::computed::Context,
_base_size: crate::values::specified::length::FontBaseSize, _base_size: crate::values::specified::length::FontBaseSize,
) -> FontMetricsQueryResult { ) -> FontMetricsQueryResult {
FontMetricsQueryResult::NotAvailable Default::default()
} }
/// Get default size of a given language and generic family. /// Get default size of a given language and generic family.

View file

@ -20,7 +20,7 @@ use crate::context::{PostAnimationTasks, QuirksMode, SharedStyleContext, UpdateA
use crate::data::ElementData; use crate::data::ElementData;
use crate::dom::{LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNode, TShadowRoot}; use crate::dom::{LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNode, TShadowRoot};
use crate::element_state::{DocumentState, ElementState}; use crate::element_state::{DocumentState, ElementState};
use crate::font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult}; use crate::font_metrics::{FontMetrics, FontMetricsProvider};
use crate::gecko::data::GeckoStyleSheet; use crate::gecko::data::GeckoStyleSheet;
use crate::gecko::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl}; use crate::gecko::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl};
use crate::gecko::snapshot_helpers; use crate::gecko::snapshot_helpers;
@ -1035,10 +1035,10 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
&self, &self,
context: &crate::values::computed::Context, context: &crate::values::computed::Context,
base_size: FontBaseSize, base_size: FontBaseSize,
) -> FontMetricsQueryResult { ) -> FontMetrics {
let pc = match context.device().pres_context() { let pc = match context.device().pres_context() {
Some(pc) => pc, Some(pc) => pc,
None => return FontMetricsQueryResult::NotAvailable, None => return Default::default(),
}; };
let size = base_size.resolve(context); let size = base_size.resolve(context);
@ -1066,11 +1066,14 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
!context.in_media_query, !context.in_media_query,
) )
}; };
let metrics = FontMetrics { FontMetrics {
x_height: Au(gecko_metrics.mXSize), x_height: Some(Au(gecko_metrics.mXSize)),
zero_advance_measure: Au(gecko_metrics.mChSize), zero_advance_measure: if gecko_metrics.mChSize >= 0 {
}; Some(Au(gecko_metrics.mChSize))
FontMetricsQueryResult::Available(metrics) } else {
None
},
}
} }
} }

View file

@ -7,7 +7,7 @@
//! [length]: https://drafts.csswg.org/css-values/#lengths //! [length]: https://drafts.csswg.org/css-values/#lengths
use super::{AllowQuirks, Number, Percentage, ToComputedValue}; use super::{AllowQuirks, Number, Percentage, ToComputedValue};
use crate::font_metrics::FontMetricsQueryResult; use crate::font_metrics::FontMetrics;
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::properties::computed_value_flags::ComputedValueFlags; use crate::properties::computed_value_flags::ComputedValueFlags;
use crate::values::computed::{self, CSSPixelLength, Context}; use crate::values::computed::{self, CSSPixelLength, Context};
@ -133,7 +133,7 @@ impl FontRelativeLength {
fn query_font_metrics( fn query_font_metrics(
context: &Context, context: &Context,
base_size: FontBaseSize, base_size: FontBaseSize,
) -> FontMetricsQueryResult { ) -> FontMetrics {
context.font_metrics_provider.query(context, base_size) context.font_metrics_provider.query(context, base_size)
} }
@ -160,16 +160,16 @@ impl FontRelativeLength {
context.rule_cache_conditions.borrow_mut().set_uncacheable(); context.rule_cache_conditions.borrow_mut().set_uncacheable();
} }
context.builder.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS); context.builder.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS);
let reference_size = match query_font_metrics(context, base_size) { let metrics = query_font_metrics(context, base_size);
FontMetricsQueryResult::Available(metrics) => metrics.x_height, let reference_size = metrics.x_height.unwrap_or_else(|| {
// https://drafts.csswg.org/css-values/#ex // https://drafts.csswg.org/css-values/#ex
// //
// In the cases where it is impossible or impractical to // In the cases where it is impossible or impractical to
// determine the x-height, a value of 0.5em must be // determine the x-height, a value of 0.5em must be
// assumed. // assumed.
// //
FontMetricsQueryResult::NotAvailable => reference_font_size.scale_by(0.5), reference_font_size.scale_by(0.5)
}; });
(reference_size, length) (reference_size, length)
}, },
FontRelativeLength::Ch(length) => { FontRelativeLength::Ch(length) => {
@ -177,8 +177,8 @@ impl FontRelativeLength {
context.rule_cache_conditions.borrow_mut().set_uncacheable(); context.rule_cache_conditions.borrow_mut().set_uncacheable();
} }
context.builder.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS); context.builder.add_flags(ComputedValueFlags::DEPENDS_ON_FONT_METRICS);
let reference_size = match query_font_metrics(context, base_size) { let metrics = query_font_metrics(context, base_size);
FontMetricsQueryResult::Available(metrics) => metrics.zero_advance_measure, let reference_size = metrics.zero_advance_measure.unwrap_or_else(|| {
// https://drafts.csswg.org/css-values/#ch // https://drafts.csswg.org/css-values/#ch
// //
// In the cases where it is impossible or impractical to // In the cases where it is impossible or impractical to
@ -189,14 +189,12 @@ impl FontRelativeLength {
// writing-mode is vertical-rl or vertical-lr and // writing-mode is vertical-rl or vertical-lr and
// text-orientation is upright). // text-orientation is upright).
// //
FontMetricsQueryResult::NotAvailable => { if context.style().writing_mode.is_vertical() {
if context.style().writing_mode.is_vertical() { reference_font_size
reference_font_size } else {
} else { reference_font_size.scale_by(0.5)
reference_font_size.scale_by(0.5) }
} });
},
};
(reference_size, length) (reference_size, length)
}, },
FontRelativeLength::Rem(length) => { FontRelativeLength::Rem(length) => {