Move LayoutNode and related traits to script_layout_interface.

This commit is contained in:
Ms2ger 2016-06-15 15:04:04 +01:00
parent 000e2de57a
commit 0d0b268138
15 changed files with 408 additions and 359 deletions

View file

@ -35,6 +35,7 @@ use multicol::{MulticolFlow, MulticolColumnFlow};
use parallel; use parallel;
use script::layout_interface::is_image_data; use script::layout_interface::is_image_data;
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, RECONSTRUCT_FLOW, RestyleDamage}; use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, RECONSTRUCT_FLOW, RestyleDamage};
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutNode, PseudoElementType, ThreadSafeLayoutElement};
use script_layout_interface::{LayoutNodeType, LayoutElementType}; use script_layout_interface::{LayoutNodeType, LayoutElementType};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::collections::LinkedList; use std::collections::LinkedList;
@ -59,8 +60,7 @@ use traversal::PostorderNodeMutTraversal;
use url::Url; use url::Url;
use util::linked_list; use util::linked_list;
use util::opts; use util::opts;
use wrapper::{PseudoElementType, TextContent, ThreadSafeLayoutElement}; use wrapper::{TextContent, ThreadSafeLayoutNodeHelpers};
use wrapper::{ThreadSafeLayoutNode, ThreadSafeLayoutNodeHelpers};
/// The results of flow construction for a DOM node. /// The results of flow construction for a DOM node.
#[derive(Clone)] #[derive(Clone)]

View file

@ -42,6 +42,7 @@ use multicol::MulticolFlow;
use parallel::FlowParallelInfo; use parallel::FlowParallelInfo;
use rustc_serialize::{Encodable, Encoder}; use rustc_serialize::{Encodable, Encoder};
use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage}; use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutNode};
use std::iter::Zip; use std::iter::Zip;
use std::slice::IterMut; use std::slice::IterMut;
use std::sync::Arc; use std::sync::Arc;
@ -60,7 +61,6 @@ use table_row::TableRowFlow;
use table_rowgroup::TableRowGroupFlow; use table_rowgroup::TableRowGroupFlow;
use table_wrapper::TableWrapperFlow; use table_wrapper::TableWrapperFlow;
use util::print_tree::PrintTree; use util::print_tree::PrintTree;
use wrapper::{PseudoElementType, ThreadSafeLayoutNode};
/// Virtual methods that make up a float context. /// Virtual methods that make up a float context.
/// ///

View file

@ -31,6 +31,7 @@ use range::*;
use rustc_serialize::{Encodable, Encoder}; use rustc_serialize::{Encodable, Encoder};
use script_layout_interface::HTMLCanvasData; use script_layout_interface::HTMLCanvasData;
use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, RestyleDamage}; use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, RestyleDamage};
use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::collections::LinkedList; use std::collections::LinkedList;
@ -49,7 +50,6 @@ use text;
use text::TextRunScanner; use text::TextRunScanner;
use url::Url; use url::Url;
use util; use util;
use wrapper::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
/// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position /// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position
/// themselves. In general, fragments do not have a simple correspondence with CSS fragments in the /// themselves. In general, fragments do not have a simple correspondence with CSS fragments in the

View file

@ -14,6 +14,7 @@ use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, Immutab
use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use script_layout_interface::restyle_damage::{RESOLVE_GENERATED_CONTENT, RestyleDamage}; use script_layout_interface::restyle_damage::{RESOLVE_GENERATED_CONTENT, RestyleDamage};
use script_layout_interface::wrapper_traits::PseudoElementType;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::collections::{HashMap, LinkedList}; use std::collections::{HashMap, LinkedList};
use std::sync::Arc; use std::sync::Arc;
@ -22,7 +23,6 @@ use style::computed_values::{display, list_style_type};
use style::dom::TRestyleDamage; use style::dom::TRestyleDamage;
use style::properties::{ComputedValues, ServoComputedValues}; use style::properties::{ComputedValues, ServoComputedValues};
use text::TextRunScanner; use text::TextRunScanner;
use wrapper::PseudoElementType;
// Decimal styles per CSS-COUNTER-STYLES § 6.1: // Decimal styles per CSS-COUNTER-STYLES § 6.1:
static DECIMAL: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; static DECIMAL: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];

View file

@ -26,6 +26,7 @@ use model::IntrinsicISizesContribution;
use range::{Range, RangeIndex}; use range::{Range, RangeIndex};
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW}; use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
use script_layout_interface::restyle_damage::{REPAINT, RESOLVE_GENERATED_CONTENT}; use script_layout_interface::restyle_damage::{REPAINT, RESOLVE_GENERATED_CONTENT};
use script_layout_interface::wrapper_traits::PseudoElementType;
use std::cmp::max; use std::cmp::max;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::Arc; use std::sync::Arc;
@ -39,7 +40,6 @@ use text;
use unicode_bidi; use unicode_bidi;
use util; use util;
use util::print_tree::PrintTree; use util::print_tree::PrintTree;
use wrapper::PseudoElementType;
// From gfxFontConstants.h in Firefox // From gfxFontConstants.h in Firefox
static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20; static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20;

View file

@ -50,6 +50,7 @@ use script::layout_interface::{LayoutRPC, OffsetParentResponse, NodeOverflowResp
use script::layout_interface::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow}; use script::layout_interface::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow};
use script::reporter::CSSErrorReporter; use script::reporter::CSSErrorReporter;
use script_layout_interface::restyle_damage::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW}; use script_layout_interface::restyle_damage::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW};
use script_layout_interface::wrapper_traits::LayoutNode;
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData}; use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData};
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg}; use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
use script_traits::{StackingContextScrollState, UntrustedNodeAddress}; use script_traits::{StackingContextScrollState, UntrustedNodeAddress};
@ -85,7 +86,7 @@ use util::thread_state;
use util::workqueue::WorkQueue; use util::workqueue::WorkQueue;
use webrender_helpers::{WebRenderDisplayListConverter, WebRenderFrameBuilder}; use webrender_helpers::{WebRenderDisplayListConverter, WebRenderFrameBuilder};
use webrender_traits; use webrender_traits;
use wrapper::{LayoutNode, LayoutNodeLayoutData, NonOpaqueStyleAndLayoutData, ServoLayoutNode}; use wrapper::{LayoutNodeLayoutData, NonOpaqueStyleAndLayoutData, ServoLayoutNode};
/// The number of screens of data we're allowed to generate display lists for in each direction. /// The number of screens of data we're allowed to generate display lists for in each direction.
pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8; pub const DISPLAY_PORT_SIZE_FACTOR: i32 = 8;

View file

@ -19,6 +19,7 @@ use opaque_node::OpaqueNodeMethods;
use script::layout_interface::{ContentBoxResponse, NodeOverflowResponse, ContentBoxesResponse, NodeGeometryResponse}; use script::layout_interface::{ContentBoxResponse, NodeOverflowResponse, ContentBoxesResponse, NodeGeometryResponse};
use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse, NodeLayerIdResponse}; use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse, NodeLayerIdResponse};
use script::layout_interface::{ResolvedStyleResponse, MarginStyleResponse}; use script::layout_interface::{ResolvedStyleResponse, MarginStyleResponse};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use script_traits::LayoutMsg as ConstellationMsg; use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
use sequential; use sequential;
@ -34,7 +35,7 @@ use style::properties::style_structs;
use style::selector_impl::PseudoElement; use style::selector_impl::PseudoElement;
use style::values::AuExtensionMethods; use style::values::AuExtensionMethods;
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
use wrapper::{LayoutNode, ThreadSafeLayoutNode, ThreadSafeLayoutNodeHelpers}; use wrapper::ThreadSafeLayoutNodeHelpers;
pub struct LayoutRPCImpl(pub Arc<Mutex<LayoutThreadData>>); pub struct LayoutRPCImpl(pub Arc<Mutex<LayoutThreadData>>);

View file

@ -19,6 +19,7 @@ use gfx_traits::StackingContextId;
use layout_debug; use layout_debug;
use model::MaybeAuto; use model::MaybeAuto;
use script_layout_interface::restyle_damage::REFLOW; use script_layout_interface::restyle_damage::REFLOW;
use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use style::computed_values::{border_collapse, border_top_style, vertical_align}; use style::computed_values::{border_collapse, border_top_style, vertical_align};
@ -27,7 +28,6 @@ use style::properties::{ComputedValues, ServoComputedValues};
use table::InternalTable; use table::InternalTable;
use table_row::{CollapsedBorder, CollapsedBorderProvenance}; use table_row::{CollapsedBorder, CollapsedBorderProvenance};
use util::print_tree::PrintTree; use util::print_tree::PrintTree;
use wrapper::ThreadSafeLayoutNode;
/// A table formatting context. /// A table formatting context.
#[derive(RustcEncodable)] #[derive(RustcEncodable)]

View file

@ -11,6 +11,7 @@ use flow::{CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils, PostorderFlowTraversal};
use flow::{PreorderFlowTraversal, self}; use flow::{PreorderFlowTraversal, self};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage}; use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use std::mem; use std::mem;
use style::context::StyleContext; use style::context::StyleContext;
use style::matching::MatchMethods; use style::matching::MatchMethods;
@ -18,8 +19,7 @@ use style::traversal::{DomTraversalContext, STYLE_BLOOM};
use style::traversal::{put_thread_local_bloom_filter, recalc_style_at}; use style::traversal::{put_thread_local_bloom_filter, recalc_style_at};
use util::opts; use util::opts;
use util::tid::tid; use util::tid::tid;
use wrapper::{LayoutNode, LayoutNodeLayoutData, ServoLayoutNode}; use wrapper::{LayoutNodeLayoutData, ServoLayoutNode, ThreadSafeLayoutNodeHelpers};
use wrapper::{ThreadSafeLayoutNode, ThreadSafeLayoutNodeHelpers};
pub struct RecalcStyleAndConstructFlows<'lc> { pub struct RecalcStyleAndConstructFlows<'lc> {
context: LayoutContext<'lc>, context: LayoutContext<'lc>,

View file

@ -34,7 +34,6 @@ use core::nonzero::NonZero;
use data::{LayoutDataFlags, PrivateLayoutData}; use data::{LayoutDataFlags, PrivateLayoutData};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use gfx::text::glyph::ByteIndex; use gfx::text::glyph::ByteIndex;
use gfx_traits::{LayerId, LayerType};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use opaque_node::OpaqueNodeMethods; use opaque_node::OpaqueNodeMethods;
use range::Range; use range::Range;
@ -45,6 +44,8 @@ use script::layout_interface::{LayoutDocumentHelpers, LayoutElementHelpers, Layo
use script::layout_interface::{LayoutNodeHelpers, Node, NodeTypeId}; use script::layout_interface::{LayoutNodeHelpers, Node, NodeTypeId};
use script::layout_interface::{RawLayoutElementHelpers, Text, TrustedNodeAddress}; use script::layout_interface::{RawLayoutElementHelpers, Text, TrustedNodeAddress};
use script_layout_interface::restyle_damage::RestyleDamage; use script_layout_interface::restyle_damage::RestyleDamage;
use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, LayoutNode, PseudoElementType};
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutNode, ThreadSafeLayoutElement};
use script_layout_interface::{HTMLCanvasData, LayoutNodeType}; use script_layout_interface::{HTMLCanvasData, LayoutNodeType};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData}; use script_layout_interface::{OpaqueStyleAndLayoutData, PartialStyleAndLayoutData};
use selectors::matching::{DeclarationBlock, ElementFlags}; use selectors::matching::{DeclarationBlock, ElementFlags};
@ -53,7 +54,6 @@ use smallvec::VecLike;
use std::cell::{Ref, RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
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::content::ContentItem; use style::computed_values::content::ContentItem;
@ -63,29 +63,13 @@ use style::element_state::*;
use style::properties::{ComputedValues, ServoComputedValues}; use style::properties::{ComputedValues, ServoComputedValues};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
use style::restyle_hints::ElementSnapshot; use style::restyle_hints::ElementSnapshot;
use style::selector_impl::{NonTSPseudoClass, PseudoElement, PseudoElementCascadeType, ServoSelectorImpl}; use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::servo::{PrivateStyleData, SharedStyleContext}; use style::servo::{PrivateStyleData, SharedStyleContext};
use url::Url; use url::Url;
use util::str::is_whitespace; use util::str::is_whitespace;
pub type NonOpaqueStyleAndLayoutData = *mut RefCell<PrivateLayoutData>; pub type NonOpaqueStyleAndLayoutData = *mut RefCell<PrivateLayoutData>;
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
/// only ever see these and must never see instances of `LayoutJS`.
pub trait LayoutNode: TNode {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode;
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
/// Returns the type ID of this node.
fn type_id(&self) -> LayoutNodeType;
fn get_style_data(&self) -> Option<&RefCell<PartialStyleAndLayoutData>>;
fn init_style_and_layout_data(&self, data: OpaqueStyleAndLayoutData);
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
}
pub trait LayoutNodeLayoutData { pub trait LayoutNodeLayoutData {
/// Similar to borrow_data*, but returns the full PrivateLayoutData rather /// Similar to borrow_data*, but returns the full PrivateLayoutData rather
/// than only the PrivateStyleData. /// than only the PrivateStyleData.
@ -650,313 +634,6 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
} }
} }
#[derive(Copy, PartialEq, Clone)]
pub enum PseudoElementType<T> {
Normal,
Before(T),
After(T),
DetailsSummary(T),
DetailsContent(T),
}
impl<T> PseudoElementType<T> {
pub fn is_before(&self) -> bool {
match *self {
PseudoElementType::Before(_) => true,
_ => false,
}
}
pub fn is_replaced_content(&self) -> bool {
match *self {
PseudoElementType::Before(_) | PseudoElementType::After(_) => true,
_ => false,
}
}
pub fn strip(&self) -> PseudoElementType<()> {
match *self {
PseudoElementType::Normal => PseudoElementType::Normal,
PseudoElementType::Before(_) => PseudoElementType::Before(()),
PseudoElementType::After(_) => PseudoElementType::After(()),
PseudoElementType::DetailsSummary(_) => PseudoElementType::DetailsSummary(()),
PseudoElementType::DetailsContent(_) => PseudoElementType::DetailsContent(()),
}
}
pub fn style_pseudo_element(&self) -> PseudoElement {
match *self {
PseudoElementType::Normal => unreachable!("style_pseudo_element called with PseudoElementType::Normal"),
PseudoElementType::Before(_) => PseudoElement::Before,
PseudoElementType::After(_) => PseudoElement::After,
PseudoElementType::DetailsSummary(_) => PseudoElement::DetailsSummary,
PseudoElementType::DetailsContent(_) => PseudoElement::DetailsContent,
}
}
}
/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
/// node does not allow any parents or siblings of nodes to be accessed, to avoid races.
pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
type ConcreteThreadSafeLayoutElement:
ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>
+ ::selectors::Element<Impl=ServoSelectorImpl>;
type ChildrenIterator: Iterator<Item = Self> + Sized;
/// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode`
/// with a different pseudo-element type.
fn with_pseudo(&self, pseudo: PseudoElementType<Option<display::T>>) -> Self;
/// Converts self into an `OpaqueNode`.
fn opaque(&self) -> OpaqueNode;
/// Returns the type ID of this node.
/// Returns `None` if this is a pseudo-element; otherwise, returns `Some`.
fn type_id(&self) -> Option<LayoutNodeType>;
/// Returns the type ID of this node, without discarding pseudo-elements as
/// `type_id` does.
fn type_id_without_excluding_pseudo_elements(&self) -> LayoutNodeType;
#[inline]
fn is_element_or_elements_pseudo(&self) -> bool {
match self.type_id_without_excluding_pseudo_elements() {
LayoutNodeType::Element(..) => true,
_ => false,
}
}
fn debug_id(self) -> usize;
/// Returns an iterator over this node's children.
fn children(&self) -> Self::ChildrenIterator;
#[inline]
fn is_element(&self) -> bool { if let Some(LayoutNodeType::Element(_)) = self.type_id() { true } else { false } }
/// If this is an element, accesses the element data. Fails if this is not an element node.
#[inline]
fn as_element(&self) -> Self::ConcreteThreadSafeLayoutElement;
#[inline]
fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>>;
#[inline]
fn get_before_pseudo(&self) -> Option<Self> {
if self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo
.contains_key(&PseudoElement::Before) {
Some(self.with_pseudo(PseudoElementType::Before(None)))
} else {
None
}
}
#[inline]
fn get_after_pseudo(&self) -> Option<Self> {
if self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo
.contains_key(&PseudoElement::After) {
Some(self.with_pseudo(PseudoElementType::After(None)))
} else {
None
}
}
#[inline]
fn get_details_summary_pseudo(&self) -> Option<Self> {
if self.is_element() &&
self.as_element().get_local_name() == atom!("details") &&
self.as_element().get_namespace() == ns!(html) {
Some(self.with_pseudo(PseudoElementType::DetailsSummary(None)))
} else {
None
}
}
#[inline]
fn get_details_content_pseudo(&self) -> Option<Self> {
if self.is_element() &&
self.as_element().get_local_name() == atom!("details") &&
self.as_element().get_namespace() == ns!(html) {
let display = if self.as_element().get_attr(&ns!(), &atom!("open")).is_some() {
None // Specified by the stylesheet
} else {
Some(display::T::none)
};
Some(self.with_pseudo(PseudoElementType::DetailsContent(display)))
} else {
None
}
}
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
/// Returns the style results for the given node. If CSS selector matching
/// has not yet been performed, fails.
///
/// Unlike the version on TNode, this handles pseudo-elements.
#[inline]
fn style(&self, context: &SharedStyleContext) -> Ref<Arc<ServoComputedValues>> {
match self.get_pseudo_element_type() {
PseudoElementType::Normal => {
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
data.style_data.style.as_ref().unwrap()
})
},
other => {
// Precompute non-eagerly-cascaded pseudo-element styles if not
// cached before.
let style_pseudo = other.style_pseudo_element();
match style_pseudo.cascade_type() {
// Already computed during the cascade.
PseudoElementCascadeType::Eager => {},
PseudoElementCascadeType::Precomputed => {
if !self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo.contains_key(&style_pseudo) {
let mut data = self.get_style_data().unwrap().borrow_mut();
let new_style =
context.stylist
.precomputed_values_for_pseudo(&style_pseudo,
data.style_data.style.as_ref());
data.style_data.per_pseudo
.insert(style_pseudo.clone(), new_style.unwrap());
}
}
PseudoElementCascadeType::Lazy => {
debug_assert!(self.is_element_or_elements_pseudo());
if !self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo.contains_key(&style_pseudo) {
let mut data = self.get_style_data().unwrap().borrow_mut();
let new_style =
context.stylist
.lazily_compute_pseudo_element_style(
&self.as_element(),
&style_pseudo,
data.style_data.style.as_ref().unwrap());
data.style_data.per_pseudo
.insert(style_pseudo.clone(), new_style.unwrap());
}
}
}
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
data.style_data.per_pseudo.get(&style_pseudo).unwrap()
})
}
}
}
/// Returns the already resolved style of the node.
///
/// This differs from `style(ctx)` in that if the pseudo-element has not yet
/// been computed it would panic.
///
/// This should be used just for querying layout, or when we know the
/// element style is precomputed, not from general layout itself.
#[inline]
fn resolved_style(&self) -> Ref<Arc<ServoComputedValues>> {
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
match self.get_pseudo_element_type() {
PseudoElementType::Normal
=> data.style_data.style.as_ref().unwrap(),
other
=> data.style_data.per_pseudo.get(&other.style_pseudo_element()).unwrap(),
}
})
}
#[inline]
fn selected_style(&self, _context: &SharedStyleContext) -> Ref<Arc<ServoComputedValues>> {
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
data.style_data.per_pseudo
.get(&PseudoElement::Selection)
.unwrap_or(data.style_data.style.as_ref().unwrap())
})
}
/// Removes the style from this node.
///
/// Unlike the version on TNode, this handles pseudo-elements.
fn unstyle(self) {
let mut data = self.get_style_data().unwrap().borrow_mut();
match self.get_pseudo_element_type() {
PseudoElementType::Normal => {
data.style_data.style = None;
}
other => {
data.style_data.per_pseudo.remove(&other.style_pseudo_element());
}
};
}
fn is_ignorable_whitespace(&self, context: &SharedStyleContext) -> bool;
fn restyle_damage(self) -> RestyleDamage;
fn set_restyle_damage(self, damage: RestyleDamage);
/// Returns true if this node contributes content. This is used in the implementation of
/// `empty_cells` per CSS 2.1 § 17.6.1.1.
fn is_content(&self) -> bool {
match self.type_id() {
Some(LayoutNodeType::Element(..)) | Some(LayoutNodeType::Text) => true,
_ => false
}
}
fn can_be_fragmented(&self) -> bool;
fn node_text_content(&self) -> String;
/// If the insertion point is within this node, returns it. Otherwise, returns `None`.
fn selection(&self) -> Option<Range<ByteIndex>>;
/// If this is an image element, returns its URL. If this is not an image element, fails.
///
/// FIXME(pcwalton): Don't copy URLs.
fn image_url(&self) -> Option<Url>;
fn canvas_data(&self) -> Option<HTMLCanvasData>;
/// If this node is an iframe element, returns its pipeline ID. If this node is
/// not an iframe element, fails.
fn iframe_pipeline_id(&self) -> PipelineId;
fn get_colspan(&self) -> u32;
fn layer_id(&self) -> LayerId {
let layer_type = match self.get_pseudo_element_type() {
PseudoElementType::Normal => LayerType::FragmentBody,
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
PseudoElementType::After(_) => LayerType::AfterPseudoContent,
PseudoElementType::DetailsSummary(_) => LayerType::FragmentBody,
PseudoElementType::DetailsContent(_) => LayerType::FragmentBody,
};
LayerId::new_of_type(layer_type, self.opaque().id() as usize)
}
fn layer_id_for_overflow_scroll(&self) -> LayerId {
LayerId::new_of_type(LayerType::OverflowScroll, self.opaque().id() as usize)
}
fn get_style_data(&self) -> Option<&RefCell<PartialStyleAndLayoutData>>;
}
pub trait ThreadSafeLayoutNodeHelpers { pub trait ThreadSafeLayoutNodeHelpers {
fn flow_debug_id(self) -> usize; fn flow_debug_id(self) -> usize;
@ -990,28 +667,6 @@ pub trait ThreadSafeLayoutNodeHelpers {
fn text_content(&self) -> TextContent; fn text_content(&self) -> TextContent;
} }
// This trait is only public so that it can be implemented by the gecko wrapper.
// It can be used to violate thread-safety, so don't use it elsewhere in layout!
pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
unsafe fn dangerous_first_child(&self) -> Option<Self>;
unsafe fn dangerous_next_sibling(&self) -> Option<Self>;
}
pub trait ThreadSafeLayoutElement: Clone + Copy + Sized +
::selectors::Element<Impl=ServoSelectorImpl> +
PresentationalHintsSynthetizer {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<ConcreteThreadSafeLayoutElement = Self>;
#[inline]
fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str>;
#[inline]
fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a>;
#[inline]
fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a>;
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct ServoThreadSafeLayoutNode<'ln> { pub struct ServoThreadSafeLayoutNode<'ln> {
/// The wrapped node. /// The wrapped node.

View file

@ -11,8 +11,14 @@ path = "lib.rs"
[dependencies] [dependencies]
bitflags = "0.7" bitflags = "0.7"
canvas_traits = {path = "../canvas_traits"} canvas_traits = {path = "../canvas_traits"}
gfx_traits = {path = "../gfx_traits"}
heapsize = "0.3.0" heapsize = "0.3.0"
heapsize_plugin = "0.1.2" heapsize_plugin = "0.1.2"
ipc-channel = {git = "https://github.com/servo/ipc-channel"} ipc-channel = {git = "https://github.com/servo/ipc-channel"}
msg = {path = "../msg"}
plugins = {path = "../plugins"} plugins = {path = "../plugins"}
range = {path = "../range"}
selectors = {version = "0.6", features = ["heap_size"]}
string_cache = {version = "0.2.20", features = ["heap_size"]}
style = {path = "../style"} style = {path = "../style"}
url = {version = "1.0.0", features = ["heap_size"]}

View file

@ -19,11 +19,19 @@
extern crate bitflags; extern crate bitflags;
extern crate canvas_traits; extern crate canvas_traits;
extern crate core; extern crate core;
extern crate gfx_traits;
extern crate heapsize; extern crate heapsize;
extern crate ipc_channel; extern crate ipc_channel;
extern crate msg;
extern crate range;
extern crate selectors;
#[macro_use(atom, ns)]
extern crate string_cache;
extern crate style; extern crate style;
extern crate url;
pub mod restyle_damage; pub mod restyle_damage;
pub mod wrapper_traits;
use canvas_traits::CanvasMsg; use canvas_traits::CanvasMsg;
use core::nonzero::NonZero; use core::nonzero::NonZero;

View file

@ -0,0 +1,366 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use HTMLCanvasData;
use LayoutNodeType;
use OpaqueStyleAndLayoutData;
use PartialStyleAndLayoutData;
use gfx_traits::{ByteIndex, LayerId, LayerType};
use msg::constellation_msg::PipelineId;
use range::Range;
use restyle_damage::RestyleDamage;
use std::cell::{Ref, RefCell};
use std::sync::Arc;
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace};
use style::computed_values::display;
use style::dom::OpaqueNode;
use style::dom::{PresentationalHintsSynthetizer, TNode};
use style::properties::ServoComputedValues;
use style::selector_impl::{PseudoElement, PseudoElementCascadeType, ServoSelectorImpl};
use style::servo::SharedStyleContext;
use url::Url;
#[derive(Copy, PartialEq, Clone)]
pub enum PseudoElementType<T> {
Normal,
Before(T),
After(T),
DetailsSummary(T),
DetailsContent(T),
}
impl<T> PseudoElementType<T> {
pub fn is_before(&self) -> bool {
match *self {
PseudoElementType::Before(_) => true,
_ => false,
}
}
pub fn is_replaced_content(&self) -> bool {
match *self {
PseudoElementType::Before(_) | PseudoElementType::After(_) => true,
_ => false,
}
}
pub fn strip(&self) -> PseudoElementType<()> {
match *self {
PseudoElementType::Normal => PseudoElementType::Normal,
PseudoElementType::Before(_) => PseudoElementType::Before(()),
PseudoElementType::After(_) => PseudoElementType::After(()),
PseudoElementType::DetailsSummary(_) => PseudoElementType::DetailsSummary(()),
PseudoElementType::DetailsContent(_) => PseudoElementType::DetailsContent(()),
}
}
pub fn style_pseudo_element(&self) -> PseudoElement {
match *self {
PseudoElementType::Normal => unreachable!("style_pseudo_element called with PseudoElementType::Normal"),
PseudoElementType::Before(_) => PseudoElement::Before,
PseudoElementType::After(_) => PseudoElement::After,
PseudoElementType::DetailsSummary(_) => PseudoElement::DetailsSummary,
PseudoElementType::DetailsContent(_) => PseudoElement::DetailsContent,
}
}
}
/// A wrapper so that layout can access only the methods that it should have access to. Layout must
/// only ever see these and must never see instances of `LayoutJS`.
pub trait LayoutNode: TNode {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode;
fn to_threadsafe(&self) -> Self::ConcreteThreadSafeLayoutNode;
/// Returns the type ID of this node.
fn type_id(&self) -> LayoutNodeType;
fn get_style_data(&self) -> Option<&RefCell<PartialStyleAndLayoutData>>;
fn init_style_and_layout_data(&self, data: OpaqueStyleAndLayoutData);
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
}
/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
/// node does not allow any parents or siblings of nodes to be accessed, to avoid races.
pub trait ThreadSafeLayoutNode: Clone + Copy + Sized + PartialEq {
type ConcreteThreadSafeLayoutElement:
ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>
+ ::selectors::Element<Impl=ServoSelectorImpl>;
type ChildrenIterator: Iterator<Item = Self> + Sized;
/// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode`
/// with a different pseudo-element type.
fn with_pseudo(&self, pseudo: PseudoElementType<Option<display::T>>) -> Self;
/// Converts self into an `OpaqueNode`.
fn opaque(&self) -> OpaqueNode;
/// Returns the type ID of this node.
/// Returns `None` if this is a pseudo-element; otherwise, returns `Some`.
fn type_id(&self) -> Option<LayoutNodeType>;
/// Returns the type ID of this node, without discarding pseudo-elements as
/// `type_id` does.
fn type_id_without_excluding_pseudo_elements(&self) -> LayoutNodeType;
#[inline]
fn is_element_or_elements_pseudo(&self) -> bool {
match self.type_id_without_excluding_pseudo_elements() {
LayoutNodeType::Element(..) => true,
_ => false,
}
}
fn debug_id(self) -> usize;
/// Returns an iterator over this node's children.
fn children(&self) -> Self::ChildrenIterator;
#[inline]
fn is_element(&self) -> bool { if let Some(LayoutNodeType::Element(_)) = self.type_id() { true } else { false } }
/// If this is an element, accesses the element data. Fails if this is not an element node.
#[inline]
fn as_element(&self) -> Self::ConcreteThreadSafeLayoutElement;
#[inline]
fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>>;
#[inline]
fn get_before_pseudo(&self) -> Option<Self> {
if self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo
.contains_key(&PseudoElement::Before) {
Some(self.with_pseudo(PseudoElementType::Before(None)))
} else {
None
}
}
#[inline]
fn get_after_pseudo(&self) -> Option<Self> {
if self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo
.contains_key(&PseudoElement::After) {
Some(self.with_pseudo(PseudoElementType::After(None)))
} else {
None
}
}
#[inline]
fn get_details_summary_pseudo(&self) -> Option<Self> {
if self.is_element() &&
self.as_element().get_local_name() == atom!("details") &&
self.as_element().get_namespace() == ns!(html) {
Some(self.with_pseudo(PseudoElementType::DetailsSummary(None)))
} else {
None
}
}
#[inline]
fn get_details_content_pseudo(&self) -> Option<Self> {
if self.is_element() &&
self.as_element().get_local_name() == atom!("details") &&
self.as_element().get_namespace() == ns!(html) {
let display = if self.as_element().get_attr(&ns!(), &atom!("open")).is_some() {
None // Specified by the stylesheet
} else {
Some(display::T::none)
};
Some(self.with_pseudo(PseudoElementType::DetailsContent(display)))
} else {
None
}
}
fn get_style_and_layout_data(&self) -> Option<OpaqueStyleAndLayoutData>;
/// Returns the style results for the given node. If CSS selector matching
/// has not yet been performed, fails.
///
/// Unlike the version on TNode, this handles pseudo-elements.
#[inline]
fn style(&self, context: &SharedStyleContext) -> Ref<Arc<ServoComputedValues>> {
match self.get_pseudo_element_type() {
PseudoElementType::Normal => {
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
data.style_data.style.as_ref().unwrap()
})
},
other => {
// Precompute non-eagerly-cascaded pseudo-element styles if not
// cached before.
let style_pseudo = other.style_pseudo_element();
match style_pseudo.cascade_type() {
// Already computed during the cascade.
PseudoElementCascadeType::Eager => {},
PseudoElementCascadeType::Precomputed => {
if !self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo.contains_key(&style_pseudo) {
let mut data = self.get_style_data().unwrap().borrow_mut();
let new_style =
context.stylist
.precomputed_values_for_pseudo(&style_pseudo,
data.style_data.style.as_ref());
data.style_data.per_pseudo
.insert(style_pseudo.clone(), new_style.unwrap());
}
}
PseudoElementCascadeType::Lazy => {
debug_assert!(self.is_element_or_elements_pseudo());
if !self.get_style_data()
.unwrap()
.borrow()
.style_data
.per_pseudo.contains_key(&style_pseudo) {
let mut data = self.get_style_data().unwrap().borrow_mut();
let new_style =
context.stylist
.lazily_compute_pseudo_element_style(
&self.as_element(),
&style_pseudo,
data.style_data.style.as_ref().unwrap());
data.style_data.per_pseudo
.insert(style_pseudo.clone(), new_style.unwrap());
}
}
}
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
data.style_data.per_pseudo.get(&style_pseudo).unwrap()
})
}
}
}
/// Returns the already resolved style of the node.
///
/// This differs from `style(ctx)` in that if the pseudo-element has not yet
/// been computed it would panic.
///
/// This should be used just for querying layout, or when we know the
/// element style is precomputed, not from general layout itself.
#[inline]
fn resolved_style(&self) -> Ref<Arc<ServoComputedValues>> {
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
match self.get_pseudo_element_type() {
PseudoElementType::Normal
=> data.style_data.style.as_ref().unwrap(),
other
=> data.style_data.per_pseudo.get(&other.style_pseudo_element()).unwrap(),
}
})
}
#[inline]
fn selected_style(&self, _context: &SharedStyleContext) -> Ref<Arc<ServoComputedValues>> {
Ref::map(self.get_style_data().unwrap().borrow(), |data| {
data.style_data.per_pseudo
.get(&PseudoElement::Selection)
.unwrap_or(data.style_data.style.as_ref().unwrap())
})
}
/// Removes the style from this node.
///
/// Unlike the version on TNode, this handles pseudo-elements.
fn unstyle(self) {
let mut data = self.get_style_data().unwrap().borrow_mut();
match self.get_pseudo_element_type() {
PseudoElementType::Normal => {
data.style_data.style = None;
}
other => {
data.style_data.per_pseudo.remove(&other.style_pseudo_element());
}
};
}
fn is_ignorable_whitespace(&self, context: &SharedStyleContext) -> bool;
fn restyle_damage(self) -> RestyleDamage;
fn set_restyle_damage(self, damage: RestyleDamage);
/// Returns true if this node contributes content. This is used in the implementation of
/// `empty_cells` per CSS 2.1 § 17.6.1.1.
fn is_content(&self) -> bool {
match self.type_id() {
Some(LayoutNodeType::Element(..)) | Some(LayoutNodeType::Text) => true,
_ => false
}
}
fn can_be_fragmented(&self) -> bool;
fn node_text_content(&self) -> String;
/// If the insertion point is within this node, returns it. Otherwise, returns `None`.
fn selection(&self) -> Option<Range<ByteIndex>>;
/// If this is an image element, returns its URL. If this is not an image element, fails.
///
/// FIXME(pcwalton): Don't copy URLs.
fn image_url(&self) -> Option<Url>;
fn canvas_data(&self) -> Option<HTMLCanvasData>;
/// If this node is an iframe element, returns its pipeline ID. If this node is
/// not an iframe element, fails.
fn iframe_pipeline_id(&self) -> PipelineId;
fn get_colspan(&self) -> u32;
fn layer_id(&self) -> LayerId {
let layer_type = match self.get_pseudo_element_type() {
PseudoElementType::Normal => LayerType::FragmentBody,
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
PseudoElementType::After(_) => LayerType::AfterPseudoContent,
PseudoElementType::DetailsSummary(_) => LayerType::FragmentBody,
PseudoElementType::DetailsContent(_) => LayerType::FragmentBody,
};
LayerId::new_of_type(layer_type, self.opaque().id() as usize)
}
fn layer_id_for_overflow_scroll(&self) -> LayerId {
LayerId::new_of_type(LayerType::OverflowScroll, self.opaque().id() as usize)
}
fn get_style_data(&self) -> Option<&RefCell<PartialStyleAndLayoutData>>;
}
// This trait is only public so that it can be implemented by the gecko wrapper.
// It can be used to violate thread-safety, so don't use it elsewhere in layout!
#[allow(unsafe_code)]
pub trait DangerousThreadSafeLayoutNode: ThreadSafeLayoutNode {
unsafe fn dangerous_first_child(&self) -> Option<Self>;
unsafe fn dangerous_next_sibling(&self) -> Option<Self>;
}
pub trait ThreadSafeLayoutElement: Clone + Copy + Sized +
::selectors::Element<Impl=ServoSelectorImpl> +
PresentationalHintsSynthetizer {
type ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<ConcreteThreadSafeLayoutElement = Self>;
#[inline]
fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&str>;
#[inline]
fn get_local_name<'a>(&'a self) -> BorrowedAtom<'a>;
#[inline]
fn get_namespace<'a>(&'a self) -> BorrowedNamespace<'a>;
}

View file

@ -1932,11 +1932,17 @@ version = "0.0.1"
dependencies = [ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1", "canvas_traits 0.0.1",
"gfx_traits 0.0.1",
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.2.3 (git+https://github.com/servo/ipc-channel)", "ipc-channel 0.2.3 (git+https://github.com/servo/ipc-channel)",
"msg 0.0.1",
"plugins 0.0.1", "plugins 0.0.1",
"range 0.0.1",
"selectors 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1", "style 0.0.1",
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]

6
ports/cef/Cargo.lock generated
View file

@ -1790,11 +1790,17 @@ version = "0.0.1"
dependencies = [ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1", "canvas_traits 0.0.1",
"gfx_traits 0.0.1",
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.2.3 (git+https://github.com/servo/ipc-channel)", "ipc-channel 0.2.3 (git+https://github.com/servo/ipc-channel)",
"msg 0.0.1",
"plugins 0.0.1", "plugins 0.0.1",
"range 0.0.1",
"selectors 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1", "style 0.0.1",
"url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]