Move BoxConsumer to box_builder.rs, and other minor refactoring.

This commit is contained in:
Brian J. Burg 2012-10-22 16:47:35 -07:00
parent c11480db62
commit c0452d5a0f
2 changed files with 97 additions and 112 deletions

View file

@ -32,30 +32,107 @@ impl LayoutTreeBuilder {
} }
} }
struct BoxCollector { struct PendingEntry {
flow: @FlowContext, start_box: @RenderBox,
consumer: @BoxConsumer start_idx: uint
} }
impl BoxCollector { // helper object for building the initial box list and making the
static pure fn new(flow: @FlowContext, consumer: @BoxConsumer) -> BoxCollector { // mapping between DOM nodes and boxes.
BoxCollector { struct BoxGenerator {
flow: @FlowContext,
stack: DVec<PendingEntry>,
}
impl BoxGenerator {
pub static pure fn new(flow: @FlowContext) -> BoxGenerator {
unsafe { debug!("Creating box generator for flow: f%s", flow.debug_str()); }
BoxGenerator {
flow: flow, flow: flow,
consumer: consumer stack: DVec()
}
}
pub fn push_box(ctx: &LayoutContext, box: @RenderBox) {
debug!("BoxGenerator: pushing box b%d to flow f%d", box.d().id, self.flow.d().id);
let length = match self.flow {
@InlineFlow(*) => self.flow.inline().boxes.len(),
_ => 0
};
let entry = PendingEntry { start_box: box, start_idx: length };
self.stack.push(entry);
match self.flow {
@InlineFlow(*) => {
if box.requires_inline_spacers() {
do box.create_inline_spacer_for_side(ctx, LogicalBefore).iter |spacer: &@RenderBox| {
self.flow.inline().boxes.push(*spacer);
}
}
},
@BlockFlow(*) | @RootFlow(*) => {
assert self.stack.len() == 1;
},
_ => { warn!("push_box() not implemented for flow f%d", self.flow.d().id) }
}
}
pub fn pop_box(ctx: &LayoutContext, box: @RenderBox) {
assert self.stack.len() > 0;
let entry = self.stack.pop();
assert core::box::ptr_eq(box, entry.start_box);
debug!("BoxGenerator: popping box b%d to flow f%d", box.d().id, self.flow.d().id);
match self.flow {
@InlineFlow(*) => {
let span_length = self.flow.inline().boxes.len() - entry.start_idx + 1;
match (span_length, box.requires_inline_spacers()) {
// if this non-leaf box generates extra horizontal
// spacing, add a SpacerBox for it.
(_, true) => {
do box.create_inline_spacer_for_side(ctx, LogicalAfter).iter |spacer: &@RenderBox| {
self.flow.inline().boxes.push(*spacer);
}
},
// leaf box
(1, _) => { self.flow.inline().boxes.push(box); return; },
// non-leaf with no spacer; do nothing
(_, false) => { }
}
// only create NodeRanges for non-leaf nodes.
let final_span_length = self.flow.inline().boxes.len() - entry.start_idx;
assert final_span_length > 0;
let new_range = Range(entry.start_idx, final_span_length);
debug!("BoxGenerator: adding element range=%?", new_range);
self.flow.inline().elems.add_mapping(copy box.d().node, move new_range);
},
@BlockFlow(*) => {
assert self.stack.len() == 0;
assert self.flow.block().box.is_none();
self.flow.block().box = Some(entry.start_box);
},
@RootFlow(*) => {
assert self.stack.len() == 0;
assert self.flow.root().box.is_none();
self.flow.root().box = Some(entry.start_box);
},
_ => { warn!("pop_box not implemented for flow %?", self.flow.d().id) }
} }
} }
} }
struct BuilderContext { struct BuilderContext {
default_collector: BoxCollector, default_collector: @BoxGenerator,
priv mut inline_collector: Option<BoxCollector> priv mut inline_collector: Option<@BoxGenerator>
} }
impl BuilderContext { impl BuilderContext {
static pure fn new(collector: &BoxCollector) -> BuilderContext { static pure fn new(collector: @BoxGenerator) -> BuilderContext {
unsafe { debug!("Creating new BuilderContext for flow: %s", collector.flow.debug_str()); } unsafe { debug!("Creating new BuilderContext for flow: %s", collector.flow.debug_str()); }
BuilderContext { BuilderContext {
default_collector: copy *collector, default_collector: collector,
inline_collector: None, inline_collector: None,
} }
} }
@ -76,24 +153,23 @@ impl BuilderContext {
let new_flow = builder.make_flow(flow_type); let new_flow = builder.make_flow(flow_type);
self.attach_child_flow(new_flow); self.attach_child_flow(new_flow);
BuilderContext::new(&BoxCollector::new(new_flow, @BoxConsumer::new(new_flow))) BuilderContext::new(@BoxGenerator::new(new_flow))
} }
priv fn make_inline_collector(builder: &LayoutTreeBuilder) -> BuilderContext { priv fn make_inline_collector(builder: &LayoutTreeBuilder) -> BuilderContext {
debug!("BuilderContext: making new inline collector flow"); debug!("BuilderContext: making new inline collector flow");
let new_flow = builder.make_flow(Flow_Inline); let new_flow = builder.make_flow(Flow_Inline);
let new_consumer = @BoxConsumer::new(new_flow); let new_generator = @BoxGenerator::new(new_flow);
let inline_collector = BoxCollector::new(new_flow, new_consumer);
self.inline_collector = Some(inline_collector); self.inline_collector = Some(new_generator);
self.attach_child_flow(new_flow); self.attach_child_flow(new_flow);
BuilderContext::new(&inline_collector) BuilderContext::new(new_generator)
} }
priv fn get_inline_collector(builder: &LayoutTreeBuilder) -> BuilderContext { priv fn get_inline_collector(builder: &LayoutTreeBuilder) -> BuilderContext {
match copy self.inline_collector { match copy self.inline_collector {
Some(ref collector) => BuilderContext::new(collector), Some(collector) => BuilderContext::new(collector),
None => self.make_inline_collector(builder) None => self.make_inline_collector(builder)
} }
} }
@ -142,14 +218,14 @@ impl LayoutTreeBuilder {
let box_type = self.decide_box_type(cur_node, simulated_display); let box_type = self.decide_box_type(cur_node, simulated_display);
let this_ctx = parent_ctx.containing_context_for_display(simulated_display, &self); let this_ctx = parent_ctx.containing_context_for_display(simulated_display, &self);
let new_box = self.make_box(layout_ctx, box_type, cur_node, this_ctx.default_collector.flow); let new_box = self.make_box(layout_ctx, box_type, cur_node, this_ctx.default_collector.flow);
this_ctx.default_collector.consumer.push_box(layout_ctx, new_box); this_ctx.default_collector.push_box(layout_ctx, new_box);
// recurse on child nodes. // recurse on child nodes.
for tree::each_child(&NodeTree, &cur_node) |child_node| { for tree::each_child(&NodeTree, &cur_node) |child_node| {
self.construct_recursively(layout_ctx, *child_node, &this_ctx); self.construct_recursively(layout_ctx, *child_node, &this_ctx);
} }
this_ctx.default_collector.consumer.pop_box(layout_ctx, new_box); this_ctx.default_collector.pop_box(layout_ctx, new_box);
self.simplify_children_of_flow(layout_ctx, &this_ctx); self.simplify_children_of_flow(layout_ctx, &this_ctx);
// store reference to the flow context which contains any // store reference to the flow context which contains any
@ -258,8 +334,8 @@ impl LayoutTreeBuilder {
called on root DOM element. */ called on root DOM element. */
fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@FlowContext, ()> { fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@FlowContext, ()> {
let new_flow = self.make_flow(Flow_Root); let new_flow = self.make_flow(Flow_Root);
let new_consumer = @BoxConsumer::new(new_flow); let new_generator = @BoxGenerator::new(new_flow);
let root_ctx = BuilderContext::new(&BoxCollector::new(new_flow, new_consumer)); let root_ctx = BuilderContext::new(new_generator);
self.root_flow = Some(new_flow); self.root_flow = Some(new_flow);
self.construct_recursively(layout_ctx, root, &root_ctx); self.construct_recursively(layout_ctx, root, &root_ctx);

View file

@ -107,97 +107,6 @@ fn FlowData(id: int) -> FlowData {
} }
} }
struct PendingEntry {
start_box: @RenderBox,
start_idx: uint
}
// helper object for building the initial box list and making the
// mapping between DOM nodes and boxes.
struct BoxConsumer {
flow: @FlowContext,
stack: DVec<PendingEntry>,
}
impl BoxConsumer {
pub static pure fn new(flow: @FlowContext) -> BoxConsumer {
unsafe { debug!("Creating box consumer for flow: f%s", flow.debug_str()); }
BoxConsumer {
flow: flow,
stack: DVec()
}
}
pub fn push_box(ctx: &LayoutContext, box: @RenderBox) {
debug!("BoxConsumer: pushing box b%d to flow f%d", box.d().id, self.flow.d().id);
let length = match self.flow {
@InlineFlow(*) => self.flow.inline().boxes.len(),
_ => 0
};
let entry = PendingEntry { start_box: box, start_idx: length };
self.stack.push(entry);
match self.flow {
@InlineFlow(*) => {
if box.requires_inline_spacers() {
do box.create_inline_spacer_for_side(ctx, LogicalBefore).iter |spacer: &@RenderBox| {
self.flow.inline().boxes.push(*spacer);
}
}
},
@BlockFlow(*) | @RootFlow(*) => {
assert self.stack.len() == 1;
},
_ => { warn!("push_box() not implemented for flow f%d", self.flow.d().id) }
}
}
pub fn pop_box(ctx: &LayoutContext, box: @RenderBox) {
assert self.stack.len() > 0;
let entry = self.stack.pop();
assert core::box::ptr_eq(box, entry.start_box);
debug!("BoxConsumer: popping box b%d to flow f%d", box.d().id, self.flow.d().id);
match self.flow {
@InlineFlow(*) => {
let span_length = self.flow.inline().boxes.len() - entry.start_idx + 1;
match (span_length, box.requires_inline_spacers()) {
// leaf box
(1, _) => { self.flow.inline().boxes.push(box); return; },
// if this non-leaf box generates extra horizontal
// spacing, add a SpacerBox for it.
(_, true) => {
do box.create_inline_spacer_for_side(ctx, LogicalAfter).iter |spacer: &@RenderBox| {
self.flow.inline().boxes.push(*spacer);
}
},
// non-leaf with no spacer; do nothing
(_, false) => { }
}
// only create NodeRanges for non-leaf nodes.
let final_span_length = self.flow.inline().boxes.len() - entry.start_idx + 1;
assert final_span_length > 1;
let new_range = Range(entry.start_idx, final_span_length);
debug!("BoxConsumer: adding element range=%?", new_range);
self.flow.inline().elems.add_mapping(copy box.d().node, move new_range);
},
@BlockFlow(*) => {
assert self.stack.len() == 0;
assert self.flow.block().box.is_none();
self.flow.block().box = Some(entry.start_box);
},
@RootFlow(*) => {
assert self.stack.len() == 0;
assert self.flow.root().box.is_none();
self.flow.root().box = Some(entry.start_box);
},
_ => { warn!("pop_box not implemented for flow %?", self.flow.d().id) }
}
}
}
impl FlowContext : FlowContextMethods { impl FlowContext : FlowContextMethods {
pure fn d(&self) -> &self/FlowData { pure fn d(&self) -> &self/FlowData {
match *self { match *self {