mirror of
https://github.com/servo/servo.git
synced 2025-06-25 01:24:37 +01:00
Use Any
for the layout data.
Breaks the dependency between `gfx` and `script`, which is nice.
This commit is contained in:
parent
bdc7e984eb
commit
6ff7b4a6a6
8 changed files with 207 additions and 154 deletions
|
@ -226,14 +226,14 @@ DONE_gfx = $(B)src/components/gfx/libgfx.dummy
|
||||||
|
|
||||||
DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg)
|
DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg)
|
||||||
|
|
||||||
RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/style -L $(B)src/components/net -L $(B)src/components/gfx -L $(B)src/components/msg
|
RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/style -L $(B)src/components/net -L $(B)src/components/msg
|
||||||
WEBIDL_script = $(call rwildcard,$(S)src/components/script/,*.webidl)
|
WEBIDL_script = $(call rwildcard,$(S)src/components/script/,*.webidl)
|
||||||
AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script))
|
AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script))
|
||||||
SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script)
|
SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script)
|
||||||
CRATE_script = $(S)src/components/script/script.rc
|
CRATE_script = $(S)src/components/script/script.rc
|
||||||
DONE_script = $(B)src/components/script/libscript.dummy
|
DONE_script = $(B)src/components/script/libscript.dummy
|
||||||
|
|
||||||
DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_gfx) $(DONE_msg)
|
DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_style) $(DONE_net) $(DONE_msg)
|
||||||
|
|
||||||
RFLAGS_style = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util
|
RFLAGS_style = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util
|
||||||
MAKO_ZIP = $(S)src/components/style/Mako-0.8.1.zip
|
MAKO_ZIP = $(S)src/components/style/Mako-0.8.1.zip
|
||||||
|
|
|
@ -14,6 +14,7 @@ use extra::arc::RWArc;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use css::node_util::NodeUtil;
|
use css::node_util::NodeUtil;
|
||||||
use layout::incremental;
|
use layout::incremental;
|
||||||
|
use layout::util::LayoutDataAccess;
|
||||||
|
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use style::Stylist;
|
use style::Stylist;
|
||||||
|
@ -37,10 +38,7 @@ impl MatchMethods for AbstractNode<LayoutView> {
|
||||||
};
|
};
|
||||||
stylist.get_applicable_declarations(self, style_attribute, None)
|
stylist.get_applicable_declarations(self, style_attribute, None)
|
||||||
};
|
};
|
||||||
let cell = Cell::new(applicable_declarations);
|
self.layout_data().applicable_declarations.set(applicable_declarations)
|
||||||
do self.write_layout_data |data| {
|
|
||||||
data.applicable_declarations = cell.take();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn match_subtree(&self, stylist: RWArc<Stylist>) {
|
fn match_subtree(&self, stylist: RWArc<Stylist>) {
|
||||||
let num_tasks = default_sched_threads() * 2;
|
let num_tasks = default_sched_threads() * 2;
|
||||||
|
@ -84,22 +82,21 @@ impl MatchMethods for AbstractNode<LayoutView> {
|
||||||
Some(parent) => Some(parent.style()),
|
Some(parent) => Some(parent.style()),
|
||||||
None => None
|
None => None
|
||||||
};
|
};
|
||||||
let computed_values = do self.read_layout_data |data| {
|
|
||||||
cascade(data.applicable_declarations, parent_style)
|
let layout_data = self.layout_data();
|
||||||
};
|
let computed_values = cascade(*layout_data.applicable_declarations.borrow().ptr,
|
||||||
let cell = Cell::new(computed_values);
|
parent_style);
|
||||||
do self.write_layout_data |data| {
|
let style = layout_data.style.mutate();
|
||||||
let style = cell.take();
|
match *style.ptr {
|
||||||
// If there was an existing style, compute the damage that
|
|
||||||
// incremental layout will need to fix.
|
|
||||||
match data.style {
|
|
||||||
None => (),
|
None => (),
|
||||||
Some(ref previous_style) => self.set_restyle_damage(
|
Some(ref previous_style) => {
|
||||||
incremental::compute_damage(previous_style, &style))
|
self.set_restyle_damage(incremental::compute_damage(previous_style,
|
||||||
}
|
&computed_values))
|
||||||
data.style = Some(style);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*style.ptr = Some(computed_values)
|
||||||
|
}
|
||||||
|
|
||||||
fn cascade_subtree(&self, parent: Option<AbstractNode<LayoutView>>) {
|
fn cascade_subtree(&self, parent: Option<AbstractNode<LayoutView>>) {
|
||||||
self.cascade_node(parent);
|
self.cascade_node(parent);
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,13 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use layout::incremental::RestyleDamage;
|
use layout::incremental::RestyleDamage;
|
||||||
|
use layout::util::LayoutDataAccess;
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cell::Cell;
|
|
||||||
use style::ComputedValues;
|
use style::ComputedValues;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::tree::TreeNodeRef;
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
|
|
||||||
pub trait NodeUtil<'self> {
|
pub trait NodeUtil<'self> {
|
||||||
fn get_css_select_results(self) -> &'self ComputedValues;
|
fn get_css_select_results(self) -> &'self ComputedValues;
|
||||||
fn set_css_select_results(self, decl: ComputedValues);
|
fn set_css_select_results(self, decl: ComputedValues);
|
||||||
|
@ -29,23 +28,21 @@ impl<'self> NodeUtil<'self> for AbstractNode<LayoutView> {
|
||||||
* stored in a box that can be overwritten
|
* stored in a box that can be overwritten
|
||||||
*/
|
*/
|
||||||
fn get_css_select_results(self) -> &'self ComputedValues {
|
fn get_css_select_results(self) -> &'self ComputedValues {
|
||||||
do self.read_layout_data |layout_data| {
|
let layout_data = self.layout_data();
|
||||||
match layout_data.style {
|
match *layout_data.style.borrow().ptr {
|
||||||
None => fail!(~"style() called on node without a style!"),
|
None => fail!(~"style() called on node without a style!"),
|
||||||
Some(ref style) => unsafe { cast::transmute_region(style) }
|
Some(ref style) => unsafe { cast::transmute_region(style) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Does this node have a computed style yet?
|
/// Does this node have a computed style yet?
|
||||||
fn have_css_select_results(self) -> bool {
|
fn have_css_select_results(self) -> bool {
|
||||||
self.read_layout_data(|data| data.style.is_some())
|
self.layout_data().style.borrow().ptr.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the computed style of an HTML element with a style specified by CSS.
|
/// Update the computed style of an HTML element with a style specified by CSS.
|
||||||
fn set_css_select_results(self, decl: ComputedValues) {
|
fn set_css_select_results(self, decl: ComputedValues) {
|
||||||
let cell = Cell::new(decl);
|
*self.layout_data().style.mutate().ptr = Some(decl)
|
||||||
self.write_layout_data(|data| data.style = Some(cell.take()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the description of how to account for recent style changes.
|
/// Get the description of how to account for recent style changes.
|
||||||
|
@ -59,15 +56,17 @@ impl<'self> NodeUtil<'self> for AbstractNode<LayoutView> {
|
||||||
RestyleDamage::none()
|
RestyleDamage::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
do self.read_layout_data |layout_data| {
|
self.layout_data()
|
||||||
layout_data.restyle_damage
|
.restyle_damage
|
||||||
|
.borrow()
|
||||||
|
.ptr
|
||||||
.map(|x| RestyleDamage::from_int(x))
|
.map(|x| RestyleDamage::from_int(x))
|
||||||
.unwrap_or(default)
|
.unwrap_or(default)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the restyle damage field.
|
/// Set the restyle damage field.
|
||||||
fn set_restyle_damage(self, damage: RestyleDamage) {
|
fn set_restyle_damage(self, damage: RestyleDamage) {
|
||||||
self.write_layout_data(|data| data.restyle_damage = Some(damage.to_int()));
|
*self.layout_data().restyle_damage.mutate().ptr = Some(damage.to_int())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,11 @@
|
||||||
|
|
||||||
//! Code for managing the layout data in the DOM.
|
//! Code for managing the layout data in the DOM.
|
||||||
|
|
||||||
|
use layout::util::{DisplayBoxes, LayoutData, LayoutDataAccess};
|
||||||
|
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::tree::TreeNodeRef;
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
use std::cast;
|
||||||
|
|
||||||
/// Functionality useful for querying the layout-specific data on DOM nodes.
|
/// Functionality useful for querying the layout-specific data on DOM nodes.
|
||||||
pub trait LayoutAuxMethods {
|
pub trait LayoutAuxMethods {
|
||||||
|
@ -15,10 +18,16 @@ pub trait LayoutAuxMethods {
|
||||||
|
|
||||||
impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
||||||
/// Resets layout data and styles for the node.
|
/// Resets layout data and styles for the node.
|
||||||
|
///
|
||||||
|
/// FIXME(pcwalton): Do this as part of box building instead of in a traversal.
|
||||||
fn initialize_layout_data(self) {
|
fn initialize_layout_data(self) {
|
||||||
do self.write_layout_data |data| {
|
unsafe {
|
||||||
data.boxes.display_list = None;
|
let node = cast::transmute_mut(self.node());
|
||||||
data.boxes.range = None;
|
if node.layout_data.is_none() {
|
||||||
|
node.layout_data = Some(~LayoutData::new() as ~Any)
|
||||||
|
} else {
|
||||||
|
self.layout_data().boxes.set(DisplayBoxes::init());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,11 @@ use layout::flow::{FlowContext, ImmutableFlowUtils, MutableFlowUtils, PreorderFl
|
||||||
use layout::flow::{PostorderFlowTraversal};
|
use layout::flow::{PostorderFlowTraversal};
|
||||||
use layout::flow;
|
use layout::flow;
|
||||||
use layout::incremental::{RestyleDamage, BubbleWidths};
|
use layout::incremental::{RestyleDamage, BubbleWidths};
|
||||||
|
use layout::util::LayoutDataAccess;
|
||||||
|
|
||||||
use std::cast::transmute;
|
use std::cast::transmute;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::comm::{Port};
|
use std::comm::Port;
|
||||||
use std::task;
|
use std::task;
|
||||||
use extra::arc::{Arc, RWArc};
|
use extra::arc::{Arc, RWArc};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
@ -419,12 +420,14 @@ impl LayoutTask {
|
||||||
transmute(display_list.get().list[i].base().extra)
|
transmute(display_list.get().list[i].base().extra)
|
||||||
};
|
};
|
||||||
|
|
||||||
do node.write_layout_data |layout_data| {
|
// FIXME(pcwalton): Why are we cloning the display list here?!
|
||||||
layout_data.boxes.display_list = Some(display_list.clone());
|
let layout_data = node.layout_data();
|
||||||
|
let boxes = layout_data.boxes.mutate();
|
||||||
|
boxes.ptr.display_list = Some(display_list.clone());
|
||||||
|
|
||||||
if layout_data.boxes.range.is_none() {
|
if boxes.ptr.range.is_none() {
|
||||||
debug!("Creating initial range for node");
|
debug!("Creating initial range for node");
|
||||||
layout_data.boxes.range = Some(Range::new(i,1));
|
boxes.ptr.range = Some(Range::new(i,1));
|
||||||
} else {
|
} else {
|
||||||
debug!("Appending item to range");
|
debug!("Appending item to range");
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -433,8 +436,7 @@ impl LayoutTask {
|
||||||
"Non-contiguous arrangement of display items");
|
"Non-contiguous arrangement of display items");
|
||||||
}
|
}
|
||||||
|
|
||||||
layout_data.boxes.range.unwrap().extend_by(1);
|
boxes.ptr.range.unwrap().extend_by(1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,8 +471,10 @@ impl LayoutTask {
|
||||||
};
|
};
|
||||||
|
|
||||||
fn box_for_node(node: AbstractNode<LayoutView>) -> Option<Rect<Au>> {
|
fn box_for_node(node: AbstractNode<LayoutView>) -> Option<Rect<Au>> {
|
||||||
do node.read_layout_data |layout_data| {
|
// FIXME(pcwalton): Why are we cloning the display list here?!
|
||||||
match (layout_data.boxes.display_list.clone(), layout_data.boxes.range) {
|
let boxes = node.layout_data().boxes.borrow();
|
||||||
|
let boxes = boxes.ptr;
|
||||||
|
match (boxes.display_list.clone(), boxes.range) {
|
||||||
(Some(display_list), Some(range)) => {
|
(Some(display_list), Some(range)) => {
|
||||||
let mut rect: Option<Rect<Au>> = None;
|
let mut rect: Option<Rect<Au>> = None;
|
||||||
for i in range.eachi() {
|
for i in range.eachi() {
|
||||||
|
@ -499,7 +503,6 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let rect = box_for_node(node).unwrap_or(Rect(Point2D(Au(0), Au(0)),
|
let rect = box_for_node(node).unwrap_or(Rect(Point2D(Au(0), Au(0)),
|
||||||
Size2D(Au(0), Au(0))));
|
Size2D(Au(0), Au(0))));
|
||||||
|
@ -511,25 +514,23 @@ impl LayoutTask {
|
||||||
transmute(node)
|
transmute(node)
|
||||||
};
|
};
|
||||||
|
|
||||||
fn boxes_for_node(node: AbstractNode<LayoutView>,
|
fn boxes_for_node(node: AbstractNode<LayoutView>, mut box_accumulator: ~[Rect<Au>])
|
||||||
boxes: ~[Rect<Au>]) -> ~[Rect<Au>] {
|
-> ~[Rect<Au>] {
|
||||||
let boxes = Cell::new(boxes);
|
let boxes = node.layout_data().boxes.borrow();
|
||||||
do node.read_layout_data |layout_data| {
|
let boxes = boxes.ptr;
|
||||||
let mut boxes = boxes.take();
|
match (boxes.display_list.clone(), boxes.range) {
|
||||||
match (layout_data.boxes.display_list.clone(), layout_data.boxes.range) {
|
|
||||||
(Some(display_list), Some(range)) => {
|
(Some(display_list), Some(range)) => {
|
||||||
for i in range.eachi() {
|
for i in range.eachi() {
|
||||||
boxes.push(display_list.get().list[i].bounds());
|
box_accumulator.push(display_list.get().list[i].bounds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
boxes = boxes_for_node(child, boxes);
|
box_accumulator = boxes_for_node(child, box_accumulator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boxes
|
box_accumulator
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut boxes = ~[];
|
let mut boxes = ~[];
|
||||||
|
|
|
@ -3,12 +3,34 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use layout::box::{RenderBox, RenderBoxUtils};
|
use layout::box::{RenderBox, RenderBoxUtils};
|
||||||
|
|
||||||
|
use extra::arc::Arc;
|
||||||
|
use gfx::display_list::DisplayList;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
use servo_util::slot::Slot;
|
||||||
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
use std::any::AnyRefExt;
|
||||||
use std::iter::Enumerate;
|
use std::iter::Enumerate;
|
||||||
use std::vec::VecIterator;
|
use std::vec::VecIterator;
|
||||||
|
use style::{ComputedValues, PropertyDeclaration};
|
||||||
|
|
||||||
|
/// The boxes associated with a node.
|
||||||
|
pub struct DisplayBoxes {
|
||||||
|
display_list: Option<Arc<DisplayList<AbstractNode<()>>>>,
|
||||||
|
range: Option<Range>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayBoxes {
|
||||||
|
pub fn init() -> DisplayBoxes {
|
||||||
|
DisplayBoxes {
|
||||||
|
display_list: None,
|
||||||
|
range: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A range of nodes.
|
||||||
pub struct NodeRange {
|
pub struct NodeRange {
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
range: Range,
|
range: Range,
|
||||||
|
@ -16,7 +38,10 @@ pub struct NodeRange {
|
||||||
|
|
||||||
impl NodeRange {
|
impl NodeRange {
|
||||||
pub fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
pub fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
||||||
NodeRange { node: node, range: (*range).clone() }
|
NodeRange {
|
||||||
|
node: node,
|
||||||
|
range: (*range).clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,3 +136,51 @@ impl ElementMapping {
|
||||||
debug!("----------------------------------");
|
debug!("----------------------------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Data that layout associates with a node.
|
||||||
|
pub struct LayoutData {
|
||||||
|
/// The results of CSS matching for this node.
|
||||||
|
applicable_declarations: Slot<~[Arc<~[PropertyDeclaration]>]>,
|
||||||
|
|
||||||
|
/// The results of CSS styling for this node.
|
||||||
|
style: Slot<Option<ComputedValues>>,
|
||||||
|
|
||||||
|
/// Description of how to account for recent style changes.
|
||||||
|
restyle_damage: Slot<Option<int>>,
|
||||||
|
|
||||||
|
/// The boxes assosiated with this flow.
|
||||||
|
/// Used for getBoundingClientRect and friends.
|
||||||
|
boxes: Slot<DisplayBoxes>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutData {
|
||||||
|
/// Creates new layout data.
|
||||||
|
pub fn new() -> LayoutData {
|
||||||
|
LayoutData {
|
||||||
|
applicable_declarations: Slot::init(~[]),
|
||||||
|
style: Slot::init(None),
|
||||||
|
restyle_damage: Slot::init(None),
|
||||||
|
boxes: Slot::init(DisplayBoxes::init()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This serves as a static assertion that layout data remains sendable. If this is not done, then
|
||||||
|
// we can have memory unsafety, which usually manifests as shutdown crashes.
|
||||||
|
fn assert_is_sendable<T:Send>(_: T) {}
|
||||||
|
fn assert_layout_data_is_sendable() {
|
||||||
|
assert_is_sendable(LayoutData::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait that allows access to the layout data of a DOM node.
|
||||||
|
pub trait LayoutDataAccess {
|
||||||
|
fn layout_data<'a>(&'a self) -> &'a LayoutData;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutDataAccess for AbstractNode<LayoutView> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn layout_data<'a>(&'a self) -> &'a LayoutData {
|
||||||
|
self.node().layout_data.as_ref().unwrap().as_ref().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,8 @@ use dom::text::Text;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cast::transmute;
|
use std::cast::transmute;
|
||||||
use std::unstable::raw::Box;
|
use std::unstable::raw::Box;
|
||||||
use extra::arc::Arc;
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
use style::{ComputedValues, PropertyDeclaration};
|
|
||||||
use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement};
|
use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement};
|
||||||
use servo_util::range::Range;
|
|
||||||
use gfx::display_list::DisplayList;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The basic Node structure
|
// The basic Node structure
|
||||||
|
@ -93,7 +89,7 @@ pub struct Node<View> {
|
||||||
child_list: Option<@mut NodeList>,
|
child_list: Option<@mut NodeList>,
|
||||||
|
|
||||||
/// Layout information. Only the layout task may touch this data.
|
/// Layout information. Only the layout task may touch this data.
|
||||||
priv layout_data: LayoutData,
|
layout_data: Option<~Any>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The different types of nodes.
|
/// The different types of nodes.
|
||||||
|
@ -543,7 +539,7 @@ impl Node<ScriptView> {
|
||||||
owner_doc: doc,
|
owner_doc: doc,
|
||||||
child_list: None,
|
child_list: None,
|
||||||
|
|
||||||
layout_data: LayoutData::new(),
|
layout_data: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1058,62 +1054,41 @@ impl Reflectable for Node<ScriptView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This stuff is notionally private to layout, but we put it here because it needs
|
/// A bottom-up, parallelizable traversal.
|
||||||
// to be stored in a Node, and we can't have cross-crate cyclic dependencies.
|
pub trait PostorderNodeTraversal {
|
||||||
|
/// The operation to perform. Return true to continue or false to stop.
|
||||||
|
fn process(&mut self, node: AbstractNode<LayoutView>) -> bool;
|
||||||
|
|
||||||
pub struct DisplayBoxes {
|
/// Returns true if this node should be pruned. If this returns true, we skip the operation
|
||||||
display_list: Option<Arc<DisplayList<AbstractNode<()>>>>,
|
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
|
||||||
range: Option<Range>,
|
/// visited. The default implementation never prunes any nodes.
|
||||||
}
|
fn should_prune(&mut self, _node: AbstractNode<LayoutView>) -> bool {
|
||||||
|
false
|
||||||
/// Data that layout associates with a node.
|
|
||||||
pub struct LayoutData {
|
|
||||||
/// The results of CSS matching for this node.
|
|
||||||
applicable_declarations: ~[Arc<~[PropertyDeclaration]>],
|
|
||||||
|
|
||||||
/// The results of CSS styling for this node.
|
|
||||||
style: Option<ComputedValues>,
|
|
||||||
|
|
||||||
/// Description of how to account for recent style changes.
|
|
||||||
restyle_damage: Option<int>,
|
|
||||||
|
|
||||||
/// The boxes assosiated with this flow.
|
|
||||||
/// Used for getBoundingClientRect and friends.
|
|
||||||
boxes: DisplayBoxes,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LayoutData {
|
|
||||||
/// Creates new layout data.
|
|
||||||
pub fn new() -> LayoutData {
|
|
||||||
LayoutData {
|
|
||||||
applicable_declarations: ~[],
|
|
||||||
style: None,
|
|
||||||
restyle_damage: None,
|
|
||||||
boxes: DisplayBoxes {
|
|
||||||
display_list: None,
|
|
||||||
range: None,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This serves as a static assertion that layout data remains sendable. If this is not done, then
|
|
||||||
// we can have memory unsafety, which usually manifests as shutdown crashes.
|
|
||||||
fn assert_is_sendable<T:Send>(_: T) {}
|
|
||||||
fn assert_layout_data_is_sendable() {
|
|
||||||
assert_is_sendable(LayoutData::new())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode<LayoutView> {
|
impl AbstractNode<LayoutView> {
|
||||||
// These accessors take a continuation rather than returning a reference, because
|
/// Traverses the tree in postorder.
|
||||||
// an AbstractNode doesn't have a lifetime parameter relating to the underlying
|
///
|
||||||
// Node. Also this makes it easier to switch to RWArc if we decide that is
|
/// TODO(pcwalton): Offer a parallel version with a compatible API.
|
||||||
// necessary.
|
pub fn traverse_postorder<T:PostorderNodeTraversal>(self, traversal: &mut T) -> bool {
|
||||||
pub fn read_layout_data<R>(self, blk: &fn(data: &LayoutData) -> R) -> R {
|
if traversal.should_prune(self) {
|
||||||
blk(&self.node().layout_data)
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_layout_data<R>(self, blk: &fn(data: &mut LayoutData) -> R) -> R {
|
let mut opt_kid = self.first_child();
|
||||||
blk(&mut self.mut_node().layout_data)
|
loop {
|
||||||
|
match opt_kid {
|
||||||
|
None => break,
|
||||||
|
Some(kid) => {
|
||||||
|
if !kid.traverse_postorder(traversal) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
opt_kid = kid.next_sibling()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
traversal.process(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#[feature(globs, macro_rules, struct_variant, managed_boxes)];
|
#[feature(globs, macro_rules, struct_variant, managed_boxes)];
|
||||||
|
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod gfx (name = "gfx");
|
|
||||||
extern mod hubbub;
|
extern mod hubbub;
|
||||||
extern mod js;
|
extern mod js;
|
||||||
extern mod servo_net (name = "net");
|
extern mod servo_net (name = "net");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue