mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
style: Refactor TRestyleDamage and TNode to accept/provide a "style source"
In the Gecko case, this style source would be the style context. In the servo case, it will be always the computed values. We could optimise this further in the case of stylo (from three FFI calls to one) if we use an API of the form CalcAndStore(node, new_cv). But that would imply borrowing the data twice from Servo (we also have borrow_data_unchecked fwiw, but...).
This commit is contained in:
parent
1470d5b174
commit
6d67525172
10 changed files with 120 additions and 48 deletions
|
@ -14,6 +14,7 @@ use script_traits::{AnimationState, LayoutMsg as ConstellationMsg};
|
||||||
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::dom::TRestyleDamage;
|
||||||
use style::timer::Timer;
|
use style::timer::Timer;
|
||||||
|
|
||||||
/// Processes any new animations that were discovered after style recalculation.
|
/// Processes any new animations that were discovered after style recalculation.
|
||||||
|
@ -130,10 +131,11 @@ pub fn recalc_style_for_animations(context: &SharedLayoutContext,
|
||||||
flow.mutate_fragments(&mut |fragment| {
|
flow.mutate_fragments(&mut |fragment| {
|
||||||
if let Some(ref animations) = animations.get(&fragment.node) {
|
if let Some(ref animations) = animations.get(&fragment.node) {
|
||||||
for animation in animations.iter() {
|
for animation in animations.iter() {
|
||||||
|
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);
|
||||||
Some(&mut damage));
|
damage |= RestyleDamage::compute(Some(&old_style), &fragment.style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,6 +51,7 @@ use selectors::matching::{DeclarationBlock, ElementFlags};
|
||||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::{transmute, transmute_copy};
|
use std::mem::{transmute, transmute_copy};
|
||||||
|
use std::sync::Arc;
|
||||||
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
|
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
|
||||||
use style::attr::AttrValue;
|
use style::attr::AttrValue;
|
||||||
use style::computed_values::display;
|
use style::computed_values::display;
|
||||||
|
@ -58,7 +59,7 @@ use style::context::SharedStyleContext;
|
||||||
use style::data::PrivateStyleData;
|
use style::data::PrivateStyleData;
|
||||||
use style::dom::{PresentationalHintsSynthetizer, OpaqueNode, TDocument, TElement, TNode, UnsafeNode};
|
use style::dom::{PresentationalHintsSynthetizer, OpaqueNode, TDocument, TElement, TNode, UnsafeNode};
|
||||||
use style::element_state::*;
|
use style::element_state::*;
|
||||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
use style::properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use style::refcell::{Ref, RefCell, RefMut};
|
use style::refcell::{Ref, RefCell, RefMut};
|
||||||
use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, ServoSelectorImpl};
|
use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, ServoSelectorImpl};
|
||||||
use style::sink::Push;
|
use style::sink::Push;
|
||||||
|
@ -262,6 +263,13 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
||||||
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
|
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn existing_style_for_restyle_damage<'a>(&'a self,
|
||||||
|
current_cv: Option<&'a Arc<ComputedValues>>)
|
||||||
|
-> Option<&'a Arc<ComputedValues>> {
|
||||||
|
current_cv
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
|
impl<'ln> LayoutNode for ServoLayoutNode<'ln> {
|
||||||
|
|
|
@ -44,21 +44,28 @@ bitflags! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TRestyleDamage for RestyleDamage {
|
impl TRestyleDamage for RestyleDamage {
|
||||||
fn compute(old: Option<&Arc<ServoComputedValues>>, new: &Arc<ServoComputedValues>) ->
|
/// For Servo the style source is always the computed values.
|
||||||
RestyleDamage { compute_damage(old, new) }
|
type PreExistingComputedValues = Arc<ServoComputedValues>;
|
||||||
|
|
||||||
/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed.
|
fn compute(old: Option<&Arc<ServoComputedValues>>,
|
||||||
|
new: &Arc<ServoComputedValues>) -> RestyleDamage {
|
||||||
|
compute_damage(old, new)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a bitmask that represents a flow that needs to be rebuilt and
|
||||||
|
/// reflowed.
|
||||||
///
|
///
|
||||||
/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in
|
/// Use this instead of `RestyleDamage::all()` because
|
||||||
/// unnecessary sequential resolution of generated content.
|
/// `RestyleDamage::all()` will result in unnecessary sequential resolution
|
||||||
|
/// of generated content.
|
||||||
fn rebuild_and_reflow() -> RestyleDamage {
|
fn rebuild_and_reflow() -> RestyleDamage {
|
||||||
REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RestyleDamage {
|
impl RestyleDamage {
|
||||||
/// Supposing a flow has the given `position` property and this damage, returns the damage that
|
/// Supposing a flow has the given `position` property and this damage,
|
||||||
/// we should add to the *parent* of this flow.
|
/// returns the damage that we should add to the *parent* of this flow.
|
||||||
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
|
pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage {
|
||||||
if child_is_absolutely_positioned {
|
if child_is_absolutely_positioned {
|
||||||
self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use bezier::Bezier;
|
use bezier::Bezier;
|
||||||
use context::SharedStyleContext;
|
use context::SharedStyleContext;
|
||||||
use dom::{OpaqueNode, TRestyleDamage};
|
use dom::OpaqueNode;
|
||||||
use euclid::point::Point2D;
|
use euclid::point::Point2D;
|
||||||
use keyframes::{KeyframesStep, KeyframesStepValue};
|
use keyframes::{KeyframesStep, KeyframesStepValue};
|
||||||
use properties::animated_properties::{AnimatedProperty, TransitionProperty};
|
use properties::animated_properties::{AnimatedProperty, TransitionProperty};
|
||||||
|
@ -490,13 +490,12 @@ pub fn update_style_for_animation_frame(mut new_style: &mut Arc<ComputedValues>,
|
||||||
}
|
}
|
||||||
/// Updates a single animation and associated style based on the current time.
|
/// Updates a single animation and associated style based on the current time.
|
||||||
/// If `damage` is provided, inserts the appropriate restyle damage.
|
/// If `damage` is provided, inserts the appropriate restyle damage.
|
||||||
pub fn update_style_for_animation<Damage>(context: &SharedStyleContext,
|
pub fn update_style_for_animation(context: &SharedStyleContext,
|
||||||
animation: &Animation,
|
animation: &Animation,
|
||||||
style: &mut Arc<ComputedValues>,
|
style: &mut Arc<ComputedValues>) {
|
||||||
damage: Option<&mut Damage>)
|
|
||||||
where Damage: TRestyleDamage {
|
|
||||||
debug!("update_style_for_animation: entering");
|
debug!("update_style_for_animation: entering");
|
||||||
debug_assert!(!animation.is_expired());
|
debug_assert!(!animation.is_expired());
|
||||||
|
|
||||||
match *animation {
|
match *animation {
|
||||||
Animation::Transition(_, start_time, ref frame, _) => {
|
Animation::Transition(_, start_time, ref frame, _) => {
|
||||||
debug!("update_style_for_animation: transition found");
|
debug!("update_style_for_animation: transition found");
|
||||||
|
@ -506,10 +505,6 @@ where Damage: TRestyleDamage {
|
||||||
now, start_time,
|
now, start_time,
|
||||||
frame);
|
frame);
|
||||||
if updated_style {
|
if updated_style {
|
||||||
if let Some(damage) = damage {
|
|
||||||
*damage = *damage | Damage::compute(Some(style), &new_style);
|
|
||||||
}
|
|
||||||
|
|
||||||
*style = new_style
|
*style = new_style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,10 +655,6 @@ where Damage: TRestyleDamage {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("update_style_for_animation: got style change in animation \"{}\"", name);
|
debug!("update_style_for_animation: got style change in animation \"{}\"", name);
|
||||||
if let Some(damage) = damage {
|
|
||||||
*damage = *damage | Damage::compute(Some(style), &new_style);
|
|
||||||
}
|
|
||||||
|
|
||||||
*style = new_style;
|
*style = new_style;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,19 @@ impl OpaqueNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TRestyleDamage : BitOr<Output=Self> + Copy {
|
pub trait TRestyleDamage : BitOr<Output=Self> + Copy {
|
||||||
fn compute(old: Option<&Arc<ComputedValues>>, new: &Arc<ComputedValues>) -> Self;
|
/// The source for our current computed values in the cascade. This is a
|
||||||
|
/// ComputedValues in Servo and a StyleContext in Gecko.
|
||||||
|
///
|
||||||
|
/// This is needed because Gecko has a few optimisations for the calculation
|
||||||
|
/// of the difference depending on which values have been used during
|
||||||
|
/// layout.
|
||||||
|
///
|
||||||
|
/// This should be obtained via TNode::existing_style_for_restyle_damage
|
||||||
|
type PreExistingComputedValues;
|
||||||
|
|
||||||
|
fn compute(old: Option<&Self::PreExistingComputedValues>,
|
||||||
|
new: &Arc<ComputedValues>) -> Self;
|
||||||
|
|
||||||
fn rebuild_and_reflow() -> Self;
|
fn rebuild_and_reflow() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +171,13 @@ pub trait TNode : Sized + Copy + Clone {
|
||||||
fn unstyle(self) {
|
fn unstyle(self) {
|
||||||
self.mutate_data().unwrap().style = None;
|
self.mutate_data().unwrap().style = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// XXX: It's a bit unfortunate we need to pass the current computed values
|
||||||
|
/// as an argument here, but otherwise Servo would crash due to double
|
||||||
|
/// borrows to return it.
|
||||||
|
fn existing_style_for_restyle_damage<'a>(&'a self,
|
||||||
|
current_computed_values: Option<&'a Arc<ComputedValues>>)
|
||||||
|
-> Option<&'a <Self::ConcreteRestyleDamage as TRestyleDamage>::PreExistingComputedValues>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TDocument : Sized + Copy + Clone {
|
pub trait TDocument : Sized + Copy + Clone {
|
||||||
|
|
|
@ -46,8 +46,13 @@ impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
|
||||||
unsafe { transmute(owned) }
|
unsafe { transmute(owned) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn borrow(borrowed: &Arc<ServoType>) -> *const &mut GeckoType {
|
pub fn borrow<F, Output>(borrowed: &Arc<ServoType>, cb: F) -> Output
|
||||||
transmute(borrowed)
|
where F: FnOnce(&mut GeckoType) -> Output
|
||||||
|
{
|
||||||
|
let borrowed_gecko_type: *const &mut GeckoType =
|
||||||
|
unsafe { transmute(borrowed) };
|
||||||
|
|
||||||
|
unsafe { cb(*borrowed_gecko_type) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn addref(ptr: *mut GeckoType) {
|
pub unsafe fn addref(ptr: *mut GeckoType) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use animation::{self, Animation};
|
use animation;
|
||||||
use arc_ptr_eq;
|
use arc_ptr_eq;
|
||||||
use cache::{LRUCache, SimpleHashCache};
|
use cache::{LRUCache, SimpleHashCache};
|
||||||
use context::{StyleContext, SharedStyleContext};
|
use context::{StyleContext, SharedStyleContext};
|
||||||
|
@ -442,8 +442,13 @@ trait PrivateMatchMethods: TNode
|
||||||
cacheable = cacheable && !animations_started
|
cacheable = cacheable && !animations_started
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let existing_style =
|
||||||
|
self.existing_style_for_restyle_damage(style.map(|s| &*s));
|
||||||
|
|
||||||
// Calculate style difference.
|
// Calculate style difference.
|
||||||
let damage = Self::ConcreteRestyleDamage::compute(style.map(|s| &*s), &this_style);
|
let damage =
|
||||||
|
Self::ConcreteRestyleDamage::compute(existing_style, &this_style);
|
||||||
|
|
||||||
// Cache the resolved style if it was cacheable.
|
// Cache the resolved style if it was cacheable.
|
||||||
if cacheable {
|
if cacheable {
|
||||||
|
@ -490,8 +495,9 @@ trait PrivateMatchMethods: TNode
|
||||||
// See #12171 and the associated PR for an example where this
|
// See #12171 and the associated PR for an example where this
|
||||||
// happened while debugging other release panic.
|
// happened while debugging other release panic.
|
||||||
if !running_animation.is_expired() {
|
if !running_animation.is_expired() {
|
||||||
animation::update_style_for_animation::<Self::ConcreteRestyleDamage>(
|
animation::update_style_for_animation(context,
|
||||||
context, running_animation, style, None);
|
running_animation,
|
||||||
|
style);
|
||||||
running_animation.mark_as_expired();
|
running_animation.mark_as_expired();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -585,9 +591,17 @@ pub trait ElementMatchMethods : TElement {
|
||||||
if let Some(shared_style) = self.share_style_with_candidate_if_possible(parent.clone(), candidate) {
|
if let Some(shared_style) = self.share_style_with_candidate_if_possible(parent.clone(), candidate) {
|
||||||
// Yay, cache hit. Share the style.
|
// Yay, cache hit. Share the style.
|
||||||
let node = self.as_node();
|
let node = self.as_node();
|
||||||
|
|
||||||
let style = &mut node.mutate_data().unwrap().style;
|
let style = &mut node.mutate_data().unwrap().style;
|
||||||
let damage = <<Self as TElement>::ConcreteNode as TNode>
|
|
||||||
::ConcreteRestyleDamage::compute((*style).as_ref(), &shared_style);
|
let damage = {
|
||||||
|
let source =
|
||||||
|
node.existing_style_for_restyle_damage((*style).as_ref());
|
||||||
|
let damage = <<Self as TElement>::ConcreteNode as TNode>
|
||||||
|
::ConcreteRestyleDamage::compute(source, &shared_style);
|
||||||
|
damage
|
||||||
|
};
|
||||||
|
|
||||||
*style = Some(shared_style);
|
*style = Some(shared_style);
|
||||||
return StyleSharingResult::StyleWasShared(i, damage)
|
return StyleSharingResult::StyleWasShared(i, damage)
|
||||||
}
|
}
|
||||||
|
@ -675,8 +689,14 @@ pub trait MatchMethods : TNode {
|
||||||
let mut data_ref = self.mutate_data().unwrap();
|
let mut data_ref = self.mutate_data().unwrap();
|
||||||
let mut data = &mut *data_ref;
|
let mut data = &mut *data_ref;
|
||||||
let cloned_parent_style = ComputedValues::style_for_child_text_node(parent_style.unwrap());
|
let cloned_parent_style = ComputedValues::style_for_child_text_node(parent_style.unwrap());
|
||||||
damage = Self::ConcreteRestyleDamage::compute(data.style.as_ref(),
|
|
||||||
&cloned_parent_style);
|
{
|
||||||
|
let existing_style =
|
||||||
|
self.existing_style_for_restyle_damage(data.style.as_ref());
|
||||||
|
damage = Self::ConcreteRestyleDamage::compute(existing_style,
|
||||||
|
&cloned_parent_style);
|
||||||
|
}
|
||||||
|
|
||||||
data.style = Some(cloned_parent_style);
|
data.style = Some(cloned_parent_style);
|
||||||
} else {
|
} else {
|
||||||
damage = {
|
damage = {
|
||||||
|
@ -697,7 +717,6 @@ pub trait MatchMethods : TNode {
|
||||||
let applicable_declarations_for_this_pseudo =
|
let applicable_declarations_for_this_pseudo =
|
||||||
applicable_declarations.per_pseudo.get(&pseudo).unwrap();
|
applicable_declarations.per_pseudo.get(&pseudo).unwrap();
|
||||||
|
|
||||||
|
|
||||||
if !applicable_declarations_for_this_pseudo.is_empty() {
|
if !applicable_declarations_for_this_pseudo.is_empty() {
|
||||||
// NB: Transitions and animations should only work for
|
// NB: Transitions and animations should only work for
|
||||||
// pseudo-elements ::before and ::after
|
// pseudo-elements ::before and ::after
|
||||||
|
|
|
@ -144,6 +144,10 @@ use structs::nsFont;
|
||||||
use structs::FontFamilyList;
|
use structs::FontFamilyList;
|
||||||
use structs::FontFamilyType;
|
use structs::FontFamilyType;
|
||||||
use structs::nsIAtom;
|
use structs::nsIAtom;
|
||||||
|
use structs::nsStyleContext;
|
||||||
|
unsafe impl Send for nsStyleContext {}
|
||||||
|
unsafe impl Sync for nsStyleContext {}
|
||||||
|
impl HeapSizeOf for nsStyleContext { fn heap_size_of_children(&self) -> usize { 0 } }
|
||||||
|
|
||||||
pub type RawGeckoNode = nsINode;
|
pub type RawGeckoNode = nsINode;
|
||||||
pub enum Element { }
|
pub enum Element { }
|
||||||
|
@ -294,7 +298,9 @@ extern "C" {
|
||||||
pub fn Gecko_GetNodeFlags(node: *mut RawGeckoNode) -> u32;
|
pub fn Gecko_GetNodeFlags(node: *mut RawGeckoNode) -> u32;
|
||||||
pub fn Gecko_SetNodeFlags(node: *mut RawGeckoNode, flags: u32);
|
pub fn Gecko_SetNodeFlags(node: *mut RawGeckoNode, flags: u32);
|
||||||
pub fn Gecko_UnsetNodeFlags(node: *mut RawGeckoNode, flags: u32);
|
pub fn Gecko_UnsetNodeFlags(node: *mut RawGeckoNode, flags: u32);
|
||||||
pub fn Gecko_CalcStyleDifference(oldstyle: *mut ServoComputedValues,
|
pub fn Gecko_GetStyleContext(node: *mut RawGeckoNode)
|
||||||
|
-> *mut nsStyleContext;
|
||||||
|
pub fn Gecko_CalcStyleDifference(oldstyle: *mut nsStyleContext,
|
||||||
newstyle: *mut ServoComputedValues)
|
newstyle: *mut ServoComputedValues)
|
||||||
-> nsChangeHint;
|
-> nsChangeHint;
|
||||||
pub fn Gecko_StoreStyleDifference(node: *mut RawGeckoNode,
|
pub fn Gecko_StoreStyleDifference(node: *mut RawGeckoNode,
|
||||||
|
|
|
@ -128,7 +128,7 @@ COMPILATION_TARGETS = {
|
||||||
"nsStyleCoord::Calc", "nsRestyleHint", "ServoElementSnapshot",
|
"nsStyleCoord::Calc", "nsRestyleHint", "ServoElementSnapshot",
|
||||||
"nsChangeHint", "SheetParsingMode", "nsMainThreadPtrHandle",
|
"nsChangeHint", "SheetParsingMode", "nsMainThreadPtrHandle",
|
||||||
"nsMainThreadPtrHolder", "nscolor", "nsFont", "FontFamilyList",
|
"nsMainThreadPtrHolder", "nscolor", "nsFont", "FontFamilyList",
|
||||||
"FontFamilyType", "nsIAtom",
|
"FontFamilyType", "nsIAtom", "nsStyleContext"
|
||||||
],
|
],
|
||||||
"void_types": [
|
"void_types": [
|
||||||
"nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
|
"nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
|
||||||
|
|
|
@ -8,6 +8,7 @@ use gecko_bindings::bindings;
|
||||||
use gecko_bindings::bindings::Gecko_ChildrenCount;
|
use gecko_bindings::bindings::Gecko_ChildrenCount;
|
||||||
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
use gecko_bindings::bindings::Gecko_ClassOrClassList;
|
||||||
use gecko_bindings::bindings::Gecko_GetNodeData;
|
use gecko_bindings::bindings::Gecko_GetNodeData;
|
||||||
|
use gecko_bindings::bindings::Gecko_GetStyleContext;
|
||||||
use gecko_bindings::bindings::ServoComputedValues;
|
use gecko_bindings::bindings::ServoComputedValues;
|
||||||
use gecko_bindings::bindings::ServoNodeData;
|
use gecko_bindings::bindings::ServoNodeData;
|
||||||
use gecko_bindings::bindings::{Gecko_CalcStyleDifference, Gecko_StoreStyleDifference};
|
use gecko_bindings::bindings::{Gecko_CalcStyleDifference, Gecko_StoreStyleDifference};
|
||||||
|
@ -24,7 +25,7 @@ use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
|
||||||
use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
||||||
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
|
use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
|
||||||
use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
|
use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
|
||||||
use gecko_bindings::structs::{nsIAtom, nsChangeHint};
|
use gecko_bindings::structs::{nsIAtom, nsChangeHint, nsStyleContext};
|
||||||
use glue::GeckoDeclarationBlock;
|
use glue::GeckoDeclarationBlock;
|
||||||
use libc::uintptr_t;
|
use libc::uintptr_t;
|
||||||
use selectors::Element;
|
use selectors::Element;
|
||||||
|
@ -97,19 +98,19 @@ impl<'ln> GeckoNode<'ln> {
|
||||||
pub struct GeckoRestyleDamage(nsChangeHint);
|
pub struct GeckoRestyleDamage(nsChangeHint);
|
||||||
|
|
||||||
impl TRestyleDamage for GeckoRestyleDamage {
|
impl TRestyleDamage for GeckoRestyleDamage {
|
||||||
fn compute(previous_style: Option<&Arc<ComputedValues>>,
|
type PreExistingComputedValues = nsStyleContext;
|
||||||
current_style: &Arc<ComputedValues>) -> Self {
|
fn compute(source: Option<&nsStyleContext>,
|
||||||
|
new_style: &Arc<ComputedValues>) -> Self {
|
||||||
type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
|
type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
|
||||||
let previous_style = match previous_style {
|
let context = match source {
|
||||||
Some(previous) => previous,
|
Some(ctx) => ctx as *const nsStyleContext as *mut nsStyleContext,
|
||||||
None => return Self::rebuild_and_reflow(),
|
None => return Self::rebuild_and_reflow(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let previous = unsafe { Helpers::borrow(previous_style) };
|
Helpers::borrow(new_style, |new_style| {
|
||||||
let current = unsafe { Helpers::borrow(current_style) };
|
let hint = unsafe { Gecko_CalcStyleDifference(context, new_style) };
|
||||||
let hint = unsafe { Gecko_CalcStyleDifference(*previous, *current) };
|
GeckoRestyleDamage(hint)
|
||||||
|
})
|
||||||
GeckoRestyleDamage(hint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebuild_and_reflow() -> Self {
|
fn rebuild_and_reflow() -> Self {
|
||||||
|
@ -307,6 +308,20 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn existing_style_for_restyle_damage<'a>(&'a self,
|
||||||
|
current_cv: Option<&'a Arc<ComputedValues>>)
|
||||||
|
-> Option<&'a nsStyleContext> {
|
||||||
|
if current_cv.is_none() {
|
||||||
|
// Don't bother in doing an ffi call to get null back.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let context_ptr = Gecko_GetStyleContext(self.node);
|
||||||
|
context_ptr.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn needs_dirty_on_viewport_size_changed(&self) -> bool {
|
fn needs_dirty_on_viewport_size_changed(&self) -> bool {
|
||||||
// Gecko's node doesn't have the DIRTY_ON_VIEWPORT_SIZE_CHANGE flag,
|
// Gecko's node doesn't have the DIRTY_ON_VIEWPORT_SIZE_CHANGE flag,
|
||||||
// so we force them to be dirtied on viewport size change, regardless if
|
// so we force them to be dirtied on viewport size change, regardless if
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue