Clean up aux layout data creation

This commit is contained in:
Brian J. Burg 2012-09-21 10:20:43 -07:00
parent 545acff3a8
commit b7b3cc8bbb
4 changed files with 67 additions and 65 deletions

View file

@ -1,7 +1,9 @@
#[doc="High-level interface to CSS selector matching."]
/**
* High-level interface to CSS selector matching.
*/
use std::arc::{ARC, get, clone};
use core::dvec::DVec;
use css::values::*;
use css::values::Stylesheet;
use dom::element::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement};
@ -39,7 +41,7 @@ impl NodeKind : DefaultStyleMethods {
/* TODO: this belongs in the UA stylesheet */
fn default_display_type() -> CSSDisplay {
match self {
Text(*) => { DisplayInline }
Text(*) => DisplayInline,
Element(element) => {
match *element.kind {
HTMLDivElement => DisplayBlock,
@ -80,75 +82,64 @@ fn empty_style_for_node_kind(kind: NodeKind) -> SpecifiedStyle {
mut width : Initial}
}
trait StylePriv {
fn initialize_style() -> ~[@LayoutData];
}
impl Node : StylePriv {
#[doc="
Set a default auxiliary data so that other threads can modify it.
This is, importantly, the function that creates the layout
data for the node (the reader-auxiliary box in the RCU model)
and populates it with the default style.
"]
// TODO: we should look into folding this into building the dom,
// instead of doing a linear sweep afterwards.
fn initialize_style() -> ~[@LayoutData] {
if !self.has_aux() {
let node_kind = self.read(|n| copy *n.kind);
let the_layout_data = @LayoutData({
mut style : ~empty_style_for_node_kind(node_kind),
mut box : None
});
self.set_aux(the_layout_data);
~[the_layout_data]
} else {
~[]
}
}
}
trait StyleMethods {
fn initialize_style_for_subtree() -> ~[@LayoutData];
fn initialize_layout_data() -> Option<@LayoutData>;
fn style() -> SpecifiedStyle;
fn initialize_style_for_subtree(ctx: &LayoutContext, refs: &DVec<@LayoutData>);
fn recompute_style_for_subtree(ctx: &LayoutContext, styles : ARC<Stylesheet>);
}
impl Node : StyleMethods {
#[doc="Sequentially initialize the nodes' auxilliary data so they can be updated in parallel."]
fn initialize_style_for_subtree() -> ~[@LayoutData] {
let mut handles = self.initialize_style();
for NodeTree.each_child(self) |kid| {
handles += kid.initialize_style_for_subtree();
/** If none exists, creates empty layout data for the node (the reader-auxiliary
* box in the RCU model) and populates it with an empty style object.
*/
fn initialize_layout_data() -> Option<@LayoutData> {
match self.has_aux() {
false => {
let node_kind = self.read(|n| copy *n.kind);
let data = @LayoutData({
mut style : ~empty_style_for_node_kind(node_kind),
mut flow : None
});
self.set_aux(data); Some(data)
},
true => None
}
return handles;
}
#[doc="
Returns the computed style for the given node. If CSS selector matching has not yet been
performed, fails.
TODO: Return a safe reference; don't copy.
"]
/**
* Returns the computed style for the given node. If CSS selector
* matching has not yet been performed, fails.
*/
fn style() -> SpecifiedStyle {
if !self.has_aux() {
fail ~"get_style() called on a node without a style!";
}
// TODO: return a safe reference; don't copy!
return copy *self.aux(|x| copy x).style;
}
#[doc="
Performs CSS selector matching on a subtree.
/**
* Initializes layout data and styles for a Node tree, if any nodes do not have
* this data already. Append created layout data to the task's GC roots.
*/
fn initialize_style_for_subtree(_ctx: &LayoutContext, refs: &DVec<@LayoutData>) {
do self.traverse_preorder |n| {
match n.initialize_layout_data() {
Some(r) => refs.push(r),
None => {}
}
}
}
This is, importantly, the function that updates the layout data for the node (the reader-
auxiliary box in the RCU model) with the computed style.
"]
/**
* Performs CSS selector matching on a subtree.
* This is, importantly, the function that updates the layout data for
* the node (the reader-auxiliary box in the RCU model) with the
* computed style.
*/
fn recompute_style_for_subtree(ctx: &LayoutContext, styles : ARC<Stylesheet>) {
let mut i = 0u;

View file

@ -12,7 +12,7 @@ use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, jsval, JSBool};
use js::rust::{bare_compartment, compartment, methods};
use js::{JSPROP_ENUMERATE, JSPROP_SHARED};
use layout::base::RenderBox;
use layout::base::FlowContext;
use layout::debug::DebugMethods;
use ptr::null;
use std::arc::ARC;
@ -37,6 +37,18 @@ impl NodeTree : tree::ReadMethods<Node> {
}
}
impl Node {
fn traverse_preorder(preorder_cb: &fn(Node)) {
preorder_cb(self);
do NodeTree.each_child(self) |child| { child.traverse_preorder(preorder_cb); true }
}
fn traverse_postorder(postorder_cb: &fn(Node)) {
do NodeTree.each_child(self) |child| { child.traverse_postorder(postorder_cb); true }
postorder_cb(self);
}
}
impl Node : DebugMethods {
/* Dumps the subtree rooted at this node, for debugging. */
@ -105,7 +117,7 @@ fn define_bindings(compartment: bare_compartment, doc: @Document,
Note that there may be multiple boxes per DOM node. */
enum LayoutData = {
mut style: ~SpecifiedStyle,
mut box: Option<@RenderBox>
mut flow: Option<@FlowContext>
};
type Node = rcu::Handle<NodeData, LayoutData>;
@ -151,5 +163,4 @@ impl NodeScope : tree::WriteMethods<Node> {
fn with_tree_fields<R>(node: Node, f: fn(tree::Tree<Node>) -> R) -> R {
self.write(node, |n| f(n.tree))
}
}
}

View file

@ -1,11 +1,11 @@
/** Creates CSS boxes from a DOM. */
use au = gfx::geometry;
use core::dvec::DVec;
use css::styles::SpecifiedStyle;
use css::styles::{SpecifiedStyle, empty_style_for_node_kind};
use css::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, DisplayNone};
use css::values::{Inherit, Initial, Specified};
use dom::element::*;
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree};
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData};
use layout::base::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree};
use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
use layout::block::BlockFlowData;

View file

@ -10,7 +10,7 @@ use core::dvec::DVec;
use css::resolve::apply::apply_style;
use css::values::Stylesheet;
use dl = gfx::display_list;
use dom::node::Node;
use dom::node::{Node, LayoutData};
use dom::event::{Event, ReflowEvent};
use geom::point::Point2D;
use geom::rect::Rect;
@ -41,7 +41,7 @@ fn LayoutTask(render_task: RenderTask, image_cache_task: ImageCacheTask) -> Layo
do spawn_listener::<Msg>|request| {
// This just keeps our dom aux objects alive
let mut layout_data_refs = ~[];
let layout_data_refs = DVec();
let font_cache = FontCache();
loop {
@ -65,7 +65,7 @@ fn LayoutTask(render_task: RenderTask, image_cache_task: ImageCacheTask) -> Layo
};
do util::time::time(~"layout") {
layout_data_refs += node.initialize_style_for_subtree();
node.initialize_style_for_subtree(&layout_ctx, &layout_data_refs);
node.recompute_style_for_subtree(&layout_ctx, styles);
// TODO: this should care about root flow, not root box.