mirror of
https://github.com/servo/servo.git
synced 2025-10-04 18:49:23 +01:00
Auto merge of #16316 - Manishearth:stylo-threadsafe, r=emilio
stylo: Make font base size computation threadsafe r=emilio https://bugzilla.mozilla.org/show_bug.cgi?id=1351200 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16316) <!-- Reviewable:end -->
This commit is contained in:
commit
d77d752990
25 changed files with 339 additions and 46 deletions
|
@ -13,6 +13,7 @@ use script_traits::{AnimationState, ConstellationControlMsg, LayoutMsg as Conste
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use style::animation::{Animation, update_style_for_animation};
|
use style::animation::{Animation, update_style_for_animation};
|
||||||
|
use style::font_metrics::ServoMetricsProvider;
|
||||||
use style::selector_parser::RestyleDamage;
|
use style::selector_parser::RestyleDamage;
|
||||||
use style::timer::Timer;
|
use style::timer::Timer;
|
||||||
|
|
||||||
|
@ -143,7 +144,8 @@ pub fn recalc_style_for_animations(context: &LayoutContext,
|
||||||
let old_style = fragment.style.clone();
|
let old_style = fragment.style.clone();
|
||||||
update_style_for_animation(&context.style_context,
|
update_style_for_animation(&context.style_context,
|
||||||
animation,
|
animation,
|
||||||
&mut fragment.style);
|
&mut fragment.style,
|
||||||
|
&ServoMetricsProvider);
|
||||||
damage |= RestyleDamage::compute(&old_style, &fragment.style);
|
damage |= RestyleDamage::compute(&old_style, &fragment.style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ impl<'a> RecalcStyleAndConstructFlows<'a> {
|
||||||
impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a>
|
impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a>
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
E::ConcreteNode: LayoutNode,
|
E::ConcreteNode: LayoutNode,
|
||||||
|
E::FontMetricsProvider: Send,
|
||||||
{
|
{
|
||||||
type ThreadLocalContext = ScopedThreadLocalLayoutContext<E>;
|
type ThreadLocalContext = ScopedThreadLocalLayoutContext<E>;
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ use style::data::ElementData;
|
||||||
use style::dom::{DescendantsBit, DirtyDescendants, LayoutIterator, NodeInfo, OpaqueNode};
|
use style::dom::{DescendantsBit, DirtyDescendants, LayoutIterator, NodeInfo, OpaqueNode};
|
||||||
use style::dom::{PresentationalHintsSynthetizer, TElement, TNode, UnsafeNode};
|
use style::dom::{PresentationalHintsSynthetizer, TElement, TNode, UnsafeNode};
|
||||||
use style::element_state::*;
|
use style::element_state::*;
|
||||||
|
use style::font_metrics::ServoMetricsProvider;
|
||||||
use style::properties::{ComputedValues, PropertyDeclarationBlock};
|
use style::properties::{ComputedValues, PropertyDeclarationBlock};
|
||||||
use style::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl};
|
use style::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl};
|
||||||
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked};
|
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked};
|
||||||
|
@ -373,6 +374,8 @@ impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> {
|
||||||
impl<'le> TElement for ServoLayoutElement<'le> {
|
impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
type ConcreteNode = ServoLayoutNode<'le>;
|
type ConcreteNode = ServoLayoutNode<'le>;
|
||||||
|
|
||||||
|
type FontMetricsProvider = ServoMetricsProvider;
|
||||||
|
|
||||||
fn as_node(&self) -> ServoLayoutNode<'le> {
|
fn as_node(&self) -> ServoLayoutNode<'le> {
|
||||||
ServoLayoutNode::from_layout_js(self.element.upcast())
|
ServoLayoutNode::from_layout_js(self.element.upcast())
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use style::context::SharedStyleContext;
|
||||||
use style::data::ElementData;
|
use style::data::ElementData;
|
||||||
use style::dom::{LayoutIterator, NodeInfo, PresentationalHintsSynthetizer, TNode};
|
use style::dom::{LayoutIterator, NodeInfo, PresentationalHintsSynthetizer, TNode};
|
||||||
use style::dom::OpaqueNode;
|
use style::dom::OpaqueNode;
|
||||||
|
use style::font_metrics::ServoMetricsProvider;
|
||||||
use style::properties::{CascadeFlags, ServoComputedValues};
|
use style::properties::{CascadeFlags, ServoComputedValues};
|
||||||
use style::selector_parser::{PseudoElement, PseudoElementCascadeType, SelectorImpl};
|
use style::selector_parser::{PseudoElement, PseudoElementCascadeType, SelectorImpl};
|
||||||
|
|
||||||
|
@ -411,7 +412,8 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
|
||||||
&context.guards,
|
&context.guards,
|
||||||
&style_pseudo,
|
&style_pseudo,
|
||||||
Some(data.styles().primary.values()),
|
Some(data.styles().primary.values()),
|
||||||
CascadeFlags::empty());
|
CascadeFlags::empty(),
|
||||||
|
&ServoMetricsProvider);
|
||||||
data.styles_mut().cached_pseudos
|
data.styles_mut().cached_pseudos
|
||||||
.insert(style_pseudo.clone(), new_style);
|
.insert(style_pseudo.clone(), new_style);
|
||||||
}
|
}
|
||||||
|
@ -426,7 +428,8 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
|
||||||
&context.guards,
|
&context.guards,
|
||||||
unsafe { &self.unsafe_get() },
|
unsafe { &self.unsafe_get() },
|
||||||
&style_pseudo,
|
&style_pseudo,
|
||||||
data.styles().primary.values());
|
data.styles().primary.values(),
|
||||||
|
&ServoMetricsProvider);
|
||||||
data.styles_mut().cached_pseudos
|
data.styles_mut().cached_pseudos
|
||||||
.insert(style_pseudo.clone(), new_style.unwrap());
|
.insert(style_pseudo.clone(), new_style.unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use bezier::Bezier;
|
||||||
use context::SharedStyleContext;
|
use context::SharedStyleContext;
|
||||||
use dom::{OpaqueNode, UnsafeNode};
|
use dom::{OpaqueNode, UnsafeNode};
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
use keyframes::{KeyframesStep, KeyframesStepValue};
|
use keyframes::{KeyframesStep, KeyframesStepValue};
|
||||||
use properties::{self, CascadeFlags, ComputedValues, Importance};
|
use properties::{self, CascadeFlags, ComputedValues, Importance};
|
||||||
use properties::animated_properties::{AnimatedProperty, TransitionProperty};
|
use properties::animated_properties::{AnimatedProperty, TransitionProperty};
|
||||||
|
@ -410,7 +411,8 @@ pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>
|
||||||
fn compute_style_for_animation_step(context: &SharedStyleContext,
|
fn compute_style_for_animation_step(context: &SharedStyleContext,
|
||||||
step: &KeyframesStep,
|
step: &KeyframesStep,
|
||||||
previous_style: &ComputedValues,
|
previous_style: &ComputedValues,
|
||||||
style_from_cascade: &ComputedValues)
|
style_from_cascade: &ComputedValues,
|
||||||
|
font_metrics_provider: &FontMetricsProvider)
|
||||||
-> ComputedValues {
|
-> ComputedValues {
|
||||||
match step.value {
|
match step.value {
|
||||||
KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
|
KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
|
||||||
|
@ -433,7 +435,7 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
|
||||||
previous_style,
|
previous_style,
|
||||||
/* cascade_info = */ None,
|
/* cascade_info = */ None,
|
||||||
&*context.error_reporter,
|
&*context.error_reporter,
|
||||||
/* Metrics provider */ None,
|
font_metrics_provider,
|
||||||
CascadeFlags::empty());
|
CascadeFlags::empty());
|
||||||
computed
|
computed
|
||||||
}
|
}
|
||||||
|
@ -534,7 +536,8 @@ pub fn update_style_for_animation_frame(mut new_style: &mut Arc<ComputedValues>,
|
||||||
/// If `damage` is provided, inserts the appropriate restyle damage.
|
/// If `damage` is provided, inserts the appropriate restyle damage.
|
||||||
pub fn update_style_for_animation(context: &SharedStyleContext,
|
pub fn update_style_for_animation(context: &SharedStyleContext,
|
||||||
animation: &Animation,
|
animation: &Animation,
|
||||||
style: &mut Arc<ComputedValues>) {
|
style: &mut Arc<ComputedValues>,
|
||||||
|
font_metrics_provider: &FontMetricsProvider) {
|
||||||
debug!("update_style_for_animation: entering");
|
debug!("update_style_for_animation: entering");
|
||||||
debug_assert!(!animation.is_expired());
|
debug_assert!(!animation.is_expired());
|
||||||
|
|
||||||
|
@ -658,7 +661,8 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
|
||||||
let from_style = compute_style_for_animation_step(context,
|
let from_style = compute_style_for_animation_step(context,
|
||||||
last_keyframe,
|
last_keyframe,
|
||||||
&**style,
|
&**style,
|
||||||
&state.cascade_style);
|
&state.cascade_style,
|
||||||
|
font_metrics_provider);
|
||||||
|
|
||||||
// NB: The spec says that the timing function can be overwritten
|
// NB: The spec says that the timing function can be overwritten
|
||||||
// from the keyframe style.
|
// from the keyframe style.
|
||||||
|
@ -672,7 +676,8 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
|
||||||
let target_style = compute_style_for_animation_step(context,
|
let target_style = compute_style_for_animation_step(context,
|
||||||
target_keyframe,
|
target_keyframe,
|
||||||
&from_style,
|
&from_style,
|
||||||
&state.cascade_style);
|
&state.cascade_style,
|
||||||
|
font_metrics_provider);
|
||||||
|
|
||||||
let mut new_style = (*style).clone();
|
let mut new_style = (*style).clone();
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,7 @@ mod bindings {
|
||||||
"mozilla::SERVO_PREF_.*",
|
"mozilla::SERVO_PREF_.*",
|
||||||
"kNameSpaceID_.*",
|
"kNameSpaceID_.*",
|
||||||
"kGenericFont_.*",
|
"kGenericFont_.*",
|
||||||
|
"kPresContext_.*",
|
||||||
];
|
];
|
||||||
let whitelist = [
|
let whitelist = [
|
||||||
"RawGecko.*",
|
"RawGecko.*",
|
||||||
|
@ -338,6 +339,7 @@ mod bindings {
|
||||||
"FontFamilyListRefCnt",
|
"FontFamilyListRefCnt",
|
||||||
"FontFamilyName",
|
"FontFamilyName",
|
||||||
"FontFamilyType",
|
"FontFamilyType",
|
||||||
|
"FontSizePrefs",
|
||||||
"FragmentOrURL",
|
"FragmentOrURL",
|
||||||
"FrameRequestCallback",
|
"FrameRequestCallback",
|
||||||
"GeckoParserExtraData",
|
"GeckoParserExtraData",
|
||||||
|
@ -623,6 +625,7 @@ mod bindings {
|
||||||
"ComputedTimingFunction_BeforeFlag",
|
"ComputedTimingFunction_BeforeFlag",
|
||||||
"FontFamilyList",
|
"FontFamilyList",
|
||||||
"FontFamilyType",
|
"FontFamilyType",
|
||||||
|
"FontSizePrefs",
|
||||||
"Keyframe",
|
"Keyframe",
|
||||||
"ServoBundledURI",
|
"ServoBundledURI",
|
||||||
"ServoElementSnapshot",
|
"ServoElementSnapshot",
|
||||||
|
|
|
@ -12,6 +12,7 @@ use data::ElementData;
|
||||||
use dom::{OpaqueNode, TNode, TElement, SendElement};
|
use dom::{OpaqueNode, TNode, TElement, SendElement};
|
||||||
use error_reporting::ParseErrorReporter;
|
use error_reporting::ParseErrorReporter;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::structs;
|
#[cfg(feature = "gecko")] use gecko_bindings::structs;
|
||||||
use matching::StyleSharingCandidateCache;
|
use matching::StyleSharingCandidateCache;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
@ -291,6 +292,9 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
||||||
pub statistics: TraversalStatistics,
|
pub statistics: TraversalStatistics,
|
||||||
/// Information related to the current element, non-None during processing.
|
/// Information related to the current element, non-None during processing.
|
||||||
pub current_element_info: Option<CurrentElementInfo>,
|
pub current_element_info: Option<CurrentElementInfo>,
|
||||||
|
/// 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: TElement> ThreadLocalStyleContext<E> {
|
impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
|
@ -303,6 +307,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
tasks: Vec::new(),
|
tasks: Vec::new(),
|
||||||
statistics: TraversalStatistics::default(),
|
statistics: TraversalStatistics::default(),
|
||||||
current_element_info: None,
|
current_element_info: None,
|
||||||
|
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||||
#[cfg(feature = "gecko")] use context::UpdateAnimationsTasks;
|
#[cfg(feature = "gecko")] use context::UpdateAnimationsTasks;
|
||||||
use data::ElementData;
|
use data::ElementData;
|
||||||
use element_state::ElementState;
|
use element_state::ElementState;
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
use properties::{ComputedValues, PropertyDeclarationBlock};
|
use properties::{ComputedValues, PropertyDeclarationBlock};
|
||||||
use selector_parser::{ElementExt, PreExistingComputedValues, PseudoElement};
|
use selector_parser::{ElementExt, PreExistingComputedValues, PseudoElement};
|
||||||
use selectors::matching::ElementSelectorFlags;
|
use selectors::matching::ElementSelectorFlags;
|
||||||
|
@ -278,6 +279,12 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
|
||||||
/// The concrete node type.
|
/// The concrete node type.
|
||||||
type ConcreteNode: TNode<ConcreteElement = Self>;
|
type ConcreteNode: TNode<ConcreteElement = Self>;
|
||||||
|
|
||||||
|
/// Type of the font metrics provider
|
||||||
|
///
|
||||||
|
/// XXXManishearth It would be better to make this a type parameter on
|
||||||
|
/// ThreadLocalStyleContext and StyleContext
|
||||||
|
type FontMetricsProvider: FontMetricsProvider;
|
||||||
|
|
||||||
/// Get this element as a node.
|
/// Get this element as a node.
|
||||||
fn as_node(&self) -> Self::ConcreteNode;
|
fn as_node(&self) -> Self::ConcreteNode;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
use context::SharedStyleContext;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -31,8 +32,44 @@ pub enum FontMetricsQueryResult {
|
||||||
NotAvailable,
|
NotAvailable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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, _font_name: &Atom, _font_family: u8) -> Au {
|
||||||
|
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() -> ::gecko::wrapper::GeckoFontMetricsProvider {
|
||||||
|
::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
|
||||||
|
}
|
||||||
|
|
||||||
/// 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: Send + Sync + fmt::Debug {
|
pub trait FontMetricsProvider: fmt::Debug {
|
||||||
/// 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
|
/// TODO: We could make this take the full list, I guess, and save a few
|
||||||
|
@ -41,4 +78,11 @@ pub trait FontMetricsProvider: Send + Sync + fmt::Debug {
|
||||||
fn query(&self, _font_name: &Atom) -> FontMetricsQueryResult {
|
fn query(&self, _font_name: &Atom) -> FontMetricsQueryResult {
|
||||||
FontMetricsQueryResult::NotAvailable
|
FontMetricsQueryResult::NotAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get default size of a given language and generic family
|
||||||
|
fn get_size(&self, font_name: &Atom, font_family: u8) -> Au;
|
||||||
|
|
||||||
|
/// Construct from a shared style context
|
||||||
|
fn create_from(context: &SharedStyleContext) -> Self where Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{CssStringWriter, Parser, Token};
|
use cssparser::{CssStringWriter, Parser, Token};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
|
use font_metrics::get_metrics_provider_for_product;
|
||||||
use gecko_bindings::bindings;
|
use gecko_bindings::bindings;
|
||||||
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsStringBuffer};
|
use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsStringBuffer};
|
||||||
use gecko_bindings::structs::{nsMediaExpression_Range, nsMediaFeature};
|
use gecko_bindings::structs::{nsMediaExpression_Range, nsMediaFeature};
|
||||||
|
@ -499,6 +500,8 @@ impl Expression {
|
||||||
|
|
||||||
let default_values = device.default_computed_values();
|
let default_values = device.default_computed_values();
|
||||||
|
|
||||||
|
let provider = get_metrics_provider_for_product();
|
||||||
|
|
||||||
// http://dev.w3.org/csswg/mediaqueries3/#units
|
// http://dev.w3.org/csswg/mediaqueries3/#units
|
||||||
// em units are relative to the initial font-size.
|
// em units are relative to the initial font-size.
|
||||||
let context = computed::Context {
|
let context = computed::Context {
|
||||||
|
@ -509,7 +512,7 @@ impl Expression {
|
||||||
// This cloning business is kind of dumb.... It's because Context
|
// This cloning business is kind of dumb.... It's because Context
|
||||||
// insists on having an actual ComputedValues inside itself.
|
// insists on having an actual ComputedValues inside itself.
|
||||||
style: default_values.clone(),
|
style: default_values.clone(),
|
||||||
font_metrics_provider: None,
|
font_metrics_provider: &provider,
|
||||||
};
|
};
|
||||||
|
|
||||||
let required_value = match self.value {
|
let required_value = match self.value {
|
||||||
|
|
|
@ -14,13 +14,15 @@
|
||||||
//! style system it's kind of pointless in the Stylo case, and only Servo forces
|
//! style system it's kind of pointless in the Stylo case, and only Servo forces
|
||||||
//! the separation between the style system implementation and everything else.
|
//! the separation between the style system implementation and everything else.
|
||||||
|
|
||||||
|
use app_units::Au;
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
use context::UpdateAnimationsTasks;
|
use context::{SharedStyleContext, UpdateAnimationsTasks};
|
||||||
use data::ElementData;
|
use data::ElementData;
|
||||||
use dom::{self, AnimationRules, DescendantsBit, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
|
use dom::{self, AnimationRules, DescendantsBit, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
|
||||||
use dom::{OpaqueNode, PresentationalHintsSynthetizer};
|
use dom::{OpaqueNode, PresentationalHintsSynthetizer};
|
||||||
use element_state::ElementState;
|
use element_state::ElementState;
|
||||||
use error_reporting::StdoutErrorReporter;
|
use error_reporting::StdoutErrorReporter;
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
use gecko::global_style_data::GLOBAL_STYLE_DATA;
|
use gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||||
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
|
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
|
||||||
use gecko::snapshot_helpers;
|
use gecko::snapshot_helpers;
|
||||||
|
@ -60,6 +62,7 @@ use selectors::matching::{ElementSelectorFlags, StyleRelations};
|
||||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||||
use shared_lock::Locked;
|
use shared_lock::Locked;
|
||||||
use sink::Push;
|
use sink::Push;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -426,8 +429,65 @@ fn get_animation_rule(element: &GeckoElement,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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, ::gecko_bindings::structs::FontSizePrefs)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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: u8) -> Au {
|
||||||
|
use gecko_bindings::bindings::Gecko_GetBaseSize;
|
||||||
|
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 {
|
||||||
|
Gecko_GetBaseSize(font_name.as_ptr())
|
||||||
|
};
|
||||||
|
cache.push((font_name.clone(), sizes));
|
||||||
|
sizes.size_for_generic(font_family)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl structs::FontSizePrefs {
|
||||||
|
fn size_for_generic(&self, font_family: u8) -> Au {
|
||||||
|
Au(match font_family {
|
||||||
|
structs::kPresContext_DefaultVariableFont_ID => self.mDefaultVariableSize,
|
||||||
|
structs::kPresContext_DefaultFixedFont_ID => self.mDefaultFixedSize,
|
||||||
|
structs::kGenericFont_serif => self.mDefaultSerifSize,
|
||||||
|
structs::kGenericFont_sans_serif => self.mDefaultSansSerifSize,
|
||||||
|
structs::kGenericFont_monospace => self.mDefaultMonospaceSize,
|
||||||
|
structs::kGenericFont_cursive => self.mDefaultCursiveSize,
|
||||||
|
structs::kGenericFont_fantasy => self.mDefaultFantasySize,
|
||||||
|
x => unreachable!("Unknown generic ID {}", x),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'le> TElement for GeckoElement<'le> {
|
impl<'le> TElement for GeckoElement<'le> {
|
||||||
type ConcreteNode = GeckoNode<'le>;
|
type ConcreteNode = GeckoNode<'le>;
|
||||||
|
type FontMetricsProvider = GeckoFontMetricsProvider;
|
||||||
|
|
||||||
fn as_node(&self) -> Self::ConcreteNode {
|
fn as_node(&self) -> Self::ConcreteNode {
|
||||||
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
|
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
|
||||||
|
|
|
@ -27,6 +27,7 @@ use gecko_bindings::structs::TraversalRootBehavior;
|
||||||
use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;
|
use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;
|
||||||
use gecko_bindings::structs::FontFamilyList;
|
use gecko_bindings::structs::FontFamilyList;
|
||||||
use gecko_bindings::structs::FontFamilyType;
|
use gecko_bindings::structs::FontFamilyType;
|
||||||
|
use gecko_bindings::structs::FontSizePrefs;
|
||||||
use gecko_bindings::structs::Keyframe;
|
use gecko_bindings::structs::Keyframe;
|
||||||
use gecko_bindings::structs::ServoBundledURI;
|
use gecko_bindings::structs::ServoBundledURI;
|
||||||
use gecko_bindings::structs::ServoElementSnapshot;
|
use gecko_bindings::structs::ServoElementSnapshot;
|
||||||
|
@ -1062,10 +1063,7 @@ extern "C" {
|
||||||
aSource: *const nsStyleFont);
|
aSource: *const nsStyleFont);
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_nsStyleFont_GetBaseSize(font: *const nsStyleFont,
|
pub fn Gecko_GetBaseSize(lang: *mut nsIAtom) -> FontSizePrefs;
|
||||||
pres_context:
|
|
||||||
RawGeckoPresContextBorrowed)
|
|
||||||
-> nscoord;
|
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
|
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
|
||||||
|
|
|
@ -19547,6 +19547,8 @@ pub mod root {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct gfxMissingFontRecorder([u8; 0]);
|
pub struct gfxMissingFontRecorder([u8; 0]);
|
||||||
|
pub const kPresContext_DefaultVariableFont_ID: u8 = 0;
|
||||||
|
pub const kPresContext_DefaultFixedFont_ID: u8 = 1;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct nsRootPresContext {
|
pub struct nsRootPresContext {
|
||||||
|
@ -27150,6 +27152,67 @@ pub mod root {
|
||||||
fn clone(&self) -> Self { *self }
|
fn clone(&self) -> Self { *self }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy)]
|
||||||
|
pub struct FontSizePrefs {
|
||||||
|
pub mDefaultVariableSize: root::nscoord,
|
||||||
|
pub mDefaultFixedSize: root::nscoord,
|
||||||
|
pub mDefaultSerifSize: root::nscoord,
|
||||||
|
pub mDefaultSansSerifSize: root::nscoord,
|
||||||
|
pub mDefaultMonospaceSize: root::nscoord,
|
||||||
|
pub mDefaultCursiveSize: root::nscoord,
|
||||||
|
pub mDefaultFantasySize: root::nscoord,
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn bindgen_test_layout_FontSizePrefs() {
|
||||||
|
assert_eq!(::std::mem::size_of::<FontSizePrefs>() , 28usize , concat !
|
||||||
|
( "Size of: " , stringify ! ( FontSizePrefs ) ));
|
||||||
|
assert_eq! (::std::mem::align_of::<FontSizePrefs>() , 4usize , concat
|
||||||
|
! ( "Alignment of " , stringify ! ( FontSizePrefs ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultVariableSize as * const _ as usize } , 0usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultVariableSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) . mDefaultFixedSize
|
||||||
|
as * const _ as usize } , 4usize , concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultFixedSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) . mDefaultSerifSize
|
||||||
|
as * const _ as usize } , 8usize , concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultSerifSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultSansSerifSize as * const _ as usize } , 12usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultSansSerifSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultMonospaceSize as * const _ as usize } , 16usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultMonospaceSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultCursiveSize as * const _ as usize } , 20usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultCursiveSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultFantasySize as * const _ as usize } , 24usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultFantasySize ) ));
|
||||||
|
}
|
||||||
|
impl Clone for FontSizePrefs {
|
||||||
|
fn clone(&self) -> Self { *self }
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct nsROCSSPrimitiveValue([u8; 0]);
|
pub struct nsROCSSPrimitiveValue([u8; 0]);
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -18981,6 +18981,8 @@ pub mod root {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct gfxMissingFontRecorder([u8; 0]);
|
pub struct gfxMissingFontRecorder([u8; 0]);
|
||||||
|
pub const kPresContext_DefaultVariableFont_ID: u8 = 0;
|
||||||
|
pub const kPresContext_DefaultFixedFont_ID: u8 = 1;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct nsRootPresContext {
|
pub struct nsRootPresContext {
|
||||||
|
@ -26491,6 +26493,67 @@ pub mod root {
|
||||||
fn clone(&self) -> Self { *self }
|
fn clone(&self) -> Self { *self }
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Copy)]
|
||||||
|
pub struct FontSizePrefs {
|
||||||
|
pub mDefaultVariableSize: root::nscoord,
|
||||||
|
pub mDefaultFixedSize: root::nscoord,
|
||||||
|
pub mDefaultSerifSize: root::nscoord,
|
||||||
|
pub mDefaultSansSerifSize: root::nscoord,
|
||||||
|
pub mDefaultMonospaceSize: root::nscoord,
|
||||||
|
pub mDefaultCursiveSize: root::nscoord,
|
||||||
|
pub mDefaultFantasySize: root::nscoord,
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn bindgen_test_layout_FontSizePrefs() {
|
||||||
|
assert_eq!(::std::mem::size_of::<FontSizePrefs>() , 28usize , concat !
|
||||||
|
( "Size of: " , stringify ! ( FontSizePrefs ) ));
|
||||||
|
assert_eq! (::std::mem::align_of::<FontSizePrefs>() , 4usize , concat
|
||||||
|
! ( "Alignment of " , stringify ! ( FontSizePrefs ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultVariableSize as * const _ as usize } , 0usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultVariableSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) . mDefaultFixedSize
|
||||||
|
as * const _ as usize } , 4usize , concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultFixedSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) . mDefaultSerifSize
|
||||||
|
as * const _ as usize } , 8usize , concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultSerifSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultSansSerifSize as * const _ as usize } , 12usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultSansSerifSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultMonospaceSize as * const _ as usize } , 16usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultMonospaceSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultCursiveSize as * const _ as usize } , 20usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultCursiveSize ) ));
|
||||||
|
assert_eq! (unsafe {
|
||||||
|
& ( * ( 0 as * const FontSizePrefs ) ) .
|
||||||
|
mDefaultFantasySize as * const _ as usize } , 24usize ,
|
||||||
|
concat ! (
|
||||||
|
"Alignment of field: " , stringify ! ( FontSizePrefs ) ,
|
||||||
|
"::" , stringify ! ( mDefaultFantasySize ) ));
|
||||||
|
}
|
||||||
|
impl Clone for FontSizePrefs {
|
||||||
|
fn clone(&self) -> Self { *self }
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct nsROCSSPrimitiveValue([u8; 0]);
|
pub struct nsROCSSPrimitiveValue([u8; 0]);
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -186,10 +186,11 @@ impl fmt::Display for WeakAtom {
|
||||||
|
|
||||||
impl Atom {
|
impl Atom {
|
||||||
/// Execute a callback with the atom represented by `ptr`.
|
/// Execute a callback with the atom represented by `ptr`.
|
||||||
pub unsafe fn with<F>(ptr: *mut nsIAtom, callback: &mut F) where F: FnMut(&Atom) {
|
pub unsafe fn with<F, R: 'static>(ptr: *mut nsIAtom, callback: &mut F) -> R where F: FnMut(&Atom) -> R {
|
||||||
let atom = Atom(WeakAtom::new(ptr));
|
let atom = Atom(WeakAtom::new(ptr));
|
||||||
callback(&atom);
|
let ret = callback(&atom);
|
||||||
mem::forget(atom);
|
mem::forget(atom);
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an atom from an static atom pointer without checking in release
|
/// Creates an atom from an static atom pointer without checking in release
|
||||||
|
|
|
@ -15,6 +15,7 @@ use cascade_info::CascadeInfo;
|
||||||
use context::{SequentialTask, SharedStyleContext, StyleContext};
|
use context::{SequentialTask, SharedStyleContext, StyleContext};
|
||||||
use data::{ComputedStyle, ElementData, ElementStyles, RestyleData};
|
use data::{ComputedStyle, ElementData, ElementStyles, RestyleData};
|
||||||
use dom::{AnimationRules, SendElement, TElement, TNode};
|
use dom::{AnimationRules, SendElement, TElement, TNode};
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
use properties::{CascadeFlags, ComputedValues, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
use properties::{CascadeFlags, ComputedValues, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
||||||
use properties::longhands::display::computed_value as display;
|
use properties::longhands::display::computed_value as display;
|
||||||
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_CSS_ANIMATIONS, RestyleHint};
|
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_CSS_ANIMATIONS, RestyleHint};
|
||||||
|
@ -323,6 +324,7 @@ trait PrivateMatchMethods: TElement {
|
||||||
|
|
||||||
fn cascade_with_rules(&self,
|
fn cascade_with_rules(&self,
|
||||||
shared_context: &SharedStyleContext,
|
shared_context: &SharedStyleContext,
|
||||||
|
font_metrics_provider: &FontMetricsProvider,
|
||||||
rule_node: &StrongRuleNode,
|
rule_node: &StrongRuleNode,
|
||||||
primary_style: &ComputedStyle,
|
primary_style: &ComputedStyle,
|
||||||
cascade_flags: CascadeFlags,
|
cascade_flags: CascadeFlags,
|
||||||
|
@ -388,6 +390,7 @@ trait PrivateMatchMethods: TElement {
|
||||||
layout_parent_style,
|
layout_parent_style,
|
||||||
Some(&mut cascade_info),
|
Some(&mut cascade_info),
|
||||||
&*shared_context.error_reporter,
|
&*shared_context.error_reporter,
|
||||||
|
font_metrics_provider,
|
||||||
cascade_flags));
|
cascade_flags));
|
||||||
|
|
||||||
cascade_info.finish(&self.as_node());
|
cascade_info.finish(&self.as_node());
|
||||||
|
@ -406,7 +409,8 @@ trait PrivateMatchMethods: TElement {
|
||||||
|
|
||||||
// Grab the rule node.
|
// Grab the rule node.
|
||||||
let rule_node = &pseudo_style.as_ref().map_or(primary_style, |p| &*p.1).rules;
|
let rule_node = &pseudo_style.as_ref().map_or(primary_style, |p| &*p.1).rules;
|
||||||
self.cascade_with_rules(context.shared, rule_node, primary_style, cascade_flags, pseudo_style.is_some())
|
self.cascade_with_rules(context.shared, &context.thread_local.font_metrics_provider,
|
||||||
|
rule_node, primary_style, cascade_flags, pseudo_style.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes values and damage for the primary or pseudo style of an element,
|
/// Computes values and damage for the primary or pseudo style of an element,
|
||||||
|
@ -470,6 +474,7 @@ trait PrivateMatchMethods: TElement {
|
||||||
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
|
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
|
||||||
}
|
}
|
||||||
self.cascade_with_rules(context.shared,
|
self.cascade_with_rules(context.shared,
|
||||||
|
&context.thread_local.font_metrics_provider,
|
||||||
&without_transition_rules,
|
&without_transition_rules,
|
||||||
primary_style,
|
primary_style,
|
||||||
cascade_flags,
|
cascade_flags,
|
||||||
|
@ -531,7 +536,8 @@ trait PrivateMatchMethods: TElement {
|
||||||
let shared_context = context.shared;
|
let shared_context = context.shared;
|
||||||
if let Some(ref mut old) = *old_values {
|
if let Some(ref mut old) = *old_values {
|
||||||
self.update_animations_for_cascade(shared_context, old,
|
self.update_animations_for_cascade(shared_context, old,
|
||||||
possibly_expired_animations);
|
possibly_expired_animations,
|
||||||
|
&context.thread_local.font_metrics_provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_animations_sender = &context.thread_local.new_animations_sender;
|
let new_animations_sender = &context.thread_local.new_animations_sender;
|
||||||
|
@ -606,7 +612,8 @@ trait PrivateMatchMethods: TElement {
|
||||||
fn update_animations_for_cascade(&self,
|
fn update_animations_for_cascade(&self,
|
||||||
context: &SharedStyleContext,
|
context: &SharedStyleContext,
|
||||||
style: &mut Arc<ComputedValues>,
|
style: &mut Arc<ComputedValues>,
|
||||||
possibly_expired_animations: &mut Vec<PropertyAnimation>) {
|
possibly_expired_animations: &mut Vec<PropertyAnimation>,
|
||||||
|
font_metrics: &FontMetricsProvider) {
|
||||||
// Finish any expired transitions.
|
// Finish any expired transitions.
|
||||||
let this_opaque = self.as_node().opaque();
|
let this_opaque = self.as_node().opaque();
|
||||||
animation::complete_expired_transitions(this_opaque, style, context);
|
animation::complete_expired_transitions(this_opaque, style, context);
|
||||||
|
@ -633,7 +640,8 @@ trait PrivateMatchMethods: TElement {
|
||||||
if !running_animation.is_expired() {
|
if !running_animation.is_expired() {
|
||||||
animation::update_style_for_animation(context,
|
animation::update_style_for_animation(context,
|
||||||
running_animation,
|
running_animation,
|
||||||
style);
|
style,
|
||||||
|
font_metrics);
|
||||||
if let Animation::Transition(_, _, _, ref frame, _) = *running_animation {
|
if let Animation::Transition(_, _, _, ref frame, _) = *running_animation {
|
||||||
possibly_expired_animations.push(frame.property_animation.clone())
|
possibly_expired_animations.push(frame.property_animation.clone())
|
||||||
}
|
}
|
||||||
|
@ -1145,6 +1153,7 @@ pub trait MatchMethods : TElement {
|
||||||
/// Returns computed values without animation and transition rules.
|
/// Returns computed values without animation and transition rules.
|
||||||
fn get_base_style(&self,
|
fn get_base_style(&self,
|
||||||
shared_context: &SharedStyleContext,
|
shared_context: &SharedStyleContext,
|
||||||
|
font_metrics_provider: &FontMetricsProvider,
|
||||||
primary_style: &ComputedStyle,
|
primary_style: &ComputedStyle,
|
||||||
pseudo_style: &Option<(&PseudoElement, &ComputedStyle)>)
|
pseudo_style: &Option<(&PseudoElement, &ComputedStyle)>)
|
||||||
-> Arc<ComputedValues> {
|
-> Arc<ComputedValues> {
|
||||||
|
@ -1163,6 +1172,7 @@ pub trait MatchMethods : TElement {
|
||||||
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
|
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP)
|
||||||
}
|
}
|
||||||
self.cascade_with_rules(shared_context,
|
self.cascade_with_rules(shared_context,
|
||||||
|
font_metrics_provider,
|
||||||
&without_animation_rules,
|
&without_animation_rules,
|
||||||
primary_style,
|
primary_style,
|
||||||
cascade_flags,
|
cascade_flags,
|
||||||
|
|
|
@ -536,7 +536,8 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
type ComputedValue = Au;
|
type ComputedValue = Au;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, cx: &Context) -> computed_value::T {
|
fn to_computed_value(&self, cx: &Context) -> computed_value::T {
|
||||||
use gecko_bindings::bindings::Gecko_nsStyleFont_GetBaseSize;
|
use gecko_bindings::bindings::Gecko_GetBaseSize;
|
||||||
|
use gecko_bindings::structs;
|
||||||
use values::specified::length::au_to_int_px;
|
use values::specified::length::au_to_int_px;
|
||||||
// Data from nsRuleNode.cpp in Gecko
|
// Data from nsRuleNode.cpp in Gecko
|
||||||
// Mapping from base size and HTML size to pixels
|
// Mapping from base size and HTML size to pixels
|
||||||
|
@ -561,10 +562,11 @@ ${helpers.single_keyword("font-variant-caps",
|
||||||
|
|
||||||
// XXXManishearth handle quirks mode
|
// XXXManishearth handle quirks mode
|
||||||
|
|
||||||
let base_size = unsafe {
|
let ref gecko_font = cx.style().get_font().gecko();
|
||||||
Gecko_nsStyleFont_GetBaseSize(cx.style().get_font().gecko(),
|
let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw(), &mut |atom| {
|
||||||
&*cx.device.pres_context)
|
cx.font_metrics_provider.get_size(atom, gecko_font.mGenericID).0
|
||||||
};
|
}) };
|
||||||
|
|
||||||
let base_size_px = au_to_int_px(base_size as f32);
|
let base_size_px = au_to_int_px(base_size as f32);
|
||||||
let html_size = *self as usize;
|
let html_size = *self as usize;
|
||||||
if base_size_px >= 9 && base_size_px <= 16 {
|
if base_size_px >= 9 && base_size_px <= 16 {
|
||||||
|
|
|
@ -1944,6 +1944,7 @@ pub fn cascade(device: &Device,
|
||||||
layout_parent_style: Option<<&ComputedValues>,
|
layout_parent_style: Option<<&ComputedValues>,
|
||||||
cascade_info: Option<<&mut CascadeInfo>,
|
cascade_info: Option<<&mut CascadeInfo>,
|
||||||
error_reporter: &ParseErrorReporter,
|
error_reporter: &ParseErrorReporter,
|
||||||
|
font_metrics_provider: &FontMetricsProvider,
|
||||||
flags: CascadeFlags)
|
flags: CascadeFlags)
|
||||||
-> ComputedValues {
|
-> ComputedValues {
|
||||||
debug_assert_eq!(parent_style.is_some(), layout_parent_style.is_some());
|
debug_assert_eq!(parent_style.is_some(), layout_parent_style.is_some());
|
||||||
|
@ -1988,7 +1989,7 @@ pub fn cascade(device: &Device,
|
||||||
layout_parent_style,
|
layout_parent_style,
|
||||||
cascade_info,
|
cascade_info,
|
||||||
error_reporter,
|
error_reporter,
|
||||||
None,
|
font_metrics_provider,
|
||||||
flags)
|
flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2002,7 +2003,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
||||||
layout_parent_style: &ComputedValues,
|
layout_parent_style: &ComputedValues,
|
||||||
mut cascade_info: Option<<&mut CascadeInfo>,
|
mut cascade_info: Option<<&mut CascadeInfo>,
|
||||||
error_reporter: &ParseErrorReporter,
|
error_reporter: &ParseErrorReporter,
|
||||||
font_metrics_provider: Option<<&FontMetricsProvider>,
|
font_metrics_provider: &FontMetricsProvider,
|
||||||
flags: CascadeFlags)
|
flags: CascadeFlags)
|
||||||
-> ComputedValues
|
-> ComputedValues
|
||||||
where F: Fn() -> I,
|
where F: Fn() -> I,
|
||||||
|
@ -2109,6 +2110,7 @@ pub fn apply_declarations<'a, F, I>(device: &Device,
|
||||||
| LonghandId::TextOrientation
|
| LonghandId::TextOrientation
|
||||||
| LonghandId::AnimationName
|
| LonghandId::AnimationName
|
||||||
| LonghandId::TransitionProperty
|
| LonghandId::TransitionProperty
|
||||||
|
| LonghandId::XLang
|
||||||
% endif
|
% endif
|
||||||
);
|
);
|
||||||
if
|
if
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use euclid::{Size2D, TypedSize2D};
|
use euclid::{Size2D, TypedSize2D};
|
||||||
|
use font_metrics::ServoMetricsProvider;
|
||||||
use media_queries::MediaType;
|
use media_queries::MediaType;
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -185,7 +186,10 @@ impl Range<specified::Length> {
|
||||||
// This cloning business is kind of dumb.... It's because Context
|
// This cloning business is kind of dumb.... It's because Context
|
||||||
// insists on having an actual ComputedValues inside itself.
|
// insists on having an actual ComputedValues inside itself.
|
||||||
style: default_values.clone(),
|
style: default_values.clone(),
|
||||||
font_metrics_provider: None
|
// Servo doesn't support font metrics
|
||||||
|
// A real provider will be needed here once we do; since
|
||||||
|
// ch units can exist in media queries.
|
||||||
|
font_metrics_provider: &ServoMetricsProvider,
|
||||||
};
|
};
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use {Atom, LocalName};
|
||||||
use data::ComputedStyle;
|
use data::ComputedStyle;
|
||||||
use dom::{AnimationRules, PresentationalHintsSynthetizer, TElement};
|
use dom::{AnimationRules, PresentationalHintsSynthetizer, TElement};
|
||||||
use error_reporting::StdoutErrorReporter;
|
use error_reporting::StdoutErrorReporter;
|
||||||
|
use font_metrics::FontMetricsProvider;
|
||||||
use keyframes::KeyframesAnimation;
|
use keyframes::KeyframesAnimation;
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use pdqsort::sort_by;
|
use pdqsort::sort_by;
|
||||||
|
@ -345,7 +346,8 @@ impl Stylist {
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent: Option<&Arc<ComputedValues>>,
|
parent: Option<&Arc<ComputedValues>>,
|
||||||
cascade_flags: CascadeFlags)
|
cascade_flags: CascadeFlags,
|
||||||
|
font_metrics: &FontMetricsProvider)
|
||||||
-> ComputedStyle {
|
-> ComputedStyle {
|
||||||
debug_assert!(pseudo.is_precomputed());
|
debug_assert!(pseudo.is_precomputed());
|
||||||
|
|
||||||
|
@ -381,6 +383,7 @@ impl Stylist {
|
||||||
parent.map(|p| &**p),
|
parent.map(|p| &**p),
|
||||||
None,
|
None,
|
||||||
&StdoutErrorReporter,
|
&StdoutErrorReporter,
|
||||||
|
font_metrics,
|
||||||
cascade_flags);
|
cascade_flags);
|
||||||
ComputedStyle::new(rule_node, Arc::new(computed))
|
ComputedStyle::new(rule_node, Arc::new(computed))
|
||||||
}
|
}
|
||||||
|
@ -392,6 +395,8 @@ impl Stylist {
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent_style: &Arc<ComputedValues>)
|
parent_style: &Arc<ComputedValues>)
|
||||||
-> Arc<ComputedValues> {
|
-> Arc<ComputedValues> {
|
||||||
|
use font_metrics::ServoMetricsProvider;
|
||||||
|
|
||||||
// For most (but not all) pseudo-elements, we inherit all values from the parent.
|
// For most (but not all) pseudo-elements, we inherit all values from the parent.
|
||||||
let inherit_all = match *pseudo {
|
let inherit_all = match *pseudo {
|
||||||
PseudoElement::ServoText |
|
PseudoElement::ServoText |
|
||||||
|
@ -416,7 +421,8 @@ impl Stylist {
|
||||||
if inherit_all {
|
if inherit_all {
|
||||||
cascade_flags.insert(INHERIT_ALL);
|
cascade_flags.insert(INHERIT_ALL);
|
||||||
}
|
}
|
||||||
self.precomputed_values_for_pseudo(guards, &pseudo, Some(parent_style), cascade_flags)
|
self.precomputed_values_for_pseudo(guards, &pseudo, Some(parent_style), cascade_flags,
|
||||||
|
&ServoMetricsProvider)
|
||||||
.values.unwrap()
|
.values.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +437,8 @@ impl Stylist {
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
element: &E,
|
element: &E,
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent: &Arc<ComputedValues>)
|
parent: &Arc<ComputedValues>,
|
||||||
|
font_metrics: &FontMetricsProvider)
|
||||||
-> Option<ComputedStyle>
|
-> Option<ComputedStyle>
|
||||||
where E: TElement +
|
where E: TElement +
|
||||||
fmt::Debug +
|
fmt::Debug +
|
||||||
|
@ -494,6 +501,7 @@ impl Stylist {
|
||||||
Some(&**parent),
|
Some(&**parent),
|
||||||
None,
|
None,
|
||||||
&StdoutErrorReporter,
|
&StdoutErrorReporter,
|
||||||
|
font_metrics,
|
||||||
CascadeFlags::empty());
|
CascadeFlags::empty());
|
||||||
|
|
||||||
Some(ComputedStyle::new(rule_node, Arc::new(computed)))
|
Some(ComputedStyle::new(rule_node, Arc::new(computed)))
|
||||||
|
|
|
@ -57,9 +57,7 @@ pub struct Context<'a> {
|
||||||
|
|
||||||
/// A font metrics provider, used to access font metrics to implement
|
/// A font metrics provider, used to access font metrics to implement
|
||||||
/// font-relative units.
|
/// font-relative units.
|
||||||
///
|
pub font_metrics_provider: &'a FontMetricsProvider,
|
||||||
/// TODO(emilio): This should be required, see #14079.
|
|
||||||
pub font_metrics_provider: Option<&'a FontMetricsProvider>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Context<'a> {
|
impl<'a> Context<'a> {
|
||||||
|
|
|
@ -73,11 +73,9 @@ impl FontRelativeLength {
|
||||||
/// font-family list.
|
/// font-family list.
|
||||||
pub fn find_first_available_font_metrics(context: &Context) -> Option<FontMetrics> {
|
pub fn find_first_available_font_metrics(context: &Context) -> Option<FontMetrics> {
|
||||||
use font_metrics::FontMetricsQueryResult::*;
|
use font_metrics::FontMetricsQueryResult::*;
|
||||||
if let Some(ref metrics_provider) = context.font_metrics_provider {
|
for family in context.style().get_font().font_family_iter() {
|
||||||
for family in context.style().get_font().font_family_iter() {
|
if let Available(metrics) = context.font_metrics_provider.query(family.atom()) {
|
||||||
if let Available(metrics) = metrics_provider.query(family.atom()) {
|
return metrics;
|
||||||
return metrics;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ use app_units::Au;
|
||||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
||||||
use cssparser::ToCss as ParserToCss;
|
use cssparser::ToCss as ParserToCss;
|
||||||
use euclid::size::TypedSize2D;
|
use euclid::size::TypedSize2D;
|
||||||
|
use font_metrics::get_metrics_provider_for_product;
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use parser::{Parse, ParserContext, log_css_error};
|
use parser::{Parse, ParserContext, log_css_error};
|
||||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
|
@ -672,6 +673,8 @@ impl MaybeNew for ViewportConstraints {
|
||||||
// resolved against initial values
|
// resolved against initial values
|
||||||
let initial_viewport = device.au_viewport_size();
|
let initial_viewport = device.au_viewport_size();
|
||||||
|
|
||||||
|
let provider = get_metrics_provider_for_product();
|
||||||
|
|
||||||
// TODO(emilio): Stop cloning `ComputedValues` around!
|
// TODO(emilio): Stop cloning `ComputedValues` around!
|
||||||
let context = Context {
|
let context = Context {
|
||||||
is_root_element: false,
|
is_root_element: false,
|
||||||
|
@ -679,7 +682,7 @@ impl MaybeNew for ViewportConstraints {
|
||||||
inherited_style: device.default_computed_values(),
|
inherited_style: device.default_computed_values(),
|
||||||
layout_parent_style: device.default_computed_values(),
|
layout_parent_style: device.default_computed_values(),
|
||||||
style: device.default_computed_values().clone(),
|
style: device.default_computed_values().clone(),
|
||||||
font_metrics_provider: None, // TODO: Should have!
|
font_metrics_provider: &provider,
|
||||||
};
|
};
|
||||||
|
|
||||||
// DEVICE-ADAPT § 9.3 Resolving 'extend-to-zoom'
|
// DEVICE-ADAPT § 9.3 Resolving 'extend-to-zoom'
|
||||||
|
|
|
@ -20,6 +20,7 @@ use style::data::{ElementData, ElementStyles, RestyleData};
|
||||||
use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants};
|
use style::dom::{AnimationOnlyDirtyDescendants, DirtyDescendants};
|
||||||
use style::dom::{ShowSubtreeData, TElement, TNode};
|
use style::dom::{ShowSubtreeData, TElement, TNode};
|
||||||
use style::error_reporting::StdoutErrorReporter;
|
use style::error_reporting::StdoutErrorReporter;
|
||||||
|
use style::font_metrics::get_metrics_provider_for_product;
|
||||||
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||||
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||||
|
@ -418,7 +419,8 @@ pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawSe
|
||||||
let pseudos = &styles.pseudos;
|
let pseudos = &styles.pseudos;
|
||||||
let pseudo_style = pseudo.as_ref().map(|p| (p, pseudos.get(p).unwrap()));
|
let pseudo_style = pseudo.as_ref().map(|p| (p, pseudos.get(p).unwrap()));
|
||||||
|
|
||||||
element.get_base_style(shared_context, &styles.primary, &pseudo_style)
|
let provider = get_metrics_provider_for_product();
|
||||||
|
element.get_base_style(shared_context, &provider, &styles.primary, &pseudo_style)
|
||||||
.into_strong()
|
.into_strong()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -812,8 +814,9 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
|
||||||
if skip_display_fixup {
|
if skip_display_fixup {
|
||||||
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
|
cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
|
||||||
}
|
}
|
||||||
|
let metrics = get_metrics_provider_for_product();
|
||||||
data.stylist.precomputed_values_for_pseudo(&guards, &pseudo, maybe_parent,
|
data.stylist.precomputed_values_for_pseudo(&guards, &pseudo, maybe_parent,
|
||||||
cascade_flags)
|
cascade_flags, &metrics)
|
||||||
.values.unwrap()
|
.values.unwrap()
|
||||||
.into_strong()
|
.into_strong()
|
||||||
}
|
}
|
||||||
|
@ -859,10 +862,12 @@ fn get_pseudo_style(guard: &SharedRwLockReadGuard, element: GeckoElement, pseudo
|
||||||
let d = doc_data.borrow_mut();
|
let d = doc_data.borrow_mut();
|
||||||
let base = styles.primary.values();
|
let base = styles.primary.values();
|
||||||
let guards = StylesheetGuards::same(guard);
|
let guards = StylesheetGuards::same(guard);
|
||||||
|
let metrics = get_metrics_provider_for_product();
|
||||||
d.stylist.lazily_compute_pseudo_element_style(&guards,
|
d.stylist.lazily_compute_pseudo_element_style(&guards,
|
||||||
&element,
|
&element,
|
||||||
&pseudo,
|
&pseudo,
|
||||||
base)
|
base,
|
||||||
|
&metrics)
|
||||||
.map(|s| s.values().clone())
|
.map(|s| s.values().clone())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1672,6 +1677,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis
|
||||||
let parent_style = parent_style.as_ref().map(|r| &**ComputedValues::as_arc(&r));
|
let parent_style = parent_style.as_ref().map(|r| &**ComputedValues::as_arc(&r));
|
||||||
|
|
||||||
let default_values = data.default_computed_values();
|
let default_values = data.default_computed_values();
|
||||||
|
let metrics = get_metrics_provider_for_product();
|
||||||
|
|
||||||
let context = Context {
|
let context = Context {
|
||||||
is_root_element: false,
|
is_root_element: false,
|
||||||
|
@ -1679,7 +1685,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis
|
||||||
inherited_style: parent_style.unwrap_or(default_values),
|
inherited_style: parent_style.unwrap_or(default_values),
|
||||||
layout_parent_style: parent_style.unwrap_or(default_values),
|
layout_parent_style: parent_style.unwrap_or(default_values),
|
||||||
style: (**style).clone(),
|
style: (**style).clone(),
|
||||||
font_metrics_provider: None,
|
font_metrics_provider: &metrics,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (index, keyframe) in keyframes.iter().enumerate() {
|
for (index, keyframe) in keyframes.iter().enumerate() {
|
||||||
|
|
|
@ -6,6 +6,7 @@ use cssparser::Parser;
|
||||||
use euclid::size::TypedSize2D;
|
use euclid::size::TypedSize2D;
|
||||||
use media_queries::CSSErrorReporterTest;
|
use media_queries::CSSErrorReporterTest;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
use style::font_metrics::ServoMetricsProvider;
|
||||||
use style::media_queries::{Device, MediaType};
|
use style::media_queries::{Device, MediaType};
|
||||||
use style::parser::ParserContext;
|
use style::parser::ParserContext;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -51,7 +52,7 @@ fn test_linear_gradient() {
|
||||||
inherited_style: initial_style,
|
inherited_style: initial_style,
|
||||||
layout_parent_style: initial_style,
|
layout_parent_style: initial_style,
|
||||||
style: initial_style.clone(),
|
style: initial_style.clone(),
|
||||||
font_metrics_provider: None,
|
font_metrics_provider: &ServoMetricsProvider,
|
||||||
};
|
};
|
||||||
assert_eq!(specified::AngleOrCorner::None.to_computed_value(&specified_context),
|
assert_eq!(specified::AngleOrCorner::None.to_computed_value(&specified_context),
|
||||||
computed::AngleOrCorner::Angle(Angle::from_radians(PI)));
|
computed::AngleOrCorner::Angle(Angle::from_radians(PI)));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue