style: Make all font-metrics-affecting properties cascade early.

And make font-size computation work on the whole font of the parent, not just
accounting for the parent's font-size.

Differential Revision: https://phabricator.services.mozilla.com/D20656
This commit is contained in:
Emilio Cobos Álvarez 2019-03-18 16:27:54 +00:00
parent aa5ea337da
commit d3f254d2e4
4 changed files with 36 additions and 38 deletions

View file

@ -7,9 +7,6 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use crate::context::SharedStyleContext; use crate::context::SharedStyleContext;
use crate::logical_geometry::WritingMode;
use crate::media_queries::Device;
use crate::properties::style_structs::Font;
use crate::Atom; use crate::Atom;
use app_units::Au; use app_units::Au;
@ -36,22 +33,15 @@ pub enum FontMetricsQueryResult {
/// A trait used to represent something capable of providing us font metrics. /// A trait used to represent something capable of providing us font metrics.
pub trait FontMetricsProvider { pub trait FontMetricsProvider {
/// Obtain the metrics for given font family. /// Obtain the metrics for given font family.
///
/// TODO: We could make this take the full list, I guess, and save a few
/// virtual calls in the case we are repeatedly unable to find font metrics?
/// That is not too common in practice though.
fn query( fn query(
&self, &self,
_font: &Font, _context: &crate::values::computed::Context,
_font_size: Au, _base_size: crate::values::specified::length::FontBaseSize,
_wm: WritingMode,
_in_media_query: bool,
_device: &Device,
) -> FontMetricsQueryResult { ) -> FontMetricsQueryResult {
FontMetricsQueryResult::NotAvailable FontMetricsQueryResult::NotAvailable
} }
/// Get default size of a given language and generic family /// Get default size of a given language and generic family.
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au; fn get_size(&self, font_name: &Atom, font_family: u8) -> Au;
/// Construct from a shared style context /// Construct from a shared style context

View file

@ -58,10 +58,8 @@ use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
use crate::global_style_data::GLOBAL_STYLE_DATA; use crate::global_style_data::GLOBAL_STYLE_DATA;
use crate::hash::FxHashMap; use crate::hash::FxHashMap;
use crate::invalidation::element::restyle_hints::RestyleHint; use crate::invalidation::element::restyle_hints::RestyleHint;
use crate::logical_geometry::WritingMode;
use crate::media_queries::Device; use crate::media_queries::Device;
use crate::properties::animated_properties::{AnimationValue, AnimationValueMap}; use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
use crate::properties::style_structs::Font;
use crate::properties::{ComputedValues, LonghandId}; use crate::properties::{ComputedValues, LonghandId};
use crate::properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; use crate::properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use crate::rule_tree::CascadeLevel as ServoCascadeLevel; use crate::rule_tree::CascadeLevel as ServoCascadeLevel;
@ -69,6 +67,7 @@ use crate::selector_parser::{AttrValue, HorizontalDirection, Lang};
use crate::shared_lock::Locked; use crate::shared_lock::Locked;
use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use crate::stylist::CascadeData; use crate::stylist::CascadeData;
use crate::values::specified::length::FontBaseSize;
use crate::CaseSensitivityExt; use crate::CaseSensitivityExt;
use app_units::Au; use app_units::Au;
use atomic_refcell::{AtomicRefCell, AtomicRefMut}; use atomic_refcell::{AtomicRefCell, AtomicRefMut};
@ -1023,37 +1022,48 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
} }
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au { fn get_size(&self, font_name: &Atom, font_family: u8) -> Au {
use crate::gecko_bindings::bindings::Gecko_GetBaseSize;
let mut cache = self.font_size_cache.borrow_mut(); let mut cache = self.font_size_cache.borrow_mut();
if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) { if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
return sizes.1.size_for_generic(font_family); return sizes.1.size_for_generic(font_family);
} }
let sizes = unsafe { Gecko_GetBaseSize(font_name.as_ptr()) }; let sizes = unsafe { bindings::Gecko_GetBaseSize(font_name.as_ptr()) };
cache.push((font_name.clone(), sizes)); cache.push((font_name.clone(), sizes));
sizes.size_for_generic(font_family) sizes.size_for_generic(font_family)
} }
fn query( fn query(
&self, &self,
font: &Font, context: &crate::values::computed::Context,
font_size: Au, base_size: FontBaseSize,
wm: WritingMode,
in_media_query: bool,
device: &Device,
) -> FontMetricsQueryResult { ) -> FontMetricsQueryResult {
use crate::gecko_bindings::bindings::Gecko_GetFontMetrics; let pc = match context.device().pres_context() {
let pc = match device.pres_context() {
Some(pc) => pc, Some(pc) => pc,
None => return FontMetricsQueryResult::NotAvailable, None => return FontMetricsQueryResult::NotAvailable,
}; };
let size = base_size.resolve(context);
let style = context.style();
let (wm, font) = match base_size {
FontBaseSize::CurrentStyle => {
(style.writing_mode, style.get_font())
},
// These are only used for font-size computation, and the first is
// really dubious...
FontBaseSize::InheritedStyleButStripEmUnits |
FontBaseSize::InheritedStyle => {
(*style.inherited_writing_mode(), style.get_parent_font())
},
};
let gecko_metrics = unsafe { let gecko_metrics = unsafe {
Gecko_GetFontMetrics( bindings::Gecko_GetFontMetrics(
pc, pc,
wm.is_vertical() && !wm.is_sideways(), wm.is_vertical() && !wm.is_sideways(),
font.gecko(), font.gecko(),
font_size.0, size.0,
// we don't use the user font set in a media query // we don't use the user font set in a media query
!in_media_query, !context.in_media_query,
) )
}; };
let metrics = FontMetrics { let metrics = FontMetrics {

View file

@ -1257,8 +1257,12 @@ impl LonghandId {
LonghandId::MozScriptLevel | LonghandId::MozScriptLevel |
% endif % endif
// Needed to compute font-relative lengths correctly. // Needed to compute the first available font, in order to
// compute font-relative units correctly.
LonghandId::FontSize | LonghandId::FontSize |
LonghandId::FontWeight |
LonghandId::FontStretch |
LonghandId::FontStyle |
LonghandId::FontFamily | LonghandId::FontFamily |
// Needed to resolve currentcolor at computed value time properly. // Needed to resolve currentcolor at computed value time properly.

View file

@ -131,15 +131,9 @@ impl FontRelativeLength {
) -> (Au, CSSFloat) { ) -> (Au, CSSFloat) {
fn query_font_metrics( fn query_font_metrics(
context: &Context, context: &Context,
reference_font_size: Au, base_size: FontBaseSize,
) -> FontMetricsQueryResult { ) -> FontMetricsQueryResult {
context.font_metrics_provider.query( context.font_metrics_provider.query(context, base_size)
context.style().get_font(),
reference_font_size,
context.style().writing_mode,
context.in_media_query,
context.device(),
)
} }
let reference_font_size = base_size.resolve(context); let reference_font_size = base_size.resolve(context);
@ -164,7 +158,7 @@ impl FontRelativeLength {
if context.for_non_inherited_property.is_some() { if context.for_non_inherited_property.is_some() {
context.rule_cache_conditions.borrow_mut().set_uncacheable(); context.rule_cache_conditions.borrow_mut().set_uncacheable();
} }
let reference_size = match query_font_metrics(context, reference_font_size) { let reference_size = match query_font_metrics(context, base_size) {
FontMetricsQueryResult::Available(metrics) => metrics.x_height, FontMetricsQueryResult::Available(metrics) => metrics.x_height,
// https://drafts.csswg.org/css-values/#ex // https://drafts.csswg.org/css-values/#ex
// //
@ -180,7 +174,7 @@ impl FontRelativeLength {
if context.for_non_inherited_property.is_some() { if context.for_non_inherited_property.is_some() {
context.rule_cache_conditions.borrow_mut().set_uncacheable(); context.rule_cache_conditions.borrow_mut().set_uncacheable();
} }
let reference_size = match query_font_metrics(context, reference_font_size) { let reference_size = match query_font_metrics(context, base_size) {
FontMetricsQueryResult::Available(metrics) => metrics.zero_advance_measure, FontMetricsQueryResult::Available(metrics) => metrics.zero_advance_measure,
// https://drafts.csswg.org/css-values/#ch // https://drafts.csswg.org/css-values/#ch
// //