From c0452d5a0fed7cab2f4f65589b2ebae76a2aeb64 Mon Sep 17 00:00:00 2001 From: "Brian J. Burg" Date: Mon, 22 Oct 2012 16:47:35 -0700 Subject: [PATCH] Move BoxConsumer to box_builder.rs, and other minor refactoring. --- src/servo/layout/box_builder.rs | 118 ++++++++++++++++++++++++++------ src/servo/layout/flow.rs | 91 ------------------------ 2 files changed, 97 insertions(+), 112 deletions(-) diff --git a/src/servo/layout/box_builder.rs b/src/servo/layout/box_builder.rs index 1864e3c81e2..894676146a5 100644 --- a/src/servo/layout/box_builder.rs +++ b/src/servo/layout/box_builder.rs @@ -32,30 +32,107 @@ impl LayoutTreeBuilder { } } -struct BoxCollector { - flow: @FlowContext, - consumer: @BoxConsumer +struct PendingEntry { + start_box: @RenderBox, + start_idx: uint } -impl BoxCollector { - static pure fn new(flow: @FlowContext, consumer: @BoxConsumer) -> BoxCollector { - BoxCollector { +// helper object for building the initial box list and making the +// mapping between DOM nodes and boxes. +struct BoxGenerator { + flow: @FlowContext, + stack: DVec, +} + +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, - 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 { - default_collector: BoxCollector, - priv mut inline_collector: Option + default_collector: @BoxGenerator, + priv mut inline_collector: Option<@BoxGenerator> } 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()); } BuilderContext { - default_collector: copy *collector, + default_collector: collector, inline_collector: None, } } @@ -76,24 +153,23 @@ impl BuilderContext { let new_flow = builder.make_flow(flow_type); 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 { debug!("BuilderContext: making new inline collector flow"); let new_flow = builder.make_flow(Flow_Inline); - let new_consumer = @BoxConsumer::new(new_flow); - let inline_collector = BoxCollector::new(new_flow, new_consumer); + let new_generator = @BoxGenerator::new(new_flow); - self.inline_collector = Some(inline_collector); + self.inline_collector = Some(new_generator); self.attach_child_flow(new_flow); - BuilderContext::new(&inline_collector) + BuilderContext::new(new_generator) } priv fn get_inline_collector(builder: &LayoutTreeBuilder) -> BuilderContext { match copy self.inline_collector { - Some(ref collector) => BuilderContext::new(collector), + Some(collector) => BuilderContext::new(collector), None => self.make_inline_collector(builder) } } @@ -142,14 +218,14 @@ impl LayoutTreeBuilder { let box_type = self.decide_box_type(cur_node, simulated_display); 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); - 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. for tree::each_child(&NodeTree, &cur_node) |child_node| { 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); // store reference to the flow context which contains any @@ -258,8 +334,8 @@ impl LayoutTreeBuilder { called on root DOM element. */ fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@FlowContext, ()> { let new_flow = self.make_flow(Flow_Root); - let new_consumer = @BoxConsumer::new(new_flow); - let root_ctx = BuilderContext::new(&BoxCollector::new(new_flow, new_consumer)); + let new_generator = @BoxGenerator::new(new_flow); + let root_ctx = BuilderContext::new(new_generator); self.root_flow = Some(new_flow); self.construct_recursively(layout_ctx, root, &root_ctx); diff --git a/src/servo/layout/flow.rs b/src/servo/layout/flow.rs index 7d46cf51c83..1be459bf2f4 100644 --- a/src/servo/layout/flow.rs +++ b/src/servo/layout/flow.rs @@ -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, -} - -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 { pure fn d(&self) -> &self/FlowData { match *self {