Move core pseudo-element handling to ThreadSafeLayoutElement.

This commit is contained in:
Bobby Holley 2016-10-27 16:19:03 -07:00
parent 2fce2fbb0c
commit 46e29184bd
7 changed files with 314 additions and 301 deletions

View file

@ -62,7 +62,7 @@ use text::TextRunScanner;
use traversal::PostorderNodeMutTraversal;
use url::Url;
use util::opts;
use wrapper::{TextContent, ThreadSafeLayoutNodeHelpers};
use wrapper::{LayoutNodeLayoutData, TextContent, ThreadSafeLayoutNodeHelpers};
/// The results of flow construction for a DOM node.
#[derive(Clone)]
@ -221,7 +221,7 @@ impl InlineFragmentsAccumulator {
address: node.opaque(),
pseudo: node.get_pseudo_element_type().strip(),
style: node.style(style_context),
selected_style: node.selected_style(style_context),
selected_style: node.selected_style(),
flags: InlineFragmentNodeFlags::empty(),
}),
bidi_control_chars: None,
@ -514,11 +514,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
properties::modify_style_for_replaced_content(&mut whitespace_style);
properties::modify_style_for_text(&mut whitespace_style);
let style_context = self.style_context();
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
node.selected_style(style_context),
node.selected_style(),
whitespace_damage,
fragment_info);
inline_fragment_accumulator.fragments.fragments.push_back(fragment);
@ -650,7 +649,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
_ => properties::modify_style_for_text(&mut style)
}
let selected_style = node.selected_style(self.style_context());
let selected_style = node.selected_style();
match text_content {
TextContent::Text(string) => {
@ -811,7 +810,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
node.selected_style(self.style_context()),
node.selected_style(),
whitespace_damage,
fragment_info);
fragment_accumulator.fragments.fragments.push_back(fragment)
@ -834,7 +833,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
node.selected_style(self.style_context()),
node.selected_style(),
node.restyle_damage(),
info);
fragment_accumulator.fragments.fragments.push_back(fragment)
@ -921,7 +920,6 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
_ => unreachable!()
};
let style_context = self.style_context();
let mut modified_style = node.style(self.style_context());
properties::modify_style_for_outer_inline_block_fragment(&mut modified_style);
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
@ -929,7 +927,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
node.selected_style(style_context),
node.selected_style(),
node.restyle_damage(),
fragment_info);
@ -964,7 +962,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
style,
node.selected_style(style_context),
node.selected_style(),
node.restyle_damage(),
fragment_info);
@ -1076,7 +1074,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
wrapper_style,
node.selected_style(self.style_context()),
node.selected_style(),
node.restyle_damage(),
SpecificFragmentInfo::TableWrapper);
let wrapper_float_kind = FloatKind::from_property(float_value);
@ -1661,7 +1659,7 @@ trait ObjectElement {
impl<N> ObjectElement for N where N: ThreadSafeLayoutNode {
fn has_object_data(&self) -> bool {
let elem = self.as_element();
let elem = self.as_element().unwrap();
let type_and_data = (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data")));
match type_and_data {
(None, Some(uri)) => is_image_data(uri),
@ -1670,7 +1668,7 @@ impl<N> ObjectElement for N where N: ThreadSafeLayoutNode {
}
fn object_data(&self) -> Option<Url> {
let elem = self.as_element();
let elem = self.as_element().unwrap();
let type_and_data = (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data")));
match type_and_data {
(None, Some(uri)) if is_image_data(uri) => Url::parse(uri).ok(),

View file

@ -885,7 +885,7 @@ pub struct TableColumnFragmentInfo {
impl TableColumnFragmentInfo {
/// Create the information specific to an table column fragment.
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> TableColumnFragmentInfo {
let element = node.as_element();
let element = node.as_element().unwrap();
let span = element.get_attr(&ns!(), &atom!("span"))
.and_then(|string| string.parse().ok())
.unwrap_or(0);
@ -908,7 +908,7 @@ impl Fragment {
Fragment {
node: node.opaque(),
style: style,
selected_style: node.selected_style(style_context),
selected_style: node.selected_style(),
restyle_damage: restyle_damage,
border_box: LogicalRect::zero(writing_mode),
border_padding: LogicalMargin::zero(writing_mode),

View file

@ -19,7 +19,7 @@ use script_layout_interface::rpc::{HitTestResponse, LayoutRPC};
use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
use script_layout_interface::rpc::{NodeOverflowResponse, OffsetParentResponse};
use script_layout_interface::rpc::ResolvedStyleResponse;
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
use sequential;
@ -36,7 +36,7 @@ use style::selector_impl::PseudoElement;
use style::selector_matching::Stylist;
use style::values::LocalToCss;
use style_traits::cursor::Cursor;
use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};
/// Mutable data belonging to the LayoutThread.
///
@ -640,27 +640,27 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
ensure_node_data_initialized(&requested_node);
ensure_element_styled(requested_node.as_element().unwrap(), style_context);
let layout_node = requested_node.to_threadsafe();
let layout_node = match *pseudo {
Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
Some(PseudoElement::After) => layout_node.get_after_pseudo(),
let layout_el = requested_node.to_threadsafe().as_element().unwrap();
let layout_el = match *pseudo {
Some(PseudoElement::Before) => layout_el.get_before_pseudo(),
Some(PseudoElement::After) => layout_el.get_after_pseudo(),
Some(PseudoElement::DetailsSummary) |
Some(PseudoElement::DetailsContent) |
Some(PseudoElement::Selection) => None,
_ => Some(layout_node)
_ => Some(layout_el)
};
let layout_node = match layout_node {
let layout_el = match layout_el {
None => {
// The pseudo doesn't exist, return nothing. Chrome seems to query
// the element itself in this case, Firefox uses the resolved value.
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=29006
return None;
}
Some(layout_node) => layout_node
Some(layout_el) => layout_el
};
let style = &*layout_node.resolved_style();
let style = &*layout_el.resolved_style();
let positioned = match style.get_box().position {
position::computed_value::T::relative |
@ -678,11 +678,11 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
let applies = true;
fn used_value_for_position_property<N: LayoutNode>(
layout_node: N::ConcreteThreadSafeLayoutNode,
layout_el: <N::ConcreteThreadSafeLayoutNode as ThreadSafeLayoutNode>::ConcreteThreadSafeLayoutElement,
layout_root: &mut Flow,
requested_node: N,
property: &Atom) -> Option<String> {
let maybe_data = layout_node.borrow_layout_data();
let maybe_data = layout_el.borrow_layout_data();
let position = maybe_data.map_or(Point2D::zero(), |data| {
match (*data).flow_construction_result {
ConstructionResult::Flow(ref flow_ref, _) =>
@ -744,12 +744,12 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
atom!("left")
if applies && positioned && style.get_box().display !=
display::computed_value::T::none => {
used_value_for_position_property(layout_node, layout_root, requested_node, property)
used_value_for_position_property(layout_el, layout_root, requested_node, property)
}
atom!("width") | atom!("height")
if applies && style.get_box().display !=
display::computed_value::T::none => {
used_value_for_position_property(layout_node, layout_root, requested_node, property)
used_value_for_position_property(layout_el, layout_root, requested_node, property)
}
// FIXME: implement used value computation for line-height
ref property => {
@ -781,7 +781,7 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root
pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOverflowResponse {
let layout_node = requested_node.to_threadsafe();
let style = &*layout_node.resolved_style();
let style = &*layout_node.as_element().unwrap().resolved_style();
let style_box = style.get_box();
NodeOverflowResponse(Some((Point2D::new(style_box.overflow_x, style_box.overflow_y.0))))
@ -790,7 +790,7 @@ pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOv
pub fn process_margin_style_query<N: LayoutNode>(requested_node: N)
-> MarginStyleResponse {
let layout_node = requested_node.to_threadsafe();
let style = &*layout_node.resolved_style();
let style = &*layout_node.as_element().unwrap().resolved_style();
let margin = style.get_margin();
MarginStyleResponse {

View file

@ -23,7 +23,7 @@ use style::traversal::{recalc_style_at, remove_from_bloom_filter};
use style::traversal::RestyleResult;
use style::traversal::take_thread_local_bloom_filter;
use util::opts;
use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};
pub struct RecalcStyleAndConstructFlows<'lc> {
context: LayoutContext<'lc>,

View file

@ -33,7 +33,8 @@
use core::nonzero::NonZero;
use data::{LayoutDataFlags, PersistentLayoutData};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use script_layout_interface::wrapper_traits::{GetLayoutData, LayoutNode};
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use style::atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use style::computed_values::content::{self, ContentItem};
@ -44,11 +45,10 @@ pub trait LayoutNodeLayoutData {
/// than only the style::data::NodeData.
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>>;
fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>>;
fn initialize_data(self);
fn flow_debug_id(self) -> usize;
}
impl<T: LayoutNode> LayoutNodeLayoutData for T {
impl<T: GetLayoutData> LayoutNodeLayoutData for T {
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
@ -67,6 +67,16 @@ impl<T: LayoutNode> LayoutNodeLayoutData for T {
}
}
fn flow_debug_id(self) -> usize {
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}
}
pub trait LayoutNodeHelpers {
fn initialize_data(self);
}
impl<T: LayoutNode> LayoutNodeHelpers for T {
fn initialize_data(self) {
if self.borrow_layout_data().is_none() {
let ptr: NonOpaqueStyleAndLayoutData =
@ -77,27 +87,9 @@ impl<T: LayoutNode> LayoutNodeLayoutData for T {
self.init_style_and_layout_data(opaque);
}
}
fn flow_debug_id(self) -> usize {
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}
}
pub trait ThreadSafeLayoutNodeHelpers {
fn flow_debug_id(self) -> usize;
/// Borrows the layout data immutably. Fails on a conflicting borrow.
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
#[inline(always)]
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>>;
/// Borrows the layout data mutably. Fails on a conflicting borrow.
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
#[inline(always)]
fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>>;
/// Returns the layout data flags for this node.
fn flags(self) -> LayoutDataFlags;
@ -115,28 +107,6 @@ pub trait ThreadSafeLayoutNodeHelpers {
}
impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
fn flow_debug_id(self) -> usize {
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
(*container).borrow()
})
}
}
fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
(*container).borrow_mut()
})
}
}
fn flags(self) -> LayoutDataFlags {
self.borrow_layout_data().as_ref().unwrap().flags
}
@ -151,7 +121,7 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
fn text_content(&self) -> TextContent {
if self.get_pseudo_element_type().is_replaced_content() {
let style = self.resolved_style();
let style = self.as_element().unwrap().resolved_style();
return match style.as_ref().get_counters().content {
content::T::Content(ref value) if !value.is_empty() => {